payload-intl 1.3.2 → 1.4.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.
Files changed (276) hide show
  1. package/README.md +23 -3
  2. package/dist/components/MessagesField.d.ts +12 -0
  3. package/dist/components/MessagesField.d.ts.map +1 -0
  4. package/dist/components/MessagesField.js +36 -0
  5. package/dist/components/MessagesField.js.map +1 -0
  6. package/dist/components/MessagesImport.d.ts +2 -0
  7. package/dist/components/MessagesImport.d.ts.map +1 -0
  8. package/dist/components/MessagesImport.js +68 -0
  9. package/dist/components/MessagesImport.js.map +1 -0
  10. package/dist/components/MessagesImport.module.css +8 -0
  11. package/dist/components/input/LexicalInput.d.ts +8 -0
  12. package/dist/components/input/LexicalInput.d.ts.map +1 -0
  13. package/dist/components/input/LexicalInput.js +21 -0
  14. package/dist/components/input/LexicalInput.js.map +1 -0
  15. package/dist/components/input/MessageInput.d.ts +12 -0
  16. package/dist/components/input/MessageInput.d.ts.map +1 -0
  17. package/dist/components/{inputs → input}/MessageInput.js +31 -38
  18. package/dist/components/input/MessageInput.js.map +1 -0
  19. package/dist/components/{inputs → input}/MessageInput.module.css +14 -19
  20. package/dist/components/{inputs → input}/ReferencePopover.d.ts +1 -1
  21. package/dist/components/input/ReferencePopover.d.ts.map +1 -0
  22. package/dist/components/{inputs → input}/ReferencePopover.js +20 -5
  23. package/dist/components/input/ReferencePopover.js.map +1 -0
  24. package/dist/components/input/SingleLinePlugin.d.ts.map +1 -0
  25. package/dist/components/input/SingleLinePlugin.js.map +1 -0
  26. package/dist/components/{hooks → input}/useHtmlLexicalAdapter.d.ts.map +1 -1
  27. package/dist/components/{hooks → input}/useHtmlLexicalAdapter.js.map +1 -1
  28. package/dist/{utils/format.d.ts → components/input/utils.d.ts} +2 -2
  29. package/dist/components/input/utils.d.ts.map +1 -0
  30. package/dist/{utils/format.js → components/input/utils.js} +2 -2
  31. package/dist/components/input/utils.js.map +1 -0
  32. package/dist/components/input/variables/VariableChip.d.ts.map +1 -0
  33. package/dist/components/{inputs → input}/variables/VariableChip.js +1 -2
  34. package/dist/components/input/variables/VariableChip.js.map +1 -0
  35. package/dist/components/input/variables/VariableIcon.d.ts.map +1 -0
  36. package/dist/components/input/variables/VariableIcon.js.map +1 -0
  37. package/dist/components/input/variables/VariableNode.d.ts.map +1 -0
  38. package/dist/components/input/variables/VariableNode.js.map +1 -0
  39. package/dist/components/input/variables/VariableSuggestion.d.ts.map +1 -0
  40. package/dist/components/input/variables/VariableSuggestion.js.map +1 -0
  41. package/dist/components/input/variables/editors/PluralVariableEditor.d.ts.map +1 -0
  42. package/dist/components/{inputs → input}/variables/editors/PluralVariableEditor.js +1 -1
  43. package/dist/components/input/variables/editors/PluralVariableEditor.js.map +1 -0
  44. package/dist/components/input/variables/editors/SelectVariableEditor.d.ts.map +1 -0
  45. package/dist/components/{inputs → input}/variables/editors/SelectVariableEditor.js +1 -1
  46. package/dist/components/input/variables/editors/SelectVariableEditor.js.map +1 -0
  47. package/dist/components/input/variables/editors/TagVariableEditor.d.ts.map +1 -0
  48. package/dist/components/{inputs → input}/variables/editors/TagVariableEditor.js +1 -1
  49. package/dist/components/input/variables/editors/TagVariableEditor.js.map +1 -0
  50. package/dist/components/input/variables/editors/TemporalVariableEditor.d.ts.map +1 -0
  51. package/dist/components/input/variables/editors/TemporalVariableEditor.js.map +1 -0
  52. package/dist/components/input/variables/pickers/NumericVariableEditor.d.ts.map +1 -0
  53. package/dist/components/{inputs → input}/variables/pickers/NumericVariableEditor.js +1 -1
  54. package/dist/components/input/variables/pickers/NumericVariableEditor.js.map +1 -0
  55. package/dist/components/input/variables/pickers/TemporalVariablePicker.d.ts.map +1 -0
  56. package/dist/components/{inputs → input}/variables/pickers/TemporalVariablePicker.js +1 -1
  57. package/dist/components/input/variables/pickers/TemporalVariablePicker.js.map +1 -0
  58. package/dist/components/layout/MessageField.d.ts +5 -4
  59. package/dist/components/layout/MessageField.d.ts.map +1 -1
  60. package/dist/components/layout/MessageField.js +44 -51
  61. package/dist/components/layout/MessageField.js.map +1 -1
  62. package/dist/components/layout/MessageField.module.css +17 -5
  63. package/dist/components/layout/MessagesTabs.d.ts.map +1 -1
  64. package/dist/components/layout/MessagesTabs.js +9 -19
  65. package/dist/components/layout/MessagesTabs.js.map +1 -1
  66. package/dist/components/layout/MessagesTree.d.ts +7 -5
  67. package/dist/components/layout/MessagesTree.d.ts.map +1 -1
  68. package/dist/components/layout/MessagesTree.js +12 -22
  69. package/dist/components/layout/MessagesTree.js.map +1 -1
  70. package/dist/components/layout/MessagesTree.module.css +7 -3
  71. package/dist/{utils/config.d.ts → config.d.ts} +1 -1
  72. package/dist/config.d.ts.map +1 -0
  73. package/dist/config.js.map +1 -0
  74. package/dist/const.d.ts +3 -9
  75. package/dist/const.d.ts.map +1 -1
  76. package/dist/const.js +3 -12
  77. package/dist/const.js.map +1 -1
  78. package/dist/exports/client.d.ts +3 -1
  79. package/dist/exports/client.d.ts.map +1 -1
  80. package/dist/exports/client.js +3 -1
  81. package/dist/exports/client.js.map +1 -1
  82. package/dist/exports/fetchMessages.d.ts +4 -0
  83. package/dist/exports/fetchMessages.d.ts.map +1 -0
  84. package/dist/exports/fetchMessages.js +18 -0
  85. package/dist/exports/fetchMessages.js.map +1 -0
  86. package/dist/exports/rsc.d.ts +0 -2
  87. package/dist/exports/rsc.d.ts.map +1 -1
  88. package/dist/exports/rsc.js +0 -2
  89. package/dist/exports/rsc.js.map +1 -1
  90. package/dist/file-storage-hooks.d.ts +17 -0
  91. package/dist/file-storage-hooks.d.ts.map +1 -0
  92. package/dist/file-storage-hooks.js +37 -0
  93. package/dist/file-storage-hooks.js.map +1 -0
  94. package/dist/hooks.d.ts +19 -3
  95. package/dist/hooks.d.ts.map +1 -1
  96. package/dist/hooks.js +41 -20
  97. package/dist/hooks.js.map +1 -1
  98. package/dist/icu/guards.d.ts.map +1 -0
  99. package/dist/icu/guards.js.map +1 -0
  100. package/dist/icu/index.d.ts +6 -0
  101. package/dist/icu/index.d.ts.map +1 -0
  102. package/dist/icu/index.js +7 -0
  103. package/dist/icu/index.js.map +1 -0
  104. package/dist/{utils/icu-tranform.d.ts → icu/lexical.d.ts} +1 -10
  105. package/dist/icu/lexical.d.ts.map +1 -0
  106. package/dist/{utils/icu-tranform.js → icu/lexical.js} +4 -44
  107. package/dist/icu/lexical.js.map +1 -0
  108. package/dist/icu/schema.d.ts +4 -0
  109. package/dist/icu/schema.d.ts.map +1 -0
  110. package/dist/icu/schema.js +43 -0
  111. package/dist/icu/schema.js.map +1 -0
  112. package/dist/icu/serialize.d.ts +11 -0
  113. package/dist/icu/serialize.d.ts.map +1 -0
  114. package/dist/icu/serialize.js +45 -0
  115. package/dist/icu/serialize.js.map +1 -0
  116. package/dist/icu/validate.d.ts.map +1 -0
  117. package/dist/icu/validate.js.map +1 -0
  118. package/dist/index.d.ts +23 -22
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +181 -37
  121. package/dist/index.js.map +1 -1
  122. package/dist/payload-types.d.ts +43 -16
  123. package/dist/payload-types.d.ts.map +1 -1
  124. package/dist/types.d.ts +24 -8
  125. package/dist/types.d.ts.map +1 -1
  126. package/dist/types.js.map +1 -1
  127. package/dist/utils/file-storage.d.ts +26 -0
  128. package/dist/utils/file-storage.d.ts.map +1 -0
  129. package/dist/utils/file-storage.js +61 -0
  130. package/dist/utils/file-storage.js.map +1 -0
  131. package/dist/utils/sanitize.d.ts +5 -3
  132. package/dist/utils/sanitize.d.ts.map +1 -1
  133. package/dist/utils/sanitize.js +4 -2
  134. package/dist/utils/sanitize.js.map +1 -1
  135. package/dist/utils/schema.d.ts +5 -7
  136. package/dist/utils/schema.d.ts.map +1 -1
  137. package/dist/utils/schema.js +11 -39
  138. package/dist/utils/schema.js.map +1 -1
  139. package/dist/utils/scopes.d.ts +3 -0
  140. package/dist/utils/scopes.d.ts.map +1 -0
  141. package/dist/utils/scopes.js +24 -0
  142. package/dist/utils/scopes.js.map +1 -0
  143. package/package.json +5 -5
  144. package/dist/components/MessageFormField.d.ts +0 -14
  145. package/dist/components/MessageFormField.d.ts.map +0 -1
  146. package/dist/components/MessageFormField.js +0 -28
  147. package/dist/components/MessageFormField.js.map +0 -1
  148. package/dist/components/MessagesForm.d.ts +0 -13
  149. package/dist/components/MessagesForm.d.ts.map +0 -1
  150. package/dist/components/MessagesForm.js +0 -120
  151. package/dist/components/MessagesForm.js.map +0 -1
  152. package/dist/components/MessagesForm.module.css +0 -41
  153. package/dist/components/MessagesFormProvider.d.ts +0 -33
  154. package/dist/components/MessagesFormProvider.d.ts.map +0 -1
  155. package/dist/components/MessagesFormProvider.js +0 -34
  156. package/dist/components/MessagesFormProvider.js.map +0 -1
  157. package/dist/components/MessagesLink.d.ts +0 -8
  158. package/dist/components/MessagesLink.d.ts.map +0 -1
  159. package/dist/components/MessagesLink.js +0 -22
  160. package/dist/components/MessagesLink.js.map +0 -1
  161. package/dist/components/MessagesView.d.ts +0 -10
  162. package/dist/components/MessagesView.d.ts.map +0 -1
  163. package/dist/components/MessagesView.js +0 -57
  164. package/dist/components/MessagesView.js.map +0 -1
  165. package/dist/components/actions/CopyMessages.d.ts +0 -2
  166. package/dist/components/actions/CopyMessages.d.ts.map +0 -1
  167. package/dist/components/actions/CopyMessages.js +0 -41
  168. package/dist/components/actions/CopyMessages.js.map +0 -1
  169. package/dist/components/actions/CopyMessages.module.css +0 -8
  170. package/dist/components/actions/JsonImport.d.ts +0 -5
  171. package/dist/components/actions/JsonImport.d.ts.map +0 -1
  172. package/dist/components/actions/JsonImport.js +0 -52
  173. package/dist/components/actions/JsonImport.js.map +0 -1
  174. package/dist/components/actions/JsonImport.module.css +0 -14
  175. package/dist/components/hooks/useMessagesFormSubmit.d.ts +0 -11
  176. package/dist/components/hooks/useMessagesFormSubmit.d.ts.map +0 -1
  177. package/dist/components/hooks/useMessagesFormSubmit.js +0 -44
  178. package/dist/components/hooks/useMessagesFormSubmit.js.map +0 -1
  179. package/dist/components/inputs/FieldWrapper.d.ts +0 -8
  180. package/dist/components/inputs/FieldWrapper.d.ts.map +0 -1
  181. package/dist/components/inputs/FieldWrapper.js +0 -24
  182. package/dist/components/inputs/FieldWrapper.js.map +0 -1
  183. package/dist/components/inputs/FieldWrapper.module.css +0 -24
  184. package/dist/components/inputs/LexicalInput.d.ts +0 -9
  185. package/dist/components/inputs/LexicalInput.d.ts.map +0 -1
  186. package/dist/components/inputs/LexicalInput.js +0 -26
  187. package/dist/components/inputs/LexicalInput.js.map +0 -1
  188. package/dist/components/inputs/MessageInput.d.ts +0 -14
  189. package/dist/components/inputs/MessageInput.d.ts.map +0 -1
  190. package/dist/components/inputs/MessageInput.js.map +0 -1
  191. package/dist/components/inputs/ReferencePopover.d.ts.map +0 -1
  192. package/dist/components/inputs/ReferencePopover.js.map +0 -1
  193. package/dist/components/inputs/SingleLinePlugin.d.ts.map +0 -1
  194. package/dist/components/inputs/SingleLinePlugin.js.map +0 -1
  195. package/dist/components/inputs/variables/VariableChip.d.ts.map +0 -1
  196. package/dist/components/inputs/variables/VariableChip.js.map +0 -1
  197. package/dist/components/inputs/variables/VariableIcon.d.ts.map +0 -1
  198. package/dist/components/inputs/variables/VariableIcon.js.map +0 -1
  199. package/dist/components/inputs/variables/VariableNode.d.ts.map +0 -1
  200. package/dist/components/inputs/variables/VariableNode.js.map +0 -1
  201. package/dist/components/inputs/variables/VariableSuggestion.d.ts.map +0 -1
  202. package/dist/components/inputs/variables/VariableSuggestion.js.map +0 -1
  203. package/dist/components/inputs/variables/editors/PluralVariableEditor.d.ts.map +0 -1
  204. package/dist/components/inputs/variables/editors/PluralVariableEditor.js.map +0 -1
  205. package/dist/components/inputs/variables/editors/SelectVariableEditor.d.ts.map +0 -1
  206. package/dist/components/inputs/variables/editors/SelectVariableEditor.js.map +0 -1
  207. package/dist/components/inputs/variables/editors/TagVariableEditor.d.ts.map +0 -1
  208. package/dist/components/inputs/variables/editors/TagVariableEditor.js.map +0 -1
  209. package/dist/components/inputs/variables/editors/TemporalVariableEditor.d.ts.map +0 -1
  210. package/dist/components/inputs/variables/editors/TemporalVariableEditor.js.map +0 -1
  211. package/dist/components/inputs/variables/pickers/NumericVariableEditor.d.ts.map +0 -1
  212. package/dist/components/inputs/variables/pickers/NumericVariableEditor.js.map +0 -1
  213. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.d.ts.map +0 -1
  214. package/dist/components/inputs/variables/pickers/TemporalVariablePicker.js.map +0 -1
  215. package/dist/components/layout/GroupStatusDot.d.ts +0 -6
  216. package/dist/components/layout/GroupStatusDot.d.ts.map +0 -1
  217. package/dist/components/layout/GroupStatusDot.js +0 -24
  218. package/dist/components/layout/GroupStatusDot.js.map +0 -1
  219. package/dist/components/layout/StatusDot.d.ts +0 -7
  220. package/dist/components/layout/StatusDot.d.ts.map +0 -1
  221. package/dist/components/layout/StatusDot.js +0 -12
  222. package/dist/components/layout/StatusDot.js.map +0 -1
  223. package/dist/components/layout/StatusDot.module.css +0 -16
  224. package/dist/endpoints/set-messages.d.ts +0 -3
  225. package/dist/endpoints/set-messages.d.ts.map +0 -1
  226. package/dist/endpoints/set-messages.js +0 -105
  227. package/dist/endpoints/set-messages.js.map +0 -1
  228. package/dist/entities.d.ts +0 -5
  229. package/dist/entities.d.ts.map +0 -1
  230. package/dist/entities.js +0 -42
  231. package/dist/entities.js.map +0 -1
  232. package/dist/requests/fetchMessages.d.ts +0 -3
  233. package/dist/requests/fetchMessages.d.ts.map +0 -1
  234. package/dist/requests/fetchMessages.js +0 -40
  235. package/dist/requests/fetchMessages.js.map +0 -1
  236. package/dist/utils/config.d.ts.map +0 -1
  237. package/dist/utils/config.js.map +0 -1
  238. package/dist/utils/format.d.ts.map +0 -1
  239. package/dist/utils/format.js.map +0 -1
  240. package/dist/utils/guards.d.ts.map +0 -1
  241. package/dist/utils/guards.js.map +0 -1
  242. package/dist/utils/icu-tranform.d.ts.map +0 -1
  243. package/dist/utils/icu-tranform.js.map +0 -1
  244. package/dist/utils/validate.d.ts.map +0 -1
  245. package/dist/utils/validate.js.map +0 -1
  246. /package/dist/components/{inputs → input}/ReferencePopover.module.css +0 -0
  247. /package/dist/components/{inputs → input}/SingleLinePlugin.d.ts +0 -0
  248. /package/dist/components/{inputs → input}/SingleLinePlugin.js +0 -0
  249. /package/dist/components/{hooks → input}/useHtmlLexicalAdapter.d.ts +0 -0
  250. /package/dist/components/{hooks → input}/useHtmlLexicalAdapter.js +0 -0
  251. /package/dist/components/{inputs → input}/variables/VariableChip.d.ts +0 -0
  252. /package/dist/components/{inputs → input}/variables/VariableChip.module.css +0 -0
  253. /package/dist/components/{inputs → input}/variables/VariableIcon.d.ts +0 -0
  254. /package/dist/components/{inputs → input}/variables/VariableIcon.js +0 -0
  255. /package/dist/components/{inputs → input}/variables/VariableNode.d.ts +0 -0
  256. /package/dist/components/{inputs → input}/variables/VariableNode.js +0 -0
  257. /package/dist/components/{inputs → input}/variables/VariableSuggestion.d.ts +0 -0
  258. /package/dist/components/{inputs → input}/variables/VariableSuggestion.js +0 -0
  259. /package/dist/components/{inputs → input}/variables/VariableSuggestion.module.css +0 -0
  260. /package/dist/components/{inputs → input}/variables/editors/PluralVariableEditor.d.ts +0 -0
  261. /package/dist/components/{inputs → input}/variables/editors/PluralVariableEditor.module.css +0 -0
  262. /package/dist/components/{inputs → input}/variables/editors/SelectVariableEditor.d.ts +0 -0
  263. /package/dist/components/{inputs → input}/variables/editors/SelectVariableEditor.module.css +0 -0
  264. /package/dist/components/{inputs → input}/variables/editors/TagVariableEditor.d.ts +0 -0
  265. /package/dist/components/{inputs → input}/variables/editors/TagVariableEditor.module.css +0 -0
  266. /package/dist/components/{inputs → input}/variables/editors/TemporalVariableEditor.d.ts +0 -0
  267. /package/dist/components/{inputs → input}/variables/editors/TemporalVariableEditor.js +0 -0
  268. /package/dist/components/{inputs → input}/variables/pickers/NumericVariableEditor.d.ts +0 -0
  269. /package/dist/components/{inputs → input}/variables/pickers/NumericVariableEditor.module.css +0 -0
  270. /package/dist/components/{inputs → input}/variables/pickers/TemporalVariablePicker.d.ts +0 -0
  271. /package/dist/components/{inputs → input}/variables/pickers/TemporalVariablePicker.module.css +0 -0
  272. /package/dist/{utils/config.js → config.js} +0 -0
  273. /package/dist/{utils → icu}/guards.d.ts +0 -0
  274. /package/dist/{utils → icu}/guards.js +0 -0
  275. /package/dist/{utils → icu}/validate.d.ts +0 -0
  276. /package/dist/{utils → icu}/validate.js +0 -0
