payload-intl 0.2.4 → 0.3.0
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/README.md +3 -4
- package/dist/components/MessageController.js +25 -47
- package/dist/components/MessageController.js.map +1 -1
- package/dist/components/layout/MessageField.js +6 -6
- package/dist/components/layout/MessageField.js.map +1 -1
- package/dist/utils/schema.d.ts +1 -1
- package/dist/utils/schema.js +10 -9
- package/dist/utils/schema.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/inputs/LexicalInput.js +0 -80
- package/dist/components/inputs/LexicalInput.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- Autocomplete to quickly insert and configure valid ICU arguments
|
|
14
14
|
- Add optional descriptions to each message so editors understand the context
|
|
15
15
|
- Visual tree & tabbed editor for quick navigation
|
|
16
|
-
- Support for Rich Text messages
|
|
16
|
+
<!-- - Support for Rich Text messages -->
|
|
17
17
|
<!-- - Import/export JSON, copy messages between paths -->
|
|
18
18
|
|
|
19
19
|
## Getting Started
|
|
@@ -107,7 +107,6 @@ The `intlPlugin` accepts the following configuration:
|
|
|
107
107
|
| `editorAccess` | Authenticated users only | Access control for editing messages |
|
|
108
108
|
| `hooks` | - | Collection hooks with and additional `afterUpdate` hook |
|
|
109
109
|
| `tabs` | - | Enable tabbed interface |
|
|
110
|
-
| `richTextEditorOptions` | - | Configure rich text editor options |
|
|
111
110
|
|
|
112
111
|
## Storage Adapter Requirements
|
|
113
112
|
|
|
@@ -131,7 +130,7 @@ export default {
|
|
|
131
130
|
} as const;
|
|
132
131
|
```
|
|
133
132
|
|
|
134
|
-
### Rich Text Messages
|
|
133
|
+
<!-- ### Rich Text Messages
|
|
135
134
|
|
|
136
135
|
Use `"$RICH$"` as the message value to enable rich text editing. Note that rich text messages do not support ICU arguments.
|
|
137
136
|
|
|
@@ -142,7 +141,7 @@ export default {
|
|
|
142
141
|
terms: "$RICH$", // Rich text editor will be used
|
|
143
142
|
},
|
|
144
143
|
} as const;
|
|
145
|
-
```
|
|
144
|
+
``` -->
|
|
146
145
|
|
|
147
146
|
## Example Usage
|
|
148
147
|
|
|
@@ -1,65 +1,43 @@
|
|
|
1
1
|
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
-
import { Controller as
|
|
3
|
-
import { useMessagesForm as
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
className: s
|
|
2
|
+
import { Controller as p } from "react-hook-form";
|
|
3
|
+
import { useMessagesForm as g } from "../context/messages-form.js";
|
|
4
|
+
import { MessageInput as i } from "./inputs/MessageInput.js";
|
|
5
|
+
function v({
|
|
6
|
+
type: C,
|
|
7
|
+
name: e,
|
|
8
|
+
variables: n,
|
|
9
|
+
label: t,
|
|
10
|
+
locale: s,
|
|
11
|
+
validate: u,
|
|
12
|
+
className: l
|
|
14
13
|
}) {
|
|
15
|
-
const { control:
|
|
16
|
-
return
|
|
17
|
-
|
|
14
|
+
const { control: m } = g();
|
|
15
|
+
return /* @__PURE__ */ o(
|
|
16
|
+
p,
|
|
18
17
|
{
|
|
19
|
-
control:
|
|
20
|
-
name:
|
|
21
|
-
render: ({ field: r, fieldState:
|
|
22
|
-
|
|
18
|
+
control: m,
|
|
19
|
+
name: e,
|
|
20
|
+
render: ({ field: r, fieldState: a }) => /* @__PURE__ */ o(
|
|
21
|
+
i,
|
|
23
22
|
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
lang: t,
|
|
28
|
-
onChange: r.onChange,
|
|
29
|
-
onBlur: r.onBlur,
|
|
30
|
-
value: r.value || ""
|
|
31
|
-
}
|
|
32
|
-
),
|
|
33
|
-
rules: {
|
|
34
|
-
required: !0
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
) : /* @__PURE__ */ o(
|
|
38
|
-
g,
|
|
39
|
-
{
|
|
40
|
-
control: a,
|
|
41
|
-
name: n,
|
|
42
|
-
render: ({ field: r, fieldState: e }) => /* @__PURE__ */ o(
|
|
43
|
-
h,
|
|
44
|
-
{
|
|
45
|
-
label: u,
|
|
46
|
-
lang: t,
|
|
47
|
-
className: s,
|
|
23
|
+
label: t,
|
|
24
|
+
lang: s,
|
|
25
|
+
className: l,
|
|
48
26
|
value: r.value || "",
|
|
49
|
-
variables:
|
|
50
|
-
error:
|
|
27
|
+
variables: n,
|
|
28
|
+
error: a.error,
|
|
51
29
|
onChange: r.onChange,
|
|
52
30
|
onBlur: r.onBlur
|
|
53
31
|
}
|
|
54
32
|
),
|
|
55
33
|
rules: {
|
|
56
34
|
required: !0,
|
|
57
|
-
validate:
|
|
35
|
+
validate: u
|
|
58
36
|
}
|
|
59
37
|
}
|
|
60
38
|
);
|
|
61
39
|
}
|
|
62
40
|
export {
|
|
63
|
-
|
|
41
|
+
v as MessageController
|
|
64
42
|
};
|
|
65
43
|
//# sourceMappingURL=MessageController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageController.js","sources":["../../src/components/MessageController.tsx"],"sourcesContent":["import type { TemplateVariable } from \"@/types\";\nimport type { MessageType } from \"@/utils/schema\";\nimport type { MessageValidator } from \"@/utils/validate\";\nimport { Controller } from \"react-hook-form\";\n\nimport { useMessagesForm } from \"@/context/messages-form\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"MessageController.js","sources":["../../src/components/MessageController.tsx"],"sourcesContent":["import type { TemplateVariable } from \"@/types\";\nimport type { MessageType } from \"@/utils/schema\";\nimport type { MessageValidator } from \"@/utils/validate\";\nimport { Controller } from \"react-hook-form\";\n\nimport { useMessagesForm } from \"@/context/messages-form\";\n\nimport { MessageInput } from \"./inputs/MessageInput\";\n\ninterface MessageControllerProps {\n type: MessageType;\n label?: string;\n locale: string;\n name: string;\n className?: string;\n variables: TemplateVariable[];\n validate: MessageValidator;\n}\n\nexport function MessageController({\n type,\n name,\n variables,\n label,\n locale,\n validate,\n className,\n}: MessageControllerProps): React.ReactNode {\n const { control } = useMessagesForm();\n\n // if (type === \"rich\") {\n // return (\n // <Controller\n // control={control}\n // name={name}\n // render={({ field, fieldState }) => (\n // <LexicalInput\n // className={className}\n // error={fieldState.error}\n // label={label}\n // lang={locale}\n // onChange={field.onChange}\n // onBlur={field.onBlur}\n // value={(field.value as unknown as string) || \"\"}\n // />\n // )}\n // rules={{\n // required: true,\n // }}\n // />\n // );\n // }\n\n return (\n <Controller\n control={control}\n name={name}\n render={({ field, fieldState }) => (\n <MessageInput\n label={label}\n lang={locale}\n className={className}\n value={(field.value as unknown as string) || \"\"}\n variables={variables}\n error={fieldState.error}\n onChange={field.onChange}\n onBlur={field.onBlur}\n />\n )}\n rules={{\n required: true,\n validate,\n }}\n />\n );\n}\n"],"names":["MessageController","type","name","variables","label","locale","validate","className","control","useMessagesForm","jsx","Controller","field","fieldState","MessageInput"],"mappings":";;;;AAmBO,SAASA,EAAkB;AAAA,EAChC,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AACF,GAA4C;AAC1C,QAAM,EAAE,SAAAC,EAAA,IAAYC,EAAA;AAyBpB,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAAH;AAAA,MACA,MAAAN;AAAA,MACA,QAAQ,CAAC,EAAE,OAAAU,GAAO,YAAAC,QAChB,gBAAAH;AAAA,QAACI;AAAA,QAAA;AAAA,UACC,OAAAV;AAAA,UACA,MAAMC;AAAA,UACN,WAAAE;AAAA,UACA,OAAQK,EAAM,SAA+B;AAAA,UAC7C,WAAAT;AAAA,UACA,OAAOU,EAAW;AAAA,UAClB,UAAUD,EAAM;AAAA,UAChB,QAAQA,EAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAGlB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAAN;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsxs as
|
|
1
|
+
import { jsxs as d, jsx as i } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo as p } from "react";
|
|
3
|
-
import { useMessagesForm as
|
|
3
|
+
import { useMessagesForm as f } from "../../context/messages-form.js";
|
|
4
4
|
import { cn as n } from "../../utils/cn.js";
|
|
5
5
|
import { parseMessageSchema as v } from "../../utils/schema.js";
|
|
6
6
|
import { createValidator as x } from "../../utils/validate.js";
|
|
@@ -11,11 +11,11 @@ function w({
|
|
|
11
11
|
path: t,
|
|
12
12
|
className: l
|
|
13
13
|
}) {
|
|
14
|
-
const { locales: r } =
|
|
14
|
+
const { locales: r } = f(), e = p(() => v(o), [o]), m = p(
|
|
15
15
|
() => x(e.variables),
|
|
16
16
|
[e.variables]
|
|
17
17
|
);
|
|
18
|
-
return /* @__PURE__ */
|
|
18
|
+
return /* @__PURE__ */ d("div", { className: n("", l), children: [
|
|
19
19
|
e.description && /* @__PURE__ */ i("p", { children: e.description }),
|
|
20
20
|
r.length === 1 ? /* @__PURE__ */ i(
|
|
21
21
|
c,
|
|
@@ -31,8 +31,8 @@ function w({
|
|
|
31
31
|
"div",
|
|
32
32
|
{
|
|
33
33
|
className: n("-mx-3 flex min-w-0 gap-4 px-3", {
|
|
34
|
-
"overflow-x-auto": e.type === "icu"
|
|
35
|
-
"flex-col":
|
|
34
|
+
"overflow-x-auto": e.type === "icu"
|
|
35
|
+
// "flex-col": config.type === "rich",
|
|
36
36
|
}),
|
|
37
37
|
children: r.map((a) => /* @__PURE__ */ i(
|
|
38
38
|
c,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageField.js","sources":["../../../src/components/layout/MessageField.tsx"],"sourcesContent":["import type { MessageSchema } from \"@/types\";\nimport { useMemo } from \"react\";\n\nimport { useMessagesForm } from \"@/context/messages-form\";\nimport { cn } from \"@/utils/cn\";\nimport { parseMessageSchema } from \"@/utils/schema\";\nimport { createValidator } from \"@/utils/validate\";\n\nimport { MessageController } from \"../MessageController\";\n\ninterface MessageFieldProps {\n schema: MessageSchema;\n messageKey: string;\n path: string;\n className?: string;\n}\n\nexport function MessageField({\n schema,\n messageKey,\n path,\n className,\n}: MessageFieldProps): React.ReactNode {\n const { locales } = useMessagesForm();\n\n const config = useMemo(() => parseMessageSchema(schema), [schema]);\n\n const validator = useMemo(\n () => createValidator(config.variables),\n [config.variables],\n );\n\n return (\n <div className={cn(\"\", className)}>\n {config.description && <p>{config.description}</p>}\n\n {locales.length === 1 ? (\n <MessageController\n className={className}\n type={config.type}\n variables={config.variables}\n locale={locales[0]}\n name={[locales[0], path, messageKey].join(\".\")}\n validate={validator}\n />\n ) : (\n <div\n className={cn(\"-mx-3 flex min-w-0 gap-4 px-3\", {\n \"overflow-x-auto\": config.type === \"icu\",\n \"flex-col\": config.type === \"rich\",\n })}\n >\n {locales.map((locale) => (\n <MessageController\n key={locale}\n className=\"flex-1\"\n type={config.type}\n label={locale.toUpperCase()}\n locale={locale}\n variables={config.variables}\n name={[locale, path, messageKey].join(\".\")}\n validate={validator}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["MessageField","schema","messageKey","path","className","locales","useMessagesForm","config","useMemo","parseMessageSchema","validator","createValidator","cn","jsx","MessageController","locale"],"mappings":";;;;;;;AAiBO,SAASA,EAAa;AAAA,EAC3B,QAAAC;AAAA,EACA,YAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC;AACF,GAAuC;AACrC,QAAM,EAAE,SAAAC,EAAA,IAAYC,EAAA,GAEdC,IAASC,EAAQ,MAAMC,EAAmBR,CAAM,GAAG,CAACA,CAAM,CAAC,GAE3DS,IAAYF;AAAA,IAChB,MAAMG,EAAgBJ,EAAO,SAAS;AAAA,IACtC,CAACA,EAAO,SAAS;AAAA,EAAA;AAGnB,2BACG,OAAA,EAAI,WAAWK,EAAG,IAAIR,CAAS,GAC7B,UAAA;AAAA,IAAAG,EAAO,eAAe,gBAAAM,EAAC,KAAA,EAAG,UAAAN,EAAO,aAAY;AAAA,IAE7CF,EAAQ,WAAW,IAClB,gBAAAQ;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,WAAAV;AAAA,QACA,MAAMG,EAAO;AAAA,QACb,WAAWA,EAAO;AAAA,QAClB,QAAQF,EAAQ,CAAC;AAAA,QACjB,MAAM,CAACA,EAAQ,CAAC,GAAGF,GAAMD,CAAU,EAAE,KAAK,GAAG;AAAA,QAC7C,UAAUQ;AAAA,MAAA;AAAA,IAAA,IAGZ,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWD,EAAG,iCAAiC;AAAA,UAC7C,mBAAmBL,EAAO,SAAS;AAAA
|
|
1
|
+
{"version":3,"file":"MessageField.js","sources":["../../../src/components/layout/MessageField.tsx"],"sourcesContent":["import type { MessageSchema } from \"@/types\";\nimport { useMemo } from \"react\";\n\nimport { useMessagesForm } from \"@/context/messages-form\";\nimport { cn } from \"@/utils/cn\";\nimport { parseMessageSchema } from \"@/utils/schema\";\nimport { createValidator } from \"@/utils/validate\";\n\nimport { MessageController } from \"../MessageController\";\n\ninterface MessageFieldProps {\n schema: MessageSchema;\n messageKey: string;\n path: string;\n className?: string;\n}\n\nexport function MessageField({\n schema,\n messageKey,\n path,\n className,\n}: MessageFieldProps): React.ReactNode {\n const { locales } = useMessagesForm();\n\n const config = useMemo(() => parseMessageSchema(schema), [schema]);\n\n const validator = useMemo(\n () => createValidator(config.variables),\n [config.variables],\n );\n\n return (\n <div className={cn(\"\", className)}>\n {config.description && <p>{config.description}</p>}\n\n {locales.length === 1 ? (\n <MessageController\n className={className}\n type={config.type}\n variables={config.variables}\n locale={locales[0]}\n name={[locales[0], path, messageKey].join(\".\")}\n validate={validator}\n />\n ) : (\n <div\n className={cn(\"-mx-3 flex min-w-0 gap-4 px-3\", {\n \"overflow-x-auto\": config.type === \"icu\",\n // \"flex-col\": config.type === \"rich\",\n })}\n >\n {locales.map((locale) => (\n <MessageController\n key={locale}\n className=\"flex-1\"\n type={config.type}\n label={locale.toUpperCase()}\n locale={locale}\n variables={config.variables}\n name={[locale, path, messageKey].join(\".\")}\n validate={validator}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"names":["MessageField","schema","messageKey","path","className","locales","useMessagesForm","config","useMemo","parseMessageSchema","validator","createValidator","cn","jsx","MessageController","locale"],"mappings":";;;;;;;AAiBO,SAASA,EAAa;AAAA,EAC3B,QAAAC;AAAA,EACA,YAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC;AACF,GAAuC;AACrC,QAAM,EAAE,SAAAC,EAAA,IAAYC,EAAA,GAEdC,IAASC,EAAQ,MAAMC,EAAmBR,CAAM,GAAG,CAACA,CAAM,CAAC,GAE3DS,IAAYF;AAAA,IAChB,MAAMG,EAAgBJ,EAAO,SAAS;AAAA,IACtC,CAACA,EAAO,SAAS;AAAA,EAAA;AAGnB,2BACG,OAAA,EAAI,WAAWK,EAAG,IAAIR,CAAS,GAC7B,UAAA;AAAA,IAAAG,EAAO,eAAe,gBAAAM,EAAC,KAAA,EAAG,UAAAN,EAAO,aAAY;AAAA,IAE7CF,EAAQ,WAAW,IAClB,gBAAAQ;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,WAAAV;AAAA,QACA,MAAMG,EAAO;AAAA,QACb,WAAWA,EAAO;AAAA,QAClB,QAAQF,EAAQ,CAAC;AAAA,QACjB,MAAM,CAACA,EAAQ,CAAC,GAAGF,GAAMD,CAAU,EAAE,KAAK,GAAG;AAAA,QAC7C,UAAUQ;AAAA,MAAA;AAAA,IAAA,IAGZ,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWD,EAAG,iCAAiC;AAAA,UAC7C,mBAAmBL,EAAO,SAAS;AAAA;AAAA,QAAA,CAEpC;AAAA,QAEA,UAAAF,EAAQ,IAAI,CAACU,MACZ,gBAAAF;AAAA,UAACC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YACV,MAAMP,EAAO;AAAA,YACb,OAAOQ,EAAO,YAAA;AAAA,YACd,QAAAA;AAAA,YACA,WAAWR,EAAO;AAAA,YAClB,MAAM,CAACQ,GAAQZ,GAAMD,CAAU,EAAE,KAAK,GAAG;AAAA,YACzC,UAAUQ;AAAA,UAAA;AAAA,UAPLK;AAAA,QAAA,CASR;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GAEJ;AAEJ;"}
|
package/dist/utils/schema.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MessageSchema, TemplateVariable } from '../types.ts';
|
|
2
2
|
export declare const parseMessageSchema: (schema: MessageSchema) => MessageConfig;
|
|
3
3
|
export declare const extractTemplateVariables: (schema: MessageSchema) => TemplateVariable[];
|
|
4
|
-
export type MessageType = "
|
|
4
|
+
export type MessageType = "icu";
|
|
5
5
|
export type MessageConfig = {
|
|
6
6
|
description: string | undefined;
|
|
7
7
|
type: MessageType;
|
package/dist/utils/schema.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { parse as r, TYPE as e } from "@formatjs/icu-messageformat-parser";
|
|
2
|
-
const
|
|
2
|
+
const i = (a) => ({
|
|
3
3
|
description: a.match(/^\[.+\]/)?.[0]?.slice(1, -1),
|
|
4
|
-
type:
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
// type: schema === "$RICH$" ? "rich" : "icu",
|
|
5
|
+
type: "icu",
|
|
6
|
+
variables: l(a)
|
|
7
|
+
}), l = (a) => s(r(a)), s = (a) => a.flatMap((t) => {
|
|
7
8
|
switch (t.type) {
|
|
8
9
|
case e.literal:
|
|
9
10
|
case e.pound:
|
|
@@ -17,18 +18,18 @@ const n = (a) => ({
|
|
|
17
18
|
case e.select:
|
|
18
19
|
return [
|
|
19
20
|
t,
|
|
20
|
-
...
|
|
21
|
-
Object.values(t.options).flatMap(({ value:
|
|
21
|
+
...s(
|
|
22
|
+
Object.values(t.options).flatMap(({ value: c }) => c)
|
|
22
23
|
)
|
|
23
24
|
];
|
|
24
25
|
case e.tag:
|
|
25
|
-
return [t, ...
|
|
26
|
+
return [t, ...s(t.children)];
|
|
26
27
|
default:
|
|
27
28
|
return [t];
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
export {
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
l as extractTemplateVariables,
|
|
33
|
+
i as parseMessageSchema
|
|
33
34
|
};
|
|
34
35
|
//# sourceMappingURL=schema.js.map
|
package/dist/utils/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sources":["../../src/utils/schema.ts"],"sourcesContent":["import type { MessageSchema, TemplateVariable } from \"@/types\";\nimport type { MessageFormatElement } from \"@formatjs/icu-messageformat-parser\";\nimport { parse, TYPE } from \"@formatjs/icu-messageformat-parser\";\n\nexport const parseMessageSchema = (schema: MessageSchema): MessageConfig => {\n const description = schema.match(/^\\[.+\\]/)?.[0];\n // TODO add support for variables description\n // const withoutDescription = schema.replace(description || \"\", \"\").trim();\n // const withoutOptional = withoutDescription.split(\" | \")[0]?.trim();\n\n return {\n description: description?.slice(1, -1),\n type: schema === \"$RICH$\" ? \"rich\" : \"icu\",\n variables: extractTemplateVariables(schema),\n };\n};\n\nexport const extractTemplateVariables = (\n schema: MessageSchema,\n): TemplateVariable[] => collectTemplateVariables(parse(schema));\n\nconst collectTemplateVariables = (\n parts: MessageFormatElement[],\n): TemplateVariable[] =>\n parts.flatMap<TemplateVariable>((part) => {\n switch (part.type) {\n case TYPE.literal:\n case TYPE.pound:\n return [];\n case TYPE.argument:\n case TYPE.number:\n case TYPE.date:\n case TYPE.time:\n return [part];\n case TYPE.plural:\n case TYPE.select:\n return [\n part,\n ...collectTemplateVariables(\n Object.values(part.options).flatMap(({ value }) => value),\n ),\n ];\n case TYPE.tag:\n return [part, ...collectTemplateVariables(part.children)];\n default:\n return [part];\n }\n });\n\n// MARK: Types\n\nexport type MessageType = \"
|
|
1
|
+
{"version":3,"file":"schema.js","sources":["../../src/utils/schema.ts"],"sourcesContent":["import type { MessageSchema, TemplateVariable } from \"@/types\";\nimport type { MessageFormatElement } from \"@formatjs/icu-messageformat-parser\";\nimport { parse, TYPE } from \"@formatjs/icu-messageformat-parser\";\n\nexport const parseMessageSchema = (schema: MessageSchema): MessageConfig => {\n const description = schema.match(/^\\[.+\\]/)?.[0];\n // TODO add support for variables description\n // const withoutDescription = schema.replace(description || \"\", \"\").trim();\n // const withoutOptional = withoutDescription.split(\" | \")[0]?.trim();\n\n return {\n description: description?.slice(1, -1),\n // type: schema === \"$RICH$\" ? \"rich\" : \"icu\",\n type: \"icu\",\n variables: extractTemplateVariables(schema),\n };\n};\n\nexport const extractTemplateVariables = (\n schema: MessageSchema,\n): TemplateVariable[] => collectTemplateVariables(parse(schema));\n\nconst collectTemplateVariables = (\n parts: MessageFormatElement[],\n): TemplateVariable[] =>\n parts.flatMap<TemplateVariable>((part) => {\n switch (part.type) {\n case TYPE.literal:\n case TYPE.pound:\n return [];\n case TYPE.argument:\n case TYPE.number:\n case TYPE.date:\n case TYPE.time:\n return [part];\n case TYPE.plural:\n case TYPE.select:\n return [\n part,\n ...collectTemplateVariables(\n Object.values(part.options).flatMap(({ value }) => value),\n ),\n ];\n case TYPE.tag:\n return [part, ...collectTemplateVariables(part.children)];\n default:\n return [part];\n }\n });\n\n// MARK: Types\n\nexport type MessageType = \"icu\" // \"rich\";\nexport type MessageConfig = {\n description: string | undefined;\n type: MessageType;\n variables: TemplateVariable[];\n};\n"],"names":["parseMessageSchema","schema","extractTemplateVariables","collectTemplateVariables","parse","parts","part","TYPE","value"],"mappings":";AAIO,MAAMA,IAAqB,CAACC,OAM1B;AAAA,EACL,aANkBA,EAAO,MAAM,SAAS,IAAI,CAAC,GAMnB,MAAM,GAAG,EAAE;AAAA;AAAA,EAErC,MAAM;AAAA,EACN,WAAWC,EAAyBD,CAAM;AAAA,IAIjCC,IAA2B,CACtCD,MACuBE,EAAyBC,EAAMH,CAAM,CAAC,GAEzDE,IAA2B,CAC/BE,MAEAA,EAAM,QAA0B,CAACC,MAAS;AACxC,UAAQA,EAAK,MAAA;AAAA,IACX,KAAKC,EAAK;AAAA,IACV,KAAKA,EAAK;AACR,aAAO,CAAA;AAAA,IACT,KAAKA,EAAK;AAAA,IACV,KAAKA,EAAK;AAAA,IACV,KAAKA,EAAK;AAAA,IACV,KAAKA,EAAK;AACR,aAAO,CAACD,CAAI;AAAA,IACd,KAAKC,EAAK;AAAA,IACV,KAAKA,EAAK;AACR,aAAO;AAAA,QACLD;AAAA,QACA,GAAGH;AAAA,UACD,OAAO,OAAOG,EAAK,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAAE,EAAA,MAAYA,CAAK;AAAA,QAAA;AAAA,MAC1D;AAAA,IAEJ,KAAKD,EAAK;AACR,aAAO,CAACD,GAAM,GAAGH,EAAyBG,EAAK,QAAQ,CAAC;AAAA,IAC1D;AACE,aAAO,CAACA,CAAI;AAAA,EAAA;AAElB,CAAC;"}
|
package/package.json
CHANGED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { jsx as l } from "react/jsx-runtime";
|
|
2
|
-
import { defaultEditorFeatures as p, defaultEditorConfig as f } from "@payloadcms/richtext-lexical";
|
|
3
|
-
import { buildDefaultEditorState as E, RenderLexical as g, getEnabledNodes as S, sanitizeClientEditorConfig as x } from "@payloadcms/richtext-lexical/client";
|
|
4
|
-
import { $getRoot as b } from "@payloadcms/richtext-lexical/lexical";
|
|
5
|
-
import { createHeadlessEditor as h } from "@payloadcms/richtext-lexical/lexical/headless";
|
|
6
|
-
import { $generateNodesFromDOM as C, $generateHtmlFromNodes as T } from "@payloadcms/richtext-lexical/lexical/html";
|
|
7
|
-
import { useRef as F, useCallback as u, useMemo as H } from "react";
|
|
8
|
-
import { InputWrapper as M } from "./InputWrapper.js";
|
|
9
|
-
function y({
|
|
10
|
-
error: r,
|
|
11
|
-
label: o,
|
|
12
|
-
value: i,
|
|
13
|
-
onChange: a,
|
|
14
|
-
className: s
|
|
15
|
-
}) {
|
|
16
|
-
const n = v({
|
|
17
|
-
html: i,
|
|
18
|
-
onChange: a
|
|
19
|
-
});
|
|
20
|
-
return /* @__PURE__ */ l(M, { label: o, error: r, className: s, children: /* @__PURE__ */ l(
|
|
21
|
-
g,
|
|
22
|
-
{
|
|
23
|
-
field: {
|
|
24
|
-
name: "myCustomEditor",
|
|
25
|
-
label: !1,
|
|
26
|
-
type: "richText"
|
|
27
|
-
},
|
|
28
|
-
value: n.value,
|
|
29
|
-
setValue: (e) => n.setValue(e),
|
|
30
|
-
schemaPath: "global.intl-plugin.editorTemplate"
|
|
31
|
-
}
|
|
32
|
-
) });
|
|
33
|
-
}
|
|
34
|
-
const N = E({});
|
|
35
|
-
function v({
|
|
36
|
-
html: r,
|
|
37
|
-
onChange: o
|
|
38
|
-
}) {
|
|
39
|
-
const i = F(
|
|
40
|
-
h({
|
|
41
|
-
nodes: S({
|
|
42
|
-
editorConfig: x(
|
|
43
|
-
// @ts-expect-error - FIXME
|
|
44
|
-
p,
|
|
45
|
-
f
|
|
46
|
-
)
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
), a = u(
|
|
50
|
-
(e) => {
|
|
51
|
-
const t = i.current;
|
|
52
|
-
return t.update(
|
|
53
|
-
() => {
|
|
54
|
-
const c = new DOMParser().parseFromString(e, "text/html"), m = C(t, c);
|
|
55
|
-
b().clear().append(...m);
|
|
56
|
-
},
|
|
57
|
-
{ discrete: !0 }
|
|
58
|
-
), t.getEditorState().toJSON();
|
|
59
|
-
},
|
|
60
|
-
[]
|
|
61
|
-
), s = H(() => {
|
|
62
|
-
const e = a(r);
|
|
63
|
-
return e.root.children.length === 0 ? N : e;
|
|
64
|
-
}, [r, a]), n = u(
|
|
65
|
-
(e) => {
|
|
66
|
-
const t = i.current;
|
|
67
|
-
t.setEditorState(t.parseEditorState(e)), t.read(() => {
|
|
68
|
-
const d = T(t);
|
|
69
|
-
d !== r && o(d);
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
[r, o]
|
|
73
|
-
);
|
|
74
|
-
return { value: s, setValue: n };
|
|
75
|
-
}
|
|
76
|
-
export {
|
|
77
|
-
y as LexicalInput,
|
|
78
|
-
v as useHtmlLexicalAdapter
|
|
79
|
-
};
|
|
80
|
-
//# sourceMappingURL=LexicalInput.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LexicalInput.js","sources":["../../../src/components/inputs/LexicalInput.tsx"],"sourcesContent":["import type {\n DefaultNodeTypes,\n TypedEditorState,\n} from \"@payloadcms/richtext-lexical\";\nimport type { SerializedEditorState } from \"@payloadcms/richtext-lexical/lexical\";\nimport {\n defaultEditorConfig,\n defaultEditorFeatures,\n} from \"@payloadcms/richtext-lexical\";\nimport {\n buildDefaultEditorState,\n getEnabledNodes,\n RenderLexical,\n sanitizeClientEditorConfig,\n} from \"@payloadcms/richtext-lexical/client\";\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\nimport type { InputWrapperProps } from \"./InputWrapper\";\nimport { InputWrapper } from \"./InputWrapper\";\n\nexport interface LexicalInputProps extends InputWrapperProps {\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 <InputWrapper label={label} error={error} className={className}>\n <RenderLexical\n field={{\n name: \"myCustomEditor\",\n label: false,\n type: \"richText\",\n }}\n value={editor.value}\n setValue={(val) => editor.setValue(val as SerializedEditorState)}\n schemaPath=\"global.intl-plugin.editorTemplate\"\n />\n </InputWrapper>\n );\n}\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":["LexicalInput","error","label","value","onChange","className","editor","useHtmlLexicalAdapter","jsx","InputWrapper","RenderLexical","val","EMPTY_STATE","buildDefaultEditorState","html","headlessEditor","useRef","createHeadlessEditor","getEnabledNodes","sanitizeClientEditorConfig","defaultEditorFeatures","defaultEditorConfig","getSerializedState","useCallback","htmlString","dom","nodes","$generateNodesFromDOM","$getRoot","useMemo","serializedState","setValue","newHtml","$generateHtmlFromNodes"],"mappings":";;;;;;;;AAiCO,SAASA,EAAa;AAAA,EAC3B,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AACF,GAAuC;AACrC,QAAMC,IAASC,EAAsB;AAAA,IACnC,MAAMJ;AAAA,IACN,UAAAC;AAAA,EAAA,CACD;AAED,SACE,gBAAAI,EAACC,GAAA,EAAa,OAAAP,GAAc,OAAAD,GAAc,WAAAI,GACxC,UAAA,gBAAAG;AAAA,IAACE;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,MAAA;AAAA,MAER,OAAOJ,EAAO;AAAA,MACd,UAAU,CAACK,MAAQL,EAAO,SAASK,CAA4B;AAAA,MAC/D,YAAW;AAAA,IAAA;AAAA,EAAA,GAEf;AAEJ;AAEA,MAAMC,IAAcC,EAAwB,EAAE;AAOvC,SAASN,EAAsB;AAAA,EACpC,MAAAO;AAAA,EACA,UAAAV;AACF,GAA+B;AAE7B,QAAMW,IAAiBC;AAAA,IACrBC,EAAqB;AAAA,MACnB,OAAOC,EAAgB;AAAA,QACrB,cAAcC;AAAA;AAAA,UAEZC;AAAA,UACAC;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA,CACF;AAAA,EAAA,GAIGC,IAAqBC;AAAA,IACzB,CAACC,MAA8C;AAC7C,YAAMlB,IAASS,EAAe;AAC9B,aAAAT,EAAO;AAAA,QACL,MAAM;AAEJ,gBAAMmB,IADS,IAAI,UAAA,EACA,gBAAgBD,GAAY,WAAW,GACpDE,IAAQC,EAAsBrB,GAAQmB,CAAG;AAG/C,UADaG,EAAA,EACR,MAAA,EAAQ,OAAO,GAAGF,CAAK;AAAA,QAC9B;AAAA,QACA,EAAE,UAAU,GAAA;AAAA,MAAK,GAGZpB,EAAO,eAAA,EAAiB,OAAA;AAAA,IACjC;AAAA,IACA,CAAA;AAAA,EAAC,GAIGH,IAAQ0B,EAAQ,MAAM;AAC1B,UAAMC,IAAkBR,EAAmBR,CAAI;AAE/C,WAAIgB,EAAgB,KAAK,SAAS,WAAW,IACpClB,IAGFkB;AAAA,EACT,GAAG,CAAChB,GAAMQ,CAAkB,CAAC,GAGvBS,IAAWR;AAAA,IACf,CAACO,MAA2C;AAC1C,YAAMxB,IAASS,EAAe;AAG9B,MAAAT,EAAO,eAAeA,EAAO,iBAAiBwB,CAAe,CAAC,GAG9DxB,EAAO,KAAK,MAAM;AAChB,cAAM0B,IAAUC,EAAuB3B,CAAM;AAC7C,QAAI0B,MAAYlB,KACdV,EAAS4B,CAAO;AAAA,MAEpB,CAAC;AAAA,IACH;AAAA,IACA,CAAClB,GAAMV,CAAQ;AAAA,EAAA;AAGjB,SAAO,EAAE,OAAAD,GAAoD,UAAA4B,EAAA;AAC/D;"}
|