pentatrion-design 1.2.6 → 1.2.7

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 1.2.7
2
+
3
+ ### Patch Changes
4
+
5
+ - b21f8c8: better wysiwygSchema validation
6
+ - 6dc10d7: enhance wysiwyg submitOnEnterPlugin
7
+ - 6dc10d7: fix useDoubleCheck typing
8
+ - 6dc10d7: fix fileField
9
+
1
10
  ## 1.2.6
2
11
 
3
12
  ### Patch Changes
@@ -1,2 +1,2 @@
1
- import { a as parseMediaValue, i as mediaSchema, n as Media, o as serializeMediaValue, r as MediaImage, t as FileField } from "../../../index-BG2A_6RX.mjs";
1
+ import { a as parseMediaValue, i as mediaSchema, n as Media, o as serializeMediaValue, r as MediaImage, t as FileField } from "../../../index-DDmga78w.mjs";
2
2
  export { FileField, type Media, type MediaImage, mediaSchema, parseMediaValue, serializeMediaValue };
@@ -43,8 +43,6 @@ const mockMedias = [
43
43
  origin: "external",
44
44
  category: "audio",
45
45
  mimeType: "audio/mpeg",
46
- width: null,
47
- height: null,
48
46
  size: null,
49
47
  src: "/audio/mock-track.mp3"
50
48
  }
@@ -56,8 +54,6 @@ const mockMedias = [
56
54
  origin: "external",
57
55
  category: "document",
58
56
  mimeType: "application/pdf",
59
- width: null,
60
- height: null,
61
57
  size: null,
62
58
  src: "/documents/mock-file.pdf"
63
59
  }
