@liveblocks/react-lexical 2.1.1-test2 → 2.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"floating-composer.js","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\n/**\n * Dispatching OPEN_FLOATING_COMPOSER_COMMAND will display the FloatingComposer\n *\n * @example\n * import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n * import { OPEN_FLOATING_COMPOSER_COMMAND } from \"@liveblocks/react-lexical\";\n *\n * function Toolbar() {\n * const [editor] = useLexicalComposerContext();\n *\n * return (\n * <button\n * onClick={() => {\n * editor.dispatchCommand(OPEN_FLOATING_COMPOSER_COMMAND);\n * }}\n * >\n * 💬 New comment\n * </button>\n * );\n * }\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\n/**\n * Displays a `Composer` near the current lexical selection.\n *\n * To open it, dispatch `OPEN_FLOATING_COMPOSER_COMMAND`.\n *\n * Submitting a comment will attach an annotation thread at the current selection.\n * Should be nested inside `LiveblocksPlugin`.\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":["createCommand","forwardRef","FloatingComposer","useState","useLexicalComposerContext","useEffect","$getSelection","$isRangeSelection","range","createDOMRange","COMMAND_PRIORITY_EDITOR","useCreateThread","useCallback","$wrapSelectionInThreadMarkNode","$setSelection","Composer","useFloating","offset","autoUpdate","useLayoutEffect","createRectsFromDOMRange","createPortal","flip","hide","shift","limitShift","size"],"mappings":"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"}
1
+ {"version":3,"file":"floating-composer.js","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, DM } 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\n/**\n * Dispatching OPEN_FLOATING_COMPOSER_COMMAND will display the FloatingComposer\n *\n * @example\n * import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n * import { OPEN_FLOATING_COMPOSER_COMMAND } from \"@liveblocks/react-lexical\";\n *\n * function Toolbar() {\n * const [editor] = useLexicalComposerContext();\n *\n * return (\n * <button\n * onClick={() => {\n * editor.dispatchCommand(OPEN_FLOATING_COMPOSER_COMMAND);\n * }}\n * >\n * 💬 New comment\n * </button>\n * );\n * }\n */\nexport const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void> =\n createCommand(\"OPEN_FLOATING_COMPOSER_COMMAND\");\n\ntype ComposerElement = ComponentRef<typeof Composer>;\n\ntype FloatingComposerProps<M extends BaseMetadata = DM> = Omit<\n ComposerProps<M>,\n \"threadId\" | \"commentId\"\n>;\n\n/**\n * Displays a `Composer` near the current lexical selection.\n *\n * To open it, dispatch `OPEN_FLOATING_COMPOSER_COMMAND`.\n *\n * Submitting a comment will attach an annotation thread at the current selection.\n * Should be nested inside `LiveblocksPlugin`.\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":["createCommand","forwardRef","FloatingComposer","useState","useLexicalComposerContext","useEffect","$getSelection","$isRangeSelection","range","createDOMRange","COMMAND_PRIORITY_EDITOR","useCreateThread","useCallback","$wrapSelectionInThreadMarkNode","$setSelection","Composer","useFloating","offset","autoUpdate","useLayoutEffect","createRectsFromDOMRange","createPortal","flip","hide","shift","limitShift","size"],"mappings":"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"}
@@ -1 +1 @@
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\n/**\n * Dispatching OPEN_FLOATING_COMPOSER_COMMAND will display the FloatingComposer\n *\n * @example\n * import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n * import { OPEN_FLOATING_COMPOSER_COMMAND } from \"@liveblocks/react-lexical\";\n *\n * function Toolbar() {\n * const [editor] = useLexicalComposerContext();\n *\n * return (\n * <button\n * onClick={() => {\n * editor.dispatchCommand(OPEN_FLOATING_COMPOSER_COMMAND);\n * }}\n * >\n * 💬 New comment\n * </button>\n * );\n * }\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\n/**\n * Displays a `Composer` near the current lexical selection.\n *\n * To open it, dispatch `OPEN_FLOATING_COMPOSER_COMMAND`.\n *\n * Submitting a comment will attach an annotation thread at the current selection.\n * Should be nested inside `LiveblocksPlugin`.\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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"}
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, DM } 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\n/**\n * Dispatching OPEN_FLOATING_COMPOSER_COMMAND will display the FloatingComposer\n *\n * @example\n * import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n * import { OPEN_FLOATING_COMPOSER_COMMAND } from \"@liveblocks/react-lexical\";\n *\n * function Toolbar() {\n * const [editor] = useLexicalComposerContext();\n *\n * return (\n * <button\n * onClick={() => {\n * editor.dispatchCommand(OPEN_FLOATING_COMPOSER_COMMAND);\n * }}\n * >\n * 💬 New comment\n * </button>\n * );\n * }\n */\nexport const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void> =\n createCommand(\"OPEN_FLOATING_COMPOSER_COMMAND\");\n\ntype ComposerElement = ComponentRef<typeof Composer>;\n\ntype FloatingComposerProps<M extends BaseMetadata = DM> = Omit<\n ComposerProps<M>,\n \"threadId\" | \"commentId\"\n>;\n\n/**\n * Displays a `Composer` near the current lexical selection.\n *\n * To open it, dispatch `OPEN_FLOATING_COMPOSER_COMMAND`.\n *\n * Submitting a comment will attach an annotation thread at the current selection.\n * Should be nested inside `LiveblocksPlugin`.\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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"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseMetadata } from '@liveblocks/core';
1
+ import { BaseMetadata, DM } from '@liveblocks/core';
2
2
  import { ComposerProps } from '@liveblocks/react-ui';
