@liveblocks/react-tiptap 2.15.1 → 2.16.0-toolbars1

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 (68) hide show
  1. package/dist/LiveblocksExtension.js +1 -1
  2. package/dist/LiveblocksExtension.js.map +1 -1
  3. package/dist/LiveblocksExtension.mjs +1 -1
  4. package/dist/LiveblocksExtension.mjs.map +1 -1
  5. package/dist/comments/AnchoredThreads.js +34 -16
  6. package/dist/comments/AnchoredThreads.js.map +1 -1
  7. package/dist/comments/AnchoredThreads.mjs +33 -15
  8. package/dist/comments/AnchoredThreads.mjs.map +1 -1
  9. package/dist/comments/CommentsExtension.js +6 -2
  10. package/dist/comments/CommentsExtension.js.map +1 -1
  11. package/dist/comments/CommentsExtension.mjs +7 -3
  12. package/dist/comments/CommentsExtension.mjs.map +1 -1
  13. package/dist/comments/FloatingComposer.js +34 -33
  14. package/dist/comments/FloatingComposer.js.map +1 -1
  15. package/dist/comments/FloatingComposer.mjs +36 -35
  16. package/dist/comments/FloatingComposer.mjs.map +1 -1
  17. package/dist/comments/FloatingThreads.js +5 -2
  18. package/dist/comments/FloatingThreads.js.map +1 -1
  19. package/dist/comments/FloatingThreads.mjs +5 -2
  20. package/dist/comments/FloatingThreads.mjs.map +1 -1
  21. package/dist/context.js +24 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/context.mjs +21 -0
  24. package/dist/context.mjs.map +1 -0
  25. package/dist/index.d.mts +65 -13
  26. package/dist/index.d.ts +65 -13
  27. package/dist/index.js +4 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +2 -0
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/mentions/MentionsList.js +117 -107
  32. package/dist/mentions/MentionsList.js.map +1 -1
  33. package/dist/mentions/MentionsList.mjs +119 -109
  34. package/dist/mentions/MentionsList.mjs.map +1 -1
  35. package/dist/toolbar/FloatingToolbar.js +301 -0
  36. package/dist/toolbar/FloatingToolbar.js.map +1 -0
  37. package/dist/toolbar/FloatingToolbar.mjs +298 -0
  38. package/dist/toolbar/FloatingToolbar.mjs.map +1 -0
  39. package/dist/toolbar/FloatingToolbarContext.js +8 -0
  40. package/dist/toolbar/FloatingToolbarContext.js.map +1 -0
  41. package/dist/toolbar/FloatingToolbarContext.mjs +6 -0
  42. package/dist/toolbar/FloatingToolbarContext.mjs.map +1 -0
  43. package/dist/toolbar/Toolbar.js +352 -0
  44. package/dist/toolbar/Toolbar.js.map +1 -0
  45. package/dist/toolbar/Toolbar.mjs +327 -0
  46. package/dist/toolbar/Toolbar.mjs.map +1 -0
  47. package/dist/types.js +7 -3
  48. package/dist/types.js.map +1 -1
  49. package/dist/types.mjs +6 -3
  50. package/dist/types.mjs.map +1 -1
  51. package/dist/utils.js +17 -0
  52. package/dist/utils.js.map +1 -1
  53. package/dist/utils.mjs +16 -1
  54. package/dist/utils.mjs.map +1 -1
  55. package/dist/version-history/HistoryVersionPreview.js +79 -79
  56. package/dist/version-history/HistoryVersionPreview.js.map +1 -1
  57. package/dist/version-history/HistoryVersionPreview.mjs +79 -79
  58. package/dist/version-history/HistoryVersionPreview.mjs.map +1 -1
  59. package/dist/version.js +1 -1
  60. package/dist/version.js.map +1 -1
  61. package/dist/version.mjs +1 -1
  62. package/dist/version.mjs.map +1 -1
  63. package/package.json +11 -8
  64. package/src/styles/constants.css +2 -1
  65. package/src/styles/index.css +58 -6
  66. package/src/styles/utils.css +11 -0
  67. package/styles.css +1 -1
  68. package/styles.css.map +1 -1
@@ -1,8 +1,9 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useFloating, flip, offset, hide, shift, limitShift, size, autoUpdate } from '@floating-ui/react-dom';
3
+ import { useLayoutEffect } from '@liveblocks/react/_private';
3
4
  import { Thread } from '@liveblocks/react-ui';
4
5
  import { useEditorState } from '@tiptap/react';
5
- import { useState, useEffect, useCallback, useLayoutEffect } from 'react';
6
+ import { useState, useEffect, useCallback } from 'react';
6
7
  import { createPortal } from 'react-dom';
7
8
  import { classNames } from '../classnames.mjs';
8
9
  import { THREADS_PLUGIN_KEY } from '../types.mjs';
@@ -114,7 +115,9 @@ function FloatingThreadPortal({
114
115
  }
115
116
  });
