diff --git a/templates/website/src/fields/slug/SlugComponent.tsx b/templates/website/src/fields/slug/SlugComponent.tsx index f21ae829d2..8114973e16 100644 --- a/templates/website/src/fields/slug/SlugComponent.tsx +++ b/templates/website/src/fields/slug/SlugComponent.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { useCallback, useEffect } from 'react' +import React, { useCallback } from 'react' import { TextFieldClientProps } from 'payload' import { useField, Button, TextInput, FieldLabel, useFormFields, useForm } from '@payloadcms/ui' @@ -27,21 +27,18 @@ export const SlugComponent: React.FC = ({ const { value, setValue } = useField({ path: path || field.name }) - const { dispatchFields } = useForm() + const { dispatchFields, getDataByPath } = useForm() - // The value of the checkbox - // We're using separate useFormFields to minimise re-renders - const checkboxValue = useFormFields(([fields]) => { + const isLocked = useFormFields(([fields]) => { return fields[checkboxFieldPath]?.value as string }) - // The value of the field we're listening to for the slug - const targetFieldValue = useFormFields(([fields]) => { - return fields[fieldToUse]?.value as string - }) + const handleGenerate = useCallback( + (e: React.MouseEvent) => { + e.preventDefault() + + const targetFieldValue = getDataByPath(fieldToUse) as string - useEffect(() => { - if (checkboxValue) { if (targetFieldValue) { const formattedSlug = formatSlug(targetFieldValue) @@ -49,8 +46,9 @@ export const SlugComponent: React.FC = ({ } else { if (value !== '') setValue('') } - } - }, [targetFieldValue, checkboxValue, setValue, value]) + }, + [setValue, value, fieldToUse, getDataByPath], + ) const handleLock = useCallback( (e: React.MouseEvent) => { @@ -59,29 +57,30 @@ export const SlugComponent: React.FC = ({ dispatchFields({ type: 'UPDATE', path: checkboxFieldPath, - value: !checkboxValue, + value: !isLocked, }) }, - [checkboxValue, checkboxFieldPath, dispatchFields], + [isLocked, checkboxFieldPath, dispatchFields], ) - const readOnly = readOnlyFromProps || checkboxValue - return (
- + {!isLocked && ( + + )}
-
) diff --git a/templates/website/src/fields/slug/formatSlug.ts b/templates/website/src/fields/slug/formatSlug.ts index 9129de8932..0d4b78239b 100644 --- a/templates/website/src/fields/slug/formatSlug.ts +++ b/templates/website/src/fields/slug/formatSlug.ts @@ -1,8 +1,8 @@ import type { FieldHook } from 'payload' -export const formatSlug = (val: string): string => +export const formatSlug = (val: string): string | undefined => val - .replace(/ /g, '-') + ?.replace(/ /g, '-') .replace(/[^\w-]+/g, '') .toLowerCase() @@ -13,10 +13,10 @@ export const formatSlugHook = return formatSlug(value) } - if (operation === 'create' || !data?.slug) { - const fallbackData = data?.[fallback] || data?.[fallback] + if (operation === 'create' || data?.slug === undefined) { + const fallbackData = data?.[fallback] - if (fallbackData && typeof fallbackData === 'string') { + if (typeof fallbackData === 'string') { return formatSlug(fallbackData) } } diff --git a/templates/website/src/fields/slug/index.scss b/templates/website/src/fields/slug/index.scss index e3dd2d8369..514af3d225 100644 --- a/templates/website/src/fields/slug/index.scss +++ b/templates/website/src/fields/slug/index.scss @@ -3,6 +3,7 @@ display: flex; justify-content: space-between; align-items: center; + gap: calc(var(--base) / 2); } .lock-button { diff --git a/templates/with-vercel-website/src/fields/slug/SlugComponent.tsx b/templates/with-vercel-website/src/fields/slug/SlugComponent.tsx index f21ae829d2..8114973e16 100644 --- a/templates/with-vercel-website/src/fields/slug/SlugComponent.tsx +++ b/templates/with-vercel-website/src/fields/slug/SlugComponent.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { useCallback, useEffect } from 'react' +import React, { useCallback } from 'react' import { TextFieldClientProps } from 'payload' import { useField, Button, TextInput, FieldLabel, useFormFields, useForm } from '@payloadcms/ui' @@ -27,21 +27,18 @@ export const SlugComponent: React.FC = ({ const { value, setValue } = useField({ path: path || field.name }) - const { dispatchFields } = useForm() + const { dispatchFields, getDataByPath } = useForm() - // The value of the checkbox - // We're using separate useFormFields to minimise re-renders - const checkboxValue = useFormFields(([fields]) => { + const isLocked = useFormFields(([fields]) => { return fields[checkboxFieldPath]?.value as string }) - // The value of the field we're listening to for the slug - const targetFieldValue = useFormFields(([fields]) => { - return fields[fieldToUse]?.value as string - }) + const handleGenerate = useCallback( + (e: React.MouseEvent) => { + e.preventDefault() + + const targetFieldValue = getDataByPath(fieldToUse) as string - useEffect(() => { - if (checkboxValue) { if (targetFieldValue) { const formattedSlug = formatSlug(targetFieldValue) @@ -49,8 +46,9 @@ export const SlugComponent: React.FC = ({ } else { if (value !== '') setValue('') } - } - }, [targetFieldValue, checkboxValue, setValue, value]) + }, + [setValue, value, fieldToUse, getDataByPath], + ) const handleLock = useCallback( (e: React.MouseEvent) => { @@ -59,29 +57,30 @@ export const SlugComponent: React.FC = ({ dispatchFields({ type: 'UPDATE', path: checkboxFieldPath, - value: !checkboxValue, + value: !isLocked, }) }, - [checkboxValue, checkboxFieldPath, dispatchFields], + [isLocked, checkboxFieldPath, dispatchFields], ) - const readOnly = readOnlyFromProps || checkboxValue - return (
- + {!isLocked && ( + + )}
-
) diff --git a/templates/with-vercel-website/src/fields/slug/formatSlug.ts b/templates/with-vercel-website/src/fields/slug/formatSlug.ts index 9129de8932..0d4b78239b 100644 --- a/templates/with-vercel-website/src/fields/slug/formatSlug.ts +++ b/templates/with-vercel-website/src/fields/slug/formatSlug.ts @@ -1,8 +1,8 @@ import type { FieldHook } from 'payload' -export const formatSlug = (val: string): string => +export const formatSlug = (val: string): string | undefined => val - .replace(/ /g, '-') + ?.replace(/ /g, '-') .replace(/[^\w-]+/g, '') .toLowerCase() @@ -13,10 +13,10 @@ export const formatSlugHook = return formatSlug(value) } - if (operation === 'create' || !data?.slug) { - const fallbackData = data?.[fallback] || data?.[fallback] + if (operation === 'create' || data?.slug === undefined) { + const fallbackData = data?.[fallback] - if (fallbackData && typeof fallbackData === 'string') { + if (typeof fallbackData === 'string') { return formatSlug(fallbackData) } } diff --git a/templates/with-vercel-website/src/fields/slug/index.scss b/templates/with-vercel-website/src/fields/slug/index.scss index e3dd2d8369..514af3d225 100644 --- a/templates/with-vercel-website/src/fields/slug/index.scss +++ b/templates/with-vercel-website/src/fields/slug/index.scss @@ -3,6 +3,7 @@ display: flex; justify-content: space-between; align-items: center; + gap: calc(var(--base) / 2); } .lock-button {