@thangph2146/lexical-editor 0.0.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/editor-x/editor.cjs +33121 -0
- package/dist/editor-x/editor.cjs.map +1 -0
- package/dist/editor-x/editor.css +2854 -0
- package/dist/editor-x/editor.css.map +1 -0
- package/dist/editor-x/editor.d.cts +12 -0
- package/dist/editor-x/editor.d.ts +12 -0
- package/dist/editor-x/editor.js +33095 -0
- package/dist/editor-x/editor.js.map +1 -0
- package/dist/index.cjs +33210 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +2854 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +33183 -0
- package/dist/index.js.map +1 -0
- package/package.json +84 -0
- package/src/components/lexical-editor.tsx +123 -0
- package/src/context/editor-container-context.tsx +29 -0
- package/src/context/priority-image-context.tsx +7 -0
- package/src/context/toolbar-context.tsx +60 -0
- package/src/context/uploads-context.tsx +53 -0
- package/src/editor-hooks/use-debounce.ts +80 -0
- package/src/editor-hooks/use-modal.tsx +64 -0
- package/src/editor-hooks/use-report.ts +57 -0
- package/src/editor-hooks/use-update-toolbar.ts +41 -0
- package/src/editor-ui/broken-image.tsx +18 -0
- package/src/editor-ui/caption-composer.tsx +45 -0
- package/src/editor-ui/code-button.tsx +75 -0
- package/src/editor-ui/color-picker.tsx +2010 -0
- package/src/editor-ui/content-editable.tsx +37 -0
- package/src/editor-ui/hooks/use-image-caption-controls.ts +118 -0
- package/src/editor-ui/hooks/use-image-node-interactions.ts +245 -0
- package/src/editor-ui/hooks/use-responsive-image-dimensions.ts +202 -0
- package/src/editor-ui/image-component.tsx +321 -0
- package/src/editor-ui/image-placeholder.tsx +57 -0
- package/src/editor-ui/image-resizer.tsx +499 -0
- package/src/editor-ui/image-sizing.ts +120 -0
- package/src/editor-ui/lazy-image.tsx +136 -0
- package/src/editor-x/editor.tsx +117 -0
- package/src/editor-x/nodes.ts +79 -0
- package/src/editor-x/plugins.tsx +380 -0
- package/src/hooks/use-click-outside.ts +27 -0
- package/src/hooks/use-element-size.ts +54 -0
- package/src/hooks/use-header-height.ts +95 -0
- package/src/hooks/use-isomorphic-layout-effect.ts +4 -0
- package/src/index.ts +4 -0
- package/src/lib/logger.ts +6 -0
- package/src/lib/utils.ts +19 -0
- package/src/nodes/autocomplete-node.tsx +94 -0
- package/src/nodes/embeds/tweet-node.tsx +224 -0
- package/src/nodes/embeds/youtube-node.tsx +519 -0
- package/src/nodes/emoji-node.tsx +83 -0
- package/src/nodes/image-node.tsx +328 -0
- package/src/nodes/keyword-node.tsx +58 -0
- package/src/nodes/layout-container-node.tsx +128 -0
- package/src/nodes/layout-item-node.tsx +118 -0
- package/src/nodes/list-with-color-node.tsx +160 -0
- package/src/nodes/mention-node.ts +122 -0
- package/src/plugins/actions/actions-plugin.tsx +3 -0
- package/src/plugins/actions/character-limit-plugin.tsx +27 -0
- package/src/plugins/actions/clear-editor-plugin.tsx +70 -0
- package/src/plugins/actions/counter-character-plugin.tsx +80 -0
- package/src/plugins/actions/edit-mode-toggle-plugin.tsx +49 -0
- package/src/plugins/actions/import-export-plugin.tsx +61 -0
- package/src/plugins/actions/markdown-toggle-plugin.tsx +78 -0
- package/src/plugins/actions/max-length-plugin.tsx +59 -0
- package/src/plugins/actions/share-content-plugin.tsx +72 -0
- package/src/plugins/actions/speech-to-text-plugin.tsx +159 -0
- package/src/plugins/actions/tree-view-plugin.tsx +63 -0
- package/src/plugins/align-plugin.tsx +86 -0
- package/src/plugins/auto-link-plugin.tsx +34 -0
- package/src/plugins/autocomplete-plugin.tsx +2574 -0
- package/src/plugins/code-action-menu-plugin.tsx +240 -0
- package/src/plugins/code-highlight-plugin.tsx +22 -0
- package/src/plugins/component-picker-menu-plugin.tsx +427 -0
- package/src/plugins/context-menu-plugin.tsx +311 -0
- package/src/plugins/drag-drop-paste-plugin.tsx +52 -0
- package/src/plugins/draggable-block-plugin.tsx +50 -0
- package/src/plugins/embeds/auto-embed-plugin.tsx +324 -0
- package/src/plugins/embeds/twitter-plugin.tsx +45 -0
- package/src/plugins/embeds/youtube-plugin.tsx +84 -0
- package/src/plugins/emoji-picker-plugin.tsx +206 -0
- package/src/plugins/emojis-plugin.tsx +84 -0
- package/src/plugins/floating-link-editor-plugin.tsx +791 -0
- package/src/plugins/floating-text-format-plugin.tsx +710 -0
- package/src/plugins/images-plugin.tsx +671 -0
- package/src/plugins/keywords-plugin.tsx +59 -0
- package/src/plugins/layout-plugin.tsx +658 -0
- package/src/plugins/link-plugin.tsx +18 -0
- package/src/plugins/list-color-plugin.tsx +178 -0
- package/src/plugins/list-max-indent-level-plugin.tsx +85 -0
- package/src/plugins/mentions-plugin.tsx +714 -0
- package/src/plugins/picker/alignment-picker-plugin.tsx +40 -0
- package/src/plugins/picker/bulleted-list-picker-plugin.tsx +14 -0
- package/src/plugins/picker/check-list-picker-plugin.tsx +14 -0
- package/src/plugins/picker/code-picker-plugin.tsx +30 -0
- package/src/plugins/picker/columns-layout-picker-plugin.tsx +16 -0
- package/src/plugins/picker/component-picker-option.tsx +47 -0
- package/src/plugins/picker/divider-picker-plugin.tsx +14 -0
- package/src/plugins/picker/embeds-picker-plugin.tsx +24 -0
- package/src/plugins/picker/heading-picker-plugin.tsx +32 -0
- package/src/plugins/picker/image-picker-plugin.tsx +16 -0
- package/src/plugins/picker/numbered-list-picker-plugin.tsx +14 -0
- package/src/plugins/picker/paragraph-picker-plugin.tsx +20 -0
- package/src/plugins/picker/quote-picker-plugin.tsx +21 -0
- package/src/plugins/picker/table-picker-plugin.tsx +56 -0
- package/src/plugins/tab-focus-plugin.tsx +66 -0
- package/src/plugins/table-column-resizer-plugin.tsx +309 -0
- package/src/plugins/table-plugin.tsx +299 -0
- package/src/plugins/toolbar/block-format/block-format-data.tsx +69 -0
- package/src/plugins/toolbar/block-format/format-bulleted-list.tsx +40 -0
- package/src/plugins/toolbar/block-format/format-check-list.tsx +40 -0
- package/src/plugins/toolbar/block-format/format-code-block.tsx +45 -0
- package/src/plugins/toolbar/block-format/format-heading.tsx +34 -0
- package/src/plugins/toolbar/block-format/format-list-with-marker.tsx +74 -0
- package/src/plugins/toolbar/block-format/format-numbered-list.tsx +40 -0
- package/src/plugins/toolbar/block-format/format-paragraph.tsx +31 -0
- package/src/plugins/toolbar/block-format/format-quote.tsx +32 -0
- package/src/plugins/toolbar/block-format-toolbar-plugin.tsx +117 -0
- package/src/plugins/toolbar/block-insert/insert-columns-layout.tsx +32 -0
- package/src/plugins/toolbar/block-insert/insert-embeds.tsx +31 -0
- package/src/plugins/toolbar/block-insert/insert-horizontal-rule.tsx +30 -0
- package/src/plugins/toolbar/block-insert/insert-image.tsx +32 -0
- package/src/plugins/toolbar/block-insert/insert-table.tsx +32 -0
- package/src/plugins/toolbar/block-insert-plugin.tsx +30 -0
- package/src/plugins/toolbar/clear-formatting-toolbar-plugin.tsx +92 -0
- package/src/plugins/toolbar/code-language-toolbar-plugin.tsx +121 -0
- package/src/plugins/toolbar/element-format-toolbar-plugin.tsx +251 -0
- package/src/plugins/toolbar/font-background-toolbar-plugin.tsx +179 -0
- package/src/plugins/toolbar/font-color-toolbar-plugin.tsx +101 -0
- package/src/plugins/toolbar/font-family-toolbar-plugin.tsx +91 -0
- package/src/plugins/toolbar/font-format-toolbar-plugin.tsx +85 -0
- package/src/plugins/toolbar/font-size-toolbar-plugin.tsx +177 -0
- package/src/plugins/toolbar/history-toolbar-plugin.tsx +87 -0
- package/src/plugins/toolbar/link-toolbar-plugin.tsx +90 -0
- package/src/plugins/toolbar/subsuper-toolbar-plugin.tsx +69 -0
- package/src/plugins/toolbar/toolbar-plugin.tsx +66 -0
- package/src/plugins/typing-pref-plugin.tsx +118 -0
- package/src/shared/can-use-dom.ts +4 -0
- package/src/shared/environment.ts +47 -0
- package/src/shared/invariant.ts +16 -0
- package/src/shared/use-layout-effect.ts +12 -0
- package/src/themes/_mixins.scss +107 -0
- package/src/themes/_variables.scss +33 -0
- package/src/themes/editor-theme.scss +622 -0
- package/src/themes/editor-theme.ts +118 -0
- package/src/themes/plugins.scss +1180 -0
- package/src/themes/ui-components.scss +936 -0
- package/src/transformers/markdown-emoji-transformer.ts +20 -0
- package/src/transformers/markdown-hr-transformer.ts +28 -0
- package/src/transformers/markdown-image-transformer.ts +31 -0
- package/src/transformers/markdown-list-transformer.ts +51 -0
- package/src/transformers/markdown-table-transformer.ts +200 -0
- package/src/transformers/markdown-tweet-transformer.ts +26 -0
- package/src/ui/button-group.tsx +10 -0
- package/src/ui/button.tsx +29 -0
- package/src/ui/collapsible.tsx +67 -0
- package/src/ui/command.tsx +48 -0
- package/src/ui/dialog.tsx +146 -0
- package/src/ui/flex.tsx +38 -0
- package/src/ui/input.tsx +20 -0
- package/src/ui/label.tsx +20 -0
- package/src/ui/popover.tsx +128 -0
- package/src/ui/scroll-area.tsx +17 -0
- package/src/ui/select.tsx +171 -0
- package/src/ui/separator.tsx +20 -0
- package/src/ui/slider.tsx +14 -0
- package/src/ui/slot.tsx +3 -0
- package/src/ui/tabs.tsx +87 -0
- package/src/ui/toggle-group.tsx +109 -0
- package/src/ui/toggle.tsx +28 -0
- package/src/ui/tooltip.tsx +28 -0
- package/src/ui/typography.tsx +44 -0
- package/src/utils/doc-serialization.ts +68 -0
- package/src/utils/emoji-list.ts +16604 -0
- package/src/utils/get-dom-range-rect.ts +20 -0
- package/src/utils/get-selected-node.ts +20 -0
- package/src/utils/is-mobile-width.ts +0 -0
- package/src/utils/set-floating-elem-position-for-link-editor.ts +39 -0
- package/src/utils/set-floating-elem-position.ts +44 -0
- package/src/utils/swipe.ts +119 -0
- package/src/utils/url.ts +32 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import type { JSX } from "react"
|
|
4
|
+
import * as React from "react"
|
|
5
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"
|
|
6
|
+
import { mergeRegister } from "@lexical/utils"
|
|
7
|
+
import { COMMAND_PRIORITY_EDITOR, createCommand, $getNodeByKey } from "lexical"
|
|
8
|
+
import type { LexicalCommand, NodeKey } from "lexical"
|
|
9
|
+
import {
|
|
10
|
+
ColorPicker,
|
|
11
|
+
ColorPickerArea,
|
|
12
|
+
ColorPickerContent,
|
|
13
|
+
ColorPickerHueSlider,
|
|
14
|
+
ColorPickerInput,
|
|
15
|
+
ColorPickerPresets,
|
|
16
|
+
} from "../editor-ui/color-picker"
|
|
17
|
+
import { useEditorModal } from "../editor-hooks/use-modal"
|
|
18
|
+
import {
|
|
19
|
+
$isListWithColorNode,
|
|
20
|
+
} from "../nodes/list-with-color-node"
|
|
21
|
+
import { createListWithColorNodeFromRegistry } from "../editor-x/nodes"
|
|
22
|
+
import { $isListNode, ListNode } from "@lexical/list"
|
|
23
|
+
import { Button } from "../ui/button"
|
|
24
|
+
import { DialogFooter } from "../ui/dialog"
|
|
25
|
+
import { Flex } from "../ui/flex"
|
|
26
|
+
|
|
27
|
+
export const OPEN_LIST_COLOR_PICKER_COMMAND: LexicalCommand<{
|
|
28
|
+
listKey: NodeKey
|
|
29
|
+
}> = createCommand<{ listKey: NodeKey }>("OPEN_LIST_COLOR_PICKER_COMMAND")
|
|
30
|
+
|
|
31
|
+
const listColorStore = new Map<NodeKey, string>()
|
|
32
|
+
|
|
33
|
+
/** Patch serialized state: thêm listColor vào list nodes theo listColorStore (fallback khi load content cũ). */
|
|
34
|
+
export function patchListColorsInSerializedState(
|
|
35
|
+
json: Record<string, unknown>
|
|
36
|
+
): void {
|
|
37
|
+
const root = json.root as Record<string, unknown> | undefined
|
|
38
|
+
if (!root || typeof root !== "object") return
|
|
39
|
+
const children = root.children as Array<Record<string, unknown>> | undefined
|
|
40
|
+
if (!Array.isArray(children)) return
|
|
41
|
+
|
|
42
|
+
function walk(nodes: Array<Record<string, unknown>>): void {
|
|
43
|
+
for (const node of nodes) {
|
|
44
|
+
const key = node.key as string | undefined
|
|
45
|
+
const type = node.type as string | undefined
|
|
46
|
+
if (type === "list" && key && listColorStore.has(key)) {
|
|
47
|
+
;(node as Record<string, unknown>).listColor = listColorStore.get(key)
|
|
48
|
+
}
|
|
49
|
+
const childList = node.children as Array<Record<string, unknown>> | undefined
|
|
50
|
+
if (Array.isArray(childList)) walk(childList)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
walk(children)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getListElement(element: HTMLElement): HTMLElement | null {
|
|
57
|
+
const tag = element.tagName.toUpperCase()
|
|
58
|
+
if (tag === "UL" || tag === "OL") return element
|
|
59
|
+
const list = element.querySelector("ul, ol")
|
|
60
|
+
return list instanceof HTMLElement ? list : null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function applyListColor(editor: ReturnType<typeof useLexicalComposerContext>[0]) {
|
|
64
|
+
listColorStore.forEach((color, listKey) => {
|
|
65
|
+
const element = editor.getElementByKey(listKey)
|
|
66
|
+
if (!(element instanceof HTMLElement)) return
|
|
67
|
+
const listEl = getListElement(element)
|
|
68
|
+
if (!listEl) return
|
|
69
|
+
listEl.style.setProperty("--list-marker-color", color, "important")
|
|
70
|
+
listEl.setAttribute("data-list-color", color)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function ListColorPlugin(): JSX.Element | null {
|
|
75
|
+
const [editor] = useLexicalComposerContext()
|
|
76
|
+
const [modal, showModal] = useEditorModal()
|
|
77
|
+
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
const applyColor = (color: string, listKey: NodeKey) => {
|
|
80
|
+
listColorStore.set(listKey, color)
|
|
81
|
+
editor.update(() => {
|
|
82
|
+
const node = $getNodeByKey(listKey)
|
|
83
|
+
if ($isListWithColorNode(node)) {
|
|
84
|
+
node.setListColor(color)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
if ($isListNode(node)) {
|
|
88
|
+
const listType = node.getListType()
|
|
89
|
+
const start = node.getStart()
|
|
90
|
+
const newList = createListWithColorNodeFromRegistry(editor, listType, start)
|
|
91
|
+
newList.setListColor(color)
|
|
92
|
+
const children = node.getChildren()
|
|
93
|
+
for (const c of children) newList.append(c)
|
|
94
|
+
node.replace(newList)
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
applyListColor(editor)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return mergeRegister(
|
|
101
|
+
editor.registerNodeTransform(ListNode, (node) => {
|
|
102
|
+
if ($isListWithColorNode(node)) return
|
|
103
|
+
const listType = node.getListType()
|
|
104
|
+
const start = node.getStart()
|
|
105
|
+
const newList = createListWithColorNodeFromRegistry(editor, listType, start)
|
|
106
|
+
const children = node.getChildren()
|
|
107
|
+
for (const c of children) newList.append(c)
|
|
108
|
+
node.replace(newList)
|
|
109
|
+
}),
|
|
110
|
+
editor.registerUpdateListener(() => {
|
|
111
|
+
applyListColor(editor)
|
|
112
|
+
}),
|
|
113
|
+
editor.registerCommand(
|
|
114
|
+
OPEN_LIST_COLOR_PICKER_COMMAND,
|
|
115
|
+
({ listKey }) => {
|
|
116
|
+
const element = editor.getElementByKey(listKey)
|
|
117
|
+
if (!(element instanceof HTMLElement)) return true
|
|
118
|
+
const listEl = getListElement(element)
|
|
119
|
+
if (!listEl) return true
|
|
120
|
+
|
|
121
|
+
const fromStore = listColorStore.get(listKey)
|
|
122
|
+
const fromVar = listEl.style.getPropertyValue("--list-marker-color")
|
|
123
|
+
const fromAttr = listEl.getAttribute("data-list-color")
|
|
124
|
+
const initialColor =
|
|
125
|
+
fromStore || fromVar || fromAttr || "#000000"
|
|
126
|
+
|
|
127
|
+
function ListColorModalContent({ onClose }: { onClose: () => void }) {
|
|
128
|
+
const [color, setColor] = React.useState(initialColor)
|
|
129
|
+
return (
|
|
130
|
+
<div className="editor-list-color-dialog">
|
|
131
|
+
<Flex direction="column" gap={4}>
|
|
132
|
+
<div className="editor-text-xs-muted">
|
|
133
|
+
Chọn màu cho bullet hoặc số thứ tự của list.
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<ColorPicker
|
|
137
|
+
inline
|
|
138
|
+
value={color}
|
|
139
|
+
onValueChange={(next) => {
|
|
140
|
+
setColor(next)
|
|
141
|
+
applyColor(next, listKey)
|
|
142
|
+
applyListColor(editor)
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
145
|
+
<ColorPickerContent className="editor-w-full editor-border-0 editor-shadow-none editor-p-0">
|
|
146
|
+
<ColorPickerArea className="editor-h-40 editor-w-full editor-rounded-md" />
|
|
147
|
+
<Flex direction="column" gap={3} className="editor-mt-3">
|
|
148
|
+
<Flex direction="column" gap={2}>
|
|
149
|
+
<ColorPickerHueSlider className="editor-w-full" />
|
|
150
|
+
<ColorPickerInput className="editor-w-full" />
|
|
151
|
+
</Flex>
|
|
152
|
+
<ColorPickerPresets />
|
|
153
|
+
</Flex>
|
|
154
|
+
</ColorPickerContent>
|
|
155
|
+
</ColorPicker>
|
|
156
|
+
|
|
157
|
+
<DialogFooter className="editor-px-0">
|
|
158
|
+
<Button variant="outline" size="sm" onClick={onClose} className="editor-w-full">
|
|
159
|
+
Hoàn tất
|
|
160
|
+
</Button>
|
|
161
|
+
</DialogFooter>
|
|
162
|
+
</Flex>
|
|
163
|
+
</div>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
showModal("Đổi màu list", (onClose) => (
|
|
168
|
+
<ListColorModalContent onClose={onClose} />
|
|
169
|
+
))
|
|
170
|
+
return true
|
|
171
|
+
},
|
|
172
|
+
COMMAND_PRIORITY_EDITOR
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
}, [editor, showModal])
|
|
176
|
+
|
|
177
|
+
return <>{modal}</>
|
|
178
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
import { useEffect } from "react"
|
|
11
|
+
import { $getListDepth, $isListItemNode, $isListNode } from "@lexical/list"
|
|
12
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"
|
|
13
|
+
import type { ElementNode, RangeSelection } from "lexical"
|
|
14
|
+
import {
|
|
15
|
+
$getSelection,
|
|
16
|
+
$isElementNode,
|
|
17
|
+
$isRangeSelection,
|
|
18
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
19
|
+
INDENT_CONTENT_COMMAND,
|
|
20
|
+
} from "lexical"
|
|
21
|
+
|
|
22
|
+
function getElementNodesInSelection(
|
|
23
|
+
selection: RangeSelection
|
|
24
|
+
): Set<ElementNode> {
|
|
25
|
+
const nodesInSelection = selection.getNodes()
|
|
26
|
+
|
|
27
|
+
if (nodesInSelection.length === 0) {
|
|
28
|
+
return new Set([
|
|
29
|
+
selection.anchor.getNode().getParentOrThrow(),
|
|
30
|
+
selection.focus.getNode().getParentOrThrow(),
|
|
31
|
+
])
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return new Set(
|
|
35
|
+
nodesInSelection.map((n) => ($isElementNode(n) ? n : n.getParentOrThrow()))
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function $shouldPreventIndent(maxDepth: number): boolean {
|
|
40
|
+
const selection = $getSelection()
|
|
41
|
+
|
|
42
|
+
if (!$isRangeSelection(selection)) {
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const elementNodesInSelection: Set<ElementNode> =
|
|
47
|
+
getElementNodesInSelection(selection)
|
|
48
|
+
|
|
49
|
+
let totalDepth = 0
|
|
50
|
+
|
|
51
|
+
for (const elementNode of Array.from(elementNodesInSelection)) {
|
|
52
|
+
if ($isListNode(elementNode)) {
|
|
53
|
+
totalDepth = Math.max($getListDepth(elementNode) + 1, totalDepth)
|
|
54
|
+
} else if ($isListItemNode(elementNode)) {
|
|
55
|
+
const parent = elementNode.getParent()
|
|
56
|
+
|
|
57
|
+
if (!$isListNode(parent)) {
|
|
58
|
+
throw new Error(
|
|
59
|
+
"ListMaxIndentLevelPlugin: A ListItemNode must have a ListNode for a parent."
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
totalDepth = Math.max($getListDepth(parent) + 1, totalDepth)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return totalDepth > maxDepth
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function ListMaxIndentLevelPlugin({
|
|
71
|
+
maxDepth = 7,
|
|
72
|
+
}: {
|
|
73
|
+
maxDepth?: number
|
|
74
|
+
}): null {
|
|
75
|
+
const [editor] = useLexicalComposerContext()
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
return editor.registerCommand(
|
|
79
|
+
INDENT_CONTENT_COMMAND,
|
|
80
|
+
() => $shouldPreventIndent(maxDepth),
|
|
81
|
+
COMMAND_PRIORITY_CRITICAL
|
|
82
|
+
)
|
|
83
|
+
}, [editor, maxDepth])
|
|
84
|
+
return null
|
|
85
|
+
}
|