@liveblocks/react-lexical 2.14.0-v2encoding → 2.15.0-debug1

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 (55) hide show
  1. package/dist/comments/anchored-threads.js +52 -50
  2. package/dist/comments/anchored-threads.js.map +1 -1
  3. package/dist/comments/anchored-threads.mjs +36 -34
  4. package/dist/comments/anchored-threads.mjs.map +1 -1
  5. package/dist/comments/comment-plugin-provider.js +46 -63
  6. package/dist/comments/comment-plugin-provider.js.map +1 -1
  7. package/dist/comments/comment-plugin-provider.mjs +29 -28
  8. package/dist/comments/comment-plugin-provider.mjs.map +1 -1
  9. package/dist/comments/floating-composer.js +66 -56
  10. package/dist/comments/floating-composer.js.map +1 -1
  11. package/dist/comments/floating-composer.mjs +54 -44
  12. package/dist/comments/floating-composer.mjs.map +1 -1
  13. package/dist/comments/floating-threads.js +29 -28
  14. package/dist/comments/floating-threads.js.map +1 -1
  15. package/dist/comments/floating-threads.mjs +16 -15
  16. package/dist/comments/floating-threads.mjs.map +1 -1
  17. package/dist/index.d.mts +8 -6
  18. package/dist/index.d.ts +8 -6
  19. package/dist/liveblocks-plugin-provider.js +46 -38
  20. package/dist/liveblocks-plugin-provider.js.map +1 -1
  21. package/dist/liveblocks-plugin-provider.mjs +28 -20
  22. package/dist/liveblocks-plugin-provider.mjs.map +1 -1
  23. package/dist/mentions/avatar.js +24 -17
  24. package/dist/mentions/avatar.js.map +1 -1
  25. package/dist/mentions/avatar.mjs +21 -14
  26. package/dist/mentions/avatar.mjs.map +1 -1
  27. package/dist/mentions/mention-component.js +9 -8
  28. package/dist/mentions/mention-component.js.map +1 -1
  29. package/dist/mentions/mention-component.mjs +6 -5
  30. package/dist/mentions/mention-component.mjs.map +1 -1
  31. package/dist/mentions/mention-node.js +10 -25
  32. package/dist/mentions/mention-node.js.map +1 -1
  33. package/dist/mentions/mention-node.mjs +10 -6
  34. package/dist/mentions/mention-node.mjs.map +1 -1
  35. package/dist/mentions/mention-plugin.js +42 -33
  36. package/dist/mentions/mention-plugin.js.map +1 -1
  37. package/dist/mentions/mention-plugin.mjs +36 -27
  38. package/dist/mentions/mention-plugin.mjs.map +1 -1
  39. package/dist/mentions/suggestions.js +34 -30
  40. package/dist/mentions/suggestions.js.map +1 -1
  41. package/dist/mentions/suggestions.mjs +16 -12
  42. package/dist/mentions/suggestions.mjs.map +1 -1
  43. package/dist/mentions/user.js +9 -7
  44. package/dist/mentions/user.js.map +1 -1
  45. package/dist/mentions/user.mjs +6 -4
  46. package/dist/mentions/user.mjs.map +1 -1
  47. package/dist/version-history/history-version-preview.js +77 -54
  48. package/dist/version-history/history-version-preview.js.map +1 -1
  49. package/dist/version-history/history-version-preview.mjs +70 -47
  50. package/dist/version-history/history-version-preview.mjs.map +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/version.js.map +1 -1
  53. package/dist/version.mjs +1 -1
  54. package/dist/version.mjs.map +1 -1
  55. package/package.json +8 -10
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
+ var jsxRuntime = require('react/jsx-runtime');
3
4
  var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
4
5
  var reactUi = require('@liveblocks/react-ui');
5
6
  var lexical = require('lexical');
6
- var React = require('react');
7
+ var react = require('react');
7
8
  var classnames = require('../classnames.js');
8
9
  var liveblocksPluginProvider = require('../liveblocks-plugin-provider.js');
9
10
  var commentPluginProvider = require('./comment-plugin-provider.js');
