@liveblocks/react-tiptap 0.0.1 → 2.8.3-tiptap1

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 (69) hide show
  1. package/dist/LiveblocksExtension.js +144 -0
  2. package/dist/LiveblocksExtension.js.map +1 -0
  3. package/dist/LiveblocksExtension.mjs +142 -0
  4. package/dist/LiveblocksExtension.mjs.map +1 -0
  5. package/dist/classnames.js +8 -0
  6. package/dist/classnames.js.map +1 -0
  7. package/dist/classnames.mjs +6 -0
  8. package/dist/classnames.mjs.map +1 -0
  9. package/dist/comments/AnchoredThreads.js +178 -0
  10. package/dist/comments/AnchoredThreads.js.map +1 -0
  11. package/dist/comments/AnchoredThreads.mjs +176 -0
  12. package/dist/comments/AnchoredThreads.mjs.map +1 -0
  13. package/dist/comments/CommentsExtension.js +207 -0
  14. package/dist/comments/CommentsExtension.js.map +1 -0
  15. package/dist/comments/CommentsExtension.mjs +205 -0
  16. package/dist/comments/CommentsExtension.mjs.map +1 -0
  17. package/dist/comments/FloatingComposer.js +103 -0
  18. package/dist/comments/FloatingComposer.js.map +1 -0
  19. package/dist/comments/FloatingComposer.mjs +100 -0
  20. package/dist/comments/FloatingComposer.mjs.map +1 -0
  21. package/dist/comments/FloatingThreads.js +154 -0
  22. package/dist/comments/FloatingThreads.js.map +1 -0
  23. package/dist/comments/FloatingThreads.mjs +151 -0
  24. package/dist/comments/FloatingThreads.mjs.map +1 -0
  25. package/dist/index.d.mts +65 -0
  26. package/dist/index.d.ts +65 -0
  27. package/dist/index.js +18 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/index.mjs +10 -0
  30. package/dist/index.mjs.map +1 -0
  31. package/dist/mentions/Avatar.js +53 -0
  32. package/dist/mentions/Avatar.js.map +1 -0
  33. package/dist/mentions/Avatar.mjs +51 -0
  34. package/dist/mentions/Avatar.mjs.map +1 -0
  35. package/dist/mentions/Mention.js +24 -0
  36. package/dist/mentions/Mention.js.map +1 -0
  37. package/dist/mentions/Mention.mjs +22 -0
  38. package/dist/mentions/Mention.mjs.map +1 -0
  39. package/dist/mentions/MentionExtension.js +221 -0
  40. package/dist/mentions/MentionExtension.js.map +1 -0
  41. package/dist/mentions/MentionExtension.mjs +219 -0
  42. package/dist/mentions/MentionExtension.mjs.map +1 -0
  43. package/dist/mentions/MentionsList.js +123 -0
  44. package/dist/mentions/MentionsList.js.map +1 -0
  45. package/dist/mentions/MentionsList.mjs +119 -0
  46. package/dist/mentions/MentionsList.mjs.map +1 -0
  47. package/dist/types.js +33 -0
  48. package/dist/types.js.map +1 -0
  49. package/dist/types.mjs +24 -0
  50. package/dist/types.mjs.map +1 -0
  51. package/dist/utils.js +47 -0
  52. package/dist/utils.js.map +1 -0
  53. package/dist/utils.mjs +43 -0
  54. package/dist/utils.mjs.map +1 -0
  55. package/dist/version-history/HistoryVersionPreview.js +79 -0
  56. package/dist/version-history/HistoryVersionPreview.js.map +1 -0
  57. package/dist/version-history/HistoryVersionPreview.mjs +77 -0
  58. package/dist/version-history/HistoryVersionPreview.mjs.map +1 -0
  59. package/dist/version.js +10 -0
  60. package/dist/version.js.map +1 -0
  61. package/dist/version.mjs +6 -0
  62. package/dist/version.mjs.map +1 -0
  63. package/package.json +77 -1
  64. package/src/styles/constants.css +9 -0
  65. package/src/styles/index.css +247 -0
  66. package/src/styles/utils.css +6 -0
  67. package/styles.css +1 -0
  68. package/styles.css.d.ts +1 -0
  69. package/styles.css.map +1 -0
