@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.
- package/dist/field/apply-value-plugin.js +1 -3
- package/dist/field/config/default-extensions.d.ts +32 -0
- package/dist/field/config/default-extensions.js +49 -0
- package/dist/field/config/default.d.ts +8 -0
- package/dist/field/config/default.js +0 -28
- package/dist/field/config/editor-config-context.js +2 -6
- package/dist/field/config/extensions-list.d.ts +44 -0
- package/dist/field/config/extensions-list.js +55 -0
- package/dist/field/config/types.d.ts +28 -1
- package/dist/field/editor-context.d.ts +1 -1
- package/dist/field/editor-context.js +39 -35
- package/dist/field/editor.js +11 -57
- package/dist/field/{plugins/admonition-plugin/index.d.ts → extensions/admonition/admonition-extension.d.ts} +2 -1
- package/dist/field/{plugins/admonition-plugin/index.js → extensions/admonition/admonition-extension.js} +51 -4
- package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.d.ts +1 -1
- package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.js +1 -1
- package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node.d.ts +1 -1
- package/dist/field/{plugins/admonition-plugin → extensions/admonition}/fields.d.ts +1 -1
- package/dist/field/{nodes/admonition-node → extensions/admonition}/index.js +1 -1
- package/dist/field/{plugins/admonition-plugin → extensions/admonition}/types.d.ts +1 -1
- package/dist/field/{plugins/auto-embed-plugin/index.d.ts → extensions/auto-embed/auto-embed-extension.d.ts} +1 -0
- package/dist/field/{plugins/auto-embed-plugin/index.js → extensions/auto-embed/auto-embed-extension.js} +47 -4
- package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.d.ts +1 -1
- package/dist/field/extensions/byline-floating-ui/byline-floating-ui-extension.d.ts +68 -0
- package/dist/field/extensions/byline-floating-ui/byline-floating-ui-extension.js +19 -0
- package/dist/field/{nodes/admonition-node → extensions/byline-floating-ui}/index.d.ts +1 -2
- package/dist/field/extensions/byline-floating-ui/index.js +1 -0
- package/dist/field/extensions/byline-toolbar/byline-toolbar-extension.d.ts +69 -0
- package/dist/field/extensions/byline-toolbar/byline-toolbar-extension.js +19 -0
- package/dist/field/{nodes/inline-image-node → extensions/byline-toolbar}/index.d.ts +1 -2
- package/dist/field/extensions/byline-toolbar/index.js +1 -0
- package/dist/field/extensions/code-highlight/code-highlight-extension.d.ts +10 -0
- package/dist/field/extensions/code-highlight/code-highlight-extension.js +11 -0
- package/dist/field/extensions/floating-text-format/floating-text-format-extension.d.ts +18 -0
- package/dist/field/extensions/floating-text-format/floating-text-format-extension.js +17 -0
- package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.js +1 -1
- package/dist/field/extensions/horizontal-rule/horizontal-rule-extension.d.ts +6 -0
- package/dist/field/extensions/horizontal-rule/horizontal-rule-extension.js +45 -0
- package/dist/field/{nodes/inline-image-node → extensions/inline-image}/index.js +1 -1
- package/dist/field/{plugins/inline-image-plugin/index.d.ts → extensions/inline-image/inline-image-extension.d.ts} +6 -3
- package/dist/field/{plugins/inline-image-plugin/index.js → extensions/inline-image/inline-image-extension.js} +57 -5
- package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.d.ts +2 -2
- package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.js +4 -4
- package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.d.ts +2 -2
- package/dist/field/{nodes/inline-image-node/types.d.ts → extensions/inline-image/node-types.d.ts} +1 -1
- package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/types.d.ts +1 -1
- package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.d.ts +1 -1
- package/dist/field/{plugins/layout-plugin/layout-plugin.d.ts → extensions/layout/layout-extension.d.ts} +1 -0
- package/dist/field/{plugins/layout-plugin/layout-plugin.js → extensions/layout/layout-extension.js} +53 -5
- package/dist/field/extensions/link/auto-link-extension.d.ts +12 -0
- package/dist/field/{plugins/link-plugin/auto-link/index.js → extensions/link/auto-link-extension.js} +14 -2
- package/dist/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.d.ts +1 -1
- package/dist/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.js +2 -2
- package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.css +2 -2
- package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.js +4 -4
- package/dist/field/extensions/link/index.d.ts +5 -0
- package/dist/field/extensions/link/index.js +5 -0
- package/dist/field/extensions/link/link-extension.d.ts +14 -0
- package/dist/field/extensions/link/link-extension.js +66 -0
- package/dist/field/{plugins/link-plugin/link/types.d.ts → extensions/link/link-modal-types.d.ts} +1 -1
- package/dist/field/{plugins/link-plugin → extensions}/link/link-modal.d.ts +1 -1
- package/dist/field/{plugins/link-plugin → extensions}/link/link-modal.js +3 -3
- package/dist/field/{nodes/link-nodes → extensions/link}/types.d.ts +1 -1
- package/dist/field/extensions/table/table-action-menu-plugin/index.d.ts +4 -0
- package/dist/field/{plugins → extensions/table}/table-action-menu-plugin/index.js +8 -6
- package/dist/field/extensions/table/table-extension.d.ts +17 -0
- package/dist/field/extensions/table/table-extension.js +58 -0
- package/dist/field/extensions/vimeo/vimeo-extension.d.ts +12 -0
- package/dist/field/extensions/vimeo/vimeo-extension.js +16 -0
- package/dist/field/extensions/youtube/youtube-extension.d.ts +12 -0
- package/dist/field/extensions/youtube/youtube-extension.js +16 -0
- package/dist/field/nodes/index.js +7 -7
- package/dist/field/plugins/table-plugin/index.js +5 -6
- package/dist/field/plugins/toolbar-plugin/index.js +40 -114
- package/dist/field/plugins/toolbar-plugin/toolbar-active-editor.d.ts +25 -0
- package/dist/field/plugins/toolbar-plugin/toolbar-active-editor.js +17 -0
- package/dist/field/themes/lexical-editor-theme.css +13 -3
- package/dist/field/themes/lexical-editor-theme.js +1 -0
- package/dist/index.d.ts +17 -1
- package/dist/index.js +16 -0
- package/dist/lexical-editor.d.ts +25 -13
- package/dist/lexical-editor.js +9 -1
- package/dist/richtext-field.js +6 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/package.json +7 -10
- package/src/field/apply-value-plugin.tsx +6 -6
- package/src/field/config/default-extensions.ts +104 -0
- package/src/field/config/default.ts +8 -28
- package/src/field/config/editor-config-context.tsx +1 -7
- package/src/field/config/extensions-list.ts +107 -0
- package/src/field/config/types.ts +28 -28
- package/src/field/editor-context.tsx +77 -41
- package/src/field/editor.tsx +24 -72
- package/src/field/extensions/README.md +31 -0
- package/src/field/{plugins/admonition-plugin/index.tsx → extensions/admonition/admonition-extension.tsx} +45 -2
- package/src/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.tsx +1 -1
- package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.tsx +5 -5
- package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node.tsx +1 -1
- package/src/field/{plugins/admonition-plugin → extensions/admonition}/fields.ts +1 -1
- package/src/field/{nodes/admonition-node → extensions/admonition}/index.ts +5 -1
- package/src/field/{plugins/admonition-plugin → extensions/admonition}/types.ts +1 -1
- package/src/field/{plugins/auto-embed-plugin/index.tsx → extensions/auto-embed/auto-embed-extension.tsx} +46 -3
- package/src/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.tsx +1 -1
- package/src/field/extensions/byline-floating-ui/byline-floating-ui-extension.ts +90 -0
- package/src/field/extensions/byline-floating-ui/index.ts +15 -0
- package/src/field/extensions/byline-toolbar/byline-toolbar-extension.ts +95 -0
- package/src/field/extensions/byline-toolbar/index.ts +15 -0
- package/src/field/extensions/code-highlight/code-highlight-extension.ts +18 -0
- package/src/field/extensions/floating-text-format/floating-text-format-extension.ts +39 -0
- package/src/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.tsx +1 -1
- package/src/field/extensions/horizontal-rule/horizontal-rule-extension.tsx +57 -0
- package/src/field/{nodes/inline-image-node → extensions/inline-image}/index.ts +1 -1
- package/src/field/{plugins/inline-image-plugin/index.tsx → extensions/inline-image/inline-image-extension.tsx} +54 -6
- package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.tsx +1 -1
- package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.tsx +6 -6
- package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.tsx +2 -2
- package/src/field/{nodes/inline-image-node/types.ts → extensions/inline-image/node-types.ts} +1 -1
- package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/types.ts +1 -1
- package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.ts +1 -1
- package/src/field/{plugins/layout-plugin/layout-plugin.tsx → extensions/layout/layout-extension.tsx} +47 -8
- package/src/field/{plugins/link-plugin/auto-link/index.tsx → extensions/link/auto-link-extension.tsx} +13 -3
- package/src/field/{plugins/link-plugin/auto-link → extensions/link}/auto-link-plugin.tsx +2 -2
- package/src/field/{plugins/link-plugin → extensions}/link/floating-link-editor.css +2 -2
- package/src/field/{plugins/link-plugin → extensions}/link/floating-link-editor.tsx +5 -5
- package/src/field/extensions/link/index.ts +5 -0
- package/src/field/extensions/link/link-extension.tsx +131 -0
- package/src/field/{plugins/link-plugin/link/types.ts → extensions/link/link-modal-types.ts} +1 -1
- package/src/field/{plugins/link-plugin → extensions}/link/link-modal.tsx +6 -6
- package/src/field/{nodes/link-nodes → extensions/link}/types.ts +1 -1
- package/src/field/{plugins → extensions/table}/table-action-menu-plugin/index.tsx +12 -8
- package/src/field/extensions/table/table-extension.tsx +86 -0
- package/src/field/extensions/vimeo/vimeo-extension.ts +36 -0
- package/src/field/extensions/youtube/youtube-extension.ts +37 -0
- package/src/field/nodes/index.ts +7 -7
- package/src/field/plugins/table-plugin/index.tsx +10 -10
- package/src/field/plugins/toolbar-plugin/index.tsx +59 -122
- package/src/field/plugins/toolbar-plugin/toolbar-active-editor.tsx +48 -0
- package/src/field/themes/lexical-editor-theme.css +18 -3
- package/src/field/themes/lexical-editor-theme.tsx +1 -0
- package/src/index.ts +45 -2
- package/src/lexical-editor.tsx +35 -14
- package/src/richtext-field.tsx +8 -1
- package/src/server.ts +4 -4
- package/dist/field/nodes/link-nodes/index.d.ts +0 -3
- package/dist/field/nodes/link-nodes/index.js +0 -3
- package/dist/field/plugins/code-highlight-plugin/index.d.ts +0 -9
- package/dist/field/plugins/code-highlight-plugin/index.js +0 -11
- package/dist/field/plugins/link-plugin/auto-link/index.d.ts +0 -9
- package/dist/field/plugins/link-plugin/link/index.d.ts +0 -1
- package/dist/field/plugins/link-plugin/link/index.js +0 -43
- package/dist/field/plugins/table-action-menu-plugin/index.d.ts +0 -5
- package/dist/field/plugins/vimeo-plugin/index.d.ts +0 -3
- package/dist/field/plugins/vimeo-plugin/index.js +0 -24
- package/dist/field/plugins/youtube-plugin/index.d.ts +0 -3
- package/dist/field/plugins/youtube-plugin/index.js +0 -24
- package/dist/field/toolbar-extensions.d.ts +0 -31
- package/dist/field/toolbar-extensions.js +0 -56
- package/src/field/nodes/link-nodes/index.ts +0 -3
- package/src/field/plugins/code-highlight-plugin/index.ts +0 -23
- package/src/field/plugins/link-plugin/link/index.tsx +0 -99
- package/src/field/plugins/vimeo-plugin/index.ts +0 -42
- package/src/field/plugins/youtube-plugin/index.ts +0 -43
- package/src/field/themes/lexical-editor-theme.js +0 -104
- package/src/field/toolbar-extensions.tsx +0 -93
- /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.css +0 -0
- /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.d.ts +0 -0
- /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.css +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/admonition-node.js +0 -0
- /package/dist/field/{plugins/admonition-plugin → extensions/admonition}/fields.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.css +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.d.ts +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/index.d.ts +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/index.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.css +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.d.ts +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.css +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.d.ts +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.js +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.css +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.d.ts +0 -0
- /package/dist/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.js +0 -0
- /package/dist/field/{nodes/admonition-node/types.d.ts → extensions/admonition/node-types.d.ts} +0 -0
- /package/dist/field/{nodes/admonition-node/types.js → extensions/admonition/node-types.js} +0 -0
- /package/dist/field/{nodes/inline-image-node → extensions/admonition}/types.js +0 -0
- /package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.css +0 -0
- /package/dist/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.js +0 -0
- /package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.css +0 -0
- /package/dist/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.d.ts +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.d.ts +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.js +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.css +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.d.ts +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.js +0 -0
- /package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.css +0 -0
- /package/dist/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node.js +0 -0
- /package/dist/field/{nodes/link-nodes/types.js → extensions/inline-image/node-types.js} +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.d.ts +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.js +0 -0
- /package/dist/field/{plugins/admonition-plugin → extensions/inline-image}/types.js +0 -0
- /package/dist/field/{plugins/inline-image-plugin → extensions/inline-image}/utils.js +0 -0
- /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.css +0 -0
- /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.d.ts +0 -0
- /package/dist/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.js +0 -0
- /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.d.ts +0 -0
- /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.js +0 -0
- /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.d.ts +0 -0
- /package/dist/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.js +0 -0
- /package/dist/field/{nodes/link-nodes → extensions/link}/auto-link-node.d.ts +0 -0
- /package/dist/field/{nodes/link-nodes → extensions/link}/auto-link-node.js +0 -0
- /package/dist/field/{plugins/link-plugin → extensions}/link/floating-link-editor.d.ts +0 -0
- /package/dist/field/{plugins/inline-image-plugin/types.js → extensions/link/link-modal-types.js} +0 -0
- /package/dist/field/{nodes/link-nodes → extensions/link}/link-node.d.ts +0 -0
- /package/dist/field/{nodes/link-nodes → extensions/link}/link-node.js +0 -0
- /package/dist/field/{plugins/link-plugin → extensions/link}/populate.d.ts +0 -0
- /package/dist/field/{plugins/link-plugin → extensions/link}/populate.js +0 -0
- /package/dist/field/{plugins/link-plugin → extensions}/link/types.js +0 -0
- /package/dist/field/{nodes/vimeo-node/index.d.ts → extensions/vimeo/vimeo-node.d.ts} +0 -0
- /package/dist/field/{nodes/vimeo-node/index.js → extensions/vimeo/vimeo-node.js} +0 -0
- /package/dist/field/{nodes/youtube-node/index.d.ts → extensions/youtube/youtube-node.d.ts} +0 -0
- /package/dist/field/{nodes/youtube-node/index.js → extensions/youtube/youtube-node.js} +0 -0
- /package/src/field/{plugins/admonition-plugin → extensions/admonition}/admonition-modal.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/admonition-node-component.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.js +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/danger-icon.tsx +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/index.js +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/index.ts +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.js +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/note-icon.tsx +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.js +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/tip-icon.tsx +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.css +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.js +0 -0
- /package/src/field/{nodes/admonition-node → extensions/admonition}/icons/warning-icon.tsx +0 -0
- /package/src/field/{nodes/admonition-node/types.ts → extensions/admonition/node-types.ts} +0 -0
- /package/src/field/{plugins/auto-embed-plugin → extensions/auto-embed}/auto-embed-modal.css +0 -0
- /package/src/field/{plugins/floating-text-format-toolbar-plugin → extensions/floating-text-format}/index.css +0 -0
- /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/fields.ts +0 -0
- /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/inline-image-modal.css +0 -0
- /package/src/field/{nodes/inline-image-node → extensions/inline-image}/inline-image-node-component.css +0 -0
- /package/src/field/{plugins/inline-image-plugin → extensions/inline-image}/populate.ts +0 -0
- /package/src/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.css +0 -0
- /package/src/field/{plugins/layout-plugin → extensions/layout}/insert-layout-modal.tsx +0 -0
- /package/src/field/{nodes/layout-container-node → extensions/layout}/layout-container-node.ts +0 -0
- /package/src/field/{nodes/layout-container-node → extensions/layout}/layout-item-node.ts +0 -0
- /package/src/field/{nodes/link-nodes → extensions/link}/auto-link-node.ts +0 -0
- /package/src/field/{nodes/link-nodes → extensions/link}/link-node.ts +0 -0
- /package/src/field/{plugins/link-plugin → extensions/link}/populate.ts +0 -0
- /package/src/field/{nodes/vimeo-node/index.tsx → extensions/vimeo/vimeo-node.tsx} +0 -0
- /package/src/field/{nodes/youtube-node/index.tsx → extensions/youtube/youtube-node.tsx} +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Client-only — pulls in every built-in extension along with their React
|
|
11
|
+
* decorators and modal components. The `/server` entry never imports
|
|
12
|
+
* this file.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
AutoFocusExtension,
|
|
17
|
+
ClearEditorExtension,
|
|
18
|
+
TabIndentationExtension,
|
|
19
|
+
} from '@lexical/extension'
|
|
20
|
+
import { CheckListExtension, ListExtension } from '@lexical/list'
|
|
21
|
+
import type { AnyLexicalExtensionArgument } from 'lexical'
|
|
22
|
+
|
|
23
|
+
import { AdmonitionExtension } from '../extensions/admonition/admonition-extension'
|
|
24
|
+
import { AutoEmbedExtension } from '../extensions/auto-embed/auto-embed-extension'
|
|
25
|
+
import { BylineFloatingUIExtension } from '../extensions/byline-floating-ui/byline-floating-ui-extension'
|
|
26
|
+
import { BylineToolbarExtension } from '../extensions/byline-toolbar/byline-toolbar-extension'
|
|
27
|
+
import { CodeHighlightExtension } from '../extensions/code-highlight/code-highlight-extension'
|
|
28
|
+
import { FloatingTextFormatExtension } from '../extensions/floating-text-format/floating-text-format-extension'
|
|
29
|
+
import { HorizontalRuleExtension } from '../extensions/horizontal-rule/horizontal-rule-extension'
|
|
30
|
+
import { InlineImageExtension } from '../extensions/inline-image/inline-image-extension'
|
|
31
|
+
import { LayoutExtension } from '../extensions/layout/layout-extension'
|
|
32
|
+
import { AutoLinkExtension } from '../extensions/link/auto-link-extension'
|
|
33
|
+
import { LinkExtension } from '../extensions/link/link-extension'
|
|
34
|
+
import { TableExtension } from '../extensions/table/table-extension'
|
|
35
|
+
import { VimeoExtension } from '../extensions/vimeo/vimeo-extension'
|
|
36
|
+
import { YouTubeExtension } from '../extensions/youtube/youtube-extension'
|
|
37
|
+
import { defaultEditorConfig } from './default'
|
|
38
|
+
import { ExtensionsList } from './extensions-list'
|
|
39
|
+
import type { EditorConfig } from './types'
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns a fresh array of every Byline-built-in Lexical extension in
|
|
43
|
+
* their canonical order. Includes the `BylineToolbarExtension` registry
|
|
44
|
+
* itself so contributing extensions can attach their toolbar items via
|
|
45
|
+
* `peerDependencies`.
|
|
46
|
+
*
|
|
47
|
+
* Order matters: stock framework extensions (clear-editor, tab-indent,
|
|
48
|
+
* auto-focus) come first; toolbar contract sits ahead of any
|
|
49
|
+
* contributing extension; relation-bearing extensions (link, image)
|
|
50
|
+
* land near the end.
|
|
51
|
+
*/
|
|
52
|
+
export function defaultExtensionsArray(): AnyLexicalExtensionArgument[] {
|
|
53
|
+
return [
|
|
54
|
+
// Always-on stock extensions.
|
|
55
|
+
ClearEditorExtension,
|
|
56
|
+
TabIndentationExtension,
|
|
57
|
+
AutoFocusExtension,
|
|
58
|
+
|
|
59
|
+
// Toolbar + floating-UI contracts — must be present before any
|
|
60
|
+
// extension that contributes items to them via `peerDependencies`.
|
|
61
|
+
BylineToolbarExtension,
|
|
62
|
+
BylineFloatingUIExtension,
|
|
63
|
+
|
|
64
|
+
// Block- / list-level features.
|
|
65
|
+
ListExtension,
|
|
66
|
+
CheckListExtension,
|
|
67
|
+
HorizontalRuleExtension,
|
|
68
|
+
LayoutExtension,
|
|
69
|
+
AdmonitionExtension,
|
|
70
|
+
CodeHighlightExtension,
|
|
71
|
+
TableExtension,
|
|
72
|
+
|
|
73
|
+
// Link & link-related.
|
|
74
|
+
LinkExtension,
|
|
75
|
+
AutoLinkExtension,
|
|
76
|
+
|
|
77
|
+
// Embeds & inline images.
|
|
78
|
+
InlineImageExtension,
|
|
79
|
+
YouTubeExtension,
|
|
80
|
+
VimeoExtension,
|
|
81
|
+
AutoEmbedExtension,
|
|
82
|
+
|
|
83
|
+
// Floating UIs (the text-format popover lives at the floating-UI layer
|
|
84
|
+
// rather than the toolbar contract, so it gets its own extension).
|
|
85
|
+
FloatingTextFormatExtension,
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Fresh `ExtensionsList` populated with the built-in extensions. */
|
|
90
|
+
export function defaultExtensionsList(): ExtensionsList {
|
|
91
|
+
return new ExtensionsList(defaultExtensionsArray())
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Client-side default editor config — settings + lexical config + the
|
|
96
|
+
* full default extensions list. Used by `lexicalEditor((c) => ...)` as
|
|
97
|
+
* the seed before invoking the configure callback. Server-only modules
|
|
98
|
+
* (e.g. seeds) must import `defaultEditorConfig` from
|
|
99
|
+
* `@byline/richtext-lexical/server` instead.
|
|
100
|
+
*/
|
|
101
|
+
export const defaultClientEditorConfig: EditorConfig = {
|
|
102
|
+
...defaultEditorConfig,
|
|
103
|
+
extensions: defaultExtensionsList(),
|
|
104
|
+
}
|
|
@@ -10,41 +10,13 @@ export const defaultEditorLexicalConfig: LexicalEditorConfig = {
|
|
|
10
10
|
|
|
11
11
|
export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
|
12
12
|
options: {
|
|
13
|
-
disableBeforeInput: false,
|
|
14
|
-
autocomplete: false,
|
|
15
|
-
charLimit: false,
|
|
16
|
-
charLimitUtf8: false,
|
|
17
|
-
collab: false,
|
|
18
|
-
maxLength: false,
|
|
19
13
|
richText: true,
|
|
20
|
-
measureTypingPerf: false,
|
|
21
|
-
showNestedEditorTreeView: false,
|
|
22
|
-
showTableOfContents: false,
|
|
23
14
|
showTreeView: false,
|
|
24
15
|
textAlignment: true,
|
|
25
|
-
tablePlugin: true,
|
|
26
|
-
tableCellBackgroundColor: true,
|
|
27
|
-
tableCellMerge: true,
|
|
28
|
-
tableActionMenuPlugin: true,
|
|
29
|
-
layoutPlugin: true,
|
|
30
|
-
outputHTML: false,
|
|
31
|
-
outputMarkdown: false,
|
|
32
|
-
autoFocusPlugin: false,
|
|
33
|
-
autoLinkPlugin: false,
|
|
34
|
-
inlineImagePlugin: true,
|
|
35
|
-
admonitionPlugin: true,
|
|
36
|
-
checkListPlugin: true,
|
|
37
|
-
listPlugin: true,
|
|
38
|
-
codeHighlightPlugin: true,
|
|
39
|
-
horizontalRulePlugin: true,
|
|
40
16
|
markdownShortcutPlugin: false,
|
|
41
17
|
undoRedo: true,
|
|
42
18
|
textStyle: true,
|
|
43
19
|
inlineCode: true,
|
|
44
|
-
links: true,
|
|
45
|
-
floatingLinkEditorPlugin: true,
|
|
46
|
-
floatingTextFormatToolbarPlugin: false,
|
|
47
|
-
autoEmbedPlugin: true,
|
|
48
20
|
debug: false,
|
|
49
21
|
},
|
|
50
22
|
inlineImageUploadCollection: 'media',
|
|
@@ -52,6 +24,14 @@ export const DEFAULT_EDITOR_SETTINGS: EditorSettings = {
|
|
|
52
24
|
embedRelationsOnSave: true,
|
|
53
25
|
}
|
|
54
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Server-safe editor config — settings + Lexical core config only. The
|
|
29
|
+
* `extensions` field is intentionally omitted because extension entries
|
|
30
|
+
* carry React-bearing decorators that would break tsx-loaded seeds and
|
|
31
|
+
* other server-side schema consumers. The client-side
|
|
32
|
+
* `defaultClientEditorConfig` (in `default-extensions.tsx`) layers the
|
|
33
|
+
* extensions list on top.
|
|
34
|
+
*/
|
|
55
35
|
export const defaultEditorConfig: EditorConfig = {
|
|
56
36
|
settings: DEFAULT_EDITOR_SETTINGS,
|
|
57
37
|
lexical: defaultEditorLexicalConfig,
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
import type * as React from 'react'
|
|
4
4
|
import { createContext, useCallback, useContext, useMemo, useState } from 'react'
|
|
5
5
|
|
|
6
|
-
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
|
7
|
-
|
|
8
6
|
import { DEFAULT_EDITOR_SETTINGS } from './default'
|
|
9
7
|
import type { EditorSettings, OptionName } from './types'
|
|
10
8
|
|
|
@@ -34,7 +32,6 @@ export const EditorConfigContext = ({
|
|
|
34
32
|
const [config, setConfig] = useState(configFromProps ?? DEFAULT_EDITOR_SETTINGS)
|
|
35
33
|
// State to store the UUID
|
|
36
34
|
const [uuid] = useState(() => generateQuickGuid())
|
|
37
|
-
const [editor] = useLexicalComposerContext()
|
|
38
35
|
|
|
39
36
|
const setOption = useCallback((option: OptionName, value: boolean) => {
|
|
40
37
|
setConfig((config) => {
|
|
@@ -43,10 +40,7 @@ export const EditorConfigContext = ({
|
|
|
43
40
|
})
|
|
44
41
|
}, [])
|
|
45
42
|
|
|
46
|
-
const editorContext = useMemo(
|
|
47
|
-
() => ({ setOption, config, uuid, editor }),
|
|
48
|
-
[setOption, config, uuid, editor]
|
|
49
|
-
)
|
|
43
|
+
const editorContext = useMemo(() => ({ setOption, config, uuid }), [setOption, config, uuid])
|
|
50
44
|
|
|
51
45
|
return <Context.Provider value={editorContext}>{children}</Context.Provider>
|
|
52
46
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
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
|
+
|
|
9
|
+
import {
|
|
10
|
+
type AnyLexicalExtension,
|
|
11
|
+
type AnyLexicalExtensionArgument,
|
|
12
|
+
configExtension,
|
|
13
|
+
type LexicalExtensionConfig,
|
|
14
|
+
} from 'lexical'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Chainable wrapper around an ordered list of Lexical extensions. Used
|
|
18
|
+
* inside the `lexicalEditor((c) => ...)` configure callback so site
|
|
19
|
+
* authors can add, remove, configure, or reorder extensions before the
|
|
20
|
+
* editor is built.
|
|
21
|
+
*
|
|
22
|
+
* Comparison is by extension `name` so a bare `LinkExtension` and a
|
|
23
|
+
* `configExtension(LinkExtension, {...})` tuple are treated as the same
|
|
24
|
+
* entry.
|
|
25
|
+
*/
|
|
26
|
+
export class ExtensionsList {
|
|
27
|
+
private items: AnyLexicalExtensionArgument[]
|
|
28
|
+
|
|
29
|
+
constructor(items: ReadonlyArray<AnyLexicalExtensionArgument> = []) {
|
|
30
|
+
this.items = [...items]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Append `extension` to the end of the list. */
|
|
34
|
+
add(extension: AnyLexicalExtensionArgument): this {
|
|
35
|
+
this.items.push(extension)
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Remove every entry whose name matches `extension.name`. No-op when
|
|
41
|
+
* the extension isn't present.
|
|
42
|
+
*/
|
|
43
|
+
remove(extension: AnyLexicalExtension): this {
|
|
44
|
+
const targetName = extension.name
|
|
45
|
+
this.items = this.items.filter((item) => extensionName(item) !== targetName)
|
|
46
|
+
return this
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Replace `oldExtension` with `newExtension`, preserving position. */
|
|
50
|
+
replace(oldExtension: AnyLexicalExtension, newExtension: AnyLexicalExtensionArgument): this {
|
|
51
|
+
const targetName = oldExtension.name
|
|
52
|
+
let replaced = false
|
|
53
|
+
this.items = this.items.map((item) => {
|
|
54
|
+
if (!replaced && extensionName(item) === targetName) {
|
|
55
|
+
replaced = true
|
|
56
|
+
return newExtension
|
|
57
|
+
}
|
|
58
|
+
return item
|
|
59
|
+
})
|
|
60
|
+
if (!replaced) this.items.push(newExtension)
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Re-wrap an existing extension entry with a fresh `configExtension`
|
|
66
|
+
* binding the supplied config. If the extension isn't present, it is
|
|
67
|
+
* added. If it was already wrapped with `configExtension`, the wrapper
|
|
68
|
+
* is replaced rather than nested.
|
|
69
|
+
*/
|
|
70
|
+
configure<Extension extends AnyLexicalExtension>(
|
|
71
|
+
extension: Extension,
|
|
72
|
+
config: Partial<LexicalExtensionConfig<Extension>>
|
|
73
|
+
): this {
|
|
74
|
+
const wrapped = configExtension(extension, config)
|
|
75
|
+
return this.replace(extension, wrapped)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** True when an entry with the same `name` is present. */
|
|
79
|
+
has(extension: AnyLexicalExtension): boolean {
|
|
80
|
+
const targetName = extension.name
|
|
81
|
+
return this.items.some((item) => extensionName(item) === targetName)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Independent copy — safe to hand to a configure callback. */
|
|
85
|
+
clone(): ExtensionsList {
|
|
86
|
+
return new ExtensionsList(this.items)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The list as a plain array, ready for `defineExtension({ dependencies })`. */
|
|
90
|
+
toArray(): AnyLexicalExtensionArgument[] {
|
|
91
|
+
return [...this.items]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function extensionName(item: AnyLexicalExtensionArgument): string | undefined {
|
|
96
|
+
if (Array.isArray(item)) {
|
|
97
|
+
const head = item[0]
|
|
98
|
+
if (head != null && typeof head === 'object' && 'name' in head) {
|
|
99
|
+
return (head as AnyLexicalExtension).name
|
|
100
|
+
}
|
|
101
|
+
return undefined
|
|
102
|
+
}
|
|
103
|
+
if (item != null && typeof item === 'object' && 'name' in item) {
|
|
104
|
+
return (item as AnyLexicalExtension).name
|
|
105
|
+
}
|
|
106
|
+
return undefined
|
|
107
|
+
}
|
|
@@ -1,45 +1,32 @@
|
|
|
1
1
|
import type { EditorConfig as LexicalEditorConfig } from 'lexical'
|
|
2
2
|
|
|
3
|
+
import type { ExtensionsList } from './extensions-list'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Settings that aren't expressible as "is extension X present in the
|
|
7
|
+
* extensions list?" — toolbar / UI mode toggles, debug switches, the
|
|
8
|
+
* inline-image upload target, etc. Everything else now lives on
|
|
9
|
+
* {@link EditorConfig.extensions} and is manipulated via the chainable
|
|
10
|
+
* `lexicalEditor((c) => c.extensions.add(...).remove(...))` API.
|
|
11
|
+
*/
|
|
3
12
|
export type OptionName =
|
|
4
|
-
| 'disableBeforeInput'
|
|
5
|
-
| 'autocomplete'
|
|
6
|
-
| 'charLimit'
|
|
7
|
-
| 'charLimitUtf8'
|
|
8
|
-
| 'collab'
|
|
9
|
-
| 'maxLength'
|
|
10
13
|
| 'richText'
|
|
11
|
-
| 'measureTypingPerf'
|
|
12
|
-
| 'showNestedEditorTreeView'
|
|
13
|
-
| 'showTableOfContents'
|
|
14
14
|
| 'showTreeView'
|
|
15
15
|
| 'textAlignment'
|
|
16
|
-
| 'tablePlugin'
|
|
17
|
-
| 'tableCellBackgroundColor'
|
|
18
|
-
| 'tableCellMerge'
|
|
19
|
-
| 'tableActionMenuPlugin'
|
|
20
|
-
| 'layoutPlugin'
|
|
21
|
-
| 'outputHTML'
|
|
22
|
-
| 'outputMarkdown'
|
|
23
|
-
| 'autoFocusPlugin'
|
|
24
|
-
| 'autoLinkPlugin'
|
|
25
|
-
| 'inlineImagePlugin'
|
|
26
|
-
| 'admonitionPlugin'
|
|
27
|
-
| 'checkListPlugin'
|
|
28
|
-
| 'listPlugin'
|
|
29
|
-
| 'codeHighlightPlugin'
|
|
30
|
-
| 'horizontalRulePlugin'
|
|
31
16
|
| 'markdownShortcutPlugin'
|
|
32
17
|
| 'undoRedo'
|
|
33
18
|
| 'textStyle'
|
|
34
19
|
| 'inlineCode'
|
|
35
|
-
| 'links'
|
|
36
|
-
| 'floatingLinkEditorPlugin'
|
|
37
|
-
| 'floatingTextFormatToolbarPlugin'
|
|
38
|
-
| 'autoEmbedPlugin'
|
|
39
20
|
| 'debug'
|
|
40
21
|
|
|
41
22
|
export interface EditorSettings {
|
|
42
23
|
options: Record<OptionName, boolean>
|
|
24
|
+
/**
|
|
25
|
+
* Upload collection passed to the inline-image picker. Forwarded to
|
|
26
|
+
* `InlineImageExtension`'s config when the extensions list is built;
|
|
27
|
+
* setting it here is equivalent to
|
|
28
|
+
* `c.extensions.configure(InlineImageExtension, { collection })`.
|
|
29
|
+
*/
|
|
43
30
|
inlineImageUploadCollection: string
|
|
44
31
|
placeholderText: string
|
|
45
32
|
/**
|
|
@@ -64,4 +51,17 @@ export interface EditorSettingsOverride {
|
|
|
64
51
|
export interface EditorConfig {
|
|
65
52
|
settings: EditorSettings
|
|
66
53
|
lexical: LexicalEditorConfig
|
|
54
|
+
/**
|
|
55
|
+
* Manipulable list of Lexical extensions wired into the editor. When
|
|
56
|
+
* omitted (server-safe `defaultEditorConfig` from `/server` does not
|
|
57
|
+
* carry one), the editor falls back to the package's built-in list at
|
|
58
|
+
* render time.
|
|
59
|
+
*
|
|
60
|
+
* Field-level `RichTextField.editorConfig` should not set this
|
|
61
|
+
* directly — extension references are not JSON-safe and would break
|
|
62
|
+
* tsx-loaded seeds. Per-field extension overrides go through a
|
|
63
|
+
* client-side wrapper component registered via
|
|
64
|
+
* `FieldAdminConfig.editor` (see `aiRichTextAdmin()` for the pattern).
|
|
65
|
+
*/
|
|
66
|
+
extensions?: ExtensionsList
|
|
67
67
|
}
|
|
@@ -11,16 +11,22 @@
|
|
|
11
11
|
import type * as React from 'react'
|
|
12
12
|
import { useMemo } from 'react'
|
|
13
13
|
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
|
|
14
|
+
import { LexicalExtensionComposer } from '@lexical/react/LexicalExtensionComposer'
|
|
15
|
+
import {
|
|
16
|
+
type AnyLexicalExtensionArgument,
|
|
17
|
+
defineExtension,
|
|
18
|
+
type EditorState,
|
|
19
|
+
type LexicalEditor,
|
|
20
|
+
type SerializedEditorState,
|
|
21
|
+
} from 'lexical'
|
|
17
22
|
|
|
23
|
+
import { defaultExtensionsList } from './config/default-extensions'
|
|
18
24
|
import { EditorConfigContext } from './config/editor-config-context'
|
|
19
25
|
import { SharedHistoryContext } from './context/shared-history-context'
|
|
20
26
|
import { SharedOnChangeContext } from './context/shared-on-change-context'
|
|
21
27
|
import { Editor } from './editor'
|
|
28
|
+
import { InlineImageExtension } from './extensions/inline-image/inline-image-extension'
|
|
22
29
|
import { Nodes } from './nodes'
|
|
23
|
-
import { ToolbarExtensionsProvider } from './toolbar-extensions'
|
|
24
30
|
import type { EditorConfig } from './config/types'
|
|
25
31
|
|
|
26
32
|
// Catch any errors that occur during Lexical updates and log them
|
|
@@ -54,49 +60,79 @@ export function EditorContext(props: {
|
|
|
54
60
|
children,
|
|
55
61
|
} = props
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const editable = readOnly !== true
|
|
64
|
+
|
|
65
|
+
// The root extension must be a referentially stable value across renders.
|
|
66
|
+
// Unlike the legacy LexicalComposer (which memoised the editor with [] deps
|
|
67
|
+
// and ignored subsequent initialConfig changes), LexicalExtensionComposer
|
|
68
|
+
// rebuilds the editor whenever the `extension` prop changes by reference —
|
|
69
|
+
// destroying editor state and history. So we deliberately compute this
|
|
70
|
+
// only on mount and capture readOnly / value / editorConfig from the first
|
|
71
|
+
// render. The `key={composerKey + editable}` below already forces a remount
|
|
72
|
+
// when readOnly toggles, so a fresh extension is built then.
|
|
73
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: capture-once on mount; remount via `key` handles editable transitions
|
|
74
|
+
const rootExtension = useMemo<AnyLexicalExtensionArgument>(() => {
|
|
75
|
+
// Source of truth for the extension graph: editorConfig.extensions,
|
|
76
|
+
// optionally manipulated by site code via lexicalEditor((c) => ...).
|
|
77
|
+
// Server-loaded EditorConfigs (e.g. via /server) carry no extensions
|
|
78
|
+
// field; in that case we materialise the package default here.
|
|
79
|
+
const extensionsList = editorConfig.extensions ?? defaultExtensionsList()
|
|
80
|
+
|
|
81
|
+
// Forward the inline-image upload collection from the settings facade
|
|
82
|
+
// onto the InlineImageExtension's typed config, but only when the
|
|
83
|
+
// user hasn't already configured the extension explicitly.
|
|
84
|
+
const dependencies = extensionsList
|
|
85
|
+
.clone()
|
|
86
|
+
.configure(InlineImageExtension, {
|
|
87
|
+
collection: editorConfig.settings.inlineImageUploadCollection,
|
|
88
|
+
})
|
|
89
|
+
.toArray()
|
|
90
|
+
|
|
91
|
+
return defineExtension({
|
|
92
|
+
name: '[root]',
|
|
63
93
|
namespace: editorConfig.lexical.namespace,
|
|
64
94
|
nodes: [...Nodes],
|
|
95
|
+
theme: editorConfig.lexical.theme,
|
|
96
|
+
editable,
|
|
97
|
+
$initialEditorState: value != null ? JSON.stringify(value) : undefined,
|
|
65
98
|
onError: (error: Error) => {
|
|
66
99
|
throw error
|
|
67
100
|
},
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
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
|
-
}
|
|
101
|
+
dependencies,
|
|
102
|
+
})
|
|
103
|
+
}, [])
|
|
83
104
|
|
|
105
|
+
// These three context providers MUST sit OUTSIDE LexicalExtensionComposer.
|
|
106
|
+
//
|
|
107
|
+
// LexicalExtensionComposer renders the editor's React decorator portals
|
|
108
|
+
// (the components mounted for AdmonitionNode, InlineImageNode, etc.) as
|
|
109
|
+
// a sibling of its `children` inside an internal EditorChildrenComponent,
|
|
110
|
+
// not as descendants of `children`. Any context provider we place inside
|
|
111
|
+
// the composer is invisible to those decorators — so nested editors
|
|
112
|
+
// wired through SharedOnChangeContext silently fail to propagate change
|
|
113
|
+
// events up to the parent, and SharedHistoryContext falls back to a
|
|
114
|
+
// local history state instead of being shared with the root editor.
|
|
115
|
+
//
|
|
116
|
+
// Hoisting these providers above the composer puts the node decorators
|
|
117
|
+
// back inside their React tree.
|
|
84
118
|
return (
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
119
|
+
<EditorConfigContext config={editorConfig.settings}>
|
|
120
|
+
<SharedOnChangeContext onChange={onChange}>
|
|
121
|
+
<SharedHistoryContext>
|
|
122
|
+
<LexicalExtensionComposer
|
|
123
|
+
extension={rootExtension}
|
|
124
|
+
contentEditable={null}
|
|
125
|
+
key={composerKey + editable}
|
|
126
|
+
>
|
|
127
|
+
<div className="editor-shell">
|
|
128
|
+
{beforeEditor}
|
|
129
|
+
<Editor minHeight={props.minHeight} maxHeight={props.maxHeight} />
|
|
130
|
+
{afterEditor}
|
|
131
|
+
{children}
|
|
132
|
+
</div>
|
|
133
|
+
</LexicalExtensionComposer>
|
|
134
|
+
</SharedHistoryContext>
|
|
135
|
+
</SharedOnChangeContext>
|
|
136
|
+
</EditorConfigContext>
|
|
101
137
|
)
|
|
102
138
|
}
|
package/src/field/editor.tsx
CHANGED
|
@@ -12,19 +12,16 @@ import type * as React from 'react'
|
|
|
12
12
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
|
13
13
|
|
|
14
14
|
import { TRANSFORMERS } from '@lexical/markdown'
|
|
15
|
-
import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin'
|
|
16
|
-
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
|
|
17
|
-
import { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin'
|
|
18
15
|
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
|
|
19
16
|
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
|
|
20
|
-
import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin'
|
|
21
|
-
import { ListPlugin } from '@lexical/react/LexicalListPlugin'
|
|
22
17
|
import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'
|
|
23
18
|
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
|
|
24
19
|
import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin'
|
|
25
20
|
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
|
|
26
|
-
import {
|
|
27
|
-
|
|
21
|
+
import {
|
|
22
|
+
useExtensionDependency,
|
|
23
|
+
useOptionalExtensionDependency,
|
|
24
|
+
} from '@lexical/react/useExtensionComponent'
|
|
28
25
|
import type { EditorState, LexicalEditor } from 'lexical'
|
|
29
26
|
|
|
30
27
|
import { useEditorConfig } from './config/editor-config-context'
|
|
@@ -32,23 +29,16 @@ import { ContentEditable } from './content-editable'
|
|
|
32
29
|
import { useSharedHistoryContext } from './context/shared-history-context'
|
|
33
30
|
import { useSharedOnChange } from './context/shared-on-change-context'
|
|
34
31
|
import { Debug } from './debug'
|
|
35
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
BylineFloatingUIExtension,
|
|
34
|
+
selectFloatingUIItems,
|
|
35
|
+
} from './extensions/byline-floating-ui/byline-floating-ui-extension'
|
|
36
|
+
import { TableExtension as BylineTableExtension } from './extensions/table/table-extension'
|
|
36
37
|
// import { AiPlugin } from './plugins/ai-plugin'
|
|
37
|
-
import { AutoEmbedPlugin } from './plugins/auto-embed-plugin'
|
|
38
|
-
import { CodeHighlightPlugin } from './plugins/code-highlight-plugin'
|
|
39
38
|
// import { DragDropPaste } from './plugins/drag-drop-paste-plugin'
|
|
40
|
-
import {
|
|
41
|
-
import { InlineImagePlugin } from './plugins/inline-image-plugin'
|
|
42
|
-
import { LayoutPlugin } from './plugins/layout-plugin/layout-plugin'
|
|
43
|
-
import { AutoLinkPlugin } from './plugins/link-plugin/auto-link'
|
|
44
|
-
import { LinkPlugin } from './plugins/link-plugin/link'
|
|
45
|
-
import { FloatingLinkEditorPlugin } from './plugins/link-plugin/link/floating-link-editor'
|
|
46
|
-
import { TableActionMenuPlugin } from './plugins/table-action-menu-plugin'
|
|
47
|
-
import { TablePlugin as PayloadTablePlugin } from './plugins/table-plugin'
|
|
39
|
+
import { TablePlugin } from './plugins/table-plugin'
|
|
48
40
|
import { ToolbarPlugin } from './plugins/toolbar-plugin'
|
|
49
41
|
import { TreeViewPlugin } from './plugins/treeview-plugin'
|
|
50
|
-
import { VimeoPlugin } from './plugins/vimeo-plugin'
|
|
51
|
-
import { YouTubePlugin } from './plugins/youtube-plugin'
|
|
52
42
|
import { CAN_USE_DOM } from './shared/canUseDOM'
|
|
53
43
|
import { Placeholder } from './ui/placeholder'
|
|
54
44
|
|
|
@@ -75,31 +65,17 @@ export const Editor = memo(function Editor({
|
|
|
75
65
|
const { historyState } = useSharedHistoryContext()
|
|
76
66
|
const {
|
|
77
67
|
config: {
|
|
78
|
-
options: {
|
|
79
|
-
debug,
|
|
80
|
-
richText,
|
|
81
|
-
showTreeView,
|
|
82
|
-
autoFocusPlugin,
|
|
83
|
-
tablePlugin,
|
|
84
|
-
tableActionMenuPlugin,
|
|
85
|
-
layoutPlugin,
|
|
86
|
-
inlineImagePlugin,
|
|
87
|
-
admonitionPlugin,
|
|
88
|
-
links,
|
|
89
|
-
autoLinkPlugin,
|
|
90
|
-
checkListPlugin,
|
|
91
|
-
listPlugin,
|
|
92
|
-
codeHighlightPlugin,
|
|
93
|
-
horizontalRulePlugin,
|
|
94
|
-
markdownShortcutPlugin,
|
|
95
|
-
floatingLinkEditorPlugin,
|
|
96
|
-
floatingTextFormatToolbarPlugin,
|
|
97
|
-
autoEmbedPlugin,
|
|
98
|
-
},
|
|
68
|
+
options: { debug, richText, showTreeView, markdownShortcutPlugin },
|
|
99
69
|
placeholderText,
|
|
100
|
-
inlineImageUploadCollection,
|
|
101
70
|
},
|
|
102
71
|
} = useEditorConfig()
|
|
72
|
+
const hasTableExtension = useOptionalExtensionDependency(BylineTableExtension) !== undefined
|
|
73
|
+
// Merged floating-UI contributions from every extension in the graph.
|
|
74
|
+
// Removing a contributing extension (e.g. `c.extensions.remove(LinkExtension)`)
|
|
75
|
+
// automatically suppresses its floating UI — no separate boolean toggle.
|
|
76
|
+
const floatingUIItems = selectFloatingUIItems(
|
|
77
|
+
useExtensionDependency(BylineFloatingUIExtension).config.items
|
|
78
|
+
)
|
|
103
79
|
|
|
104
80
|
const onRef = useCallback((_floatingAnchorElem: HTMLDivElement): void => {
|
|
105
81
|
if (_floatingAnchorElem != null) {
|
|
@@ -154,7 +130,7 @@ export const Editor = memo(function Editor({
|
|
|
154
130
|
|
|
155
131
|
const content = (
|
|
156
132
|
<>
|
|
157
|
-
{
|
|
133
|
+
{hasTableExtension && <TablePlugin />}
|
|
158
134
|
{richText && <ToolbarPlugin />}
|
|
159
135
|
<div
|
|
160
136
|
className={`editor-container ${showTreeView ? 'tree-view' : ''} ${
|
|
@@ -162,11 +138,6 @@ export const Editor = memo(function Editor({
|
|
|
162
138
|
}`}
|
|
163
139
|
>
|
|
164
140
|
{/* <DragDropPaste /> */}
|
|
165
|
-
{autoFocusPlugin && <AutoFocusPlugin />}
|
|
166
|
-
{links && <LinkPlugin />}
|
|
167
|
-
{autoEmbedPlugin && <AutoEmbedPlugin />}
|
|
168
|
-
<TabIndentationPlugin />
|
|
169
|
-
{autoLinkPlugin && <AutoLinkPlugin />}
|
|
170
141
|
<OnChangePlugin
|
|
171
142
|
// Ignore any onChange event triggered by focus or selection only
|
|
172
143
|
ignoreSelectionChange={true}
|
|
@@ -190,30 +161,12 @@ export const Editor = memo(function Editor({
|
|
|
190
161
|
ErrorBoundary={LexicalErrorBoundary}
|
|
191
162
|
/>
|
|
192
163
|
<HistoryPlugin externalHistoryState={historyState} />
|
|
193
|
-
{inlineImagePlugin && <InlineImagePlugin collection={inlineImageUploadCollection} />}
|
|
194
|
-
{admonitionPlugin && <AdmonitionPlugin />}
|
|
195
|
-
{checkListPlugin && <CheckListPlugin />}
|
|
196
|
-
{listPlugin && <ListPlugin />}
|
|
197
|
-
{codeHighlightPlugin && <CodeHighlightPlugin />}
|
|
198
|
-
{horizontalRulePlugin && <HorizontalRulePlugin />}
|
|
199
|
-
{layoutPlugin && <LayoutPlugin />}
|
|
200
|
-
{autoEmbedPlugin && <YouTubePlugin />}
|
|
201
|
-
{autoEmbedPlugin && <VimeoPlugin />}
|
|
202
164
|
{markdownShortcutPlugin && <MarkdownShortcutPlugin transformers={TRANSFORMERS} />}
|
|
203
|
-
{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
)}
|
|
209
|
-
{tableActionMenuPlugin && (
|
|
210
|
-
<TableActionMenuPlugin anchorElem={floatingAnchorElem} cellMerge={false} />
|
|
211
|
-
)}
|
|
212
|
-
{floatingTextFormatToolbarPlugin && (
|
|
213
|
-
<FloatingTextFormatToolbarPlugin anchorElem={floatingAnchorElem} />
|
|
214
|
-
)}
|
|
215
|
-
</>
|
|
216
|
-
)}
|
|
165
|
+
{floatingAnchorElem != null &&
|
|
166
|
+
!isSmallWidthViewport &&
|
|
167
|
+
floatingUIItems.map(({ id, Component }) => (
|
|
168
|
+
<Component key={id} anchorElem={floatingAnchorElem} />
|
|
169
|
+
))}
|
|
217
170
|
</>
|
|
218
171
|
) : (
|
|
219
172
|
<>
|
|
@@ -225,7 +178,6 @@ export const Editor = memo(function Editor({
|
|
|
225
178
|
<HistoryPlugin externalHistoryState={historyState} />
|
|
226
179
|
</>
|
|
227
180
|
)}
|
|
228
|
-
<ClearEditorPlugin />
|
|
229
181
|
{debug && (
|
|
230
182
|
<>
|
|
231
183
|
<Debug />
|