@liveblocks/react-lexical 1.12.0-lexical3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/active-selection.js +143 -0
  2. package/dist/active-selection.js.map +1 -0
  3. package/dist/active-selection.mjs +123 -0
  4. package/dist/active-selection.mjs.map +1 -0
  5. package/dist/comments/ThreadPanel.js +26 -0
  6. package/dist/comments/ThreadPanel.js.map +1 -0
  7. package/dist/comments/ThreadPanel.mjs +24 -0
  8. package/dist/comments/ThreadPanel.mjs.map +1 -0
  9. package/dist/comments/comment-plugin-provider.js +322 -0
  10. package/dist/comments/comment-plugin-provider.js.map +1 -0
  11. package/dist/comments/comment-plugin-provider.mjs +299 -0
  12. package/dist/comments/comment-plugin-provider.mjs.map +1 -0
  13. package/dist/comments/floating-composer.js +34 -0
  14. package/dist/comments/floating-composer.js.map +1 -0
  15. package/dist/comments/floating-composer.mjs +32 -0
  16. package/dist/comments/floating-composer.mjs.map +1 -0
  17. package/dist/comments/get-thread-mark-ids.js +23 -0
  18. package/dist/comments/get-thread-mark-ids.js.map +1 -0
  19. package/dist/comments/get-thread-mark-ids.mjs +21 -0
  20. package/dist/comments/get-thread-mark-ids.mjs.map +1 -0
  21. package/dist/comments/thread-mark-node.js +138 -0
  22. package/dist/comments/thread-mark-node.js.map +1 -0
  23. package/dist/comments/thread-mark-node.mjs +134 -0
  24. package/dist/comments/thread-mark-node.mjs.map +1 -0
  25. package/dist/comments/unwrap-thread-mark-node.js +19 -0
  26. package/dist/comments/unwrap-thread-mark-node.js.map +1 -0
  27. package/dist/comments/unwrap-thread-mark-node.mjs +17 -0
  28. package/dist/comments/unwrap-thread-mark-node.mjs.map +1 -0
  29. package/dist/comments/wrap-selection-in-thread-mark-node.js +63 -0
  30. package/dist/comments/wrap-selection-in-thread-mark-node.js.map +1 -0
  31. package/dist/comments/wrap-selection-in-thread-mark-node.mjs +61 -0
  32. package/dist/comments/wrap-selection-in-thread-mark-node.mjs.map +1 -0
  33. package/dist/floating-selection-container.js +157 -0
  34. package/dist/floating-selection-container.js.map +1 -0
  35. package/dist/floating-selection-container.mjs +155 -0
  36. package/dist/floating-selection-container.mjs.map +1 -0
  37. package/dist/index.d.ts +61 -0
  38. package/dist/index.js +20 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/index.mjs +11 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/dist/liveblocks-config.js +89 -0
  43. package/dist/liveblocks-config.js.map +1 -0
  44. package/dist/liveblocks-config.mjs +67 -0
  45. package/dist/liveblocks-config.mjs.map +1 -0
  46. package/dist/liveblocks-plugin-provider.js +79 -0
  47. package/dist/liveblocks-plugin-provider.js.map +1 -0
  48. package/dist/liveblocks-plugin-provider.mjs +76 -0
  49. package/dist/liveblocks-plugin-provider.mjs.map +1 -0
  50. package/dist/mentions/avatar.js +49 -0
  51. package/dist/mentions/avatar.js.map +1 -0
  52. package/dist/mentions/avatar.mjs +47 -0
  53. package/dist/mentions/avatar.mjs.map +1 -0
  54. package/dist/mentions/mention-component.js +63 -0
  55. package/dist/mentions/mention-component.js.map +1 -0
  56. package/dist/mentions/mention-component.mjs +60 -0
  57. package/dist/mentions/mention-component.mjs.map +1 -0
  58. package/dist/mentions/mention-node.js +105 -0
  59. package/dist/mentions/mention-node.js.map +1 -0
  60. package/dist/mentions/mention-node.mjs +84 -0
  61. package/dist/mentions/mention-node.mjs.map +1 -0
  62. package/dist/mentions/mention-plugin.js +291 -0
  63. package/dist/mentions/mention-plugin.js.map +1 -0
  64. package/dist/mentions/mention-plugin.mjs +284 -0
  65. package/dist/mentions/mention-plugin.mjs.map +1 -0
  66. package/dist/mentions/suggestions.js +161 -0
  67. package/dist/mentions/suggestions.js.map +1 -0
  68. package/dist/mentions/suggestions.mjs +158 -0
  69. package/dist/mentions/suggestions.mjs.map +1 -0
  70. package/dist/mentions/user.js +21 -0
  71. package/dist/mentions/user.js.map +1 -0
  72. package/dist/mentions/user.mjs +19 -0
  73. package/dist/mentions/user.mjs.map +1 -0
  74. package/dist/version.js +10 -0
  75. package/dist/version.js.map +1 -0
  76. package/dist/version.mjs +6 -0
  77. package/dist/version.mjs.map +1 -0
  78. package/package.json +102 -0
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
4
+ var selection = require('@lexical/selection');
5
+ var lexical = require('lexical');
6
+ var React = require('react');
7
+ var reactDom = require('react-dom');
8
+ var index_js = require('use-sync-external-store/shim/index.js');
9
+
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
28
+
29
+ function ActiveSelection({ styles }) {
30
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
31
+ const selection = useSelection();
32
+ if (selection === null)
33
+ return null;
34
+ const info = editor.getEditorState().read(() => {
35
+ return {
36
+ anchor: {
37
+ node: selection.anchor.getNode(),
38
+ offset: selection.anchor.offset
39
+ },
40
+ focus: {
41
+ node: selection.focus.getNode(),
42
+ offset: selection.focus.offset
43
+ }
44
+ };
45
+ });
46
+ const root = editor.getRootElement();
47
+ if (root === null)
48
+ return null;
49
+ const rootContainer = root.parentElement;
50
+ if (rootContainer === null)
51
+ return null;
52
+ return reactDom.createPortal(
53
+ /* @__PURE__ */ React__namespace.createElement(SelectionRects, {
54
+ selection: info,
55
+ styles
56
+ }),
57
+ rootContainer
58
+ );
59
+ }
60
+ function SelectionRects({
61
+ selection: selection$1,
62
+ styles = {}
63
+ }) {
64
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
65
+ const divRef = React.useRef(null);
66
+ React.useLayoutEffect(() => {
67
+ const container = divRef.current;
68
+ if (container === null)
69
+ return;
70
+ function drawSelectionRects() {
71
+ if (container === null)
72
+ return;
73
+ while (container.firstChild) {
74
+ container.removeChild(container.firstChild);
75
+ }
76
+ const range = selection.createDOMRange(
77
+ editor,
78
+ selection$1.anchor.node,
79
+ selection$1.anchor.offset,
80
+ selection$1.focus.node,
81
+ selection$1.focus.offset
82
+ );
83
+ if (range === null)
84
+ return;
85
+ const rects = selection.createRectsFromDOMRange(editor, range);
86
+ for (const rect of rects) {
87
+ const div = document.createElement("div");
88
+ Object.assign(div.style, {
89
+ backgroundColor: "rgba(255, 212, 0, 0.14)",
90
+ ...styles,
91
+ position: "absolute",
92
+ top: `${rect.top - container.getBoundingClientRect().top}px`,
93
+ left: `${rect.left - container.getBoundingClientRect().left}px`,
94
+ width: `${rect.width}px`,
95
+ height: `${rect.height}px`,
96
+ pointerEvents: "none"
97
+ });
98
+ container.appendChild(div);
99
+ }
100
+ }
101
+ const observer = new ResizeObserver(drawSelectionRects);
102
+ observer.observe(container);
103
+ const unsubscribeFromUpdates = editor.registerUpdateListener(drawSelectionRects);
104
+ return () => {
105
+ observer.disconnect();
106
+ unsubscribeFromUpdates();
107
+ };
108
+ }, [selection$1, editor, styles]);
109
+ return /* @__PURE__ */ React__namespace.createElement("div", {
110
+ ref: divRef,
111
+ style: {
112
+ position: "absolute",
113
+ top: 0,
114
+ left: 0,
115
+ width: "100%",
116
+ height: "100%",
117
+ pointerEvents: "none"
118
+ }
119
+ });
120
+ }
121
+ function useSelection() {
122
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
123
+ const subscribe = React.useCallback(
124
+ (onStoreChange) => {
125
+ return editor.registerUpdateListener(onStoreChange);
126
+ },
127
+ [editor]
128
+ );
129
+ const getSnapshot = React.useCallback(() => {
130
+ return editor.getEditorState().read(() => {
131
+ const selection = lexical.$getSelection();
132
+ if (!lexical.$isRangeSelection(selection))
133
+ return null;
134
+ if (selection.isCollapsed())
135
+ return null;
136
+ return selection;
137
+ });
138
+ }, [editor]);
139
+ return index_js.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
140
+ }
141
+
142
+ exports.ActiveSelection = ActiveSelection;
143
+ //# sourceMappingURL=active-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-selection.js","sources":["../src/active-selection.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { createDOMRange, createRectsFromDOMRange } from \"@lexical/selection\";\nimport type { LexicalNode, RangeSelection } from \"lexical\";\nimport { $getSelection, $isRangeSelection } from \"lexical\";\nimport * as React from \"react\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\ninterface ActiveSelectionProps {\n styles?: Partial<CSSStyleDeclaration>;\n}\n\nexport function ActiveSelection({ styles }: ActiveSelectionProps) {\n const [editor] = useLexicalComposerContext();\n const selection = useSelection();\n if (selection === null) return null;\n\n const info = editor.getEditorState().read(() => {\n return {\n anchor: {\n node: selection.anchor.getNode(),\n offset: selection.anchor.offset,\n },\n focus: {\n node: selection.focus.getNode(),\n offset: selection.focus.offset,\n },\n };\n });\n\n const root = editor.getRootElement();\n if (root === null) return null;\n\n const rootContainer = root.parentElement;\n if (rootContainer === null) return null;\n\n return createPortal(\n <SelectionRects selection={info} styles={styles} />,\n rootContainer\n );\n}\n\nfunction SelectionRects({\n selection,\n styles = {},\n}: {\n selection: SelectionInfo;\n styles?: Partial<CSSStyleDeclaration>;\n}) {\n const [editor] = useLexicalComposerContext();\n\n const divRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const container = divRef.current;\n if (container === null) return;\n\n function drawSelectionRects() {\n if (container === null) return;\n\n // Remove all existing children of the container\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const range = createDOMRange(\n editor,\n selection.anchor.node,\n selection.anchor.offset,\n selection.focus.node,\n selection.focus.offset\n );\n\n if (range === null) return;\n const rects = createRectsFromDOMRange(editor, range);\n\n for (const rect of rects) {\n const div = document.createElement(\"div\");\n\n Object.assign(div.style, {\n backgroundColor: \"rgba(255, 212, 0, 0.14)\",\n ...styles,\n position: \"absolute\",\n top: `${rect.top - container.getBoundingClientRect().top}px`,\n left: `${rect.left - container.getBoundingClientRect().left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n pointerEvents: \"none\",\n });\n\n container.appendChild(div);\n }\n }\n\n // Observe resizes of the container element to redraw the selection\n const observer = new ResizeObserver(drawSelectionRects);\n\n observer.observe(container);\n\n // Listen to updates in the editor to redraw the selection\n const unsubscribeFromUpdates =\n editor.registerUpdateListener(drawSelectionRects);\n\n return () => {\n observer.disconnect();\n unsubscribeFromUpdates();\n };\n }, [selection, editor, styles]);\n\n return (\n <div\n ref={divRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n }}\n />\n );\n}\n\ntype SelectionInfo = {\n anchor: {\n node: LexicalNode;\n offset: number;\n };\n focus: {\n node: LexicalNode;\n offset: number;\n };\n};\n\nfunction useSelection(): RangeSelection | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerUpdateListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getEditorState().read(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return null;\n\n if (selection.isCollapsed()) return null;\n\n return selection;\n });\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":["useLexicalComposerContext","createPortal","React","selection","useRef","useLayoutEffect","createDOMRange","createRectsFromDOMRange","useCallback","$getSelection","$isRangeSelection","useSyncExternalStore"],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
2
+ import { createDOMRange, createRectsFromDOMRange } from '@lexical/selection';
3
+ import { $getSelection, $isRangeSelection } from 'lexical';
4
+ import * as React from 'react';
5
+ import { useRef, useLayoutEffect, useCallback } from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js';
8
+
9
+ function ActiveSelection({ styles }) {
10
+ const [editor] = useLexicalComposerContext();
11
+ const selection = useSelection();
12
+ if (selection === null)
13
+ return null;
14
+ const info = editor.getEditorState().read(() => {
15
+ return {
16
+ anchor: {
17
+ node: selection.anchor.getNode(),
18
+ offset: selection.anchor.offset
19
+ },
20
+ focus: {
21
+ node: selection.focus.getNode(),
22
+ offset: selection.focus.offset
23
+ }
24
+ };
25
+ });
26
+ const root = editor.getRootElement();
27
+ if (root === null)
28
+ return null;
29
+ const rootContainer = root.parentElement;
30
+ if (rootContainer === null)
31
+ return null;
32
+ return createPortal(
33
+ /* @__PURE__ */ React.createElement(SelectionRects, {
34
+ selection: info,
35
+ styles
36
+ }),
37
+ rootContainer
38
+ );
39
+ }
40
+ function SelectionRects({
41
+ selection,
42
+ styles = {}
43
+ }) {
44
+ const [editor] = useLexicalComposerContext();
45
+ const divRef = useRef(null);
46
+ useLayoutEffect(() => {
47
+ const container = divRef.current;
48
+ if (container === null)
49
+ return;
50
+ function drawSelectionRects() {
51
+ if (container === null)
52
+ return;
53
+ while (container.firstChild) {
54
+ container.removeChild(container.firstChild);
55
+ }
56
+ const range = createDOMRange(
57
+ editor,
58
+ selection.anchor.node,
59
+ selection.anchor.offset,
60
+ selection.focus.node,
61
+ selection.focus.offset
62
+ );
63
+ if (range === null)
64
+ return;
65
+ const rects = createRectsFromDOMRange(editor, range);
66
+ for (const rect of rects) {
67
+ const div = document.createElement("div");
68
+ Object.assign(div.style, {
69
+ backgroundColor: "rgba(255, 212, 0, 0.14)",
70
+ ...styles,
71
+ position: "absolute",
72
+ top: `${rect.top - container.getBoundingClientRect().top}px`,
73
+ left: `${rect.left - container.getBoundingClientRect().left}px`,
74
+ width: `${rect.width}px`,
75
+ height: `${rect.height}px`,
76
+ pointerEvents: "none"
77
+ });
78
+ container.appendChild(div);
79
+ }
80
+ }
81
+ const observer = new ResizeObserver(drawSelectionRects);
82
+ observer.observe(container);
83
+ const unsubscribeFromUpdates = editor.registerUpdateListener(drawSelectionRects);
84
+ return () => {
85
+ observer.disconnect();
86
+ unsubscribeFromUpdates();
87
+ };
88
+ }, [selection, editor, styles]);
89
+ return /* @__PURE__ */ React.createElement("div", {
90
+ ref: divRef,
91
+ style: {
92
+ position: "absolute",
93
+ top: 0,
94
+ left: 0,
95
+ width: "100%",
96
+ height: "100%",
97
+ pointerEvents: "none"
98
+ }
99
+ });
100
+ }
101
+ function useSelection() {
102
+ const [editor] = useLexicalComposerContext();
103
+ const subscribe = useCallback(
104
+ (onStoreChange) => {
105
+ return editor.registerUpdateListener(onStoreChange);
106
+ },
107
+ [editor]
108
+ );
109
+ const getSnapshot = useCallback(() => {
110
+ return editor.getEditorState().read(() => {
111
+ const selection = $getSelection();
112
+ if (!$isRangeSelection(selection))
113
+ return null;
114
+ if (selection.isCollapsed())
115
+ return null;
116
+ return selection;
117
+ });
118
+ }, [editor]);
119
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
120
+ }
121
+
122
+ export { ActiveSelection };
123
+ //# sourceMappingURL=active-selection.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-selection.mjs","sources":["../src/active-selection.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { createDOMRange, createRectsFromDOMRange } from \"@lexical/selection\";\nimport type { LexicalNode, RangeSelection } from \"lexical\";\nimport { $getSelection, $isRangeSelection } from \"lexical\";\nimport * as React from \"react\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\n\ninterface ActiveSelectionProps {\n styles?: Partial<CSSStyleDeclaration>;\n}\n\nexport function ActiveSelection({ styles }: ActiveSelectionProps) {\n const [editor] = useLexicalComposerContext();\n const selection = useSelection();\n if (selection === null) return null;\n\n const info = editor.getEditorState().read(() => {\n return {\n anchor: {\n node: selection.anchor.getNode(),\n offset: selection.anchor.offset,\n },\n focus: {\n node: selection.focus.getNode(),\n offset: selection.focus.offset,\n },\n };\n });\n\n const root = editor.getRootElement();\n if (root === null) return null;\n\n const rootContainer = root.parentElement;\n if (rootContainer === null) return null;\n\n return createPortal(\n <SelectionRects selection={info} styles={styles} />,\n rootContainer\n );\n}\n\nfunction SelectionRects({\n selection,\n styles = {},\n}: {\n selection: SelectionInfo;\n styles?: Partial<CSSStyleDeclaration>;\n}) {\n const [editor] = useLexicalComposerContext();\n\n const divRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const container = divRef.current;\n if (container === null) return;\n\n function drawSelectionRects() {\n if (container === null) return;\n\n // Remove all existing children of the container\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n\n const range = createDOMRange(\n editor,\n selection.anchor.node,\n selection.anchor.offset,\n selection.focus.node,\n selection.focus.offset\n );\n\n if (range === null) return;\n const rects = createRectsFromDOMRange(editor, range);\n\n for (const rect of rects) {\n const div = document.createElement(\"div\");\n\n Object.assign(div.style, {\n backgroundColor: \"rgba(255, 212, 0, 0.14)\",\n ...styles,\n position: \"absolute\",\n top: `${rect.top - container.getBoundingClientRect().top}px`,\n left: `${rect.left - container.getBoundingClientRect().left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n pointerEvents: \"none\",\n });\n\n container.appendChild(div);\n }\n }\n\n // Observe resizes of the container element to redraw the selection\n const observer = new ResizeObserver(drawSelectionRects);\n\n observer.observe(container);\n\n // Listen to updates in the editor to redraw the selection\n const unsubscribeFromUpdates =\n editor.registerUpdateListener(drawSelectionRects);\n\n return () => {\n observer.disconnect();\n unsubscribeFromUpdates();\n };\n }, [selection, editor, styles]);\n\n return (\n <div\n ref={divRef}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n }}\n />\n );\n}\n\ntype SelectionInfo = {\n anchor: {\n node: LexicalNode;\n offset: number;\n };\n focus: {\n node: LexicalNode;\n offset: number;\n };\n};\n\nfunction useSelection(): RangeSelection | null {\n const [editor] = useLexicalComposerContext();\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return editor.registerUpdateListener(onStoreChange);\n },\n [editor]\n );\n\n const getSnapshot = useCallback(() => {\n return editor.getEditorState().read(() => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) return null;\n\n if (selection.isCollapsed()) return null;\n\n return selection;\n });\n }, [editor]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var react = require('@liveblocks/react');
4
+ var reactComments = require('@liveblocks/react-comments');
5
+ var React = require('react');
6
+
7
+ const ThreadPanel = () => {
8
+ const { useThreads } = react.useRoomContextBundle();
9
+ const { threads } = useThreads();
10
+ if (!threads || threads.length === 0) {
11
+ return /* @__PURE__ */ React.createElement("div", {
12
+ className: "lb-lexical-threads-empty"
13
+ }, "No threads yet");
14
+ }
15
+ return /* @__PURE__ */ React.createElement("div", {
16
+ className: "lb-lexical-threads"
17
+ }, threads.map((thread) => {
18
+ return /* @__PURE__ */ React.createElement(reactComments.Thread, {
19
+ key: thread.id,
20
+ thread
21
+ });
22
+ }));
23
+ };
24
+
25
+ exports.ThreadPanel = ThreadPanel;
26
+ //# sourceMappingURL=ThreadPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadPanel.js","sources":["../../src/comments/ThreadPanel.tsx"],"sourcesContent":["\nimport { useRoomContextBundle } from \"@liveblocks/react\";\nimport { Thread } from \"@liveblocks/react-comments\";\nimport React from \"react\";\n\nconst ThreadPanel = () => {\n const { useThreads } = useRoomContextBundle();\n const { threads } = useThreads();\n\n if (!threads || threads.length === 0) {\n return <div className=\"lb-lexical-threads-empty\">No threads yet</div>;\n }\n\n return (\n <div className=\"lb-lexical-threads\">\n {threads.map((thread) => {\n return <Thread key={thread.id} thread={thread} />;\n })}\n </div>\n );\n}\n\nexport { ThreadPanel }"],"names":["useRoomContextBundle","Thread"],"mappings":";;;;;;AAKA,MAAM,cAAc,MAAM;AACxB,EAAM,MAAA,EAAE,UAAW,EAAA,GAAIA,0BAAqB,EAAA,CAAA;AAC5C,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,UAAW,EAAA,CAAA;AAE/B,EAAA,IAAI,CAAC,OAAA,IAAW,OAAQ,CAAA,MAAA,KAAW,CAAG,EAAA;AACpC,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,MAAI,SAAU,EAAA,0BAAA;AAAA,KAAA,EAA2B,gBAAc,CAAA,CAAA;AAAA,GACjE;AAEA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAI,SAAU,EAAA,oBAAA;AAAA,GACZ,EAAA,OAAA,CAAQ,GAAI,CAAA,CAAC,MAAW,KAAA;AACvB,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAAC,oBAAA,EAAA;AAAA,MAAO,KAAK,MAAO,CAAA,EAAA;AAAA,MAAI,MAAA;AAAA,KAAgB,CAAA,CAAA;AAAA,GAChD,CACH,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,24 @@
1
+ import { useRoomContextBundle } from '@liveblocks/react';
2
+ import { Thread } from '@liveblocks/react-comments';
3
+ import React__default from 'react';
4
+
5
+ const ThreadPanel = () => {
6
+ const { useThreads } = useRoomContextBundle();
7
+ const { threads } = useThreads();
8
+ if (!threads || threads.length === 0) {
9
+ return /* @__PURE__ */ React__default.createElement("div", {
10
+ className: "lb-lexical-threads-empty"
11
+ }, "No threads yet");
12
+ }
13
+ return /* @__PURE__ */ React__default.createElement("div", {
14
+ className: "lb-lexical-threads"
15
+ }, threads.map((thread) => {
16
+ return /* @__PURE__ */ React__default.createElement(Thread, {
17
+ key: thread.id,
18
+ thread
19
+ });
20
+ }));
21
+ };
22
+
23
+ export { ThreadPanel };
24
+ //# sourceMappingURL=ThreadPanel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThreadPanel.mjs","sources":["../../src/comments/ThreadPanel.tsx"],"sourcesContent":["\nimport { useRoomContextBundle } from \"@liveblocks/react\";\nimport { Thread } from \"@liveblocks/react-comments\";\nimport React from \"react\";\n\nconst ThreadPanel = () => {\n const { useThreads } = useRoomContextBundle();\n const { threads } = useThreads();\n\n if (!threads || threads.length === 0) {\n return <div className=\"lb-lexical-threads-empty\">No threads yet</div>;\n }\n\n return (\n <div className=\"lb-lexical-threads\">\n {threads.map((thread) => {\n return <Thread key={thread.id} thread={thread} />;\n })}\n </div>\n );\n}\n\nexport { ThreadPanel }"],"names":["React"],"mappings":";;;;AAKA,MAAM,cAAc,MAAM;AACxB,EAAM,MAAA,EAAE,UAAW,EAAA,GAAI,oBAAqB,EAAA,CAAA;AAC5C,EAAM,MAAA,EAAE,OAAQ,EAAA,GAAI,UAAW,EAAA,CAAA;AAE/B,EAAA,IAAI,CAAC,OAAA,IAAW,OAAQ,CAAA,MAAA,KAAW,CAAG,EAAA;AACpC,IAAA,uBAAQA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,MAAI,SAAU,EAAA,0BAAA;AAAA,KAAA,EAA2B,gBAAc,CAAA,CAAA;AAAA,GACjE;AAEA,EAAA,uBACGA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAI,SAAU,EAAA,oBAAA;AAAA,GACZ,EAAA,OAAA,CAAQ,GAAI,CAAA,CAAC,MAAW,KAAA;AACvB,IAAA,uBAAQA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,MAAO,KAAK,MAAO,CAAA,EAAA;AAAA,MAAI,MAAA;AAAA,KAAgB,CAAA,CAAA;AAAA,GAChD,CACH,CAAA,CAAA;AAEJ;;;;"}
@@ -0,0 +1,322 @@
1
+ 'use strict';
2
+
3
+ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
4
+ var utils = require('@lexical/utils');
5
+ var core = require('@liveblocks/core');
6
+ var react = require('@liveblocks/react');
7
+ var lexical = require('lexical');
8
+ var React = require('react');
9
+ var withSelector_js = require('use-sync-external-store/shim/with-selector.js');
10
+ var activeSelection = require('../active-selection.js');
11
+ var getThreadMarkIds = require('./get-thread-mark-ids.js');
12
+ var threadMarkNode = require('./thread-mark-node.js');
13
+ var unwrapThreadMarkNode = require('./unwrap-thread-mark-node.js');
14
+ var wrapSelectionInThreadMarkNode = require('./wrap-selection-in-thread-mark-node.js');
15
+
16
+ function _interopNamespaceDefault(e) {
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
34
+
35
+ const ShowFloatingComposerContext = React__namespace.createContext(null);
36
+ const ShowFloatingComposerProvider = ({ children }) => {
37
+ const [showFloatingComposer, setShowFloatingComposer] = React.useState(false);
38
+ return /* @__PURE__ */ React__namespace.createElement(ShowFloatingComposerContext.Provider, {
39
+ value: {
40
+ setShowFloatingComposer,
41
+ showFloatingComposer
42
+ }
43
+ }, children);
44
+ };
45
+ function useCreateThread() {
46
+ const context = React__namespace.useContext(ShowFloatingComposerContext);
47
+ if (context === null) {
48
+ throw new Error(
49
+ "useCreateThread must be used within a LiveblocksPluginProvider with comments enabled"
50
+ );
51
+ }
52
+ return () => {
53
+ context.setShowFloatingComposer(true);
54
+ };
55
+ }
56
+ function useShowFloatingComposer() {
57
+ const context = React__namespace.useContext(ShowFloatingComposerContext);
58
+ if (context === null) {
59
+ throw new Error(
60
+ "useShowFloatingComposer must be used within a LiveblocksPluginProvider with comments enabled"
61
+ );
62
+ }
63
+ return context.showFloatingComposer;
64
+ }
65
+ function useHideFloatingComposer() {
66
+ const context = React__namespace.useContext(ShowFloatingComposerContext);
67
+ if (context === null) {
68
+ throw new Error(
69
+ "useHideFloatingComposer must be used within a LiveblocksPluginProvider with comments enabled"
70
+ );
71
+ }
72
+ return () => {
73
+ context.setShowFloatingComposer(false);
74
+ };
75
+ }
76
+ function CommentPluginProvider({ children }) {
77
+ const [editor, context] = LexicalComposerContext.useLexicalComposerContext();
78
+ const [threadToNodes, setThreadToNodes] = React.useState(
79
+ /* @__PURE__ */ new Map()
80
+ );
81
+ const [activeThreads, setActiveThreads] = React.useState([]);
82
+ const [showActiveSelection, setShowActiveSelection] = React.useState(false);
83
+ const client = react.useClient();
84
+ const {
85
+ useRoom,
86
+ [core.kInternal]: {
87
+ useCommentsErrorListener,
88
+ ThreadCreateCallbackProvider,
89
+ ThreadDeleteCallbackProvider,
90
+ ComposerFocusCallbackProvider,
91
+ IsThreadActiveCallbackProvider
92
+ }
93
+ } = react.useRoomContextBundle();
94
+ const room = useRoom();
95
+ React.useEffect(() => {
96
+ if (!editor.hasNodes([threadMarkNode.ThreadMarkNode])) {
97
+ throw new Error(
98
+ "CommentPluginProvider: ThreadMarkNode not registered on editor"
99
+ );
100
+ }
101
+ }, [editor]);
102
+ const isThreadActive = React.useCallback(
103
+ (threadId) => {
104
+ return activeThreads.includes(threadId);
105
+ },
106
+ [activeThreads]
107
+ );
108
+ const handleThreadCreate = React.useCallback(
109
+ (threadId) => {
110
+ editor.update(() => {
111
+ const selection = lexical.$getSelection();
112
+ if (!lexical.$isRangeSelection(selection))
113
+ return;
114
+ if (selection.isCollapsed())
115
+ return;
116
+ const isBackward = selection.isBackward();
117
+ wrapSelectionInThreadMarkNode(selection, isBackward, threadId);
118
+ lexical.$setSelection(null);
119
+ });
120
+ },
121
+ [editor]
122
+ );
123
+ const handleThreadDelete = React.useCallback(
124
+ (threadId) => {
125
+ editor.update(() => {
126
+ const keys = threadToNodes.get(threadId);
127
+ if (keys === void 0)
128
+ return;
129
+ for (const key of keys) {
130
+ const node = lexical.$getNodeByKey(key);
131
+ if (!threadMarkNode.$isThreadMarkNode(node))
132
+ continue;
133
+ node.deleteID(threadId);
134
+ if (node.getIDs().length === 0) {
135
+ unwrapThreadMarkNode(node);
136
+ }
137
+ }
138
+ });
139
+ },
140
+ [editor, threadToNodes]
141
+ );
142
+ useCommentsErrorListener((error) => {
143
+ if (error instanceof react.CreateThreadError) {
144
+ handleThreadDelete(error.context.threadId);
145
+ }
146
+ });
147
+ const store = client[core.kInternal].cacheStore;
148
+ const threads = withSelector_js.useSyncExternalStoreWithSelector(
149
+ store.subscribe,
150
+ store.get,
151
+ store.get,
152
+ React.useCallback(
153
+ () => client[core.kInternal].comments.selectedThreads(room.id, store.get(), {}),
154
+ [client, room.id, store]
155
+ )
156
+ );
157
+ React.useEffect(() => {
158
+ function getThreadMarkElements() {
159
+ const activeElements = /* @__PURE__ */ new Set();
160
+ for (const thread of threads) {
161
+ const keys = threadToNodes.get(thread.id);
162
+ if (keys === void 0)
163
+ continue;
164
+ for (const key of keys) {
165
+ const element = editor.getElementByKey(key);
166
+ if (element === null)
167
+ continue;
168
+ activeElements.add(element);
169
+ }
170
+ }
171
+ return activeElements;
172
+ }
173
+ const elements = getThreadMarkElements();
174
+ const theme = context.getTheme();
175
+ if (theme === null || theme === void 0)
176
+ return;
177
+ elements.forEach((element) => {
178
+ utils.addClassNamesToElement(element, theme.threadMark);
179
+ });
180
+ return () => {
181
+ elements.forEach((element) => {
182
+ utils.removeClassNamesFromElement(element, theme.threadMark);
183
+ });
184
+ };
185
+ }, [context, editor, threadToNodes, threads]);
186
+ React.useEffect(() => {
187
+ function onMutation(mutations) {
188
+ const state = editor.getEditorState();
189
+ setThreadToNodes((prev) => {
190
+ const updatedMap = new Map(prev);
191
+ state.read(() => {
192
+ for (const [key, mutation] of mutations) {
193
+ if (mutation === "destroyed") {
194
+ for (const [, nodes] of updatedMap) {
195
+ nodes.delete(key);
196
+ }
197
+ } else if (mutation === "created" || mutation === "updated") {
198
+ const node = lexical.$getNodeByKey(key);
199
+ if (!threadMarkNode.$isThreadMarkNode(node))
200
+ continue;
201
+ const threadIds = node.getIDs();
202
+ for (const id of threadIds) {
203
+ const keys = updatedMap.get(id) ?? /* @__PURE__ */ new Set();
204
+ keys.add(key);
205
+ updatedMap.set(id, keys);
206
+ }
207
+ }
208
+ }
209
+ });
210
+ return updatedMap;
211
+ });
212
+ }
213
+ return editor.registerMutationListener(threadMarkNode.ThreadMarkNode, onMutation);
214
+ }, [editor]);
215
+ React.useEffect(() => {
216
+ const selectedThreads = client[core.kInternal].comments.selectedThreads;
217
+ function $getThreadIds(selection) {
218
+ if (selection === null)
219
+ return [];
220
+ if (!lexical.$isRangeSelection(selection))
221
+ return [];
222
+ const anchor = selection.anchor.getNode();
223
+ if (!lexical.$isTextNode(anchor))
224
+ return [];
225
+ return getThreadMarkIds(anchor, selection.anchor.offset) ?? [];
226
+ }
227
+ function $onStateRead() {
228
+ const selection = lexical.$getSelection();
229
+ const threadIds = $getThreadIds(selection).filter((id) => {
230
+ return selectedThreads(room.id, store.get(), {}).some(
231
+ (thread) => thread.id === id
232
+ );
233
+ });
234
+ setActiveThreads(threadIds);
235
+ }
236
+ const unsubscribeCache = store.subscribe(() => {
237
+ editor.getEditorState().read($onStateRead);
238
+ });
239
+ const unregisterUpdateListener = editor.registerUpdateListener(
240
+ ({ editorState: state }) => {
241
+ state.read($onStateRead);
242
+ }
243
+ );
244
+ return () => {
245
+ unregisterUpdateListener();
246
+ unsubscribeCache();
247
+ };
248
+ }, [editor, client, room.id, store]);
249
+ React.useEffect(() => {
250
+ function getActiveElements() {
251
+ const activeElements2 = /* @__PURE__ */ new Set();
252
+ for (const thread of activeThreads) {
253
+ const keys = threadToNodes.get(thread);
254
+ if (keys === void 0)
255
+ continue;
256
+ for (const key of keys) {
257
+ const element = editor.getElementByKey(key);
258
+ if (element === null)
259
+ continue;
260
+ activeElements2.add(element);
261
+ }
262
+ }
263
+ return activeElements2;
264
+ }
265
+ const activeElements = getActiveElements();
266
+ activeElements.forEach((element) => {
267
+ element.setAttribute("data-state", "active");
268
+ });
269
+ return () => {
270
+ activeElements.forEach((element) => {
271
+ element.removeAttribute("data-state");
272
+ });
273
+ };
274
+ }, [activeThreads, editor, threadToNodes]);
275
+ React.useEffect(() => {
276
+ return utils.registerNestedElementResolver(
277
+ editor,
278
+ threadMarkNode.ThreadMarkNode,
279
+ (from) => {
280
+ return threadMarkNode.$createThreadMarkNode(from.getIDs());
281
+ },
282
+ (from, to) => {
283
+ const ids = from.getIDs();
284
+ ids.forEach((id) => {
285
+ to.addID(id);
286
+ });
287
+ }
288
+ );
289
+ }, [editor]);
290
+ const handleComposerFocus = React.useCallback(
291
+ (commentId, threadId) => {
292
+ if (commentId === void 0 && threadId === void 0) {
293
+ setShowActiveSelection(true);
294
+ } else {
295
+ setShowActiveSelection(false);
296
+ }
297
+ },
298
+ []
299
+ );
300
+ React.useEffect(() => {
301
+ return editor.registerUpdateListener(({ editorState: state, tags }) => {
302
+ if (tags.has("collaboration"))
303
+ return;
304
+ state.read(() => setShowActiveSelection(false));
305
+ });
306
+ }, [editor]);
307
+ return /* @__PURE__ */ React__namespace.createElement(ShowFloatingComposerProvider, null, /* @__PURE__ */ React__namespace.createElement(ThreadCreateCallbackProvider, {
308
+ value: handleThreadCreate
309
+ }, /* @__PURE__ */ React__namespace.createElement(ThreadDeleteCallbackProvider, {
310
+ value: handleThreadDelete
311
+ }, /* @__PURE__ */ React__namespace.createElement(ComposerFocusCallbackProvider, {
312
+ value: handleComposerFocus
313
+ }, /* @__PURE__ */ React__namespace.createElement(IsThreadActiveCallbackProvider, {
314
+ value: isThreadActive
315
+ }, showActiveSelection && /* @__PURE__ */ React__namespace.createElement(activeSelection.ActiveSelection, null), children)))));
316
+ }
317
+
318
+ exports.CommentPluginProvider = CommentPluginProvider;
319
+ exports.useCreateThread = useCreateThread;
320
+ exports.useHideFloatingComposer = useHideFloatingComposer;
321
+ exports.useShowFloatingComposer = useShowFloatingComposer;
322
+ //# sourceMappingURL=comment-plugin-provider.js.map