@@ -243,8 +239,8 @@ const mediaSchema = z.object({
243
239
  id: z.string(),
244
240
  category: z.string(),
245
241
  mimeType: z.string(),
246
- width: z._default(z.nullable(z.coerce.number().check(z.int())), null),
247
- height: z._default(z.nullable(z.coerce.number().check(z.int())), null),
242
+ width: z.optional(z.coerce.number().check(z.int())),
243
+ height: z.optional(z.coerce.number().check(z.int())),
248
244
  origin: z.enum([
249
245
  "s3Upload",
250
246
  "localUpload",
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["useMemo","useState","clsx","Button","Modal","ModalContent","ModalDescription","ModalFooter","ModalHeader","Media","Props","onPick","media","allowedTypes","imageRatio","className","id","mockMedias","label","origin","category","mimeType","width","height","size","src","UploaderMock","t0","$","_c","isOpen","setIsOpen","t1","t2","cssProperties","t3","t4","Symbol","for","t5","t6","t7","map","t8","idx","t9","t10","t11","t12","useControl","useField","FieldName","Field","FieldProps","isMediaImage","MediaPreview","Button","UploaderMock","Media","Props","Omit","name","mediaContainerClassName","allowedTypes","imageRatio","FileField","id","forcedId","rest","field","itemErrors","Object","values","fieldErrors","flat","errors","length","undefined","control","defaultValue","parse","payload","Error","JSON","serialize","value","stringify","media","register","change","console","log","z","mediaSchema","object","id","string","category","mimeType","width","_default","nullable","coerce","number","check","int","height","origin","enum","src","size","Media","infer","MediaImage","Omit","parseMediaValue","payload","undefined","Error","JSON","parse","serializeMediaValue","value","stringify"],"sources":["../../../../src/components/fields/file/UploaderMock.tsx","../../../../src/components/fields/file/FileField.tsx","../../../../src/components/fields/file/types.ts"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport clsx from \"clsx\";\nimport { Button } from \"../../button/Button\";\nimport { Modal, ModalContent, ModalDescription, ModalFooter, ModalHeader } from \"../../modal\";\nimport type { Media } from \"./types\";\n\ninterface Props {\n onPick: (media: Media | null) => void;\n allowedTypes?: \"image\" | \"audio\" | \"all-safe\";\n imageRatio?: number;\n className?: string;\n id?: string;\n}\n\nconst mockMedias: { label: string; media: Media | null }[] = [\n {\n label: \"Image paysage\",\n media: {\n id: \"mock-landscape\",\n origin: \"external\",\n category: \"image\",\n mimeType: \"image/jpg\",\n width: 400,\n height: 300,\n size: null,\n src: \"/medias/400x300.jpg\",\n },\n },\n {\n label: \"Image portrait\",\n media: {\n id: \"mock-portrait\",\n origin: \"external\",\n category: \"image\",\n mimeType: \"image/jpeg\",\n width: 600,\n height: 900,\n size: null,\n src: \"https://picsum.photos/600/900\",\n },\n },\n {\n label: \"Audio\",\n media: {\n id: \"mock-audio\",\n origin: \"external\",\n category: \"audio\",\n mimeType: \"audio/mpeg\",\n width: null,\n height: null,\n size: null,\n src: \"/audio/mock-track.mp3\",\n },\n },\n {\n label: \"PDF\",\n media: {\n id: \"mock-pdf\",\n origin: \"external\",\n category: \"document\",\n mimeType: \"application/pdf\",\n width: null,\n height: null,\n size: null,\n src: \"/documents/mock-file.pdf\",\n },\n },\n {\n label: \"Null\",\n media: null,\n },\n];\n\nexport function UploaderMock({ onPick, imageRatio, className, id }: Props) {\n const [isOpen, setIsOpen] = useState(false);\n\n const cssProperties = useMemo(() => ({ \"--media-ratio\": imageRatio ?? 16 / 9 }), [imageRatio]);\n\n return (\n <div\n className={clsx(\n \"bg-gray-0/50 outline-gray-2 relative flex aspect-(--media-ratio) flex-col items-center justify-center rounded-2xl outline\",\n className,\n )}\n style={cssProperties}\n >\n <Button id={id} type=\"button\" onClick={() => setIsOpen(true)}>\n Choisir un média (mock)\n </Button>\n\n <Modal open={isOpen} onOpen={setIsOpen}>\n <ModalContent>\n <ModalHeader>Choisir un média (mock)</ModalHeader>\n <ModalDescription>\n <div className=\"flex flex-col gap-2 p-4\">\n {mockMedias.map(({ label, media }, idx) => (\n <Button\n key={media?.id ?? idx}\n type=\"button\"\n onClick={() => {\n onPick(media);\n setIsOpen(false);\n }}\n >\n {label}\n </Button>\n ))}\n </div>\n </ModalDescription>\n <ModalFooter>\n <div className=\"flex justify-end\">\n <Button variant=\"text\" color=\"gray\" onClick={() => setIsOpen(false)}>\n Annuler\n </Button>\n </div>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n}\n","import { useControl, useField, type FieldName } from \"@conform-to/react/future\";\nimport { Field, type FieldProps } from \"../field/Field\";\nimport { isMediaImage, MediaPreview } from \"../../media-preview\";\nimport { Button } from \"../../button/Button\";\n\nimport { UploaderMock } from \"./UploaderMock\";\nimport { Media } from \"./types\";\n\ntype Props = Omit<FieldProps, \"children\" | \"group\"> & {\n name: FieldName<Media | null | undefined>;\n mediaContainerClassName?: string;\n allowedTypes?: \"image\" | \"audio\" | \"all-safe\";\n imageRatio?: number;\n};\n\nexport function FileField({\n name,\n mediaContainerClassName,\n allowedTypes = \"all-safe\",\n imageRatio,\n id: forcedId,\n ...rest\n}: Props) {\n const field = useField(name);\n const id = forcedId ?? field.id;\n\n const itemErrors = Object.values(field.fieldErrors).flat();\n const errors = field.errors ?? (itemErrors.length > 0 ? itemErrors : undefined);\n\n const control = useControl<Media, string>({\n defaultValue: field.defaultValue,\n parse(payload) {\n if (typeof payload !== \"string\") {\n throw new Error(\"media input must return string\");\n }\n if (payload == null || payload === \"\") {\n return undefined;\n }\n return JSON.parse(payload);\n },\n // appelé uniquement par control.change(value) (ex: onPick, le bouton de suppression) :\n // convertit le Media/null en string écrite dans l'input caché et déclenche l'event\n // \"input\" natif. N'est pas utilisé pour le defaultValue initial (déjà une string).\n serialize(value) {\n return typeof value !== \"string\" && value != null ? JSON.stringify(value) : value;\n },\n });\n\n const media = control.payload;\n\n return (\n <>\n <input\n name={field.name}\n type=\"text\"\n autoComplete=\"off\"\n tabIndex={-1}\n ref={control.register}\n defaultValue={control.defaultValue ?? \"\"}\n />\n <Field id={id} errors={errors} data-testid={field.name} {...rest}>\n {media ? (\n <MediaPreview\n media={media}\n fit={isMediaImage(media) ? \"original\" : \"cover\"}\n className={mediaContainerClassName}\n >\n <Button\n onClick={() => {\n control.change(null);\n }}\n type=\"button\"\n icon\n color=\"gray\"\n size=\"large\"\n >\n <i className=\"fe-trash text-body-xl\"></i>\n </Button>\n </MediaPreview>\n ) : (\n <UploaderMock\n id={id}\n className={mediaContainerClassName}\n onPick={(media: Media | null) => {\n console.log(\"onPick\", media);\n control.change(media);\n }}\n imageRatio={imageRatio}\n allowedTypes={allowedTypes}\n />\n )}\n </Field>\n </>\n );\n}\n","import { z } from \"zod/v4-mini\";\n\nexport const mediaSchema = z.object({\n id: z.string(),\n category: z.string(),\n mimeType: z.string(),\n width: z._default(z.nullable(z.coerce.number().check(z.int())), null),\n height: z._default(z.nullable(z.coerce.number().check(z.int())), null),\n origin: z.enum([\"s3Upload\", \"localUpload\", \"external\", \"asset\"]),\n src: z.string(),\n // in bytes\n size: z._default(z.nullable(z.coerce.number().check(z.int())), null),\n});\n\nexport type Media = z.infer<typeof mediaSchema>;\n\nexport type MediaImage = Omit<Media, \"width\" | \"height\"> & {\n width: number;\n height: number;\n};\n\nexport function parseMediaValue(payload: unknown): Media | undefined {\n if (payload == null || payload === \"\") {\n return undefined;\n }\n if (typeof payload !== \"string\") {\n throw new Error(\"media value must be a JSON string\");\n }\n try {\n return JSON.parse(payload);\n } catch {\n // JSON corrompu (ex. donnée persistée avant une migration de schéma) : on dégrade\n // gracieusement vers \"absent\" plutôt que de faire planter le rendu du champ.\n return undefined;\n }\n}\n\nexport function serializeMediaValue(value: unknown): string | null {\n return value == null ? null : typeof value === \"string\" ? value : JSON.stringify(value);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["useMemo","useState","clsx","Button","Modal","ModalContent","ModalDescription","ModalFooter","ModalHeader","Media","Props","onPick","media","allowedTypes","imageRatio","className","id","mockMedias","label","origin","category","mimeType","width","height","size","src","UploaderMock","t0","$","_c","isOpen","setIsOpen","t1","t2","cssProperties","t3","t4","Symbol","for","t5","t6","t7","map","t8","idx","t9","t10","t11","t12","useControl","useField","FieldName","Field","FieldProps","isMediaImage","MediaPreview","Button","UploaderMock","Media","Props","Omit","name","mediaContainerClassName","allowedTypes","imageRatio","FileField","id","forcedId","rest","field","itemErrors","Object","values","fieldErrors","flat","errors","length","undefined","control","defaultValue","parse","payload","Error","JSON","serialize","value","stringify","media","register","change","console","log","z","mediaSchema","object","id","string","category","mimeType","width","optional","coerce","number","check","int","height","origin","enum","src","size","_default","nullable","Media","infer","MediaImage","Omit","parseMediaValue","payload","undefined","Error","JSON","parse","serializeMediaValue","value","stringify"],"sources":["../../../../src/components/fields/file/UploaderMock.tsx","../../../../src/components/fields/file/FileField.tsx","../../../../src/components/fields/file/types.ts"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport clsx from \"clsx\";\nimport { Button } from \"../../button/Button\";\nimport { Modal, ModalContent, ModalDescription, ModalFooter, ModalHeader } from \"../../modal\";\nimport type { Media } from \"./types\";\n\ninterface Props {\n onPick: (media: Media | null) => void;\n allowedTypes?: \"image\" | \"audio\" | \"all-safe\";\n imageRatio?: number;\n className?: string;\n id?: string;\n}\n\nconst mockMedias: { label: string; media: Media | null }[] = [\n {\n label: \"Image paysage\",\n media: {\n id: \"mock-landscape\",\n origin: \"external\",\n category: \"image\",\n mimeType: \"image/jpg\",\n width: 400,\n height: 300,\n size: null,\n src: \"/medias/400x300.jpg\",\n },\n },\n {\n label: \"Image portrait\",\n media: {\n id: \"mock-portrait\",\n origin: \"external\",\n category: \"image\",\n mimeType: \"image/jpeg\",\n width: 600,\n height: 900,\n size: null,\n src: \"https://picsum.photos/600/900\",\n },\n },\n {\n label: \"Audio\",\n media: {\n id: \"mock-audio\",\n origin: \"external\",\n category: \"audio\",\n mimeType: \"audio/mpeg\",\n size: null,\n src: \"/audio/mock-track.mp3\",\n },\n },\n {\n label: \"PDF\",\n media: {\n id: \"mock-pdf\",\n origin: \"external\",\n category: \"document\",\n mimeType: \"application/pdf\",\n size: null,\n src: \"/documents/mock-file.pdf\",\n },\n },\n {\n label: \"Null\",\n media: null,\n },\n];\n\nexport function UploaderMock({ onPick, imageRatio, className, id }: Props) {\n const [isOpen, setIsOpen] = useState(false);\n\n const cssProperties = useMemo(() => ({ \"--media-ratio\": imageRatio ?? 16 / 9 }), [imageRatio]);\n\n return (\n <div\n className={clsx(\n \"bg-gray-0/50 outline-gray-2 relative flex aspect-(--media-ratio) flex-col items-center justify-center rounded-2xl outline\",\n className,\n )}\n style={cssProperties}\n >\n <Button id={id} type=\"button\" onClick={() => setIsOpen(true)}>\n Choisir un média (mock)\n </Button>\n\n <Modal open={isOpen} onOpen={setIsOpen}>\n <ModalContent>\n <ModalHeader>Choisir un média (mock)</ModalHeader>\n <ModalDescription>\n <div className=\"flex flex-col gap-2 p-4\">\n {mockMedias.map(({ label, media }, idx) => (\n <Button\n key={media?.id ?? idx}\n type=\"button\"\n onClick={() => {\n onPick(media);\n setIsOpen(false);\n }}\n >\n {label}\n </Button>\n ))}\n </div>\n </ModalDescription>\n <ModalFooter>\n <div className=\"flex justify-end\">\n <Button variant=\"text\" color=\"gray\" onClick={() => setIsOpen(false)}>\n Annuler\n </Button>\n </div>\n </ModalFooter>\n </ModalContent>\n </Modal>\n </div>\n );\n}\n","import { useControl, useField, type FieldName } from \"@conform-to/react/future\";\nimport { Field, type FieldProps } from \"../field/Field\";\nimport { isMediaImage, MediaPreview } from \"../../media-preview\";\nimport { Button } from \"../../button/Button\";\n\nimport { UploaderMock } from \"./UploaderMock\";\nimport { Media } from \"./types\";\n\ntype Props = Omit<FieldProps, \"children\" | \"group\"> & {\n name: FieldName<Media | null | undefined>;\n mediaContainerClassName?: string;\n allowedTypes?: \"image\" | \"audio\" | \"all-safe\";\n imageRatio?: number;\n};\n\nexport function FileField({\n name,\n mediaContainerClassName,\n allowedTypes = \"all-safe\",\n imageRatio,\n id: forcedId,\n ...rest\n}: Props) {\n const field = useField(name);\n const id = forcedId ?? field.id;\n\n const itemErrors = Object.values(field.fieldErrors).flat();\n const errors = field.errors ?? (itemErrors.length > 0 ? itemErrors : undefined);\n\n const control = useControl<Media, string>({\n defaultValue: field.defaultValue,\n parse(payload) {\n if (typeof payload !== \"string\") {\n throw new Error(\"media input must return string\");\n }\n if (payload == null || payload === \"\") {\n return undefined;\n }\n return JSON.parse(payload);\n },\n // appelé uniquement par control.change(value) (ex: onPick, le bouton de suppression) :\n // convertit le Media/null en string écrite dans l'input caché et déclenche l'event\n // \"input\" natif. N'est pas utilisé pour le defaultValue initial (déjà une string).\n serialize(value) {\n return typeof value !== \"string\" && value != null ? JSON.stringify(value) : value;\n },\n });\n\n const media = control.payload;\n\n return (\n <>\n <input\n name={field.name}\n type=\"text\"\n autoComplete=\"off\"\n tabIndex={-1}\n ref={control.register}\n defaultValue={control.defaultValue ?? \"\"}\n />\n <Field id={id} errors={errors} data-testid={field.name} {...rest}>\n {media ? (\n <MediaPreview\n media={media}\n fit={isMediaImage(media) ? \"original\" : \"cover\"}\n className={mediaContainerClassName}\n >\n <Button\n onClick={() => {\n control.change(null);\n }}\n type=\"button\"\n icon\n color=\"gray\"\n size=\"large\"\n >\n <i className=\"fe-trash text-body-xl\"></i>\n </Button>\n </MediaPreview>\n ) : (\n <UploaderMock\n id={id}\n className={mediaContainerClassName}\n onPick={(media: Media | null) => {\n console.log(\"onPick\", media);\n control.change(media);\n }}\n imageRatio={imageRatio}\n allowedTypes={allowedTypes}\n />\n )}\n </Field>\n </>\n );\n}\n","import { z } from \"zod/v4-mini\";\n\nexport const mediaSchema = z.object({\n id: z.string(),\n category: z.string(),\n mimeType: z.string(),\n width: z.optional(z.coerce.number().check(z.int())),\n height: z.optional(z.coerce.number().check(z.int())),\n origin: z.enum([\"s3Upload\", \"localUpload\", \"external\", \"asset\"]),\n src: z.string(),\n // in bytes\n size: z._default(z.nullable(z.coerce.number().check(z.int())), null),\n});\n\nexport type Media = z.infer<typeof mediaSchema>;\n\nexport type MediaImage = Omit<Media, \"width\" | \"height\"> & {\n width: number;\n height: number;\n};\n\nexport function parseMediaValue(payload: unknown): Media | undefined {\n if (payload == null || payload === \"\") {\n return undefined;\n }\n if (typeof payload !== \"string\") {\n throw new Error(\"media value must be a JSON string\");\n }\n try {\n return JSON.parse(payload);\n } catch {\n // JSON corrompu (ex. donnée persistée avant une migration de schéma) : on dégrade\n // gracieusement vers \"absent\" plutôt que de faire planter le rendu du champ.\n return undefined;\n }\n}\n\nexport function serializeMediaValue(value: unknown): string | null {\n return value == null ? null : typeof value === \"string\" ? value : JSON.stringify(value);\n}\n"],"mappings":"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"}
@@ -28,6 +28,7 @@ declare const wysiwygSchema: z.ZodMiniObject<{
28
28
  }, z.core.$strip>;
29
29
  declare function parseWysiwygValue(payload: unknown): WysiwygValue | null;
30
30
  declare function serializeWysiwygValue(value: unknown): string | null;
31
+ declare function isWysiwygStateEmpty(value: WysiwygValue): boolean;
31
32
  //#endregion
32
33
  //#region src/components/fields/wysiwyg/Wysiwyg.d.ts
33
34
  interface Props$2 {
@@ -95,8 +96,19 @@ declare function stateToHtml(state: SerializedEditorState): string;
95
96
  //#region src/components/fields/wysiwyg/config/state.d.ts
96
97
  declare function isStateEmpty(state: SerializedEditorState): boolean;
97
98
  //#endregion
99
+ //#region src/components/fields/wysiwyg/config/validation.d.ts
100
+ declare function isPlausibleLexicalState(state: unknown): state is SerializedEditorState;
101
+ declare function isValidLexicalState(state: unknown): state is SerializedEditorState;
102
+ //#endregion
98
103
  //#region src/components/fields/wysiwyg/plugins/SubmitOnEnterPlugin.d.ts
99
- declare function SubmitOnEnterPlugin(): null;
104
+ interface SubmitOnEnterPluginProps {
105
+ /**
106
+ * When true, Shift+Enter or Ctrl+Enter submits the form and Enter inserts
107
+ * a newline (inverse of the default Enter-to-submit behavior).
108
+ */
109
+ submitOnShiftOrCtrlEnter?: boolean;
110
+ }
111
+ declare function SubmitOnEnterPlugin({ submitOnShiftOrCtrlEnter }: SubmitOnEnterPluginProps): null;
100
112
  //#endregion
101
- export { SubmitOnEnterPlugin, Wysiwyg, WysiwygField, WysiwygReader, type WysiwygRef, type WysiwygValue, chatContentEditableStyle, contentEditableStyles, defaultContentEditableStyle, isStateEmpty, parseWysiwygValue, serializeWysiwygValue, stateToHtml, toolbarVariants, wysiwygSchema };
113
+ export { SubmitOnEnterPlugin, Wysiwyg, WysiwygField, WysiwygReader, type WysiwygRef, type WysiwygValue, chatContentEditableStyle, contentEditableStyles, defaultContentEditableStyle, isPlausibleLexicalState, isStateEmpty, isValidLexicalState, isWysiwygStateEmpty, parseWysiwygValue, serializeWysiwygValue, stateToHtml, toolbarVariants, wysiwygSchema };
102
114
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/components/fields/wysiwyg/style.ts","../../../../src/components/fields/wysiwyg/types.ts","../../../../src/components/fields/wysiwyg/Wysiwyg.tsx","../../../../src/components/fields/wysiwyg/WysiwygField.tsx","../../../../src/components/fields/wysiwyg/WysiwygReader.tsx","../../../../src/components/fields/wysiwyg/config/html.ts","../../../../src/components/fields/wysiwyg/config/state.ts","../../../../src/components/fields/wysiwyg/plugins/SubmitOnEnterPlugin.tsx"],"mappings":";;;;;;;cAGa,kBAAe;;;6CAiB1B;KACU,sBAAsB,oBAAoB;cAEzC;cAGA;cAGA;EACX;EACA;;;;KC5BU;EACV;EACA,OAAO;;cAGI,eAAa,EAAA;;;GAGxB,EAAA,KAAA;iBAIc,kBAAkB,mBAAgB;iBA+BlC,sBAAsB;;;UCnB5B;EACR;EACA;EACA;EACA,eAAe;EACf;EACA;EAEA;EAEA;;;;EAIA;EACA;;;;;EAKA,gBAAgB;EAChB,iBAAiB;EAEjB,MAAM,UAAU;EAChB;EACA,YAAY,OAAO;EACnB,WAAW;;UAQI;EACf,gBAAgB;EAChB,UAAU,cAAc;EACxB,gBAAgB;EAChB,WAAW,OAAO,uBAAuB;EACzC,QAAQ;;iBAGM,UACd,IACA,kBACA,iBACA,cACA,cACA,UACA,UACA,0BACA,0BACA,oBACA,KACA,eACA,gBACA,gBACA,UACA,YACC,0BAAK,IAAA;;;UC9EE,gBAAc,KAAK;EAC3B,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB;EACA,gBAAgB;EAChB;EACA;EACA;EACA;;iBAGc,eACd,MACA,KACA,gBACA,eACA,0BACA,oBACA,UACA,UACA,IAAI,aACD,QACF,0BAAK,IAAA;;;UCxBE;EACR,OAAO;EACP;EACA;;iBAGc,gBAAgB,OAAO,cAAsB,aAAa,wBAAK,IAAA;;;;;;;iBCyB/D,YAAY,OAAO;;;iBCnCnB,aAAa,OAAO;;;iBCSpB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/components/fields/wysiwyg/style.ts","../../../../src/components/fields/wysiwyg/types.ts","../../../../src/components/fields/wysiwyg/Wysiwyg.tsx","../../../../src/components/fields/wysiwyg/WysiwygField.tsx","../../../../src/components/fields/wysiwyg/WysiwygReader.tsx","../../../../src/components/fields/wysiwyg/config/html.ts","../../../../src/components/fields/wysiwyg/config/state.ts","../../../../src/components/fields/wysiwyg/config/validation.ts","../../../../src/components/fields/wysiwyg/plugins/SubmitOnEnterPlugin.tsx"],"mappings":";;;;;;;cAGa,kBAAe;;;6CAiB1B;KACU,sBAAsB,oBAAoB;cAEzC;cAGA;cAGA;EACX;EACA;;;;KC3BU;EACV;EACA,OAAO;;cAKI,eAAa,EAAA;;;GAKxB,EAAA,KAAA;iBAIc,kBAAkB,mBAAgB;iBA+BlC,sBAAsB;iBAYtB,oBAAoB,OAAO;;;UCpCjC;EACR;EACA;EACA;EACA,eAAe;EACf;EACA;EAEA;EAEA;;;;EAIA;EACA;;;;;EAKA,gBAAgB;EAChB,iBAAiB;EAEjB,MAAM,UAAU;EAChB;EACA,YAAY,OAAO;EACnB,WAAW;;UAQI;EACf,gBAAgB;EAChB,UAAU,cAAc;EACxB,gBAAgB;EAChB,WAAW,OAAO,uBAAuB;EACzC,QAAQ;;iBAGM,UACd,IACA,kBACA,iBACA,cACA,cACA,UACA,UACA,0BACA,0BACA,oBACA,KACA,eACA,gBACA,gBACA,UACA,YACC,0BAAK,IAAA;;;UC9EE,gBAAc,KAAK;EAC3B,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB;EACA,gBAAgB;EAChB;EACA;EACA;EACA;;iBAGc,eACd,MACA,KACA,gBACA,eACA,0BACA,oBACA,UACA,UACA,IAAI,aACD,QACF,0BAAK,IAAA;;;UCxBE;EACR,OAAO;EACP;EACA;;iBAGc,gBAAgB,OAAO,cAAsB,aAAa,wBAAK,IAAA;;;;;;;iBCyB/D,YAAY,OAAO;;;iBCnCnB,aAAa,OAAO;;;iBCCpB,wBAAwB,iBAAiB,SAAS;iBAelD,oBAAoB,iBAAiB,SAAS;;;UCPpD;;;;;EAKR;;iBAGc,sBACd,4BACC"}
@@ -744,7 +744,7 @@ function ToolbarPlugin(t0) {
744
744
  const selection = $getSelection();
745
745
  if ($isRangeSelection(selection)) {
746
746
  const anchorNode = selection.anchor.getNode();
747
- let element = anchorNode.getKey() === "root" ? anchorNode : $findMatchingParent(anchorNode, _temp$3);
747
+ let element = anchorNode.getKey() === "root" ? anchorNode : $findMatchingParent(anchorNode, _temp$2);
748
748
  if (element === null) element = anchorNode.getTopLevelElementOrThrow();
749
749
  const elementKey = element.getKey();
750
750
  const elementDOM = editor.getElementByKey(elementKey);
@@ -1125,7 +1125,7 @@ function _temp3(f) {
1125
1125
  function _temp2$2(parentNode) {
1126
1126
  return $isElementNode(parentNode) && !parentNode.isInline();
1127
1127
  }
1128
- function _temp$3(e) {
1128
+ function _temp$2(e) {
1129
1129
  const parent = e.getParent();
1130
1130
  return parent !== null && $isRootOrShadowRoot(parent);
1131
1131
  }
@@ -1572,7 +1572,7 @@ function FloatingLinkEditorPlugin(t0) {
1572
1572
  setIsLink(false);
1573
1573
  return;
1574
1574
  }
1575
- if (!selection.getNodes().filter(_temp$2).find((node_0) => {
1575
+ if (!selection.getNodes().filter(_temp$1).find((node_0) => {
1576
1576
  const linkNode = $findMatchingParent(node_0, $isLinkNode);
1577
1577
  const autoLinkNode = $findMatchingParent(node_0, $isAutoLinkNode);
1578
1578
  return focusLinkNode && !focusLinkNode.is(linkNode) || linkNode && !linkNode.is(focusLinkNode) || focusAutoLinkNode && !focusAutoLinkNode.is(autoLinkNode) || autoLinkNode && (!autoLinkNode.is(focusAutoLinkNode) || autoLinkNode.getIsUnlinked());
@@ -1647,7 +1647,7 @@ function _temp2$1(payload) {
1647
1647
  }
1648
1648
  return false;
1649
1649
  }
1650
- function _temp$2(node) {
1650
+ function _temp$1(node) {
1651
1651
  return !$isLineBreakNode(node);
1652
1652
  }
1653
1653
  //#endregion
@@ -1762,7 +1762,7 @@ const constructImportMap = () => {
1762
1762
  return importMap;
1763
1763
  };
1764
1764
  //#endregion
1765
- //#region src/components/fields/wysiwyg/config/index.ts
1765
+ //#region src/components/fields/wysiwyg/config/editor.ts
1766
1766
  const editorConfig = {
1767
1767
  html: {
1768
1768
  export: exportMap,
@@ -2069,16 +2069,37 @@ function Wysiwyg(t0) {
2069
2069
  return t30;
2070
2070
  }
2071
2071
  function _temp2() {
2072
- $getRoot().getChildren().forEach(_temp$1);
2072
+ $getRoot().getChildren().forEach(_temp);
2073
2073
  }
2074
- function _temp$1(node) {
2074
+ function _temp(node) {
2075
2075
  node.remove();
2076
2076
  }
2077
2077
  //#endregion
2078
+ //#region src/components/fields/wysiwyg/config/validation.ts
2079
+ function isPlausibleLexicalState(state) {
2080
+ if (typeof state !== "object" || state === null) return false;
2081
+ const root = state.root;
2082
+ return typeof root === "object" && root !== null && root.type === "root" && Array.isArray(root.children);
2083
+ }
2084
+ function isValidLexicalState(state) {
2085
+ try {
2086
+ createEditor({
2087
+ ...editorConfig,
2088
+ onError(err) {
2089
+ throw err;
2090
+ }
2091
+ }).parseEditorState(state);
2092
+ return true;
2093
+ } catch {
2094
+ return false;
2095
+ }
2096
+ }
2097
+ //#endregion
2078
2098
  //#region src/components/fields/wysiwyg/types.ts
2099
+ const maxContentBytes = 1e5;
2079
2100
  const wysiwygSchema = z.object({
2080
2101
  html: z.optional(z.string()),
2081
- state: z.custom()
2102
+ state: z.custom(isPlausibleLexicalState).check(z.refine((state) => JSON.stringify(state).length <= maxContentBytes))
2082
2103
  });
2083
2104
  function parseWysiwygValue(payload) {
2084
2105
  if (payload == null || payload === "") return null;
@@ -2103,6 +2124,9 @@ function serializeWysiwygValue(value) {
2103
2124
  return null;
2104
2125
  }
2105
2126
  }
2127
+ function isWysiwygStateEmpty(value) {
2128
+ return value.state.root.children.length === 0;
2129
+ }
2106
2130
  //#endregion
2107
2131
  //#region src/components/fields/wysiwyg/WysiwygField.tsx
2108
2132
  function WysiwygField({ name, ref, debounceChange = false, toolbarSticky, contentEditableClassName, containerClassName, disabled = false, readOnly = false, id: forcedId, ...rest }) {
@@ -2198,35 +2222,37 @@ function isStateEmpty(state) {
2198
2222
  }
2199
2223
  //#endregion
2200
2224
  //#region src/components/fields/wysiwyg/plugins/SubmitOnEnterPlugin.tsx
2201
- function SubmitOnEnterPlugin() {
2202
- const $ = c(3);
2225
+ function SubmitOnEnterPlugin(t0) {
2226
+ const $ = c(4);
2227
+ const { submitOnShiftOrCtrlEnter: t1 } = t0;
2228
+ const submitOnShiftOrCtrlEnter = t1 === void 0 ? false : t1;
2203
2229
  const [editor] = useLexicalComposerContext();
2204
- let t0;
2205
- let t1;
2206
- if ($[0] !== editor) {
2207
- t0 = () => editor.registerCommand(KEY_ENTER_COMMAND, _temp, COMMAND_PRIORITY_CRITICAL);
2208
- t1 = [editor];
2230
+ let t2;
2231
+ let t3;
2232
+ if ($[0] !== editor || $[1] !== submitOnShiftOrCtrlEnter) {
2233
+ t2 = () => editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
2234
+ if (!$isRangeSelection($getSelection())) return false;
2235
+ if (event !== null) {
2236
+ if ((IS_IOS || IS_SAFARI || IS_APPLE_WEBKIT) && CAN_USE_BEFORE_INPUT) return false;
2237
+ event.preventDefault();
2238
+ if (submitOnShiftOrCtrlEnter ? !(event.shiftKey || event.ctrlKey) : event.shiftKey) return false;
2239
+ }
2240
+ (document.activeElement?.closest("form"))?.requestSubmit();
2241
+ return true;
2242
+ }, COMMAND_PRIORITY_CRITICAL);
2243
+ t3 = [editor, submitOnShiftOrCtrlEnter];
2209
2244
  $[0] = editor;
2210
- $[1] = t0;
2211
- $[2] = t1;
2245
+ $[1] = submitOnShiftOrCtrlEnter;
2246
+ $[2] = t2;
2247
+ $[3] = t3;
2212
2248
  } else {
2213
- t0 = $[1];
2214
- t1 = $[2];
2249
+ t2 = $[2];
2250
+ t3 = $[3];
2215
2251
  }
2216
- useEffect(t0, t1);
2252
+ useEffect(t2, t3);
2217
2253
  return null;
2218
2254
  }
2219
- function _temp(event) {
2220
- if (!$isRangeSelection($getSelection())) return false;
2221
- if (event !== null) {
2222
- if ((IS_IOS || IS_SAFARI || IS_APPLE_WEBKIT) && CAN_USE_BEFORE_INPUT) return false;
2223
- event.preventDefault();
2224
- if (event.shiftKey) return false;
2225
- }
2226
- (document.activeElement?.closest("form"))?.requestSubmit();
2227
- return true;
2228
- }
2229
2255
  //#endregion
2230
- export { SubmitOnEnterPlugin, Wysiwyg, WysiwygField, WysiwygReader, chatContentEditableStyle, contentEditableStyles, defaultContentEditableStyle, isStateEmpty, parseWysiwygValue, serializeWysiwygValue, stateToHtml, toolbarVariants, wysiwygSchema };
2256
+ export { SubmitOnEnterPlugin, Wysiwyg, WysiwygField, WysiwygReader, chatContentEditableStyle, contentEditableStyles, defaultContentEditableStyle, isPlausibleLexicalState, isStateEmpty, isValidLexicalState, isWysiwygStateEmpty, parseWysiwygValue, serializeWysiwygValue, stateToHtml, toolbarVariants, wysiwygSchema };
2231
2257
 
2232
2258
  //# sourceMappingURL=index.mjs.map