payload-intl 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/MessageFormField.d.ts +15 -0
- package/dist/components/MessageFormField.d.ts.map +1 -0
- package/dist/components/{MessageController.js → MessageFormField.js} +5 -3
- package/dist/components/MessageFormField.js.map +1 -0
- package/dist/components/MessagesForm.d.ts +3 -1
- package/dist/components/MessagesForm.d.ts.map +1 -1
- package/dist/components/MessagesForm.js +25 -36
- package/dist/components/MessagesForm.js.map +1 -1
- package/dist/components/{MessageFormContext.d.ts → MessagesFormProvider.d.ts} +6 -2
- package/dist/components/MessagesFormProvider.d.ts.map +1 -0
- package/dist/components/{MessageFormContext.js → MessagesFormProvider.js} +8 -4
- package/dist/components/MessagesFormProvider.js.map +1 -0
- package/dist/components/MessagesLink.js +5 -2
- package/dist/components/MessagesLink.js.map +1 -1
- package/dist/components/MessagesView.d.ts +1 -1
- package/dist/components/MessagesView.d.ts.map +1 -1
- package/dist/components/MessagesView.js +13 -4
- package/dist/components/MessagesView.js.map +1 -1
- package/dist/components/actions/CopyMessages.d.ts +2 -0
- package/dist/components/actions/CopyMessages.d.ts.map +1 -0
- package/dist/components/actions/{Move.js → CopyMessages.js} +6 -6
- package/dist/components/actions/CopyMessages.js.map +1 -0
- package/dist/components/actions/JsonImport.d.ts +4 -1
- package/dist/components/actions/JsonImport.d.ts.map +1 -1
- package/dist/components/actions/JsonImport.js +7 -25
- package/dist/components/actions/JsonImport.js.map +1 -1
- package/dist/components/hooks/useHtmlLexicalAdapter.d.ts +12 -0
- package/dist/components/hooks/useHtmlLexicalAdapter.d.ts.map +1 -0
- package/dist/components/hooks/useHtmlLexicalAdapter.js +63 -0
- package/dist/components/hooks/useHtmlLexicalAdapter.js.map +1 -0
- package/dist/components/hooks/useMessagesFormSubmit.d.ts +11 -0
- package/dist/components/hooks/useMessagesFormSubmit.d.ts.map +1 -0
- package/dist/components/hooks/useMessagesFormSubmit.js +44 -0
- package/dist/components/hooks/useMessagesFormSubmit.js.map +1 -0
- package/dist/components/inputs/FieldWrapper.d.ts +9 -0
- package/dist/components/inputs/FieldWrapper.d.ts.map +1 -0
- package/dist/components/inputs/FieldWrapper.js +24 -0
- package/dist/components/inputs/FieldWrapper.js.map +1 -0
- package/dist/components/inputs/{InputWrapper.module.css → FieldWrapper.module.css} +2 -12
- package/dist/components/inputs/LexicalInput.d.ts +2 -13
- package/dist/components/inputs/LexicalInput.d.ts.map +1 -1
- package/dist/components/inputs/LexicalInput.js +4 -63
- package/dist/components/inputs/LexicalInput.js.map +1 -1
- package/dist/components/inputs/MessageInput.d.ts +6 -3
- package/dist/components/inputs/MessageInput.d.ts.map +1 -1
- package/dist/components/inputs/MessageInput.js +47 -43
- package/dist/components/inputs/MessageInput.js.map +1 -1
- package/dist/components/inputs/MessageInput.module.css +23 -4
- package/dist/components/inputs/ReferencePopover.d.ts +7 -0
- package/dist/components/inputs/ReferencePopover.d.ts.map +1 -0
- package/dist/components/inputs/ReferencePopover.js +42 -0
- package/dist/components/inputs/ReferencePopover.js.map +1 -0
- package/dist/components/inputs/ReferencePopover.module.css +70 -0
- package/dist/components/inputs/SingleLinePlugin.d.ts +2 -0
- package/dist/components/inputs/SingleLinePlugin.d.ts.map +1 -0
- package/dist/components/inputs/SingleLinePlugin.js +24 -0
- package/dist/components/inputs/SingleLinePlugin.js.map +1 -0
- package/dist/components/inputs/variables/VariableChip.d.ts.map +1 -1
- package/dist/components/inputs/variables/VariableChip.js +31 -32
- package/dist/components/inputs/variables/VariableChip.js.map +1 -1
- package/dist/components/inputs/variables/VariableChip.module.css +3 -3
- package/dist/components/inputs/variables/VariableSuggestion.d.ts +4 -0
- package/dist/components/inputs/variables/VariableSuggestion.d.ts.map +1 -0
- package/dist/components/inputs/variables/VariableSuggestion.js +24 -0
- package/dist/components/inputs/variables/VariableSuggestion.js.map +1 -0
- package/dist/components/inputs/variables/editors/PluralVariableEditor.d.ts.map +1 -1
- package/dist/components/inputs/variables/editors/PluralVariableEditor.js +62 -60
- package/dist/components/inputs/variables/editors/PluralVariableEditor.js.map +1 -1
- package/dist/components/inputs/variables/editors/PluralVariableEditor.module.css +4 -4
- package/dist/components/inputs/variables/editors/TemporalVariableEditor.d.ts +11 -0
- package/dist/components/inputs/variables/editors/TemporalVariableEditor.d.ts.map +1 -0
- package/dist/components/inputs/variables/editors/{DateVariableEditor.js → TemporalVariableEditor.js} +3 -3
- package/dist/components/inputs/variables/editors/TemporalVariableEditor.js.map +1 -0
- package/dist/components/inputs/variables/pickers/NumericVariableEditor.d.ts +7 -0
- package/dist/components/inputs/variables/pickers/{NumericVariablePicker.d.ts.map → NumericVariableEditor.d.ts.map} +1 -1
- package/dist/components/inputs/variables/pickers/{NumericVariablePicker.js → NumericVariableEditor.js} +15 -9
- package/dist/components/inputs/variables/pickers/NumericVariableEditor.js.map +1 -0
- package/dist/components/inputs/variables/pickers/{NumericVariablePicker.module.css → NumericVariableEditor.module.css} +3 -3
- package/dist/components/inputs/variables/pickers/TemporalVariablePicker.d.ts +7 -0
- package/dist/components/inputs/variables/pickers/TemporalVariablePicker.d.ts.map +1 -0
- package/dist/components/inputs/variables/pickers/TemporalVariablePicker.js +57 -0
- package/dist/components/inputs/variables/pickers/TemporalVariablePicker.js.map +1 -0
- package/dist/components/inputs/variables/pickers/{TemporalElementEditor.module.css → TemporalVariablePicker.module.css} +3 -3
- package/dist/components/layout/GroupStatusDot.d.ts +6 -0
- package/dist/components/layout/GroupStatusDot.d.ts.map +1 -0
- package/dist/components/layout/GroupStatusDot.js +24 -0
- package/dist/components/layout/GroupStatusDot.js.map +1 -0
- package/dist/components/layout/MessageField.d.ts +2 -1
- package/dist/components/layout/MessageField.d.ts.map +1 -1
- package/dist/components/layout/MessageField.js +52 -33
- package/dist/components/layout/MessageField.js.map +1 -1
- package/dist/components/layout/MessageField.module.css +21 -10
- package/dist/components/layout/MessagesTabs.d.ts.map +1 -1
- package/dist/components/layout/MessagesTabs.js +3 -5
- package/dist/components/layout/MessagesTabs.js.map +1 -1
- package/dist/components/layout/MessagesTree.d.ts +1 -1
- package/dist/components/layout/MessagesTree.d.ts.map +1 -1
- package/dist/components/layout/MessagesTree.js +33 -43
- package/dist/components/layout/MessagesTree.js.map +1 -1
- package/dist/components/layout/MessagesTree.module.css +10 -5
- package/dist/components/layout/StatusDot.d.ts +7 -0
- package/dist/components/layout/StatusDot.d.ts.map +1 -0
- package/dist/components/layout/StatusDot.js +12 -0
- package/dist/components/layout/StatusDot.js.map +1 -0
- package/dist/components/layout/StatusDot.module.css +16 -0
- package/dist/const.d.ts +2 -2
- package/dist/const.js +1 -1
- package/dist/entities.js +1 -1
- package/dist/internals/index.d.ts.map +1 -0
- package/dist/internals/index.js.map +1 -0
- package/dist/internals/procedure.d.ts.map +1 -0
- package/dist/internals/procedure.js.map +1 -0
- package/dist/internals/urls.d.ts.map +1 -0
- package/dist/internals/urls.js.map +1 -0
- package/dist/internals/utils.d.ts.map +1 -0
- package/dist/internals/utils.js.map +1 -0
- package/dist/utils/sanitize.d.ts +7 -6
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/utils/sanitize.js +11 -8
- package/dist/utils/sanitize.js.map +1 -1
- package/package.json +4 -3
- package/dist/_common/index.d.ts.map +0 -1
- package/dist/_common/index.js.map +0 -1
- package/dist/_common/procedure.d.ts.map +0 -1
- package/dist/_common/procedure.js.map +0 -1
- package/dist/_common/urls.d.ts.map +0 -1
- package/dist/_common/urls.js.map +0 -1
- package/dist/_common/utils.d.ts.map +0 -1
- package/dist/_common/utils.js.map +0 -1
- package/dist/components/MessageController.d.ts +0 -13
- package/dist/components/MessageController.d.ts.map +0 -1
- package/dist/components/MessageController.js.map +0 -1
- package/dist/components/MessageFormContext.d.ts.map +0 -1
- package/dist/components/MessageFormContext.js.map +0 -1
- package/dist/components/actions/Move.d.ts +0 -2
- package/dist/components/actions/Move.d.ts.map +0 -1
- package/dist/components/actions/Move.js.map +0 -1
- package/dist/components/inputs/InputWrapper.d.ts +0 -8
- package/dist/components/inputs/InputWrapper.d.ts.map +0 -1
- package/dist/components/inputs/InputWrapper.js +0 -34
- package/dist/components/inputs/InputWrapper.js.map +0 -1
- package/dist/components/inputs/variables/editors/DateVariableEditor.d.ts +0 -10
- package/dist/components/inputs/variables/editors/DateVariableEditor.d.ts.map +0 -1
- package/dist/components/inputs/variables/editors/DateVariableEditor.js.map +0 -1
- package/dist/components/inputs/variables/editors/TimeVariableEditor.d.ts +0 -10
- package/dist/components/inputs/variables/editors/TimeVariableEditor.d.ts.map +0 -1
- package/dist/components/inputs/variables/editors/TimeVariableEditor.js +0 -15
- package/dist/components/inputs/variables/editors/TimeVariableEditor.js.map +0 -1
- package/dist/components/inputs/variables/pickers/NumericVariablePicker.d.ts +0 -7
- package/dist/components/inputs/variables/pickers/NumericVariablePicker.js.map +0 -1
- package/dist/components/inputs/variables/pickers/TemporalElementEditor.d.ts +0 -7
- package/dist/components/inputs/variables/pickers/TemporalElementEditor.d.ts.map +0 -1
- package/dist/components/inputs/variables/pickers/TemporalElementEditor.js +0 -58
- package/dist/components/inputs/variables/pickers/TemporalElementEditor.js.map +0 -1
- /package/dist/components/actions/{Move.module.css → CopyMessages.module.css} +0 -0
- /package/dist/{_common → internals}/index.d.ts +0 -0
- /package/dist/{_common → internals}/index.js +0 -0
- /package/dist/{_common → internals}/procedure.d.ts +0 -0
- /package/dist/{_common → internals}/procedure.js +0 -0
- /package/dist/{_common → internals}/urls.d.ts +0 -0
- /package/dist/{_common → internals}/urls.js +0 -0
- /package/dist/{_common → internals}/utils.d.ts +0 -0
- /package/dist/{_common → internals}/utils.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/hooks/useHtmlLexicalAdapter.ts"],"sourcesContent":["import type {\n DefaultNodeTypes,\n TypedEditorState,\n} from '@payloadcms/richtext-lexical';\nimport {\n defaultEditorConfig,\n defaultEditorFeatures,\n} from '@payloadcms/richtext-lexical';\nimport {\n buildDefaultEditorState,\n getEnabledNodes,\n sanitizeClientEditorConfig,\n} from '@payloadcms/richtext-lexical/client';\nimport type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical';\nimport { $getRoot } from '@payloadcms/richtext-lexical/lexical';\nimport { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless';\nimport {\n $generateHtmlFromNodes,\n $generateNodesFromDOM,\n} from '@payloadcms/richtext-lexical/lexical/html';\nimport { useCallback, useMemo, useRef } from 'react';\n\nconst EMPTY_STATE = buildDefaultEditorState({});\n\ninterface UseHtmlLexicalAdapterProps {\n html: string;\n onChange: (html: string) => void;\n}\n\nexport function useHtmlLexicalAdapter({\n html,\n onChange,\n}: UseHtmlLexicalAdapterProps) {\n // 1. Maintain a persistent headless editor for conversion\n const headlessEditor = useRef(\n createHeadlessEditor({\n nodes: getEnabledNodes({\n editorConfig: sanitizeClientEditorConfig(\n // @ts-expect-error - FIXME\n defaultEditorFeatures,\n defaultEditorConfig,\n ),\n }),\n }),\n );\n\n // 2. HTML -> SerializedState\n const getSerializedState = useCallback(\n (htmlString: string): SerializedEditorState => {\n const editor = headlessEditor.current;\n editor.update(\n () => {\n const parser = new DOMParser();\n const dom = parser.parseFromString(htmlString, 'text/html');\n const nodes = $generateNodesFromDOM(editor, dom);\n\n const root = $getRoot();\n root.clear().append(...nodes);\n },\n { discrete: true },\n );\n\n return editor.getEditorState().toJSON();\n },\n [],\n );\n\n // 3. Memoize the initial value to prevent unnecessary re-renders\n const value = useMemo(() => {\n const serializedState = getSerializedState(html);\n\n if (serializedState.root.children.length === 0) {\n return EMPTY_STATE;\n }\n\n return serializedState;\n }, [html, getSerializedState]);\n\n // 4. SerializedState -> HTML\n const setValue = useCallback(\n (serializedState: SerializedEditorState) => {\n const editor = headlessEditor.current;\n\n // Update headless editor to match the incoming state\n editor.setEditorState(editor.parseEditorState(serializedState));\n\n // Generate HTML and broadcast if it has changed\n editor.read(() => {\n const newHtml = $generateHtmlFromNodes(editor);\n if (newHtml !== html) {\n onChange(newHtml);\n }\n });\n },\n [html, onChange],\n );\n\n return { value: value as TypedEditorState<DefaultNodeTypes>, setValue };\n}\n"],"names":["defaultEditorConfig","defaultEditorFeatures","buildDefaultEditorState","getEnabledNodes","sanitizeClientEditorConfig","$getRoot","createHeadlessEditor","$generateHtmlFromNodes","$generateNodesFromDOM","useCallback","useMemo","useRef","EMPTY_STATE","useHtmlLexicalAdapter","html","onChange","headlessEditor","nodes","editorConfig","getSerializedState","htmlString","editor","current","update","parser","DOMParser","dom","parseFromString","root","clear","append","discrete","getEditorState","toJSON","value","serializedState","children","length","setValue","setEditorState","parseEditorState","read","newHtml"],"mappings":"AAIA,SACEA,mBAAmB,EACnBC,qBAAqB,QAChB,+BAA+B;AACtC,SACEC,uBAAuB,EACvBC,eAAe,EACfC,0BAA0B,QACrB,sCAAsC;AAE7C,SAASC,QAAQ,QAAQ,uCAAuC;AAChE,SAASC,oBAAoB,QAAQ,gDAAgD;AACrF,SACEC,sBAAsB,EACtBC,qBAAqB,QAChB,4CAA4C;AACnD,SAASC,WAAW,EAAEC,OAAO,EAAEC,MAAM,QAAQ,QAAQ;AAErD,MAAMC,cAAcV,wBAAwB,CAAC;AAO7C,OAAO,SAASW,sBAAsB,EACpCC,IAAI,EACJC,QAAQ,EACmB;IAC3B,0DAA0D;IAC1D,MAAMC,iBAAiBL,OACrBL,qBAAqB;QACnBW,OAAOd,gBAAgB;YACrBe,cAAcd,2BACZ,2BAA2B;YAC3BH,uBACAD;QAEJ;IACF;IAGF,6BAA6B;IAC7B,MAAMmB,qBAAqBV,YACzB,CAACW;QACC,MAAMC,SAASL,eAAeM,OAAO;QACrCD,OAAOE,MAAM,CACX;YACE,MAAMC,SAAS,IAAIC;YACnB,MAAMC,MAAMF,OAAOG,eAAe,CAACP,YAAY;YAC/C,MAAMH,QAAQT,sBAAsBa,QAAQK;YAE5C,MAAME,OAAOvB;YACbuB,KAAKC,KAAK,GAAGC,MAAM,IAAIb;QACzB,GACA;YAAEc,UAAU;QAAK;QAGnB,OAAOV,OAAOW,cAAc,GAAGC,MAAM;IACvC,GACA,EAAE;IAGJ,iEAAiE;IACjE,MAAMC,QAAQxB,QAAQ;QACpB,MAAMyB,kBAAkBhB,mBAAmBL;QAE3C,IAAIqB,gBAAgBP,IAAI,CAACQ,QAAQ,CAACC,MAAM,KAAK,GAAG;YAC9C,OAAOzB;QACT;QAEA,OAAOuB;IACT,GAAG;QAACrB;QAAMK;KAAmB;IAE7B,6BAA6B;IAC7B,MAAMmB,WAAW7B,YACf,CAAC0B;QACC,MAAMd,SAASL,eAAeM,OAAO;QAErC,qDAAqD;QACrDD,OAAOkB,cAAc,CAAClB,OAAOmB,gBAAgB,CAACL;QAE9C,gDAAgD;QAChDd,OAAOoB,IAAI,CAAC;YACV,MAAMC,UAAUnC,uBAAuBc;YACvC,IAAIqB,YAAY5B,MAAM;gBACpBC,SAAS2B;YACX;QACF;IACF,GACA;QAAC5B;QAAMC;KAAS;IAGlB,OAAO;QAAEmB,OAAOA;QAA6CI;IAAS;AACxE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UseFormReturn } from 'react-hook-form';
|
|
2
|
+
import type { FormValues } from '../../components/MessagesFormProvider';
|
|
3
|
+
import type { DeepPartial, Messages, Translations } from '../../types';
|
|
4
|
+
interface UseMessagesFormSubmitOptions {
|
|
5
|
+
endpointUrl: string;
|
|
6
|
+
defaultValues: Translations<DeepPartial<Messages>>;
|
|
7
|
+
form: UseFormReturn<FormValues>;
|
|
8
|
+
}
|
|
9
|
+
export declare function useMessagesFormSubmit({ endpointUrl, defaultValues, form, }: UseMessagesFormSubmitOptions): (currentValues: FormValues) => Promise<void>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=useMessagesFormSubmit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMessagesFormSubmit.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useMessagesFormSubmit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGnE,UAAU,4BAA4B;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,YAAY,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,IAAI,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,WAAW,EACX,aAAa,EACb,IAAI,GACL,EAAE,4BAA4B,mBAGc,UAAU,mBAyCtD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { toast, useDocumentEvents } from '@payloadcms/ui';
|
|
2
|
+
import { isEqual } from 'lodash-es';
|
|
3
|
+
import { getErrorMessage } from '../../utils/error-handling';
|
|
4
|
+
export function useMessagesFormSubmit({ endpointUrl, defaultValues, form }) {
|
|
5
|
+
const { reportUpdate } = useDocumentEvents();
|
|
6
|
+
const handleSubmit = async (currentValues)=>{
|
|
7
|
+
const toastId = toast.loading('Saving...');
|
|
8
|
+
const changes = Object.entries(currentValues).reduce((acc, [locale, value])=>{
|
|
9
|
+
const hasChanged = !isEqual(value, defaultValues[locale]);
|
|
10
|
+
if (!hasChanged) return acc;
|
|
11
|
+
acc[locale] = value;
|
|
12
|
+
return acc;
|
|
13
|
+
}, {});
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(endpointUrl, {
|
|
16
|
+
method: 'PUT',
|
|
17
|
+
headers: {
|
|
18
|
+
'Content-Type': 'application/json'
|
|
19
|
+
},
|
|
20
|
+
body: JSON.stringify(changes)
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const error = await getErrorMessage(response);
|
|
24
|
+
throw new Error(error);
|
|
25
|
+
}
|
|
26
|
+
form.reset(currentValues);
|
|
27
|
+
reportUpdate({
|
|
28
|
+
entitySlug: 'messages',
|
|
29
|
+
operation: 'update',
|
|
30
|
+
updatedAt: new Date().toISOString()
|
|
31
|
+
});
|
|
32
|
+
toast.success('Saved', {
|
|
33
|
+
id: toastId
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
toast.error(`Failed to save: ${error instanceof Error ? error.message : 'Unknown error'}`, {
|
|
37
|
+
id: toastId
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return handleSubmit;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=useMessagesFormSubmit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/hooks/useMessagesFormSubmit.ts"],"sourcesContent":["import { toast, useDocumentEvents } from '@payloadcms/ui';\nimport { isEqual } from 'lodash-es';\nimport type { UseFormReturn } from 'react-hook-form';\nimport type { FormValues } from '@/components/MessagesFormProvider';\nimport type { DeepPartial, Messages, Translations } from '@/types';\nimport { getErrorMessage } from '@/utils/error-handling';\n\ninterface UseMessagesFormSubmitOptions {\n endpointUrl: string;\n defaultValues: Translations<DeepPartial<Messages>>;\n form: UseFormReturn<FormValues>;\n}\n\nexport function useMessagesFormSubmit({\n endpointUrl,\n defaultValues,\n form,\n}: UseMessagesFormSubmitOptions) {\n const { reportUpdate } = useDocumentEvents();\n\n const handleSubmit = async (currentValues: FormValues) => {\n const toastId = toast.loading('Saving...');\n const changes = Object.entries(currentValues).reduce<\n Translations<Messages>\n >((acc, [locale, value]) => {\n const hasChanged = !isEqual(value, defaultValues[locale]);\n if (!hasChanged) return acc;\n acc[locale] = value;\n return acc;\n }, {});\n\n try {\n const response = await fetch(endpointUrl, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(changes),\n });\n\n if (!response.ok) {\n const error = await getErrorMessage(response);\n throw new Error(error);\n }\n\n form.reset(currentValues);\n reportUpdate({\n entitySlug: 'messages',\n operation: 'update',\n updatedAt: new Date().toISOString(),\n });\n toast.success('Saved', { id: toastId });\n } catch (error) {\n toast.error(\n `Failed to save: ${error instanceof Error ? error.message : 'Unknown error'}`,\n { id: toastId },\n );\n }\n };\n\n return handleSubmit;\n}\n"],"names":["toast","useDocumentEvents","isEqual","getErrorMessage","useMessagesFormSubmit","endpointUrl","defaultValues","form","reportUpdate","handleSubmit","currentValues","toastId","loading","changes","Object","entries","reduce","acc","locale","value","hasChanged","response","fetch","method","headers","body","JSON","stringify","ok","error","Error","reset","entitySlug","operation","updatedAt","Date","toISOString","success","id","message"],"mappings":"AAAA,SAASA,KAAK,EAAEC,iBAAiB,QAAQ,iBAAiB;AAC1D,SAASC,OAAO,QAAQ,YAAY;AAIpC,SAASC,eAAe,QAAQ,yBAAyB;AAQzD,OAAO,SAASC,sBAAsB,EACpCC,WAAW,EACXC,aAAa,EACbC,IAAI,EACyB;IAC7B,MAAM,EAAEC,YAAY,EAAE,GAAGP;IAEzB,MAAMQ,eAAe,OAAOC;QAC1B,MAAMC,UAAUX,MAAMY,OAAO,CAAC;QAC9B,MAAMC,UAAUC,OAAOC,OAAO,CAACL,eAAeM,MAAM,CAElD,CAACC,KAAK,CAACC,QAAQC,MAAM;YACrB,MAAMC,aAAa,CAAClB,QAAQiB,OAAOb,aAAa,CAACY,OAAO;YACxD,IAAI,CAACE,YAAY,OAAOH;YACxBA,GAAG,CAACC,OAAO,GAAGC;YACd,OAAOF;QACT,GAAG,CAAC;QAEJ,IAAI;YACF,MAAMI,WAAW,MAAMC,MAAMjB,aAAa;gBACxCkB,QAAQ;gBACRC,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,MAAMC,KAAKC,SAAS,CAACd;YACvB;YAEA,IAAI,CAACQ,SAASO,EAAE,EAAE;gBAChB,MAAMC,QAAQ,MAAM1B,gBAAgBkB;gBACpC,MAAM,IAAIS,MAAMD;YAClB;YAEAtB,KAAKwB,KAAK,CAACrB;YACXF,aAAa;gBACXwB,YAAY;gBACZC,WAAW;gBACXC,WAAW,IAAIC,OAAOC,WAAW;YACnC;YACApC,MAAMqC,OAAO,CAAC,SAAS;gBAAEC,IAAI3B;YAAQ;QACvC,EAAE,OAAOkB,OAAO;YACd7B,MAAM6B,KAAK,CACT,CAAC,gBAAgB,EAAEA,iBAAiBC,QAAQD,MAAMU,OAAO,GAAG,iBAAiB,EAC7E;gBAAED,IAAI3B;YAAQ;QAElB;IACF;IAEA,OAAOF;AACT"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FieldError } from 'react-hook-form';
|
|
2
|
+
export interface FieldWrapperProps {
|
|
3
|
+
label?: string;
|
|
4
|
+
error: FieldError | undefined;
|
|
5
|
+
className?: string;
|
|
6
|
+
reference?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function FieldWrapper({ label, error, reference, className, children, }: React.PropsWithChildren<FieldWrapperProps>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=FieldWrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldWrapper.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/FieldWrapper.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,QAAQ,GACT,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,2CAa5C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import styles from './FieldWrapper.module.css';
|
|
4
|
+
import { ReferencePopover } from './ReferencePopover';
|
|
5
|
+
export function FieldWrapper({ label, error, reference, className, children }) {
|
|
6
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
7
|
+
className: clsx(styles.wrapper, className),
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ _jsx(ReferencePopover, {
|
|
10
|
+
reference: reference,
|
|
11
|
+
children: /*#__PURE__*/ _jsx("fieldset", {
|
|
12
|
+
className: clsx(styles.fieldset, error && styles.fieldsetError),
|
|
13
|
+
children: children
|
|
14
|
+
})
|
|
15
|
+
}),
|
|
16
|
+
error?.message && /*#__PURE__*/ _jsx("p", {
|
|
17
|
+
className: styles.errorMessage,
|
|
18
|
+
children: error.message
|
|
19
|
+
})
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=FieldWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/inputs/FieldWrapper.tsx"],"sourcesContent":["import { FieldLabel } from '@payloadcms/ui';\nimport clsx from 'clsx';\nimport type { FieldError } from 'react-hook-form';\n\nimport styles from './FieldWrapper.module.css';\nimport { ReferencePopover } from './ReferencePopover';\n\nexport interface FieldWrapperProps {\n label?: string;\n error: FieldError | undefined;\n className?: string;\n reference?: string;\n}\n\nexport function FieldWrapper({\n label,\n error,\n reference,\n className,\n children,\n}: React.PropsWithChildren<FieldWrapperProps>) {\n return (\n <div className={clsx(styles.wrapper, className)}>\n <ReferencePopover reference={reference}>\n <fieldset\n className={clsx(styles.fieldset, error && styles.fieldsetError)}\n >\n {children}\n </fieldset>\n </ReferencePopover>\n {error?.message && <p className={styles.errorMessage}>{error.message}</p>}\n </div>\n );\n}\n"],"names":["clsx","styles","ReferencePopover","FieldWrapper","label","error","reference","className","children","div","wrapper","fieldset","fieldsetError","message","p","errorMessage"],"mappings":";AACA,OAAOA,UAAU,OAAO;AAGxB,OAAOC,YAAY,4BAA4B;AAC/C,SAASC,gBAAgB,QAAQ,qBAAqB;AAStD,OAAO,SAASC,aAAa,EAC3BC,KAAK,EACLC,KAAK,EACLC,SAAS,EACTC,SAAS,EACTC,QAAQ,EACmC;IAC3C,qBACE,MAACC;QAAIF,WAAWP,KAAKC,OAAOS,OAAO,EAAEH;;0BACnC,KAACL;gBAAiBI,WAAWA;0BAC3B,cAAA,KAACK;oBACCJ,WAAWP,KAAKC,OAAOU,QAAQ,EAAEN,SAASJ,OAAOW,aAAa;8BAE7DJ;;;YAGJH,OAAOQ,yBAAW,KAACC;gBAAEP,WAAWN,OAAOc,YAAY;0BAAGV,MAAMQ,OAAO;;;;AAG1E"}
|
|
@@ -8,22 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
.fieldset {
|
|
10
10
|
margin-inline: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
border: none;
|
|
11
13
|
flex: 1;
|
|
12
|
-
border-radius: var(--style-radius-m);
|
|
13
|
-
overflow: visible;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.fieldset:focus-within {
|
|
17
|
-
border-color: var(--theme-elevation-400);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.fieldsetError {
|
|
21
|
-
border: 1px solid var(--theme-error-400);
|
|
22
|
-
background-color: var(--theme-error-100);
|
|
23
14
|
}
|
|
24
15
|
|
|
25
16
|
.legend {
|
|
26
|
-
margin-left: -0.5rem;
|
|
27
17
|
padding-inline: 0.375rem;
|
|
28
18
|
font-size: var(--font-size-base);
|
|
29
19
|
}
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
import type { InputWrapperProps } from './InputWrapper';
|
|
4
|
-
export interface LexicalInputProps extends InputWrapperProps {
|
|
1
|
+
import type { FieldWrapperProps } from './FieldWrapper';
|
|
2
|
+
export interface LexicalInputProps extends FieldWrapperProps {
|
|
5
3
|
lang: string;
|
|
6
4
|
value: string;
|
|
7
5
|
onChange: (value: string) => void;
|
|
8
6
|
onBlur: () => void;
|
|
9
7
|
}
|
|
10
8
|
export declare function LexicalInput({ error, label, value, onChange, className, }: LexicalInputProps): React.ReactNode;
|
|
11
|
-
interface UseHtmlLexicalAdapterProps {
|
|
12
|
-
html: string;
|
|
13
|
-
onChange: (html: string) => void;
|
|
14
|
-
}
|
|
15
|
-
export declare function useHtmlLexicalAdapter({ html, onChange, }: UseHtmlLexicalAdapterProps): {
|
|
16
|
-
value: TypedEditorState<DefaultNodeTypes>;
|
|
17
|
-
setValue: (serializedState: SerializedEditorState) => void;
|
|
18
|
-
};
|
|
19
|
-
export {};
|
|
20
9
|
//# sourceMappingURL=LexicalInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LexicalInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/LexicalInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LexicalInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/LexicalInput.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CAoBrC"}
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { createHeadlessEditor } from '@payloadcms/richtext-lexical/lexical/headless';
|
|
6
|
-
import { $generateHtmlFromNodes, $generateNodesFromDOM } from '@payloadcms/richtext-lexical/lexical/html';
|
|
7
|
-
import { useCallback, useMemo, useRef } from 'react';
|
|
8
|
-
import { InputWrapper } from './InputWrapper';
|
|
2
|
+
import { RenderLexical } from '@payloadcms/richtext-lexical/client';
|
|
3
|
+
import { useHtmlLexicalAdapter } from '../hooks/useHtmlLexicalAdapter';
|
|
4
|
+
import { FieldWrapper } from './FieldWrapper';
|
|
9
5
|
export function LexicalInput({ error, label, value, onChange, className }) {
|
|
10
6
|
const editor = useHtmlLexicalAdapter({
|
|
11
7
|
html: value,
|
|
12
8
|
onChange
|
|
13
9
|
});
|
|
14
|
-
return /*#__PURE__*/ _jsx(
|
|
10
|
+
return /*#__PURE__*/ _jsx(FieldWrapper, {
|
|
15
11
|
className: className,
|
|
16
12
|
error: error,
|
|
17
13
|
label: label,
|
|
@@ -27,60 +23,5 @@ export function LexicalInput({ error, label, value, onChange, className }) {
|
|
|
27
23
|
})
|
|
28
24
|
});
|
|
29
25
|
}
|
|
30
|
-
const EMPTY_STATE = buildDefaultEditorState({});
|
|
31
|
-
export function useHtmlLexicalAdapter({ html, onChange }) {
|
|
32
|
-
// 1. Maintain a persistent headless editor for conversion
|
|
33
|
-
const headlessEditor = useRef(createHeadlessEditor({
|
|
34
|
-
nodes: getEnabledNodes({
|
|
35
|
-
editorConfig: sanitizeClientEditorConfig(// @ts-expect-error - FIXME
|
|
36
|
-
defaultEditorFeatures, defaultEditorConfig)
|
|
37
|
-
})
|
|
38
|
-
}));
|
|
39
|
-
// 2. HTML -> SerializedState
|
|
40
|
-
const getSerializedState = useCallback((htmlString)=>{
|
|
41
|
-
const editor = headlessEditor.current;
|
|
42
|
-
editor.update(()=>{
|
|
43
|
-
const parser = new DOMParser();
|
|
44
|
-
const dom = parser.parseFromString(htmlString, 'text/html');
|
|
45
|
-
const nodes = $generateNodesFromDOM(editor, dom);
|
|
46
|
-
const root = $getRoot();
|
|
47
|
-
root.clear().append(...nodes);
|
|
48
|
-
}, {
|
|
49
|
-
discrete: true
|
|
50
|
-
});
|
|
51
|
-
return editor.getEditorState().toJSON();
|
|
52
|
-
}, []);
|
|
53
|
-
// 3. Memoize the initial value to prevent unnecessary re-renders
|
|
54
|
-
const value = useMemo(()=>{
|
|
55
|
-
const serializedState = getSerializedState(html);
|
|
56
|
-
if (serializedState.root.children.length === 0) {
|
|
57
|
-
return EMPTY_STATE;
|
|
58
|
-
}
|
|
59
|
-
return serializedState;
|
|
60
|
-
}, [
|
|
61
|
-
html,
|
|
62
|
-
getSerializedState
|
|
63
|
-
]);
|
|
64
|
-
// 4. SerializedState -> HTML
|
|
65
|
-
const setValue = useCallback((serializedState)=>{
|
|
66
|
-
const editor = headlessEditor.current;
|
|
67
|
-
// Update headless editor to match the incoming state
|
|
68
|
-
editor.setEditorState(editor.parseEditorState(serializedState));
|
|
69
|
-
// Generate HTML and broadcast if it has changed
|
|
70
|
-
editor.read(()=>{
|
|
71
|
-
const newHtml = $generateHtmlFromNodes(editor);
|
|
72
|
-
if (newHtml !== html) {
|
|
73
|
-
onChange(newHtml);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
}, [
|
|
77
|
-
html,
|
|
78
|
-
onChange
|
|
79
|
-
]);
|
|
80
|
-
return {
|
|
81
|
-
value: value,
|
|
82
|
-
setValue
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
26
|
|
|
86
27
|
//# sourceMappingURL=LexicalInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/inputs/LexicalInput.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/components/inputs/LexicalInput.tsx"],"sourcesContent":["import { RenderLexical } from '@payloadcms/richtext-lexical/client';\nimport type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical';\nimport { useHtmlLexicalAdapter } from '../hooks/useHtmlLexicalAdapter';\nimport type { FieldWrapperProps } from './FieldWrapper';\nimport { FieldWrapper } from './FieldWrapper';\n\nexport interface LexicalInputProps extends FieldWrapperProps {\n lang: string;\n value: string;\n onChange: (value: string) => void;\n onBlur: () => void;\n}\n\nexport function LexicalInput({\n error,\n label,\n value,\n onChange,\n className,\n}: LexicalInputProps): React.ReactNode {\n const editor = useHtmlLexicalAdapter({\n html: value,\n onChange,\n });\n\n return (\n <FieldWrapper className={className} error={error} label={label}>\n <RenderLexical\n field={{\n name: 'myCustomEditor',\n label: false,\n type: 'richText',\n }}\n schemaPath=\"global.intl-plugin.editorTemplate\"\n setValue={(val) => editor.setValue(val as SerializedEditorState)}\n value={editor.value}\n />\n </FieldWrapper>\n );\n}\n"],"names":["RenderLexical","useHtmlLexicalAdapter","FieldWrapper","LexicalInput","error","label","value","onChange","className","editor","html","field","name","type","schemaPath","setValue","val"],"mappings":";AAAA,SAASA,aAAa,QAAQ,sCAAsC;AAEpE,SAASC,qBAAqB,QAAQ,iCAAiC;AAEvE,SAASC,YAAY,QAAQ,iBAAiB;AAS9C,OAAO,SAASC,aAAa,EAC3BC,KAAK,EACLC,KAAK,EACLC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACS;IAClB,MAAMC,SAASR,sBAAsB;QACnCS,MAAMJ;QACNC;IACF;IAEA,qBACE,KAACL;QAAaM,WAAWA;QAAWJ,OAAOA;QAAOC,OAAOA;kBACvD,cAAA,KAACL;YACCW,OAAO;gBACLC,MAAM;gBACNP,OAAO;gBACPQ,MAAM;YACR;YACAC,YAAW;YACXC,UAAU,CAACC,MAAQP,OAAOM,QAAQ,CAACC;YACnCV,OAAOG,OAAOH,KAAK;;;AAI3B"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { TemplateVariable } from '../../types';
|
|
2
|
-
import type {
|
|
3
|
-
export interface MessageInputProps extends
|
|
2
|
+
import type { FieldWrapperProps } from './FieldWrapper';
|
|
3
|
+
export interface MessageInputProps extends FieldWrapperProps {
|
|
4
4
|
value: string;
|
|
5
5
|
lang: string;
|
|
6
6
|
variables: TemplateVariable[];
|
|
7
7
|
onChange: (value: string) => void;
|
|
8
8
|
onBlur: () => void;
|
|
9
|
+
readOnly?: boolean;
|
|
10
|
+
multiline?: boolean;
|
|
11
|
+
reference?: string;
|
|
9
12
|
}
|
|
10
|
-
export declare function MessageInput({ label, value, lang, error, variables, onChange, onBlur, className, }: MessageInputProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function MessageInput({ label, value, lang, error, variables, onChange, onBlur, className, multiline, reference, }: MessageInputProps): import("react/jsx-runtime").JSX.Element;
|
|
11
14
|
//# sourceMappingURL=MessageInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/MessageInput.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAShD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/MessageInput.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAShD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA2BxD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,IAAI,EACJ,KAAK,EACL,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,SAAS,EACT,SAAS,GACV,EAAE,iBAAiB,2CAuFnB"}
|
|
@@ -2,44 +2,40 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { $getRoot } from '@payloadcms/richtext-lexical/lexical';
|
|
4
4
|
import { LexicalComposer } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposer';
|
|
5
|
+
import { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext';
|
|
5
6
|
import { ContentEditable } from '@payloadcms/richtext-lexical/lexical/react/LexicalContentEditable';
|
|
6
7
|
import { LexicalErrorBoundary } from '@payloadcms/richtext-lexical/lexical/react/LexicalErrorBoundary';
|
|
7
8
|
import { HistoryPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalHistoryPlugin';
|
|
8
9
|
import { OnChangePlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalOnChangePlugin';
|
|
9
10
|
import { PlainTextPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalPlainTextPlugin';
|
|
11
|
+
import clsx from 'clsx';
|
|
10
12
|
import { BeautifulMentionNode, BeautifulMentionsPlugin } from 'lexical-beautiful-mentions';
|
|
11
|
-
import {
|
|
13
|
+
import { useCallback, useEffect, useMemo } from 'react';
|
|
12
14
|
import { formatVariableLabel } from '../../utils/format';
|
|
13
15
|
import { isTagElement } from '../../utils/guards';
|
|
14
16
|
import { parseIcuToLexicalState, serializeICUMessage } from '../../utils/icu-tranform';
|
|
15
|
-
import {
|
|
17
|
+
import { FieldWrapper } from './FieldWrapper';
|
|
16
18
|
import styles from './MessageInput.module.css';
|
|
19
|
+
import { SingleLinePlugin } from './SingleLinePlugin';
|
|
17
20
|
import { VariableMentionNode } from './variables/VariableNode';
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
role: "option",
|
|
37
|
-
tabIndex: -1,
|
|
38
|
-
children: typeof props.item.data?.label === 'string' ? props.item.data.label : props.item.displayValue
|
|
39
|
-
}));
|
|
40
|
-
// TODO add variable editor (style, options, etc)
|
|
41
|
-
// TODO add tooltip to show all variables
|
|
42
|
-
export function MessageInput({ label, value, lang, error, variables, onChange, onBlur, className }) {
|
|
21
|
+
import { MentionMenu, MentionMenuItem } from './variables/VariableSuggestion';
|
|
22
|
+
function SyncValuePlugin({ value }) {
|
|
23
|
+
const [editor] = useLexicalComposerContext();
|
|
24
|
+
useEffect(()=>{
|
|
25
|
+
const currentText = editor.getEditorState().read(()=>$getRoot().getTextContent());
|
|
26
|
+
if (value !== currentText) {
|
|
27
|
+
queueMicrotask(()=>{
|
|
28
|
+
const newState = editor.parseEditorState(JSON.stringify(parseIcuToLexicalState(value)));
|
|
29
|
+
editor.setEditorState(newState);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}, [
|
|
33
|
+
value,
|
|
34
|
+
editor
|
|
35
|
+
]);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
export function MessageInput({ label, value, lang, error, variables, onChange, onBlur, className, multiline, reference }) {
|
|
43
39
|
const handleChange = useCallback((editorState)=>{
|
|
44
40
|
editorState.read(()=>{
|
|
45
41
|
onChange($getRoot().getTextContent());
|
|
@@ -63,35 +59,43 @@ export function MessageInput({ label, value, lang, error, variables, onChange, o
|
|
|
63
59
|
}, [
|
|
64
60
|
variables
|
|
65
61
|
]);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
62
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: LexicalComposer only reads initialConfig on mount
|
|
63
|
+
const initialConfig = useMemo(()=>({
|
|
64
|
+
namespace: 'ICUMessageEditor',
|
|
65
|
+
nodes: [
|
|
66
|
+
VariableMentionNode,
|
|
67
|
+
{
|
|
68
|
+
replace: BeautifulMentionNode,
|
|
69
|
+
with: (node)=>new VariableMentionNode(node.getTrigger(), node.getValue(), node.getData()),
|
|
70
|
+
withKlass: VariableMentionNode
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
editorState: JSON.stringify(parseIcuToLexicalState(value)),
|
|
74
|
+
editable: true,
|
|
75
|
+
onError: console.error
|
|
76
|
+
}), []);
|
|
77
|
+
return /*#__PURE__*/ _jsx(FieldWrapper, {
|
|
79
78
|
className: className,
|
|
80
79
|
error: error,
|
|
81
80
|
label: label,
|
|
81
|
+
reference: reference,
|
|
82
82
|
children: /*#__PURE__*/ _jsx(LexicalComposer, {
|
|
83
83
|
initialConfig: initialConfig,
|
|
84
84
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
85
|
-
className: styles.editor,
|
|
85
|
+
className: clsx(styles.editor, multiline && styles.multiline),
|
|
86
86
|
lang: lang,
|
|
87
|
-
onBlur: onBlur,
|
|
88
87
|
children: [
|
|
89
88
|
/*#__PURE__*/ _jsx(PlainTextPlugin, {
|
|
90
89
|
contentEditable: /*#__PURE__*/ _jsx(ContentEditable, {
|
|
91
|
-
className: styles.contentEditable
|
|
90
|
+
className: clsx(styles.contentEditable, error && styles.contentEditableError),
|
|
91
|
+
onBlur: onBlur
|
|
92
92
|
}),
|
|
93
93
|
ErrorBoundary: LexicalErrorBoundary
|
|
94
94
|
}),
|
|
95
|
+
multiline && /*#__PURE__*/ _jsx(SingleLinePlugin, {}),
|
|
96
|
+
/*#__PURE__*/ _jsx(SyncValuePlugin, {
|
|
97
|
+
value: value
|
|
98
|
+
}),
|
|
95
99
|
/*#__PURE__*/ _jsx(OnChangePlugin, {
|
|
96
100
|
onChange: handleChange
|
|
97
101
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/inputs/MessageInput.tsx"],"sourcesContent":["'use client';\n\nimport type { EditorState } from '@payloadcms/richtext-lexical/lexical';\nimport { $getRoot } from '@payloadcms/richtext-lexical/lexical';\nimport { LexicalComposer } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposer';\nimport { ContentEditable } from '@payloadcms/richtext-lexical/lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@payloadcms/richtext-lexical/lexical/react/LexicalErrorBoundary';\nimport { HistoryPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalHistoryPlugin';\nimport { OnChangePlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalOnChangePlugin';\nimport { PlainTextPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalPlainTextPlugin';\nimport {\n BeautifulMentionNode,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/inputs/MessageInput.tsx"],"sourcesContent":["'use client';\n\nimport type { EditorState } from '@payloadcms/richtext-lexical/lexical';\nimport { $getRoot } from '@payloadcms/richtext-lexical/lexical';\nimport { LexicalComposer } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposer';\nimport { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext';\nimport { ContentEditable } from '@payloadcms/richtext-lexical/lexical/react/LexicalContentEditable';\nimport { LexicalErrorBoundary } from '@payloadcms/richtext-lexical/lexical/react/LexicalErrorBoundary';\nimport { HistoryPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalHistoryPlugin';\nimport { OnChangePlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalOnChangePlugin';\nimport { PlainTextPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalPlainTextPlugin';\nimport clsx from 'clsx';\nimport {\n BeautifulMentionNode,\n BeautifulMentionsPlugin,\n} from 'lexical-beautiful-mentions';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport type { TemplateVariable } from '@/types';\n\nimport { formatVariableLabel } from '@/utils/format';\nimport { isTagElement } from '@/utils/guards';\nimport {\n parseIcuToLexicalState,\n serializeICUMessage,\n} from '@/utils/icu-tranform';\n\nimport type { FieldWrapperProps } from './FieldWrapper';\nimport { FieldWrapper } from './FieldWrapper';\nimport styles from './MessageInput.module.css';\nimport { SingleLinePlugin } from './SingleLinePlugin';\nimport { VariableMentionNode } from './variables/VariableNode';\nimport { MentionMenu, MentionMenuItem } from './variables/VariableSuggestion';\n\nfunction SyncValuePlugin({ value }: { value: string }) {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const currentText = editor\n .getEditorState()\n .read(() => $getRoot().getTextContent());\n if (value !== currentText) {\n queueMicrotask(() => {\n const newState = editor.parseEditorState(\n JSON.stringify(parseIcuToLexicalState(value)),\n );\n editor.setEditorState(newState);\n });\n }\n }, [value, editor]);\n\n return null;\n}\n\nexport interface MessageInputProps extends FieldWrapperProps {\n value: string;\n lang: string;\n variables: TemplateVariable[];\n onChange: (value: string) => void;\n onBlur: () => void;\n readOnly?: boolean;\n multiline?: boolean;\n reference?: string;\n}\n\nexport function MessageInput({\n label,\n value,\n lang,\n error,\n variables,\n onChange,\n onBlur,\n className,\n multiline,\n reference,\n}: MessageInputProps) {\n const handleChange = useCallback(\n (editorState: EditorState) => {\n editorState.read(() => {\n onChange($getRoot().getTextContent());\n });\n },\n [onChange],\n );\n\n const mentionItems = useMemo(() => {\n const toItem = (v: TemplateVariable) => ({\n value: v.value,\n label: formatVariableLabel(v),\n icu: serializeICUMessage([v]),\n });\n\n return {\n '@': variables.map(toItem),\n '{': variables.filter((v) => !isTagElement(v)).map(toItem),\n '<': variables.filter((v) => isTagElement(v)).map(toItem),\n };\n }, [variables]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: LexicalComposer only reads initialConfig on mount\n const initialConfig = useMemo(\n () => ({\n namespace: 'ICUMessageEditor',\n nodes: [\n VariableMentionNode,\n {\n replace: BeautifulMentionNode,\n with: (node: BeautifulMentionNode) =>\n new VariableMentionNode(\n node.getTrigger(),\n node.getValue(),\n node.getData(),\n ),\n withKlass: VariableMentionNode,\n },\n ],\n editorState: JSON.stringify(parseIcuToLexicalState(value)),\n editable: true,\n onError: console.error,\n }),\n [],\n );\n\n return (\n <FieldWrapper\n className={className}\n error={error}\n label={label}\n reference={reference}\n >\n <LexicalComposer initialConfig={initialConfig}>\n <div\n className={clsx(styles.editor, multiline && styles.multiline)}\n lang={lang}\n >\n <PlainTextPlugin\n contentEditable={\n <ContentEditable\n className={clsx(\n styles.contentEditable,\n error && styles.contentEditableError,\n )}\n onBlur={onBlur}\n />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n {multiline && <SingleLinePlugin />}\n <SyncValuePlugin value={value} />\n <OnChangePlugin onChange={handleChange} />\n <HistoryPlugin />\n\n <BeautifulMentionsPlugin\n items={mentionItems}\n menuAnchorClassName={styles.menuAnchor}\n menuComponent={MentionMenu}\n menuItemComponent={MentionMenuItem}\n />\n </div>\n </LexicalComposer>\n </FieldWrapper>\n );\n}\n"],"names":["$getRoot","LexicalComposer","useLexicalComposerContext","ContentEditable","LexicalErrorBoundary","HistoryPlugin","OnChangePlugin","PlainTextPlugin","clsx","BeautifulMentionNode","BeautifulMentionsPlugin","useCallback","useEffect","useMemo","formatVariableLabel","isTagElement","parseIcuToLexicalState","serializeICUMessage","FieldWrapper","styles","SingleLinePlugin","VariableMentionNode","MentionMenu","MentionMenuItem","SyncValuePlugin","value","editor","currentText","getEditorState","read","getTextContent","queueMicrotask","newState","parseEditorState","JSON","stringify","setEditorState","MessageInput","label","lang","error","variables","onChange","onBlur","className","multiline","reference","handleChange","editorState","mentionItems","toItem","v","icu","map","filter","initialConfig","namespace","nodes","replace","with","node","getTrigger","getValue","getData","withKlass","editable","onError","console","div","contentEditable","contentEditableError","ErrorBoundary","items","menuAnchorClassName","menuAnchor","menuComponent","menuItemComponent"],"mappings":"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"}
|
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
.editor {
|
|
2
2
|
position: relative;
|
|
3
|
+
display: grid;
|
|
4
|
+
align-items: center;
|
|
3
5
|
min-height: 2rem;
|
|
4
6
|
font-size: var(--font-size-large);
|
|
5
7
|
}
|
|
6
8
|
|
|
9
|
+
.readOnly {
|
|
10
|
+
opacity: 0.7;
|
|
11
|
+
cursor: default;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.multiline {
|
|
15
|
+
min-height: 4rem;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
.menuAnchor {
|
|
8
19
|
z-index: 50;
|
|
9
20
|
}
|
|
10
21
|
|
|
11
22
|
.contentEditable {
|
|
12
23
|
outline: none;
|
|
24
|
+
border-radius: var(--style-radius-m);
|
|
25
|
+
background-color: var(--theme-elevation-0);
|
|
26
|
+
border: 1px solid var(--theme-elevation-300);
|
|
27
|
+
padding-block: 0.25rem;
|
|
28
|
+
padding-inline: 0.75rem;
|
|
29
|
+
height: 100%;
|
|
13
30
|
}
|
|
14
31
|
|
|
15
32
|
.contentEditable:focus {
|
|
16
33
|
outline: none;
|
|
34
|
+
border-color: var(--theme-elevation-600);
|
|
17
35
|
}
|
|
18
36
|
|
|
19
|
-
.
|
|
20
|
-
|
|
37
|
+
.contentEditableError {
|
|
38
|
+
border-color: var(--theme-error-400);
|
|
39
|
+
background-color: var(--theme-error-100);
|
|
21
40
|
}
|
|
22
41
|
|
|
23
|
-
.contentEditable
|
|
24
|
-
margin
|
|
42
|
+
.contentEditable p {
|
|
43
|
+
margin: 0;
|
|
25
44
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
export interface ReferencePopoverProps {
|
|
3
|
+
reference?: string;
|
|
4
|
+
children: ReactElement;
|
|
5
|
+
}
|
|
6
|
+
export declare function ReferencePopover({ reference, children, }: ReferencePopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ReferencePopover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReferencePopover.d.ts","sourceRoot":"","sources":["../../../src/components/inputs/ReferencePopover.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,QAAQ,GACT,EAAE,qBAAqB,2CAqBvB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Popover } from '@base-ui/react/popover';
|
|
3
|
+
import { IconX } from '@tabler/icons-react';
|
|
4
|
+
import styles from './ReferencePopover.module.css';
|
|
5
|
+
export function ReferencePopover({ reference, children }) {
|
|
6
|
+
if (!reference) return children;
|
|
7
|
+
return /*#__PURE__*/ _jsxs(Popover.Root, {
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ _jsx(Popover.Trigger, {
|
|
10
|
+
nativeButton: false,
|
|
11
|
+
render: children
|
|
12
|
+
}),
|
|
13
|
+
/*#__PURE__*/ _jsx(Popover.Portal, {
|
|
14
|
+
children: /*#__PURE__*/ _jsx(Popover.Positioner, {
|
|
15
|
+
align: "start",
|
|
16
|
+
side: "top",
|
|
17
|
+
sideOffset: 4,
|
|
18
|
+
children: /*#__PURE__*/ _jsxs(Popover.Popup, {
|
|
19
|
+
className: styles.popup,
|
|
20
|
+
initialFocus: false,
|
|
21
|
+
onMouseDown: (e)=>e.preventDefault(),
|
|
22
|
+
children: [
|
|
23
|
+
/*#__PURE__*/ _jsx(Popover.Close, {
|
|
24
|
+
className: styles.dismiss,
|
|
25
|
+
type: "button",
|
|
26
|
+
children: /*#__PURE__*/ _jsx(IconX, {
|
|
27
|
+
size: 14
|
|
28
|
+
})
|
|
29
|
+
}),
|
|
30
|
+
/*#__PURE__*/ _jsx("p", {
|
|
31
|
+
className: styles.text,
|
|
32
|
+
children: reference
|
|
33
|
+
})
|
|
34
|
+
]
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=ReferencePopover.js.map
|