package/README.md CHANGED
@@ -54,6 +54,25 @@ export default buildConfig({
54
54
  });
55
55
  ```
56
56
 
57
+ #### Scoped messages on globals
58
+
59
+ Colocate translations with the globals they belong to by adding `scopes`:
60
+
61
+ ```ts
62
+ intlPlugin({
63
+ schema: {
64
+ navigation: { home: "Home", about: "About" },
65
+ common: { greeting: "Hello {name}!" },
66
+ },
67
+ scopes: ["navigation"],
68
+ // or with position control:
69
+ // scopes: { navigation: 'sidebar' }
70
+ // scopes: { navigation: { position: 'tab', existingFieldsTabLabel: 'Nav Fields' } }
71
+ });
72
+ ```
73
+
74
+ The `navigation` key will be edited on the `navigation` global (in a Messages tab by default), while `common` stays in the `/intl` view.
75
+
57
76
  Fetch messages in your application:
58
77
 
59
78
  ```ts
@@ -67,13 +86,14 @@ const messages = await fetchMessages(payload, "en");
67
86
  | Option | Type | Default | Description |
68
87
  | ---------------- | ------------------------------------------------------ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
69
88
  | `schema` | `MessagesSchema` | — | Required. Nested object defining message keys and ICU templates. Leaf values are ICU MessageFormat strings, optionally prefixed with a `[description]`. |