@@ -0,0 +1,219 @@
1
+ import { createInboxNotificationId } from '@liveblocks/core';
2
+ import { combineTransactionSteps, getChangedRanges, Node, mergeAttributes } from '@tiptap/core';
3
+ import { Slice } from '@tiptap/pm/model';
4
+ import { Plugin } from '@tiptap/pm/state';
5
+ import { ReactNodeViewRenderer, ReactRenderer } from '@tiptap/react';
6
+ import Suggestion from '@tiptap/suggestion';
7
+ import { ySyncPluginKey } from 'y-prosemirror';
8
+ import { LIVEBLOCKS_MENTION_PASTE_KEY, LIVEBLOCKS_MENTION_TYPE, LIVEBLOCKS_MENTION_NOTIFIER_KEY, LIVEBLOCKS_MENTION_KEY } from '../types.mjs';
9
+ import { mapFragment, getMentionsFromNode } from '../utils.mjs';
10
+ import { Mention } from './Mention.mjs';
11
+ import { MentionsList } from './MentionsList.mjs';
12
+
13
+ const mentionPasteHandler = () => {
14
+ return new Plugin({
15
+ key: LIVEBLOCKS_MENTION_PASTE_KEY,
16
+ props: {
17
+ transformPasted: (slice) => {
18
+ const getNewNotificationIds = (node) => {
19
+ if (node.type.name === LIVEBLOCKS_MENTION_TYPE) {
20
+ return node.type.create(
21
+ { ...node.attrs, notificationId: createInboxNotificationId() },
22
+ node.content
23
+ );
24
+ }
25
+ return node.copy(node.content);
26
+ };
27
+ const fragment = mapFragment(slice.content, getNewNotificationIds);
28
+ return new Slice(fragment, slice.openStart, slice.openEnd);
29
+ }
30
+ }
31
+ });
32
+ };
33
+ const notifier = ({
34
+ onCreateMention,
35
+ onDeleteMention
36
+ }) => {
37
+ return new Plugin({
38
+ key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,
39
+ appendTransaction: (transactions, oldState, newState) => {
40
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
41
+ if (!docChanges) {
42
+ return;
43
+ }
44
+ if (transactions.some((transaction) => transaction.getMeta(ySyncPluginKey))) {
45
+ return;
46
+ }
47
+ const transform = combineTransactionSteps(oldState.doc, [
48
+ ...transactions
49
+ ]);
50
+ const changes = getChangedRanges(transform);
51
+ changes.forEach(({ newRange, oldRange }) => {
52
+ const newMentions = getMentionsFromNode(newState.doc, newRange);
53
+ const oldMentions = getMentionsFromNode(oldState.doc, oldRange);
54
+ if (oldMentions.length || newMentions.length) {
55
+ newMentions.forEach((mention) => {
56
+ if (!oldMentions.includes(mention)) {
57
+ onCreateMention(mention.userId, mention.notificationId);
58
+ }
59
+ });
60
+ oldMentions.forEach((mention) => {
61
+ if (!newMentions.includes(mention)) {
62
+ onDeleteMention(mention.notificationId);
63
+ }
64
+ });
65
+ }
66
+ });
67
+ return void 0;
68
+ }
69
+ });
70
+ };
71
+ const MentionExtension = Node.create({
72
+ name: LIVEBLOCKS_MENTION_TYPE,
73
+ group: "inline",
74
+ inline: true,
75
+ selectable: true,
76
+ atom: true,
77
+ parseHTML() {
78
+ return [
79
+ {
80
+ tag: "liveblocks-mention"
81
+ }
82
+ ];
83
+ },
84
+ renderHTML({ HTMLAttributes }) {
85
+ return ["liveblocks-mention", mergeAttributes(HTMLAttributes)];
86
+ },
87
+ addNodeView() {
88
+ return ReactNodeViewRenderer(Mention, {
89
+ contentDOMElementTag: "span"
90
+ });
91
+ },
92
+ addAttributes() {
93
+ return {
94
+ id: {
95
+ default: null,
96
+ parseHTML: (element) => element.getAttribute("data-id"),
97
+ renderHTML: (attributes) => {
98
+ if (!attributes.id) {
99
+ return {};
100
+ }
101
+ return {
102
+ "data-id": attributes.id
103
+ };
104
+ }
105
+ },
106
+ notificationId: {
107
+ default: null,
108
+ parseHTML: (element) => element.getAttribute("data-notification-id"),
109
+ renderHTML: (attributes) => {
110
+ if (!attributes.notificationId) {
111
+ return {};
112
+ }
113
+ return {
114
+ "data-notification-id": attributes.notificationId
115
+ };
116
+ }
117
+ }
118
+ };
119
+ },
120
+ addKeyboardShortcuts() {
121
+ return {
122
+ Backspace: () => this.editor.commands.command(({ tr, state }) => {
123
+ let isMention = false;
124
+ const { selection } = state;
125
+ const { empty, anchor } = selection;
126
+ if (!empty) {
127
+ return false;
128
+ }
129
+ state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
130
+ if (node.type.name === this.name) {
131
+ isMention = true;
132
+ tr.insertText("", pos, pos + node.nodeSize);
133
+ }
134
+ });
135
+ return isMention;
136
+ })
137
+ };
138
+ },
139
+ addOptions() {
140
+ return {
141
+ onCreateMention: () => {
142
+ },
143
+ onDeleteMention: () => {
144
+ }
145
+ };
146
+ },
147
+ addProseMirrorPlugins() {
148
+ return [
149
+ Suggestion({
150
+ editor: this.editor,
151
+ char: "@",
152
+ pluginKey: LIVEBLOCKS_MENTION_KEY,
153
+ command: ({ editor, range, props }) => {
154
+ const nodeAfter = editor.view.state.selection.$to.nodeAfter;
155
+ const overrideSpace = nodeAfter?.text?.startsWith(" ");
156
+ if (overrideSpace) {
157
+ range.to += 1;
158
+ }
159
+ editor.chain().focus().insertContentAt(range, [
160
+ {
161
+ type: this.name,
162
+ attrs: props
163
+ },
164
+ {
165
+ type: "text",
166
+ text: " "
167
+ }
168
+ ]).run();
169
+ editor.view.dom.ownerDocument.defaultView?.getSelection()?.collapseToEnd();
170
+ },
171
+ allow: ({ state, range }) => {
172
+ const $from = state.doc.resolve(range.from);
173
+ const type = state.schema.nodes[this.name];
174
+ const allow = !!$from.parent.type.contentMatch.matchType(type);
175
+ return allow;
176
+ },
177
+ allowSpaces: true,
178
+ items: () => [],
179
+ render: () => {
180
+ let component;
181
+ return {
182
+ onStart: (props) => {
183
+ component = new ReactRenderer(MentionsList, {
184
+ props,
185
+ editor: props.editor
186
+ });
187
+ if (!props.clientRect) {
188
+ return;
189
+ }
190
+ document.body.appendChild(component.element);
191
+ },
192
+ onUpdate(props) {
193
+ component.updateProps(props);
194
+ },
195
+ onKeyDown(props) {
196
+ if (props.event.key === "Escape") {
197
+ component.updateProps({
198
+ ...props,
199
+ hide: true
200
+ });
201
+ return true;
202
+ }
203
+ return component.ref?.onKeyDown(props) ?? false;
204
+ },
205
+ onExit() {
206
+ document.body.removeChild(component.element);
207
+ component.destroy();
208
+ }
209
+ };
210
+ }
211
+ }),
212
+ notifier(this.options),
213
+ mentionPasteHandler()
214
+ ];
215
+ }
216
+ });
217
+
218
+ export { MentionExtension };
219
+ //# sourceMappingURL=MentionExtension.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionExtension.mjs","sources":["../../src/mentions/MentionExtension.ts"],"sourcesContent":["import { createInboxNotificationId } from \"@liveblocks/core\";\nimport {\n combineTransactionSteps,\n getChangedRanges,\n mergeAttributes,\n Node,\n} from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Slice } from \"@tiptap/pm/model\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { ReactNodeViewRenderer, ReactRenderer } from \"@tiptap/react\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ySyncPluginKey } from \"y-prosemirror\";\n\nimport {\n LIVEBLOCKS_MENTION_KEY,\n LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n LIVEBLOCKS_MENTION_PASTE_KEY,\n LIVEBLOCKS_MENTION_TYPE,\n} from \"../types\";\nimport { getMentionsFromNode, mapFragment } from \"../utils\";\nimport { Mention } from \"./Mention\";\nimport type { MentionsListHandle, MentionsListProps } from \"./MentionsList\";\nimport { MentionsList } from \"./MentionsList\";\n\n/**\n *\n * Handles creating new notificationIds when notifications are pasted\n *\n * @returns Plugin\n */\nconst mentionPasteHandler = (): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_PASTE_KEY,\n props: {\n transformPasted: (slice) => {\n const getNewNotificationIds = (node: ProseMirrorNode) => {\n // If this is a mention node, we need to get a new notificatio id\n if (node.type.name === LIVEBLOCKS_MENTION_TYPE) {\n return node.type.create(\n { ...node.attrs, notificationId: createInboxNotificationId() },\n node.content\n );\n }\n return node.copy(node.content);\n };\n const fragment = mapFragment(slice.content, getNewNotificationIds);\n return new Slice(fragment, slice.openStart, slice.openEnd);\n },\n },\n });\n};\n\nexport type MentionExtensionOptions = {\n onCreateMention: (userId: string, notificationId: string) => void;\n onDeleteMention: (notificationId: string) => void;\n};\n/**\n *\n * The purpose of this plugin is to create inbox notifications when a mention is\n *\n * @returns Plugin (from @tiptap/core)\n */\nconst notifier = ({\n onCreateMention,\n onDeleteMention,\n}: MentionExtensionOptions): Plugin => {\n return new Plugin({\n key: LIVEBLOCKS_MENTION_NOTIFIER_KEY,\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n // don't run if there was no change\n if (!docChanges) {\n return;\n }\n // don't run if from collab\n if (\n transactions.some((transaction) => transaction.getMeta(ySyncPluginKey))\n ) {\n return;\n }\n const transform = combineTransactionSteps(oldState.doc, [\n ...transactions,\n ]);\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange, oldRange }) => {\n const newMentions = getMentionsFromNode(newState.doc, newRange);\n const oldMentions = getMentionsFromNode(oldState.doc, oldRange);\n if (oldMentions.length || newMentions.length) {\n // create new mentions\n newMentions.forEach((mention) => {\n if (!oldMentions.includes(mention)) {\n onCreateMention(mention.userId, mention.notificationId);\n }\n });\n // delete old mentions\n oldMentions.forEach((mention) => {\n if (!newMentions.includes(mention)) {\n onDeleteMention(mention.notificationId);\n }\n });\n }\n });\n\n return undefined;\n },\n });\n};\n\nexport const MentionExtension = Node.create<MentionExtensionOptions>({\n name: LIVEBLOCKS_MENTION_TYPE,\n group: \"inline\",\n inline: true,\n selectable: true,\n atom: true,\n\n parseHTML() {\n return [\n {\n tag: \"liveblocks-mention\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"liveblocks-mention\", mergeAttributes(HTMLAttributes)];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(Mention, {\n contentDOMElementTag: \"span\",\n });\n },\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => {\n if (!attributes.id) {\n return {};\n }\n\n return {\n \"data-id\": attributes.id as string, // \"as\" typing because TipTap doesn't have a way to type attributes\n };\n },\n },\n notificationId: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-notification-id\"),\n renderHTML: (attributes) => {\n if (!attributes.notificationId) {\n return {};\n }\n\n return {\n \"data-notification-id\": attributes.notificationId as string, // \"as\" typing because TipTap doesn't have a way to type attributes\n };\n },\n },\n };\n },\n addKeyboardShortcuts() {\n return {\n Backspace: () =>\n this.editor.commands.command(({ tr, state }) => {\n let isMention = false;\n const { selection } = state;\n const { empty, anchor } = selection;\n\n if (!empty) {\n return false;\n }\n\n state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n if (node.type.name === this.name) {\n isMention = true;\n tr.insertText(\"\", pos, pos + node.nodeSize);\n }\n });\n\n return isMention;\n }),\n };\n },\n\n addOptions() {\n return {\n onCreateMention: () => {},\n onDeleteMention: () => {},\n };\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: \"@\",\n pluginKey: LIVEBLOCKS_MENTION_KEY,\n command: ({ editor, range, props }) => {\n // increase range.to by one when the next node is of type \"text\"\n // and starts with a space character\n const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n const overrideSpace = nodeAfter?.text?.startsWith(\" \");\n\n if (overrideSpace) {\n range.to += 1;\n }\n\n editor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: this.name,\n attrs: props as Record<string, string>,\n },\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run();\n\n // get reference to `window` object from editor element, to support cross-frame JS usage\n editor.view.dom.ownerDocument.defaultView\n ?.getSelection()\n ?.collapseToEnd();\n },\n allow: ({ state, range }) => {\n const $from = state.doc.resolve(range.from);\n const type = state.schema.nodes[this.name];\n const allow = !!$from.parent.type.contentMatch.matchType(type);\n\n return allow;\n },\n allowSpaces: true,\n items: () => [], // we'll let the mentions list component do this\n render: () => {\n let component: ReactRenderer<MentionsListHandle, MentionsListProps>;\n return {\n onStart: (props) => {\n component = new ReactRenderer<\n MentionsListHandle,\n MentionsListProps\n >(MentionsList, {\n props,\n editor: props.editor,\n });\n\n if (!props.clientRect) {\n return;\n }\n\n document.body.appendChild(component.element);\n },\n\n onUpdate(props) {\n component.updateProps(props);\n },\n\n onKeyDown(props) {\n if (props.event.key === \"Escape\") {\n component.updateProps({\n ...props,\n hide: true,\n });\n return true;\n }\n return component.ref?.onKeyDown(props) ?? false;\n },\n\n onExit() {\n document.body.removeChild(component.element);\n component.destroy();\n },\n };\n },\n }),\n notifier(this.options),\n mentionPasteHandler(),\n ];\n },\n});\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ var reactDom = require('@floating-ui/react-dom');
4
+ var core = require('@liveblocks/core');
5
+ var react = require('@liveblocks/react');
6
+ var reactUi = require('@liveblocks/react-ui');
7
+ var React = require('react');
8
+ var Avatar = require('./Avatar.js');
9
+
10
+ const User = React.forwardRef(
11
+ function User2(props, forwardedRef) {
12
+ const { userId, className, ...spanProps } = props;
13
+ const { user, isLoading } = react.useUser(userId);
14
+ const $ = reactUi.useOverrides();
15
+ const name = user === void 0 || user === null ? $.USER_UNKNOWN : user.name;
16
+ return /* @__PURE__ */ React.createElement("span", {
17
+ className,
18
+ "data-loading": isLoading ? "" : void 0,
19
+ ref: forwardedRef,
20
+ ...spanProps
21
+ }, isLoading ? null : name);
22
+ }
23
+ );
24
+ const SUGGESTIONS_COLLISION_PADDING = 10;
25
+ const MentionsList = React.forwardRef((props, ref) => {
26
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
27
+ const suggestions = reactUi.useMentionSuggestions(props.query);
28
+ const {
29
+ refs: { setReference, setFloating },
30
+ strategy,
31
+ x,
32
+ y
33
+ } = reactDom.useFloating({
34
+ strategy: "fixed",
35
+ placement: "top-start",
36
+ middleware: [
37
+ reactDom.flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
38
+ reactDom.offset(10),
39
+ reactDom.hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
40
+ reactDom.shift({ padding: SUGGESTIONS_COLLISION_PADDING, limiter: reactDom.limitShift() }),
41
+ reactDom.size({ padding: SUGGESTIONS_COLLISION_PADDING })
42
+ ],
43
+ whileElementsMounted: (...args) => {
44
+ return reactDom.autoUpdate(...args, {
45
+ animationFrame: true
46
+ });
47
+ }
48
+ });
49
+ React.useLayoutEffect(() => {
50
+ setReference({
51
+ getBoundingClientRect: props.clientRect
52
+ });
53
+ }, [setReference, props.clientRect]);
54
+ const selectItem = (index) => {
55
+ const item = (suggestions ?? [])[index];
56
+ if (item) {
57
+ props.command({ id: item, notificationId: core.createInboxNotificationId() });
58
+ }
59
+ };
60
+ const upHandler = () => {
61
+ setSelectedIndex((selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0));
62
+ };
63
+ const downHandler = () => {
64
+ setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
65
+ };
66
+ const enterHandler = () => {
67
+ selectItem(selectedIndex);
68
+ };
69
+ React.useEffect(() => setSelectedIndex(0), [suggestions]);
70
+ React.useImperativeHandle(ref, () => ({
71
+ onKeyDown: ({ event }) => {
72
+ if (event.key === "ArrowUp") {
73
+ upHandler();
74
+ return true;
75
+ }
76
+ if (event.key === "ArrowDown") {
77
+ downHandler();
78
+ return true;
79
+ }
80
+ if (event.key === "Enter") {
81
+ enterHandler();
82
+ return true;
83
+ }
84
+ return false;
85
+ }
86
+ }));
87
+ if (suggestions !== void 0 && suggestions.length === 0) {
88
+ return null;
89
+ }
90
+ return /* @__PURE__ */ React.createElement("div", {
91
+ className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
92
+ ref: setFloating,
93
+ style: {
94
+ position: strategy,
95
+ top: 0,
96
+ left: 0,
97
+ transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
98
+ minWidth: "max-content",
99
+ display: props.hide ? "none" : "block"
100
+ }
101
+ }, /* @__PURE__ */ React.createElement("div", {
102
+ className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list"
103
+ }, suggestions === void 0 ? /* @__PURE__ */ React.createElement("div", {
104
+ className: "item"
105
+ }, "Loading...") : suggestions.map((item, index) => /* @__PURE__ */ React.createElement("div", {
106
+ className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
107
+ key: index,
108
+ role: "option",
109
+ "data-highlighted": index === selectedIndex || void 0,
110
+ onClick: () => selectItem(index)
111
+ }, /* @__PURE__ */ React.createElement(Avatar.Avatar, {
112
+ userId: item,
113
+ className: "lb-tiptap-mention-suggestion-avatar"
114
+ }), /* @__PURE__ */ React.createElement(User, {
115
+ userId: item,
116
+ className: "lb-tiptap-mention-suggestion-user"
117
+ })))));
118
+ });
119
+
120
+ exports.MentionsList = MentionsList;
121
+ exports.SUGGESTIONS_COLLISION_PADDING = SUGGESTIONS_COLLISION_PADDING;
122
+ exports.User = User;
123
+ //# sourceMappingURL=MentionsList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionsList.js","sources":["../../src/mentions/MentionsList.tsx"],"sourcesContent":["import { autoUpdate, flip, hide, limitShift, offset, shift, size, useFloating } from \"@floating-ui/react-dom\";\nimport { createInboxNotificationId } from \"@liveblocks/core\";\nimport { useUser } from \"@liveblocks/react\";\nimport { useMentionSuggestions, useOverrides } from \"@liveblocks/react-ui\";\nimport type { HTMLAttributes } from \"react\";\nimport React, {\n forwardRef, useEffect, useImperativeHandle,\n useLayoutEffect,\n useState,\n} from \"react\"\n\nimport { Avatar } from \"./Avatar\";\n\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 type MentionsListProps = {\n query: string,\n command: (otps: { id: string, notificationId: string }) => void,\n clientRect: () => DOMRect,\n hide: boolean\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 suggestions = useMentionSuggestions(props.query);\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 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 === undefined ? <div className=\"item\">Loading...</div> :\n\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 onClick={() => selectItem(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","useState","useMentionSuggestions","useFloating","flip","offset","hide","shift","limitShift","size","autoUpdate","useLayoutEffect","createInboxNotificationId","useEffect","useImperativeHandle","Avatar"],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { useFloating, flip, offset, hide, shift, limitShift, size, autoUpdate } from '@floating-ui/react-dom';
2
+ import { createInboxNotificationId } from '@liveblocks/core';
3
+ import { useUser } from '@liveblocks/react';
4
+ import { useOverrides, useMentionSuggestions } from '@liveblocks/react-ui';
5
+ import React, { forwardRef, useState, useLayoutEffect, useEffect, useImperativeHandle } from 'react';
6
+ import { Avatar } from './Avatar.mjs';
7
+
8
+ const User = forwardRef(
9
+ function User2(props, forwardedRef) {
10
+ const { userId, className, ...spanProps } = props;
11
+ const { user, isLoading } = useUser(userId);
12
+ const $ = useOverrides();
13
+ const name = user === void 0 || user === null ? $.USER_UNKNOWN : user.name;
14
+ return /* @__PURE__ */ React.createElement("span", {
15
+ className,
16
+ "data-loading": isLoading ? "" : void 0,
17
+ ref: forwardedRef,
18
+ ...spanProps
19
+ }, isLoading ? null : name);
20
+ }
21
+ );
22
+ const SUGGESTIONS_COLLISION_PADDING = 10;
23
+ const MentionsList = forwardRef((props, ref) => {
24
+ const [selectedIndex, setSelectedIndex] = useState(0);
25
+ const suggestions = useMentionSuggestions(props.query);
26
+ const {
27
+ refs: { setReference, setFloating },
28
+ strategy,
29
+ x,
30
+ y
31
+ } = useFloating({
32
+ strategy: "fixed",
33
+ placement: "top-start",
34
+ middleware: [
35
+ flip({ padding: SUGGESTIONS_COLLISION_PADDING, crossAxis: false }),
36
+ offset(10),
37
+ hide({ padding: SUGGESTIONS_COLLISION_PADDING }),
38
+ shift({ padding: SUGGESTIONS_COLLISION_PADDING, limiter: limitShift() }),
39
+ size({ padding: SUGGESTIONS_COLLISION_PADDING })
40
+ ],
41
+ whileElementsMounted: (...args) => {
42
+ return autoUpdate(...args, {
43
+ animationFrame: true
44
+ });
45
+ }
46
+ });
47
+ useLayoutEffect(() => {
48
+ setReference({
49
+ getBoundingClientRect: props.clientRect
50
+ });
51
+ }, [setReference, props.clientRect]);
52
+ const selectItem = (index) => {
53
+ const item = (suggestions ?? [])[index];
54
+ if (item) {
55
+ props.command({ id: item, notificationId: createInboxNotificationId() });
56
+ }
57
+ };
58
+ const upHandler = () => {
59
+ setSelectedIndex((selectedIndex + (suggestions?.length ?? 0) - 1) % (suggestions?.length ?? 0));
60
+ };
61
+ const downHandler = () => {
62
+ setSelectedIndex((selectedIndex + 1) % (suggestions?.length ?? 0));
63
+ };
64
+ const enterHandler = () => {
65
+ selectItem(selectedIndex);
66
+ };
67
+ useEffect(() => setSelectedIndex(0), [suggestions]);
68
+ useImperativeHandle(ref, () => ({
69
+ onKeyDown: ({ event }) => {
70
+ if (event.key === "ArrowUp") {
71
+ upHandler();
72
+ return true;
73
+ }
74
+ if (event.key === "ArrowDown") {
75
+ downHandler();
76
+ return true;
77
+ }
78
+ if (event.key === "Enter") {
79
+ enterHandler();
80
+ return true;
81
+ }
82
+ return false;
83
+ }
84
+ }));
85
+ if (suggestions !== void 0 && suggestions.length === 0) {
86
+ return null;
87
+ }
88
+ return /* @__PURE__ */ React.createElement("div", {
89
+ className: "lb-root lb-portal lb-elevation lb-tiptap-suggestions lb-tiptap-mention-suggestions",
90
+ ref: setFloating,
91
+ style: {
92
+ position: strategy,
93
+ top: 0,
94
+ left: 0,
95
+ transform: `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`,
96
+ minWidth: "max-content",
97
+ display: props.hide ? "none" : "block"
98
+ }
99
+ }, /* @__PURE__ */ React.createElement("div", {
100
+ className: "lb-tiptap-suggestions-list lb-tiptap-mention-suggestions-list"
101
+ }, suggestions === void 0 ? /* @__PURE__ */ React.createElement("div", {
102
+ className: "item"
103
+ }, "Loading...") : suggestions.map((item, index) => /* @__PURE__ */ React.createElement("div", {
104
+ className: "lb-tiptap-suggestions-list-item lb-tiptap-mention-suggestion",
105
+ key: index,
106
+ role: "option",
107
+ "data-highlighted": index === selectedIndex || void 0,
108
+ onClick: () => selectItem(index)
109
+ }, /* @__PURE__ */ React.createElement(Avatar, {
110
+ userId: item,
111
+ className: "lb-tiptap-mention-suggestion-avatar"
112
+ }), /* @__PURE__ */ React.createElement(User, {
113
+ userId: item,
114
+ className: "lb-tiptap-mention-suggestion-user"
115
+ })))));
116
+ });
117
+
118
+ export { MentionsList, SUGGESTIONS_COLLISION_PADDING, User };
119
+ //# sourceMappingURL=MentionsList.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionsList.mjs","sources":["../../src/mentions/MentionsList.tsx"],"sourcesContent":["import { autoUpdate, flip, hide, limitShift, offset, shift, size, useFloating } from \"@floating-ui/react-dom\";\nimport { createInboxNotificationId } from \"@liveblocks/core\";\nimport { useUser } from \"@liveblocks/react\";\nimport { useMentionSuggestions, useOverrides } from \"@liveblocks/react-ui\";\nimport type { HTMLAttributes } from \"react\";\nimport React, {\n forwardRef, useEffect, useImperativeHandle,\n useLayoutEffect,\n useState,\n} from \"react\"\n\nimport { Avatar } from \"./Avatar\";\n\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 type MentionsListProps = {\n query: string,\n command: (otps: { id: string, notificationId: string }) => void,\n clientRect: () => DOMRect,\n hide: boolean\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 suggestions = useMentionSuggestions(props.query);\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 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 === undefined ? <div className=\"item\">Loading...</div> :\n\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 onClick={() => selectItem(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":["User"],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ var state = require('@tiptap/pm/state');
4
+
5
+ const LIVEBLOCKS_MENTION_KEY = new state.PluginKey("lb-plugin-mention");
6
+ const LIVEBLOCKS_MENTION_PASTE_KEY = new state.PluginKey(
7
+ "lb-plugin-mention-paste"
8
+ );
9
+ const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new state.PluginKey(
10
+ "lb-plugin-mention-notify"
11
+ );
12
+ const LIVEBLOCKS_MENTION_TYPE = "liveblocksMention";
13
+ const ACTIVE_SELECTION_PLUGIN = new state.PluginKey(
14
+ "lb-active-selection-plugin"
15
+ );
16
+ const THREADS_PLUGIN_KEY = new state.PluginKey(
17
+ "lb-threads-plugin"
18
+ );
19
+ const LIVEBLOCKS_COMMENT_MARK_TYPE = "liveblocksCommentMark";
20
+ var ThreadPluginActions = /* @__PURE__ */ ((ThreadPluginActions2) => {
21
+ ThreadPluginActions2["SET_SELECTED_THREAD_ID"] = "SET_SELECTED_THREAD_ID";
22
+ return ThreadPluginActions2;
23
+ })(ThreadPluginActions || {});
24
+
25
+ exports.ACTIVE_SELECTION_PLUGIN = ACTIVE_SELECTION_PLUGIN;
26
+ exports.LIVEBLOCKS_COMMENT_MARK_TYPE = LIVEBLOCKS_COMMENT_MARK_TYPE;
27
+ exports.LIVEBLOCKS_MENTION_KEY = LIVEBLOCKS_MENTION_KEY;
28
+ exports.LIVEBLOCKS_MENTION_NOTIFIER_KEY = LIVEBLOCKS_MENTION_NOTIFIER_KEY;
29
+ exports.LIVEBLOCKS_MENTION_PASTE_KEY = LIVEBLOCKS_MENTION_PASTE_KEY;
30
+ exports.LIVEBLOCKS_MENTION_TYPE = LIVEBLOCKS_MENTION_TYPE;
31
+ exports.THREADS_PLUGIN_KEY = THREADS_PLUGIN_KEY;
32
+ exports.ThreadPluginActions = ThreadPluginActions;
33
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import type { TextSelection } from \"@tiptap/pm/state\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\n\nexport const ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\nexport type CommentsExtensionStorage = {\n pendingCommentSelection: TextSelection | null;\n};\n\nexport const enum ThreadPluginActions {\n SET_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\n}\n\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\n decorations: DecorationSet;\n};\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":["PluginKey","ThreadPluginActions"],"mappings":";;;;AAIa,MAAA,sBAAA,GAAyB,IAAIA,eAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAIA,eAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAIA,eAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AACO,MAAM,uBAA0B,GAAA,oBAAA;AAEhC,MAAM,0BAA0B,IAAIA,eAAA;AAAA,EACzC,4BAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAIA,eAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AAM1B,IAAA,mBAAA,qBAAAC,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;;;;;;;;"}
package/dist/types.mjs ADDED
@@ -0,0 +1,24 @@
1
+ import { PluginKey } from '@tiptap/pm/state';
2
+
3
+ const LIVEBLOCKS_MENTION_KEY = new PluginKey("lb-plugin-mention");
4
+ const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(
5
+ "lb-plugin-mention-paste"
6
+ );
7
+ const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(
8
+ "lb-plugin-mention-notify"
9
+ );
10
+ const LIVEBLOCKS_MENTION_TYPE = "liveblocksMention";
11
+ const ACTIVE_SELECTION_PLUGIN = new PluginKey(
12
+ "lb-active-selection-plugin"
13
+ );
14
+ const THREADS_PLUGIN_KEY = new PluginKey(
15
+ "lb-threads-plugin"
16
+ );
17
+ const LIVEBLOCKS_COMMENT_MARK_TYPE = "liveblocksCommentMark";
18
+ var ThreadPluginActions = /* @__PURE__ */ ((ThreadPluginActions2) => {
19
+ ThreadPluginActions2["SET_SELECTED_THREAD_ID"] = "SET_SELECTED_THREAD_ID";
20
+ return ThreadPluginActions2;
21
+ })(ThreadPluginActions || {});
22
+
23
+ export { ACTIVE_SELECTION_PLUGIN, LIVEBLOCKS_COMMENT_MARK_TYPE, LIVEBLOCKS_MENTION_KEY, LIVEBLOCKS_MENTION_NOTIFIER_KEY, LIVEBLOCKS_MENTION_PASTE_KEY, LIVEBLOCKS_MENTION_TYPE, THREADS_PLUGIN_KEY, ThreadPluginActions };
24
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.mjs","sources":["../src/types.ts"],"sourcesContent":["import type { TextSelection } from \"@tiptap/pm/state\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport type { DecorationSet } from \"@tiptap/pm/view\";\n\nexport const LIVEBLOCKS_MENTION_KEY = new PluginKey(\"lb-plugin-mention\");\nexport const LIVEBLOCKS_MENTION_PASTE_KEY = new PluginKey(\n \"lb-plugin-mention-paste\"\n);\nexport const LIVEBLOCKS_MENTION_NOTIFIER_KEY = new PluginKey(\n \"lb-plugin-mention-notify\"\n);\nexport const LIVEBLOCKS_MENTION_TYPE = \"liveblocksMention\";\n\nexport const ACTIVE_SELECTION_PLUGIN = new PluginKey(\n \"lb-active-selection-plugin\"\n);\nexport const THREADS_PLUGIN_KEY = new PluginKey<ThreadPluginState>(\n \"lb-threads-plugin\"\n);\n\nexport const LIVEBLOCKS_COMMENT_MARK_TYPE = \"liveblocksCommentMark\";\n\nexport type CommentsExtensionStorage = {\n pendingCommentSelection: TextSelection | null;\n};\n\nexport const enum ThreadPluginActions {\n SET_SELECTED_THREAD_ID = \"SET_SELECTED_THREAD_ID\",\n}\n\nexport type ThreadPluginState = {\n threadPositions: Map<string, { from: number; to: number }>;\n selectedThreadId: string | null;\n selectedThreadPos: number | null;\n decorations: DecorationSet;\n};\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":["ThreadPluginActions"],"mappings":";;AAIa,MAAA,sBAAA,GAAyB,IAAI,SAAA,CAAU,mBAAmB,EAAA;AAChE,MAAM,+BAA+B,IAAI,SAAA;AAAA,EAC9C,yBAAA;AACF,EAAA;AACO,MAAM,kCAAkC,IAAI,SAAA;AAAA,EACjD,0BAAA;AACF,EAAA;AACO,MAAM,uBAA0B,GAAA,oBAAA;AAEhC,MAAM,0BAA0B,IAAI,SAAA;AAAA,EACzC,4BAAA;AACF,EAAA;AACO,MAAM,qBAAqB,IAAI,SAAA;AAAA,EACpC,mBAAA;AACF,EAAA;AAEO,MAAM,4BAA+B,GAAA,wBAAA;AAM1B,IAAA,mBAAA,qBAAAA,oBAAX,KAAA;AACL,EAAAA,qBAAA,wBAAyB,CAAA,GAAA,wBAAA,CAAA;AADT,EAAAA,OAAAA,oBAAAA,CAAAA;AAAA,CAAA,EAAA,mBAAA,IAAA,EAAA;;;;"}
package/dist/utils.js ADDED
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ var model = require('@tiptap/pm/model');
4
+ var types = require('./types.js');
5
+
6
+ const getRectFromCoords = (coords) => {
7
+ return {
8
+ ...coords,
9
+ x: coords.left,
10
+ y: coords.top,
11
+ width: coords.right - coords.left,
12
+ height: coords.bottom - coords.top
13
+ };
14
+ };
15
+ const getMentionsFromNode = (node, range) => {
16
+ const result = [];
17
+ node.nodesBetween(range.from, range.to, (child) => {
18
+ if (child.type.name === types.LIVEBLOCKS_MENTION_TYPE) {
19
+ const mention = child.attrs;
20
+ if (mention.id && mention.notificationId) {
21
+ result.push({
22
+ notificationId: mention.notificationId,
23
+ userId: mention.id
24
+ });
25
+ }
26
+ }
27
+ });
28
+ return result;
29
+ };
30
+ const mapFragment = (fragment, callback) => {
31
+ const content = [];
32
+ fragment.forEach((node) => {
33
+ if (node.content.childCount > 0) {
34
+ content.push(
35
+ node.type.create(node.attrs, mapFragment(node.content, callback))
36
+ );
37
+ return;
38
+ }
39
+ content.push(callback(node));
40
+ });
41
+ return model.Fragment.from(content);
42
+ };
43
+
44
+ exports.getMentionsFromNode = getMentionsFromNode;
45
+ exports.getRectFromCoords = getRectFromCoords;
46
+ exports.mapFragment = mapFragment;
47
+ //# sourceMappingURL=utils.js.map