116
117
  const updateRef = useCallback(() => {
117
- const el = editor.view.dom.querySelector(`[data-lb-thread-id="${thread.id}"]`);
118
+ const el = editor.view.dom.querySelector(
119
+ `[data-lb-thread-id="${thread.id}"]`
120
+ );
118
121
  if (el) {
119
122
  setReference(el);
120
123
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingThreads.mjs","sources":["../../src/comments/FloatingThreads.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n hide,\n limitShift,\n offset,\n shift,\n size,\n useFloating,\n} from \"@floating-ui/react-dom\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { type Editor, useEditorState } from \"@tiptap/react\";\nimport {\n type ComponentType,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { classNames } from \"../classnames\";\nimport { THREADS_PLUGIN_KEY } from \"../types\";\n\ntype ThreadPanelComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface FloatingThreadsProps<M extends BaseMetadata = DM>\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<ThreadPanelComponents>;\n\n /**\n * The tiptap editor\n */\n editor: Editor | null;\n}\n\nexport function FloatingThreads({\n threads,\n components,\n editor,\n ...props\n}: FloatingThreadsProps) {\n const Thread = components?.Thread ?? DefaultThread;\n\n const { pluginState } = useEditorState({\n editor,\n selector: (ctx) => {\n if (!ctx?.editor?.state) return { pluginState: undefined };\n const state = THREADS_PLUGIN_KEY.getState(ctx.editor.state);\n return {\n pluginState: state,\n };\n },\n equalityFn: (prev, next) => {\n if (!prev || !next) return false;\n return prev.pluginState?.selectedThreadPos === next.pluginState?.selectedThreadPos &&\n prev.pluginState?.selectedThreadId === next.pluginState?.selectedThreadId;\n },\n }) ?? { pluginState: undefined };\n\n const [activeThread, setActiveThread] = useState<ThreadData | null>(null);\n\n useEffect(() => {\n if (!editor || !pluginState) {\n setActiveThread(null);\n return;\n }\n const { selectedThreadId, selectedThreadPos } = pluginState;\n if (selectedThreadId === null || selectedThreadPos === null) {\n setActiveThread(null);\n return;\n }\n const active = (threads ?? []).find((thread) =>\n selectedThreadId === thread.id\n );\n setActiveThread(active ?? null);\n }, [editor, pluginState, threads]);\n\n const handleEscapeKeydown = useCallback((): boolean => {\n if (!editor || activeThread === null) return false;\n editor.commands.selectThread(null);\n return true;\n }, [activeThread, editor]);\n\n if (!activeThread || !editor || activeThread.resolved) return null;\n\n return (\n <FloatingThreadPortal\n thread={activeThread}\n editor={editor}\n container={document.body}\n {...props}\n >\n {activeThread &&\n <ThreadWrapper\n key={activeThread.id}\n thread={activeThread}\n Thread={Thread}\n onEscapeKeydown={handleEscapeKeydown}\n className=\"lb-tiptap-floating-threads-thread\"\n />\n }\n </FloatingThreadPortal>\n );\n}\n\ninterface FloatingThreadPortalProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n thread: ThreadData;\n editor: Editor;\n container: HTMLElement;\n children: ReactNode;\n}\n\nexport const FLOATING_THREAD_COLLISION_PADDING = 10;\n\nfunction FloatingThreadPortal({\n container,\n editor,\n thread,\n children,\n className,\n style,\n ...props\n}: FloatingThreadPortalProps) {\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"absolute\",\n placement: \"bottom\",\n middleware: [\n flip({ padding: FLOATING_THREAD_COLLISION_PADDING, crossAxis: false }),\n offset(10),\n hide({ padding: FLOATING_THREAD_COLLISION_PADDING }),\n shift({\n padding: FLOATING_THREAD_COLLISION_PADDING,\n limiter: limitShift(),\n }),\n size({\n padding: FLOATING_THREAD_COLLISION_PADDING,\n apply({ availableWidth, availableHeight, elements }) {\n elements.floating.style.setProperty(\n \"--lb-tiptap-floating-threads-available-width\",\n `${availableWidth}px`\n );\n elements.floating.style.setProperty(\n \"--lb-tiptap-floating-threads-available-height\",\n `${availableHeight}px`\n );\n },\n }),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n const updateRef = useCallback(() => {\n const el = editor.view.dom.querySelector(`[data-lb-thread-id=\"${thread.id}\"]`);\n if (el) {\n setReference(el);\n }\n }, [setReference, editor, thread.id]);\n\n // Remote cursor updates and other edits can cause the ref to break\n useEffect(() => {\n editor.on(\"transaction\", updateRef)\n return () => {\n editor.off(\"transaction\", updateRef);\n };\n }, [editor, updateRef]);\n\n useLayoutEffect(updateRef, [updateRef]);\n\n return createPortal(\n <div\n ref={setFloating}\n {...props}\n style={{\n ...style,\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n }}\n className={classNames(\n \"lb-root lb-portal lb-elevation lb-tiptap-floating lb-tiptap-floating-threads\",\n className\n )}\n >\n {children}\n </div>,\n container\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n thread: ThreadData;\n Thread: ComponentType<ThreadProps>;\n onEscapeKeydown: () => void;\n}\n\nfunction ThreadWrapper({\n thread,\n Thread,\n onEscapeKeydown,\n onKeyDown,\n ...threadProps\n}: ThreadWrapperProps) {\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n // TODO: Add ability to preventDefault on keydown to override the default behavior, e.g. to show an alert dialog\n if (event.key === \"Escape\") {\n onEscapeKeydown();\n }\n },\n [onEscapeKeydown, onKeyDown]\n );\n\n return <Thread thread={thread} onKeyDown={handleKeyDown} {...threadProps} />;\n}\n"],"names":["Thread","DefaultThread"],"mappings":"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"}
1
+ {"version":3,"file":"FloatingThreads.mjs","sources":["../../src/comments/FloatingThreads.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n hide,\n limitShift,\n offset,\n shift,\n size,\n useFloating,\n} from \"@floating-ui/react-dom\";\nimport type { BaseMetadata, DM, ThreadData } from \"@liveblocks/core\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n Thread as DefaultThread,\n type ThreadProps,\n} from \"@liveblocks/react-ui\";\nimport { type Editor, useEditorState } from \"@tiptap/react\";\nimport {\n type ComponentType,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { classNames } from \"../classnames\";\nimport { THREADS_PLUGIN_KEY } from \"../types\";\n\ntype ThreadPanelComponents = {\n Thread: ComponentType<ThreadProps>;\n};\n\nexport interface FloatingThreadsProps<M extends BaseMetadata = DM>\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /**\n * The threads to display.\n */\n threads: ThreadData<M>[];\n\n /**\n * Override the component's components.\n */\n components?: Partial<ThreadPanelComponents>;\n\n /**\n * The tiptap editor\n */\n editor: Editor | null;\n}\n\nexport function FloatingThreads({\n threads,\n components,\n editor,\n ...props\n}: FloatingThreadsProps) {\n const Thread = components?.Thread ?? DefaultThread;\n\n const { pluginState } = useEditorState({\n editor,\n selector: (ctx) => {\n if (!ctx?.editor?.state) return { pluginState: undefined };\n const state = THREADS_PLUGIN_KEY.getState(ctx.editor.state);\n return {\n pluginState: state,\n };\n },\n equalityFn: (prev, next) => {\n if (!prev || !next) return false;\n return (\n prev.pluginState?.selectedThreadPos ===\n next.pluginState?.selectedThreadPos &&\n prev.pluginState?.selectedThreadId ===\n next.pluginState?.selectedThreadId\n );\n },\n }) ?? { pluginState: undefined };\n\n const [activeThread, setActiveThread] = useState<ThreadData | null>(null);\n\n useEffect(() => {\n if (!editor || !pluginState) {\n setActiveThread(null);\n return;\n }\n const { selectedThreadId, selectedThreadPos } = pluginState;\n if (selectedThreadId === null || selectedThreadPos === null) {\n setActiveThread(null);\n return;\n }\n const active = (threads ?? []).find(\n (thread) => selectedThreadId === thread.id\n );\n setActiveThread(active ?? null);\n }, [editor, pluginState, threads]);\n\n const handleEscapeKeydown = useCallback((): boolean => {\n if (!editor || activeThread === null) return false;\n editor.commands.selectThread(null);\n return true;\n }, [activeThread, editor]);\n\n if (!activeThread || !editor || activeThread.resolved) return null;\n\n return (\n <FloatingThreadPortal\n thread={activeThread}\n editor={editor}\n container={document.body}\n {...props}\n >\n {activeThread && (\n <ThreadWrapper\n key={activeThread.id}\n thread={activeThread}\n Thread={Thread}\n onEscapeKeydown={handleEscapeKeydown}\n className=\"lb-tiptap-floating-threads-thread\"\n />\n )}\n </FloatingThreadPortal>\n );\n}\n\ninterface FloatingThreadPortalProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n thread: ThreadData;\n editor: Editor;\n container: HTMLElement;\n children: ReactNode;\n}\n\nexport const FLOATING_THREAD_COLLISION_PADDING = 10;\n\nfunction FloatingThreadPortal({\n container,\n editor,\n thread,\n children,\n className,\n style,\n ...props\n}: FloatingThreadPortalProps) {\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"absolute\",\n placement: \"bottom\",\n middleware: [\n flip({ padding: FLOATING_THREAD_COLLISION_PADDING, crossAxis: false }),\n offset(10),\n hide({ padding: FLOATING_THREAD_COLLISION_PADDING }),\n shift({\n padding: FLOATING_THREAD_COLLISION_PADDING,\n limiter: limitShift(),\n }),\n size({\n padding: FLOATING_THREAD_COLLISION_PADDING,\n apply({ availableWidth, availableHeight, elements }) {\n elements.floating.style.setProperty(\n \"--lb-tiptap-floating-threads-available-width\",\n `${availableWidth}px`\n );\n elements.floating.style.setProperty(\n \"--lb-tiptap-floating-threads-available-height\",\n `${availableHeight}px`\n );\n },\n }),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n const updateRef = useCallback(() => {\n const el = editor.view.dom.querySelector(\n `[data-lb-thread-id=\"${thread.id}\"]`\n );\n if (el) {\n setReference(el);\n }\n }, [setReference, editor, thread.id]);\n\n // Remote cursor updates and other edits can cause the ref to break\n useEffect(() => {\n editor.on(\"transaction\", updateRef);\n return () => {\n editor.off(\"transaction\", updateRef);\n };\n }, [editor, updateRef]);\n\n useLayoutEffect(updateRef, [updateRef]);\n\n return createPortal(\n <div\n ref={setFloating}\n {...props}\n style={{\n ...style,\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n }}\n className={classNames(\n \"lb-root lb-portal lb-elevation lb-tiptap-floating lb-tiptap-floating-threads\",\n className\n )}\n >\n {children}\n </div>,\n container\n );\n}\n\ninterface ThreadWrapperProps extends ThreadProps {\n thread: ThreadData;\n Thread: ComponentType<ThreadProps>;\n onEscapeKeydown: () => void;\n}\n\nfunction ThreadWrapper({\n thread,\n Thread,\n onEscapeKeydown,\n onKeyDown,\n ...threadProps\n}: ThreadWrapperProps) {\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n // TODO: Add ability to preventDefault on keydown to override the default behavior, e.g. to show an alert dialog\n if (event.key === \"Escape\") {\n onEscapeKeydown();\n }\n },\n [onEscapeKeydown, onKeyDown]\n );\n\n return <Thread thread={thread} onKeyDown={handleKeyDown} {...threadProps} />;\n}\n"],"names":["Thread","DefaultThread"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@liveblocks/core');
5
+ var react = require('react');
6
+
7
+ const EditorContext = react.createContext(null);
8
+ function EditorProvider({
9
+ editor,
10
+ children
11
+ }) {
12
+ return /* @__PURE__ */ jsxRuntime.jsx(EditorContext.Provider, {
13
+ value: editor,
14
+ children
15
+ });
16
+ }
17
+ function useCurrentEditor(source, parent) {
18
+ const currentEditor = react.useContext(EditorContext);
19
+ return core.nn(currentEditor, `${source} can\u2019t be used outside of ${parent}.`);
20
+ }
21
+
22
+ exports.EditorProvider = EditorProvider;
23
+ exports.useCurrentEditor = useCurrentEditor;
24
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sources":["../src/context.tsx"],"sourcesContent":["import { nn } from \"@liveblocks/core\";\nimport type { Editor } from \"@tiptap/react\";\nimport type { PropsWithChildren } from \"react\";\nimport { createContext, useContext } from \"react\";\n\nconst EditorContext = createContext<Editor | null>(null);\n\nexport function EditorProvider({\n editor,\n children,\n}: PropsWithChildren<{ editor: Editor }>) {\n return (\n <EditorContext.Provider value={editor}>{children}</EditorContext.Provider>\n );\n}\n\n/**\n * @tiptap/react already offers a `useCurrentEditor` hook but our components might\n * not live under `EditorProvider` or `EditorContent` so we create our own to reduce\n * repetition within our own nested components.\n *\n * @example\n * <Toolbar editor={editor}> // `editor` is required here\n * <ToolbarSectionInline /> // But it isn't there, because `Toolbar` uses our own `EditorProvider`\n * </Toolbar>\n */\nexport function useCurrentEditor(source: string, parent: string) {\n const currentEditor = useContext(EditorContext);\n\n return nn(currentEditor, `${source} can’t be used outside of ${parent}.`);\n}\n"],"names":["createContext","jsx","useContext","nn"],"mappings":";;;;;;AAKA,MAAM,aAAA,GAAgBA,oBAA6B,IAAI,CAAA,CAAA;AAEhD,SAAS,cAAe,CAAA;AAAA,EAC7B,MAAA;AAAA,EACA,QAAA;AACF,CAA0C,EAAA;AACxC,EACE,uBAAAC,cAAA,CAAC,cAAc,QAAd,EAAA;AAAA,IAAuB,KAAO,EAAA,MAAA;AAAA,IAAS,QAAA;AAAA,GAAS,CAAA,CAAA;AAErD,CAAA;AAYgB,SAAA,gBAAA,CAAiB,QAAgB,MAAgB,EAAA;AAC/D,EAAM,MAAA,aAAA,GAAgBC,iBAAW,aAAa,CAAA,CAAA;AAE9C,EAAA,OAAOC,OAAG,CAAA,aAAA,EAAe,CAAG,EAAA,MAAA,CAAA,+BAAA,EAAmC,MAAS,CAAA,CAAA,CAAA,CAAA,CAAA;AAC1E;;;;;"}
@@ -0,0 +1,21 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { nn } from '@liveblocks/core';
3
+ import { createContext, useContext } from 'react';
4
+
5
+ const EditorContext = createContext(null);
6
+ function EditorProvider({
7
+ editor,
8
+ children
9
+ }) {
10
+ return /* @__PURE__ */ jsx(EditorContext.Provider, {
11
+ value: editor,
12
+ children
13
+ });
14
+ }
15
+ function useCurrentEditor(source, parent) {
16
+ const currentEditor = useContext(EditorContext);
17
+ return nn(currentEditor, `${source} can\u2019t be used outside of ${parent}.`);
18
+ }
19
+
20
+ export { EditorProvider, useCurrentEditor };
21
+ //# sourceMappingURL=context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.mjs","sources":["../src/context.tsx"],"sourcesContent":["import { nn } from \"@liveblocks/core\";\nimport type { Editor } from \"@tiptap/react\";\nimport type { PropsWithChildren } from \"react\";\nimport { createContext, useContext } from \"react\";\n\nconst EditorContext = createContext<Editor | null>(null);\n\nexport function EditorProvider({\n editor,\n children,\n}: PropsWithChildren<{ editor: Editor }>) {\n return (\n <EditorContext.Provider value={editor}>{children}</EditorContext.Provider>\n );\n}\n\n/**\n * @tiptap/react already offers a `useCurrentEditor` hook but our components might\n * not live under `EditorProvider` or `EditorContent` so we create our own to reduce\n * repetition within our own nested components.\n *\n * @example\n * <Toolbar editor={editor}> // `editor` is required here\n * <ToolbarSectionInline /> // But it isn't there, because `Toolbar` uses our own `EditorProvider`\n * </Toolbar>\n */\nexport function useCurrentEditor(source: string, parent: string) {\n const currentEditor = useContext(EditorContext);\n\n return nn(currentEditor, `${source} can’t be used outside of ${parent}.`);\n}\n"],"names":[],"mappings":";;;;AAKA,MAAM,aAAA,GAAgB,cAA6B,IAAI,CAAA,CAAA;AAEhD,SAAS,cAAe,CAAA;AAAA,EAC7B,MAAA;AAAA,EACA,QAAA;AACF,CAA0C,EAAA;AACxC,EACE,uBAAA,GAAA,CAAC,cAAc,QAAd,EAAA;AAAA,IAAuB,KAAO,EAAA,MAAA;AAAA,IAAS,QAAA;AAAA,GAAS,CAAA,CAAA;AAErD,CAAA;AAYgB,SAAA,gBAAA,CAAiB,QAAgB,MAAgB,EAAA;AAC/D,EAAM,MAAA,aAAA,GAAgB,WAAW,aAAa,CAAA,CAAA;AAE9C,EAAA,OAAO,EAAG,CAAA,aAAA,EAAe,CAAG,EAAA,MAAA,CAAA,+BAAA,EAAmC,MAAS,CAAA,CAAA,CAAA,CAAA,CAAA;AAC1E;;;;"}
package/dist/index.d.mts CHANGED
@@ -3,11 +3,21 @@ import { BaseMetadata, DM, ThreadData, HistoryVersion } from '@liveblocks/core';
3
3
  import { ThreadProps, ComposerProps } from '@liveblocks/react-ui';
