@byline/richtext-lexical 1.11.2 → 1.12.1

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 (256) hide show
  1. package/dist/field/apply-value-plugin.js +1 -3
  2. package/dist/field/config/default-extensions.d.ts +32 -0
  3. package/dist/field/config/default-extensions.js +49 -0
  4. package/dist/field/config/default.d.ts +8 -0
  5. package/dist/field/config/default.js +0 -28
  6. package/dist/field/config/editor-config-context.js +2 -6
  7. package/dist/field/config/extensions-list.d.ts +44 -0
  8. package/dist/field/config/extensions-list.js +55 -0
  9. package/dist/field/config/types.d.ts +28 -1
  10. package/dist/field/editor-context.d.ts +1 -1
  11. package/dist/field/editor-context.js +39 -35
  12. package/dist/field/editor.js +11 -57
  13. package/dist/field/{plugins/admonition-plugin/index.d.ts → extensions/admonition/admonition-extension.d.ts} +2 -1
  14. package/dist/field/{plugins/admonition-plugin/index.js → extensions/admonition/admonition-extension.js} +51 -4
  15. package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.d.ts +1 -1
  16. package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.js +1 -1
  17. package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node.d.ts +1 -1
  18. package/dist/field/{plugins/admonition-plugin → extensions/admonition}/fields.d.ts +1 -1
  19. package/dist/field/{nodes/admonition-node → extensions/admonition}/index.js +1 -1
  20. package/dist/field/{plugins/admonition-plugin → extensions/admonition}/types.d.ts +1 -1
  21. package/dist/field/{plugins/auto-embed-plugin/index.d.ts → extensions/auto-embed/auto-embed-extension.d.ts} +1 -0
  22. package/dist/field/{plugins/auto-embed-plugin/index.js → extensions/auto-embed/auto-embed-extension.js} +47 -4
  23. package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.d.ts +1 -1
  24. package/dist/field/extensions/byline-floating-ui/byline-floating-ui-extension.d.ts +68 -0
  25. package/dist/field/extensions/byline-floating-ui/byline-floating-ui-extension.js +19 -0
  26. package/dist/field/{nodes/admonition-node → extensions/byline-floating-ui}/index.d.ts +1 -2
  27. package/dist/field/extensions/byline-floating-ui/index.js +1 -0
  28. package/dist/field/extensions/byline-toolbar/byline-toolbar-extension.d.ts +69 -0
  29. package/dist/field/extensions/byline-toolbar/byline-toolbar-extension.js +19 -0
  30. package/dist/field/{nodes/inline-image-node → extensions/byline-toolbar}/index.d.ts +1 -2
  31. package/dist/field/extensions/byline-toolbar/index.js +1 -0
  32. package/dist/field/extensions/code-highlight/code-highlight-extension.d.ts +10 -0
  33. package/dist/field/extensions/code-highlight/code-highlight-extension.js +11 -0
  34. package/dist/field/extensions/floating-text-format/floating-text-format-extension.d.ts +18 -0
  35. package/dist/field/extensions/floating-text-format/floating-text-format-extension.js +17 -0
  36. package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.js +1 -1
  37. package/dist/field/extensions/horizontal-rule/horizontal-rule-extension.d.ts +6 -0
  38. package/dist/field/extensions/horizontal-rule/horizontal-rule-extension.js +45 -0
  39. package/dist/field/{nodes/inline-image-node → extensions/inline-image}/index.js +1 -1
  40. package/dist/field/{plugins/inline-image-plugin/index.d.ts → extensions/inline-image/inline-image-extension.d.ts} +6 -3
  41. package/dist/field/{plugins/inline-image-plugin/index.js → extensions/inline-image/inline-image-extension.js} +57 -5
  42. package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.d.ts +2 -2
  43. package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.js +4 -4
  44. package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.d.ts +2 -2
  45. package/dist/field/{nodes/inline-image-node/types.d.ts → extensions/inline-image/node-types.d.ts} +1 -1
  46. package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/types.d.ts +1 -1
  47. package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.d.ts +1 -1
  48. package/dist/field/{plugins/layout-plugin/layout-plugin.d.ts → extensions/layout/layout-extension.d.ts} +1 -0
  49. package/dist/field/{plugins/layout-plugin/layout-plugin.js → extensions/layout/layout-extension.js} +53 -5
  50. package/dist/field/extensions/link/auto-link-extension.d.ts +12 -0
  51. package/dist/field/{plugins/link-plugin/auto-link/index.js → extensions/link/auto-link-extension.js} +14 -2
  52. package/dist/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.d.ts +1 -1
  53. package/dist/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.js +2 -2
  54. package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.css +2 -2
  55. package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.js +4 -4
  56. package/dist/field/extensions/link/index.d.ts +5 -0
  57. package/dist/field/extensions/link/index.js +5 -0
  58. package/dist/field/extensions/link/link-extension.d.ts +14 -0
  59. package/dist/field/extensions/link/link-extension.js +66 -0
  60. package/dist/field/{plugins/link-plugin/link/types.d.ts → extensions/link/link-modal-types.d.ts} +1 -1
  61. package/dist/field/{plugins/link-plugin → extensions}/link/link-modal.d.ts +1 -1
  62. package/dist/field/{plugins/link-plugin → extensions}/link/link-modal.js +3 -3
  63. package/dist/field/{nodes/link-nodes → extensions/link}/types.d.ts +1 -1
  64. package/dist/field/extensions/table/table-action-menu-plugin/index.d.ts +4 -0
  65. package/dist/field/{plugins → extensions/table}/table-action-menu-plugin/index.js +8 -6
  66. package/dist/field/extensions/table/table-extension.d.ts +17 -0
  67. package/dist/field/extensions/table/table-extension.js +58 -0
  68. package/dist/field/extensions/vimeo/vimeo-extension.d.ts +12 -0
  69. package/dist/field/extensions/vimeo/vimeo-extension.js +16 -0
  70. package/dist/field/extensions/youtube/youtube-extension.d.ts +12 -0
  71. package/dist/field/extensions/youtube/youtube-extension.js +16 -0
  72. package/dist/field/nodes/index.js +7 -7
  73. package/dist/field/plugins/table-plugin/index.js +5 -6
  74. package/dist/field/plugins/toolbar-plugin/index.js +40 -114
  75. package/dist/field/plugins/toolbar-plugin/toolbar-active-editor.d.ts +25 -0
  76. package/dist/field/plugins/toolbar-plugin/toolbar-active-editor.js +17 -0
  77. package/dist/field/themes/lexical-editor-theme.css +13 -3
  78. package/dist/field/themes/lexical-editor-theme.js +1 -0
  79. package/dist/index.d.ts +17 -1
  80. package/dist/index.js +16 -0
  81. package/dist/lexical-editor.d.ts +25 -13
  82. package/dist/lexical-editor.js +9 -1
  83. package/dist/richtext-field.js +6 -1
  84. package/dist/server.d.ts +2 -2
  85. package/dist/server.js +2 -2
  86. package/package.json +7 -10
  87. package/src/field/apply-value-plugin.tsx +6 -6
  88. package/src/field/config/default-extensions.ts +104 -0
  89. package/src/field/config/default.ts +8 -28
  90. package/src/field/config/editor-config-context.tsx +1 -7
  91. package/src/field/config/extensions-list.ts +107 -0
  92. package/src/field/config/types.ts +28 -28
  93. package/src/field/editor-context.tsx +77 -41
  94. package/src/field/editor.tsx +24 -72
  95. package/src/field/extensions/README.md +31 -0
  96. package/src/field/{plugins/admonition-plugin/index.tsx → extensions/admonition/admonition-extension.tsx} +45 -2
  97. package/src/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.tsx +1 -1
  98. package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.tsx +5 -5
  99. package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node.tsx +1 -1
  100. package/src/field/{plugins/admonition-plugin → extensions/admonition}/fields.ts +1 -1
  101. package/src/field/{nodes/admonition-node → extensions/admonition}/index.ts +5 -1
  102. package/src/field/{plugins/admonition-plugin → extensions/admonition}/types.ts +1 -1
  103. package/src/field/{plugins/auto-embed-plugin/index.tsx → extensions/auto-embed/auto-embed-extension.tsx} +46 -3
  104. package/src/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.tsx +1 -1
  105. package/src/field/extensions/byline-floating-ui/byline-floating-ui-extension.ts +90 -0
  106. package/src/field/extensions/byline-floating-ui/index.ts +15 -0
  107. package/src/field/extensions/byline-toolbar/byline-toolbar-extension.ts +95 -0
  108. package/src/field/extensions/byline-toolbar/index.ts +15 -0
  109. package/src/field/extensions/code-highlight/code-highlight-extension.ts +18 -0
  110. package/src/field/extensions/floating-text-format/floating-text-format-extension.ts +39 -0
  111. package/src/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.tsx +1 -1
  112. package/src/field/extensions/horizontal-rule/horizontal-rule-extension.tsx +57 -0
  113. package/src/field/{nodes/inline-image-node → extensions/inline-image}/index.ts +1 -1
  114. package/src/field/{plugins/inline-image-plugin/index.tsx → extensions/inline-image/inline-image-extension.tsx} +54 -6
  115. package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.tsx +1 -1
  116. package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.tsx +6 -6
  117. package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.tsx +2 -2
  118. package/src/field/{nodes/inline-image-node/types.ts → extensions/inline-image/node-types.ts} +1 -1
  119. package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/types.ts +1 -1
  120. package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.ts +1 -1
  121. package/src/field/{plugins/layout-plugin/layout-plugin.tsx → extensions/layout/layout-extension.tsx} +47 -8
  122. package/src/field/{plugins/link-plugin/auto-link/index.tsx → extensions/link/auto-link-extension.tsx} +13 -3
  123. package/src/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.tsx +2 -2
  124. package/src/field/{plugins/link-plugin → extensions}/link/floating-link-editor.css +2 -2
  125. package/src/field/{plugins/link-plugin → extensions}/link/floating-link-editor.tsx +5 -5
  126. package/src/field/extensions/link/index.ts +5 -0
  127. package/src/field/extensions/link/link-extension.tsx +131 -0
  128. package/src/field/{plugins/link-plugin/link/types.ts → extensions/link/link-modal-types.ts} +1 -1
  129. package/src/field/{plugins/link-plugin → extensions}/link/link-modal.tsx +6 -6
  130. package/src/field/{nodes/link-nodes → extensions/link}/types.ts +1 -1
  131. package/src/field/{plugins → extensions/table}/table-action-menu-plugin/index.tsx +12 -8
  132. package/src/field/extensions/table/table-extension.tsx +86 -0
  133. package/src/field/extensions/vimeo/vimeo-extension.ts +36 -0
  134. package/src/field/extensions/youtube/youtube-extension.ts +37 -0
  135. package/src/field/nodes/index.ts +7 -7
  136. package/src/field/plugins/table-plugin/index.tsx +10 -10
  137. package/src/field/plugins/toolbar-plugin/index.tsx +59 -122
  138. package/src/field/plugins/toolbar-plugin/toolbar-active-editor.tsx +48 -0
  139. package/src/field/themes/lexical-editor-theme.css +18 -3
  140. package/src/field/themes/lexical-editor-theme.tsx +1 -0
  141. package/src/index.ts +45 -2
  142. package/src/lexical-editor.tsx +35 -14
  143. package/src/richtext-field.tsx +8 -1
  144. package/src/server.ts +4 -4
  145. package/dist/field/nodes/link-nodes/index.d.ts +0 -3
  146. package/dist/field/nodes/link-nodes/index.js +0 -3
  147. package/dist/field/plugins/code-highlight-plugin/index.d.ts +0 -9
  148. package/dist/field/plugins/code-highlight-plugin/index.js +0 -11
  149. package/dist/field/plugins/link-plugin/auto-link/index.d.ts +0 -9
  150. package/dist/field/plugins/link-plugin/link/index.d.ts +0 -1
  151. package/dist/field/plugins/link-plugin/link/index.js +0 -43
  152. package/dist/field/plugins/table-action-menu-plugin/index.d.ts +0 -5
  153. package/dist/field/plugins/vimeo-plugin/index.d.ts +0 -3
  154. package/dist/field/plugins/vimeo-plugin/index.js +0 -24
  155. package/dist/field/plugins/youtube-plugin/index.d.ts +0 -3
  156. package/dist/field/plugins/youtube-plugin/index.js +0 -24
  157. package/dist/field/toolbar-extensions.d.ts +0 -31
  158. package/dist/field/toolbar-extensions.js +0 -56
  159. package/src/field/nodes/link-nodes/index.ts +0 -3
  160. package/src/field/plugins/code-highlight-plugin/index.ts +0 -23
  161. package/src/field/plugins/link-plugin/link/index.tsx +0 -99
  162. package/src/field/plugins/vimeo-plugin/index.ts +0 -42
  163. package/src/field/plugins/youtube-plugin/index.ts +0 -43
  164. package/src/field/themes/lexical-editor-theme.js +0 -104
  165. package/src/field/toolbar-extensions.tsx +0 -93
  166. /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.css +0 -0
  167. /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.d.ts +0 -0
  168. /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.js +0 -0
  169. /package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.css +0 -0
  170. /package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node.js +0 -0
  171. /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/fields.js +0 -0
  172. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.css +0 -0
  173. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.d.ts +0 -0
  174. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.js +0 -0
  175. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/index.d.ts +0 -0
  176. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/index.js +0 -0
  177. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.css +0 -0
  178. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.d.ts +0 -0
  179. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.js +0 -0
  180. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.css +0 -0
  181. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.d.ts +0 -0
  182. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.js +0 -0
  183. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.css +0 -0
  184. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.d.ts +0 -0
  185. /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.js +0 -0
  186. /package/dist/field/{nodes/admonition-node/types.d.ts → extensions/admonition/node-types.d.ts} +0 -0
  187. /package/dist/field/{nodes/admonition-node/types.js → extensions/admonition/node-types.js} +0 -0
  188. /package/dist/field/{nodes/inline-image-node → extensions/admonition}/types.js +0 -0
  189. /package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.css +0 -0
  190. /package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.js +0 -0
  191. /package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.css +0 -0
  192. /package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.d.ts +0 -0
  193. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.d.ts +0 -0
  194. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.js +0 -0
  195. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.css +0 -0
  196. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.d.ts +0 -0
  197. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.js +0 -0
  198. /package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.css +0 -0
  199. /package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.js +0 -0
  200. /package/dist/field/{nodes/link-nodes/types.js → extensions/inline-image/node-types.js} +0 -0
  201. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.d.ts +0 -0
  202. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.js +0 -0
  203. /package/dist/field/{plugins/admonition-plugin → extensions/inline-image}/types.js +0 -0
  204. /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.js +0 -0
  205. /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.css +0 -0
  206. /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.d.ts +0 -0
  207. /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.js +0 -0
  208. /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.d.ts +0 -0
  209. /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.js +0 -0
  210. /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.d.ts +0 -0
  211. /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.js +0 -0
  212. /package/dist/field/{nodes/link-nodes → extensions/link}/auto-link-node.d.ts +0 -0
  213. /package/dist/field/{nodes/link-nodes → extensions/link}/auto-link-node.js +0 -0
  214. /package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.d.ts +0 -0
  215. /package/dist/field/{plugins/inline-image-plugin/types.js → extensions/link/link-modal-types.js} +0 -0
  216. /package/dist/field/{nodes/link-nodes → extensions/link}/link-node.d.ts +0 -0
  217. /package/dist/field/{nodes/link-nodes → extensions/link}/link-node.js +0 -0
  218. /package/dist/field/{plugins/link-plugin → extensions/link}/populate.d.ts +0 -0
  219. /package/dist/field/{plugins/link-plugin → extensions/link}/populate.js +0 -0
  220. /package/dist/field/{plugins/link-plugin → extensions}/link/types.js +0 -0
  221. /package/dist/field/{nodes/vimeo-node/index.d.ts → extensions/vimeo/vimeo-node.d.ts} +0 -0
  222. /package/dist/field/{nodes/vimeo-node/index.js → extensions/vimeo/vimeo-node.js} +0 -0
  223. /package/dist/field/{nodes/youtube-node/index.d.ts → extensions/youtube/youtube-node.d.ts} +0 -0
  224. /package/dist/field/{nodes/youtube-node/index.js → extensions/youtube/youtube-node.js} +0 -0
  225. /package/src/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.css +0 -0
  226. /package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.css +0 -0
  227. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.css +0 -0
  228. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.js +0 -0
  229. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.tsx +0 -0
  230. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/index.js +0 -0
  231. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/index.ts +0 -0
  232. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.css +0 -0
  233. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.js +0 -0
  234. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.tsx +0 -0
  235. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.css +0 -0
  236. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.js +0 -0
  237. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.tsx +0 -0
  238. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.css +0 -0
  239. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.js +0 -0
  240. /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.tsx +0 -0
  241. /package/src/field/{nodes/admonition-node/types.ts → extensions/admonition/node-types.ts} +0 -0
  242. /package/src/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.css +0 -0
  243. /package/src/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.css +0 -0
  244. /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.ts +0 -0
  245. /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.css +0 -0
  246. /package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.css +0 -0
  247. /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.ts +0 -0
  248. /package/src/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.css +0 -0
  249. /package/src/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.tsx +0 -0
  250. /package/src/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.ts +0 -0
  251. /package/src/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.ts +0 -0
  252. /package/src/field/{nodes/link-nodes → extensions/link}/auto-link-node.ts +0 -0
  253. /package/src/field/{nodes/link-nodes → extensions/link}/link-node.ts +0 -0
  254. /package/src/field/{plugins/link-plugin → extensions/link}/populate.ts +0 -0
  255. /package/src/field/{nodes/vimeo-node/index.tsx → extensions/vimeo/vimeo-node.tsx} +0 -0
  256. /package/src/field/{nodes/youtube-node/index.tsx → extensions/youtube/youtube-node.tsx} +0 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ *
8
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
9
+ */
10
+
11
+ import { $insertNodeToNearestRoot } from '@lexical/utils'
12
+ import {
13
+ COMMAND_PRIORITY_EDITOR,
14
+ createCommand,
15
+ defineExtension,
16
+ type LexicalCommand,
17
+ } from 'lexical'
18
+
19
+ import { $createVimeoNode, VimeoNode } from './vimeo-node'
20
+
21
+ export const INSERT_VIMEO_COMMAND: LexicalCommand<string> = createCommand('INSERT_VIMEO_COMMAND')
22
+
23
+ export const VimeoExtension = defineExtension({
24
+ name: '@byline/richtext-lexical/Vimeo',
25
+ nodes: () => [VimeoNode],
26
+ register: (editor) =>
27
+ editor.registerCommand<string>(
28
+ INSERT_VIMEO_COMMAND,
29
+ (payload) => {
30
+ const vimeoNode = $createVimeoNode(payload)
31
+ $insertNodeToNearestRoot(vimeoNode)
32
+ return true
33
+ },
34
+ COMMAND_PRIORITY_EDITOR
35
+ ),
36
+ })
@@ -0,0 +1,37 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ *
8
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
9
+ */
10
+
11
+ import { $insertNodeToNearestRoot } from '@lexical/utils'
12
+ import {
13
+ COMMAND_PRIORITY_EDITOR,
14
+ createCommand,
15
+ defineExtension,
16
+ type LexicalCommand,
17
+ } from 'lexical'
18
+
19
+ import { $createYouTubeNode, YouTubeNode } from './youtube-node'
20
+
21
+ export const INSERT_YOUTUBE_COMMAND: LexicalCommand<string> =
22
+ createCommand('INSERT_YOUTUBE_COMMAND')
23
+
24
+ export const YouTubeExtension = defineExtension({
25
+ name: '@byline/richtext-lexical/YouTube',
26
+ nodes: () => [YouTubeNode],
27
+ register: (editor) =>
28
+ editor.registerCommand<string>(
29
+ INSERT_YOUTUBE_COMMAND,
30
+ (payload) => {
31
+ const youTubeNode = $createYouTubeNode(payload)
32
+ $insertNodeToNearestRoot(youTubeNode)
33
+ return true
34
+ },
35
+ COMMAND_PRIORITY_EDITOR
36
+ ),
37
+ })
@@ -15,13 +15,13 @@ import { HeadingNode, QuoteNode } from '@lexical/rich-text'
15
15
  import { TableCellNode, TableNode, TableRowNode } from '@lexical/table'
