@liveblocks/react-lexical 1.12.0-lexical6 → 2.0.0-alpha2
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/classnames.js +8 -0
- package/dist/classnames.js.map +1 -0
- package/dist/classnames.mjs +6 -0
- package/dist/classnames.mjs.map +1 -0
- package/dist/comments/ThreadPanel.js +27 -7
- package/dist/comments/ThreadPanel.js.map +1 -1
- package/dist/comments/ThreadPanel.mjs +28 -8
- package/dist/comments/ThreadPanel.mjs.map +1 -1
- package/dist/comments/comment-plugin-provider.js +18 -106
- package/dist/comments/comment-plugin-provider.js.map +1 -1
- package/dist/comments/comment-plugin-provider.mjs +17 -104
- package/dist/comments/comment-plugin-provider.mjs.map +1 -1
- package/dist/comments/floating-composer.js +226 -15
- package/dist/comments/floating-composer.js.map +1 -1
- package/dist/comments/floating-composer.mjs +224 -15
- package/dist/comments/floating-composer.mjs.map +1 -1
- package/dist/create-dom-range.js +63 -0
- package/dist/create-dom-range.js.map +1 -0
- package/dist/create-dom-range.mjs +61 -0
- package/dist/create-dom-range.mjs.map +1 -0
- package/dist/create-rects-from-dom-range.js +36 -0
- package/dist/create-rects-from-dom-range.js.map +1 -0
- package/dist/create-rects-from-dom-range.mjs +34 -0
- package/dist/create-rects-from-dom-range.mjs.map +1 -0
- package/dist/index.d.mts +96 -44
- package/dist/index.d.ts +96 -44
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -4
- package/dist/index.mjs.map +1 -1
- package/dist/liveblocks-config.js +3 -75
- package/dist/liveblocks-config.js.map +1 -1
- package/dist/liveblocks-config.mjs +4 -56
- package/dist/liveblocks-config.mjs.map +1 -1
- package/dist/liveblocks-plugin-provider.js +12 -29
- package/dist/liveblocks-plugin-provider.js.map +1 -1
- package/dist/liveblocks-plugin-provider.mjs +13 -29
- package/dist/liveblocks-plugin-provider.mjs.map +1 -1
- package/dist/mentions/avatar.js +10 -6
- package/dist/mentions/avatar.js.map +1 -1
- package/dist/mentions/avatar.mjs +10 -6
- package/dist/mentions/avatar.mjs.map +1 -1
- package/dist/mentions/mention-component.js +5 -18
- package/dist/mentions/mention-component.js.map +1 -1
- package/dist/mentions/mention-component.mjs +7 -19
- package/dist/mentions/mention-component.mjs.map +1 -1
- package/dist/mentions/mention-node.js +76 -80
- package/dist/mentions/mention-node.js.map +1 -1
- package/dist/mentions/mention-node.mjs +75 -81
- package/dist/mentions/mention-node.mjs.map +1 -1
- package/dist/mentions/mention-plugin.js +102 -90
- package/dist/mentions/mention-plugin.js.map +1 -1
- package/dist/mentions/mention-plugin.mjs +87 -71
- package/dist/mentions/mention-plugin.mjs.map +1 -1
- package/dist/mentions/suggestions.js +34 -6
- package/dist/mentions/suggestions.js.map +1 -1
- package/dist/mentions/suggestions.mjs +28 -3
- package/dist/mentions/suggestions.mjs.map +1 -1
- package/dist/mentions/user.js +8 -5
- package/dist/mentions/user.js.map +1 -1
- package/dist/mentions/user.mjs +8 -5
- package/dist/mentions/user.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/version.mjs.map +1 -1
- package/package.json +13 -13
- package/src/styles/constants.css +1 -0
- package/src/styles/index.css +142 -0
- package/src/styles/utils.css +6 -0
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/active-selection.js +0 -143
- package/dist/active-selection.js.map +0 -1
- package/dist/active-selection.mjs +0 -123
- package/dist/active-selection.mjs.map +0 -1
- package/dist/floating-selection-container.js +0 -157
- package/dist/floating-selection-container.js.map +0 -1
- package/dist/floating-selection-container.mjs +0 -155
- package/dist/floating-selection-container.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floating-composer.mjs","sources":["../../src/comments/floating-composer.tsx"],"sourcesContent":["import { Composer, ComposerProps } from \"@liveblocks/react-comments\";\nimport React, { ComponentRef, forwardRef, KeyboardEvent } from \"react\";\nimport { FloatingSelectionContainer } from \"../floating-selection-container\";\nimport type { BaseMetadata } from \"@liveblocks/core\";\nimport {\n useHideFloatingComposer,\n useShowFloatingComposer,\n} from \"./comment-plugin-provider\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n\ntype ComposerElement = ComponentRef<typeof Composer>;\n\ntype ThreadMetadata = {\n resolved?: boolean;\n};\n\ntype FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<\n ComposerProps<M>,\n \"threadId\" | \"commentId\"\n>;\n\nexport const FloatingComposer = forwardRef<\n ComposerElement,\n FloatingComposerProps\n>(function FloatingComposer(props, forwardedRef) {\n const shouldShowFloatingComposer = useShowFloatingComposer();\n const hideFloatingComposer = useHideFloatingComposer();\n const [editor] = useLexicalComposerContext();\n\n if (!shouldShowFloatingComposer) return null;\n\n function handleKeyDown(event: KeyboardEvent<HTMLFormElement>) {\n if (event.key === \"Escape\") {\n hideFloatingComposer();\n editor.focus();\n }\n }\n\n return (\n <FloatingSelectionContainer\n sideOffset={5}\n alignOffset={0}\n collisionPadding={5}\n >\n <Composer\n autoFocus\n onKeyDown={handleKeyDown}\n {...props}\n ref={forwardedRef}\n />\n </FloatingSelectionContainer>\n );\n});\n"],"names":["FloatingComposer","React"],"mappings":";;;;;;AAqBO,MAAM,gBAAmB,GAAA,UAAA,CAG9B,SAASA,iBAAAA,CAAiB,OAAO,YAAc,EAAA;AAC/C,EAAA,MAAM,6BAA6B,uBAAwB,EAAA,CAAA;AAC3D,EAAA,MAAM,uBAAuB,uBAAwB,EAAA,CAAA;AACrD,EAAM,MAAA,CAAC,MAAM,CAAA,GAAI,yBAA0B,EAAA,CAAA;AAE3C,EAAA,IAAI,CAAC,0BAAA;AAA4B,IAAO,OAAA,IAAA,CAAA;AAExC,EAAA,SAAS,cAAc,KAAuC,EAAA;AAC5D,IAAI,IAAA,KAAA,CAAM,QAAQ,QAAU,EAAA;AAC1B,MAAqB,oBAAA,EAAA,CAAA;AACrB,MAAA,MAAA,CAAO,KAAM,EAAA,CAAA;AAAA,KACf;AAAA,GACF;AAEA,EAAA,uBACGC,cAAA,CAAA,aAAA,CAAA,0BAAA,EAAA;AAAA,IACC,UAAY,EAAA,CAAA;AAAA,IACZ,WAAa,EAAA,CAAA;AAAA,IACb,gBAAkB,EAAA,CAAA;AAAA,GAAA,kBAEjBA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA;AAAA,IACC,SAAS,EAAA,IAAA;AAAA,IACT,SAAW,EAAA,aAAA;AAAA,IACV,GAAG,KAAA;AAAA,IACJ,GAAK,EAAA,YAAA;AAAA,GACP,CACF,CAAA,CAAA;AAEJ,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"floating-composer.mjs","sources":["../../src/comments/floating-composer.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n hide,\n limitShift,\n offset,\n shift,\n size,\n useFloating,\n} from \"@floating-ui/react-dom\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { BaseMetadata } from \"@liveblocks/core\";\nimport { useCreateThread } from \"@liveblocks/react\";\nimport type {\n ComposerProps,\n ComposerSubmitComment,\n} from \"@liveblocks/react-ui\";\nimport { Composer } from \"@liveblocks/react-ui\";\nimport type { LexicalCommand } from \"lexical\";\nimport {\n $getSelection,\n $isRangeSelection,\n $setSelection,\n COMMAND_PRIORITY_EDITOR,\n createCommand,\n} from \"lexical\";\nimport type { ComponentRef, FormEvent, KeyboardEvent, ReactNode } from \"react\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { createDOMRange } from \"../create-dom-range\";\nimport { createRectsFromDOMRange } from \"../create-rects-from-dom-range\";\nimport $wrapSelectionInThreadMarkNode from \"./wrap-selection-in-thread-mark-node\";\n\nexport const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void> =\n createCommand(\"OPEN_FLOATING_COMPOSER_COMMAND\");\n\ntype ComposerElement = ComponentRef<typeof Composer>;\n\ntype ThreadMetadata = {\n resolved?: boolean;\n};\n\ntype FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<\n ComposerProps<M>,\n \"threadId\" | \"commentId\"\n>;\n\nexport const FloatingComposer = forwardRef<\n ComposerElement,\n FloatingComposerProps\n>(function FloatingComposer(props, forwardedRef) {\n const [range, setRange] = useState<Range | null>(null);\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n return editor.registerCommand(\n OPEN_FLOATING_COMPOSER_COMMAND,\n () => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return false;\n\n if (selection.isCollapsed()) return false;\n\n const { anchor, focus } = selection;\n\n const range = createDOMRange(\n editor,\n anchor.getNode(),\n anchor.offset,\n focus.getNode(),\n focus.offset\n );\n\n setRange(range);\n\n return true;\n },\n COMMAND_PRIORITY_EDITOR\n );\n }, [editor]);\n\n if (range === null) return null;\n\n return (\n <FloatingComposerImpl\n ref={forwardedRef}\n {...props}\n range={range}\n onRangeChange={setRange}\n />\n );\n});\n\ninterface FloatingComposerImplProps extends FloatingComposerProps {\n range: Range;\n onRangeChange: (range: Range | null) => void;\n}\n\nconst FloatingComposerImpl = forwardRef<\n ComposerElement,\n FloatingComposerImplProps\n>(function FloatingComposer(props, forwardedRef) {\n const {\n range,\n onRangeChange,\n onKeyDown,\n onComposerSubmit,\n ...composerProps\n } = props;\n\n const [editor] = useLexicalComposerContext();\n const createThread = useCreateThread();\n\n const $onStateRead = useCallback((): Range | null => {\n const selection = $getSelection();\n\n // If the selection is not a range selection or is collapsed, clear the range so the composer is no longer displayed.\n if (!$isRangeSelection(selection) || selection.isCollapsed()) {\n return null;\n }\n\n const { anchor, focus } = selection;\n const range = createDOMRange(\n editor,\n anchor.getNode(),\n anchor.offset,\n focus.getNode(),\n focus.offset\n );\n\n return range;\n }, [editor]);\n\n useEffect(() => {\n return editor.registerUpdateListener(({ editorState: state, tags }) => {\n // If the update is not related to collaboration, clear the range so the composer is no longer displayed.\n if (!tags.has(\"collaboration\")) {\n onRangeChange(null);\n return;\n }\n\n const range = state.read(() => $onStateRead());\n onRangeChange(range);\n });\n }, [editor, range, onRangeChange, $onStateRead]);\n\n /**\n * Create a new ThreadMarkNode and wrap the selected content in it.\n * @param threadId The id of the thread to associate with the selected content\n */\n const onThreadCreate = useCallback(\n (threadId: string) => {\n editor.update(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return;\n\n // If the selection is collapsed, we do not create a new thread node in the editor.\n if (selection.isCollapsed()) return;\n\n const isBackward = selection.isBackward();\n // Wrap content in a ThreadMarkNode\n $wrapSelectionInThreadMarkNode(selection, isBackward, threadId);\n\n // Clear the selection after wrapping\n $setSelection(null);\n });\n },\n [editor]\n );\n\n const handleComposerSubmit = useCallback(\n (comment: ComposerSubmitComment, event: FormEvent<HTMLFormElement>) => {\n onComposerSubmit?.(comment, event);\n if (event.defaultPrevented) return;\n\n event.preventDefault();\n\n const thread = createThread({\n body: comment.body,\n metadata: props.metadata ?? {},\n });\n\n onThreadCreate(thread.id);\n },\n [onThreadCreate, onComposerSubmit, props.metadata, createThread]\n );\n\n function handleKeyDown(event: KeyboardEvent<HTMLFormElement>) {\n if (event.key === \"Escape\") {\n onRangeChange(null);\n editor.focus();\n }\n onKeyDown?.(event);\n }\n\n return (\n <>\n <ActiveSelectionPortal range={range} container={document.body} />\n\n <FloatingComposerPortal range={range} container={document.body}>\n <Composer\n autoFocus\n {...composerProps}\n onKeyDown={handleKeyDown}\n onComposerSubmit={handleComposerSubmit}\n ref={forwardedRef}\n />\n </FloatingComposerPortal>\n </>\n );\n});\n\nfunction ActiveSelectionPortal({\n range,\n container,\n}: {\n range: Range;\n container: HTMLElement;\n}) {\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n middleware: [offset(-range.getBoundingClientRect().height)],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n useLayoutEffect(() => {\n setReference({\n getBoundingClientRect: () => range.getBoundingClientRect(),\n });\n }, [setReference, range]);\n\n const [editor] = useLexicalComposerContext();\n const rects = createRectsFromDOMRange(editor, range);\n\n return createPortal(\n <>\n <span\n ref={setFloating}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n width: range.getBoundingClientRect().width,\n height: range.getBoundingClientRect().height,\n pointerEvents: \"none\",\n }}\n className=\"lb-root lb-portal\"\n >\n {rects.map((rect) => (\n <span\n key={JSON.stringify(rect)}\n style={{\n position: \"absolute\",\n top: rect.top - range.getBoundingClientRect().top,\n left: rect.left - range.getBoundingClientRect().left,\n width: rect.width,\n height: rect.height,\n backgroundColor: \"rgba(0, 0, 255, 0.2)\",\n pointerEvents: \"none\",\n }}\n className=\"lb-lexical-active-selection\"\n />\n ))}\n </span>\n </>,\n container\n );\n}\n\nexport const FLOATING_COMPOSER_COLLISION_PADDING = 10;\n\nfunction FloatingComposerPortal({\n container,\n range,\n children,\n}: {\n container: HTMLElement;\n range: Range;\n children: ReactNode;\n}) {\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n middleware: [\n flip({ padding: FLOATING_COMPOSER_COLLISION_PADDING, crossAxis: false }),\n offset(10),\n hide({ padding: FLOATING_COMPOSER_COLLISION_PADDING }),\n shift({\n padding: FLOATING_COMPOSER_COLLISION_PADDING,\n limiter: limitShift(),\n }),\n size({ padding: FLOATING_COMPOSER_COLLISION_PADDING }),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n useLayoutEffect(() => {\n setReference({\n getBoundingClientRect: () => range.getBoundingClientRect(),\n });\n }, [range, setReference]);\n\n return createPortal(\n <div\n ref={setFloating}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n }}\n className=\"lb-root lb-portal lb-elevation lb-lexical-floating-composer\"\n >\n {children}\n </div>,\n container\n );\n}\n"],"names":["FloatingComposer","range","React"],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var lexical = require('lexical');
|
|
4
|
+
|
|
5
|
+
function getDOMTextNode(element) {
|
|
6
|
+
let node = element;
|
|
7
|
+
while (node !== null) {
|
|
8
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
9
|
+
return node;
|
|
10
|
+
}
|
|
11
|
+
node = node.firstChild;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
function getDOMIndexWithinParent(node) {
|
|
16
|
+
const parent = node.parentNode;
|
|
17
|
+
if (parent === null) {
|
|
18
|
+
throw new Error("Should never happen");
|
|
19
|
+
}
|
|
20
|
+
return [parent, Array.from(parent.childNodes).indexOf(node)];
|
|
21
|
+
}
|
|
22
|
+
function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {
|
|
23
|
+
const anchorKey = anchorNode.getKey();
|
|
24
|
+
const focusKey = focusNode.getKey();
|
|
25
|
+
const range = document.createRange();
|
|
26
|
+
let anchorDOM = editor.getElementByKey(anchorKey);
|
|
27
|
+
let focusDOM = editor.getElementByKey(focusKey);
|
|
28
|
+
let anchorOffset = _anchorOffset;
|
|
29
|
+
let focusOffset = _focusOffset;
|
|
30
|
+
if (lexical.$isTextNode(anchorNode)) {
|
|
31
|
+
anchorDOM = getDOMTextNode(anchorDOM);
|
|
32
|
+
}
|
|
33
|
+
if (lexical.$isTextNode(focusNode)) {
|
|
34
|
+
focusDOM = getDOMTextNode(focusDOM);
|
|
35
|
+
}
|
|
36
|
+
if (anchorNode === void 0 || focusNode === void 0 || anchorDOM === null || focusDOM === null) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (anchorDOM.nodeName === "BR") {
|
|
40
|
+
[anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
|
|
41
|
+
}
|
|
42
|
+
if (focusDOM.nodeName === "BR") {
|
|
43
|
+
[focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
|
|
44
|
+
}
|
|
45
|
+
const firstChild = anchorDOM.firstChild;
|
|
46
|
+
if (anchorDOM === focusDOM && firstChild !== null && firstChild.nodeName === "BR" && anchorOffset === 0 && focusOffset === 0) {
|
|
47
|
+
focusOffset = 1;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
range.setStart(anchorDOM, anchorOffset);
|
|
51
|
+
range.setEnd(focusDOM, focusOffset);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
|
|
56
|
+
range.setStart(focusDOM, focusOffset);
|
|
57
|
+
range.setEnd(anchorDOM, anchorOffset);
|
|
58
|
+
}
|
|
59
|
+
return range;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.createDOMRange = createDOMRange;
|
|
63
|
+
//# sourceMappingURL=create-dom-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-dom-range.js","sources":["../src/create-dom-range.ts"],"sourcesContent":["/**\n * MIT License\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { LexicalEditor, LexicalNode } from \"lexical\";\nimport { $isTextNode } from \"lexical\";\n\nfunction getDOMTextNode(element: Node | null): Text | null {\n let node = element;\n\n while (node !== null) {\n if (node.nodeType === Node.TEXT_NODE) {\n return node as Text;\n }\n\n node = node.firstChild;\n }\n\n return null;\n}\n\nfunction getDOMIndexWithinParent(node: ChildNode): [ParentNode, number] {\n const parent = node.parentNode;\n\n if (parent === null) {\n throw new Error(\"Should never happen\");\n }\n\n return [parent, Array.from(parent.childNodes).indexOf(node)];\n}\n\n/**\n * Creates a selection range for the DOM.\n * @param editor - The lexical editor.\n * @param anchorNode - The anchor node of a selection.\n * @param _anchorOffset - The amount of space offset from the anchor to the focus.\n * @param focusNode - The current focus.\n * @param _focusOffset - The amount of space offset from the focus to the anchor.\n * @returns The range of selection for the DOM that was created.\n */\nexport function createDOMRange(\n editor: LexicalEditor,\n anchorNode: LexicalNode,\n _anchorOffset: number,\n focusNode: LexicalNode,\n _focusOffset: number\n): Range | null {\n const anchorKey = anchorNode.getKey();\n const focusKey = focusNode.getKey();\n const range = document.createRange();\n let anchorDOM: Node | Text | null = editor.getElementByKey(anchorKey);\n let focusDOM: Node | Text | null = editor.getElementByKey(focusKey);\n let anchorOffset = _anchorOffset;\n let focusOffset = _focusOffset;\n\n if ($isTextNode(anchorNode)) {\n anchorDOM = getDOMTextNode(anchorDOM);\n }\n\n if ($isTextNode(focusNode)) {\n focusDOM = getDOMTextNode(focusDOM);\n }\n\n if (\n anchorNode === undefined ||\n focusNode === undefined ||\n anchorDOM === null ||\n focusDOM === null\n ) {\n return null;\n }\n\n if (anchorDOM.nodeName === \"BR\") {\n [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM as ChildNode);\n }\n\n if (focusDOM.nodeName === \"BR\") {\n [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM as ChildNode);\n }\n\n const firstChild = anchorDOM.firstChild;\n\n if (\n anchorDOM === focusDOM &&\n firstChild !== null &&\n firstChild.nodeName === \"BR\" &&\n anchorOffset === 0 &&\n focusOffset === 0\n ) {\n focusOffset = 1;\n }\n\n try {\n range.setStart(anchorDOM, anchorOffset);\n range.setEnd(focusDOM, focusOffset);\n } catch (e) {\n return null;\n }\n\n if (\n range.collapsed &&\n (anchorOffset !== focusOffset || anchorKey !== focusKey)\n ) {\n // Range is backwards, we need to reverse it\n range.setStart(focusDOM, focusOffset);\n range.setEnd(anchorDOM, anchorOffset);\n }\n\n return range;\n}\n"],"names":["$isTextNode"],"mappings":";;;;AA0BA,SAAS,eAAe,OAAmC,EAAA;AACzD,EAAA,IAAI,IAAO,GAAA,OAAA,CAAA;AAEX,EAAA,OAAO,SAAS,IAAM,EAAA;AACpB,IAAI,IAAA,IAAA,CAAK,QAAa,KAAA,IAAA,CAAK,SAAW,EAAA;AACpC,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAEA,IAAA,IAAA,GAAO,IAAK,CAAA,UAAA,CAAA;AAAA,GACd;AAEA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA;AAEA,SAAS,wBAAwB,IAAuC,EAAA;AACtE,EAAA,MAAM,SAAS,IAAK,CAAA,UAAA,CAAA;AAEpB,EAAA,IAAI,WAAW,IAAM,EAAA;AACnB,IAAM,MAAA,IAAI,MAAM,qBAAqB,CAAA,CAAA;AAAA,GACvC;AAEA,EAAO,OAAA,CAAC,QAAQ,KAAM,CAAA,IAAA,CAAK,OAAO,UAAU,CAAA,CAAE,OAAQ,CAAA,IAAI,CAAC,CAAA,CAAA;AAC7D,CAAA;AAWO,SAAS,cACd,CAAA,MAAA,EACA,UACA,EAAA,aAAA,EACA,WACA,YACc,EAAA;AACd,EAAM,MAAA,SAAA,GAAY,WAAW,MAAO,EAAA,CAAA;AACpC,EAAM,MAAA,QAAA,GAAW,UAAU,MAAO,EAAA,CAAA;AAClC,EAAM,MAAA,KAAA,GAAQ,SAAS,WAAY,EAAA,CAAA;AACnC,EAAI,IAAA,SAAA,GAAgC,MAAO,CAAA,eAAA,CAAgB,SAAS,CAAA,CAAA;AACpE,EAAI,IAAA,QAAA,GAA+B,MAAO,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClE,EAAA,IAAI,YAAe,GAAA,aAAA,CAAA;AACnB,EAAA,IAAI,WAAc,GAAA,YAAA,CAAA;AAElB,EAAI,IAAAA,mBAAA,CAAY,UAAU,CAAG,EAAA;AAC3B,IAAA,SAAA,GAAY,eAAe,SAAS,CAAA,CAAA;AAAA,GACtC;AAEA,EAAI,IAAAA,mBAAA,CAAY,SAAS,CAAG,EAAA;AAC1B,IAAA,QAAA,GAAW,eAAe,QAAQ,CAAA,CAAA;AAAA,GACpC;AAEA,EAAA,IACE,eAAe,KACf,CAAA,IAAA,SAAA,KAAc,UACd,SAAc,KAAA,IAAA,IACd,aAAa,IACb,EAAA;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA,SAAA,CAAU,aAAa,IAAM,EAAA;AAC/B,IAAA,CAAC,SAAW,EAAA,YAAY,CAAI,GAAA,uBAAA,CAAwB,SAAsB,CAAA,CAAA;AAAA,GAC5E;AAEA,EAAI,IAAA,QAAA,CAAS,aAAa,IAAM,EAAA;AAC9B,IAAA,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,uBAAA,CAAwB,QAAqB,CAAA,CAAA;AAAA,GACzE;AAEA,EAAA,MAAM,aAAa,SAAU,CAAA,UAAA,CAAA;AAE7B,EACE,IAAA,SAAA,KAAc,QACd,IAAA,UAAA,KAAe,IACf,IAAA,UAAA,CAAW,aAAa,IACxB,IAAA,YAAA,KAAiB,CACjB,IAAA,WAAA,KAAgB,CAChB,EAAA;AACA,IAAc,WAAA,GAAA,CAAA,CAAA;AAAA,GAChB;AAEA,EAAI,IAAA;AACF,IAAM,KAAA,CAAA,QAAA,CAAS,WAAW,YAAY,CAAA,CAAA;AACtC,IAAM,KAAA,CAAA,MAAA,CAAO,UAAU,WAAW,CAAA,CAAA;AAAA,WAC3B,CAAP,EAAA;AACA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,IACE,KAAM,CAAA,SAAA,KACL,YAAiB,KAAA,WAAA,IAAe,cAAc,QAC/C,CAAA,EAAA;AAEA,IAAM,KAAA,CAAA,QAAA,CAAS,UAAU,WAAW,CAAA,CAAA;AACpC,IAAM,KAAA,CAAA,MAAA,CAAO,WAAW,YAAY,CAAA,CAAA;AAAA,GACtC;AAEA,EAAO,OAAA,KAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { $isTextNode } from 'lexical';
|
|
2
|
+
|
|
3
|
+
function getDOMTextNode(element) {
|
|
4
|
+
let node = element;
|
|
5
|
+
while (node !== null) {
|
|
6
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
7
|
+
return node;
|
|
8
|
+
}
|
|
9
|
+
node = node.firstChild;
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
function getDOMIndexWithinParent(node) {
|
|
14
|
+
const parent = node.parentNode;
|
|
15
|
+
if (parent === null) {
|
|
16
|
+
throw new Error("Should never happen");
|
|
17
|
+
}
|
|
18
|
+
return [parent, Array.from(parent.childNodes).indexOf(node)];
|
|
19
|
+
}
|
|
20
|
+
function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {
|
|
21
|
+
const anchorKey = anchorNode.getKey();
|
|
22
|
+
const focusKey = focusNode.getKey();
|
|
23
|
+
const range = document.createRange();
|
|
24
|
+
let anchorDOM = editor.getElementByKey(anchorKey);
|
|
25
|
+
let focusDOM = editor.getElementByKey(focusKey);
|
|
26
|
+
let anchorOffset = _anchorOffset;
|
|
27
|
+
let focusOffset = _focusOffset;
|
|
28
|
+
if ($isTextNode(anchorNode)) {
|
|
29
|
+
anchorDOM = getDOMTextNode(anchorDOM);
|
|
30
|
+
}
|
|
31
|
+
if ($isTextNode(focusNode)) {
|
|
32
|
+
focusDOM = getDOMTextNode(focusDOM);
|
|
33
|
+
}
|
|
34
|
+
if (anchorNode === void 0 || focusNode === void 0 || anchorDOM === null || focusDOM === null) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (anchorDOM.nodeName === "BR") {
|
|
38
|
+
[anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
|
|
39
|
+
}
|
|
40
|
+
if (focusDOM.nodeName === "BR") {
|
|
41
|
+
[focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
|
|
42
|
+
}
|
|
43
|
+
const firstChild = anchorDOM.firstChild;
|
|
44
|
+
if (anchorDOM === focusDOM && firstChild !== null && firstChild.nodeName === "BR" && anchorOffset === 0 && focusOffset === 0) {
|
|
45
|
+
focusOffset = 1;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
range.setStart(anchorDOM, anchorOffset);
|
|
49
|
+
range.setEnd(focusDOM, focusOffset);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
|
|
54
|
+
range.setStart(focusDOM, focusOffset);
|
|
55
|
+
range.setEnd(anchorDOM, anchorOffset);
|
|
56
|
+
}
|
|
57
|
+
return range;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { createDOMRange };
|
|
61
|
+
//# sourceMappingURL=create-dom-range.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-dom-range.mjs","sources":["../src/create-dom-range.ts"],"sourcesContent":["/**\n * MIT License\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { LexicalEditor, LexicalNode } from \"lexical\";\nimport { $isTextNode } from \"lexical\";\n\nfunction getDOMTextNode(element: Node | null): Text | null {\n let node = element;\n\n while (node !== null) {\n if (node.nodeType === Node.TEXT_NODE) {\n return node as Text;\n }\n\n node = node.firstChild;\n }\n\n return null;\n}\n\nfunction getDOMIndexWithinParent(node: ChildNode): [ParentNode, number] {\n const parent = node.parentNode;\n\n if (parent === null) {\n throw new Error(\"Should never happen\");\n }\n\n return [parent, Array.from(parent.childNodes).indexOf(node)];\n}\n\n/**\n * Creates a selection range for the DOM.\n * @param editor - The lexical editor.\n * @param anchorNode - The anchor node of a selection.\n * @param _anchorOffset - The amount of space offset from the anchor to the focus.\n * @param focusNode - The current focus.\n * @param _focusOffset - The amount of space offset from the focus to the anchor.\n * @returns The range of selection for the DOM that was created.\n */\nexport function createDOMRange(\n editor: LexicalEditor,\n anchorNode: LexicalNode,\n _anchorOffset: number,\n focusNode: LexicalNode,\n _focusOffset: number\n): Range | null {\n const anchorKey = anchorNode.getKey();\n const focusKey = focusNode.getKey();\n const range = document.createRange();\n let anchorDOM: Node | Text | null = editor.getElementByKey(anchorKey);\n let focusDOM: Node | Text | null = editor.getElementByKey(focusKey);\n let anchorOffset = _anchorOffset;\n let focusOffset = _focusOffset;\n\n if ($isTextNode(anchorNode)) {\n anchorDOM = getDOMTextNode(anchorDOM);\n }\n\n if ($isTextNode(focusNode)) {\n focusDOM = getDOMTextNode(focusDOM);\n }\n\n if (\n anchorNode === undefined ||\n focusNode === undefined ||\n anchorDOM === null ||\n focusDOM === null\n ) {\n return null;\n }\n\n if (anchorDOM.nodeName === \"BR\") {\n [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM as ChildNode);\n }\n\n if (focusDOM.nodeName === \"BR\") {\n [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM as ChildNode);\n }\n\n const firstChild = anchorDOM.firstChild;\n\n if (\n anchorDOM === focusDOM &&\n firstChild !== null &&\n firstChild.nodeName === \"BR\" &&\n anchorOffset === 0 &&\n focusOffset === 0\n ) {\n focusOffset = 1;\n }\n\n try {\n range.setStart(anchorDOM, anchorOffset);\n range.setEnd(focusDOM, focusOffset);\n } catch (e) {\n return null;\n }\n\n if (\n range.collapsed &&\n (anchorOffset !== focusOffset || anchorKey !== focusKey)\n ) {\n // Range is backwards, we need to reverse it\n range.setStart(focusDOM, focusOffset);\n range.setEnd(anchorDOM, anchorOffset);\n }\n\n return range;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function createRectsFromDOMRange(editor, range) {
|
|
4
|
+
const rootElement = editor.getRootElement();
|
|
5
|
+
if (rootElement === null) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
9
|
+
const computedStyle = getComputedStyle(rootElement);
|
|
10
|
+
const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
|
|
11
|
+
const selectionRects = Array.from(range.getClientRects());
|
|
12
|
+
let selectionRectsLength = selectionRects.length;
|
|
13
|
+
selectionRects.sort((a, b) => {
|
|
14
|
+
const top = a.top - b.top;
|
|
15
|
+
if (Math.abs(top) <= 3) {
|
|
16
|
+
return a.left - b.left;
|
|
17
|
+
}
|
|
18
|
+
return top;
|
|
19
|
+
});
|
|
20
|
+
let prevRect;
|
|
21
|
+
for (let i = 0; i < selectionRectsLength; i++) {
|
|
22
|
+
const selectionRect = selectionRects[i];
|
|
23
|
+
const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left;
|
|
24
|
+
const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
|
|
25
|
+
if (isOverlappingRect || selectionSpansElement) {
|
|
26
|
+
selectionRects.splice(i--, 1);
|
|
27
|
+
selectionRectsLength--;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
prevRect = selectionRect;
|
|
31
|
+
}
|
|
32
|
+
return selectionRects;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.createRectsFromDOMRange = createRectsFromDOMRange;
|
|
36
|
+
//# sourceMappingURL=create-rects-from-dom-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-rects-from-dom-range.js","sources":["../src/create-rects-from-dom-range.ts"],"sourcesContent":["/**\n * MIT License\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { LexicalEditor } from \"lexical\";\n\n/**\n * Creates DOMRects, generally used to help the editor find a specific location on the screen.\n * @param editor - The lexical editor\n * @param range - A fragment of a document that can contain nodes and parts of text nodes.\n * @returns The selectionRects as an array.\n */\nexport function createRectsFromDOMRange(\n editor: LexicalEditor,\n range: Range\n): Array<ClientRect> {\n const rootElement = editor.getRootElement();\n\n if (rootElement === null) {\n return [];\n }\n const rootRect = rootElement.getBoundingClientRect();\n const computedStyle = getComputedStyle(rootElement);\n const rootPadding =\n parseFloat(computedStyle.paddingLeft) +\n parseFloat(computedStyle.paddingRight);\n const selectionRects = Array.from(range.getClientRects());\n let selectionRectsLength = selectionRects.length;\n //sort rects from top left to bottom right.\n selectionRects.sort((a, b) => {\n const top = a.top - b.top;\n // Some rects match position closely, but not perfectly,\n // so we give a 3px tolerance.\n if (Math.abs(top) <= 3) {\n return a.left - b.left;\n }\n return top;\n });\n let prevRect;\n for (let i = 0; i < selectionRectsLength; i++) {\n const selectionRect = selectionRects[i];\n // Exclude rects that overlap preceding Rects in the sorted list.\n const isOverlappingRect =\n prevRect &&\n prevRect.top <= selectionRect.top &&\n prevRect.top + prevRect.height > selectionRect.top &&\n prevRect.left + prevRect.width > selectionRect.left;\n // Exclude selections that span the entire element\n const selectionSpansElement =\n selectionRect.width + rootPadding === rootRect.width;\n if (isOverlappingRect || selectionSpansElement) {\n selectionRects.splice(i--, 1);\n selectionRectsLength--;\n continue;\n }\n prevRect = selectionRect;\n }\n return selectionRects;\n}\n"],"names":[],"mappings":";;AA+BgB,SAAA,uBAAA,CACd,QACA,KACmB,EAAA;AACnB,EAAM,MAAA,WAAA,GAAc,OAAO,cAAe,EAAA,CAAA;AAE1C,EAAA,IAAI,gBAAgB,IAAM,EAAA;AACxB,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AACA,EAAM,MAAA,QAAA,GAAW,YAAY,qBAAsB,EAAA,CAAA;AACnD,EAAM,MAAA,aAAA,GAAgB,iBAAiB,WAAW,CAAA,CAAA;AAClD,EAAA,MAAM,cACJ,UAAW,CAAA,aAAA,CAAc,WAAW,CACpC,GAAA,UAAA,CAAW,cAAc,YAAY,CAAA,CAAA;AACvC,EAAA,MAAM,cAAiB,GAAA,KAAA,CAAM,IAAK,CAAA,KAAA,CAAM,gBAAgB,CAAA,CAAA;AACxD,EAAA,IAAI,uBAAuB,cAAe,CAAA,MAAA,CAAA;AAE1C,EAAe,cAAA,CAAA,IAAA,CAAK,CAAC,CAAA,EAAG,CAAM,KAAA;AAC5B,IAAM,MAAA,GAAA,GAAM,CAAE,CAAA,GAAA,GAAM,CAAE,CAAA,GAAA,CAAA;AAGtB,IAAA,IAAI,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,IAAK,CAAG,EAAA;AACtB,MAAO,OAAA,CAAA,CAAE,OAAO,CAAE,CAAA,IAAA,CAAA;AAAA,KACpB;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACD,EAAI,IAAA,QAAA,CAAA;AACJ,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,oBAAA,EAAsB,CAAK,EAAA,EAAA;AAC7C,IAAA,MAAM,gBAAgB,cAAe,CAAA,CAAA,CAAA,CAAA;AAErC,IAAA,MAAM,oBACJ,QACA,IAAA,QAAA,CAAS,GAAO,IAAA,aAAA,CAAc,OAC9B,QAAS,CAAA,GAAA,GAAM,QAAS,CAAA,MAAA,GAAS,cAAc,GAC/C,IAAA,QAAA,CAAS,IAAO,GAAA,QAAA,CAAS,QAAQ,aAAc,CAAA,IAAA,CAAA;AAEjD,IAAA,MAAM,qBACJ,GAAA,aAAA,CAAc,KAAQ,GAAA,WAAA,KAAgB,QAAS,CAAA,KAAA,CAAA;AACjD,IAAA,IAAI,qBAAqB,qBAAuB,EAAA;AAC9C,MAAe,cAAA,CAAA,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAC5B,MAAA,oBAAA,EAAA,CAAA;AACA,MAAA,SAAA;AAAA,KACF;AACA,IAAW,QAAA,GAAA,aAAA,CAAA;AAAA,GACb;AACA,EAAO,OAAA,cAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
function createRectsFromDOMRange(editor, range) {
|
|
2
|
+
const rootElement = editor.getRootElement();
|
|
3
|
+
if (rootElement === null) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
const rootRect = rootElement.getBoundingClientRect();
|
|
7
|
+
const computedStyle = getComputedStyle(rootElement);
|
|
8
|
+
const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
|
|
9
|
+
const selectionRects = Array.from(range.getClientRects());
|
|
10
|
+
let selectionRectsLength = selectionRects.length;
|
|
11
|
+
selectionRects.sort((a, b) => {
|
|
12
|
+
const top = a.top - b.top;
|
|
13
|
+
if (Math.abs(top) <= 3) {
|
|
14
|
+
return a.left - b.left;
|
|
15
|
+
}
|
|
16
|
+
return top;
|
|
17
|
+
});
|
|
18
|
+
let prevRect;
|
|
19
|
+
for (let i = 0; i < selectionRectsLength; i++) {
|
|
20
|
+
const selectionRect = selectionRects[i];
|
|
21
|
+
const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left;
|
|
22
|
+
const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
|
|
23
|
+
if (isOverlappingRect || selectionSpansElement) {
|
|
24
|
+
selectionRects.splice(i--, 1);
|
|
25
|
+
selectionRectsLength--;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
prevRect = selectionRect;
|
|
29
|
+
}
|
|
30
|
+
return selectionRects;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { createRectsFromDOMRange };
|
|
34
|
+
//# sourceMappingURL=create-rects-from-dom-range.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-rects-from-dom-range.mjs","sources":["../src/create-rects-from-dom-range.ts"],"sourcesContent":["/**\n * MIT License\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n * \n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { LexicalEditor } from \"lexical\";\n\n/**\n * Creates DOMRects, generally used to help the editor find a specific location on the screen.\n * @param editor - The lexical editor\n * @param range - A fragment of a document that can contain nodes and parts of text nodes.\n * @returns The selectionRects as an array.\n */\nexport function createRectsFromDOMRange(\n editor: LexicalEditor,\n range: Range\n): Array<ClientRect> {\n const rootElement = editor.getRootElement();\n\n if (rootElement === null) {\n return [];\n }\n const rootRect = rootElement.getBoundingClientRect();\n const computedStyle = getComputedStyle(rootElement);\n const rootPadding =\n parseFloat(computedStyle.paddingLeft) +\n parseFloat(computedStyle.paddingRight);\n const selectionRects = Array.from(range.getClientRects());\n let selectionRectsLength = selectionRects.length;\n //sort rects from top left to bottom right.\n selectionRects.sort((a, b) => {\n const top = a.top - b.top;\n // Some rects match position closely, but not perfectly,\n // so we give a 3px tolerance.\n if (Math.abs(top) <= 3) {\n return a.left - b.left;\n }\n return top;\n });\n let prevRect;\n for (let i = 0; i < selectionRectsLength; i++) {\n const selectionRect = selectionRects[i];\n // Exclude rects that overlap preceding Rects in the sorted list.\n const isOverlappingRect =\n prevRect &&\n prevRect.top <= selectionRect.top &&\n prevRect.top + prevRect.height > selectionRect.top &&\n prevRect.left + prevRect.width > selectionRect.left;\n // Exclude selections that span the entire element\n const selectionSpansElement =\n selectionRect.width + rootPadding === rootRect.width;\n if (isOverlappingRect || selectionSpansElement) {\n selectionRects.splice(i--, 1);\n selectionRectsLength--;\n continue;\n }\n prevRect = selectionRect;\n }\n return selectionRects;\n}\n"],"names":[],"mappings":"AA+BgB,SAAA,uBAAA,CACd,QACA,KACmB,EAAA;AACnB,EAAM,MAAA,WAAA,GAAc,OAAO,cAAe,EAAA,CAAA;AAE1C,EAAA,IAAI,gBAAgB,IAAM,EAAA;AACxB,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AACA,EAAM,MAAA,QAAA,GAAW,YAAY,qBAAsB,EAAA,CAAA;AACnD,EAAM,MAAA,aAAA,GAAgB,iBAAiB,WAAW,CAAA,CAAA;AAClD,EAAA,MAAM,cACJ,UAAW,CAAA,aAAA,CAAc,WAAW,CACpC,GAAA,UAAA,CAAW,cAAc,YAAY,CAAA,CAAA;AACvC,EAAA,MAAM,cAAiB,GAAA,KAAA,CAAM,IAAK,CAAA,KAAA,CAAM,gBAAgB,CAAA,CAAA;AACxD,EAAA,IAAI,uBAAuB,cAAe,CAAA,MAAA,CAAA;AAE1C,EAAe,cAAA,CAAA,IAAA,CAAK,CAAC,CAAA,EAAG,CAAM,KAAA;AAC5B,IAAM,MAAA,GAAA,GAAM,CAAE,CAAA,GAAA,GAAM,CAAE,CAAA,GAAA,CAAA;AAGtB,IAAA,IAAI,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,IAAK,CAAG,EAAA;AACtB,MAAO,OAAA,CAAA,CAAE,OAAO,CAAE,CAAA,IAAA,CAAA;AAAA,KACpB;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACD,EAAI,IAAA,QAAA,CAAA;AACJ,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,oBAAA,EAAsB,CAAK,EAAA,EAAA;AAC7C,IAAA,MAAM,gBAAgB,cAAe,CAAA,CAAA,CAAA,CAAA;AAErC,IAAA,MAAM,oBACJ,QACA,IAAA,QAAA,CAAS,GAAO,IAAA,aAAA,CAAc,OAC9B,QAAS,CAAA,GAAA,GAAM,QAAS,CAAA,MAAA,GAAS,cAAc,GAC/C,IAAA,QAAA,CAAS,IAAO,GAAA,QAAA,CAAS,QAAQ,aAAc,CAAA,IAAA,CAAA;AAEjD,IAAA,MAAM,qBACJ,GAAA,aAAA,CAAc,KAAQ,GAAA,WAAA,KAAgB,QAAS,CAAA,KAAA,CAAA;AACjD,IAAA,IAAI,qBAAqB,qBAAuB,EAAA;AAC9C,MAAe,cAAA,CAAA,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AAC5B,MAAA,oBAAA,EAAA,CAAA;AACA,MAAA,SAAA;AAAA,KACF;AACA,IAAW,QAAA,GAAA,aAAA,CAAA;AAAA,GACb;AACA,EAAO,OAAA,cAAA,CAAA;AACT;;;;"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,61 +1,113 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BaseMetadata, ThreadData } from '@liveblocks/core';
|
|
2
|
+
import { ComposerProps } from '@liveblocks/react-ui';
|
|
2
3
|
import * as lexical from 'lexical';
|
|
4
|
+
import { LexicalCommand, ElementNode, NodeKey, RangeSelection, LexicalNode, BaseSelection, Spread, SerializedElementNode, DecoratorNode, DOMConversionMap, DOMExportOutput, SerializedLexicalNode } from 'lexical';
|
|
5
|
+
import React, { ComponentType, ReactNode, JSX as JSX$1 } from 'react';
|
|
3
6
|
import { InitialConfigType } from '@lexical/react/LexicalComposer';
|
|
4
|
-
import { ComposerProps } from '@liveblocks/react-comments';
|
|
5
|
-
import { BaseMetadata } from '@liveblocks/core';
|
|
6
7
|
|
|
7
|
-
declare const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
children?: React.ReactNode;
|
|
8
|
+
declare const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void>;
|
|
9
|
+
declare type ThreadMetadata = {
|
|
10
|
+
resolved?: boolean;
|
|
11
11
|
};
|
|
12
|
-
declare
|
|
12
|
+
declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<ComposerProps<M>, "threadId" | "commentId">;
|
|
13
|
+
declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
/**
|
|
16
|
+
* MIT License
|
|
17
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
18
|
+
|
|
19
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
20
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
21
|
+
* in the Software without restriction, including without limitation the rights
|
|
22
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
23
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
24
|
+
* furnished to do so, subject to the following conditions:
|
|
25
|
+
*
|
|
26
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
27
|
+
* copies or substantial portions of the Software.
|
|
28
|
+
*
|
|
29
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
30
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
32
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
33
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
34
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
35
|
+
* SOFTWARE.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
declare type SerializedThreadMarkNode = Spread<{
|
|
39
|
+
ids: Array<string>;
|
|
40
|
+
}, SerializedElementNode>;
|
|
41
|
+
declare class ThreadMarkNode extends ElementNode {
|
|
42
|
+
static getType(): string;
|
|
43
|
+
static clone(node: ThreadMarkNode): ThreadMarkNode;
|
|
44
|
+
static importDOM(): null;
|
|
45
|
+
static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode;
|
|
46
|
+
exportJSON(): SerializedThreadMarkNode;
|
|
47
|
+
constructor(ids: Array<string>, key?: NodeKey);
|
|
48
|
+
createDOM(): HTMLElement;
|
|
49
|
+
updateDOM(): boolean;
|
|
50
|
+
hasID(id: string): boolean;
|
|
51
|
+
getIDs(): Array<string>;
|
|
52
|
+
addID(id: string): void;
|
|
53
|
+
deleteID(id: string): void;
|
|
54
|
+
insertNewAfter(_: RangeSelection, restoreSelection?: boolean): null | ElementNode;
|
|
55
|
+
canInsertTextBefore(): false;
|
|
56
|
+
canInsertTextAfter(): false;
|
|
57
|
+
canBeEmpty(): false;
|
|
58
|
+
isInline(): true;
|
|
59
|
+
extractWithChild(_: LexicalNode, selection: BaseSelection, destination: "clone" | "html"): boolean;
|
|
60
|
+
excludeFromCopy(destination: "clone" | "html"): boolean;
|
|
39
61
|
}
|
|
40
|
-
|
|
62
|
+
|
|
63
|
+
declare type ThreadProps = {
|
|
64
|
+
thread: ThreadData<BaseMetadata>;
|
|
65
|
+
isActive: boolean;
|
|
66
|
+
};
|
|
67
|
+
declare type ThreadPanelProps = {
|
|
68
|
+
renderThread?: ComponentType<ThreadProps>;
|
|
69
|
+
};
|
|
70
|
+
declare const ThreadPanel: ({ renderThread }: ThreadPanelProps) => React.JSX.Element;
|
|
71
|
+
|
|
72
|
+
declare function liveblocksConfig(editorConfig: Omit<InitialConfigType, "editorState">): {
|
|
41
73
|
nodes: (lexical.KlassConstructor<typeof lexical.LexicalNode> | lexical.LexicalNodeReplacement)[];
|
|
42
74
|
editorState: null;
|
|
75
|
+
html?: lexical.HTMLConfig | undefined;
|
|
76
|
+
onError: (error: Error, editor: lexical.LexicalEditor) => void;
|
|
43
77
|
editor__DEPRECATED?: lexical.LexicalEditor | null | undefined;
|
|
44
78
|
namespace: string;
|
|
45
|
-
onError: (error: Error, editor: lexical.LexicalEditor) => void;
|
|
46
79
|
editable?: boolean | undefined;
|
|
47
80
|
theme?: lexical.EditorThemeClasses | undefined;
|
|
48
|
-
html?: lexical.HTMLConfig | undefined;
|
|
49
81
|
};
|
|
50
82
|
|
|
51
|
-
declare
|
|
52
|
-
|
|
53
|
-
declare type ThreadMetadata = {
|
|
54
|
-
resolved?: boolean;
|
|
83
|
+
declare type LiveblocksPluginProps = {
|
|
84
|
+
children?: React.ReactNode;
|
|
55
85
|
};
|
|
56
|
-
declare
|
|
57
|
-
declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
|
|
86
|
+
declare const LiveblocksPlugin: ({ children, }: LiveblocksPluginProps) => JSX.Element;
|
|
58
87
|
|
|
59
|
-
declare function
|
|
88
|
+
declare function Mention({ nodeKey, children, }: {
|
|
89
|
+
nodeKey: NodeKey;
|
|
90
|
+
children: ReactNode;
|
|
91
|
+
}): React.JSX.Element;
|
|
92
|
+
|
|
93
|
+
declare type SerializedMentionNode = Spread<{
|
|
94
|
+
userId: string;
|
|
95
|
+
}, SerializedLexicalNode>;
|
|
96
|
+
declare class MentionNode extends DecoratorNode<JSX$1.Element> {
|
|
97
|
+
__id: string;
|
|
98
|
+
__userId: string;
|
|
99
|
+
constructor(id: string, userId: string, key?: NodeKey);
|
|
100
|
+
static getType(): string;
|
|
101
|
+
static clone(node: MentionNode): MentionNode;
|
|
102
|
+
createDOM(): HTMLElement;
|
|
103
|
+
updateDOM(): boolean;
|
|
104
|
+
static importDom(): DOMConversionMap<HTMLElement> | null;
|
|
105
|
+
exportDOM(): DOMExportOutput;
|
|
106
|
+
static importJSON(serializedNode: SerializedMentionNode): MentionNode;
|
|
107
|
+
exportJSON(): SerializedMentionNode;
|
|
108
|
+
getUserId(): string;
|
|
109
|
+
getId(): string;
|
|
110
|
+
decorate(): JSX$1.Element;
|
|
111
|
+
}
|
|
60
112
|
|
|
61
|
-
export { FloatingComposer,
|
|
113
|
+
export { FloatingComposer, LiveblocksPlugin, Mention, MentionNode, OPEN_FLOATING_COMPOSER_COMMAND, ThreadMarkNode, ThreadPanel, liveblocksConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,61 +1,113 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BaseMetadata, ThreadData } from '@liveblocks/core';
|
|
2
|
+
import { ComposerProps } from '@liveblocks/react-ui';
|
|
2
3
|
import * as lexical from 'lexical';
|
|
4
|
+
import { LexicalCommand, ElementNode, NodeKey, RangeSelection, LexicalNode, BaseSelection, Spread, SerializedElementNode, DecoratorNode, DOMConversionMap, DOMExportOutput, SerializedLexicalNode } from 'lexical';
|
|
5
|
+
import React, { ComponentType, ReactNode, JSX as JSX$1 } from 'react';
|
|
3
6
|
import { InitialConfigType } from '@lexical/react/LexicalComposer';
|
|
4
|
-
import { ComposerProps } from '@liveblocks/react-comments';
|
|
5
|
-
import { BaseMetadata } from '@liveblocks/core';
|
|
6
7
|
|
|
7
|
-
declare const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
children?: React.ReactNode;
|
|
8
|
+
declare const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void>;
|
|
9
|
+
declare type ThreadMetadata = {
|
|
10
|
+
resolved?: boolean;
|
|
11
11
|
};
|
|
12
|
-
declare
|
|
12
|
+
declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<ComposerProps<M>, "threadId" | "commentId">;
|
|
13
|
+
declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
15
|
+
/**
|
|
16
|
+
* MIT License
|
|
17
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
18
|
+
|
|
19
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
20
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
21
|
+
* in the Software without restriction, including without limitation the rights
|
|
22
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
23
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
24
|
+
* furnished to do so, subject to the following conditions:
|
|
25
|
+
*
|
|
26
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
27
|
+
* copies or substantial portions of the Software.
|
|
28
|
+
*
|
|
29
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
30
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
32
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
33
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
34
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
35
|
+
* SOFTWARE.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
declare type SerializedThreadMarkNode = Spread<{
|
|
39
|
+
ids: Array<string>;
|
|
40
|
+
}, SerializedElementNode>;
|
|
41
|
+
declare class ThreadMarkNode extends ElementNode {
|
|
42
|
+
static getType(): string;
|
|
43
|
+
static clone(node: ThreadMarkNode): ThreadMarkNode;
|
|
44
|
+
static importDOM(): null;
|
|
45
|
+
static importJSON(serializedNode: SerializedThreadMarkNode): ThreadMarkNode;
|
|
46
|
+
exportJSON(): SerializedThreadMarkNode;
|
|
47
|
+
constructor(ids: Array<string>, key?: NodeKey);
|
|
48
|
+
createDOM(): HTMLElement;
|
|
49
|
+
updateDOM(): boolean;
|
|
50
|
+
hasID(id: string): boolean;
|
|
51
|
+
getIDs(): Array<string>;
|
|
52
|
+
addID(id: string): void;
|
|
53
|
+
deleteID(id: string): void;
|
|
54
|
+
insertNewAfter(_: RangeSelection, restoreSelection?: boolean): null | ElementNode;
|
|
55
|
+
canInsertTextBefore(): false;
|
|
56
|
+
canInsertTextAfter(): false;
|
|
57
|
+
canBeEmpty(): false;
|
|
58
|
+
isInline(): true;
|
|
59
|
+
extractWithChild(_: LexicalNode, selection: BaseSelection, destination: "clone" | "html"): boolean;
|
|
60
|
+
excludeFromCopy(destination: "clone" | "html"): boolean;
|
|
39
61
|
}
|
|
40
|
-
|
|
62
|
+
|
|
63
|
+
declare type ThreadProps = {
|
|
64
|
+
thread: ThreadData<BaseMetadata>;
|
|
65
|
+
isActive: boolean;
|
|
66
|
+
};
|
|
67
|
+
declare type ThreadPanelProps = {
|
|
68
|
+
renderThread?: ComponentType<ThreadProps>;
|
|
69
|
+
};
|
|
70
|
+
declare const ThreadPanel: ({ renderThread }: ThreadPanelProps) => React.JSX.Element;
|
|
71
|
+
|
|
72
|
+
declare function liveblocksConfig(editorConfig: Omit<InitialConfigType, "editorState">): {
|
|
41
73
|
nodes: (lexical.KlassConstructor<typeof lexical.LexicalNode> | lexical.LexicalNodeReplacement)[];
|
|
42
74
|
editorState: null;
|
|
75
|
+
html?: lexical.HTMLConfig | undefined;
|
|
76
|
+
onError: (error: Error, editor: lexical.LexicalEditor) => void;
|
|
43
77
|
editor__DEPRECATED?: lexical.LexicalEditor | null | undefined;
|
|
44
78
|
namespace: string;
|
|
45
|
-
onError: (error: Error, editor: lexical.LexicalEditor) => void;
|
|
46
79
|
editable?: boolean | undefined;
|
|
47
80
|
theme?: lexical.EditorThemeClasses | undefined;
|
|
48
|
-
html?: lexical.HTMLConfig | undefined;
|
|
49
81
|
};
|
|
50
82
|
|
|
51
|
-
declare
|
|
52
|
-
|
|
53
|
-
declare type ThreadMetadata = {
|
|
54
|
-
resolved?: boolean;
|
|
83
|
+
declare type LiveblocksPluginProps = {
|
|
84
|
+
children?: React.ReactNode;
|
|
55
85
|
};
|
|
56
|
-
declare
|
|
57
|
-
declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
|
|
86
|
+
declare const LiveblocksPlugin: ({ children, }: LiveblocksPluginProps) => JSX.Element;
|
|
58
87
|
|
|
59
|
-
declare function
|
|
88
|
+
declare function Mention({ nodeKey, children, }: {
|
|
89
|
+
nodeKey: NodeKey;
|
|
90
|
+
children: ReactNode;
|
|
91
|
+
}): React.JSX.Element;
|
|
92
|
+
|
|
93
|
+
declare type SerializedMentionNode = Spread<{
|
|
94
|
+
userId: string;
|
|
95
|
+
}, SerializedLexicalNode>;
|
|
96
|
+
declare class MentionNode extends DecoratorNode<JSX$1.Element> {
|
|
97
|
+
__id: string;
|
|
98
|
+
__userId: string;
|
|
99
|
+
constructor(id: string, userId: string, key?: NodeKey);
|
|
100
|
+
static getType(): string;
|
|
101
|
+
static clone(node: MentionNode): MentionNode;
|
|
102
|
+
createDOM(): HTMLElement;
|
|
103
|
+
updateDOM(): boolean;
|
|
104
|
+
static importDom(): DOMConversionMap<HTMLElement> | null;
|
|
105
|
+
exportDOM(): DOMExportOutput;
|
|
106
|
+
static importJSON(serializedNode: SerializedMentionNode): MentionNode;
|
|
107
|
+
exportJSON(): SerializedMentionNode;
|
|
108
|
+
getUserId(): string;
|
|
109
|
+
getId(): string;
|
|
110
|
+
decorate(): JSX$1.Element;
|
|
111
|
+
}
|
|
60
112
|
|
|
61
|
-
export { FloatingComposer,
|
|
113
|
+
export { FloatingComposer, LiveblocksPlugin, Mention, MentionNode, OPEN_FLOATING_COMPOSER_COMMAND, ThreadMarkNode, ThreadPanel, liveblocksConfig };
|