4
4
  import { Editor } from '@tiptap/react';
5
5
  import * as react from 'react';
6
- import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } from 'react';
6
+ import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes, ComponentProps, ReactNode } from 'react';
7
7
  import { BaseMetadata as BaseMetadata$1 } from '@liveblocks/client';
8
8
  import { Extension, Content } from '@tiptap/core';
9
9
 
10
- declare type AnchoredThreadsComponents = {
10
+ type FloatingPosition = "top" | "bottom";
11
+ type CommentsCommands<ReturnType> = {
12
+ /**
13
+ * Add a comment
14
+ */
15
+ addComment: (id: string) => ReturnType;
16
+ selectThread: (id: string | null) => ReturnType;
17
+ addPendingComment: () => ReturnType;
18
+ };
19
+
20
+ type AnchoredThreadsComponents = {
11
21
  Thread: ComponentType<ThreadProps>;
12
22
  };
13
23
  interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
@@ -30,7 +40,7 @@ declare const FloatingComposer: react.ForwardRefExoticComponent<Omit<ComposerPro
30
40
  editor: Editor | null;
31
41
  } & react.RefAttributes<HTMLFormElement>>;
32
42
 
33
- declare type ThreadPanelComponents = {
43
+ type ThreadPanelComponents = {
34
44
  Thread: ComponentType<ThreadProps>;
35
45
  };
36
46
  interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
@@ -49,7 +59,7 @@ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAtt
49
59
  }