16
16
  import type { Klass, LexicalNode } from 'lexical'
17
17
 
18
- import { AdmonitionNode } from './admonition-node/admonition-node'
19
- import { InlineImageNode } from './inline-image-node/inline-image-node'
20
- import { LayoutContainerNode } from './layout-container-node/layout-container-node'
21
- import { LayoutItemNode } from './layout-container-node/layout-item-node'
22
- import { AutoLinkNode, LinkNode } from './link-nodes'
23
- import { VimeoNode } from './vimeo-node'
24
- import { YouTubeNode } from './youtube-node'
18
+ import { AdmonitionNode } from '../extensions/admonition/admonition-node'
19
+ import { InlineImageNode } from '../extensions/inline-image/inline-image-node'
20
+ import { LayoutContainerNode } from '../extensions/layout/layout-container-node'
21
+ import { LayoutItemNode } from '../extensions/layout/layout-item-node'
22
+ import { AutoLinkNode, LinkNode } from '../extensions/link'
23
+ import { VimeoNode } from '../extensions/vimeo/vimeo-node'
24
+ import { YouTubeNode } from '../extensions/youtube/youtube-node'
25
25
 
26
26
  export const Nodes: Array<Klass<LexicalNode>> = [
27
27
  HeadingNode,
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import * as React from 'react'
4
+ import { useEffect } from 'react'
4
5
 
5
6
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
6
7
  import { COMMAND_PRIORITY_NORMAL, createCommand } from 'lexical'
@@ -13,17 +14,16 @@ export function TablePlugin(): React.JSX.Element {
13
14
  const [editor] = useLexicalComposerContext()
14
15
  const [open, setOpen] = React.useState(false)
15
16
 
16
- editor.registerCommand<null>(
17
- OPEN_TABLE_MODAL_COMMAND,
18
- () => {
19
- if (open === false) {
20
- setOpen(true)
17
+ useEffect(() => {
18
+ return editor.registerCommand<null>(
19
+ OPEN_TABLE_MODAL_COMMAND,
20
+ () => {
21
+ setOpen((prev) => (prev ? prev : true))
21
22
  return true
22
- }
23
- return false
24
- },
25
- COMMAND_PRIORITY_NORMAL
26
- )
23
+ },
24
+ COMMAND_PRIORITY_NORMAL
25
+ )
26
+ }, [editor])
27
27
 
28
28
  const handleOnClose = (): void => {
29
29
  setOpen(false)
@@ -16,27 +16,32 @@
16
16
  *
17
17
  */
18
18
  import type * as React from 'react'
19
- import { Fragment, useCallback, useEffect, useState } from 'react'
19
+ import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'
20
20
 
21
21
  import {
22
22
  $createCodeNode,
23
23
  $isCodeNode,
24
24
  CODE_LANGUAGE_FRIENDLY_NAME_MAP,
25
25
  CODE_LANGUAGE_MAP,
26
+ CodeNode,
26
27
  getLanguageFriendlyName,
27
28
  } from '@lexical/code'
28
29
  import {
29
30
  $isListNode,
31
+ CheckListExtension,
30
32
  INSERT_CHECK_LIST_COMMAND,
31
33
  INSERT_ORDERED_LIST_COMMAND,
32
34
  INSERT_UNORDERED_LIST_COMMAND,
35
+ ListExtension,
33
36
  ListNode,
34
37
  REMOVE_LIST_COMMAND,
35
38
  } from '@lexical/list'
36
- import { INSERT_EMBED_COMMAND } from '@lexical/react/LexicalAutoEmbedPlugin'
37
39
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
38
40
  import { $isDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode'
39
- import { INSERT_HORIZONTAL_RULE_COMMAND } from '@lexical/react/LexicalHorizontalRuleNode'
41
+ import {
42
+ useExtensionDependency,
43
+ useOptionalExtensionDependency,
44
+ } from '@lexical/react/useExtensionComponent'
40
45
  import {
41
46
  $createHeadingNode,
42
47
  $createQuoteNode,
@@ -76,22 +81,22 @@ import {
76
81
  } from 'lexical'
77
82
 
78
83
  import { useEditorConfig } from '../../config/editor-config-context'
84
+ import {
85
+ BylineToolbarExtension,
86
+ selectToolbarItems,
87
+ } from '../../extensions/byline-toolbar/byline-toolbar-extension'
79
88
  import {
80
89
  $isLinkNode,
81
90
  type LinkAttributes,
91
+ LinkExtension,
82
92
  OPEN_LINK_MODAL_COMMAND,
83
93
  TOGGLE_LINK_COMMAND,
84
- } from '../../nodes/link-nodes'
94
+ } from '../../extensions/link'
85
95
  import { IS_APPLE } from '../../shared/environment'
86
- import { useToolbarExtensions } from '../../toolbar-extensions'
87
96
  import { DropDown, DropDownItem } from '../../ui/dropdown'
88
97
  import { getSelectedNode } from '../../utils/getSelectedNode'
89
98
  import { sanitizeUrl } from '../../utils/url'
90
- import { OPEN_ADMONITION_MODAL_COMMAND } from '../admonition-plugin'
91
- import { EmbedConfigs } from '../auto-embed-plugin'
92
- import { OPEN_INLINE_IMAGE_MODAL_COMMAND } from '../inline-image-plugin'
93
- import { OPEN_INSERT_LAYOUT_MODAL_COMMAND } from '../layout-plugin/layout-plugin'
94
- import { OPEN_TABLE_MODAL_COMMAND } from '../table-plugin'
99
+ import { ToolbarActiveEditorProvider } from './toolbar-active-editor'
95
100
 
96
101
  const blockTypeToBlockName = {
97
102
  bullet: 'Bulleted List',
@@ -141,11 +146,14 @@ function BlockFormatDropDown({
141
146
  editor: LexicalEditor
142
147
  disabled?: boolean
143
148
  }): React.JSX.Element {
144
- const {
145
- config: {
146
- options: { checkListPlugin, listPlugin, codeHighlightPlugin },
147
- },
148
- } = useEditorConfig()
149
+ // Block-format dropdown entries are gated on whether the underlying
150
+ // extensions are present in the editor's extension graph. Removing
151
+ // ListExtension via lexicalEditor((c) => c.extensions.remove(ListExtension))
152
+ // hides the list options here without any flag in EditorSettings.
153
+ const hasList = useOptionalExtensionDependency(ListExtension) !== undefined
154
+ const hasCheckList = useOptionalExtensionDependency(CheckListExtension) !== undefined
155
+ const [composerEditor] = useLexicalComposerContext()
156
+ const hasCodeHighlight = composerEditor.hasNodes([CodeNode])
149
157
 
150
158
  const formatParagraph = (): void => {
151
159
  editor.update(() => {
@@ -275,7 +283,7 @@ function BlockFormatDropDown({
275
283
  <i className="icon h4" />
276
284
  <span className="text">Heading 4</span>
277
285
  </DropDownItem>
278
- {listPlugin && (
286
+ {hasList && (
279
287
  <>
280
288
  <DropDownItem
281
289
  className={`item ${dropDownActiveClass(blockType === 'bullet')}`}
@@ -294,7 +302,7 @@ function BlockFormatDropDown({
294
302
  </>
295
303
  )}
296
304
 
297
- {checkListPlugin && (
305
+ {hasCheckList && (
298
306
  <DropDownItem
299
307
  className={`item ${dropDownActiveClass(blockType === 'check')}`}
300
308
  onClick={formatCheckList}
@@ -311,7 +319,7 @@ function BlockFormatDropDown({
311
319
  <i className="icon quote" />
312
320
  <span className="text">Quote</span>
313
321
  </DropDownItem>
314
- {codeHighlightPlugin && (
322
+ {hasCodeHighlight && (
315
323
  <DropDownItem
316
324
  className={`item ${dropDownActiveClass(blockType === 'code')}`}
317
325
  onClick={formatCode}
@@ -351,23 +359,20 @@ export function ToolbarPlugin(): React.JSX.Element {
351
359
  const [isRTL, _setIsRTL] = useState(false)
352
360
  const [codeLanguage, setCodeLanguage] = useState<string>('')
353
361
  const [isEditable, setIsEditable] = useState(() => editor.isEditable())
354
- const { items: toolbarExtensionItems } = useToolbarExtensions()
362
+ const { config: toolbarConfig } = useExtensionDependency(BylineToolbarExtension)
363
+ const insertMenuItems = useMemo(
364
+ () => selectToolbarItems(toolbarConfig.items, 'insert-menu'),
365
+ [toolbarConfig.items]
366
+ )
367
+ const trailingToolbarItems = useMemo(
368
+ () => selectToolbarItems(toolbarConfig.items, 'toolbar'),
369
+ [toolbarConfig.items]
370
+ )
371
+ const hasLinkExtension = useOptionalExtensionDependency(LinkExtension) !== undefined
355
372
  const {
356
373
  uuid,
357
374
  config: {
358
- options: {
359
- textAlignment,
360
- tablePlugin,
361
- inlineImagePlugin,
362
- admonitionPlugin,
363
- horizontalRulePlugin,
364
- layoutPlugin,
365
- autoEmbedPlugin,
366
- undoRedo,
367
- textStyle,
368
- inlineCode,
369
- links,
370
- },
375
+ options: { textAlignment, undoRedo, textStyle, inlineCode },
371
376
  },
372
377
  } = useEditorConfig()
373
378
  // const { openModal } = usePayloadModal()
@@ -773,7 +778,7 @@ export function ToolbarPlugin(): React.JSX.Element {
773
778
  <i className="format code" />
774
779
  </button>
775
780
  )}
776
- {links && (
781
+ {hasLinkExtension && (
777
782
  <button
778
783
  key="link"
779
784
  type="button"
@@ -838,100 +843,32 @@ export function ToolbarPlugin(): React.JSX.Element {
838
843
  </DropDownItem>
839
844
  </DropDown>
840
845
 
841
- {activeEditor === editor &&
842
- (horizontalRulePlugin || inlineImagePlugin || tablePlugin || admonitionPlugin) && (
843
- <>
844
- <Divider />
845
- <DropDown
846
- disabled={!isEditable}
847
- buttonClassName="toolbar-item spaced"
848
- buttonLabel="Insert"
849
- buttonAriaLabel="Insert specialized editor node"
850
- buttonIconClassName="icon plus"
851
- >
852
- {horizontalRulePlugin && (
853
- <DropDownItem
854
- onClick={() => {
855
- activeEditor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined)
856
- }}
857
- className="item"
858
- >
859
- <i className="icon horizontal-rule" />
860
- <span className="text">Horizontal Rule</span>
861
- </DropDownItem>
862
- )}
863
-
864
- {layoutPlugin && (
865
- <DropDownItem
866
- onClick={() => {
867
- activeEditor.dispatchCommand(OPEN_INSERT_LAYOUT_MODAL_COMMAND, null)
868
- }}
869
- className="item"
870
- >
871
- <i className="icon columns" />
872
- <span className="text">Columns Layout</span>
873
- </DropDownItem>
874
- )}
875
-
876
- {admonitionPlugin && (
877
- <DropDownItem
878
- onClick={() => {
879
- activeEditor.dispatchCommand(OPEN_ADMONITION_MODAL_COMMAND, null)
880
- }}
881
- className="item"
882
- >
883
- <i className="icon admonition" />
884
- <span className="text">Admonition</span>
885
- </DropDownItem>
886
- )}
887
-
888
- {inlineImagePlugin && (
889
- <DropDownItem
890
- onClick={() => {
891
- activeEditor.dispatchCommand(OPEN_INLINE_IMAGE_MODAL_COMMAND, null)
892
- }}
893
- className="item"
894
- >
895
- <i className="icon image" />
896
- <span className="text">Inline Image</span>
897
- </DropDownItem>
898
- )}
899
- {tablePlugin && (
900
- <DropDownItem
901
- onClick={() => {
902
- activeEditor.dispatchCommand(OPEN_TABLE_MODAL_COMMAND, null)
903
- }}
904
- className="item"
905
- >
906
- <i className="icon table" />
907
- <span className="text">Table</span>
908
- </DropDownItem>
909
- )}
910
- {autoEmbedPlugin &&
911
- EmbedConfigs.map((embedConfig) => (
912
- <DropDownItem
913
- key={embedConfig.type}
914
- onClick={() => {
915
- activeEditor.dispatchCommand(INSERT_EMBED_COMMAND, embedConfig.type)
916
- }}
917
- className="item"
918
- >
919
- {embedConfig.icon}
920
- <span className="text">{embedConfig.contentName}</span>
921
- </DropDownItem>
922
- ))}
923
- </DropDown>
924
- </>
925
- )}
846
+ {activeEditor === editor && insertMenuItems.length > 0 && (
847
+ <>
848
+ <Divider />
849
+ <DropDown
850
+ disabled={!isEditable}
851
+ buttonClassName="toolbar-item spaced"
852
+ buttonLabel="Insert"
853
+ buttonAriaLabel="Insert specialized editor node"
854
+ buttonIconClassName="icon plus"
855
+ >
856
+ <ToolbarActiveEditorProvider editor={activeEditor}>
857
+ {insertMenuItems.map((item) => (
858
+ <Fragment key={item.id}>{item.node}</Fragment>
859
+ ))}
860
+ </ToolbarActiveEditorProvider>
861
+ </DropDown>
862
+ </>
863
+ )}
926
864
  </>
927
865
  )}
928
866
 
929
- {toolbarExtensionItems
930
- .slice()
931
- .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
932
- .map((item) => (
867
+ <ToolbarActiveEditorProvider editor={activeEditor}>
868
+ {trailingToolbarItems.map((item) => (
933
869
  <Fragment key={item.id}>{item.node}</Fragment>
934
870
  ))}
871
+ </ToolbarActiveEditorProvider>
935
872
  </div>
936
873
  )
937
874
  }
@@ -0,0 +1,48 @@
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 { createContext, useContext } from 'react'
13
+
14
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
15
+ import type { LexicalEditor } from 'lexical'
16
+
17
+ const ToolbarActiveEditorContext = createContext<LexicalEditor | null>(null)
18
+
19
+ /**
20
+ * Provider used by the toolbar plugin to expose the *active* Lexical
21
+ * editor (the editor for the current selection — may be a nested
22
+ * composer's editor) to contributed toolbar items.
23
+ */
24
+ export function ToolbarActiveEditorProvider({
25
+ editor,
26
+ children,
27
+ }: {
28
+ editor: LexicalEditor
29
+ children: React.ReactNode
30
+ }): React.JSX.Element {
31
+ return (
32
+ <ToolbarActiveEditorContext.Provider value={editor}>
33
+ {children}
34
+ </ToolbarActiveEditorContext.Provider>
35
+ )
36
+ }
37
+
38
+ /**
39
+ * Returns the editor a toolbar contribution should dispatch commands on.
40
+ * Falls back to the root composer editor when called outside the
41
+ * toolbar's provider, so contributions remain usable in standalone
42
+ * test/preview contexts.
43
+ */
44
+ export function useToolbarActiveEditor(): LexicalEditor {
45
+ const fromToolbar = useContext(ToolbarActiveEditorContext)
46
+ const [composerEditor] = useLexicalComposerContext()
47
+ return fromToolbar ?? composerEditor
48
+ }
@@ -112,7 +112,8 @@
112
112
  font-family: Menlo, Consolas, Monaco, monospace;
113
113
  }
114
114
 
115
- html[data-theme="dark"] .LexicalEditorTheme__textCode {
115
+ html[data-theme="dark"] .LexicalEditorTheme__textCode,
116
+ .dark .LexicalEditorTheme__textCode {
116
117
  color: #f1f5f9;
117
118
  background-color: #1e293b;
118
119
  border-color: #495362;
@@ -165,11 +166,13 @@ html[data-theme="dark"] .LexicalEditorTheme__textCode {
165
166
  min-width: 25px;
166
167
  }
167
168
 
168
- html[data-theme="dark"] .LexicalEditorTheme__code {
169
+ html[data-theme="dark"] .LexicalEditorTheme__code,
170
+ .dark .LexicalEditorTheme__code {
169
171
  background-color: #1a1a1a;
170
172
  }
171
173
 
172
- html[data-theme="dark"] .LexicalEditorTheme__code:before {
174
+ html[data-theme="dark"] .LexicalEditorTheme__code:before,
175
+ .dark .LexicalEditorTheme__code:before {
173
176
  background-color: #161616;
174
177
  border-right: 1px solid #ccc;
175
178
  color: #777;
@@ -185,6 +188,18 @@ html[data-theme="dark"] .LexicalEditorTheme__code:before {
185
188
  margin: 30px 0;
186
189
  }
187
190
 
191
+ .LexicalEditorTheme__tableScrollableWrapper {
192
+ overflow-x: auto;
193
+ margin: 30px 0;
194
+ }
195
+
196
+ /* When wrapped for horizontal scroll, the wrapper owns the vertical margin
197
+ so the table's own margin doesn't compound it. */
198
+ .LexicalEditorTheme__tableScrollableWrapper > .LexicalEditorTheme__table {
199
+ margin-top: 0;
200
+ margin-bottom: 0;
201
+ }
202
+
188
203
  .LexicalEditorTheme__tableSelected {
189
204
  outline: 2px solid rgb(60, 132, 244);
190
205
  }
@@ -101,6 +101,7 @@ export const theme: EditorThemeClasses = {
101
101
  tableCellSelected: 'LexicalEditorTheme__tableCellSelected',
102
102
  tableCellSortedIndicator: 'LexicalEditorTheme__tableCellSortedIndicator',
103
103
  tableResizeRuler: 'LexicalEditorTheme__tableCellResizeRuler',
104
+ tableScrollableWrapper: 'LexicalEditorTheme__tableScrollableWrapper',
104
105
  tableSelected: 'LexicalEditorTheme__tableSelected',
105
106
  text: {
106
107
  bold: 'LexicalEditorTheme__textBold',
package/src/index.ts CHANGED
@@ -11,16 +11,59 @@ export type {
11
11
  } from 'lexical'
12
12
 
13
13
  export { defaultEditorConfig } from './field/config/default'
14
+ export {
15
+ defaultClientEditorConfig,
16
+ defaultExtensionsArray,
17
+ defaultExtensionsList,
18
+ } from './field/config/default-extensions'
19
+ export { ExtensionsList } from './field/config/extensions-list'
14
20
  export { EditorField } from './field/editor-field'
21
+ // Built-in extensions exposed for `lexicalEditor((c) => c.extensions...)`
22
+ // manipulation and for third-party extensions to declare against via
23
+ // peer dependencies.
24
+ export { AdmonitionExtension } from './field/extensions/admonition/admonition-extension'
25
+ export { AutoEmbedExtension } from './field/extensions/auto-embed/auto-embed-extension'
26
+ export {
27
+ type BylineFloatingUIConfig,
28
+ BylineFloatingUIExtension,
29
+ type BylineFloatingUIItem,
30
+ type BylineFloatingUIProps,
31
+ selectFloatingUIItems,
32
+ } from './field/extensions/byline-floating-ui'
33
+ export {
34
+ type BylineToolbarConfig,
35
+ BylineToolbarExtension,
36
+ type BylineToolbarItem,
37
+ type BylineToolbarPlacement,
38
+ selectToolbarItems,
39
+ } from './field/extensions/byline-toolbar'
40
+ export { CodeHighlightExtension } from './field/extensions/code-highlight/code-highlight-extension'
41
+ export { FloatingTextFormatExtension } from './field/extensions/floating-text-format/floating-text-format-extension'
42
+ export { HorizontalRuleExtension } from './field/extensions/horizontal-rule/horizontal-rule-extension'
43
+ export {
44
+ type InlineImageConfig,
45
+ InlineImageExtension,
46
+ } from './field/extensions/inline-image/inline-image-extension'
47
+ export { LayoutExtension } from './field/extensions/layout/layout-extension'
48
+ export { AutoLinkExtension, LinkExtension } from './field/extensions/link'
49
+ export { TableExtension } from './field/extensions/table/table-extension'
50
+ export { VimeoExtension } from './field/extensions/vimeo/vimeo-extension'
51
+ export { YouTubeExtension } from './field/extensions/youtube/youtube-extension'
15
52
  export { Nodes } from './field/nodes'
53
+ // Hook for extensions that contribute toolbar items via
54
+ // BylineToolbarExtension and need the active editor for command dispatch.
55
+ export {
56
+ ToolbarActiveEditorProvider,
57
+ useToolbarActiveEditor,
58
+ } from './field/plugins/toolbar-plugin/toolbar-active-editor'
16
59
  export { lexicalEditor } from './lexical-editor'
17
60
  export { RichTextField } from './richtext-field'
18
61
  export { createEmptyEditorState } from './validate/createEmptyEditorState'
19
62
  export { hasText } from './validate/hasText'
20
63
  export type { EditorConfig, EditorSettings, EditorSettingsOverride } from './field/config/types'
21
- export type { DocumentRelation } from './field/nodes/document-relation'
22
64
  export type {
23
65
  InlineImageAttributes,
24
66
  Position as InlineImagePosition,
25
67
  SerializedInlineImageNode,
26
- } from './field/nodes/inline-image-node/types'
68
+ } from './field/extensions/inline-image/node-types'
69
+ export type { DocumentRelation } from './field/nodes/document-relation'
@@ -10,32 +10,46 @@ import type { RichTextEditorComponent } from '@byline/core'
10
10
  import { cloneDeep } from 'lodash-es'
11
11
 
12
12
  import { defaultEditorConfig } from './field/config/default'
13
+ import { defaultExtensionsList } from './field/config/default-extensions'
13
14
  import { RichTextField } from './richtext-field'
15
+ import type { ExtensionsList } from './field/config/extensions-list'
14
16
  import type { EditorConfig } from './field/config/types'
15
17
 
16
18
  /**
17
- * Returns a `RichTextEditorComponent` with editor settings baked in. Use this
18
- * at the registration site in your admin config when you want to
19
- * customise the editor across the whole installation; per-field overrides
20
- * via `RichTextField.editorConfig` continue to take precedence at render time.
19
+ * Inside `lexicalEditor((c) => ...)` the seed always carries an
20
+ * `ExtensionsList`, so narrow the callback parameter so callers can write
21
+ * `c.extensions.add(...)` without a non-null assertion.
22
+ */
23
+ export type LexicalEditorConfigureInput = Omit<EditorConfig, 'extensions'> & {
24
+ extensions: ExtensionsList
25
+ }
26
+
27
+ /**
28
+ * Returns a `RichTextEditorComponent` with editor settings baked in. Use
29
+ * this at the registration site in your admin config when you want to
30
+ * customise the editor across the whole installation; per-field
31
+ * overrides via `RichTextField.editorConfig` continue to take precedence
32
+ * at render time.
21
33
  *
22
- * The `configure` callback receives a deep clone of `defaultEditorConfig`
23
- * mutate and return, or return a new object. Mutating the input is safe
24
- * because the clone is local to this call.
34
+ * The `configure` callback receives a deep clone of `defaultEditorConfig`
35
+ * with `extensions` populated from `defaultExtensionsList()`. Mutate the
36
+ * clone freely it's local to this call. Use the chainable
37
+ * `c.extensions.add(...)`, `.remove(...)`, `.replace(...)`, and
38
+ * `.configure(...)` methods to manipulate the extension graph.
25
39
  *
26
- * Calling `lexicalEditor()` with no argument is equivalent to registering
27
- * `RichTextField` directly.
40
+ * Calling `lexicalEditor()` with no argument is equivalent to
41
+ * registering `RichTextField` directly with the package defaults.
28
42
  *
29
43
  * @example
30
44
  * ```ts
31
- * import { lexicalEditor } from '@byline/richtext-lexical'
45
+ * import { lexicalEditor, TableExtension } from '@byline/richtext-lexical'
32
46
  *
33
47
  * defineClientConfig({
34
48
  * fields: {
35
49
  * richText: {
36
50
  * editor: lexicalEditor((c) => {
37
- * c.settings.options.tablePlugin = false
38
- * c.settings.options.codeHighlightPlugin = false
51
+ * c.extensions.remove(TableExtension) // drop a built-in
52
+ * c.settings.placeholderText = 'Start writing...'
39
53
  * return c
40
54
  * }),
41
55
  * },
@@ -44,9 +58,16 @@ import type { EditorConfig } from './field/config/types'
44
58
  * ```
45
59
  */
46
60
  export function lexicalEditor(
47
- configure?: (config: EditorConfig) => EditorConfig
61
+ configure?: (config: LexicalEditorConfigureInput) => LexicalEditorConfigureInput
48
62
  ): RichTextEditorComponent {
49
- const baked = configure ? configure(cloneDeep(defaultEditorConfig)) : undefined
63
+ let baked: EditorConfig | undefined
64
+ if (configure) {
65
+ const seed: LexicalEditorConfigureInput = {
66
+ ...cloneDeep(defaultEditorConfig),
67
+ extensions: defaultExtensionsList(),
68
+ }
69
+ baked = configure(seed)
70
+ }
50
71
 
51
72
  const ConfiguredEditor: RichTextEditorComponent = (props) => (
52
73
  <RichTextField {...props} editorConfig={baked} />