3
3
  import * as lexical from 'lexical';
4
4
  import { LexicalCommand } from 'lexical';
@@ -34,10 +34,7 @@ declare function useIsThreadActive(threadId: string): boolean;
34
34
  * }
35
35
  */
36
36
  declare const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void>;
37
- declare type ThreadMetadata = {
38
- resolved?: boolean;
39
- };
40
- declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<ComposerProps<M>, "threadId" | "commentId">;
37
+ declare type FloatingComposerProps<M extends BaseMetadata = DM> = Omit<ComposerProps<M>, "threadId" | "commentId">;
41
38
  /**
42
39
  * Displays a `Composer` near the current lexical selection.
43
40
  *
@@ -46,7 +43,7 @@ declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Om
46
43
  * Submitting a comment will attach an annotation thread at the current selection.
47
44
  * Should be nested inside `LiveblocksPlugin`.
48
45
  */
49
- declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
46
+ declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<BaseMetadata> & React.RefAttributes<HTMLFormElement>>;
50
47
 
51
48
  /**
52
49
  * Function that takes a Lexical editor config and modifies it to add the necessary
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseMetadata } from '@liveblocks/core';
1
+ import { BaseMetadata, DM } from '@liveblocks/core';
2
2
  import { ComposerProps } from '@liveblocks/react-ui';
3
3
  import * as lexical from 'lexical';
4
4
  import { LexicalCommand } from 'lexical';
@@ -34,10 +34,7 @@ declare function useIsThreadActive(threadId: string): boolean;
34
34
  * }
35
35
  */
36
36
  declare const OPEN_FLOATING_COMPOSER_COMMAND: LexicalCommand<void>;
37
- declare type ThreadMetadata = {
38
- resolved?: boolean;
39
- };
40
- declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Omit<ComposerProps<M>, "threadId" | "commentId">;
37
+ declare type FloatingComposerProps<M extends BaseMetadata = DM> = Omit<ComposerProps<M>, "threadId" | "commentId">;
41
38
  /**
42
39
  * Displays a `Composer` near the current lexical selection.
43
40
  *
@@ -46,7 +43,7 @@ declare type FloatingComposerProps<M extends BaseMetadata = ThreadMetadata> = Om
46
43
  * Submitting a comment will attach an annotation thread at the current selection.
47
44
  * Should be nested inside `LiveblocksPlugin`.
48
45
  */
49
- declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<ThreadMetadata> & React.RefAttributes<HTMLFormElement>>;
46
+ declare const FloatingComposer: React.ForwardRefExoticComponent<FloatingComposerProps<BaseMetadata> & React.RefAttributes<HTMLFormElement>>;
50
47
 