50
60
  declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): react_jsx_runtime.JSX.Element | null;
51
61
 
52
- declare type LiveblocksExtensionOptions = {
62
+ type LiveblocksExtensionOptions = {
53
63
  field?: string;
54
64
  comments?: boolean;
55
65
  mentions?: boolean;
@@ -64,6 +74,55 @@ declare type LiveblocksExtensionOptions = {
64
74
  declare function useIsEditorReady(): boolean;
65
75
  declare const useLiveblocksExtension: (opts?: LiveblocksExtensionOptions) => Extension;
66
76
 
77
+ interface ToolbarSlotProps {
78
+ editor: Editor;
79
+ }
80
+ type ToolbarSlot = ReactNode | ComponentType<ToolbarSlotProps>;
81
+ interface ToolbarProps extends Omit<ComponentProps<"div">, "children"> {
82
+ editor: Editor | null;
83
+ children?: ToolbarSlot;
84
+ before?: ToolbarSlot;
85
+ after?: ToolbarSlot;
86
+ }
87
+ interface ToolbarButtonProps extends ComponentProps<"button"> {
88
+ icon?: ReactNode;
89
+ name: string;
90
+ shortcut?: string;
91
+ }
92
+ interface ToolbarToggleProps extends ToolbarButtonProps {
93
+ active: boolean;
94
+ }
95
+ interface ToolbarBlockSelectorItem {
96
+ name: string;
97
+ isActive: (editor: Editor) => boolean;
98
+ setActive: (editor: Editor) => void;
99
+ }
100
+ interface ToolbarBlockSelectorProps extends ComponentProps<"button"> {
101
+ items?: ToolbarBlockSelectorItem[];
102
+ }
103
+ declare function ToolbarSectionHistory(): react_jsx_runtime.JSX.Element;
104
+ declare function ToolbarSectionInline(): react_jsx_runtime.JSX.Element;
105
+ declare function ToolbarSectionCollaboration(): react_jsx_runtime.JSX.Element;
106
+ declare const Toolbar: react.ForwardRefExoticComponent<Omit<ToolbarProps, "ref"> & react.RefAttributes<HTMLDivElement>> & {
107
+ Button: react.ForwardRefExoticComponent<Omit<ToolbarButtonProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
108
+ Toggle: react.ForwardRefExoticComponent<Omit<ToolbarToggleProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
109
+ Separator: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
110
+ SectionHistory: typeof ToolbarSectionHistory;
111
+ SectionInline: typeof ToolbarSectionInline;
112
+ SectionCollaboration: typeof ToolbarSectionCollaboration;
113
+ BlockSelector: react.ForwardRefExoticComponent<Omit<ToolbarBlockSelectorProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
114
+ };
115
+
116
+ interface FloatingToolbarProps extends Omit<ComponentProps<"div">, "children"> {
117
+ editor: Editor | null;
118
+ position?: FloatingPosition;
119
+ offset?: number;
120
+ children?: ToolbarSlot;
121
+ before?: ToolbarSlot;
122
+ after?: ToolbarSlot;
123
+ }
124
+ declare const FloatingToolbar: react.ForwardRefExoticComponent<Omit<FloatingToolbarProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
125
+
67
126
  interface HistoryVersionPreviewProps extends ComponentPropsWithoutRef<"div"> {
68
127
  version: HistoryVersion;
69
128
  editor: Editor;
@@ -79,15 +138,8 @@ declare const HistoryVersionPreview: react.ForwardRefExoticComponent<HistoryVers
79
138
 
80
139
  declare module "@tiptap/core" {
81
140
  interface Commands<ReturnType> {
82
- comments: {
83
- /**
84
- * Add a comment
85
- */
86
- addComment: (id: string) => ReturnType;
87
- selectThread: (id: string | null) => ReturnType;
88
- addPendingComment: () => ReturnType;
89
- };
141
+ comments: CommentsCommands<ReturnType>;
90
142
  }
91
143
  }
92
144
 
93
- export { AnchoredThreads, FloatingComposer, FloatingThreads, HistoryVersionPreview, useIsEditorReady, useLiveblocksExtension };
145
+ export { AnchoredThreads, FloatingComposer, FloatingThreads, FloatingToolbar, HistoryVersionPreview, Toolbar, useIsEditorReady, useLiveblocksExtension };
package/dist/index.d.ts CHANGED
@@ -3,11 +3,21 @@ import { BaseMetadata, DM, ThreadData, HistoryVersion } from '@liveblocks/core';
3
3
  import { ThreadProps, ComposerProps } from '@liveblocks/react-ui';
4
4
  import { Editor } from '@tiptap/react';
5
5
  import * as react from 'react';
6
- import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } from 'react';
6
+ import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes, ComponentProps, ReactNode } from 'react';
7
7
  import { BaseMetadata as BaseMetadata$1 } from '@liveblocks/client';
8
8
  import { Extension, Content } from '@tiptap/core';
9
9
 
10
- declare type AnchoredThreadsComponents = {
10
+ type FloatingPosition = "top" | "bottom";
11
+ type CommentsCommands<ReturnType> = {
12
+ /**
13
+ * Add a comment
14
+ */
15
+ addComment: (id: string) => ReturnType;
16
+ selectThread: (id: string | null) => ReturnType;
17
+ addPendingComment: () => ReturnType;
18
+ };
19
+
20
+ type AnchoredThreadsComponents = {
11
21
  Thread: ComponentType<ThreadProps>;
12
22
  };
13
23
  interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
@@ -30,7 +40,7 @@ declare const FloatingComposer: react.ForwardRefExoticComponent<Omit<ComposerPro
30
40
  editor: Editor | null;
31
41
  } & react.RefAttributes<HTMLFormElement>>;
32
42
 
33
- declare type ThreadPanelComponents = {
43
+ type ThreadPanelComponents = {
34
44
  Thread: ComponentType<ThreadProps>;
35
45
  };
36
46
  interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
@@ -49,7 +59,7 @@ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAtt
49
59
  }
50
60
  declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): react_jsx_runtime.JSX.Element | null;
51
61
 
52
- declare type LiveblocksExtensionOptions = {
62
+ type LiveblocksExtensionOptions = {
53
63
  field?: string;
54
64
  comments?: boolean;
55
65
  mentions?: boolean;
@@ -64,6 +74,55 @@ declare type LiveblocksExtensionOptions = {
64
74
  declare function useIsEditorReady(): boolean;
65
75
  declare const useLiveblocksExtension: (opts?: LiveblocksExtensionOptions) => Extension;
66
76
 
77
+ interface ToolbarSlotProps {
78
+ editor: Editor;
79
+ }
80
+ type ToolbarSlot = ReactNode | ComponentType<ToolbarSlotProps>;
81
+ interface ToolbarProps extends Omit<ComponentProps<"div">, "children"> {
82
+ editor: Editor | null;
83
+ children?: ToolbarSlot;
84
+ before?: ToolbarSlot;
85
+ after?: ToolbarSlot;
86
+ }
87
+ interface ToolbarButtonProps extends ComponentProps<"button"> {
88
+ icon?: ReactNode;
89
+ name: string;
90
+ shortcut?: string;
91
+ }
92
+ interface ToolbarToggleProps extends ToolbarButtonProps {
93
+ active: boolean;
94
+ }
95
+ interface ToolbarBlockSelectorItem {
96
+ name: string;
97
+ isActive: (editor: Editor) => boolean;
98
+ setActive: (editor: Editor) => void;
99
+ }
100
+ interface ToolbarBlockSelectorProps extends ComponentProps<"button"> {
101
+ items?: ToolbarBlockSelectorItem[];
102
+ }
103
+ declare function ToolbarSectionHistory(): react_jsx_runtime.JSX.Element;
104
+ declare function ToolbarSectionInline(): react_jsx_runtime.JSX.Element;
105
+ declare function ToolbarSectionCollaboration(): react_jsx_runtime.JSX.Element;
106
+ declare const Toolbar: react.ForwardRefExoticComponent<Omit<ToolbarProps, "ref"> & react.RefAttributes<HTMLDivElement>> & {
107
+ Button: react.ForwardRefExoticComponent<Omit<ToolbarButtonProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
108
+ Toggle: react.ForwardRefExoticComponent<Omit<ToolbarToggleProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
109
+ Separator: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & react.RefAttributes<HTMLDivElement>>;
110
+ SectionHistory: typeof ToolbarSectionHistory;
111
+ SectionInline: typeof ToolbarSectionInline;
112
+ SectionCollaboration: typeof ToolbarSectionCollaboration;
113
+ BlockSelector: react.ForwardRefExoticComponent<Omit<ToolbarBlockSelectorProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
114
+ };
115
+
116
+ interface FloatingToolbarProps extends Omit<ComponentProps<"div">, "children"> {
117
+ editor: Editor | null;
118
+ position?: FloatingPosition;
119
+ offset?: number;
120
+ children?: ToolbarSlot;
121
+ before?: ToolbarSlot;
122
+ after?: ToolbarSlot;
123
+ }
124
+ declare const FloatingToolbar: react.ForwardRefExoticComponent<Omit<FloatingToolbarProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
125
+
67
126
  interface HistoryVersionPreviewProps extends ComponentPropsWithoutRef<"div"> {
68
127
  version: HistoryVersion;
69
128
  editor: Editor;
@@ -79,15 +138,8 @@ declare const HistoryVersionPreview: react.ForwardRefExoticComponent<HistoryVers
79
138
 
80
139
  declare module "@tiptap/core" {
81
140
  interface Commands<ReturnType> {
82
- comments: {
83
- /**
84
- * Add a comment
85
- */
86
- addComment: (id: string) => ReturnType;
87
- selectThread: (id: string | null) => ReturnType;
88
- addPendingComment: () => ReturnType;
89
- };
141
+ comments: CommentsCommands<ReturnType>;
90
142
  }
91
143
  }
92
144
 
93
- export { AnchoredThreads, FloatingComposer, FloatingThreads, HistoryVersionPreview, useIsEditorReady, useLiveblocksExtension };
145
+ export { AnchoredThreads, FloatingComposer, FloatingThreads, FloatingToolbar, HistoryVersionPreview, Toolbar, useIsEditorReady, useLiveblocksExtension };
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ var AnchoredThreads = require('./comments/AnchoredThreads.js');
6
6
  var FloatingComposer = require('./comments/FloatingComposer.js');
7
7
  var FloatingThreads = require('./comments/FloatingThreads.js');
8
8
  var LiveblocksExtension = require('./LiveblocksExtension.js');
9
+ var FloatingToolbar = require('./toolbar/FloatingToolbar.js');
10
+ var Toolbar = require('./toolbar/Toolbar.js');
9
11
  var HistoryVersionPreview = require('./version-history/HistoryVersionPreview.js');
10
12
 
11
13
  core.detectDupes(version.PKG_NAME, version.PKG_VERSION, version.PKG_FORMAT);
@@ -15,5 +17,7 @@ exports.FloatingComposer = FloatingComposer.FloatingComposer;
15
17
  exports.FloatingThreads = FloatingThreads.FloatingThreads;
16
18
  exports.useIsEditorReady = LiveblocksExtension.useIsEditorReady;
17
19
  exports.useLiveblocksExtension = LiveblocksExtension.useLiveblocksExtension;
20
+ exports.FloatingToolbar = FloatingToolbar.FloatingToolbar;
21
+ exports.Toolbar = Toolbar.Toolbar;
18
22
  exports.HistoryVersionPreview = HistoryVersionPreview.HistoryVersionPreview;
19
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { useIsEditorReady } from \"./LiveblocksExtension\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n comments: {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n };\n }\n}\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;;;;AAIAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport type { CommentsCommands } from \"./types\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { useIsEditorReady } from \"./LiveblocksExtension\";\nexport { FloatingToolbar } from \"./toolbar/FloatingToolbar\";\nexport { Toolbar } from \"./toolbar/Toolbar\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n comments: CommentsCommands<ReturnType>;\n }\n}\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;;;;;;AAKAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -4,6 +4,8 @@ export { AnchoredThreads } from './comments/AnchoredThreads.mjs';
4
4
  export { FloatingComposer } from './comments/FloatingComposer.mjs';
5
5
  export { FloatingThreads } from './comments/FloatingThreads.mjs';
6
6
  export { useIsEditorReady, useLiveblocksExtension } from './LiveblocksExtension.mjs';
7
+ export { FloatingToolbar } from './toolbar/FloatingToolbar.mjs';
8
+ export { Toolbar } from './toolbar/Toolbar.mjs';
7
9
  export { HistoryVersionPreview } from './version-history/HistoryVersionPreview.mjs';
8
10
 
9
11
  detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { useIsEditorReady } from \"./LiveblocksExtension\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n comments: {\n /**\n * Add a comment\n */\n addComment: (id: string) => ReturnType;\n selectThread: (id: string | null) => ReturnType;\n addPendingComment: () => ReturnType;\n };\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAIA,WAAY,CAAA,QAAA,EAAU,aAAa,UAAU,CAAA"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport type { CommentsCommands } from \"./types\";\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { useIsEditorReady } from \"./LiveblocksExtension\";\nexport { FloatingToolbar } from \"./toolbar/FloatingToolbar\";\nexport { Toolbar } from \"./toolbar/Toolbar\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n comments: CommentsCommands<ReturnType>;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;AAKA,WAAY,CAAA,QAAA,EAAU,aAAa,UAAU,CAAA"}
@@ -25,118 +25,128 @@ const User = react.forwardRef(
25
25
  }
26
26
  );
27
27
  const SUGGESTIONS_COLLISION_PADDING = 10;
28
- const MentionsList = react.forwardRef((props, ref) => {
29
- const [selectedIndex, setSelectedIndex] = react.useState(0);
30
- const room = react$1.useRoom();
31
- const suggestions = _private.useMentionSuggestions(room.id, props.query);
32
- const { onMouseEnter, onClick } = props;
33
- const {
34
- refs: { setReference, setFloating },
35
- strategy,
36
- x,
37
- y
38
- } = reactDom.useFloating({
39
- strategy: "fixed",
40
- placement: "top-start",
41
- middleware: [
42
- reactDom.flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
43
- reactDom.offset(10),
44
- reactDom.hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
45
- reactDom.shift({ padding: SUGGESTIONS_COLLISION_PADDING, limiter: reactDom.limitShift() }),
46
- reactDom.size({ padding: SUGGESTIONS_COLLISION_PADDING })
47
- ],
48
- whileElementsMounted: (...args) => {
49
- return reactDom.autoUpdate(...args, {
50
- animationFrame: true
51
- });
52
- }
53
- });
54
- react.useLayoutEffect(() => {
55
- setReference({
56
- getBoundingClientRect: props.clientRect
57
- });
58
- }, [setReference, props.clientRect]);
59
- const selectItem = (index) => {
60
- const item = (suggestions ?? [])[index];
61
- if (item) {
62
- props.command({ id: item, notificationId: core.createInboxNotificationId() });
63
- }
64
- };
65
- const upHandler = () => {
66
- setSelectedIndex((selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0));
67
- };
68
- const downHandler = () => {
69
- setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
70
- };
71
- const enterHandler = () => {
72
- selectItem(selectedIndex);
73
- };
74
- react.useEffect(() => setSelectedIndex(0), [suggestions]);
75
- react.useImperativeHandle(ref, () => ({
76
- onKeyDown: ({ event }) => {
77
- if (event.key === "ArrowUp") {
78
- upHandler();
79
- return true;
28
+ const MentionsList = react.forwardRef(
29
+ (props, ref) => {
30
+ const [selectedIndex, setSelectedIndex] = react.useState(0);
31
+ const room = react$1.useRoom();
32
+ const suggestions = _private.useMentionSuggestions(room.id, props.query);
33
+ const { onMouseEnter, onClick } = props;
34
+ const {
35
+ refs: { setReference, setFloating },
36
+ strategy,
37
+ x,
38
+ y
39
+ } = reactDom.useFloating({
40
+ strategy: "fixed",
41
+ placement: "top-start",
42
+ middleware: [
43
+ reactDom.flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
44
+ reactDom.offset(10),
45
+ reactDom.hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
46
+ reactDom.shift({
47
+ padding: SUGGESTIONS_COLLISION_PADDING,
48
+ limiter: reactDom.limitShift()
49
+ }),
50
+ reactDom.size({ padding: SUGGESTIONS_COLLISION_PADDING })
51
+ ],
52
+ whileElementsMounted: (...args) => {
53
+ return reactDom.autoUpdate(...args, {
54
+ animationFrame: true
55
+ });
80
56
  }
81
- if (event.key === "ArrowDown") {
82
- downHandler();
83
- return true;
57
+ });
58
+ _private.useLayoutEffect(() => {
59
+ setReference({
60
+ getBoundingClientRect: props.clientRect
61
+ });
62
+ }, [setReference, props.clientRect]);
63
+ const selectItem = (index) => {
64
+ const item = (suggestions ?? [])[index];
65
+ if (item) {
66
+ props.command({
67
+ id: item,
68
+ notificationId: core.createInboxNotificationId()
69
+ });
84
70
  }
85
- if (event.key === "Enter") {
86
- enterHandler();
87
- return true;
71
+ };
72
+ const upHandler = () => {
73
+ setSelectedIndex(
74
+ (selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0)
75
+ );
76
+ };
77
+ const downHandler = () => {
78
+ setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
79
+ };
80
+ const enterHandler = () => {
81
+ selectItem(selectedIndex);
82
+ };
83
+ react.useEffect(() => setSelectedIndex(0), [suggestions]);
84
+ react.useImperativeHandle(ref, () => ({
85
+ onKeyDown: ({ event }) => {
86
+ if (event.key === "ArrowUp") {
87
+ upHandler();
88
+ return true;
89
+ }
90
+ if (event.key === "ArrowDown") {
91
+ downHandler();
92
+ return true;
93
+ }
94
+ if (event.key === "Enter") {
95
+ enterHandler();
96
+ return true;
97
+ }
98
+ return false;
88
99
  }
89
- return false;
100
+ }));
101
+ const handleClick = (index) => (event) => {
102
+ onClick?.(event);
103
+ if (event.isDefaultPrevented())
104
+ return;
105
+ selectItem(index);
106
+ };
107
+ const handleMouseEnter = (index) => (event) => {
108
+ onMouseEnter?.(event);
109
+ if (event.isDefaultPrevented())
110
+ return;
111
+ setSelectedIndex(index);
112
+ };
113
+ if (suggestions === void 0 || suggestions.length === 0) {
114
+ return null;
90
115
  }
91
- }));
92
- const handleClick = (index) => (event) => {
93
- onClick?.(event);
94
- if (event.isDefaultPrevented())
95
- return;
96
- selectItem(index);
97
- };
98
- const handleMouseEnter = (index) => (event) => {
99
- onMouseEnter?.(event);
100
- if (event.isDefaultPrevented())
101
- return;
102
- setSelectedIndex(index);
103
- };
104
- if (suggestions === void 0 || suggestions.length === 0) {
105
- return null;
116
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
117
+ className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
118
+ ref: setFloating,
119
+ style: {
120
+ position: strategy,
121
+ top: 0,
122
+ left: 0,
123
+ transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
124
+ minWidth: "max-content",
125
+ display: props.hide ? "none" : "block"
126
+ },
127
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", {
128
+ className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list",
129
+ children: suggestions.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", {
130
+ className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
131
+ role: "option",
132
+ "data-highlighted": index === selectedIndex || void 0,
133
+ onMouseEnter: handleMouseEnter(index),
134
+ onClick: handleClick(index),
135
+ children: [
136
+ /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, {
137
+ userId: item,
138
+ className: "lb-tiptap-mention-suggestion-avatar"
139
+ }),
140
+ /* @__PURE__ */ jsxRuntime.jsx(User, {
141
+ userId: item,
142
+ className: "lb-tiptap-mention-suggestion-user"
143
+ })
144
+ ]
145
+ }, index))
146
+ })
147
+ });
106
148
  }
107
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
108
- className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
109
- ref: setFloating,
110
- style: {
111
- position: strategy,
112
- top: 0,
113
- left: 0,
114
- transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
115
- minWidth: "max-content",
116
- display: props.hide ? "none" : "block"
117
- },
118
- children: /* @__PURE__ */ jsxRuntime.jsx("div", {
119
- className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list",
120
- children: suggestions.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", {
121
- className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
122
- role: "option",
123
- "data-highlighted": index === selectedIndex || void 0,
124
- onMouseEnter: handleMouseEnter(index),
125
- onClick: handleClick(index),
126
- children: [
127
- /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, {
128
- userId: item,
129
- className: "lb-tiptap-mention-suggestion-avatar"
130
- }),
131
- /* @__PURE__ */ jsxRuntime.jsx(User, {
132
- userId: item,
133
- className: "lb-tiptap-mention-suggestion-user"
134
- })
135
- ]
136
- }, index))
137
- })
138
- });
139
- });
149
+ );
140
150
 
141
151
  exports.MentionsList = MentionsList;
142
152
  exports.SUGGESTIONS_COLLISION_PADDING = SUGGESTIONS_COLLISION_PADDING;