@liveblocks/react-tiptap 2.15.1 → 2.16.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"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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"}
package/dist/index.d.mts CHANGED
@@ -7,7 +7,7 @@ import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } 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 AnchoredThreadsComponents = {
11
11
  Thread: ComponentType<ThreadProps>;
12
12
  };
13
13
  interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
@@ -30,7 +30,7 @@ declare const FloatingComposer: react.ForwardRefExoticComponent<Omit<ComposerPro
30
30
  editor: Editor | null;
31
31
  } & react.RefAttributes<HTMLFormElement>>;
32
32
 
33
- declare type ThreadPanelComponents = {
33
+ type ThreadPanelComponents = {
34
34
  Thread: ComponentType<ThreadProps>;
35
35
  };
36
36
  interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
@@ -49,7 +49,7 @@ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAtt
49
49
  }
50
50
  declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): react_jsx_runtime.JSX.Element | null;
51
51
 
52
- declare type LiveblocksExtensionOptions = {
52
+ type LiveblocksExtensionOptions = {
53
53
  field?: string;
54
54
  comments?: boolean;
55
55
  mentions?: boolean;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ import { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } 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 AnchoredThreadsComponents = {
11
11
  Thread: ComponentType<ThreadProps>;
12
12
  };
13
13
  interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
@@ -30,7 +30,7 @@ declare const FloatingComposer: react.ForwardRefExoticComponent<Omit<ComposerPro
30
30
  editor: Editor | null;
31
31
  } & react.RefAttributes<HTMLFormElement>>;
32
32
 
33
- declare type ThreadPanelComponents = {
33
+ type ThreadPanelComponents = {
34
34
  Thread: ComponentType<ThreadProps>;
35
35
  };
36
36
  interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
@@ -49,7 +49,7 @@ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAtt
49
49
  }
50
50
  declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): react_jsx_runtime.JSX.Element | null;
51
51
 