51
48
  /**
52
49
  * Function that takes a Lexical editor config and modifies it to add the necessary
@@ -1 +1 @@
1
- {"version":3,"file":"liveblocks-plugin-provider.js","sources":["../src/liveblocks-plugin-provider.tsx"],"sourcesContent":["import { autoUpdate, useFloating } from \"@floating-ui/react-dom\";\nimport { CollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { CollaborationPlugin } from \"@lexical/react/LexicalCollaborationPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { Provider } from \"@lexical/yjs\";\nimport { kInternal, nn } from \"@liveblocks/core\";\nimport { useClient, useRoom, useSelf } from \"@liveblocks/react\";\nimport { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { MutableRefObject } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport { Doc } from \"yjs\";\n\nimport { CommentPluginProvider } from \"./comments/comment-plugin-provider\";\nimport { ThreadMarkNode } from \"./comments/thread-mark-node\";\nimport { MentionNode } from \"./mentions/mention-node\";\nimport { MentionPlugin } from \"./mentions/mention-plugin\";\n\n// TODO: Replace by ref once I understand why useRef is not stable (?!)\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<never, never, never, never, never>\n>();\n\nexport type EditorStatus =\n /* The editor state is not loaded and has not been requested. */\n | \"not-loaded\"\n /* The editor state is loading from Liveblocks servers */\n | \"loading\"\n /**\n * Not working yet! Will be available in a future release.\n * Some editor state modifications has not been acknowledged yet by the server\n */\n | \"synchronizing\"\n /* The editor state is sync with Liveblocks servers */\n | \"synchronized\";\n\nfunction getEditorStatus(\n provider?: LiveblocksYjsProvider<never, never, never, never, never>\n) {\n if (provider === undefined) {\n return \"not-loaded\";\n }\n\n return provider.synced ? \"synchronized\" : \"loading\";\n}\n\n/**\n * Get the storage status.\n *\n * - `not-loaded`: Initial state when entering the room.\n * - `loading`: Once the editor state has been requested by LiveblocksPlugin.\n * - `synchronizing`: Not working yet! Will be available in a future release.\n * - `synchronized`: The editor state is sync with Liveblocks servers.\n */\nexport function useEditorStatus(): EditorStatus {\n const room = useRoom();\n const provider = providersMap.get(room.id);\n\n const [status, setStatus] = useState<EditorStatus>(getEditorStatus(provider));\n\n useEffect(() => {\n const provider = providersMap.get(room.id);\n\n setStatus(getEditorStatus(provider));\n\n if (provider === undefined) {\n return;\n }\n\n const cb = () => setStatus(getEditorStatus(provider));\n\n provider.on(\"sync\", cb);\n\n return () => provider.off(\"sync\", cb);\n }, [room]);\n\n return status;\n}\n\nexport type LiveblocksPluginProps = {\n children?: React.ReactNode;\n};\n\n/**\n * Liveblocks plugin for Lexical that adds collaboration to your editor.\n *\n * `LiveblocksPlugin` should always be nested inside `LexicalComposer`.\n *\n * @example\n *\n * import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\n * import { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\n * import { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\n * import { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\n * import { liveblocksConfig, LiveblocksPlugin } from \"@liveblocks/react-lexical\";\n *\n * const initialConfig = liveblocksConfig({\n * namespace: \"MyEditor\",\n * theme: {},\n * nodes: [],\n * onError: (err) => console.error(err),\n * });\n *\n * function Editor() {\n * return (\n * <LexicalComposer initialConfig={initialConfig}>\n * <LiveblocksPlugin />\n * <RichTextPlugin\n * contentEditable={<ContentEditable />}\n * placeholder={<div>Enter some text...</div>}\n * ErrorBoundary={LexicalErrorBoundary}\n * />\n * </LexicalComposer>\n * );\n * }\n */\nexport const LiveblocksPlugin = ({\n children,\n}: LiveblocksPluginProps): JSX.Element => {\n const client = useClient();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const [editor] = useLexicalComposerContext();\n const room = useRoom();\n const collabContext = useContext(CollaborationContext);\n const previousRoomIdRef = useRef<string | null>(null);\n\n if (!editor.hasNodes([ThreadMarkNode, MentionNode])) {\n throw new Error(\n \"LiveblocksPlugin requires Lexical configuration to be wrapped in the `liveblocksConfig(options)` function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-react-lexical#liveblocksConfig\"\n );\n }\n\n const [containerRef, setContainerRef] = useState<\n MutableRefObject<HTMLDivElement | null> | undefined\n >(undefined);\n\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n // Warn users if initialConfig.editorState, set on the composer, is not null\n useEffect(() => {\n // only in dev mode\n if (process.env.NODE_ENV !== \"production\") {\n // A user should not even be set an emptyState, but when passing null, getEditorState still has initial empty state\n if (!editor.getEditorState().isEmpty()) {\n console.warn(\n \"Warning: LiveblocksPlugin: editorState in initialConfig detected, but must be null.\"\n );\n }\n }\n\n // we know editor is already defined as we're inside LexicalComposer, and we only want this running the first time\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n // Report that this is lexical and root is the rootKey\n room[kInternal].reportTextEditor(\"lexical\", \"root\");\n }, [room]);\n\n // Get user info or allow override from props\n const info = useSelf((me) => me.info);\n const username = info?.name || \"\"; // use empty string to prevent random name\n const cursorcolor = info?.color as string | undefined;\n\n const providerFactory = useCallback(\n (id: string, yjsDocMap: Map<string, Doc>): Provider => {\n // Destroy previously used provider to avoid memory leaks\n // TODO: Find a way to destroy the last used provider on unmount (while working with StrictMode)\n if (\n previousRoomIdRef.current !== null &&\n previousRoomIdRef.current !== id\n ) {\n const previousProvider = providersMap.get(id);\n if (previousProvider !== undefined) {\n previousProvider.destroy();\n }\n }\n\n let doc = yjsDocMap.get(id);\n\n if (doc === undefined) {\n doc = new Doc();\n const provider = new LiveblocksYjsProvider(room, doc);\n yjsDocMap.set(id, doc);\n providersMap.set(id, provider);\n }\n\n return nn(\n providersMap.get(id),\n \"Internal error. Should never happen\"\n ) as Provider;\n },\n [room]\n );\n\n useEffect(() => {\n collabContext.name = username || \"\";\n }, [collabContext, username]);\n\n const root = useRootElement();\n\n useLayoutEffect(() => {\n if (root === null) return;\n setReference({\n getBoundingClientRect: () => root.getBoundingClientRect(),\n });\n }, [setReference, root]);\n\n const handleFloatingRef = useCallback(\n (node: HTMLDivElement) => {\n setFloating(node);\n setContainerRef({ current: node });\n },\n [setFloating, setContainerRef]\n );\n\n return (\n <>\n <div\n ref={handleFloatingRef}\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 />\n\n <CollaborationPlugin\n // Setting the key allows us to reset the internal Y.doc used by useYjsCollaboration\n // without implementing `reload` event\n key={room.id}\n id={room.id}\n providerFactory={providerFactory}\n username={username}\n cursorColor={cursorcolor}\n cursorsContainerRef={containerRef}\n shouldBootstrap={true}\n />\n\n {hasResolveMentionSuggestions && <MentionPlugin />}\n\n <CommentPluginProvider>{children}</CommentPluginProvider>\n </>\n );\n};\n\nfunction useRootElement(): HTMLElement | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerRootListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getRootElement();\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["useRoom","useState","useEffect","provider","useClient","kInternal","useLexicalComposerContext","useContext","CollaborationContext","useRef","ThreadMarkNode","MentionNode","useFloating","autoUpdate","useSelf","useCallback","Doc","LiveblocksYjsProvider","nn","useLayoutEffect","CollaborationPlugin","MentionPlugin","CommentPluginProvider","useSyncExternalStore"],"mappings":"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"}
1
+ {"version":3,"file":"liveblocks-plugin-provider.js","sources":["../src/liveblocks-plugin-provider.tsx"],"sourcesContent":["import { autoUpdate, useFloating } from \"@floating-ui/react-dom\";\nimport { CollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { CollaborationPlugin } from \"@lexical/react/LexicalCollaborationPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { Provider } from \"@lexical/yjs\";\nimport { kInternal, nn } from \"@liveblocks/core\";\nimport { useClient, useRoom, useSelf } from \"@liveblocks/react\";\nimport { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { MutableRefObject } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport { Doc } from \"yjs\";\n\nimport { CommentPluginProvider } from \"./comments/comment-plugin-provider\";\nimport { ThreadMarkNode } from \"./comments/thread-mark-node\";\nimport { MentionNode } from \"./mentions/mention-node\";\nimport { MentionPlugin } from \"./mentions/mention-plugin\";\n\n// TODO: Replace by ref once I understand why useRef is not stable (?!)\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<never, never, never, never, never>\n>();\n\nexport type EditorStatus =\n /* The editor state is not loaded and has not been requested. */\n | \"not-loaded\"\n /* The editor state is loading from Liveblocks servers */\n | \"loading\"\n /**\n * Not working yet! Will be available in a future release.\n * Some editor state modifications has not been acknowledged yet by the server\n */\n | \"synchronizing\"\n /* The editor state is sync with Liveblocks servers */\n | \"synchronized\";\n\nfunction getEditorStatus(\n provider?: LiveblocksYjsProvider<never, never, never, never, never>\n): EditorStatus {\n if (provider === undefined) {\n return \"not-loaded\";\n }\n\n return provider.synced ? \"synchronized\" : \"loading\";\n}\n\n/**\n * Get the storage status.\n *\n * - `not-loaded`: Initial state when entering the room.\n * - `loading`: Once the editor state has been requested by LiveblocksPlugin.\n * - `synchronizing`: Not working yet! Will be available in a future release.\n * - `synchronized`: The editor state is sync with Liveblocks servers.\n */\nexport function useEditorStatus(): EditorStatus {\n const room = useRoom();\n const provider = providersMap.get(room.id);\n\n const [status, setStatus] = useState(getEditorStatus(provider));\n\n useEffect(() => {\n const provider = providersMap.get(room.id);\n\n setStatus(getEditorStatus(provider));\n\n if (provider === undefined) {\n return;\n }\n\n const cb = () => setStatus(getEditorStatus(provider));\n\n provider.on(\"sync\", cb);\n\n return () => provider.off(\"sync\", cb);\n }, [room]);\n\n return status;\n}\n\nexport type LiveblocksPluginProps = {\n children?: React.ReactNode;\n};\n\n/**\n * Liveblocks plugin for Lexical that adds collaboration to your editor.\n *\n * `LiveblocksPlugin` should always be nested inside `LexicalComposer`.\n *\n * @example\n *\n * import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\n * import { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\n * import { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\n * import { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\n * import { liveblocksConfig, LiveblocksPlugin } from \"@liveblocks/react-lexical\";\n *\n * const initialConfig = liveblocksConfig({\n * namespace: \"MyEditor\",\n * theme: {},\n * nodes: [],\n * onError: (err) => console.error(err),\n * });\n *\n * function Editor() {\n * return (\n * <LexicalComposer initialConfig={initialConfig}>\n * <LiveblocksPlugin />\n * <RichTextPlugin\n * contentEditable={<ContentEditable />}\n * placeholder={<div>Enter some text...</div>}\n * ErrorBoundary={LexicalErrorBoundary}\n * />\n * </LexicalComposer>\n * );\n * }\n */\nexport const LiveblocksPlugin = ({\n children,\n}: LiveblocksPluginProps): JSX.Element => {\n const client = useClient();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const [editor] = useLexicalComposerContext();\n const room = useRoom();\n const collabContext = useContext(CollaborationContext);\n const previousRoomIdRef = useRef<string | null>(null);\n\n if (!editor.hasNodes([ThreadMarkNode, MentionNode])) {\n throw new Error(\n \"LiveblocksPlugin requires Lexical configuration to be wrapped in the `liveblocksConfig(options)` function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-react-lexical#liveblocksConfig\"\n );\n }\n\n const [containerRef, setContainerRef] = useState<\n MutableRefObject<HTMLDivElement | null> | undefined\n >(undefined);\n\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n // Warn users if initialConfig.editorState, set on the composer, is not null\n useEffect(() => {\n // only in dev mode\n if (process.env.NODE_ENV !== \"production\") {\n // A user should not even be set an emptyState, but when passing null, getEditorState still has initial empty state\n if (!editor.getEditorState().isEmpty()) {\n console.warn(\n \"Warning: LiveblocksPlugin: editorState in initialConfig detected, but must be null.\"\n );\n }\n }\n\n // we know editor is already defined as we're inside LexicalComposer, and we only want this running the first time\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n // Report that this is lexical and root is the rootKey\n room[kInternal].reportTextEditor(\"lexical\", \"root\");\n }, [room]);\n\n // Get user info or allow override from props\n const info = useSelf((me) => me.info);\n const username = info?.name || \"\"; // use empty string to prevent random name\n const cursorcolor = info?.color as string | undefined;\n\n const providerFactory = useCallback(\n (id: string, yjsDocMap: Map<string, Doc>): Provider => {\n // Destroy previously used provider to avoid memory leaks\n // TODO: Find a way to destroy the last used provider on unmount (while working with StrictMode)\n if (\n previousRoomIdRef.current !== null &&\n previousRoomIdRef.current !== id\n ) {\n const previousProvider = providersMap.get(id);\n if (previousProvider !== undefined) {\n previousProvider.destroy();\n }\n }\n\n let doc = yjsDocMap.get(id);\n\n if (doc === undefined) {\n doc = new Doc();\n const provider = new LiveblocksYjsProvider(room, doc);\n yjsDocMap.set(id, doc);\n providersMap.set(id, provider);\n }\n\n return nn(\n providersMap.get(id),\n \"Internal error. Should never happen\"\n ) as Provider;\n },\n [room]\n );\n\n useEffect(() => {\n collabContext.name = username || \"\";\n }, [collabContext, username]);\n\n const root = useRootElement();\n\n useLayoutEffect(() => {\n if (root === null) return;\n setReference({\n getBoundingClientRect: () => root.getBoundingClientRect(),\n });\n }, [setReference, root]);\n\n const handleFloatingRef = useCallback(\n (node: HTMLDivElement) => {\n setFloating(node);\n setContainerRef({ current: node });\n },\n [setFloating, setContainerRef]\n );\n\n return (\n <>\n <div\n ref={handleFloatingRef}\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 />\n\n <CollaborationPlugin\n // Setting the key allows us to reset the internal Y.doc used by useYjsCollaboration\n // without implementing `reload` event\n key={room.id}\n id={room.id}\n providerFactory={providerFactory}\n username={username}\n cursorColor={cursorcolor}\n cursorsContainerRef={containerRef}\n shouldBootstrap={true}\n />\n\n {hasResolveMentionSuggestions && <MentionPlugin />}\n\n <CommentPluginProvider>{children}</CommentPluginProvider>\n </>\n );\n};\n\nfunction useRootElement(): HTMLElement | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerRootListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getRootElement();\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["useRoom","useState","useEffect","provider","useClient","kInternal","useLexicalComposerContext","useContext","CollaborationContext","useRef","ThreadMarkNode","MentionNode","useFloating","autoUpdate","useSelf","useCallback","Doc","LiveblocksYjsProvider","nn","useLayoutEffect","CollaborationPlugin","MentionPlugin","CommentPluginProvider","useSyncExternalStore"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"liveblocks-plugin-provider.mjs","sources":["../src/liveblocks-plugin-provider.tsx"],"sourcesContent":["import { autoUpdate, useFloating } from \"@floating-ui/react-dom\";\nimport { CollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { CollaborationPlugin } from \"@lexical/react/LexicalCollaborationPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { Provider } from \"@lexical/yjs\";\nimport { kInternal, nn } from \"@liveblocks/core\";\nimport { useClient, useRoom, useSelf } from \"@liveblocks/react\";\nimport { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { MutableRefObject } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport { Doc } from \"yjs\";\n\nimport { CommentPluginProvider } from \"./comments/comment-plugin-provider\";\nimport { ThreadMarkNode } from \"./comments/thread-mark-node\";\nimport { MentionNode } from \"./mentions/mention-node\";\nimport { MentionPlugin } from \"./mentions/mention-plugin\";\n\n// TODO: Replace by ref once I understand why useRef is not stable (?!)\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<never, never, never, never, never>\n>();\n\nexport type EditorStatus =\n /* The editor state is not loaded and has not been requested. */\n | \"not-loaded\"\n /* The editor state is loading from Liveblocks servers */\n | \"loading\"\n /**\n * Not working yet! Will be available in a future release.\n * Some editor state modifications has not been acknowledged yet by the server\n */\n | \"synchronizing\"\n /* The editor state is sync with Liveblocks servers */\n | \"synchronized\";\n\nfunction getEditorStatus(\n provider?: LiveblocksYjsProvider<never, never, never, never, never>\n) {\n if (provider === undefined) {\n return \"not-loaded\";\n }\n\n return provider.synced ? \"synchronized\" : \"loading\";\n}\n\n/**\n * Get the storage status.\n *\n * - `not-loaded`: Initial state when entering the room.\n * - `loading`: Once the editor state has been requested by LiveblocksPlugin.\n * - `synchronizing`: Not working yet! Will be available in a future release.\n * - `synchronized`: The editor state is sync with Liveblocks servers.\n */\nexport function useEditorStatus(): EditorStatus {\n const room = useRoom();\n const provider = providersMap.get(room.id);\n\n const [status, setStatus] = useState<EditorStatus>(getEditorStatus(provider));\n\n useEffect(() => {\n const provider = providersMap.get(room.id);\n\n setStatus(getEditorStatus(provider));\n\n if (provider === undefined) {\n return;\n }\n\n const cb = () => setStatus(getEditorStatus(provider));\n\n provider.on(\"sync\", cb);\n\n return () => provider.off(\"sync\", cb);\n }, [room]);\n\n return status;\n}\n\nexport type LiveblocksPluginProps = {\n children?: React.ReactNode;\n};\n\n/**\n * Liveblocks plugin for Lexical that adds collaboration to your editor.\n *\n * `LiveblocksPlugin` should always be nested inside `LexicalComposer`.\n *\n * @example\n *\n * import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\n * import { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\n * import { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\n * import { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\n * import { liveblocksConfig, LiveblocksPlugin } from \"@liveblocks/react-lexical\";\n *\n * const initialConfig = liveblocksConfig({\n * namespace: \"MyEditor\",\n * theme: {},\n * nodes: [],\n * onError: (err) => console.error(err),\n * });\n *\n * function Editor() {\n * return (\n * <LexicalComposer initialConfig={initialConfig}>\n * <LiveblocksPlugin />\n * <RichTextPlugin\n * contentEditable={<ContentEditable />}\n * placeholder={<div>Enter some text...</div>}\n * ErrorBoundary={LexicalErrorBoundary}\n * />\n * </LexicalComposer>\n * );\n * }\n */\nexport const LiveblocksPlugin = ({\n children,\n}: LiveblocksPluginProps): JSX.Element => {\n const client = useClient();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const [editor] = useLexicalComposerContext();\n const room = useRoom();\n const collabContext = useContext(CollaborationContext);\n const previousRoomIdRef = useRef<string | null>(null);\n\n if (!editor.hasNodes([ThreadMarkNode, MentionNode])) {\n throw new Error(\n \"LiveblocksPlugin requires Lexical configuration to be wrapped in the `liveblocksConfig(options)` function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-react-lexical#liveblocksConfig\"\n );\n }\n\n const [containerRef, setContainerRef] = useState<\n MutableRefObject<HTMLDivElement | null> | undefined\n >(undefined);\n\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n // Warn users if initialConfig.editorState, set on the composer, is not null\n useEffect(() => {\n // only in dev mode\n if (process.env.NODE_ENV !== \"production\") {\n // A user should not even be set an emptyState, but when passing null, getEditorState still has initial empty state\n if (!editor.getEditorState().isEmpty()) {\n console.warn(\n \"Warning: LiveblocksPlugin: editorState in initialConfig detected, but must be null.\"\n );\n }\n }\n\n // we know editor is already defined as we're inside LexicalComposer, and we only want this running the first time\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n // Report that this is lexical and root is the rootKey\n room[kInternal].reportTextEditor(\"lexical\", \"root\");\n }, [room]);\n\n // Get user info or allow override from props\n const info = useSelf((me) => me.info);\n const username = info?.name || \"\"; // use empty string to prevent random name\n const cursorcolor = info?.color as string | undefined;\n\n const providerFactory = useCallback(\n (id: string, yjsDocMap: Map<string, Doc>): Provider => {\n // Destroy previously used provider to avoid memory leaks\n // TODO: Find a way to destroy the last used provider on unmount (while working with StrictMode)\n if (\n previousRoomIdRef.current !== null &&\n previousRoomIdRef.current !== id\n ) {\n const previousProvider = providersMap.get(id);\n if (previousProvider !== undefined) {\n previousProvider.destroy();\n }\n }\n\n let doc = yjsDocMap.get(id);\n\n if (doc === undefined) {\n doc = new Doc();\n const provider = new LiveblocksYjsProvider(room, doc);\n yjsDocMap.set(id, doc);\n providersMap.set(id, provider);\n }\n\n return nn(\n providersMap.get(id),\n \"Internal error. Should never happen\"\n ) as Provider;\n },\n [room]\n );\n\n useEffect(() => {\n collabContext.name = username || \"\";\n }, [collabContext, username]);\n\n const root = useRootElement();\n\n useLayoutEffect(() => {\n if (root === null) return;\n setReference({\n getBoundingClientRect: () => root.getBoundingClientRect(),\n });\n }, [setReference, root]);\n\n const handleFloatingRef = useCallback(\n (node: HTMLDivElement) => {\n setFloating(node);\n setContainerRef({ current: node });\n },\n [setFloating, setContainerRef]\n );\n\n return (\n <>\n <div\n ref={handleFloatingRef}\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 />\n\n <CollaborationPlugin\n // Setting the key allows us to reset the internal Y.doc used by useYjsCollaboration\n // without implementing `reload` event\n key={room.id}\n id={room.id}\n providerFactory={providerFactory}\n username={username}\n cursorColor={cursorcolor}\n cursorsContainerRef={containerRef}\n shouldBootstrap={true}\n />\n\n {hasResolveMentionSuggestions && <MentionPlugin />}\n\n <CommentPluginProvider>{children}</CommentPluginProvider>\n </>\n );\n};\n\nfunction useRootElement(): HTMLElement | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerRootListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getRootElement();\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["provider","React"],"mappings":"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"}
1
+ {"version":3,"file":"liveblocks-plugin-provider.mjs","sources":["../src/liveblocks-plugin-provider.tsx"],"sourcesContent":["import { autoUpdate, useFloating } from \"@floating-ui/react-dom\";\nimport { CollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { CollaborationPlugin } from \"@lexical/react/LexicalCollaborationPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { Provider } from \"@lexical/yjs\";\nimport { kInternal, nn } from \"@liveblocks/core\";\nimport { useClient, useRoom, useSelf } from \"@liveblocks/react\";\nimport { LiveblocksYjsProvider } from \"@liveblocks/yjs\";\nimport type { MutableRefObject } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport { Doc } from \"yjs\";\n\nimport { CommentPluginProvider } from \"./comments/comment-plugin-provider\";\nimport { ThreadMarkNode } from \"./comments/thread-mark-node\";\nimport { MentionNode } from \"./mentions/mention-node\";\nimport { MentionPlugin } from \"./mentions/mention-plugin\";\n\n// TODO: Replace by ref once I understand why useRef is not stable (?!)\nconst providersMap = new Map<\n string,\n LiveblocksYjsProvider<never, never, never, never, never>\n>();\n\nexport type EditorStatus =\n /* The editor state is not loaded and has not been requested. */\n | \"not-loaded\"\n /* The editor state is loading from Liveblocks servers */\n | \"loading\"\n /**\n * Not working yet! Will be available in a future release.\n * Some editor state modifications has not been acknowledged yet by the server\n */\n | \"synchronizing\"\n /* The editor state is sync with Liveblocks servers */\n | \"synchronized\";\n\nfunction getEditorStatus(\n provider?: LiveblocksYjsProvider<never, never, never, never, never>\n): EditorStatus {\n if (provider === undefined) {\n return \"not-loaded\";\n }\n\n return provider.synced ? \"synchronized\" : \"loading\";\n}\n\n/**\n * Get the storage status.\n *\n * - `not-loaded`: Initial state when entering the room.\n * - `loading`: Once the editor state has been requested by LiveblocksPlugin.\n * - `synchronizing`: Not working yet! Will be available in a future release.\n * - `synchronized`: The editor state is sync with Liveblocks servers.\n */\nexport function useEditorStatus(): EditorStatus {\n const room = useRoom();\n const provider = providersMap.get(room.id);\n\n const [status, setStatus] = useState(getEditorStatus(provider));\n\n useEffect(() => {\n const provider = providersMap.get(room.id);\n\n setStatus(getEditorStatus(provider));\n\n if (provider === undefined) {\n return;\n }\n\n const cb = () => setStatus(getEditorStatus(provider));\n\n provider.on(\"sync\", cb);\n\n return () => provider.off(\"sync\", cb);\n }, [room]);\n\n return status;\n}\n\nexport type LiveblocksPluginProps = {\n children?: React.ReactNode;\n};\n\n/**\n * Liveblocks plugin for Lexical that adds collaboration to your editor.\n *\n * `LiveblocksPlugin` should always be nested inside `LexicalComposer`.\n *\n * @example\n *\n * import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\n * import { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\n * import { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\n * import { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\n * import { liveblocksConfig, LiveblocksPlugin } from \"@liveblocks/react-lexical\";\n *\n * const initialConfig = liveblocksConfig({\n * namespace: \"MyEditor\",\n * theme: {},\n * nodes: [],\n * onError: (err) => console.error(err),\n * });\n *\n * function Editor() {\n * return (\n * <LexicalComposer initialConfig={initialConfig}>\n * <LiveblocksPlugin />\n * <RichTextPlugin\n * contentEditable={<ContentEditable />}\n * placeholder={<div>Enter some text...</div>}\n * ErrorBoundary={LexicalErrorBoundary}\n * />\n * </LexicalComposer>\n * );\n * }\n */\nexport const LiveblocksPlugin = ({\n children,\n}: LiveblocksPluginProps): JSX.Element => {\n const client = useClient();\n const hasResolveMentionSuggestions =\n client[kInternal].resolveMentionSuggestions !== undefined;\n const [editor] = useLexicalComposerContext();\n const room = useRoom();\n const collabContext = useContext(CollaborationContext);\n const previousRoomIdRef = useRef<string | null>(null);\n\n if (!editor.hasNodes([ThreadMarkNode, MentionNode])) {\n throw new Error(\n \"LiveblocksPlugin requires Lexical configuration to be wrapped in the `liveblocksConfig(options)` function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-react-lexical#liveblocksConfig\"\n );\n }\n\n const [containerRef, setContainerRef] = useState<\n MutableRefObject<HTMLDivElement | null> | undefined\n >(undefined);\n\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"bottom\",\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n // Warn users if initialConfig.editorState, set on the composer, is not null\n useEffect(() => {\n // only in dev mode\n if (process.env.NODE_ENV !== \"production\") {\n // A user should not even be set an emptyState, but when passing null, getEditorState still has initial empty state\n if (!editor.getEditorState().isEmpty()) {\n console.warn(\n \"Warning: LiveblocksPlugin: editorState in initialConfig detected, but must be null.\"\n );\n }\n }\n\n // we know editor is already defined as we're inside LexicalComposer, and we only want this running the first time\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n // Report that this is lexical and root is the rootKey\n room[kInternal].reportTextEditor(\"lexical\", \"root\");\n }, [room]);\n\n // Get user info or allow override from props\n const info = useSelf((me) => me.info);\n const username = info?.name || \"\"; // use empty string to prevent random name\n const cursorcolor = info?.color as string | undefined;\n\n const providerFactory = useCallback(\n (id: string, yjsDocMap: Map<string, Doc>): Provider => {\n // Destroy previously used provider to avoid memory leaks\n // TODO: Find a way to destroy the last used provider on unmount (while working with StrictMode)\n if (\n previousRoomIdRef.current !== null &&\n previousRoomIdRef.current !== id\n ) {\n const previousProvider = providersMap.get(id);\n if (previousProvider !== undefined) {\n previousProvider.destroy();\n }\n }\n\n let doc = yjsDocMap.get(id);\n\n if (doc === undefined) {\n doc = new Doc();\n const provider = new LiveblocksYjsProvider(room, doc);\n yjsDocMap.set(id, doc);\n providersMap.set(id, provider);\n }\n\n return nn(\n providersMap.get(id),\n \"Internal error. Should never happen\"\n ) as Provider;\n },\n [room]\n );\n\n useEffect(() => {\n collabContext.name = username || \"\";\n }, [collabContext, username]);\n\n const root = useRootElement();\n\n useLayoutEffect(() => {\n if (root === null) return;\n setReference({\n getBoundingClientRect: () => root.getBoundingClientRect(),\n });\n }, [setReference, root]);\n\n const handleFloatingRef = useCallback(\n (node: HTMLDivElement) => {\n setFloating(node);\n setContainerRef({ current: node });\n },\n [setFloating, setContainerRef]\n );\n\n return (\n <>\n <div\n ref={handleFloatingRef}\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 />\n\n <CollaborationPlugin\n // Setting the key allows us to reset the internal Y.doc used by useYjsCollaboration\n // without implementing `reload` event\n key={room.id}\n id={room.id}\n providerFactory={providerFactory}\n username={username}\n cursorColor={cursorcolor}\n cursorsContainerRef={containerRef}\n shouldBootstrap={true}\n />\n\n {hasResolveMentionSuggestions && <MentionPlugin />}\n\n <CommentPluginProvider>{children}</CommentPluginProvider>\n </>\n );\n};\n\nfunction useRootElement(): HTMLElement | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerRootListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getRootElement();\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["provider","React"],"mappings":"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"}
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const PKG_NAME = "@liveblocks/react-lexical";
4
- const PKG_VERSION = typeof "2.1.1-test2" === "string" && "2.1.1-test2";
4
+ const PKG_VERSION = typeof "2.2.1" === "string" && "2.2.1";
5
5
  const PKG_FORMAT = typeof "cjs" === "string" && "cjs";
6
6
 
7
7
  exports.PKG_FORMAT = PKG_FORMAT;
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,4BAAA;AACX,MAAA,WAAA,GAAc,OAAO,aAAA,KAAgB,QAAY,IAAA,cAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;;;"}
1
+ {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":";;AAGO,MAAM,QAAW,GAAA,4BAAA;AACX,MAAA,WAAA,GAAc,OAAO,OAAA,KAAgB,QAAY,IAAA,QAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;;;"}
package/dist/version.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  const PKG_NAME = "@liveblocks/react-lexical";
2
- const PKG_VERSION = typeof "2.1.1-test2" === "string" && "2.1.1-test2";
2
+ const PKG_VERSION = typeof "2.2.1" === "string" && "2.2.1";
3
3
  const PKG_FORMAT = typeof "esm" === "string" && "esm";
4
4
 
5
5
  export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
@@ -1 +1 @@
1
- {"version":3,"file":"version.mjs","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,4BAAA;AACX,MAAA,WAAA,GAAc,OAAO,aAAA,KAAgB,QAAY,IAAA,cAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;"}
1
+ {"version":3,"file":"version.mjs","sources":["../src/version.ts"],"sourcesContent":["declare const __VERSION__: string;\ndeclare const ROLLUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react-lexical\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof ROLLUP_FORMAT === \"string\" && ROLLUP_FORMAT;\n"],"names":[],"mappings":"AAGO,MAAM,QAAW,GAAA,4BAAA;AACX,MAAA,WAAA,GAAc,OAAO,OAAA,KAAgB,QAAY,IAAA,QAAA;AACjD,MAAA,UAAA,GAAa,OAAO,KAAA,KAAkB,QAAY,IAAA;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/react-lexical",
3
- "version": "2.1.1-test2",
3
+ "version": "2.2.1",
4
4
  "description": "A lexical react plugin to enable collaboration, comments, live cursors, and more.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "commonjs",
@@ -42,19 +42,19 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@floating-ui/react-dom": "^2.1.0",
45
- "@liveblocks/client": "2.1.1-test2",
46
- "@liveblocks/core": "2.1.1-test2",
47
- "@liveblocks/react": "2.1.1-test2",
48
- "@liveblocks/react-ui": "2.1.1-test2",
49
- "@liveblocks/yjs": "2.1.1-test2",
45
+ "@liveblocks/client": "2.2.1",
46
+ "@liveblocks/core": "2.2.1",
47
+ "@liveblocks/react": "2.2.1",
48
+ "@liveblocks/react-ui": "2.2.1",
49
+ "@liveblocks/yjs": "2.2.1",
50
50
  "nanoid": "^3",
51
51
  "use-sync-external-store": "^1.2.2",
52
52
  "yjs": "^13.6.18"
53
53
  },
54
54
  "peerDependencies": {
55
- "@lexical/react": "^0.16.0",
56
- "@lexical/utils": "^0.16.0",
57
- "lexical": "^0.16.0",
55
+ "@lexical/react": "0.16.1",
56
+ "@lexical/utils": "0.16.1",
57
+ "lexical": "0.16.1",
58
58
  "react": "^16.14.0 || ^17 || ^18",
59
59
  "react-dom": "^16.14.0 || ^17 || ^18"
60
60
  },