42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
'use client'
|
|
|
|
import type { TextFieldClientComponent } from 'payload'
|
|
import { TextField, useField, useFormFields } from '@payloadcms/ui'
|
|
import { useEffect, useRef } from 'react'
|
|
|
|
const toSlug = (value: string): string =>
|
|
value
|
|
.toLowerCase()
|
|
.replace(/ä/g, 'ae')
|
|
.replace(/ö/g, 'oe')
|
|
.replace(/ü/g, 'ue')
|
|
.replace(/ß/g, 'ss')
|
|
.replace(/[^\w\s-]/g, '')
|
|
.replace(/[\s_]+/g, '-')
|
|
.replace(/-+/g, '-')
|
|
.replace(/^-+|-+$/g, '')
|
|
|
|
export const SlugField: TextFieldClientComponent = (props) => {
|
|
const { value, setValue } = useField<string>({ path: props.path })
|
|
const prevAutoSlug = useRef<string>('')
|
|
const sourceField =
|
|
((props as Record<string, unknown>).sourceField as string) || 'name'
|
|
|
|
const sourceValue = useFormFields(([fields]) => {
|
|
const field = fields[sourceField]
|
|
return (field?.value as string) ?? ''
|
|
})
|
|
|
|
useEffect(() => {
|
|
const newSlug = toSlug(sourceValue)
|
|
// Only auto-fill if slug is empty or matches the previous auto-slug
|
|
if (!value || value === prevAutoSlug.current) {
|
|
setValue(newSlug)
|
|
}
|
|
prevAutoSlug.current = newSlug
|
|
}, [sourceValue]) // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
return <TextField {...props} />
|
|
}
|
|
|
|
export default SlugField
|