@@ -30,10 +31,10 @@ function AnchoredThreads({
30
31
  }) {
31
32
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
32
33
  const Thread = components?.Thread ?? reactUi.Thread;
33
- const containerRef = React.useRef(null);
34
+ const containerRef = react.useRef(null);
34
35
  const activeThreads = useActiveThreads();
35
36
  const nodes = useThreadToNodes();
36
- const getOrderedThreads = React.useCallback(() => {
37
+ const getOrderedThreads = react.useCallback(() => {
37
38
  return threads.filter((thread) => thread.resolved === false).map((thread) => {
38
39
  const keys = nodes.get(thread.id);
39
40
  if (keys === void 0 || keys.size === 0)
@@ -52,20 +53,20 @@ function AnchoredThreads({
52
53
  return compareNodes(a.element, b.element);
53
54
  });
54
55
  }, [editor, threads, nodes]);
55
- const orderedThreads = React.useMemo(getOrderedThreads, [getOrderedThreads]);
56
- const [elements, setElements] = React.useState(/* @__PURE__ */ new Map());
57
- const [positions, setPositions] = React.useState(/* @__PURE__ */ new Map());
58
- const onItemAdd = React.useCallback((id, el) => {
56
+ const orderedThreads = react.useMemo(getOrderedThreads, [getOrderedThreads]);
57
+ const [elements, setElements] = react.useState(/* @__PURE__ */ new Map());
58
+ const [positions, setPositions] = react.useState(/* @__PURE__ */ new Map());
59
+ const onItemAdd = react.useCallback((id, el) => {
59
60
  setElements((prev) => new Map(prev).set(id, el));
60
61
  }, []);
61
- const onItemRemove = React.useCallback((id) => {
62
+ const onItemRemove = react.useCallback((id) => {
62
63
  setElements((prev) => {
63
64
  const items = new Map(prev);
64
65
  items.delete(id);
65
66
  return items;
66
67
  });
67
68
  }, []);
68
- const handlePositionThreads = React.useCallback(() => {
69
+ const handlePositionThreads = react.useCallback(() => {
69
70
  const container = containerRef.current;
70
71
  if (container === null)
71
72
  return;
@@ -119,15 +120,15 @@ function AnchoredThreads({
119
120
  }
120
121
  setPositions(newPositions);
121
122
  }, [getOrderedThreads, activeThreads, elements]);
122
- React.useLayoutEffect(() => {
123
+ react.useLayoutEffect(() => {
123
124
  handlePositionThreads();
124
125
  }, [handlePositionThreads]);
125
- React.useEffect(() => {
126
+ react.useEffect(() => {
126
127
  return editor.registerUpdateListener(() => {
127
128
  handlePositionThreads();
128
129
  });
129
130
  }, [editor, handlePositionThreads]);
130
- React.useEffect(() => {
131
+ react.useEffect(() => {
131
132
  const observer = new ResizeObserver(handlePositionThreads);
132
133
  for (const element of elements.values()) {
133
134
  observer.observe(element);
@@ -135,7 +136,7 @@ function AnchoredThreads({
135
136
  return () => observer.disconnect();
136
137
  }, [elements, handlePositionThreads]);
137
138
  const root = liveblocksPluginProvider.useRootElement();
138
- React.useEffect(() => {
139
+ react.useEffect(() => {
139
140
  if (root === null)
140
141
  return;
141
142
  const observer = new ResizeObserver(handlePositionThreads);
@@ -144,37 +145,37 @@ function AnchoredThreads({
144
145
  }, [root, handlePositionThreads]);
145
146
  if (orderedThreads.length === 0)
146
147
  return null;
147
- return /* @__PURE__ */ React.createElement("div", {
148
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
148
149
  ...props,
149
150
  className: classnames.classNames(className, "lb-root lb-lexical-anchored-threads"),
150
151
  ref: containerRef,
151
152
  style: {
152
153
  position: "relative",
153
154
  ...style
154
- }
155
- }, orderedThreads.map(({ thread, element }) => {
156
- const rect = element.getBoundingClientRect();
157
- const offset = root !== null ? root.getBoundingClientRect().top : 0;
158
- let top = rect.top - offset;
159
- if (positions.has(thread.id)) {
160
- top = positions.get(thread.id);
161
- }
162
- const isActive = activeThreads.includes(thread.id);
163
- return /* @__PURE__ */ React.createElement(ThreadWrapper, {
164
- key: thread.id,
165
- Thread,
166
- thread,
167
- onItemAdd,
168
- onItemRemove,
169
- style: {
170
- position: "absolute",
171
- transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,
172
- insetInlineStart: 0,
173
- inlineSize: "100%",
174
- paddingBlockEnd: GAP
155
+ },
156
+ children: orderedThreads.map(({ thread, element }) => {
157
+ const rect = element.getBoundingClientRect();
158
+ const offset = root !== null ? root.getBoundingClientRect().top : 0;
159
+ let top = rect.top - offset;
160
+ if (positions.has(thread.id)) {
161
+ top = positions.get(thread.id);
175
162
  }
176
- });
177
- }));
163
+ const isActive = activeThreads.includes(thread.id);
164
+ return /* @__PURE__ */ jsxRuntime.jsx(ThreadWrapper, {
165
+ Thread,
166
+ thread,
167
+ onItemAdd,
168
+ onItemRemove,
169
+ style: {
170
+ position: "absolute",
171
+ transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,
172
+ insetInlineStart: 0,
173
+ inlineSize: "100%",
174
+ paddingBlockEnd: GAP
175
+ }
176
+ }, thread.id);
177
+ })
178
+ });
178
179
  }
179
180
  function ThreadWrapper({
180
181
  onItemAdd,
@@ -186,7 +187,7 @@ function ThreadWrapper({
186
187
  }) {
187
188
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
188
189
  const nodes = useThreadToNodes();
189
- const divRef = React.useRef(null);
190
+ const divRef = react.useRef(null);
190
191
  const activeThreads = useActiveThreads();
191
192
  const isActive = activeThreads.includes(thread.id);
192
193
  function handleThreadClick() {
@@ -203,7 +204,7 @@ function ThreadWrapper({
203
204
  node.selectStart();
204
205
  });
205
206
  }
206
- React.useLayoutEffect(() => {
207
+ react.useLayoutEffect(() => {
207
208
  const el = divRef.current;
208
209
  if (el === null)
209
210
  return;
@@ -212,23 +213,24 @@ function ThreadWrapper({
212
213
  onItemRemove(thread.id);
213
214
  };
214
215
  }, [thread.id, onItemAdd, onItemRemove]);
215
- return /* @__PURE__ */ React.createElement("div", {
216
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
216
217
  ref: divRef,
217
218
  className: classnames.classNames(
218
219
  "lb-lexical-anchored-threads-thread-container",
219
220
  className
220
221
  ),
221
- ...props
222
- }, /* @__PURE__ */ React.createElement(Thread, {
223
- thread,
224
- "data-state": isActive ? "active" : "inactive",
225
- onClick: handleThreadClick,
226
- className: "lb-lexical-anchored-threads-thread",
227
- showComposer: isActive ? true : false
228
- }));
222
+ ...props,
223
+ children: /* @__PURE__ */ jsxRuntime.jsx(Thread, {
224
+ thread,
225
+ "data-state": isActive ? "active" : "inactive",
226
+ onClick: handleThreadClick,
227
+ className: "lb-lexical-anchored-threads-thread",
228
+ showComposer: isActive ? true : false
229
+ })
230
+ });
229
231
  }
230
232
  function useThreadToNodes() {
231
- const threadToNodes = React.useContext(commentPluginProvider.ThreadToNodesContext);
233
+ const threadToNodes = react.useContext(commentPluginProvider.ThreadToNodesContext);
232
234
  if (threadToNodes === null) {
233
235
  throw new Error(
234
236
  "AnchoredThreads component must be used within a LiveblocksPlugin component."
@@ -237,7 +239,7 @@ function useThreadToNodes() {
237
239
  return threadToNodes;
238
240
  }
239
241
  function useActiveThreads() {
240
- const activeThreads = React.useContext(commentPluginProvider.ActiveThreadsContext);
242
+ const activeThreads = react.useContext(commentPluginProvider.ActiveThreadsContext);
241
243
  if (activeThreads === null) {
242
244
  throw new Error(
243
245
  "AnchoredThreads component must be used within LiveblocksPlugin."
@@ -1 +1 @@
1
- {"version":3,"file":"anchored-threads.js","sources":["../../src/comments/anchored-threads.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { $getNodeByKey } from \"lexical\";\nimport type { ComponentPropsWithoutRef, ComponentType } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { useRootElement } from \"../liveblocks-plugin-provider\";\nimport {\n ActiveThreadsContext,\n type ThreadToNodesMap,\n} from \"./comment-plugin-provider\";\nimport { ThreadToNodesContext } from \"./comment-plugin-provider\";\nimport { $isThreadMarkNode } from \"./thread-mark-node\";\n\nconst DEFAULT_GAP = 20;\nconst DEFAULT_ACTIVE_THREAD_OFFSET = -12;\n\nconst GAP = `var(--lb-lexical-anchored-threads-gap, ${DEFAULT_GAP}px)`;\nconst ACTIVE_THREAD_OFFSET = `var(--lb-lexical-anchored-threads-active-thread-offset, ${DEFAULT_ACTIVE_THREAD_OFFSET}px)`;\n\ntype AnchoredThreadsComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface AnchoredThreadsProps<M extends BaseMetadata = DM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<AnchoredThreadsComponents>;\n}\n\n/**\n * Compares two nodes based on their position in the DOM.\n * Returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n * @param a The first node to compare\n * @param b The second node to compare\n * @returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n */\nexport function compareNodes(a: Node, b: Node): number {\n // Calculate the position of node 'b' relative to node 'a'\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nexport function AnchoredThreads({\n threads,\n components,\n className,\n style,\n ...props\n}: AnchoredThreadsProps) {\n const [editor] = useLexicalComposerContext();\n const Thread = components?.Thread ?? DefaultThread;\n const containerRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const nodes = useThreadToNodes(); // A map of thread ids to a set of thread mark nodes associated with the thread\n\n const getOrderedThreads = useCallback(() => {\n return threads\n .filter((thread) => thread.resolved === false)\n .map((thread) => {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return null;\n\n const elements = Array.from(keys.values())\n .map((key) => editor.getElementByKey(key))\n .filter(Boolean) as HTMLElement[];\n if (elements.length === 0) return null;\n\n const element = elements.sort(compareNodes)[0];\n return {\n thread,\n element,\n };\n })\n .filter(\n (entry): entry is { thread: ThreadData; element: HTMLElement } =>\n entry !== null\n )\n .sort((a, b) => {\n return compareNodes(a.element, b.element);\n });\n }, [editor, threads, nodes]);\n\n // Sort threads by the position of the first element associated with the thread in the document (top to bottom, left to right)\n const orderedThreads = useMemo(getOrderedThreads, [getOrderedThreads]);\n\n const [elements, setElements] = useState<Map<string, HTMLElement>>(new Map());\n\n const [positions, setPositions] = useState<Map<string, number>>(new Map()); // A map of thread ids to their 'top' position in the document\n\n const onItemAdd = useCallback((id: string, el: HTMLElement) => {\n setElements((prev) => new Map(prev).set(id, el));\n }, []);\n\n const onItemRemove = useCallback((id: string) => {\n setElements((prev) => {\n const items = new Map(prev);\n items.delete(id);\n return items;\n });\n }, []);\n\n const handlePositionThreads = useCallback(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const orderedThreads = getOrderedThreads();\n\n // Returns an array of threads that should be positioned in ascending order - this includes threads that are active and threads that should come after the active threads\n function getAscendingThreads() {\n // If there are no active threads, all threads are ordered in ascending manner.\n if (activeThreads.length === 0) return orderedThreads;\n\n // Filter threads that are active\n const active = orderedThreads.filter(({ thread }) =>\n activeThreads.includes(thread.id)\n );\n\n // Filter threads that should come after the active threads\n const after = orderedThreads.filter(({ thread, element }) => {\n if (activeThreads.includes(thread.id)) return false;\n\n // Check if the current thread comes after any of the active threads\n const isAfter = active.some(({ element: activeElement }) => {\n return compareNodes(activeElement, element) === -1;\n });\n\n return isAfter;\n });\n\n return active.concat(after);\n }\n\n const ascending = getAscendingThreads();\n\n // Filter threads that are neither active nor come after active threads (i.e. 'other' threads)\n const descending = orderedThreads.filter(\n (entry) => !ascending.includes(entry)\n );\n\n const newPositions = new Map<string, number>();\n\n // Iterate over each thread and calculate its new position by taking into account the position of the previously positioned threads\n for (const { thread, element } of ascending) {\n const rect = element.getBoundingClientRect();\n let top = rect.top - container.getBoundingClientRect().top;\n\n for (const [id, position] of newPositions) {\n // Retrieve the element associated with the thread\n const el = elements.get(id);\n if (el === undefined) continue;\n\n if (\n top >= position &&\n top <= position + el.getBoundingClientRect().height\n ) {\n top = position + el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n for (const { thread, element } of descending.reverse()) {\n const rect = element.getBoundingClientRect();\n // Retrieve the element associated with the current thread\n const el = elements.get(thread.id);\n if (el === undefined) continue;\n\n let top = rect.top - container.getBoundingClientRect().top;\n for (const [, position] of newPositions) {\n if (top >= position - el.getBoundingClientRect().height) {\n top = position - el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n setPositions(newPositions);\n }, [getOrderedThreads, activeThreads, elements]);\n\n useLayoutEffect(() => {\n handlePositionThreads();\n }, [handlePositionThreads]);\n\n useEffect(() => {\n return editor.registerUpdateListener(() => {\n handlePositionThreads();\n });\n }, [editor, handlePositionThreads]);\n\n useEffect(() => {\n const observer = new ResizeObserver(handlePositionThreads);\n for (const element of elements.values()) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [elements, handlePositionThreads]);\n\n const root = useRootElement();\n\n useEffect(() => {\n if (root === null) return;\n const observer = new ResizeObserver(handlePositionThreads);\n\n observer.observe(root);\n return () => observer.disconnect();\n }, [root, handlePositionThreads]);\n\n if (orderedThreads.length === 0) return null;\n\n return (\n <div\n {...props}\n className={classNames(className, \"lb-root lb-lexical-anchored-threads\")}\n ref={containerRef}\n style={{\n position: \"relative\",\n ...style,\n }}\n >\n {orderedThreads.map(({ thread, element }) => {\n const rect = element.getBoundingClientRect();\n const offset = root !== null ? root.getBoundingClientRect().top : 0;\n\n let top = rect.top - offset;\n\n if (positions.has(thread.id)) {\n top = positions.get(thread.id)!;\n }\n\n const isActive = activeThreads.includes(thread.id);\n\n return (\n <ThreadWrapper\n key={thread.id}\n Thread={Thread}\n thread={thread}\n onItemAdd={onItemAdd}\n onItemRemove={onItemRemove}\n style={{\n position: \"absolute\",\n transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,\n insetInlineStart: 0,\n inlineSize: \"100%\",\n paddingBlockEnd: GAP,\n }}\n />\n );\n })}\n </div>\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n Thread: ComponentType<ThreadProps>;\n onItemAdd: (id: string, el: HTMLElement) => void;\n onItemRemove: (id: string) => void;\n}\n\nfunction ThreadWrapper({\n onItemAdd,\n onItemRemove,\n thread,\n Thread,\n className,\n ...props\n}: ThreadWrapperProps) {\n const [editor] = useLexicalComposerContext();\n const nodes = useThreadToNodes();\n const divRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const isActive = activeThreads.includes(thread.id);\n\n function handleThreadClick() {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return;\n\n if (activeThreads.includes(thread.id)) return;\n\n editor.update(() => {\n const [key] = keys;\n const node = $getNodeByKey(key);\n if (!$isThreadMarkNode(node)) return;\n node.selectStart();\n });\n }\n\n useLayoutEffect(() => {\n const el = divRef.current;\n if (el === null) return;\n\n onItemAdd(thread.id, el);\n return () => {\n onItemRemove(thread.id);\n };\n }, [thread.id, onItemAdd, onItemRemove]);\n\n return (\n <div\n ref={divRef}\n className={classNames(\n \"lb-lexical-anchored-threads-thread-container\",\n className\n )}\n {...props}\n >\n <Thread\n thread={thread}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleThreadClick}\n className=\"lb-lexical-anchored-threads-thread\"\n showComposer={isActive ? true : false}\n />\n </div>\n );\n}\n\nfunction useThreadToNodes(): ThreadToNodesMap {\n const threadToNodes = useContext(ThreadToNodesContext);\n if (threadToNodes === null) {\n throw new Error(\n \"AnchoredThreads component must be used within a LiveblocksPlugin component.\"\n );\n }\n return threadToNodes;\n}\n\nfunction useActiveThreads() {\n const activeThreads = useContext(ActiveThreadsContext);\n if (activeThreads === null) {\n throw new Error(\n \"AnchoredThreads component must be used within LiveblocksPlugin.\"\n );\n }\n\n return activeThreads;\n}\n"],"names":["useLexicalComposerContext","DefaultThread","useRef","useCallback","elements","useMemo","useState","orderedThreads","useLayoutEffect","useEffect","useRootElement","classNames","$getNodeByKey","$isThreadMarkNode","useContext","ThreadToNodesContext","ActiveThreadsContext"],"mappings":"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"}
1
+ {"version":3,"file":"anchored-threads.js","sources":["../../src/comments/anchored-threads.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { $getNodeByKey } from \"lexical\";\nimport type { ComponentPropsWithoutRef, ComponentType } from \"react\";\nimport {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { useRootElement } from \"../liveblocks-plugin-provider\";\nimport {\n ActiveThreadsContext,\n type ThreadToNodesMap,\n} from \"./comment-plugin-provider\";\nimport { ThreadToNodesContext } from \"./comment-plugin-provider\";\nimport { $isThreadMarkNode } from \"./thread-mark-node\";\n\nconst DEFAULT_GAP = 20;\nconst DEFAULT_ACTIVE_THREAD_OFFSET = -12;\n\nconst GAP = `var(--lb-lexical-anchored-threads-gap, ${DEFAULT_GAP}px)`;\nconst ACTIVE_THREAD_OFFSET = `var(--lb-lexical-anchored-threads-active-thread-offset, ${DEFAULT_ACTIVE_THREAD_OFFSET}px)`;\n\ntype AnchoredThreadsComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface AnchoredThreadsProps<M extends BaseMetadata = DM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<AnchoredThreadsComponents>;\n}\n\n/**\n * Compares two nodes based on their position in the DOM.\n * Returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n * @param a The first node to compare\n * @param b The second node to compare\n * @returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n */\nexport function compareNodes(a: Node, b: Node): number {\n // Calculate the position of node 'b' relative to node 'a'\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nexport function AnchoredThreads({\n threads,\n components,\n className,\n style,\n ...props\n}: AnchoredThreadsProps) {\n const [editor] = useLexicalComposerContext();\n const Thread = components?.Thread ?? DefaultThread;\n const containerRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const nodes = useThreadToNodes(); // A map of thread ids to a set of thread mark nodes associated with the thread\n\n const getOrderedThreads = useCallback(() => {\n return threads\n .filter((thread) => thread.resolved === false)\n .map((thread) => {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return null;\n\n const elements = Array.from(keys.values())\n .map((key) => editor.getElementByKey(key))\n .filter(Boolean) as HTMLElement[];\n if (elements.length === 0) return null;\n\n const element = elements.sort(compareNodes)[0];\n return {\n thread,\n element,\n };\n })\n .filter(\n (entry): entry is { thread: ThreadData; element: HTMLElement } =>\n entry !== null\n )\n .sort((a, b) => {\n return compareNodes(a.element, b.element);\n });\n }, [editor, threads, nodes]);\n\n // Sort threads by the position of the first element associated with the thread in the document (top to bottom, left to right)\n const orderedThreads = useMemo(getOrderedThreads, [getOrderedThreads]);\n\n const [elements, setElements] = useState<Map<string, HTMLElement>>(new Map());\n\n const [positions, setPositions] = useState<Map<string, number>>(new Map()); // A map of thread ids to their 'top' position in the document\n\n const onItemAdd = useCallback((id: string, el: HTMLElement) => {\n setElements((prev) => new Map(prev).set(id, el));\n }, []);\n\n const onItemRemove = useCallback((id: string) => {\n setElements((prev) => {\n const items = new Map(prev);\n items.delete(id);\n return items;\n });\n }, []);\n\n const handlePositionThreads = useCallback(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const orderedThreads = getOrderedThreads();\n\n // Returns an array of threads that should be positioned in ascending order - this includes threads that are active and threads that should come after the active threads\n function getAscendingThreads() {\n // If there are no active threads, all threads are ordered in ascending manner.\n if (activeThreads.length === 0) return orderedThreads;\n\n // Filter threads that are active\n const active = orderedThreads.filter(({ thread }) =>\n activeThreads.includes(thread.id)\n );\n\n // Filter threads that should come after the active threads\n const after = orderedThreads.filter(({ thread, element }) => {\n if (activeThreads.includes(thread.id)) return false;\n\n // Check if the current thread comes after any of the active threads\n const isAfter = active.some(({ element: activeElement }) => {\n return compareNodes(activeElement, element) === -1;\n });\n\n return isAfter;\n });\n\n return active.concat(after);\n }\n\n const ascending = getAscendingThreads();\n\n // Filter threads that are neither active nor come after active threads (i.e. 'other' threads)\n const descending = orderedThreads.filter(\n (entry) => !ascending.includes(entry)\n );\n\n const newPositions = new Map<string, number>();\n\n // Iterate over each thread and calculate its new position by taking into account the position of the previously positioned threads\n for (const { thread, element } of ascending) {\n const rect = element.getBoundingClientRect();\n let top = rect.top - container.getBoundingClientRect().top;\n\n for (const [id, position] of newPositions) {\n // Retrieve the element associated with the thread\n const el = elements.get(id);\n if (el === undefined) continue;\n\n if (\n top >= position &&\n top <= position + el.getBoundingClientRect().height\n ) {\n top = position + el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n for (const { thread, element } of descending.reverse()) {\n const rect = element.getBoundingClientRect();\n // Retrieve the element associated with the current thread\n const el = elements.get(thread.id);\n if (el === undefined) continue;\n\n let top = rect.top - container.getBoundingClientRect().top;\n for (const [, position] of newPositions) {\n if (top >= position - el.getBoundingClientRect().height) {\n top = position - el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n setPositions(newPositions);\n }, [getOrderedThreads, activeThreads, elements]);\n\n useLayoutEffect(() => {\n handlePositionThreads();\n }, [handlePositionThreads]);\n\n useEffect(() => {\n return editor.registerUpdateListener(() => {\n handlePositionThreads();\n });\n }, [editor, handlePositionThreads]);\n\n useEffect(() => {\n const observer = new ResizeObserver(handlePositionThreads);\n for (const element of elements.values()) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [elements, handlePositionThreads]);\n\n const root = useRootElement();\n\n useEffect(() => {\n if (root === null) return;\n const observer = new ResizeObserver(handlePositionThreads);\n\n observer.observe(root);\n return () => observer.disconnect();\n }, [root, handlePositionThreads]);\n\n if (orderedThreads.length === 0) return null;\n\n return (\n <div\n {...props}\n className={classNames(className, \"lb-root lb-lexical-anchored-threads\")}\n ref={containerRef}\n style={{\n position: \"relative\",\n ...style,\n }}\n >\n {orderedThreads.map(({ thread, element }) => {\n const rect = element.getBoundingClientRect();\n const offset = root !== null ? root.getBoundingClientRect().top : 0;\n\n let top = rect.top - offset;\n\n if (positions.has(thread.id)) {\n top = positions.get(thread.id)!;\n }\n\n const isActive = activeThreads.includes(thread.id);\n\n return (\n <ThreadWrapper\n key={thread.id}\n Thread={Thread}\n thread={thread}\n onItemAdd={onItemAdd}\n onItemRemove={onItemRemove}\n style={{\n position: \"absolute\",\n transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,\n insetInlineStart: 0,\n inlineSize: \"100%\",\n paddingBlockEnd: GAP,\n }}\n />\n );\n })}\n </div>\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n Thread: ComponentType<ThreadProps>;\n onItemAdd: (id: string, el: HTMLElement) => void;\n onItemRemove: (id: string) => void;\n}\n\nfunction ThreadWrapper({\n onItemAdd,\n onItemRemove,\n thread,\n Thread,\n className,\n ...props\n}: ThreadWrapperProps) {\n const [editor] = useLexicalComposerContext();\n const nodes = useThreadToNodes();\n const divRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const isActive = activeThreads.includes(thread.id);\n\n function handleThreadClick() {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return;\n\n if (activeThreads.includes(thread.id)) return;\n\n editor.update(() => {\n const [key] = keys;\n const node = $getNodeByKey(key);\n if (!$isThreadMarkNode(node)) return;\n node.selectStart();\n });\n }\n\n useLayoutEffect(() => {\n const el = divRef.current;\n if (el === null) return;\n\n onItemAdd(thread.id, el);\n return () => {\n onItemRemove(thread.id);\n };\n }, [thread.id, onItemAdd, onItemRemove]);\n\n return (\n <div\n ref={divRef}\n className={classNames(\n \"lb-lexical-anchored-threads-thread-container\",\n className\n )}\n {...props}\n >\n <Thread\n thread={thread}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleThreadClick}\n className=\"lb-lexical-anchored-threads-thread\"\n showComposer={isActive ? true : false}\n />\n </div>\n );\n}\n\nfunction useThreadToNodes(): ThreadToNodesMap {\n const threadToNodes = useContext(ThreadToNodesContext);\n if (threadToNodes === null) {\n throw new Error(\n \"AnchoredThreads component must be used within a LiveblocksPlugin component.\"\n );\n }\n return threadToNodes;\n}\n\nfunction useActiveThreads() {\n const activeThreads = useContext(ActiveThreadsContext);\n if (activeThreads === null) {\n throw new Error(\n \"AnchoredThreads component must be used within LiveblocksPlugin.\"\n );\n }\n\n return activeThreads;\n}\n"],"names":["useLexicalComposerContext","DefaultThread","useRef","useCallback","elements","useMemo","useState","orderedThreads","useLayoutEffect","useEffect","useRootElement","jsx","classNames","$getNodeByKey","$isThreadMarkNode","useContext","ThreadToNodesContext","ActiveThreadsContext"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
+ import { jsx } from 'react/jsx-runtime';
1
2
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
2
3
  import { Thread } from '@liveblocks/react-ui';
3
4
  import { $getNodeByKey } from 'lexical';
4
- import React__default, { useRef, useCallback, useMemo, useState, useLayoutEffect, useEffect, useContext } from 'react';
5
+ import { useRef, useCallback, useMemo, useState, useLayoutEffect, useEffect, useContext } from 'react';
5
6
  import { classNames } from '../classnames.mjs';
6
7
  import { useRootElement } from '../liveblocks-plugin-provider.mjs';
7
8
  import { ThreadToNodesContext, ActiveThreadsContext } from './comment-plugin-provider.mjs';
@@ -142,37 +143,37 @@ function AnchoredThreads({
142
143
  }, [root, handlePositionThreads]);
143
144
  if (orderedThreads.length === 0)
144
145
  return null;
145
- return /* @__PURE__ */ React__default.createElement("div", {
146
+ return /* @__PURE__ */ jsx("div", {
146
147
  ...props,
147
148
  className: classNames(className, "lb-root lb-lexical-anchored-threads"),
148
149
  ref: containerRef,
149
150
  style: {
150
151
  position: "relative",
151
152
  ...style
152
- }
153
- }, orderedThreads.map(({ thread, element }) => {
154
- const rect = element.getBoundingClientRect();
155
- const offset = root !== null ? root.getBoundingClientRect().top : 0;
156
- let top = rect.top - offset;
157
- if (positions.has(thread.id)) {
158
- top = positions.get(thread.id);
159
- }
160
- const isActive = activeThreads.includes(thread.id);
161
- return /* @__PURE__ */ React__default.createElement(ThreadWrapper, {
162
- key: thread.id,
163
- Thread: Thread$1,
164
- thread,
165
- onItemAdd,
166
- onItemRemove,
167
- style: {
168
- position: "absolute",
169
- transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,
170
- insetInlineStart: 0,
171
- inlineSize: "100%",
172
- paddingBlockEnd: GAP
153
+ },
154
+ children: orderedThreads.map(({ thread, element }) => {
155
+ const rect = element.getBoundingClientRect();
156
+ const offset = root !== null ? root.getBoundingClientRect().top : 0;
157
+ let top = rect.top - offset;
158
+ if (positions.has(thread.id)) {
159
+ top = positions.get(thread.id);
173
160
  }
174
- });
175
- }));
161
+ const isActive = activeThreads.includes(thread.id);
162
+ return /* @__PURE__ */ jsx(ThreadWrapper, {
163
+ Thread: Thread$1,
164
+ thread,
165
+ onItemAdd,
166
+ onItemRemove,
167
+ style: {
168
+ position: "absolute",
169
+ transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,
170
+ insetInlineStart: 0,
171
+ inlineSize: "100%",
172
+ paddingBlockEnd: GAP
173
+ }
174
+ }, thread.id);
175
+ })
176
+ });
176
177
  }
177
178
  function ThreadWrapper({
178
179
  onItemAdd,
@@ -210,20 +211,21 @@ function ThreadWrapper({
210
211
  onItemRemove(thread.id);
211
212
  };
212
213
  }, [thread.id, onItemAdd, onItemRemove]);
213
- return /* @__PURE__ */ React__default.createElement("div", {
214
+ return /* @__PURE__ */ jsx("div", {
214
215
  ref: divRef,
215
216
  className: classNames(
216
217
  "lb-lexical-anchored-threads-thread-container",
217
218
  className
218
219
  ),
219
- ...props
220
- }, /* @__PURE__ */ React__default.createElement(Thread, {
221
- thread,
222
- "data-state": isActive ? "active" : "inactive",
223
- onClick: handleThreadClick,
224
- className: "lb-lexical-anchored-threads-thread",
225
- showComposer: isActive ? true : false
226
- }));
220
+ ...props,
221
+ children: /* @__PURE__ */ jsx(Thread, {
222
+ thread,
223
+ "data-state": isActive ? "active" : "inactive",
224
+ onClick: handleThreadClick,
225
+ className: "lb-lexical-anchored-threads-thread",
226
+ showComposer: isActive ? true : false
227
+ })
228
+ });
227
229
  }
228
230
  function useThreadToNodes() {
229
231
  const threadToNodes = useContext(ThreadToNodesContext);
@@ -1 +1 @@
1
- {"version":3,"file":"anchored-threads.mjs","sources":["../../src/comments/anchored-threads.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { $getNodeByKey } from \"lexical\";\nimport type { ComponentPropsWithoutRef, ComponentType } from \"react\";\nimport React, {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { useRootElement } from \"../liveblocks-plugin-provider\";\nimport {\n ActiveThreadsContext,\n type ThreadToNodesMap,\n} from \"./comment-plugin-provider\";\nimport { ThreadToNodesContext } from \"./comment-plugin-provider\";\nimport { $isThreadMarkNode } from \"./thread-mark-node\";\n\nconst DEFAULT_GAP = 20;\nconst DEFAULT_ACTIVE_THREAD_OFFSET = -12;\n\nconst GAP = `var(--lb-lexical-anchored-threads-gap, ${DEFAULT_GAP}px)`;\nconst ACTIVE_THREAD_OFFSET = `var(--lb-lexical-anchored-threads-active-thread-offset, ${DEFAULT_ACTIVE_THREAD_OFFSET}px)`;\n\ntype AnchoredThreadsComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface AnchoredThreadsProps<M extends BaseMetadata = DM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<AnchoredThreadsComponents>;\n}\n\n/**\n * Compares two nodes based on their position in the DOM.\n * Returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n * @param a The first node to compare\n * @param b The second node to compare\n * @returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n */\nexport function compareNodes(a: Node, b: Node): number {\n // Calculate the position of node 'b' relative to node 'a'\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nexport function AnchoredThreads({\n threads,\n components,\n className,\n style,\n ...props\n}: AnchoredThreadsProps) {\n const [editor] = useLexicalComposerContext();\n const Thread = components?.Thread ?? DefaultThread;\n const containerRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const nodes = useThreadToNodes(); // A map of thread ids to a set of thread mark nodes associated with the thread\n\n const getOrderedThreads = useCallback(() => {\n return threads\n .filter((thread) => thread.resolved === false)\n .map((thread) => {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return null;\n\n const elements = Array.from(keys.values())\n .map((key) => editor.getElementByKey(key))\n .filter(Boolean) as HTMLElement[];\n if (elements.length === 0) return null;\n\n const element = elements.sort(compareNodes)[0];\n return {\n thread,\n element,\n };\n })\n .filter(\n (entry): entry is { thread: ThreadData; element: HTMLElement } =>\n entry !== null\n )\n .sort((a, b) => {\n return compareNodes(a.element, b.element);\n });\n }, [editor, threads, nodes]);\n\n // Sort threads by the position of the first element associated with the thread in the document (top to bottom, left to right)\n const orderedThreads = useMemo(getOrderedThreads, [getOrderedThreads]);\n\n const [elements, setElements] = useState<Map<string, HTMLElement>>(new Map());\n\n const [positions, setPositions] = useState<Map<string, number>>(new Map()); // A map of thread ids to their 'top' position in the document\n\n const onItemAdd = useCallback((id: string, el: HTMLElement) => {\n setElements((prev) => new Map(prev).set(id, el));\n }, []);\n\n const onItemRemove = useCallback((id: string) => {\n setElements((prev) => {\n const items = new Map(prev);\n items.delete(id);\n return items;\n });\n }, []);\n\n const handlePositionThreads = useCallback(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const orderedThreads = getOrderedThreads();\n\n // Returns an array of threads that should be positioned in ascending order - this includes threads that are active and threads that should come after the active threads\n function getAscendingThreads() {\n // If there are no active threads, all threads are ordered in ascending manner.\n if (activeThreads.length === 0) return orderedThreads;\n\n // Filter threads that are active\n const active = orderedThreads.filter(({ thread }) =>\n activeThreads.includes(thread.id)\n );\n\n // Filter threads that should come after the active threads\n const after = orderedThreads.filter(({ thread, element }) => {\n if (activeThreads.includes(thread.id)) return false;\n\n // Check if the current thread comes after any of the active threads\n const isAfter = active.some(({ element: activeElement }) => {\n return compareNodes(activeElement, element) === -1;\n });\n\n return isAfter;\n });\n\n return active.concat(after);\n }\n\n const ascending = getAscendingThreads();\n\n // Filter threads that are neither active nor come after active threads (i.e. 'other' threads)\n const descending = orderedThreads.filter(\n (entry) => !ascending.includes(entry)\n );\n\n const newPositions = new Map<string, number>();\n\n // Iterate over each thread and calculate its new position by taking into account the position of the previously positioned threads\n for (const { thread, element } of ascending) {\n const rect = element.getBoundingClientRect();\n let top = rect.top - container.getBoundingClientRect().top;\n\n for (const [id, position] of newPositions) {\n // Retrieve the element associated with the thread\n const el = elements.get(id);\n if (el === undefined) continue;\n\n if (\n top >= position &&\n top <= position + el.getBoundingClientRect().height\n ) {\n top = position + el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n for (const { thread, element } of descending.reverse()) {\n const rect = element.getBoundingClientRect();\n // Retrieve the element associated with the current thread\n const el = elements.get(thread.id);\n if (el === undefined) continue;\n\n let top = rect.top - container.getBoundingClientRect().top;\n for (const [, position] of newPositions) {\n if (top >= position - el.getBoundingClientRect().height) {\n top = position - el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n setPositions(newPositions);\n }, [getOrderedThreads, activeThreads, elements]);\n\n useLayoutEffect(() => {\n handlePositionThreads();\n }, [handlePositionThreads]);\n\n useEffect(() => {\n return editor.registerUpdateListener(() => {\n handlePositionThreads();\n });\n }, [editor, handlePositionThreads]);\n\n useEffect(() => {\n const observer = new ResizeObserver(handlePositionThreads);\n for (const element of elements.values()) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [elements, handlePositionThreads]);\n\n const root = useRootElement();\n\n useEffect(() => {\n if (root === null) return;\n const observer = new ResizeObserver(handlePositionThreads);\n\n observer.observe(root);\n return () => observer.disconnect();\n }, [root, handlePositionThreads]);\n\n if (orderedThreads.length === 0) return null;\n\n return (\n <div\n {...props}\n className={classNames(className, \"lb-root lb-lexical-anchored-threads\")}\n ref={containerRef}\n style={{\n position: \"relative\",\n ...style,\n }}\n >\n {orderedThreads.map(({ thread, element }) => {\n const rect = element.getBoundingClientRect();\n const offset = root !== null ? root.getBoundingClientRect().top : 0;\n\n let top = rect.top - offset;\n\n if (positions.has(thread.id)) {\n top = positions.get(thread.id)!;\n }\n\n const isActive = activeThreads.includes(thread.id);\n\n return (\n <ThreadWrapper\n key={thread.id}\n Thread={Thread}\n thread={thread}\n onItemAdd={onItemAdd}\n onItemRemove={onItemRemove}\n style={{\n position: \"absolute\",\n transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,\n insetInlineStart: 0,\n inlineSize: \"100%\",\n paddingBlockEnd: GAP,\n }}\n />\n );\n })}\n </div>\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n Thread: ComponentType<ThreadProps>;\n onItemAdd: (id: string, el: HTMLElement) => void;\n onItemRemove: (id: string) => void;\n}\n\nfunction ThreadWrapper({\n onItemAdd,\n onItemRemove,\n thread,\n Thread,\n className,\n ...props\n}: ThreadWrapperProps) {\n const [editor] = useLexicalComposerContext();\n const nodes = useThreadToNodes();\n const divRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const isActive = activeThreads.includes(thread.id);\n\n function handleThreadClick() {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return;\n\n if (activeThreads.includes(thread.id)) return;\n\n editor.update(() => {\n const [key] = keys;\n const node = $getNodeByKey(key);\n if (!$isThreadMarkNode(node)) return;\n node.selectStart();\n });\n }\n\n useLayoutEffect(() => {\n const el = divRef.current;\n if (el === null) return;\n\n onItemAdd(thread.id, el);\n return () => {\n onItemRemove(thread.id);\n };\n }, [thread.id, onItemAdd, onItemRemove]);\n\n return (\n <div\n ref={divRef}\n className={classNames(\n \"lb-lexical-anchored-threads-thread-container\",\n className\n )}\n {...props}\n >\n <Thread\n thread={thread}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleThreadClick}\n className=\"lb-lexical-anchored-threads-thread\"\n showComposer={isActive ? true : false}\n />\n </div>\n );\n}\n\nfunction useThreadToNodes(): ThreadToNodesMap {\n const threadToNodes = useContext(ThreadToNodesContext);\n if (threadToNodes === null) {\n throw new Error(\n \"AnchoredThreads component must be used within a LiveblocksPlugin component.\"\n );\n }\n return threadToNodes;\n}\n\nfunction useActiveThreads() {\n const activeThreads = useContext(ActiveThreadsContext);\n if (activeThreads === null) {\n throw new Error(\n \"AnchoredThreads component must be used within LiveblocksPlugin.\"\n );\n }\n\n return activeThreads;\n}\n"],"names":["Thread","DefaultThread","elements","orderedThreads","React"],"mappings":"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"}
1
+ {"version":3,"file":"anchored-threads.mjs","sources":["../../src/comments/anchored-threads.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { $getNodeByKey } from \"lexical\";\nimport type { ComponentPropsWithoutRef, ComponentType } from \"react\";\nimport {\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { useRootElement } from \"../liveblocks-plugin-provider\";\nimport {\n ActiveThreadsContext,\n type ThreadToNodesMap,\n} from \"./comment-plugin-provider\";\nimport { ThreadToNodesContext } from \"./comment-plugin-provider\";\nimport { $isThreadMarkNode } from \"./thread-mark-node\";\n\nconst DEFAULT_GAP = 20;\nconst DEFAULT_ACTIVE_THREAD_OFFSET = -12;\n\nconst GAP = `var(--lb-lexical-anchored-threads-gap, ${DEFAULT_GAP}px)`;\nconst ACTIVE_THREAD_OFFSET = `var(--lb-lexical-anchored-threads-active-thread-offset, ${DEFAULT_ACTIVE_THREAD_OFFSET}px)`;\n\ntype AnchoredThreadsComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface AnchoredThreadsProps<M extends BaseMetadata = DM>\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<AnchoredThreadsComponents>;\n}\n\n/**\n * Compares two nodes based on their position in the DOM.\n * Returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n * @param a The first node to compare\n * @param b The second node to compare\n * @returns -1 if a comes before b, 1 if a comes after b, and 0 if they are the same node.\n */\nexport function compareNodes(a: Node, b: Node): number {\n // Calculate the position of node 'b' relative to node 'a'\n const position = a.compareDocumentPosition(b);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;\n if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;\n return 0;\n}\n\nexport function AnchoredThreads({\n threads,\n components,\n className,\n style,\n ...props\n}: AnchoredThreadsProps) {\n const [editor] = useLexicalComposerContext();\n const Thread = components?.Thread ?? DefaultThread;\n const containerRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const nodes = useThreadToNodes(); // A map of thread ids to a set of thread mark nodes associated with the thread\n\n const getOrderedThreads = useCallback(() => {\n return threads\n .filter((thread) => thread.resolved === false)\n .map((thread) => {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return null;\n\n const elements = Array.from(keys.values())\n .map((key) => editor.getElementByKey(key))\n .filter(Boolean) as HTMLElement[];\n if (elements.length === 0) return null;\n\n const element = elements.sort(compareNodes)[0];\n return {\n thread,\n element,\n };\n })\n .filter(\n (entry): entry is { thread: ThreadData; element: HTMLElement } =>\n entry !== null\n )\n .sort((a, b) => {\n return compareNodes(a.element, b.element);\n });\n }, [editor, threads, nodes]);\n\n // Sort threads by the position of the first element associated with the thread in the document (top to bottom, left to right)\n const orderedThreads = useMemo(getOrderedThreads, [getOrderedThreads]);\n\n const [elements, setElements] = useState<Map<string, HTMLElement>>(new Map());\n\n const [positions, setPositions] = useState<Map<string, number>>(new Map()); // A map of thread ids to their 'top' position in the document\n\n const onItemAdd = useCallback((id: string, el: HTMLElement) => {\n setElements((prev) => new Map(prev).set(id, el));\n }, []);\n\n const onItemRemove = useCallback((id: string) => {\n setElements((prev) => {\n const items = new Map(prev);\n items.delete(id);\n return items;\n });\n }, []);\n\n const handlePositionThreads = useCallback(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const orderedThreads = getOrderedThreads();\n\n // Returns an array of threads that should be positioned in ascending order - this includes threads that are active and threads that should come after the active threads\n function getAscendingThreads() {\n // If there are no active threads, all threads are ordered in ascending manner.\n if (activeThreads.length === 0) return orderedThreads;\n\n // Filter threads that are active\n const active = orderedThreads.filter(({ thread }) =>\n activeThreads.includes(thread.id)\n );\n\n // Filter threads that should come after the active threads\n const after = orderedThreads.filter(({ thread, element }) => {\n if (activeThreads.includes(thread.id)) return false;\n\n // Check if the current thread comes after any of the active threads\n const isAfter = active.some(({ element: activeElement }) => {\n return compareNodes(activeElement, element) === -1;\n });\n\n return isAfter;\n });\n\n return active.concat(after);\n }\n\n const ascending = getAscendingThreads();\n\n // Filter threads that are neither active nor come after active threads (i.e. 'other' threads)\n const descending = orderedThreads.filter(\n (entry) => !ascending.includes(entry)\n );\n\n const newPositions = new Map<string, number>();\n\n // Iterate over each thread and calculate its new position by taking into account the position of the previously positioned threads\n for (const { thread, element } of ascending) {\n const rect = element.getBoundingClientRect();\n let top = rect.top - container.getBoundingClientRect().top;\n\n for (const [id, position] of newPositions) {\n // Retrieve the element associated with the thread\n const el = elements.get(id);\n if (el === undefined) continue;\n\n if (\n top >= position &&\n top <= position + el.getBoundingClientRect().height\n ) {\n top = position + el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n for (const { thread, element } of descending.reverse()) {\n const rect = element.getBoundingClientRect();\n // Retrieve the element associated with the current thread\n const el = elements.get(thread.id);\n if (el === undefined) continue;\n\n let top = rect.top - container.getBoundingClientRect().top;\n for (const [, position] of newPositions) {\n if (top >= position - el.getBoundingClientRect().height) {\n top = position - el.getBoundingClientRect().height;\n }\n }\n\n newPositions.set(thread.id, top);\n }\n\n setPositions(newPositions);\n }, [getOrderedThreads, activeThreads, elements]);\n\n useLayoutEffect(() => {\n handlePositionThreads();\n }, [handlePositionThreads]);\n\n useEffect(() => {\n return editor.registerUpdateListener(() => {\n handlePositionThreads();\n });\n }, [editor, handlePositionThreads]);\n\n useEffect(() => {\n const observer = new ResizeObserver(handlePositionThreads);\n for (const element of elements.values()) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [elements, handlePositionThreads]);\n\n const root = useRootElement();\n\n useEffect(() => {\n if (root === null) return;\n const observer = new ResizeObserver(handlePositionThreads);\n\n observer.observe(root);\n return () => observer.disconnect();\n }, [root, handlePositionThreads]);\n\n if (orderedThreads.length === 0) return null;\n\n return (\n <div\n {...props}\n className={classNames(className, \"lb-root lb-lexical-anchored-threads\")}\n ref={containerRef}\n style={{\n position: \"relative\",\n ...style,\n }}\n >\n {orderedThreads.map(({ thread, element }) => {\n const rect = element.getBoundingClientRect();\n const offset = root !== null ? root.getBoundingClientRect().top : 0;\n\n let top = rect.top - offset;\n\n if (positions.has(thread.id)) {\n top = positions.get(thread.id)!;\n }\n\n const isActive = activeThreads.includes(thread.id);\n\n return (\n <ThreadWrapper\n key={thread.id}\n Thread={Thread}\n thread={thread}\n onItemAdd={onItemAdd}\n onItemRemove={onItemRemove}\n style={{\n position: \"absolute\",\n transform: `translate3d(${isActive ? ACTIVE_THREAD_OFFSET : 0}, ${top}px, 0)`,\n insetInlineStart: 0,\n inlineSize: \"100%\",\n paddingBlockEnd: GAP,\n }}\n />\n );\n })}\n </div>\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n Thread: ComponentType<ThreadProps>;\n onItemAdd: (id: string, el: HTMLElement) => void;\n onItemRemove: (id: string) => void;\n}\n\nfunction ThreadWrapper({\n onItemAdd,\n onItemRemove,\n thread,\n Thread,\n className,\n ...props\n}: ThreadWrapperProps) {\n const [editor] = useLexicalComposerContext();\n const nodes = useThreadToNodes();\n const divRef = useRef<HTMLDivElement>(null);\n\n const activeThreads = useActiveThreads();\n\n const isActive = activeThreads.includes(thread.id);\n\n function handleThreadClick() {\n const keys = nodes.get(thread.id);\n if (keys === undefined || keys.size === 0) return;\n\n if (activeThreads.includes(thread.id)) return;\n\n editor.update(() => {\n const [key] = keys;\n const node = $getNodeByKey(key);\n if (!$isThreadMarkNode(node)) return;\n node.selectStart();\n });\n }\n\n useLayoutEffect(() => {\n const el = divRef.current;\n if (el === null) return;\n\n onItemAdd(thread.id, el);\n return () => {\n onItemRemove(thread.id);\n };\n }, [thread.id, onItemAdd, onItemRemove]);\n\n return (\n <div\n ref={divRef}\n className={classNames(\n \"lb-lexical-anchored-threads-thread-container\",\n className\n )}\n {...props}\n >\n <Thread\n thread={thread}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleThreadClick}\n className=\"lb-lexical-anchored-threads-thread\"\n showComposer={isActive ? true : false}\n />\n </div>\n );\n}\n\nfunction useThreadToNodes(): ThreadToNodesMap {\n const threadToNodes = useContext(ThreadToNodesContext);\n if (threadToNodes === null) {\n throw new Error(\n \"AnchoredThreads component must be used within a LiveblocksPlugin component.\"\n );\n }\n return threadToNodes;\n}\n\nfunction useActiveThreads() {\n const activeThreads = useContext(ActiveThreadsContext);\n if (activeThreads === null) {\n throw new Error(\n \"AnchoredThreads component must be used within LiveblocksPlugin.\"\n );\n }\n\n return activeThreads;\n}\n"],"names":["Thread","DefaultThread","elements","orderedThreads"],"mappings":"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"}