@byline/richtext-lexical 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (655) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +18 -0
  3. package/dist/field/apply-value-plugin.d.ts +10 -0
  4. package/dist/field/apply-value-plugin.d.ts.map +1 -0
  5. package/dist/field/apply-value-plugin.js +60 -0
  6. package/dist/field/config/default.d.ts +6 -0
  7. package/dist/field/config/default.d.ts.map +1 -0
  8. package/dist/field/config/default.js +53 -0
  9. package/dist/field/config/editor-config-context.d.ts +14 -0
  10. package/dist/field/config/editor-config-context.d.ts.map +1 -0
  11. package/dist/field/config/editor-config-context.js +51 -0
  12. package/dist/field/config/types.d.ts +28 -0
  13. package/dist/field/config/types.d.ts.map +1 -0
  14. package/dist/field/config/types.js +1 -0
  15. package/dist/field/constants.d.ts +2 -0
  16. package/dist/field/constants.d.ts.map +1 -0
  17. package/dist/field/constants.js +2 -0
  18. package/dist/field/content-editable-inline.d.ts +13 -0
  19. package/dist/field/content-editable-inline.d.ts.map +1 -0
  20. package/dist/field/content-editable-inline.js +11 -0
  21. package/dist/field/content-editable.css +23 -0
  22. package/dist/field/content-editable.d.ts +13 -0
  23. package/dist/field/content-editable.d.ts.map +1 -0
  24. package/dist/field/content-editable.js +14 -0
  25. package/dist/field/context/shared-autocomplete-context.js +44 -0
  26. package/dist/field/context/shared-history-context.d.ts +19 -0
  27. package/dist/field/context/shared-history-context.d.ts.map +1 -0
  28. package/dist/field/context/shared-history-context.js +16 -0
  29. package/dist/field/context/shared-on-change-context.d.ts +13 -0
  30. package/dist/field/context/shared-on-change-context.d.ts.map +1 -0
  31. package/dist/field/context/shared-on-change-context.js +21 -0
  32. package/dist/field/debug.d.ts +10 -0
  33. package/dist/field/debug.d.ts.map +1 -0
  34. package/dist/field/debug.js +30 -0
  35. package/dist/field/editor-component.css +33 -0
  36. package/dist/field/editor-component.d.ts +13 -0
  37. package/dist/field/editor-component.d.ts.map +1 -0
  38. package/dist/field/editor-component.js +115 -0
  39. package/dist/field/editor-context.d.ts +23 -0
  40. package/dist/field/editor-context.d.ts.map +1 -0
  41. package/dist/field/editor-context.js +57 -0
  42. package/dist/field/editor-field.d.ts +34 -0
  43. package/dist/field/editor-field.d.ts.map +1 -0
  44. package/dist/field/editor-field.js +18 -0
  45. package/dist/field/editor.css +1449 -0
  46. package/dist/field/editor.d.ts +14 -0
  47. package/dist/field/editor.d.ts.map +1 -0
  48. package/dist/field/editor.js +190 -0
  49. package/dist/field/hooks/use-modal.d.ts +13 -0
  50. package/dist/field/hooks/use-modal.d.ts.map +1 -0
  51. package/dist/field/hooks/use-modal.js +37 -0
  52. package/dist/field/hooks/use-report.js +39 -0
  53. package/dist/field/lexical-populate-shared.d.ts +97 -0
  54. package/dist/field/lexical-populate-shared.d.ts.map +1 -0
  55. package/dist/field/lexical-populate-shared.js +60 -0
  56. package/dist/field/nodes/admonition-node/admonition-node-component.css +119 -0
  57. package/dist/field/nodes/admonition-node/admonition-node-component.d.ts +18 -0
  58. package/dist/field/nodes/admonition-node/admonition-node-component.d.ts.map +1 -0
  59. package/dist/field/nodes/admonition-node/admonition-node-component.js +190 -0
  60. package/dist/field/nodes/admonition-node/admonition-node.d.ts +35 -0
  61. package/dist/field/nodes/admonition-node/admonition-node.d.ts.map +1 -0
  62. package/dist/field/nodes/admonition-node/admonition-node.js +129 -0
  63. package/dist/field/nodes/admonition-node/icons/danger-icon.css +12 -0
  64. package/dist/field/nodes/admonition-node/icons/danger-icon.d.ts +8 -0
  65. package/dist/field/nodes/admonition-node/icons/danger-icon.d.ts.map +1 -0
  66. package/dist/field/nodes/admonition-node/icons/danger-icon.js +18 -0
  67. package/dist/field/nodes/admonition-node/icons/index.d.ts +5 -0
  68. package/dist/field/nodes/admonition-node/icons/index.d.ts.map +1 -0
  69. package/dist/field/nodes/admonition-node/icons/index.js +4 -0
  70. package/dist/field/nodes/admonition-node/icons/note-icon.css +12 -0
  71. package/dist/field/nodes/admonition-node/icons/note-icon.d.ts +8 -0
  72. package/dist/field/nodes/admonition-node/icons/note-icon.d.ts.map +1 -0
  73. package/dist/field/nodes/admonition-node/icons/note-icon.js +18 -0
  74. package/dist/field/nodes/admonition-node/icons/tip-icon.css +12 -0
  75. package/dist/field/nodes/admonition-node/icons/tip-icon.d.ts +8 -0
  76. package/dist/field/nodes/admonition-node/icons/tip-icon.d.ts.map +1 -0
  77. package/dist/field/nodes/admonition-node/icons/tip-icon.js +18 -0
  78. package/dist/field/nodes/admonition-node/icons/warning-icon.css +12 -0
  79. package/dist/field/nodes/admonition-node/icons/warning-icon.d.ts +8 -0
  80. package/dist/field/nodes/admonition-node/icons/warning-icon.d.ts.map +1 -0
  81. package/dist/field/nodes/admonition-node/icons/warning-icon.js +18 -0
  82. package/dist/field/nodes/admonition-node/index.d.ts +10 -0
  83. package/dist/field/nodes/admonition-node/index.d.ts.map +1 -0
  84. package/dist/field/nodes/admonition-node/index.js +2 -0
  85. package/dist/field/nodes/admonition-node/types.d.ts +21 -0
  86. package/dist/field/nodes/admonition-node/types.d.ts.map +1 -0
  87. package/dist/field/nodes/admonition-node/types.js +1 -0
  88. package/dist/field/nodes/document-relation.d.ts +33 -0
  89. package/dist/field/nodes/document-relation.d.ts.map +1 -0
  90. package/dist/field/nodes/document-relation.js +1 -0
  91. package/dist/field/nodes/index.d.ts +10 -0
  92. package/dist/field/nodes/index.d.ts.map +1 -0
  93. package/dist/field/nodes/index.js +37 -0
  94. package/dist/field/nodes/inline-image-node/index.d.ts +10 -0
  95. package/dist/field/nodes/inline-image-node/index.d.ts.map +1 -0
  96. package/dist/field/nodes/inline-image-node/index.js +2 -0
  97. package/dist/field/nodes/inline-image-node/inline-image-node-component.css +204 -0
  98. package/dist/field/nodes/inline-image-node/inline-image-node-component.d.ts +24 -0
  99. package/dist/field/nodes/inline-image-node/inline-image-node-component.d.ts.map +1 -0
  100. package/dist/field/nodes/inline-image-node/inline-image-node-component.js +221 -0
  101. package/dist/field/nodes/inline-image-node/inline-image-node.d.ts +45 -0
  102. package/dist/field/nodes/inline-image-node/inline-image-node.d.ts.map +1 -0
  103. package/dist/field/nodes/inline-image-node/inline-image-node.js +187 -0
  104. package/dist/field/nodes/inline-image-node/types.d.ts +30 -0
  105. package/dist/field/nodes/inline-image-node/types.d.ts.map +1 -0
  106. package/dist/field/nodes/inline-image-node/types.js +1 -0
  107. package/dist/field/nodes/layout-container-node/layout-container-node.d.ts +29 -0
  108. package/dist/field/nodes/layout-container-node/layout-container-node.d.ts.map +1 -0
  109. package/dist/field/nodes/layout-container-node/layout-container-node.js +54 -0
  110. package/dist/field/nodes/layout-container-node/layout-item-node.d.ts +23 -0
  111. package/dist/field/nodes/layout-container-node/layout-item-node.d.ts.map +1 -0
  112. package/dist/field/nodes/layout-container-node/layout-item-node.js +41 -0
  113. package/dist/field/nodes/link-nodes/auto-link-node.d.ts +17 -0
  114. package/dist/field/nodes/link-nodes/auto-link-node.d.ts.map +1 -0
  115. package/dist/field/nodes/link-nodes/auto-link-node.js +52 -0
  116. package/dist/field/nodes/link-nodes/index.d.ts +4 -0
  117. package/dist/field/nodes/link-nodes/index.d.ts.map +1 -0
  118. package/dist/field/nodes/link-nodes/index.js +3 -0
  119. package/dist/field/nodes/link-nodes/link-node.d.ts +49 -0
  120. package/dist/field/nodes/link-nodes/link-node.d.ts.map +1 -0
  121. package/dist/field/nodes/link-nodes/link-node.js +253 -0
  122. package/dist/field/nodes/link-nodes/types.d.ts +26 -0
  123. package/dist/field/nodes/link-nodes/types.d.ts.map +1 -0
  124. package/dist/field/nodes/link-nodes/types.js +1 -0
  125. package/dist/field/nodes/vimeo-node/index.d.ts +30 -0
  126. package/dist/field/nodes/vimeo-node/index.d.ts.map +1 -0
  127. package/dist/field/nodes/vimeo-node/index.js +109 -0
  128. package/dist/field/nodes/youtube-node/index.d.ts +30 -0
  129. package/dist/field/nodes/youtube-node/index.d.ts.map +1 -0
  130. package/dist/field/nodes/youtube-node/index.js +110 -0
  131. package/dist/field/plugins/admonition-plugin/admonition-modal.css +26 -0
  132. package/dist/field/plugins/admonition-plugin/admonition-modal.d.ts +12 -0
  133. package/dist/field/plugins/admonition-plugin/admonition-modal.d.ts.map +1 -0
  134. package/dist/field/plugins/admonition-plugin/admonition-modal.js +165 -0
  135. package/dist/field/plugins/admonition-plugin/fields.d.ts +21 -0
  136. package/dist/field/plugins/admonition-plugin/fields.d.ts.map +1 -0
  137. package/dist/field/plugins/admonition-plugin/fields.js +55 -0
  138. package/dist/field/plugins/admonition-plugin/index.d.ts +15 -0
  139. package/dist/field/plugins/admonition-plugin/index.d.ts.map +1 -0
  140. package/dist/field/plugins/admonition-plugin/index.js +54 -0
  141. package/dist/field/plugins/admonition-plugin/types.d.ts +34 -0
  142. package/dist/field/plugins/admonition-plugin/types.d.ts.map +1 -0
  143. package/dist/field/plugins/admonition-plugin/types.js +1 -0
  144. package/dist/field/plugins/auto-embed-plugin/auto-embed-modal.css +16 -0
  145. package/dist/field/plugins/auto-embed-plugin/auto-embed-modal.d.ts +8 -0
  146. package/dist/field/plugins/auto-embed-plugin/auto-embed-modal.d.ts.map +1 -0
  147. package/dist/field/plugins/auto-embed-plugin/auto-embed-modal.js +105 -0
  148. package/dist/field/plugins/auto-embed-plugin/index.d.ts +21 -0
  149. package/dist/field/plugins/auto-embed-plugin/index.d.ts.map +1 -0
  150. package/dist/field/plugins/auto-embed-plugin/index.js +152 -0
  151. package/dist/field/plugins/code-highlight-plugin/index.d.ts +10 -0
  152. package/dist/field/plugins/code-highlight-plugin/index.d.ts.map +1 -0
  153. package/dist/field/plugins/code-highlight-plugin/index.js +11 -0
  154. package/dist/field/plugins/drag-drop-paste-plugin/index.js +1 -0
  155. package/dist/field/plugins/floating-text-format-toolbar-plugin/index.css +148 -0
  156. package/dist/field/plugins/floating-text-format-toolbar-plugin/index.d.ts +13 -0
  157. package/dist/field/plugins/floating-text-format-toolbar-plugin/index.d.ts.map +1 -0
  158. package/dist/field/plugins/floating-text-format-toolbar-plugin/index.js +279 -0
  159. package/dist/field/plugins/inline-image-plugin/fields.d.ts +12 -0
  160. package/dist/field/plugins/inline-image-plugin/fields.d.ts.map +1 -0
  161. package/dist/field/plugins/inline-image-plugin/fields.js +22 -0
  162. package/dist/field/plugins/inline-image-plugin/index.d.ts +34 -0
  163. package/dist/field/plugins/inline-image-plugin/index.d.ts.map +1 -0
  164. package/dist/field/plugins/inline-image-plugin/index.js +107 -0
  165. package/dist/field/plugins/inline-image-plugin/inline-image-modal.css +25 -0
  166. package/dist/field/plugins/inline-image-plugin/inline-image-modal.d.ts +11 -0
  167. package/dist/field/plugins/inline-image-plugin/inline-image-modal.d.ts.map +1 -0
  168. package/dist/field/plugins/inline-image-plugin/inline-image-modal.js +271 -0
  169. package/dist/field/plugins/inline-image-plugin/populate.d.ts +10 -0
  170. package/dist/field/plugins/inline-image-plugin/populate.d.ts.map +1 -0
  171. package/dist/field/plugins/inline-image-plugin/populate.js +28 -0
  172. package/dist/field/plugins/inline-image-plugin/types.d.ts +37 -0
  173. package/dist/field/plugins/inline-image-plugin/types.d.ts.map +1 -0
  174. package/dist/field/plugins/inline-image-plugin/types.js +1 -0
  175. package/dist/field/plugins/inline-image-plugin/utils.d.ts +42 -0
  176. package/dist/field/plugins/inline-image-plugin/utils.d.ts.map +1 -0
  177. package/dist/field/plugins/inline-image-plugin/utils.js +46 -0
  178. package/dist/field/plugins/layout-plugin/insert-layout-modal.css +20 -0
  179. package/dist/field/plugins/layout-plugin/insert-layout-modal.d.ts +22 -0
  180. package/dist/field/plugins/layout-plugin/insert-layout-modal.d.ts.map +1 -0
  181. package/dist/field/plugins/layout-plugin/insert-layout-modal.js +97 -0
  182. package/dist/field/plugins/layout-plugin/layout-plugin.d.ts +10 -0
  183. package/dist/field/plugins/layout-plugin/layout-plugin.d.ts.map +1 -0
  184. package/dist/field/plugins/layout-plugin/layout-plugin.js +81 -0
  185. package/dist/field/plugins/link-plugin/auto-link/auto-link-plugin.d.ts +22 -0
  186. package/dist/field/plugins/link-plugin/auto-link/auto-link-plugin.d.ts.map +1 -0
  187. package/dist/field/plugins/link-plugin/auto-link/auto-link-plugin.js +185 -0
  188. package/dist/field/plugins/link-plugin/auto-link/index.d.ts +10 -0
  189. package/dist/field/plugins/link-plugin/auto-link/index.d.ts.map +1 -0
  190. package/dist/field/plugins/link-plugin/auto-link/index.js +15 -0
  191. package/dist/field/plugins/link-plugin/link/floating-link-editor.css +124 -0
  192. package/dist/field/plugins/link-plugin/link/floating-link-editor.d.ts +15 -0
  193. package/dist/field/plugins/link-plugin/link/floating-link-editor.d.ts.map +1 -0
  194. package/dist/field/plugins/link-plugin/link/floating-link-editor.js +234 -0
  195. package/dist/field/plugins/link-plugin/link/index.d.ts +2 -0
  196. package/dist/field/plugins/link-plugin/link/index.d.ts.map +1 -0
  197. package/dist/field/plugins/link-plugin/link/index.js +43 -0
  198. package/dist/field/plugins/link-plugin/link/link-modal.d.ts +11 -0
  199. package/dist/field/plugins/link-plugin/link/link-modal.d.ts.map +1 -0
  200. package/dist/field/plugins/link-plugin/link/link-modal.js +311 -0
  201. package/dist/field/plugins/link-plugin/link/types.d.ts +19 -0
  202. package/dist/field/plugins/link-plugin/link/types.d.ts.map +1 -0
  203. package/dist/field/plugins/link-plugin/link/types.js +1 -0
  204. package/dist/field/plugins/link-plugin/populate.d.ts +22 -0
  205. package/dist/field/plugins/link-plugin/populate.d.ts.map +1 -0
  206. package/dist/field/plugins/link-plugin/populate.js +28 -0
  207. package/dist/field/plugins/table-action-menu-plugin/index.d.ts +6 -0
  208. package/dist/field/plugins/table-action-menu-plugin/index.d.ts.map +1 -0
  209. package/dist/field/plugins/table-action-menu-plugin/index.js +598 -0
  210. package/dist/field/plugins/table-plugin/index.d.ts +4 -0
  211. package/dist/field/plugins/table-plugin/index.d.ts.map +1 -0
  212. package/dist/field/plugins/table-plugin/index.js +26 -0
  213. package/dist/field/plugins/table-plugin/table-modal.css +20 -0
  214. package/dist/field/plugins/table-plugin/table-modal.d.ts +21 -0
  215. package/dist/field/plugins/table-plugin/table-modal.d.ts.map +1 -0
  216. package/dist/field/plugins/table-plugin/table-modal.js +111 -0
  217. package/dist/field/plugins/toolbar-plugin/index.d.ts +17 -0
  218. package/dist/field/plugins/toolbar-plugin/index.d.ts.map +1 -0
  219. package/dist/field/plugins/toolbar-plugin/index.js +837 -0
  220. package/dist/field/plugins/treeview-plugin/index.d.ts +10 -0
  221. package/dist/field/plugins/treeview-plugin/index.d.ts.map +1 -0
  222. package/dist/field/plugins/treeview-plugin/index.js +17 -0
  223. package/dist/field/plugins/vimeo-plugin/index.d.ts +4 -0
  224. package/dist/field/plugins/vimeo-plugin/index.d.ts.map +1 -0
  225. package/dist/field/plugins/vimeo-plugin/index.js +24 -0
  226. package/dist/field/plugins/youtube-plugin/index.d.ts +4 -0
  227. package/dist/field/plugins/youtube-plugin/index.d.ts.map +1 -0
  228. package/dist/field/plugins/youtube-plugin/index.js +24 -0
  229. package/dist/field/shared/canUseDOM.d.ts +9 -0
  230. package/dist/field/shared/canUseDOM.d.ts.map +1 -0
  231. package/dist/field/shared/canUseDOM.js +2 -0
  232. package/dist/field/shared/environment.d.ts +23 -0
  233. package/dist/field/shared/environment.d.ts.map +1 -0
  234. package/dist/field/shared/environment.js +10 -0
  235. package/dist/field/shared/invariant.d.ts +9 -0
  236. package/dist/field/shared/invariant.d.ts.map +1 -0
  237. package/dist/field/shared/invariant.js +6 -0
  238. package/dist/field/shared/simpleDiffWithCursor.js +15 -0
  239. package/dist/field/shared/useLayoutEffect.js +5 -0
  240. package/dist/field/shared/useModalFormState.d.ts +23 -0
  241. package/dist/field/shared/useModalFormState.d.ts.map +1 -0
  242. package/dist/field/shared/useModalFormState.js +23 -0
  243. package/dist/field/shared/warnOnlyOnce.js +9 -0
  244. package/dist/field/themes/lexical-editor-theme.css +537 -0
  245. package/dist/field/themes/lexical-editor-theme.d.ts +10 -0
  246. package/dist/field/themes/lexical-editor-theme.d.ts.map +1 -0
  247. package/dist/field/themes/lexical-editor-theme.js +105 -0
  248. package/dist/field/toolbar-extensions.d.ts +32 -0
  249. package/dist/field/toolbar-extensions.d.ts.map +1 -0
  250. package/dist/field/toolbar-extensions.js +56 -0
  251. package/dist/field/types.js +1 -0
  252. package/dist/field/ui/button.css +31 -0
  253. package/dist/field/ui/button.js +19 -0
  254. package/dist/field/ui/checkbox.css +46 -0
  255. package/dist/field/ui/color-picker.css +75 -0
  256. package/dist/field/ui/color-picker.d.ts +21 -0
  257. package/dist/field/ui/color-picker.d.ts.map +1 -0
  258. package/dist/field/ui/color-picker.js +360 -0
  259. package/dist/field/ui/dialog.css +18 -0
  260. package/dist/field/ui/dialog.js +17 -0
  261. package/dist/field/ui/dropdown.d.ts +25 -0
  262. package/dist/field/ui/dropdown.d.ts.map +1 -0
  263. package/dist/field/ui/dropdown.js +150 -0
  264. package/dist/field/ui/file-input.js +27 -0
  265. package/dist/field/ui/input.css +23 -0
  266. package/dist/field/ui/modal.css +73 -0
  267. package/dist/field/ui/modal.d.ts +17 -0
  268. package/dist/field/ui/modal.d.ts.map +1 -0
  269. package/dist/field/ui/modal.js +69 -0
  270. package/dist/field/ui/placeholder-inline.d.ts +14 -0
  271. package/dist/field/ui/placeholder-inline.d.ts.map +1 -0
  272. package/dist/field/ui/placeholder-inline.js +12 -0
  273. package/dist/field/ui/placeholder.css +26 -0
  274. package/dist/field/ui/placeholder.d.ts +14 -0
  275. package/dist/field/ui/placeholder.d.ts.map +1 -0
  276. package/dist/field/ui/placeholder.js +14 -0
  277. package/dist/field/ui/select.css +32 -0
  278. package/dist/field/ui/select.js +28 -0
  279. package/dist/field/ui/switch.js +25 -0
  280. package/dist/field/ui/text-area.css +31 -0
  281. package/dist/field/ui/text-area.js +28 -0
  282. package/dist/field/ui/text-input.d.ts +20 -0
  283. package/dist/field/ui/text-input.d.ts.map +1 -0
  284. package/dist/field/ui/text-input.js +29 -0
  285. package/dist/field/utils/cloneDeep.js +26 -0
  286. package/dist/field/utils/deepEqual.js +19 -0
  287. package/dist/field/utils/emoji-list.js +21389 -0
  288. package/dist/field/utils/getDOMRangeRect.d.ts +9 -0
  289. package/dist/field/utils/getDOMRangeRect.d.ts.map +1 -0
  290. package/dist/field/utils/getDOMRangeRect.js +11 -0
  291. package/dist/field/utils/getSelectedNode.d.ts +3 -0
  292. package/dist/field/utils/getSelectedNode.d.ts.map +1 -0
  293. package/dist/field/utils/getSelectedNode.js +12 -0
  294. package/dist/field/utils/guard.js +4 -0
  295. package/dist/field/utils/hashSerializedState.d.ts +3 -0
  296. package/dist/field/utils/hashSerializedState.d.ts.map +1 -0
  297. package/dist/field/utils/hashSerializedState.js +22 -0
  298. package/dist/field/utils/isMobileWidth.js +1 -0
  299. package/dist/field/utils/joinClasses.js +4 -0
  300. package/dist/field/utils/point.js +34 -0
  301. package/dist/field/utils/rect.js +95 -0
  302. package/dist/field/utils/setFloatingElemPosition.d.ts +2 -0
  303. package/dist/field/utils/setFloatingElemPosition.d.ts.map +1 -0
  304. package/dist/field/utils/setFloatingElemPosition.js +22 -0
  305. package/dist/field/utils/setFloatingElemPositionForLinkEditor.d.ts +2 -0
  306. package/dist/field/utils/setFloatingElemPositionForLinkEditor.d.ts.map +1 -0
  307. package/dist/field/utils/setFloatingElemPositionForLinkEditor.js +22 -0
  308. package/dist/field/utils/swipe.js +77 -0
  309. package/dist/field/utils/url.d.ts +11 -0
  310. package/dist/field/utils/url.d.ts.map +1 -0
  311. package/dist/field/utils/url.js +30 -0
  312. package/dist/index.d.ts +12 -0
  313. package/dist/index.d.ts.map +1 -0
  314. package/dist/index.js +7 -0
  315. package/dist/lexical-editor.d.ts +41 -0
  316. package/dist/lexical-editor.d.ts.map +1 -0
  317. package/dist/lexical-editor.js +13 -0
  318. package/dist/richtext-field.d.ts +25 -0
  319. package/dist/richtext-field.d.ts.map +1 -0
  320. package/dist/richtext-field.js +62 -0
  321. package/dist/richtext-field.module.js +8 -0
  322. package/dist/richtext-field_module.css +18 -0
  323. package/dist/server.d.ts +64 -0
  324. package/dist/server.d.ts.map +1 -0
  325. package/dist/server.js +20 -0
  326. package/dist/static/svg/3-columns.svg +3 -0
  327. package/dist/static/svg/admonition.svg +1 -0
  328. package/dist/static/svg/ai.svg +5 -0
  329. package/dist/static/svg/arrow-clockwise.svg +1 -0
  330. package/dist/static/svg/arrow-counterclockwise.svg +1 -0
  331. package/dist/static/svg/bg-color.svg +1 -0
  332. package/dist/static/svg/camera.svg +1 -0
  333. package/dist/static/svg/caret-right-fill.svg +1 -0
  334. package/dist/static/svg/chat-square-quote.svg +1 -0
  335. package/dist/static/svg/chevron-down.svg +1 -0
  336. package/dist/static/svg/clipboard.svg +1 -0
  337. package/dist/static/svg/close.svg +1 -0
  338. package/dist/static/svg/code.svg +1 -0
  339. package/dist/static/svg/copy.svg +1 -0
  340. package/dist/static/svg/diagram-2.svg +1 -0
  341. package/dist/static/svg/download.svg +1 -0
  342. package/dist/static/svg/dropdown-more.svg +1 -0
  343. package/dist/static/svg/file-image.svg +1 -0
  344. package/dist/static/svg/filetype-gif.svg +1 -0
  345. package/dist/static/svg/font-color.svg +1 -0
  346. package/dist/static/svg/font-family.svg +1 -0
  347. package/dist/static/svg/gear.svg +1 -0
  348. package/dist/static/svg/horizontal-rule.svg +1 -0
  349. package/dist/static/svg/indent.svg +1 -0
  350. package/dist/static/svg/journal-code.svg +1 -0
  351. package/dist/static/svg/justify.svg +1 -0
  352. package/dist/static/svg/link.svg +1 -0
  353. package/dist/static/svg/list-ol.svg +1 -0
  354. package/dist/static/svg/list-ul.svg +1 -0
  355. package/dist/static/svg/lock-fill.svg +1 -0
  356. package/dist/static/svg/lock.svg +1 -0
  357. package/dist/static/svg/markdown.svg +1 -0
  358. package/dist/static/svg/mic.svg +1 -0
  359. package/dist/static/svg/outdent.svg +1 -0
  360. package/dist/static/svg/paint-bucket.svg +1 -0
  361. package/dist/static/svg/palette.svg +1 -0
  362. package/dist/static/svg/pencil-fill.svg +1 -0
  363. package/dist/static/svg/plug-fill.svg +1 -0
  364. package/dist/static/svg/plug.svg +1 -0
  365. package/dist/static/svg/plus.svg +1 -0
  366. package/dist/static/svg/prettier-error.svg +1 -0
  367. package/dist/static/svg/prettier.svg +1 -0
  368. package/dist/static/svg/square-check.svg +1 -0
  369. package/dist/static/svg/success.svg +1 -0
  370. package/dist/static/svg/table.svg +1 -0
  371. package/dist/static/svg/text-center.svg +1 -0
  372. package/dist/static/svg/text-left.svg +1 -0
  373. package/dist/static/svg/text-paragraph.svg +1 -0
  374. package/dist/static/svg/text-right.svg +1 -0
  375. package/dist/static/svg/trash.svg +1 -0
  376. package/dist/static/svg/type-bold.svg +1 -0
  377. package/dist/static/svg/type-h1.svg +1 -0
  378. package/dist/static/svg/type-h2.svg +1 -0
  379. package/dist/static/svg/type-h3.svg +1 -0
  380. package/dist/static/svg/type-h4.svg +1 -0
  381. package/dist/static/svg/type-h5.svg +1 -0
  382. package/dist/static/svg/type-h6.svg +1 -0
  383. package/dist/static/svg/type-italic.svg +1 -0
  384. package/dist/static/svg/type-strikethrough.svg +1 -0
  385. package/dist/static/svg/type-subscript.svg +1 -0
  386. package/dist/static/svg/type-superscript.svg +1 -0
  387. package/dist/static/svg/type-underline.svg +1 -0
  388. package/dist/static/svg/upload.svg +1 -0
  389. package/dist/static/svg/user.svg +1 -0
  390. package/dist/static/svg/vimeo.svg +1 -0
  391. package/dist/static/svg/youtube.svg +1 -0
  392. package/dist/types.d.ts +37 -0
  393. package/dist/types.d.ts.map +1 -0
  394. package/dist/types.js +1 -0
  395. package/dist/validate/createEmptyEditorState.d.ts +25 -0
  396. package/dist/validate/createEmptyEditorState.d.ts.map +1 -0
  397. package/dist/validate/createEmptyEditorState.js +26 -0
  398. package/dist/validate/hasText.d.ts +3 -0
  399. package/dist/validate/hasText.d.ts.map +1 -0
  400. package/dist/validate/hasText.js +20 -0
  401. package/dist/validate/validate.d.ts +5 -0
  402. package/dist/validate/validate.d.ts.map +1 -0
  403. package/dist/validate/validate.js +7 -0
  404. package/package.json +120 -0
  405. package/src/declarations.d.ts +4 -0
  406. package/src/field/apply-value-plugin.tsx +104 -0
  407. package/src/field/config/default.ts +58 -0
  408. package/src/field/config/editor-config-context.tsx +60 -0
  409. package/src/field/config/types.ts +67 -0
  410. package/src/field/constants.ts +1 -0
  411. package/src/field/content-editable-inline.tsx +27 -0
  412. package/src/field/content-editable.css +29 -0
  413. package/src/field/content-editable.tsx +27 -0
  414. package/src/field/context/shared-autocomplete-context.tsx +61 -0
  415. package/src/field/context/shared-history-context.tsx +30 -0
  416. package/src/field/context/shared-on-change-context.tsx +32 -0
  417. package/src/field/debug.tsx +39 -0
  418. package/src/field/editor-component.css +46 -0
  419. package/src/field/editor-component.md +87 -0
  420. package/src/field/editor-component.test.tsx +170 -0
  421. package/src/field/editor-component.tsx +207 -0
  422. package/src/field/editor-context.tsx +102 -0
  423. package/src/field/editor-field.tsx +51 -0
  424. package/src/field/editor.css +1481 -0
  425. package/src/field/editor.tsx +245 -0
  426. package/src/field/hooks/use-media-queryts +21 -0
  427. package/src/field/hooks/use-modal.tsx +59 -0
  428. package/src/field/hooks/use-report.ts +62 -0
  429. package/src/field/images/LICENSE.md +5 -0
  430. package/src/field/images/assets.d.ts +27 -0
  431. package/src/field/images/cat-typing.gif +0 -0
  432. package/src/field/images/emoji/1F600.png +0 -0
  433. package/src/field/images/emoji/1F641.png +0 -0
  434. package/src/field/images/emoji/1F642.png +0 -0
  435. package/src/field/images/emoji/2764.png +0 -0
  436. package/src/field/images/emoji/LICENSE.md +5 -0
  437. package/src/field/images/icons/3-columns.svg +3 -0
  438. package/src/field/images/icons/LICENSE.md +5 -0
  439. package/src/field/images/icons/admonition.svg +1 -0
  440. package/src/field/images/icons/ai.svg +5 -0
  441. package/src/field/images/icons/arrow-clockwise.svg +1 -0
  442. package/src/field/images/icons/arrow-counterclockwise.svg +1 -0
  443. package/src/field/images/icons/bg-color.svg +1 -0
  444. package/src/field/images/icons/camera.svg +1 -0
  445. package/src/field/images/icons/card-checklist.svg +1 -0
  446. package/src/field/images/icons/caret-right-fill.svg +1 -0
  447. package/src/field/images/icons/chat-left-text.svg +1 -0
  448. package/src/field/images/icons/chat-right-dots.svg +1 -0
  449. package/src/field/images/icons/chat-right-text.svg +1 -0
  450. package/src/field/images/icons/chat-right.svg +1 -0
  451. package/src/field/images/icons/chat-square-quote.svg +1 -0
  452. package/src/field/images/icons/chevron-down.svg +1 -0
  453. package/src/field/images/icons/clipboard.svg +1 -0
  454. package/src/field/images/icons/close.svg +1 -0
  455. package/src/field/images/icons/code.svg +1 -0
  456. package/src/field/images/icons/comments.svg +1 -0
  457. package/src/field/images/icons/copy.svg +1 -0
  458. package/src/field/images/icons/diagram-2.svg +1 -0
  459. package/src/field/images/icons/download.svg +1 -0
  460. package/src/field/images/icons/draggable-block-menu.svg +1 -0
  461. package/src/field/images/icons/dropdown-more.svg +1 -0
  462. package/src/field/images/icons/figma.svg +1 -0
  463. package/src/field/images/icons/file-earmark-text.svg +4 -0
  464. package/src/field/images/icons/file-image.svg +1 -0
  465. package/src/field/images/icons/filetype-gif.svg +1 -0
  466. package/src/field/images/icons/font-color.svg +1 -0
  467. package/src/field/images/icons/font-family.svg +1 -0
  468. package/src/field/images/icons/gear.svg +1 -0
  469. package/src/field/images/icons/horizontal-rule.svg +1 -0
  470. package/src/field/images/icons/indent.svg +1 -0
  471. package/src/field/images/icons/journal-code.svg +1 -0
  472. package/src/field/images/icons/journal-text.svg +1 -0
  473. package/src/field/images/icons/justify.svg +1 -0
  474. package/src/field/images/icons/link.svg +1 -0
  475. package/src/field/images/icons/list-ol.svg +1 -0
  476. package/src/field/images/icons/list-ul.svg +1 -0
  477. package/src/field/images/icons/lock-fill.svg +1 -0
  478. package/src/field/images/icons/lock.svg +1 -0
  479. package/src/field/images/icons/markdown.svg +1 -0
  480. package/src/field/images/icons/mic.svg +1 -0
  481. package/src/field/images/icons/outdent.svg +1 -0
  482. package/src/field/images/icons/paint-bucket.svg +1 -0
  483. package/src/field/images/icons/palette.svg +1 -0
  484. package/src/field/images/icons/pencil-fill.svg +1 -0
  485. package/src/field/images/icons/plug-fill.svg +1 -0
  486. package/src/field/images/icons/plug.svg +1 -0
  487. package/src/field/images/icons/plus-slash-minus.svg +1 -0
  488. package/src/field/images/icons/plus.svg +1 -0
  489. package/src/field/images/icons/prettier-error.svg +1 -0
  490. package/src/field/images/icons/prettier.svg +1 -0
  491. package/src/field/images/icons/send.svg +1 -0
  492. package/src/field/images/icons/square-check.svg +1 -0
  493. package/src/field/images/icons/sticky.svg +1 -0
  494. package/src/field/images/icons/success-alt.svg +1 -0
  495. package/src/field/images/icons/success.svg +1 -0
  496. package/src/field/images/icons/table.svg +1 -0
  497. package/src/field/images/icons/text-center.svg +1 -0
  498. package/src/field/images/icons/text-left.svg +1 -0
  499. package/src/field/images/icons/text-paragraph.svg +1 -0
  500. package/src/field/images/icons/text-right.svg +1 -0
  501. package/src/field/images/icons/trash.svg +1 -0
  502. package/src/field/images/icons/trash3.svg +1 -0
  503. package/src/field/images/icons/tweet.svg +1 -0
  504. package/src/field/images/icons/type-bold.svg +1 -0
  505. package/src/field/images/icons/type-h1.svg +1 -0
  506. package/src/field/images/icons/type-h2.svg +1 -0
  507. package/src/field/images/icons/type-h3.svg +1 -0
  508. package/src/field/images/icons/type-h4.svg +1 -0
  509. package/src/field/images/icons/type-h5.svg +1 -0
  510. package/src/field/images/icons/type-h6.svg +1 -0
  511. package/src/field/images/icons/type-italic.svg +1 -0
  512. package/src/field/images/icons/type-strikethrough.svg +1 -0
  513. package/src/field/images/icons/type-subscript.svg +1 -0
  514. package/src/field/images/icons/type-superscript.svg +1 -0
  515. package/src/field/images/icons/type-underline.svg +1 -0
  516. package/src/field/images/icons/upload.svg +1 -0
  517. package/src/field/images/icons/user.svg +1 -0
  518. package/src/field/images/icons/vimeo.svg +1 -0
  519. package/src/field/images/icons/youtube.svg +1 -0
  520. package/src/field/images/landscape.jpg +0 -0
  521. package/src/field/images/logo.svg +1 -0
  522. package/src/field/images/yellow-flower-small.jpg +0 -0
  523. package/src/field/images/yellow-flower.jpg +0 -0
  524. package/src/field/lexical-populate-shared.ts +188 -0
  525. package/src/field/nodes/admonition-node/admonition-node-component.css +115 -0
  526. package/src/field/nodes/admonition-node/admonition-node-component.tsx +256 -0
  527. package/src/field/nodes/admonition-node/admonition-node.tsx +189 -0
  528. package/src/field/nodes/admonition-node/icons/danger-icon.css +11 -0
  529. package/src/field/nodes/admonition-node/icons/danger-icon.js +17 -0
  530. package/src/field/nodes/admonition-node/icons/danger-icon.tsx +19 -0
  531. package/src/field/nodes/admonition-node/icons/index.js +4 -0
  532. package/src/field/nodes/admonition-node/icons/index.ts +4 -0
  533. package/src/field/nodes/admonition-node/icons/note-icon.css +11 -0
  534. package/src/field/nodes/admonition-node/icons/note-icon.js +17 -0
  535. package/src/field/nodes/admonition-node/icons/note-icon.tsx +19 -0
  536. package/src/field/nodes/admonition-node/icons/tip-icon.css +11 -0
  537. package/src/field/nodes/admonition-node/icons/tip-icon.js +17 -0
  538. package/src/field/nodes/admonition-node/icons/tip-icon.tsx +19 -0
  539. package/src/field/nodes/admonition-node/icons/warning-icon.css +11 -0
  540. package/src/field/nodes/admonition-node/icons/warning-icon.js +17 -0
  541. package/src/field/nodes/admonition-node/icons/warning-icon.tsx +19 -0
  542. package/src/field/nodes/admonition-node/index.ts +14 -0
  543. package/src/field/nodes/admonition-node/types.ts +33 -0
  544. package/src/field/nodes/document-relation.ts +33 -0
  545. package/src/field/nodes/index.ts +47 -0
  546. package/src/field/nodes/inline-image-node/index.ts +10 -0
  547. package/src/field/nodes/inline-image-node/inline-image-node-component.css +205 -0
  548. package/src/field/nodes/inline-image-node/inline-image-node-component.tsx +342 -0
  549. package/src/field/nodes/inline-image-node/inline-image-node.tsx +328 -0
  550. package/src/field/nodes/inline-image-node/types.ts +43 -0
  551. package/src/field/nodes/layout-container-node/layout-container-node.ts +97 -0
  552. package/src/field/nodes/layout-container-node/layout-item-node.ts +63 -0
  553. package/src/field/nodes/link-nodes/auto-link-node.ts +64 -0
  554. package/src/field/nodes/link-nodes/index.ts +3 -0
  555. package/src/field/nodes/link-nodes/link-node.ts +426 -0
  556. package/src/field/nodes/link-nodes/types.ts +33 -0
  557. package/src/field/nodes/vimeo-node/index.tsx +172 -0
  558. package/src/field/nodes/youtube-node/index.tsx +178 -0
  559. package/src/field/plugins/admonition-plugin/admonition-modal.css +25 -0
  560. package/src/field/plugins/admonition-plugin/admonition-modal.tsx +187 -0
  561. package/src/field/plugins/admonition-plugin/fields.ts +103 -0
  562. package/src/field/plugins/admonition-plugin/index.tsx +105 -0
  563. package/src/field/plugins/admonition-plugin/types.ts +37 -0
  564. package/src/field/plugins/auto-embed-plugin/auto-embed-modal.css +15 -0
  565. package/src/field/plugins/auto-embed-plugin/auto-embed-modal.tsx +110 -0
  566. package/src/field/plugins/auto-embed-plugin/index.tsx +323 -0
  567. package/src/field/plugins/code-highlight-plugin/index.ts +23 -0
  568. package/src/field/plugins/drag-drop-paste-plugin/index.ts +47 -0
  569. package/src/field/plugins/floating-text-format-toolbar-plugin/index.css +148 -0
  570. package/src/field/plugins/floating-text-format-toolbar-plugin/index.tsx +398 -0
  571. package/src/field/plugins/inline-image-plugin/fields.ts +21 -0
  572. package/src/field/plugins/inline-image-plugin/index.tsx +202 -0
  573. package/src/field/plugins/inline-image-plugin/inline-image-modal.css +29 -0
  574. package/src/field/plugins/inline-image-plugin/inline-image-modal.tsx +314 -0
  575. package/src/field/plugins/inline-image-plugin/populate.ts +48 -0
  576. package/src/field/plugins/inline-image-plugin/types.ts +39 -0
  577. package/src/field/plugins/inline-image-plugin/utils.ts +113 -0
  578. package/src/field/plugins/layout-plugin/insert-layout-modal.css +19 -0
  579. package/src/field/plugins/layout-plugin/insert-layout-modal.tsx +100 -0
  580. package/src/field/plugins/layout-plugin/layout-plugin.tsx +162 -0
  581. package/src/field/plugins/link-plugin/auto-link/auto-link-plugin.tsx +327 -0
  582. package/src/field/plugins/link-plugin/auto-link/index.tsx +35 -0
  583. package/src/field/plugins/link-plugin/link/floating-link-editor.css +128 -0
  584. package/src/field/plugins/link-plugin/link/floating-link-editor.tsx +348 -0
  585. package/src/field/plugins/link-plugin/link/index.tsx +99 -0
  586. package/src/field/plugins/link-plugin/link/link-modal.tsx +376 -0
  587. package/src/field/plugins/link-plugin/link/types.ts +20 -0
  588. package/src/field/plugins/link-plugin/populate.ts +48 -0
  589. package/src/field/plugins/table-action-menu-plugin/index.tsx +804 -0
  590. package/src/field/plugins/table-plugin/index.tsx +33 -0
  591. package/src/field/plugins/table-plugin/table-modal.css +19 -0
  592. package/src/field/plugins/table-plugin/table-modal.tsx +127 -0
  593. package/src/field/plugins/toolbar-plugin/index.tsx +937 -0
  594. package/src/field/plugins/treeview-plugin/index.tsx +29 -0
  595. package/src/field/plugins/vimeo-plugin/index.ts +42 -0
  596. package/src/field/plugins/youtube-plugin/index.ts +43 -0
  597. package/src/field/shared/canUseDOM.ts +10 -0
  598. package/src/field/shared/caretFromPoint.bak +40 -0
  599. package/src/field/shared/environment.ts +44 -0
  600. package/src/field/shared/invariant.ts +25 -0
  601. package/src/field/shared/simpleDiffWithCursor.ts +40 -0
  602. package/src/field/shared/useLayoutEffect.ts +15 -0
  603. package/src/field/shared/useModalFormState.ts +48 -0
  604. package/src/field/shared/warnOnlyOnce.ts +21 -0
  605. package/src/field/themes/lexical-editor-theme.css +565 -0
  606. package/src/field/themes/lexical-editor-theme.js +104 -0
  607. package/src/field/themes/lexical-editor-theme.tsx +115 -0
  608. package/src/field/toolbar-extensions.tsx +93 -0
  609. package/src/field/types.ts +19 -0
  610. package/src/field/ui/button.css +45 -0
  611. package/src/field/ui/button.tsx +51 -0
  612. package/src/field/ui/checkbox.css +52 -0
  613. package/src/field/ui/color-picker.css +88 -0
  614. package/src/field/ui/color-picker.tsx +395 -0
  615. package/src/field/ui/dialog.css +17 -0
  616. package/src/field/ui/dialog.tsx +29 -0
  617. package/src/field/ui/dropdown.tsx +217 -0
  618. package/src/field/ui/file-input.tsx +44 -0
  619. package/src/field/ui/input.css +32 -0
  620. package/src/field/ui/modal.css +84 -0
  621. package/src/field/ui/modal.tsx +106 -0
  622. package/src/field/ui/placeholder-inline.tsx +28 -0
  623. package/src/field/ui/placeholder.css +33 -0
  624. package/src/field/ui/placeholder.tsx +32 -0
  625. package/src/field/ui/select.css +34 -0
  626. package/src/field/ui/select.tsx +38 -0
  627. package/src/field/ui/switch.tsx +33 -0
  628. package/src/field/ui/text-area.css +45 -0
  629. package/src/field/ui/text-area.tsx +50 -0
  630. package/src/field/ui/text-input.tsx +51 -0
  631. package/src/field/utils/cloneDeep.ts +57 -0
  632. package/src/field/utils/deepEqual.ts +54 -0
  633. package/src/field/utils/emoji-list.ts +16615 -0
  634. package/src/field/utils/getDOMRangeRect.ts +24 -0
  635. package/src/field/utils/getSelectedNode.ts +25 -0
  636. package/src/field/utils/guard.ts +10 -0
  637. package/src/field/utils/hashSerializedState.ts +34 -0
  638. package/src/field/utils/isMobileWidth.ts +7 -0
  639. package/src/field/utils/joinClasses.ts +11 -0
  640. package/src/field/utils/point.ts +52 -0
  641. package/src/field/utils/rect.ts +142 -0
  642. package/src/field/utils/setFloatingElemPosition.ts +48 -0
  643. package/src/field/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
  644. package/src/field/utils/swipe.ts +129 -0
  645. package/src/field/utils/url.ts +49 -0
  646. package/src/index.ts +26 -0
  647. package/src/lexical-editor.tsx +56 -0
  648. package/src/richtext-field.module.css +29 -0
  649. package/src/richtext-field.tsx +113 -0
  650. package/src/server.ts +85 -0
  651. package/src/types.ts +43 -0
  652. package/src/validate/createEmptyEditorState.ts +52 -0
  653. package/src/validate/hasText.test.ts +89 -0
  654. package/src/validate/hasText.ts +34 -0
  655. package/src/validate/validate.ts +18 -0