52
- declare type LiveblocksExtensionOptions = {
52
+ type LiveblocksExtensionOptions = {
53
53
  field?: string;
54
54
  comments?: boolean;
55
55
  mentions?: boolean;
@@ -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;
@@ -1 +1 @@
1
- {"version":3,"file":"MentionsList.js","sources":["../../src/mentions/MentionsList.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 { createInboxNotificationId } from \"@liveblocks/core\";\nimport { useRoom, useUser } from \"@liveblocks/react\";\nimport { useMentionSuggestions } from \"@liveblocks/react/_private\";\nimport { useOverrides } from \"@liveblocks/react-ui\";\nimport type { HTMLAttributes, MouseEvent } from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useState,\n} from \"react\";\n\nimport { Avatar } from \"./Avatar\";\n\nexport interface UserProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n userId: string;\n}\n\nexport const User = forwardRef<HTMLSpanElement, UserProps>(\n function User(props, forwardedRef) {\n const { userId, className, ...spanProps } = props;\n\n const { user, isLoading } = useUser(userId);\n const $ = useOverrides();\n\n const name =\n user === undefined || user === null ? $.USER_UNKNOWN : user.name;\n\n return (\n <span\n className={className}\n data-loading={isLoading ? \"\" : undefined}\n ref={forwardedRef}\n {...spanProps}\n >\n {isLoading ? null : name}\n </span>\n );\n }\n);\n\n\nexport const SUGGESTIONS_COLLISION_PADDING = 10;\n\nexport interface MentionsListProps extends HTMLAttributes<HTMLDivElement> {\n query: string,\n command: (otps: { id: string, notificationId: string }) => void,\n clientRect: () => DOMRect,\n hide: boolean\n}\n\nexport type MentionsListHandle = {\n onKeyDown: ({ event }: { event: KeyboardEvent }) => boolean,\n};\n\nexport const MentionsList = forwardRef<MentionsListHandle, MentionsListProps>((props, ref) => {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const room = useRoom();\n const suggestions = useMentionSuggestions(room.id, props.query);\n const { onMouseEnter, onClick } = props;\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"top-start\",\n middleware: [\n flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),\n offset(10),\n hide({ padding: SUGGESTIONS_COLLISION_PADDING }),\n shift({ padding: SUGGESTIONS_COLLISION_PADDING, limiter: limitShift() }),\n size({ padding: SUGGESTIONS_COLLISION_PADDING }),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n useLayoutEffect(() => {\n setReference({\n getBoundingClientRect: props.clientRect,\n });\n }, [setReference, props.clientRect]);\n\n const selectItem = (index: number) => {\n const item = (suggestions ?? [])[index];\n if (item) {\n props.command({ id: item, notificationId: createInboxNotificationId() });\n }\n }\n\n const upHandler = () => {\n setSelectedIndex((selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0))\n }\n\n const downHandler = () => {\n setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0))\n }\n\n const enterHandler = () => {\n selectItem(selectedIndex)\n }\n\n useEffect(() => setSelectedIndex(0), [suggestions])\n\n useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n if (event.key === \"ArrowUp\") {\n upHandler()\n return true\n }\n\n if (event.key === \"ArrowDown\") {\n downHandler()\n return true\n }\n\n if (event.key === \"Enter\") {\n enterHandler()\n return true\n }\n\n return false\n },\n }))\n\n const handleClick = (index: number) => (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n\n if (event.isDefaultPrevented()) return;\n selectItem(index)\n }\n const handleMouseEnter = (index: number) => (event: MouseEvent<HTMLDivElement>) => {\n onMouseEnter?.(event);\n\n if (event.isDefaultPrevented()) return;\n\n setSelectedIndex(index);\n }\n\n if (suggestions === undefined || suggestions.length === 0) {\n return null\n }\n\n return (\n <div className=\"lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions\" ref={setFloating}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n display: props.hide ? \"none\" : \"block\"\n }}>\n <div className=\"lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list\">\n {suggestions.map((item, index) => (\n <div className=\"lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion\"\n key={index}\n role=\"option\"\n data-highlighted={index === selectedIndex || undefined}\n\n onMouseEnter={handleMouseEnter(index)}\n onClick={handleClick(index)}>\n <Avatar\n userId={item}\n className=\"lb-tiptap-mention-suggestion-avatar\"\n />\n <User\n userId={item}\n className=\"lb-tiptap-mention-suggestion-user\"\n />\n </div>\n ))\n }\n </div>\n </div>\n )\n})"],"names":["forwardRef","User","useUser","useOverrides","jsx","useState","useRoom","useMentionSuggestions","useFloating","flip","offset","hide","shift","limitShift","size","autoUpdate","useLayoutEffect","createInboxNotificationId","useEffect","useImperativeHandle","jsxs","Avatar"],"mappings":"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"}
1
+ {"version":3,"file":"MentionsList.js","sources":["../../src/mentions/MentionsList.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 { createInboxNotificationId } from \"@liveblocks/core\";\nimport { useRoom, useUser } from \"@liveblocks/react\";\nimport {\n useLayoutEffect,\n useMentionSuggestions,\n} from \"@liveblocks/react/_private\";\nimport { useOverrides } from \"@liveblocks/react-ui\";\nimport type { HTMLAttributes, MouseEvent } from \"react\";\nimport { forwardRef, useEffect, useImperativeHandle, useState } from \"react\";\n\nimport { Avatar } from \"./Avatar\";\n\nexport interface UserProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n userId: string;\n}\n\nexport const User = forwardRef<HTMLSpanElement, UserProps>(\n function User(props, forwardedRef) {\n const { userId, className, ...spanProps } = props;\n\n const { user, isLoading } = useUser(userId);\n const $ = useOverrides();\n\n const name =\n user === undefined || user === null ? $.USER_UNKNOWN : user.name;\n\n return (\n <span\n className={className}\n data-loading={isLoading ? \"\" : undefined}\n ref={forwardedRef}\n {...spanProps}\n >\n {isLoading ? null : name}\n </span>\n );\n }\n);\n\nexport const SUGGESTIONS_COLLISION_PADDING = 10;\n\nexport interface MentionsListProps extends HTMLAttributes<HTMLDivElement> {\n query: string;\n command: (otps: { id: string; notificationId: string }) => void;\n clientRect: () => DOMRect;\n hide: boolean;\n}\n\nexport type MentionsListHandle = {\n onKeyDown: ({ event }: { event: KeyboardEvent }) => boolean;\n};\n\nexport const MentionsList = forwardRef<MentionsListHandle, MentionsListProps>(\n (props, ref) => {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const room = useRoom();\n const suggestions = useMentionSuggestions(room.id, props.query);\n const { onMouseEnter, onClick } = props;\n const {\n refs: { setReference, setFloating },\n strategy,\n x,\n y,\n } = useFloating({\n strategy: \"fixed\",\n placement: \"top-start\",\n middleware: [\n flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),\n offset(10),\n hide({ padding: SUGGESTIONS_COLLISION_PADDING }),\n shift({\n padding: SUGGESTIONS_COLLISION_PADDING,\n limiter: limitShift(),\n }),\n size({ padding: SUGGESTIONS_COLLISION_PADDING }),\n ],\n whileElementsMounted: (...args) => {\n return autoUpdate(...args, {\n animationFrame: true,\n });\n },\n });\n\n useLayoutEffect(() => {\n setReference({\n getBoundingClientRect: props.clientRect,\n });\n }, [setReference, props.clientRect]);\n\n const selectItem = (index: number) => {\n const item = (suggestions ?? [])[index];\n if (item) {\n props.command({\n id: item,\n notificationId: createInboxNotificationId(),\n });\n }\n };\n\n const upHandler = () => {\n setSelectedIndex(\n (selectedIndex + (suggestions?.length ?? 0) - 1) %\n (suggestions?.length ?? 0)\n );\n };\n\n const downHandler = () => {\n setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));\n };\n\n const enterHandler = () => {\n selectItem(selectedIndex);\n };\n\n useEffect(() => setSelectedIndex(0), [suggestions]);\n\n useImperativeHandle(ref, () => ({\n onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n if (event.key === \"ArrowUp\") {\n upHandler();\n return true;\n }\n\n if (event.key === \"ArrowDown\") {\n downHandler();\n return true;\n }\n\n if (event.key === \"Enter\") {\n enterHandler();\n return true;\n }\n\n return false;\n },\n }));\n\n const handleClick =\n (index: number) => (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n\n if (event.isDefaultPrevented()) return;\n selectItem(index);\n };\n const handleMouseEnter =\n (index: number) => (event: MouseEvent<HTMLDivElement>) => {\n onMouseEnter?.(event);\n\n if (event.isDefaultPrevented()) return;\n\n setSelectedIndex(index);\n };\n\n if (suggestions === undefined || suggestions.length === 0) {\n return null;\n }\n\n return (\n <div\n className=\"lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions\"\n ref={setFloating}\n style={{\n position: strategy,\n top: 0,\n left: 0,\n transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,\n minWidth: \"max-content\",\n display: props.hide ? \"none\" : \"block\",\n }}\n >\n <div className=\"lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list\">\n {suggestions.map((item, index) => (\n <div\n className=\"lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion\"\n key={index}\n role=\"option\"\n data-highlighted={index === selectedIndex || undefined}\n onMouseEnter={handleMouseEnter(index)}\n onClick={handleClick(index)}\n >\n <Avatar\n userId={item}\n className=\"lb-tiptap-mention-suggestion-avatar\"\n />\n <User\n userId={item}\n className=\"lb-tiptap-mention-suggestion-user\"\n />\n </div>\n ))}\n </div>\n </div>\n );\n }\n);\n"],"names":["forwardRef","User","useUser","useOverrides","jsx","useState","useRoom","useMentionSuggestions","useFloating","flip","offset","hide","shift","limitShift","size","autoUpdate","useLayoutEffect","createInboxNotificationId","useEffect","useImperativeHandle","jsxs","Avatar"],"mappings":"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"}
@@ -2,9 +2,9 @@ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useFloating, flip, offset, hide, shift, limitShift, size, autoUpdate } from '@floating-ui/react-dom';
3
3
  import { createInboxNotificationId } from '@liveblocks/core';
4
4
  import { useUser, useRoom } from '@liveblocks/react';
5
- import { useMentionSuggestions } from '@liveblocks/react/_private';
5
+ import { useMentionSuggestions, useLayoutEffect } from '@liveblocks/react/_private';
6
6
  import { useOverrides } from '@liveblocks/react-ui';
7
- import { forwardRef, useState, useLayoutEffect, useEffect, useImperativeHandle } from 'react';
7
+ import { forwardRef, useState, useEffect, useImperativeHandle } from 'react';
8
8
  import { Avatar } from './Avatar.mjs';
9
9
 
10
10
  const User = forwardRef(
@@ -23,118 +23,128 @@ const User = forwardRef(
23
23
  }
24
24
  );
25
25
  const SUGGESTIONS_COLLISION_PADDING = 10;
26
- const MentionsList = forwardRef((props, ref) => {
27
- const [selectedIndex, setSelectedIndex] = useState(0);
28
- const room = useRoom();
29
- const suggestions = useMentionSuggestions(room.id, props.query);
30
- const { onMouseEnter, onClick } = props;
31
- const {
32
- refs: { setReference, setFloating },
33
- strategy,
34
- x,
35
- y
36
- } = useFloating({
37
- strategy: "fixed",
38
- placement: "top-start",
39
- middleware: [
40
- flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
41
- offset(10),
42
- hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
43
- shift({ padding: SUGGESTIONS_COLLISION_PADDING, limiter: limitShift() }),
44
- size({ padding: SUGGESTIONS_COLLISION_PADDING })
45
- ],
46
- whileElementsMounted: (...args) => {
47
- return autoUpdate(...args, {
48
- animationFrame: true
49
- });
50
- }
51
- });
52
- useLayoutEffect(() => {
53
- setReference({
54
- getBoundingClientRect: props.clientRect
55
- });
56
- }, [setReference, props.clientRect]);
57
- const selectItem = (index) => {
58
- const item = (suggestions ?? [])[index];
59
- if (item) {
60
- props.command({ id: item, notificationId: createInboxNotificationId() });
61
- }
62
- };
63
- const upHandler = () => {
64
- setSelectedIndex((selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0));
65
- };
66
- const downHandler = () => {
67
- setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
68
- };
69
- const enterHandler = () => {
70
- selectItem(selectedIndex);
71
- };
72
- useEffect(() => setSelectedIndex(0), [suggestions]);
73
- useImperativeHandle(ref, () => ({
74
- onKeyDown: ({ event }) => {
75
- if (event.key === "ArrowUp") {
76
- upHandler();
77
- return true;
26
+ const MentionsList = forwardRef(
27
+ (props, ref) => {
28
+ const [selectedIndex, setSelectedIndex] = useState(0);
29
+ const room = useRoom();
30
+ const suggestions = useMentionSuggestions(room.id, props.query);
31
+ const { onMouseEnter, onClick } = props;
32
+ const {
33
+ refs: { setReference, setFloating },
34
+ strategy,
35
+ x,
36
+ y
37
+ } = useFloating({
38
+ strategy: "fixed",
39
+ placement: "top-start",
40
+ middleware: [
41
+ flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
42
+ offset(10),
43
+ hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
44
+ shift({
45
+ padding: SUGGESTIONS_COLLISION_PADDING,
46
+ limiter: limitShift()
47
+ }),
48
+ size({ padding: SUGGESTIONS_COLLISION_PADDING })
49
+ ],
50
+ whileElementsMounted: (...args) => {
51
+ return autoUpdate(...args, {
52
+ animationFrame: true
53
+ });
78
54
  }
79
- if (event.key === "ArrowDown") {
80
- downHandler();
81
- return true;
55
+ });
56
+ useLayoutEffect(() => {
57
+ setReference({
58
+ getBoundingClientRect: props.clientRect
59
+ });
60
+ }, [setReference, props.clientRect]);
61
+ const selectItem = (index) => {
62
+ const item = (suggestions ?? [])[index];
63
+ if (item) {
64
+ props.command({
65
+ id: item,
66
+ notificationId: createInboxNotificationId()
67
+ });
82
68
  }
83
- if (event.key === "Enter") {
84
- enterHandler();
85
- return true;
69
+ };
70
+ const upHandler = () => {
71
+ setSelectedIndex(
72
+ (selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0)
73
+ );
74
+ };
75
+ const downHandler = () => {
76
+ setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
77
+ };
78
+ const enterHandler = () => {
79
+ selectItem(selectedIndex);
80
+ };
81
+ useEffect(() => setSelectedIndex(0), [suggestions]);
82
+ useImperativeHandle(ref, () => ({
83
+ onKeyDown: ({ event }) => {
84
+ if (event.key === "ArrowUp") {
85
+ upHandler();
86
+ return true;
87
+ }
88
+ if (event.key === "ArrowDown") {
89
+ downHandler();
90
+ return true;
91
+ }
92
+ if (event.key === "Enter") {
93
+ enterHandler();
94
+ return true;
95
+ }
96
+ return false;
86
97
  }
87
- return false;
98
+ }));
99
+ const handleClick = (index) => (event) => {
100
+ onClick?.(event);
101
+ if (event.isDefaultPrevented())
102
+ return;
103
+ selectItem(index);
104
+ };
105
+ const handleMouseEnter = (index) => (event) => {
106
+ onMouseEnter?.(event);
107
+ if (event.isDefaultPrevented())
108
+ return;
109
+ setSelectedIndex(index);
110
+ };
111
+ if (suggestions === void 0 || suggestions.length === 0) {
112
+ return null;
88
113
  }
89
- }));
90
- const handleClick = (index) => (event) => {
91
- onClick?.(event);
92
- if (event.isDefaultPrevented())
93
- return;
94
- selectItem(index);
95
- };
96
- const handleMouseEnter = (index) => (event) => {
97
- onMouseEnter?.(event);
98
- if (event.isDefaultPrevented())
99
- return;
100
- setSelectedIndex(index);
101
- };
102
- if (suggestions === void 0 || suggestions.length === 0) {
103
- return null;
114
+ return /* @__PURE__ */ jsx("div", {
115
+ className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
116
+ ref: setFloating,
117
+ style: {
118
+ position: strategy,
119
+ top: 0,
120
+ left: 0,
121
+ transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
122
+ minWidth: "max-content",
123
+ display: props.hide ? "none" : "block"
124
+ },
125
+ children: /* @__PURE__ */ jsx("div", {
126
+ className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list",
127
+ children: suggestions.map((item, index) => /* @__PURE__ */ jsxs("div", {
128
+ className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
129
+ role: "option",
130
+ "data-highlighted": index === selectedIndex || void 0,
131
+ onMouseEnter: handleMouseEnter(index),
132
+ onClick: handleClick(index),
133
+ children: [
134
+ /* @__PURE__ */ jsx(Avatar, {
135
+ userId: item,
136
+ className: "lb-tiptap-mention-suggestion-avatar"
137
+ }),
138
+ /* @__PURE__ */ jsx(User, {
139
+ userId: item,
140
+ className: "lb-tiptap-mention-suggestion-user"
141
+ })
142
+ ]
143
+ }, index))
144
+ })
145
+ });
104
146
  }
105
- return /* @__PURE__ */ jsx("div", {
106
- className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
107
- ref: setFloating,
108
- style: {
109
- position: strategy,
110
- top: 0,
111
- left: 0,
112
- transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
113
- minWidth: "max-content",
114
- display: props.hide ? "none" : "block"
115
- },
116
- children: /* @__PURE__ */ jsx("div", {
117
- className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list",
118
- children: suggestions.map((item, index) => /* @__PURE__ */ jsxs("div", {
119
- className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
120
- role: "option",
121
- "data-highlighted": index === selectedIndex || void 0,
122
- onMouseEnter: handleMouseEnter(index),
123
- onClick: handleClick(index),
124
- children: [
125
- /* @__PURE__ */ jsx(Avatar, {
126
- userId: item,
127
- className: "lb-tiptap-mention-suggestion-avatar"
128
- }),
129
- /* @__PURE__ */ jsx(User, {
130
- userId: item,
131
- className: "lb-tiptap-mention-suggestion-user"
132
- })
133
- ]
134
- }, index))
135
- })
136
- });
137
- });
147
+ );
138
148
 
139
149
  export { MentionsList, SUGGESTIONS_COLLISION_PADDING, User };
140
150
  //# sourceMappingURL=MentionsList.mjs.map