70
- | `collectionSlug` | `string` | `'messages'` | Slug of the collection used to store translation files. |
89
+ | `storage` | `'db' \| 'upload'` | `'db'` | `'db'` stores translations as JSON in the database. `'upload'` stores them as uploaded `.json` files for CDN/static hosting. |
90
+ | `scopes` | `MessagesScopesConfig` | — | Colocate translation editing with Payload globals. Maps top-level schema keys to globals, adding a Messages tab or sidebar. Accepts an array of slugs or a record with position config. |
91
+ | `tabs` | `boolean` | `false` | When enabled, top-level schema keys are rendered as tabs in the admin UI. |
92
+ | `collectionSlug` | `string` | `'messages'` | Slug of the collection used to store translation documents. |
71
93
  | `editorAccess` | `(req: PayloadRequest) => boolean \| Promise<boolean>` | `(req) => req.user !== null` | Access control function that determines who can edit messages. |
72
94
  | `hooks` | `MessagesHooks` | `{}` | Collection hooks. Extends Payload's collection hooks with an additional `afterUpdate` callback fired when translations are saved. |
73
- | `storage` | `'db' \| 'upload'` | `'db'` | `'db'` stores translations as JSON in the database. `'upload'` stores them as uploaded `.json` files for CDN/static hosting. |
74
95
 
75
96
  > **Note:** Switching between storage strategies on an existing deployment is not yet supported automatically. When the database schema changes (e.g. dropping upload columns), the migration data is lost before the app can read it. A safe migration path will be provided in a future release. For now, export your translations before switching strategies.
76
- | `tabs` | `boolean` | `false` | When enabled, top-level keys in the schema are rendered as tabs in the admin UI. |
77
97
 
78
98
  ## Contributing
79
99
 
