diff --git a/src/apps/content-editor/src/app/components/Editor/Field/Field.tsx b/src/apps/content-editor/src/app/components/Editor/Field/Field.tsx index 5d1bfd130..754624bb7 100644 --- a/src/apps/content-editor/src/app/components/Editor/Field/Field.tsx +++ b/src/apps/content-editor/src/app/components/Editor/Field/Field.tsx @@ -71,6 +71,7 @@ import { import { ResolvedOption } from "./ResolvedOption"; import { LinkOption } from "./LinkOption"; import { FieldTypeMedia } from "../../FieldTypeMedia"; +import { debounce } from "lodash"; const AIFieldShell = withAI(FieldShell); @@ -203,6 +204,22 @@ export const Field = ({ const value = item?.data?.[name]; const version = item?.meta?.version; const fieldData = fields?.find((field) => field.ZUID === ZUID); + const [inputValue, setInputValue] = useState(value || ""); + + const debouncedOnChange = useMemo(() => debounce(onChange, 300), [onChange]); + + const deferredChange = useCallback( + (value, name) => { + setInputValue(value); + debouncedOnChange(value, name); + }, + [debouncedOnChange] + ); + + // Keep local input value in sync with global field value + useEffect(() => { + setInputValue(value || ""); + }, [value]); useEffect(() => { if (datatype !== "date" && datatype !== "datetime") { @@ -288,7 +305,7 @@ export const Field = ({ ZUID={fieldData?.ZUID} name={fieldData?.name || name} label={fieldData?.label || label} - valueLength={(value as string)?.length ?? 0} + valueLength={(inputValue as string)?.length ?? 0} settings={ fieldData || { name: name, @@ -304,11 +321,11 @@ export const Field = ({ minLength={minLength} errors={errors} aiType="text" - value={value} + value={inputValue} > onChange(evt.target.value, name)} + value={inputValue} + onChange={(evt) => deferredChange(evt.target.value, name)} fullWidth inputProps={{ name: fieldData?.name || name, @@ -322,12 +339,12 @@ export const Field = ({ return ( onChange(evt.target.value, name)} + value={inputValue} + onChange={(evt) => deferredChange(evt.target.value, name)} fullWidth error={errors && Object.values(errors)?.some((error) => !!error)} /> @@ -338,14 +355,14 @@ export const Field = ({ return ( onChange(evt.target.value, name)} + value={inputValue} + onChange={(evt) => deferredChange(evt.target.value, name)} fullWidth type="url" error={errors && Object.values(errors)?.some((error) => !!error)} @@ -377,7 +394,7 @@ export const Field = ({ ZUID={fieldData?.ZUID} name={fieldData?.name} label={fieldData?.label} - valueLength={(value as string)?.length ?? 0} + valueLength={(inputValue as string)?.length ?? 0} settings={fieldData} onChange={(evt: ChangeEvent) => onChange(evt.target.value, name) @@ -387,11 +404,11 @@ export const Field = ({ aiType="word" maxLength={maxLength} minLength={minLength} - value={value} + value={inputValue} > onChange(evt.target.value, name)} + value={inputValue} + onChange={(evt) => deferredChange(evt.target.value, name)} fullWidth multiline rows={6} @@ -424,7 +441,7 @@ export const Field = ({ name={name} value={value} version={version} - onChange={onChange} + onChange={deferredChange} onSave={onSave} onCharacterCountChange={(charCount: number) => setCharacterCount(charCount) @@ -448,7 +465,7 @@ export const Field = ({ ZUID={fieldData?.ZUID} name={fieldData?.name} label={fieldData?.label} - valueLength={(value as string)?.length ?? 0} + valueLength={(inputValue as string)?.length ?? 0} settings={fieldData} onChange={onChange} errors={errors} @@ -456,14 +473,14 @@ export const Field = ({ datatype={fieldData?.datatype} editorType={editorType} onEditorChange={(value: EditorType) => setEditorType(value)} - value={value} + value={inputValue} > { setImageModal(opts); @@ -918,10 +935,10 @@ export const Field = ({ return ( !!error)} /> @@ -937,8 +954,8 @@ export const Field = ({ !!error)} />