@@ -0,0 +1,46 @@
1
+ .lexicalRichTextEditor {
2
+ display: flex;
3
+ isolation: isolate;
4
+ width: 100%;
5
+ }
6
+
7
+ .lexicalRichTextEditor--read-only {
8
+ .editor-shell::after {
9
+ content: "";
10
+ position: absolute;
11
+ top: 0;
12
+ left: 0;
13
+ right: 0;
14
+ bottom: 0;
15
+ background: var(--canvas-50);
16
+ opacity: 0.5;
17
+ z-index: 9;
18
+ }
19
+ }
20
+
21
+ .lexicalRichTextEditor__wrap {
22
+ width: 100%;
23
+ position: relative;
24
+ }
25
+
26
+ .lexicalRichTextEditor.error {
27
+ .editor-shell::after {
28
+ content: "";
29
+ position: absolute;
30
+ top: 0;
31
+ left: 0;
32
+ right: 0;
33
+ bottom: 0;
34
+ background: var(--red-700);
35
+ opacity: 1;
36
+ z-index: -1;
37
+ }
38
+ }
39
+
40
+ .dark {
41
+ .lexicalRichTextEditor.error {
42
+ .editor-shell::after {
43
+ background: var(--red-700-dark);
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,87 @@
1
+ # Editor Component Architecture
2
+
3
+ This architecture is designed to solve the "two-way binding problem" common in rich text editors.
4
+
5
+ Rich text editors maintain their own complex internal state (the DOM/Virtual DOM). When you try to sync this with React state (props), you often get **infinite loops** (Editor changes $\rightarrow$ React updates $\rightarrow$ Prop changes $\rightarrow$ Editor updates $\rightarrow$ Editor changes...) or **cursor jumping** (re-rendering the editor while typing).
6
+
7
+ ```
8
+ +-----------------------------------------------------------------------+
9
+ | EditorField (src/field/editor-field.tsx) |
10
+ | - Handles Lazy Loading & Suspense |
11
+ +-----------------------------------+-----------------------------------+
12
+ |
13
+ v
14
+ +-----------------------------------+-----------------------------------+
15
+ | EditorComponent (src/field/editor-component.tsx) |
16
+ | - Manages Hash Refs (lastEmitted, normalizedIncoming) |
17
+ | - Handles onChange (Debouncing & Hash Checks) |
18
+ +-----------------------------------+-----------------------------------+
19
+ |
20
+ | (renders)
21
+ v
22
+ +-----------------------------------+----------------------------------+
23
+ | EditorContext (src/field/editor-context.tsx) |
24
+ | - Wraps everything in <LexicalComposer> |
25
+ | - Provides SharedHistory & SharedOnChange Contexts |
26
+ +------------------+---------------------------------+-----------------+
27
+ | |
28
+ | (passed as children) | (renders)
29
+ v v
30
+ +------------------+------------------+ +-----------+------------------+
31
+ | ApplyValuePlugin | | Editor (src/field/editor.tsx)|
32
+ | (src/field/apply-value-plugin.tsx) | | - ToolbarPlugin |
33
+ | | | - ContentEditable |
34
+ | - Watches: incoming value & hash | | - Floating Toolbars |
35
+ | - Action: editor.update() | | - Auto-resize logic |
36
+ | (Syncs external props -> Editor) | +------------------------------+
37
+ +-------------------------------------+
38
+ ```
39
+
40
+ ### Key Relationships
41
+ 1. `EditorComponent` is the "Brain". It holds the connection to the Payload form state (`useField`) and decides when to update the form value based on hashes.
42
+ 2. `EditorContext` is the "Bridge". It initializes the Lexical instance (`LexicalComposer`) but doesn't contain the specific logic for syncing values or rendering the UI itself.
43
+ 3. `ApplyValuePlugin` is the "Synchronizer". It sits inside the Lexical context. When `EditorComponent` receives a new value from the database (or parent), it passes it down here. This plugin forces the Lexical instance to update its state to match.
44
+ 4. `Editor` is the "View". It handles the visual presentation, toolbars, and the actual `contentEditable` DOM element.
45
+
46
+
47
+ ## EditorComponent
48
+
49
+ Here's how the `useRef` hooks inside editor-component.tsx solve editor-specific problems:
50
+
51
+ ### 1. The "Debounce" Ref
52
+ **`dispatchFieldUpdateTask`**
53
+ * **Purpose:** Performance.
54
+ * **How it works:** When a user types, Lexical fires `onChange` on every keystroke. We don't want to update the main React state (and trigger re-renders up the tree) 60 times a second.
55
+ * **Mechanism:** This ref stores the ID of the current `requestIdleCallback`. If a user types again before the callback runs, we cancel the old one and start a new one. It ensures we only process the *latest* state when the browser is idle.
56
+
57
+ ### 2. The "Fresh Props" Refs
58
+ **`valueRef`** and **`initialValueRef`**
59
+ * **Purpose:** Accessing state inside `useCallback` without dependencies.
60
+ * **How it works:** The `handleChange` function is memoized via `useCallback`. If we added `value` to its dependency array, `handleChange` would be re-created every time the user typed, breaking our debounce logic.
61
+ * **Mechanism:** We copy the props into these refs on every render. Inside `handleChange`, we read `valueRef.current`. This lets the function stay stable (same memory address) while still seeing the latest data.
62
+
63
+ ### 3. The "Outbound Loop Breaker"
64
+ **`lastEmittedHashRef`**
65
+ * **Purpose:** Preventing the "Echo" loop.
66
+ * **The Problem:** You type "A". The editor emits "A". The parent saves "A" and passes "A" back down as a prop. The editor sees "A" and thinks, "Oh, a new value! I should process this."
67
+ * **The Fix:** Before calling `onChange`, we calculate a hash of the content and store it here.
68
+ * **Logic:** "If the hash I'm about to send is the same as the last one I sent, do nothing."
69
+
70
+ ### 4. The "Inbound Normalization" Refs
71
+ **`normalizedIncomingHashRef`** and **`hasNormalizedBaselineRef`**
72
+ * **Purpose:** Handling Lexical's strictness.
73
+ * **The Problem:** Lexical is opinionated. If you load a value like `{"text": "hello"}`, Lexical might instantly transform it into a more complex structure (adding IDs, versions, etc.). This immediate transformation looks like a "change" event, which might trigger a save before the user has even touched the keyboard.
74
+ * **`normalizedIncomingHashRef`:**
75
+ * The `ApplyValuePlugin` loads data, waits for Lexical to "settle" (normalize it), and then saves the hash of that *settled* state here.
76
+ * The `handleChange` function checks this: "Is this 'new' change just the result of the data I just loaded?" If yes, it ignores it.
77
+ * **`hasNormalizedBaselineRef`:**
78
+ * This acts as a gatekeeper. It starts as `false`.
79
+ * It prevents the editor from emitting *any* changes until the initial value has been fully loaded and normalized. This stops the editor from accidentally overwriting the database with an empty state during the split-second it takes to mount.
80
+
81
+ ### Summary Flow
82
+ 1. **User types:** `handleChange` triggers.
83
+ 2. **Debounce:** `dispatchFieldUpdateTask` ensures we wait for a pause.
84
+ 3. **Check Baseline:** `hasNormalizedBaselineRef` ensures we aren't just booting up.
85
+ 4. **Check Inbound:** `normalizedIncomingHashRef` ensures we aren't just reporting Lexical's own auto-formatting of the data we just gave it.
86
+ 5. **Check Outbound:** `lastEmittedHashRef` ensures we aren't reporting the same thing twice.
87
+ 6. **Success:** Only then do we call `onChange`.
@@ -0,0 +1,170 @@
1
+ import { act } from 'react'
2
+
3
+ import type {
4
+ SerializedEditorState,
5
+ SerializedElementNode,
6
+ SerializedRootNode,
7
+ SerializedTextNode,
8
+ } from 'lexical'
9
+ import { createRoot } from 'react-dom/client'
10
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
11
+
12
+ vi.mock('./editor-component.css', () => ({}))
13
+ vi.mock('./themes/lexical-editor-theme.css', () => ({}))
14
+ vi.mock('@infonomic/uikit/react', () => ({
15
+ HelpText: () => null,
16
+ Label: () => null,
17
+ }))
18
+
19
+ import { ApplyValuePlugin } from './apply-value-plugin'
20
+ import { hashSerializedState } from './utils/hashSerializedState'
21
+
22
+ // Enable React act warnings suppression for this environment
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ ;(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true
25
+
26
+ // Mock the Lexical composer context to avoid spinning up a real editor
27
+ const mockEditor = {
28
+ update: (fn: () => void) => fn(),
29
+ parseEditorState: vi.fn((val) => val),
30
+ setEditorState: vi.fn(),
31
+ }
32
+
33
+ vi.mock('@lexical/react/LexicalComposerContext', () => {
34
+ return {
35
+ useLexicalComposerContext: () => [mockEditor],
36
+ }
37
+ })
38
+
39
+ describe('ApplyValuePlugin', () => {
40
+ beforeEach(() => {
41
+ mockEditor.parseEditorState.mockClear()
42
+ mockEditor.setEditorState.mockClear()
43
+ })
44
+
45
+ const stateA: SerializedEditorState = {
46
+ root: {
47
+ children: [],
48
+ direction: 'ltr',
49
+ format: '',
50
+ indent: 0,
51
+ type: 'root',
52
+ version: 1,
53
+ } as SerializedRootNode,
54
+ }
55
+
56
+ const stateB: SerializedEditorState = {
57
+ root: {
58
+ children: [
59
+ {
60
+ children: [
61
+ {
62
+ detail: 0,
63
+ format: 0,
64
+ mode: 'normal',
65
+ style: '',
66
+ text: 'Hello world',
67
+ type: 'text',
68
+ version: 1,
69
+ } as SerializedTextNode,
70
+ ],
71
+ direction: 'ltr',
72
+ format: '',
73
+ indent: 0,
74
+ type: 'paragraph',
75
+ version: 1,
76
+ } as SerializedElementNode,
77
+ ],
78
+ direction: 'ltr',
79
+ format: '',
80
+ indent: 0,
81
+ type: 'root',
82
+ version: 1,
83
+ } as SerializedRootNode,
84
+ }
85
+
86
+ it('applies incoming value once and ignores identical hashes', async () => {
87
+ const container = document.createElement('div')
88
+ const root = createRoot(container)
89
+ const lastEmitted = { current: undefined as string | undefined }
90
+ const normalizedIncoming = { current: undefined as string | undefined }
91
+ const hasNormalizedBaseline = { current: false }
92
+
93
+ const hashA = hashSerializedState(stateA)
94
+
95
+ await act(async () => {
96
+ root.render(
97
+ <ApplyValuePlugin
98
+ value={stateA}
99
+ incomingHash={hashA}
100
+ lastEmittedHashRef={lastEmitted}
101
+ normalizedIncomingHashRef={normalizedIncoming}
102
+ hasNormalizedBaselineRef={hasNormalizedBaseline}
103
+ />
104
+ )
105
+ })
106
+
107
+ expect(mockEditor.setEditorState).toHaveBeenCalledTimes(1)
108
+ expect(mockEditor.setEditorState).toHaveBeenLastCalledWith(stateA)
109
+
110
+ // Re-render with same value -> no new apply
111
+ await act(async () => {
112
+ root.render(
113
+ <ApplyValuePlugin
114
+ value={stateA}
115
+ incomingHash={hashA}
116
+ lastEmittedHashRef={lastEmitted}
117
+ normalizedIncomingHashRef={normalizedIncoming}
118
+ hasNormalizedBaselineRef={hasNormalizedBaseline}
119
+ />
120
+ )
121
+ })
122
+ expect(mockEditor.setEditorState).toHaveBeenCalledTimes(1)
123
+
124
+ // New value -> apply again
125
+ const hashB = hashSerializedState(stateB)
126
+ await act(async () => {
127
+ root.render(
128
+ <ApplyValuePlugin
129
+ value={stateB}
130
+ incomingHash={hashB}
131
+ lastEmittedHashRef={lastEmitted}
132
+ normalizedIncomingHashRef={normalizedIncoming}
133
+ hasNormalizedBaselineRef={hasNormalizedBaseline}
134
+ />
135
+ )
136
+ })
137
+ expect(mockEditor.setEditorState).toHaveBeenCalledTimes(2)
138
+ expect(mockEditor.setEditorState).toHaveBeenLastCalledWith(stateB)
139
+
140
+ await act(async () => {
141
+ root.unmount()
142
+ })
143
+ })
144
+
145
+ it('skips apply when incoming hash matches last emitted (echo prevention)', async () => {
146
+ const container = document.createElement('div')
147
+ const root = createRoot(container)
148
+ const lastEmitted = { current: hashSerializedState(stateA) }
149
+ const normalizedIncoming = { current: undefined as string | undefined }
150
+ const hasNormalizedBaseline = { current: false }
151
+ const hashA = hashSerializedState(stateA)
152
+
153
+ await act(async () => {
154
+ root.render(
155
+ <ApplyValuePlugin
156
+ value={stateA}
157
+ incomingHash={hashA}
158
+ lastEmittedHashRef={lastEmitted}
159
+ normalizedIncomingHashRef={normalizedIncoming}
160
+ hasNormalizedBaselineRef={hasNormalizedBaseline}
161
+ />
162
+ )
163
+ })
164
+
165
+ expect(mockEditor.setEditorState).not.toHaveBeenCalled()
166
+ await act(async () => {
167
+ root.unmount()
168
+ })
169
+ })
170
+ })
@@ -0,0 +1,207 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * This Source Code is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
+ *
8
+ * Copyright (c) Infonomic Company Limited
9
+ */
10
+
11
+ import type React from 'react'
12
+ import { memo, useCallback, useMemo, useRef } from 'react'
13
+
14
+ import { HelpText, Label } from '@infonomic/uikit/react'
15
+ import type { EditorState, SerializedEditorState } from 'lexical'
16
+ import { ErrorBoundary } from 'react-error-boundary'
17
+
18
+ import { richTextValidate } from '../validate/validate'
19
+ import { ApplyValuePlugin } from './apply-value-plugin'
20
+ import { EditorContext } from './editor-context'
21
+ import { hashSerializedState } from './utils/hashSerializedState'
22
+ import type { EditorFieldProps } from '../types'
23
+
24
+ import './editor-component.css'
25
+ import './themes/lexical-editor-theme.css'
26
+
27
+ const baseClass = 'lexicalRichTextEditor'
28
+
29
+ // NOTE: @See ./editor-component.md mini doc for an explanation of our editor architecture.
30
+
31
+ // We memoize the EditorComponent to prevent re-renders from parent components or
32
+ // other editor instances. Only internal state changes for a given (this)
33
+ // editor instance should trigger re-renders. Our form-context and value handlers
34
+ // are subscription-based and so in theory this shouldn't be necessary, but
35
+ // here just in case.
36
+ export const EditorComponent = memo(function EditorComponent({
37
+ name,
38
+ id,
39
+ label,
40
+ description,
41
+ required,
42
+ readonly,
43
+ editorConfig,
44
+ defaultValue,
45
+ value,
46
+ onChange,
47
+ minHeight,
48
+ maxHeight,
49
+ validate = richTextValidate,
50
+ onError: _onError,
51
+ lexicalEditorProps: _lexicalEditorProps,
52
+ featureBeforeEditor,
53
+ featureAfterEditor,
54
+ featureChildren,
55
+ }: EditorFieldProps): React.JSX.Element {
56
+ const disabled = readonly ?? false
57
+ const dispatchFieldUpdateTask = useRef<number>(undefined)
58
+ const valueRef = useRef(value)
59
+ valueRef.current = value
60
+ const initialValueRef = useRef(defaultValue)
61
+ initialValueRef.current = defaultValue
62
+ const lastEmittedHashRef = useRef<string | undefined>(undefined)
63
+ const normalizedIncomingHashRef = useRef<string | undefined>(undefined)
64
+ const hasNormalizedBaselineRef = useRef<boolean>(false)
65
+ // const _debugLogCountRef = useRef<number>(0)
66
+
67
+ // TODO: implement validation handling (currently unused)
68
+ const _memoizedValidate = useCallback(
69
+ (val: SerializedEditorState | undefined) => {
70
+ if (typeof validate === 'function') {
71
+ return validate(val, { required })
72
+ }
73
+ return true
74
+ },
75
+ [validate, required]
76
+ )
77
+
78
+ // Debounced onChange -> emit to store
79
+ const handleChange = useCallback(
80
+ (editorState: EditorState, _editor: unknown, _tags?: Set<string>) => {
81
+ // const _capturedTags = tags != null ? Array.from(tags) : []
82
+ const updateFieldValue = (editorState: EditorState) => {
83
+ const newState = editorState.toJSON()
84
+ const nextHash = hashSerializedState(newState)
85
+
86
+ // If we have an incoming form value but haven't established a normalized baseline yet,
87
+ // ignore mount-time normalization updates (often appear as tags: []).
88
+ if (
89
+ (valueRef.current ?? initialValueRef.current) != null &&
90
+ hasNormalizedBaselineRef.current !== true
91
+ ) {
92
+ // if (process.env.NODE_ENV === 'production' && _debugLogCountRef.current < 10) {
93
+ // _debugLogCountRef.current++
94
+ // // eslint-disable-next-line no-console
95
+ // console.log('[lexical][payload][skip] waiting baseline', {
96
+ // tags: _capturedTags,
97
+ // nextHash,
98
+ // normalizedIncomingHash: normalizedIncomingHashRef.current,
99
+ // lastEmittedHash: lastEmittedHashRef.current,
100
+ // })
101
+ // }
102
+ return
103
+ }
104
+ // Prefer comparing against Lexical-normalized incoming JSON (critical for nested editors).
105
+ if (
106
+ normalizedIncomingHashRef.current != null &&
107
+ nextHash === normalizedIncomingHashRef.current
108
+ ) {
109
+ return
110
+ }
111
+
112
+ // Also avoid re-emitting the exact same state multiple times.
113
+ if (lastEmittedHashRef.current != null && nextHash === lastEmittedHashRef.current) return
114
+
115
+ lastEmittedHashRef.current = nextHash
116
+
117
+ // if (process.env.NODE_ENV === 'production' && _debugLogCountRef.current < 10) {
118
+ // _debugLogCountRef.current++
119
+ // // eslint-disable-next-line no-console
120
+ // console.log('[lexical][payload][setValue]', {
121
+ // tags: _capturedTags,
122
+ // nextHash,
123
+ // normalizedIncomingHash: normalizedIncomingHashRef.current,
124
+ // rawIncomingHash: rawIncomingHashRef.current,
125
+ // lastEmittedHash: lastEmittedHashRef.current,
126
+ // })
127
+ // }
128
+
129
+ if (typeof onChange === 'function') {
130
+ onChange(newState)
131
+ }
132
+ }
133
+
134
+ if (typeof window.requestIdleCallback === 'function') {
135
+ // Cancel earlier scheduled value updates,
136
+ // so that a CPU-limited event loop isn't flooded with n callbacks for n keystrokes
137
+ // into the rich text field, but that there's only ever the latest one state update
138
+ // dispatch task, to be executed with the next idle time,
139
+ // or the deadline of 500ms.
140
+ if (typeof window.cancelIdleCallback === 'function' && dispatchFieldUpdateTask.current) {
141
+ cancelIdleCallback(dispatchFieldUpdateTask.current)
142
+ }
143
+ // Schedule the state update to happen the next time the browser has sufficient resources,
144
+ // or the latest after 500ms.
145
+ dispatchFieldUpdateTask.current = requestIdleCallback(() => updateFieldValue(editorState), {
146
+ timeout: 500,
147
+ })
148
+ } else {
149
+ updateFieldValue(editorState)
150
+ }
151
+ },
152
+ [onChange]
153
+ )
154
+
155
+ const incomingValue = value ?? defaultValue ?? undefined
156
+
157
+ const incomingHash = useMemo(
158
+ () => (incomingValue != null ? hashSerializedState(incomingValue) : undefined),
159
+ [incomingValue]
160
+ )
161
+
162
+ return (
163
+ <div className={baseClass}>
164
+ <div className={`${baseClass}__wrap`}>
165
+ {label != null &&
166
+ (typeof label === 'string' ? (
167
+ <Label id={`${id}-label`} label={label} htmlFor={id} required={required} />
168
+ ) : (
169
+ label
170
+ ))}
171
+ <ErrorBoundary fallbackRender={fallbackRender} onReset={() => {}}>
172
+ <EditorContext
173
+ composerKey={id}
174
+ editorConfig={editorConfig}
175
+ key={id}
176
+ onChange={handleChange}
177
+ readOnly={disabled}
178
+ value={incomingValue}
179
+ minHeight={minHeight}
180
+ maxHeight={maxHeight}
181
+ beforeEditor={featureBeforeEditor}
182
+ afterEditor={featureAfterEditor}
183
+ >
184
+ <ApplyValuePlugin
185
+ value={incomingValue}
186
+ incomingHash={incomingHash}
187
+ lastEmittedHashRef={lastEmittedHashRef}
188
+ normalizedIncomingHashRef={normalizedIncomingHashRef}
189
+ hasNormalizedBaselineRef={hasNormalizedBaselineRef}
190
+ />
191
+ {featureChildren}
192
+ </EditorContext>
193
+ </ErrorBoundary>
194
+ {description && <HelpText text={description} />}
195
+ </div>
196
+ </div>
197
+ )
198
+ })
199
+
200
+ function fallbackRender({ error }: any): React.JSX.Element {
201
+ return (
202
+ <div className="errorBoundary" role="alert">
203
+ <p>Something went wrong:</p>
204
+ <pre style={{ color: 'red' }}>{error.message}</pre>
205
+ </div>
206
+ )
207
+ }
@@ -0,0 +1,102 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * This Source Code is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
+ *
8
+ * Copyright (c) Infonomic Company Limited
9
+ */
10
+
11
+ import type * as React from 'react'
12
+ import { useMemo } from 'react'
13
+
14
+ import type { InitialConfigType } from '@lexical/react/LexicalComposer'
15
+ import { LexicalComposer } from '@lexical/react/LexicalComposer'
16
+ import type { EditorState, LexicalEditor, SerializedEditorState } from 'lexical'
17
+
18
+ import { EditorConfigContext } from './config/editor-config-context'
19
+ import { SharedHistoryContext } from './context/shared-history-context'
20
+ import { SharedOnChangeContext } from './context/shared-on-change-context'
21
+ import { Editor } from './editor'
22
+ import { Nodes } from './nodes'
23
+ import { ToolbarExtensionsProvider } from './toolbar-extensions'
24
+ import type { EditorConfig } from './config/types'
25
+
26
+ // Catch any errors that occur during Lexical updates and log them
27
+ // or throw them as needed. If you don't throw them, Lexical will
28
+ // try to recover gracefully without losing user data.
29
+ function _onError(error: Error, _editor: LexicalEditor): void {
30
+ // eslint-disable-next-line no-console
31
+ console.error(error)
32
+ }
33
+
34
+ export function EditorContext(props: {
35
+ composerKey: string
36
+ editorConfig: EditorConfig
37
+ onChange: (editorState: EditorState, editor: LexicalEditor, tags: Set<string>) => void
38
+ readOnly: boolean
39
+ value?: SerializedEditorState
40
+ minHeight?: number | string
41
+ maxHeight?: number | string
42
+ children?: React.ReactNode
43
+ beforeEditor?: React.ReactNode[]
44
+ afterEditor?: React.ReactNode[]
45
+ }): React.JSX.Element {
46
+ const {
47
+ composerKey,
48
+ editorConfig,
49
+ onChange,
50
+ readOnly,
51
+ value,
52
+ beforeEditor,
53
+ afterEditor,
54
+ children,
55
+ } = props
56
+
57
+ // useMemo for the initialConfig that depends on readOnly and value
58
+ // biome-ignore lint/correctness/useExhaustiveDependencies: TODO: revisit
59
+ const initialConfig = useMemo<InitialConfigType>(() => {
60
+ return {
61
+ editable: readOnly !== true,
62
+ editorState: value != null ? JSON.stringify(value) : undefined,
63
+ namespace: editorConfig.lexical.namespace,
64
+ nodes: [...Nodes],
65
+ onError: (error: Error) => {
66
+ throw error
67
+ },
68
+ theme: editorConfig.lexical.theme,
69
+ }
70
+ // Important: do not add readOnly and value to the dependencies array.
71
+ // This will cause the entire lexical editor to re-render if the document
72
+ // is saved, which will cause the editor to lose focus.
73
+
74
+ // NOTE: 2025-04-26: This is NOT the case for our version of the editor.
75
+ // Without readOnly as a dependency, the editor will never transition
76
+ // from readOnly to editable during form loading, when disabledFromField
77
+ // in field-component will be briefly false.
78
+ }, [editorConfig, readOnly])
79
+
80
+ if (initialConfig == null) {
81
+ return <p>Loading...</p>
82
+ }
83
+
84
+ return (
85
+ <LexicalComposer initialConfig={initialConfig} key={composerKey + initialConfig.editable}>
86
+ <EditorConfigContext config={editorConfig.settings}>
87
+ <SharedOnChangeContext onChange={onChange}>
88
+ <SharedHistoryContext>
89
+ <ToolbarExtensionsProvider>
90
+ <div className="editor-shell">
91
+ {beforeEditor}
92
+ <Editor minHeight={props.minHeight} maxHeight={props.maxHeight} />
93
+ {afterEditor}
94
+ {children}
95
+ </div>
96
+ </ToolbarExtensionsProvider>
97
+ </SharedHistoryContext>
98
+ </SharedOnChangeContext>
99
+ </EditorConfigContext>
100
+ </LexicalComposer>
101
+ )
102
+ }
@@ -0,0 +1,51 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
5
+ * Copyright notices appear at the top of source files where applicable
6
+ * and are licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ *
9
+ * https://github.com/facebook/lexical
10
+ *
11
+ * Portions Copyright (c) Payload CMS, LLC info@payloadcms.com
12
+ * Copyright notices appear at the top of source files where applicable
13
+ * and are licensed under the MIT license found in the
14
+ * LICENSE file in the root directory of this source tree
15
+ *
16
+ * https://github.com/payloadcms/payload/
17
+ *
18
+ *
19
+ * Note: For historical context see...
20
+ *
21
+ * https://github.com/facebook/lexical/commits?author=58bits
22
+ * https://github.com/infonomic/payload-alternative-lexical-richtext-editor
23
+ * https://github.com/AlessioGr/payload-plugin-lexical/commits?author=58bits
24
+ * https://github.com/payloadcms/payload/commits?author=58bits
25
+ *
26
+ *
27
+ * This Source Code is subject to the terms of the Mozilla Public
28
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
29
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
30
+ *
31
+ * Copyright (c) Infonomic Company Limited
32
+ */
33
+
34
+ import type * as React from 'react'
35
+ import { lazy, Suspense } from 'react'
36
+
37
+ import { Shimmer } from '@infonomic/uikit/react'
38
+
39
+ import type { EditorFieldProps } from '../types'
40
+
41
+ const EditorComponent = lazy(() =>
42
+ import('./editor-component').then((module) => ({ default: module.EditorComponent }))
43
+ )
44
+
45
+ export function EditorField(props: EditorFieldProps): React.JSX.Element {
46
+ return (
47
+ <Suspense fallback={<Shimmer height="35vh" />}>
48
+ <EditorComponent {...props} />
49
+ </Suspense>
50
+ )
51
+ }