@@ -0,0 +1,12 @@
1
+ import type { JSONFieldClientProps } from 'payload';
2
+ import type { MessagesSchema } from '../types';
3
+ export interface MessagesFieldProps {
4
+ readonly schema: MessagesSchema;
5
+ readonly hiddenGroups?: string[];
6
+ }
7
+ /**
8
+ * Payload JSON field client component that bridges the virtual `_intlMessages`
9
+ * field with the existing MessagesFormProvider / MessagesTree component tree.
10
+ */
11
+ export declare function MessagesField({ schema, hiddenGroups, path, }: JSONFieldClientProps & MessagesFieldProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=MessagesField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagesField.d.ts","sourceRoot":"","sources":["../../src/components/MessagesField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,SAAS,CAAC;AAGxD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,YAAY,EACZ,IAAI,GACL,EAAE,oBAAoB,GAAG,kBAAkB,2CAwB3C"}
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useField } from '@payloadcms/ui';
4
+ import { useEffect } from 'react';
5
+ import { useForm } from 'react-hook-form';
6
+ import { MessagesTree } from './layout/MessagesTree';
7
+ /**
8
+ * Payload JSON field client component that bridges the virtual `_intlMessages`
9
+ * field with the existing MessagesFormProvider / MessagesTree component tree.
10
+ */ export function MessagesField({ schema, hiddenGroups, path }) {
11
+ const { value, setValue } = useField({
12
+ path
13
+ });
14
+ const form = useForm({
15
+ values: value,
16
+ reValidateMode: 'onBlur'
17
+ });
18
+ // When form values change, push back to Payload's field
19
+ useEffect(()=>{
20
+ const subscription = form.watch((formValues)=>{
21
+ setValue(formValues);
22
+ });
23
+ return ()=>subscription.unsubscribe();
24
+ }, [
25
+ form,
26
+ setValue
27
+ ]);
28
+ return /*#__PURE__*/ _jsx(MessagesTree, {
29
+ control: form.control,
30
+ hiddenGroups: hiddenGroups,
31
+ path: "",
32
+ schema: schema
33
+ });
34
+ }
35
+
36
+ //# sourceMappingURL=MessagesField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/MessagesField.tsx"],"sourcesContent":["'use client';\n\nimport { useField } from '@payloadcms/ui';\nimport type { JSONFieldClientProps } from 'payload';\nimport { useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport type { Messages, MessagesSchema } from '@/types';\nimport { MessagesTree } from './layout/MessagesTree';\n\nexport interface MessagesFieldProps {\n readonly schema: MessagesSchema;\n readonly hiddenGroups?: string[];\n}\n\n/**\n * Payload JSON field client component that bridges the virtual `_intlMessages`\n * field with the existing MessagesFormProvider / MessagesTree component tree.\n */\nexport function MessagesField({\n schema,\n hiddenGroups,\n path,\n}: JSONFieldClientProps & MessagesFieldProps) {\n const { value, setValue } = useField<Messages>({ path });\n\n const form = useForm<Messages>({\n values: value,\n reValidateMode: 'onBlur',\n });\n\n // When form values change, push back to Payload's field\n useEffect(() => {\n const subscription = form.watch((formValues) => {\n setValue(formValues);\n });\n return () => subscription.unsubscribe();\n }, [form, setValue]);\n\n return (\n <MessagesTree\n control={form.control}\n hiddenGroups={hiddenGroups}\n path=\"\"\n schema={schema}\n />\n );\n}\n"],"names":["useField","useEffect","useForm","MessagesTree","MessagesField","schema","hiddenGroups","path","value","setValue","form","values","reValidateMode","subscription","watch","formValues","unsubscribe","control"],"mappings":"AAAA;;AAEA,SAASA,QAAQ,QAAQ,iBAAiB;AAE1C,SAASC,SAAS,QAAQ,QAAQ;AAClC,SAASC,OAAO,QAAQ,kBAAkB;AAE1C,SAASC,YAAY,QAAQ,wBAAwB;AAOrD;;;CAGC,GACD,OAAO,SAASC,cAAc,EAC5BC,MAAM,EACNC,YAAY,EACZC,IAAI,EACsC;IAC1C,MAAM,EAAEC,KAAK,EAAEC,QAAQ,EAAE,GAAGT,SAAmB;QAAEO;IAAK;IAEtD,MAAMG,OAAOR,QAAkB;QAC7BS,QAAQH;QACRI,gBAAgB;IAClB;IAEA,wDAAwD;IACxDX,UAAU;QACR,MAAMY,eAAeH,KAAKI,KAAK,CAAC,CAACC;YAC/BN,SAASM;QACX;QACA,OAAO,IAAMF,aAAaG,WAAW;IACvC,GAAG;QAACN;QAAMD;KAAS;IAEnB,qBACE,KAACN;QACCc,SAASP,KAAKO,OAAO;QACrBX,cAAcA;QACdC,MAAK;QACLF,QAAQA;;AAGd"}
@@ -0,0 +1,2 @@
1
+ export declare function MessagesImport(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=MessagesImport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagesImport.d.ts","sourceRoot":"","sources":["../../src/components/MessagesImport.tsx"],"names":[],"mappings":"AAOA,wBAAgB,cAAc,4CAiE7B"}
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Button, Popup, useField } from '@payloadcms/ui';
4
+ import { useRef } from 'react';
5
+ import styles from './MessagesImport.module.css';
6
+ export function MessagesImport() {
7
+ const { setValue } = useField({
8
+ path: 'data'
9
+ });
10
+ const inputRef = useRef(null);
11
+ const handleImportFromFile = (event)=>{
12
+ const file = event.target.files?.[0];
13
+ if (!file) {
14
+ event.target.value = '';
15
+ return;
16
+ }
17
+ const reader = new FileReader();
18
+ reader.onload = (readerEvent)=>{
19
+ const text = readerEvent.target?.result;
20
+ const data = JSON.parse(text);
21
+ setValue(data);
22
+ // Clear the input value to allow re-selection of the same or different file
23
+ event.target.value = '';
24
+ };
25
+ reader.readAsText(file);
26
+ };
27
+ const handleImportFromURL = ()=>{
28
+ const url = prompt('Enter the URL of the JSON file to import:');
29
+ if (!url) return;
30
+ // TODO Validate URL
31
+ fetch(url).then((response)=>response.json()).then(setValue).catch((error)=>console.error('Error importing JSON:', error));
32
+ };
33
+ return /*#__PURE__*/ _jsxs(_Fragment, {
34
+ children: [
35
+ /*#__PURE__*/ _jsx("input", {
36
+ accept: ".json",
37
+ hidden: true,
38
+ onChange: handleImportFromFile,
39
+ ref: inputRef,
40
+ type: "file"
41
+ }),
42
+ /*#__PURE__*/ _jsx(Popup, {
43
+ button: "Import",
44
+ children: /*#__PURE__*/ _jsxs("div", {
45
+ className: styles.popup,
46
+ children: [
47
+ /*#__PURE__*/ _jsx(Button, {
48
+ buttonStyle: "subtle",
49
+ className: styles.action,
50
+ iconPosition: "left",
51
+ onClick: ()=>inputRef.current?.click(),
52
+ children: "Import from File"
53
+ }),
54
+ /*#__PURE__*/ _jsx(Button, {
55
+ buttonStyle: "subtle",
56
+ className: styles.action,
57
+ iconPosition: "left",
58
+ onClick: handleImportFromURL,
59
+ children: "Import from URL"
60
+ })
61
+ ]
62
+ })
63
+ })
64
+ ]
65
+ });
66
+ }
67
+
68
+ //# sourceMappingURL=MessagesImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/MessagesImport.tsx"],"sourcesContent":["'use client';\n\nimport { Button, Popup, useField } from '@payloadcms/ui';\nimport { useRef } from 'react';\n\nimport styles from './MessagesImport.module.css';\n\nexport function MessagesImport() {\n const { setValue } = useField({ path: 'data' });\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleImportFromFile = (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n if (!file) {\n event.target.value = '';\n return;\n }\n\n const reader = new FileReader();\n reader.onload = (readerEvent) => {\n const text = readerEvent.target?.result as string;\n const data = JSON.parse(text);\n setValue(data);\n // Clear the input value to allow re-selection of the same or different file\n event.target.value = '';\n };\n reader.readAsText(file);\n };\n\n const handleImportFromURL = () => {\n const url = prompt('Enter the URL of the JSON file to import:');\n if (!url) return;\n\n // TODO Validate URL\n\n fetch(url)\n .then((response) => response.json())\n .then(setValue)\n .catch((error) => console.error('Error importing JSON:', error));\n };\n\n return (\n <>\n <input\n accept=\".json\"\n hidden\n onChange={handleImportFromFile}\n ref={inputRef}\n type=\"file\"\n />\n <Popup button=\"Import\">\n <div className={styles.popup}>\n <Button\n buttonStyle=\"subtle\"\n className={styles.action}\n iconPosition=\"left\"\n onClick={() => inputRef.current?.click()}\n >\n Import from File\n </Button>\n <Button\n buttonStyle=\"subtle\"\n className={styles.action}\n iconPosition=\"left\"\n onClick={handleImportFromURL}\n >\n Import from URL\n </Button>\n </div>\n </Popup>\n </>\n );\n}\n"],"names":["Button","Popup","useField","useRef","styles","MessagesImport","setValue","path","inputRef","handleImportFromFile","event","file","target","files","value","reader","FileReader","onload","readerEvent","text","result","data","JSON","parse","readAsText","handleImportFromURL","url","prompt","fetch","then","response","json","catch","error","console","input","accept","hidden","onChange","ref","type","button","div","className","popup","buttonStyle","action","iconPosition","onClick","current","click"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,EAAEC,QAAQ,QAAQ,iBAAiB;AACzD,SAASC,MAAM,QAAQ,QAAQ;AAE/B,OAAOC,YAAY,8BAA8B;AAEjD,OAAO,SAASC;IACd,MAAM,EAAEC,QAAQ,EAAE,GAAGJ,SAAS;QAAEK,MAAM;IAAO;IAC7C,MAAMC,WAAWL,OAAyB;IAE1C,MAAMM,uBAAuB,CAACC;QAC5B,MAAMC,OAAOD,MAAME,MAAM,CAACC,KAAK,EAAE,CAAC,EAAE;QACpC,IAAI,CAACF,MAAM;YACTD,MAAME,MAAM,CAACE,KAAK,GAAG;YACrB;QACF;QAEA,MAAMC,SAAS,IAAIC;QACnBD,OAAOE,MAAM,GAAG,CAACC;YACf,MAAMC,OAAOD,YAAYN,MAAM,EAAEQ;YACjC,MAAMC,OAAOC,KAAKC,KAAK,CAACJ;YACxBb,SAASe;YACT,4EAA4E;YAC5EX,MAAME,MAAM,CAACE,KAAK,GAAG;QACvB;QACAC,OAAOS,UAAU,CAACb;IACpB;IAEA,MAAMc,sBAAsB;QAC1B,MAAMC,MAAMC,OAAO;QACnB,IAAI,CAACD,KAAK;QAEV,oBAAoB;QAEpBE,MAAMF,KACHG,IAAI,CAAC,CAACC,WAAaA,SAASC,IAAI,IAChCF,IAAI,CAACvB,UACL0B,KAAK,CAAC,CAACC,QAAUC,QAAQD,KAAK,CAAC,yBAAyBA;IAC7D;IAEA,qBACE;;0BACE,KAACE;gBACCC,QAAO;gBACPC,MAAM;gBACNC,UAAU7B;gBACV8B,KAAK/B;gBACLgC,MAAK;;0BAEP,KAACvC;gBAAMwC,QAAO;0BACZ,cAAA,MAACC;oBAAIC,WAAWvC,OAAOwC,KAAK;;sCAC1B,KAAC5C;4BACC6C,aAAY;4BACZF,WAAWvC,OAAO0C,MAAM;4BACxBC,cAAa;4BACbC,SAAS,IAAMxC,SAASyC,OAAO,EAAEC;sCAClC;;sCAGD,KAAClD;4BACC6C,aAAY;4BACZF,WAAWvC,OAAO0C,MAAM;4BACxBC,cAAa;4BACbC,SAASvB;sCACV;;;;;;;AAOX"}
@@ -0,0 +1,8 @@
1
+ .popup {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 0.75rem;
5
+ }
6
+ .action {
7
+ margin-block: 0;
8
+ }
@@ -0,0 +1,8 @@
1
+ export interface LexicalInputProps {
2
+ lang: string;
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ onBlur: () => void;
6
+ }
7
+ export declare function LexicalInput({ value, onChange, }: LexicalInputProps): React.ReactNode;
8
+ //# sourceMappingURL=LexicalInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LexicalInput.d.ts","sourceRoot":"","sources":["../../../src/components/input/LexicalInput.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,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,QAAQ,GACT,EAAE,iBAAiB,GAAG,KAAK,CAAC,SAAS,CAkBrC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { RenderLexical } from '@payloadcms/richtext-lexical/client';
3
+ import { useHtmlLexicalAdapter } from './useHtmlLexicalAdapter';
4
+ export function LexicalInput({ value, onChange }) {
5
+ const editor = useHtmlLexicalAdapter({
6
+ html: value,
7
+ onChange
8
+ });
9
+ return /*#__PURE__*/ _jsx(RenderLexical, {
10
+ field: {
11
+ name: 'myCustomEditor',
12
+ label: false,
13
+ type: 'richText'
14
+ },
15
+ schemaPath: "global.intl-plugin.editorTemplate",
16
+ setValue: (val)=>editor.setValue(val),
17
+ value: editor.value
18
+ });
19
+ }
20
+
21
+ //# sourceMappingURL=LexicalInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/input/LexicalInput.tsx"],"sourcesContent":["import { RenderLexical } from '@payloadcms/richtext-lexical/client';\nimport type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical';\nimport { useHtmlLexicalAdapter } from './useHtmlLexicalAdapter';\n\nexport interface LexicalInputProps {\n lang: string;\n value: string;\n onChange: (value: string) => void;\n onBlur: () => void;\n}\n\nexport function LexicalInput({\n value,\n onChange,\n}: LexicalInputProps): React.ReactNode {\n const editor = useHtmlLexicalAdapter({\n html: value,\n onChange,\n });\n\n return (\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 );\n}\n"],"names":["RenderLexical","useHtmlLexicalAdapter","LexicalInput","value","onChange","editor","html","field","name","label","type","schemaPath","setValue","val"],"mappings":";AAAA,SAASA,aAAa,QAAQ,sCAAsC;AAEpE,SAASC,qBAAqB,QAAQ,0BAA0B;AAShE,OAAO,SAASC,aAAa,EAC3BC,KAAK,EACLC,QAAQ,EACU;IAClB,MAAMC,SAASJ,sBAAsB;QACnCK,MAAMH;QACNC;IACF;IAEA,qBACE,KAACJ;QACCO,OAAO;YACLC,MAAM;YACNC,OAAO;YACPC,MAAM;QACR;QACAC,YAAW;QACXC,UAAU,CAACC,MAAQR,OAAOO,QAAQ,CAACC;QACnCV,OAAOE,OAAOF,KAAK;;AAGzB"}
@@ -0,0 +1,12 @@
1
+ import type { TemplateVariable } from '../../types';
2
+ export interface MessageInputProps {
3
+ value: string;
4
+ variables: TemplateVariable[];
5
+ onChange: (value: string) => void;
6
+ onBlur: () => void;
7
+ readOnly?: boolean;
8
+ multiline?: boolean;
9
+ error?: boolean;
10
+ }
11
+ export declare function MessageInput({ value, variables, onChange, onBlur, multiline, error, }: MessageInputProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=MessageInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../../src/components/input/MessageInput.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA2BhD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,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,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,iBAAiB,2CA2EnB"}
@@ -8,13 +8,10 @@ import { LexicalErrorBoundary } from '@payloadcms/richtext-lexical/lexical/react
8
8
  import { HistoryPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalHistoryPlugin';
9
9
  import { OnChangePlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalOnChangePlugin';
10
10
  import { PlainTextPlugin } from '@payloadcms/richtext-lexical/lexical/react/LexicalPlainTextPlugin';
11
- import clsx from 'clsx';
12
11
  import { BeautifulMentionNode, BeautifulMentionsPlugin } from 'lexical-beautiful-mentions';
13
12
  import { useCallback, useEffect, useMemo } from 'react';
14
- import { formatVariableLabel } from '../../utils/format';
15
- import { isTagElement } from '../../utils/guards';
16
- import { parseIcuToLexicalState, serializeICUMessage } from '../../utils/icu-tranform';
17
- import { FieldWrapper } from './FieldWrapper';
13
+ import { formatVariableLabel } from '../../components/input/utils';
14
+ import { isTagElement, parseIcuToLexicalState, serializeICUMessage } from '../../icu';
18
15
  import styles from './MessageInput.module.css';
19
16
  import { SingleLinePlugin } from './SingleLinePlugin';
20
17
  import { VariableMentionNode } from './variables/VariableNode';
@@ -35,7 +32,7 @@ function SyncValuePlugin({ value }) {
35
32
  ]);
36
33
  return null;
37
34
  }
38
- export function MessageInput({ value, lang, error, variables, onChange, onBlur, className, multiline, reference }) {
35
+ export function MessageInput({ value, variables, onChange, onBlur, multiline, error }) {
39
36
  const handleChange = useCallback((editorState)=>{
40
37
  editorState.read(()=>{
41
38
  onChange($getRoot().getTextContent());
@@ -74,39 +71,35 @@ export function MessageInput({ value, lang, error, variables, onChange, onBlur,
74
71
  editable: true,
75
72
  onError: console.error
76
73
  }), []);
77
- return /*#__PURE__*/ _jsx(FieldWrapper, {
78
- className: className,
79
- error: error,
80
- reference: reference,
81
- children: /*#__PURE__*/ _jsx(LexicalComposer, {
82
- initialConfig: initialConfig,
83
- children: /*#__PURE__*/ _jsxs("div", {
84
- className: clsx(styles.editor, multiline && styles.multiline),
85
- lang: lang,
86
- children: [
87
- /*#__PURE__*/ _jsx(PlainTextPlugin, {
88
- contentEditable: /*#__PURE__*/ _jsx(ContentEditable, {
89
- className: clsx(styles.contentEditable, error && styles.contentEditableError),
90
- onBlur: onBlur
91
- }),
92
- ErrorBoundary: LexicalErrorBoundary
74
+ return /*#__PURE__*/ _jsx(LexicalComposer, {
75
+ initialConfig: initialConfig,
76
+ children: /*#__PURE__*/ _jsxs("div", {
77
+ className: styles.editor,
78
+ "data-multiline": multiline,
79
+ children: [
80
+ /*#__PURE__*/ _jsx(PlainTextPlugin, {
81
+ contentEditable: /*#__PURE__*/ _jsx(ContentEditable, {
82
+ className: styles.contentEditable,
83
+ "data-error": error,
84
+ onBlur: onBlur
93
85
  }),
94
- multiline && /*#__PURE__*/ _jsx(SingleLinePlugin, {}),
95
- /*#__PURE__*/ _jsx(SyncValuePlugin, {
96
- value: value
97
- }),
98
- /*#__PURE__*/ _jsx(OnChangePlugin, {
99
- onChange: handleChange
100
- }),
101
- /*#__PURE__*/ _jsx(HistoryPlugin, {}),
102
- /*#__PURE__*/ _jsx(BeautifulMentionsPlugin, {
103
- items: mentionItems,
104
- menuAnchorClassName: styles.menuAnchor,
105
- menuComponent: MentionMenu,
106
- menuItemComponent: MentionMenuItem
107
- })
108
- ]
109
- })
86
+ ErrorBoundary: LexicalErrorBoundary
87
+ }),
88
+ multiline && /*#__PURE__*/ _jsx(SingleLinePlugin, {}),
89
+ /*#__PURE__*/ _jsx(SyncValuePlugin, {
90
+ value: value
91
+ }),
92
+ /*#__PURE__*/ _jsx(OnChangePlugin, {
93
+ onChange: handleChange
94
+ }),
95
+ /*#__PURE__*/ _jsx(HistoryPlugin, {}),
96
+ /*#__PURE__*/ _jsx(BeautifulMentionsPlugin, {
97
+ items: mentionItems,
98
+ menuAnchorClassName: styles.menuAnchor,
99
+ menuComponent: MentionMenu,
100
+ menuItemComponent: MentionMenuItem
101
+ })
102
+ ]
110
103
  })
111
104
  });
112
105
  }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/input/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 {\n BeautifulMentionNode,\n BeautifulMentionsPlugin,\n} from 'lexical-beautiful-mentions';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { formatVariableLabel } from '@/components/input/utils';\nimport {\n isTagElement,\n parseIcuToLexicalState,\n serializeICUMessage,\n} from '@/icu';\nimport type { TemplateVariable } from '@/types';\n\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 {\n value: string;\n variables: TemplateVariable[];\n onChange: (value: string) => void;\n onBlur: () => void;\n readOnly?: boolean;\n multiline?: boolean;\n error?: boolean;\n}\n\nexport function MessageInput({\n value,\n variables,\n onChange,\n onBlur,\n multiline,\n error,\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 <LexicalComposer initialConfig={initialConfig}>\n <div className={styles.editor} data-multiline={multiline}>\n <PlainTextPlugin\n contentEditable={\n <ContentEditable\n className={styles.contentEditable}\n data-error={error}\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 );\n}\n"],"names":["$getRoot","LexicalComposer","useLexicalComposerContext","ContentEditable","LexicalErrorBoundary","HistoryPlugin","OnChangePlugin","PlainTextPlugin","BeautifulMentionNode","BeautifulMentionsPlugin","useCallback","useEffect","useMemo","formatVariableLabel","isTagElement","parseIcuToLexicalState","serializeICUMessage","styles","SingleLinePlugin","VariableMentionNode","MentionMenu","MentionMenuItem","SyncValuePlugin","value","editor","currentText","getEditorState","read","getTextContent","queueMicrotask","newState","parseEditorState","JSON","stringify","setEditorState","MessageInput","variables","onChange","onBlur","multiline","error","handleChange","editorState","mentionItems","toItem","v","label","icu","map","filter","initialConfig","namespace","nodes","replace","with","node","getTrigger","getValue","getData","withKlass","editable","onError","console","div","className","data-multiline","contentEditable","data-error","ErrorBoundary","items","menuAnchorClassName","menuAnchor","menuComponent","menuItemComponent"],"mappings":"AAAA;;AAGA,SAASA,QAAQ,QAAQ,uCAAuC;AAChE,SAASC,eAAe,QAAQ,6DAA6D;AAC7F,SAASC,yBAAyB,QAAQ,oEAAoE;AAC9G,SAASC,eAAe,QAAQ,oEAAoE;AACpG,SAASC,oBAAoB,QAAQ,kEAAkE;AACvG,SAASC,aAAa,QAAQ,kEAAkE;AAChG,SAASC,cAAc,QAAQ,mEAAmE;AAClG,SAASC,eAAe,QAAQ,oEAAoE;AACpG,SACEC,oBAAoB,EACpBC,uBAAuB,QAClB,6BAA6B;AACpC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,QAAQ,QAAQ;AACxD,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SACEC,YAAY,EACZC,sBAAsB,EACtBC,mBAAmB,QACd,QAAQ;AAGf,OAAOC,YAAY,4BAA4B;AAC/C,SAASC,gBAAgB,QAAQ,qBAAqB;AACtD,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SAASC,WAAW,EAAEC,eAAe,QAAQ,iCAAiC;AAE9E,SAASC,gBAAgB,EAAEC,KAAK,EAAqB;IACnD,MAAM,CAACC,OAAO,GAAGtB;IAEjBS,UAAU;QACR,MAAMc,cAAcD,OACjBE,cAAc,GACdC,IAAI,CAAC,IAAM3B,WAAW4B,cAAc;QACvC,IAAIL,UAAUE,aAAa;YACzBI,eAAe;gBACb,MAAMC,WAAWN,OAAOO,gBAAgB,CACtCC,KAAKC,SAAS,CAAClB,uBAAuBQ;gBAExCC,OAAOU,cAAc,CAACJ;YACxB;QACF;IACF,GAAG;QAACP;QAAOC;KAAO;IAElB,OAAO;AACT;AAYA,OAAO,SAASW,aAAa,EAC3BZ,KAAK,EACLa,SAAS,EACTC,QAAQ,EACRC,MAAM,EACNC,SAAS,EACTC,KAAK,EACa;IAClB,MAAMC,eAAe/B,YACnB,CAACgC;QACCA,YAAYf,IAAI,CAAC;YACfU,SAASrC,WAAW4B,cAAc;QACpC;IACF,GACA;QAACS;KAAS;IAGZ,MAAMM,eAAe/B,QAAQ;QAC3B,MAAMgC,SAAS,CAACC,IAAyB,CAAA;gBACvCtB,OAAOsB,EAAEtB,KAAK;gBACduB,OAAOjC,oBAAoBgC;gBAC3BE,KAAK/B,oBAAoB;oBAAC6B;iBAAE;YAC9B,CAAA;QAEA,OAAO;YACL,KAAKT,UAAUY,GAAG,CAACJ;YACnB,KAAKR,UAAUa,MAAM,CAAC,CAACJ,IAAM,CAAC/B,aAAa+B,IAAIG,GAAG,CAACJ;YACnD,KAAKR,UAAUa,MAAM,CAAC,CAACJ,IAAM/B,aAAa+B,IAAIG,GAAG,CAACJ;QACpD;IACF,GAAG;QAACR;KAAU;IAEd,6GAA6G;IAC7G,MAAMc,gBAAgBtC,QACpB,IAAO,CAAA;YACLuC,WAAW;YACXC,OAAO;gBACLjC;gBACA;oBACEkC,SAAS7C;oBACT8C,MAAM,CAACC,OACL,IAAIpC,oBACFoC,KAAKC,UAAU,IACfD,KAAKE,QAAQ,IACbF,KAAKG,OAAO;oBAEhBC,WAAWxC;gBACb;aACD;YACDuB,aAAaV,KAAKC,SAAS,CAAClB,uBAAuBQ;YACnDqC,UAAU;YACVC,SAASC,QAAQtB,KAAK;QACxB,CAAA,GACA,EAAE;IAGJ,qBACE,KAACvC;QAAgBiD,eAAeA;kBAC9B,cAAA,MAACa;YAAIC,WAAW/C,OAAOO,MAAM;YAAEyC,kBAAgB1B;;8BAC7C,KAAChC;oBACC2D,+BACE,KAAC/D;wBACC6D,WAAW/C,OAAOiD,eAAe;wBACjCC,cAAY3B;wBACZF,QAAQA;;oBAGZ8B,eAAehE;;gBAEhBmC,2BAAa,KAACrB;8BACf,KAACI;oBAAgBC,OAAOA;;8BACxB,KAACjB;oBAAe+B,UAAUI;;8BAC1B,KAACpC;8BAED,KAACI;oBACC4D,OAAO1B;oBACP2B,qBAAqBrD,OAAOsD,UAAU;oBACtCC,eAAepD;oBACfqD,mBAAmBpD;;;;;AAK7B"}
@@ -4,15 +4,10 @@
4
4
  align-items: center;
5
5
  min-height: 2rem;
6
6
  font-size: var(--font-size-large);
7
- }
8
-
9
- .readOnly {
10
- opacity: 0.7;
11
- cursor: default;
12
- }
13
7
 
14
- .multiline {
15
- min-height: 4rem;
8
+ &[data-multiline="true"] {
9
+ min-height: 4rem;
10
+ }
16
11
  }
17
12
 
18
13
  .menuAnchor {
@@ -27,18 +22,18 @@
27
22
  padding-block: 0.25rem;
28
23
  padding-inline: 0.75rem;
29
24
  height: 100%;
30
- }
31
25
 
32
- .contentEditable:focus {
33
- outline: none;
34
- border-color: var(--theme-elevation-600);
35
- }
26
+ &:focus {
27
+ outline: none;
28
+ border-color: var(--theme-elevation-600);
29
+ }
36
30
 
37
- .contentEditableError {
38
- border-color: var(--theme-error-400);
39
- background-color: var(--theme-error-100);
40
- }
31
+ &[data-error="true"] {
32
+ border-color: var(--theme-error-400);
33
+ background-color: var(--theme-error-100);
34
+ }
41
35
 
42
- .contentEditable p {
43
- margin: 0;
36
+ p {
37
+ margin: 0;
38
+ }
44
39
  }
@@ -1,4 +1,4 @@
1
- import type { ReactElement } from 'react';
1
+ import { type ReactElement } from 'react';
2
2
  export interface ReferencePopoverProps {
3
3
  reference?: string;
4
4
  children: ReactElement;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReferencePopover.d.ts","sourceRoot":"","sources":["../../../src/components/input/ReferencePopover.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,OAAO,CAAC;AAIf,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,2CAQvB"}
@@ -1,18 +1,32 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Popover } from '@base-ui/react/popover';
3
3
  import { IconX } from '@tabler/icons-react';
4
+ import { useCallback, useRef, useState } from 'react';
4
5
  import styles from './ReferencePopover.module.css';
5
6
  export function ReferencePopover({ reference, children }) {
6
7
  if (!reference) return children;
8
+ return /*#__PURE__*/ _jsx(ControlledReferencePopover, {
9
+ reference: reference,
10
+ children: children
11
+ });
12
+ }
13
+ function ControlledReferencePopover({ reference, children }) {
14
+ const [open, setOpen] = useState(false);
15
+ const anchorRef = useRef(null);
16
+ const handleFocus = useCallback(()=>setOpen(true), []);
17
+ const handleBlur = useCallback((e)=>{
18
+ // Stay open if focus moves within the fieldset or into the popup
19
+ if (anchorRef.current?.contains(e.relatedTarget) || e.relatedTarget?.closest('[data-popup-open]')) return;
20
+ setOpen(false);
21
+ }, []);
7
22
  return /*#__PURE__*/ _jsxs(Popover.Root, {
23
+ onOpenChange: setOpen,
24
+ open: open,
8
25
  children: [
9
- /*#__PURE__*/ _jsx(Popover.Trigger, {
10
- nativeButton: false,
11
- render: children
12
- }),
13
26
  /*#__PURE__*/ _jsx(Popover.Portal, {
14
27
  children: /*#__PURE__*/ _jsx(Popover.Positioner, {
15
28
  align: "start",
29
+ anchor: anchorRef,
16
30
  side: "top",
17
31
  sideOffset: 4,
18
32
  children: /*#__PURE__*/ _jsxs(Popover.Popup, {
@@ -34,7 +48,8 @@ export function ReferencePopover({ reference, children }) {
34
48
  ]
35
49
  })
36
50
  })
37
- })
51
+ }),
52
+ children
38
53
  ]
39
54
  });
40
55
  }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/input/ReferencePopover.tsx"],"sourcesContent":["import { Popover } from '@base-ui/react/popover';\n\nimport { IconX } from '@tabler/icons-react';\nimport {\n cloneElement,\n type ReactElement,\n useCallback,\n useRef,\n useState,\n} from 'react';\n\nimport styles from './ReferencePopover.module.css';\n\nexport interface ReferencePopoverProps {\n reference?: string;\n children: ReactElement;\n}\n\nexport function ReferencePopover({\n reference,\n children,\n}: ReferencePopoverProps) {\n if (!reference) return children;\n\n return (\n <ControlledReferencePopover reference={reference}>\n {children}\n </ControlledReferencePopover>\n );\n}\n\nfunction ControlledReferencePopover({\n reference,\n children,\n}: {\n reference: string;\n children: ReactElement;\n}) {\n const [open, setOpen] = useState(false);\n const anchorRef = useRef<HTMLElement>(null);\n\n const handleFocus = useCallback(() => setOpen(true), []);\n const handleBlur = useCallback((e: React.FocusEvent) => {\n // Stay open if focus moves within the fieldset or into the popup\n if (\n anchorRef.current?.contains(e.relatedTarget) ||\n e.relatedTarget?.closest('[data-popup-open]')\n )\n return;\n setOpen(false);\n }, []);\n\n return (\n <Popover.Root onOpenChange={setOpen} open={open}>\n <Popover.Portal>\n <Popover.Positioner\n align=\"start\"\n anchor={anchorRef}\n side=\"top\"\n sideOffset={4}\n >\n <Popover.Popup\n className={styles.popup}\n initialFocus={false}\n onMouseDown={(e) => e.preventDefault()}\n >\n <Popover.Close className={styles.dismiss} type=\"button\">\n <IconX size={14} />\n </Popover.Close>\n <p className={styles.text}>{reference}</p>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n {children}\n {/*{cloneElement(children, {\n ref: anchorRef,\n onFocus: handleFocus,\n onBlur: handleBlur,\n })}*/}\n </Popover.Root>\n );\n}\n"],"names":["Popover","IconX","useCallback","useRef","useState","styles","ReferencePopover","reference","children","ControlledReferencePopover","open","setOpen","anchorRef","handleFocus","handleBlur","e","current","contains","relatedTarget","closest","Root","onOpenChange","Portal","Positioner","align","anchor","side","sideOffset","Popup","className","popup","initialFocus","onMouseDown","preventDefault","Close","dismiss","type","size","p","text"],"mappings":";AAAA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,SAASC,KAAK,QAAQ,sBAAsB;AAC5C,SAGEC,WAAW,EACXC,MAAM,EACNC,QAAQ,QACH,QAAQ;AAEf,OAAOC,YAAY,gCAAgC;AAOnD,OAAO,SAASC,iBAAiB,EAC/BC,SAAS,EACTC,QAAQ,EACc;IACtB,IAAI,CAACD,WAAW,OAAOC;IAEvB,qBACE,KAACC;QAA2BF,WAAWA;kBACpCC;;AAGP;AAEA,SAASC,2BAA2B,EAClCF,SAAS,EACTC,QAAQ,EAIT;IACC,MAAM,CAACE,MAAMC,QAAQ,GAAGP,SAAS;IACjC,MAAMQ,YAAYT,OAAoB;IAEtC,MAAMU,cAAcX,YAAY,IAAMS,QAAQ,OAAO,EAAE;IACvD,MAAMG,aAAaZ,YAAY,CAACa;QAC9B,iEAAiE;QACjE,IACEH,UAAUI,OAAO,EAAEC,SAASF,EAAEG,aAAa,KAC3CH,EAAEG,aAAa,EAAEC,QAAQ,sBAEzB;QACFR,QAAQ;IACV,GAAG,EAAE;IAEL,qBACE,MAACX,QAAQoB,IAAI;QAACC,cAAcV;QAASD,MAAMA;;0BACzC,KAACV,QAAQsB,MAAM;0BACb,cAAA,KAACtB,QAAQuB,UAAU;oBACjBC,OAAM;oBACNC,QAAQb;oBACRc,MAAK;oBACLC,YAAY;8BAEZ,cAAA,MAAC3B,QAAQ4B,KAAK;wBACZC,WAAWxB,OAAOyB,KAAK;wBACvBC,cAAc;wBACdC,aAAa,CAACjB,IAAMA,EAAEkB,cAAc;;0CAEpC,KAACjC,QAAQkC,KAAK;gCAACL,WAAWxB,OAAO8B,OAAO;gCAAEC,MAAK;0CAC7C,cAAA,KAACnC;oCAAMoC,MAAM;;;0CAEf,KAACC;gCAAET,WAAWxB,OAAOkC,IAAI;0CAAGhC;;;;;;YAIjCC;;;AAQP"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SingleLinePlugin.d.ts","sourceRoot":"","sources":["../../../src/components/input/SingleLinePlugin.tsx"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,SA2B/B"}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/input/SingleLinePlugin.tsx"],"sourcesContent":["import {\n COMMAND_PRIORITY_HIGH,\n INSERT_LINE_BREAK_COMMAND,\n INSERT_PARAGRAPH_COMMAND,\n LineBreakNode,\n} from '@payloadcms/richtext-lexical/lexical';\nimport { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext';\nimport { useEffect } from 'react';\n\nexport function SingleLinePlugin() {\n const [editor] = useLexicalComposerContext();\n useEffect(() => {\n const unregisterLineBreak = editor.registerCommand(\n INSERT_LINE_BREAK_COMMAND,\n () => true,\n COMMAND_PRIORITY_HIGH,\n );\n const unregisterParagraph = editor.registerCommand(\n INSERT_PARAGRAPH_COMMAND,\n () => true,\n COMMAND_PRIORITY_HIGH,\n );\n // Catch line breaks inserted via paste or other means\n const unregisterTransform = editor.registerNodeTransform(\n LineBreakNode,\n (node) => {\n node.remove();\n },\n );\n return () => {\n unregisterLineBreak();\n unregisterParagraph();\n unregisterTransform();\n };\n }, [editor]);\n return null;\n}\n"],"names":["COMMAND_PRIORITY_HIGH","INSERT_LINE_BREAK_COMMAND","INSERT_PARAGRAPH_COMMAND","LineBreakNode","useLexicalComposerContext","useEffect","SingleLinePlugin","editor","unregisterLineBreak","registerCommand","unregisterParagraph","unregisterTransform","registerNodeTransform","node","remove"],"mappings":"AAAA,SACEA,qBAAqB,EACrBC,yBAAyB,EACzBC,wBAAwB,EACxBC,aAAa,QACR,uCAAuC;AAC9C,SAASC,yBAAyB,QAAQ,oEAAoE;AAC9G,SAASC,SAAS,QAAQ,QAAQ;AAElC,OAAO,SAASC;IACd,MAAM,CAACC,OAAO,GAAGH;IACjBC,UAAU;QACR,MAAMG,sBAAsBD,OAAOE,eAAe,CAChDR,2BACA,IAAM,MACND;QAEF,MAAMU,sBAAsBH,OAAOE,eAAe,CAChDP,0BACA,IAAM,MACNF;QAEF,sDAAsD;QACtD,MAAMW,sBAAsBJ,OAAOK,qBAAqB,CACtDT,eACA,CAACU;YACCA,KAAKC,MAAM;QACb;QAEF,OAAO;YACLN;YACAE;YACAC;QACF;IACF,GAAG;QAACJ;KAAO;IACX,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"useHtmlLexicalAdapter.d.ts","sourceRoot":"","sources":["../../../src/components/hooks/useHtmlLexicalAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAUtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAWlF,UAAU,0BAA0B;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,QAAQ,GACT,EAAE,0BAA0B;WAiEF,gBAAgB,CAAC,gBAAgB,CAAC;gCAjBvC,qBAAqB;EAkB1C"}
1
+ {"version":3,"file":"useHtmlLexicalAdapter.d.ts","sourceRoot":"","sources":["../../../src/components/input/useHtmlLexicalAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAUtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAWlF,UAAU,0BAA0B;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,QAAQ,GACT,EAAE,0BAA0B;WAiEF,gBAAgB,CAAC,gBAAgB,CAAC;gCAjBvC,qBAAqB;EAkB1C"}
@@ -1 +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"}
1
+ {"version":3,"sources":["../../../src/components/input/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"}
@@ -1,4 +1,4 @@
1
- import type { TemplateVariable } from '../types';
1
+ import type { TemplateVariable } from '../../types';
2
2
  export declare const toWords: (inputString: string, joinWords?: boolean) => string;
3
3
  export declare const formatVariableLabel: (variable: TemplateVariable) => string;
4
- //# sourceMappingURL=format.d.ts.map
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/input/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,OAAO,gBAAiB,MAAM,0BAAsB,MAkBhE,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAAc,gBAAgB,WAK7D,CAAC"}
@@ -1,4 +1,4 @@
1
- import { isTagElement } from './guards';
1
+ import { isTagElement } from '../../icu';
2
2
  export const toWords = (inputString, joinWords = false)=>{
3
3
  const capitalizeFirstLetter = (string)=>string.charAt(0).toUpperCase() + string.slice(1);
4
4
  const notNullString = inputString || '';
@@ -20,4 +20,4 @@ export const formatVariableLabel = (variable)=>{
20
20
  return variable.value;
21
21
  };
22
22
 
23
- //# sourceMappingURL=format.js.map
23
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/input/utils.ts"],"sourcesContent":["import { isTagElement } from '@/icu';\nimport type { TemplateVariable } from '@/types';\n\nexport const toWords = (inputString: string, joinWords = false): string => {\n const capitalizeFirstLetter = (string: string): string =>\n string.charAt(0).toUpperCase() + string.slice(1);\n const notNullString = inputString || '';\n const trimmedString = notNullString.trim();\n const arrayOfStrings = trimmedString.split(/[\\s-]/);\n\n const splitStringsArray: string[] = [];\n arrayOfStrings.forEach((tempString) => {\n if (tempString !== '') {\n const splitWords = tempString.split(/(?=[A-Z])/).join(' ');\n splitStringsArray.push(capitalizeFirstLetter(splitWords));\n }\n });\n\n return joinWords\n ? splitStringsArray.join('').replace(/\\s/g, '')\n : splitStringsArray.join(' ');\n};\n\nexport const formatVariableLabel = (variable: TemplateVariable) => {\n if (isTagElement(variable)) {\n return `<${variable.value}/>`;\n }\n return variable.value;\n};\n"],"names":["isTagElement","toWords","inputString","joinWords","capitalizeFirstLetter","string","charAt","toUpperCase","slice","notNullString","trimmedString","trim","arrayOfStrings","split","splitStringsArray","forEach","tempString","splitWords","join","push","replace","formatVariableLabel","variable","value"],"mappings":"AAAA,SAASA,YAAY,QAAQ,QAAQ;AAGrC,OAAO,MAAMC,UAAU,CAACC,aAAqBC,YAAY,KAAK;IAC5D,MAAMC,wBAAwB,CAACC,SAC7BA,OAAOC,MAAM,CAAC,GAAGC,WAAW,KAAKF,OAAOG,KAAK,CAAC;IAChD,MAAMC,gBAAgBP,eAAe;IACrC,MAAMQ,gBAAgBD,cAAcE,IAAI;IACxC,MAAMC,iBAAiBF,cAAcG,KAAK,CAAC;IAE3C,MAAMC,oBAA8B,EAAE;IACtCF,eAAeG,OAAO,CAAC,CAACC;QACtB,IAAIA,eAAe,IAAI;YACrB,MAAMC,aAAaD,WAAWH,KAAK,CAAC,aAAaK,IAAI,CAAC;YACtDJ,kBAAkBK,IAAI,CAACf,sBAAsBa;QAC/C;IACF;IAEA,OAAOd,YACHW,kBAAkBI,IAAI,CAAC,IAAIE,OAAO,CAAC,OAAO,MAC1CN,kBAAkBI,IAAI,CAAC;AAC7B,EAAE;AAEF,OAAO,MAAMG,sBAAsB,CAACC;IAClC,IAAItB,aAAasB,WAAW;QAC1B,OAAO,CAAC,CAAC,EAAEA,SAASC,KAAK,CAAC,EAAE,CAAC;IAC/B;IACA,OAAOD,SAASC,KAAK;AACvB,EAAE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariableChip.d.ts","sourceRoot":"","sources":["../../../../src/components/input/variables/VariableChip.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAwBpE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,iBAAiB,2CAqE5E"}
@@ -5,8 +5,7 @@ import { $getNodeByKey } from '@payloadcms/richtext-lexical/lexical';
5
5
  import { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext';
6
6
  import clsx from 'clsx';
7
7
  import { useMemo } from 'react';
8
- import { isArgumentElement, isNumericElement, isSelectElement, isTagElement, isTemporalElement } from '../../../utils/guards';
9
- import { parseICUMessage } from '../../../utils/icu-tranform';
8
+ import { isArgumentElement, isNumericElement, isSelectElement, isTagElement, isTemporalElement, parseICUMessage } from '../../../icu';
10
9
  import { SelectVariableEditor } from './editors/SelectVariableEditor';
11
10
  import { TagVariableEditor } from './editors/TagVariableEditor';
12
11
  import { NumericVariableEditor } from './pickers/NumericVariableEditor';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/input/variables/VariableChip.tsx"],"sourcesContent":["'use client';\n\nimport { Popover } from '@base-ui/react/popover';\nimport type { NodeKey } from '@payloadcms/richtext-lexical/lexical';\nimport { $getNodeByKey } from '@payloadcms/richtext-lexical/lexical';\nimport { useLexicalComposerContext } from '@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext';\nimport clsx from 'clsx';\nimport type { BeautifulMentionNode } from 'lexical-beautiful-mentions';\nimport { useMemo } from 'react';\n\nimport {\n isArgumentElement,\n isNumericElement,\n isSelectElement,\n isTagElement,\n isTemporalElement,\n parseICUMessage,\n} from '@/icu';\n\nimport { SelectVariableEditor } from './editors/SelectVariableEditor';\nimport { TagVariableEditor } from './editors/TagVariableEditor';\nimport { NumericVariableEditor } from './pickers/NumericVariableEditor';\nimport { TemporalVariablePicker } from './pickers/TemporalVariablePicker';\nimport styles from './VariableChip.module.css';\n\nconst TEMPORAL_ELEMENTS_FLAG = false;\n\nexport interface VariableChipProps {\n name: string;\n label: string;\n icu: string;\n nodeKey: NodeKey;\n}\n\n// TODO replace popover with portal below input field\n\nexport function VariableChip({ name, label, icu, nodeKey }: VariableChipProps) {\n const [editor] = useLexicalComposerContext();\n\n const handleUpdate = (value: string) => {\n editor.update(() => {\n const node = $getNodeByKey(nodeKey) as BeautifulMentionNode | null;\n if (node) {\n node.setData({ ...node.getData(), icu: value });\n }\n });\n };\n\n const element = useMemo(() => {\n try {\n const [part] = parseICUMessage(icu);\n if (!part) throw new Error('No part found');\n return part;\n } catch (error) {\n console.error(error);\n throw new Error(`Invalid ICU: ${icu}`, { cause: error });\n }\n }, [icu]);\n\n const isDisabled =\n isArgumentElement(element) ||\n (isTemporalElement(element) && !TEMPORAL_ELEMENTS_FLAG);\n\n return (\n <Popover.Root>\n <Popover.Trigger\n render={\n <button\n className={clsx(styles.chip, isDisabled && styles.chipDisabled)}\n data-icu={icu}\n data-variable={name}\n type=\"button\"\n />\n }\n >\n {/* <VariableIcon type={element.type} className=\"size-4\" /> */}\n {label}\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Positioner align=\"start\" side=\"bottom\" sideOffset={5}>\n <Popover.Popup className={styles.popoverContent}>\n {isNumericElement(element) && (\n <NumericVariableEditor\n element={element}\n onUpdate={handleUpdate}\n />\n )}\n {isSelectElement(element) && (\n <SelectVariableEditor element={element} onUpdate={handleUpdate} />\n )}\n {TEMPORAL_ELEMENTS_FLAG && isTemporalElement(element) && (\n <TemporalVariablePicker\n element={element}\n onUpdate={handleUpdate}\n />\n )}\n\n {isTagElement(element) && (\n <TagVariableEditor element={element} onUpdate={handleUpdate} />\n )}\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n"],"names":["Popover","$getNodeByKey","useLexicalComposerContext","clsx","useMemo","isArgumentElement","isNumericElement","isSelectElement","isTagElement","isTemporalElement","parseICUMessage","SelectVariableEditor","TagVariableEditor","NumericVariableEditor","TemporalVariablePicker","styles","TEMPORAL_ELEMENTS_FLAG","VariableChip","name","label","icu","nodeKey","editor","handleUpdate","value","update","node","setData","getData","element","part","Error","error","console","cause","isDisabled","Root","Trigger","render","button","className","chip","chipDisabled","data-icu","data-variable","type","Portal","Positioner","align","side","sideOffset","Popup","popoverContent","onUpdate"],"mappings":"AAAA;;AAEA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,SAASC,aAAa,QAAQ,uCAAuC;AACrE,SAASC,yBAAyB,QAAQ,oEAAoE;AAC9G,OAAOC,UAAU,OAAO;AAExB,SAASC,OAAO,QAAQ,QAAQ;AAEhC,SACEC,iBAAiB,EACjBC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,EACZC,iBAAiB,EACjBC,eAAe,QACV,QAAQ;AAEf,SAASC,oBAAoB,QAAQ,iCAAiC;AACtE,SAASC,iBAAiB,QAAQ,8BAA8B;AAChE,SAASC,qBAAqB,QAAQ,kCAAkC;AACxE,SAASC,sBAAsB,QAAQ,mCAAmC;AAC1E,OAAOC,YAAY,4BAA4B;AAE/C,MAAMC,yBAAyB;AAS/B,qDAAqD;AAErD,OAAO,SAASC,aAAa,EAAEC,IAAI,EAAEC,KAAK,EAAEC,GAAG,EAAEC,OAAO,EAAqB;IAC3E,MAAM,CAACC,OAAO,GAAGpB;IAEjB,MAAMqB,eAAe,CAACC;QACpBF,OAAOG,MAAM,CAAC;YACZ,MAAMC,OAAOzB,cAAcoB;YAC3B,IAAIK,MAAM;gBACRA,KAAKC,OAAO,CAAC;oBAAE,GAAGD,KAAKE,OAAO,EAAE;oBAAER,KAAKI;gBAAM;YAC/C;QACF;IACF;IAEA,MAAMK,UAAUzB,QAAQ;QACtB,IAAI;YACF,MAAM,CAAC0B,KAAK,GAAGpB,gBAAgBU;YAC/B,IAAI,CAACU,MAAM,MAAM,IAAIC,MAAM;YAC3B,OAAOD;QACT,EAAE,OAAOE,OAAO;YACdC,QAAQD,KAAK,CAACA;YACd,MAAM,IAAID,MAAM,CAAC,aAAa,EAAEX,KAAK,EAAE;gBAAEc,OAAOF;YAAM;QACxD;IACF,GAAG;QAACZ;KAAI;IAER,MAAMe,aACJ9B,kBAAkBwB,YACjBpB,kBAAkBoB,YAAY,CAACb;IAElC,qBACE,MAAChB,QAAQoC,IAAI;;0BACX,KAACpC,QAAQqC,OAAO;gBACdC,sBACE,KAACC;oBACCC,WAAWrC,KAAKY,OAAO0B,IAAI,EAAEN,cAAcpB,OAAO2B,YAAY;oBAC9DC,YAAUvB;oBACVwB,iBAAe1B;oBACf2B,MAAK;;0BAKR1B;;0BAEH,KAACnB,QAAQ8C,MAAM;0BACb,cAAA,KAAC9C,QAAQ+C,UAAU;oBAACC,OAAM;oBAAQC,MAAK;oBAASC,YAAY;8BAC1D,cAAA,MAAClD,QAAQmD,KAAK;wBAACX,WAAWzB,OAAOqC,cAAc;;4BAC5C9C,iBAAiBuB,0BAChB,KAAChB;gCACCgB,SAASA;gCACTwB,UAAU9B;;4BAGbhB,gBAAgBsB,0BACf,KAAClB;gCAAqBkB,SAASA;gCAASwB,UAAU9B;;4BAEnDP,0BAA0BP,kBAAkBoB,0BAC3C,KAACf;gCACCe,SAASA;gCACTwB,UAAU9B;;4BAIbf,aAAaqB,0BACZ,KAACjB;gCAAkBiB,SAASA;gCAASwB,UAAU9B;;;;;;;;AAO7D"}