@liveblocks/react-tiptap 0.0.1 → 2.8.3-tiptap2

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 +206 -0
  2. package/dist/LiveblocksExtension.js.map +1 -0
  3. package/dist/LiveblocksExtension.mjs +204 -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 +224 -0
  14. package/dist/comments/CommentsExtension.js.map +1 -0
  15. package/dist/comments/CommentsExtension.mjs +222 -0
  16. package/dist/comments/CommentsExtension.mjs.map +1 -0
  17. package/dist/comments/FloatingComposer.js +100 -0
  18. package/dist/comments/FloatingComposer.js.map +1 -0
  19. package/dist/comments/FloatingComposer.mjs +97 -0
  20. package/dist/comments/FloatingComposer.mjs.map +1 -0
  21. package/dist/comments/FloatingThreads.js +159 -0
  22. package/dist/comments/FloatingThreads.js.map +1 -0
  23. package/dist/comments/FloatingThreads.mjs +156 -0
  24. package/dist/comments/FloatingThreads.mjs.map +1 -0
  25. package/dist/index.d.mts +78 -0
  26. package/dist/index.d.ts +78 -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 +222 -0
  40. package/dist/mentions/MentionExtension.js.map +1 -0
  41. package/dist/mentions/MentionExtension.mjs +220 -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 +250 -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,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"],"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"],"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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\n\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n"],"names":["LIVEBLOCKS_MENTION_TYPE","Fragment"],"mappings":";;;;;AAOa,MAAA,iBAAA,GAAoB,CAAC,MAKV,KAAA;AACtB,EAAO,OAAA;AAAA,IACL,GAAG,MAAA;AAAA,IACH,GAAG,MAAO,CAAA,IAAA;AAAA,IACV,GAAG,MAAO,CAAA,GAAA;AAAA,IACV,KAAA,EAAO,MAAO,CAAA,KAAA,GAAQ,MAAO,CAAA,IAAA;AAAA,IAC7B,MAAA,EAAQ,MAAO,CAAA,MAAA,GAAS,MAAO,CAAA,GAAA;AAAA,GACjC,CAAA;AACF,EAAA;AAEa,MAAA,mBAAA,GAAsB,CACjC,IAAA,EACA,KACiD,KAAA;AACjD,EAAA,MAAM,SAAuD,EAAC,CAAA;AAC9D,EAAA,IAAA,CAAK,aAAa,KAAM,CAAA,IAAA,EAAM,KAAM,CAAA,EAAA,EAAI,CAAC,KAAU,KAAA;AACjD,IAAI,IAAA,KAAA,CAAM,IAAK,CAAA,IAAA,KAASA,6BAAyB,EAAA;AAC/C,MAAA,MAAM,UAAU,KAAM,CAAA,KAAA,CAAA;AACtB,MAAI,IAAA,OAAA,CAAQ,EAAM,IAAA,OAAA,CAAQ,cAAgB,EAAA;AACxC,QAAA,MAAA,CAAO,IAAK,CAAA;AAAA,UACV,gBAAgB,OAAQ,CAAA,cAAA;AAAA,UACxB,QAAQ,OAAQ,CAAA,EAAA;AAAA,SACjB,CAAA,CAAA;AAAA,OACH;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACD,EAAO,OAAA,MAAA,CAAA;AACT,EAAA;AAGa,MAAA,WAAA,GAAc,CACzB,QAAA,EACA,QAGa,KAAA;AACb,EAAA,MAAM,UAA6B,EAAC,CAAA;AACpC,EAAS,QAAA,CAAA,OAAA,CAAQ,CAAC,IAAS,KAAA;AACzB,IAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,UAAA,GAAa,CAAG,EAAA;AAC/B,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,IAAA,CAAK,KAAK,MAAO,CAAA,IAAA,CAAK,OAAO,WAAY,CAAA,IAAA,CAAK,OAAS,EAAA,QAAQ,CAAC,CAAA;AAAA,OAClE,CAAA;AACA,MAAA,OAAA;AAAA,KACF;AACA,IAAQ,OAAA,CAAA,IAAA,CAAK,QAAS,CAAA,IAAI,CAAoB,CAAA,CAAA;AAAA,GAC/C,CAAA,CAAA;AAED,EAAO,OAAAC,cAAA,CAAS,KAAK,OAAO,CAAA,CAAA;AAC9B;;;;;;"}
package/dist/utils.mjs ADDED
@@ -0,0 +1,43 @@
1
+ import { Fragment } from '@tiptap/pm/model';
2
+ import { LIVEBLOCKS_MENTION_TYPE } from './types.mjs';
3
+
4
+ const getRectFromCoords = (coords) => {
5
+ return {
6
+ ...coords,
7
+ x: coords.left,
8
+ y: coords.top,
9
+ width: coords.right - coords.left,
10
+ height: coords.bottom - coords.top
11
+ };
12
+ };
13
+ const getMentionsFromNode = (node, range) => {
14
+ const result = [];
15
+ node.nodesBetween(range.from, range.to, (child) => {
16
+ if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {
17
+ const mention = child.attrs;
18
+ if (mention.id && mention.notificationId) {
19
+ result.push({
20
+ notificationId: mention.notificationId,
21
+ userId: mention.id
22
+ });
23
+ }
24
+ }
25
+ });
26
+ return result;
27
+ };
28
+ const mapFragment = (fragment, callback) => {
29
+ const content = [];
30
+ fragment.forEach((node) => {
31
+ if (node.content.childCount > 0) {
32
+ content.push(
33
+ node.type.create(node.attrs, mapFragment(node.content, callback))
34
+ );
35
+ return;
36
+ }
37
+ content.push(callback(node));
38
+ });
39
+ return Fragment.from(content);
40
+ };
41
+
42
+ export { getMentionsFromNode, getRectFromCoords, mapFragment };
43
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\n\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n"],"names":[],"mappings":";;;AAOa,MAAA,iBAAA,GAAoB,CAAC,MAKV,KAAA;AACtB,EAAO,OAAA;AAAA,IACL,GAAG,MAAA;AAAA,IACH,GAAG,MAAO,CAAA,IAAA;AAAA,IACV,GAAG,MAAO,CAAA,GAAA;AAAA,IACV,KAAA,EAAO,MAAO,CAAA,KAAA,GAAQ,MAAO,CAAA,IAAA;AAAA,IAC7B,MAAA,EAAQ,MAAO,CAAA,MAAA,GAAS,MAAO,CAAA,GAAA;AAAA,GACjC,CAAA;AACF,EAAA;AAEa,MAAA,mBAAA,GAAsB,CACjC,IAAA,EACA,KACiD,KAAA;AACjD,EAAA,MAAM,SAAuD,EAAC,CAAA;AAC9D,EAAA,IAAA,CAAK,aAAa,KAAM,CAAA,IAAA,EAAM,KAAM,CAAA,EAAA,EAAI,CAAC,KAAU,KAAA;AACjD,IAAI,IAAA,KAAA,CAAM,IAAK,CAAA,IAAA,KAAS,uBAAyB,EAAA;AAC/C,MAAA,MAAM,UAAU,KAAM,CAAA,KAAA,CAAA;AACtB,MAAI,IAAA,OAAA,CAAQ,EAAM,IAAA,OAAA,CAAQ,cAAgB,EAAA;AACxC,QAAA,MAAA,CAAO,IAAK,CAAA;AAAA,UACV,gBAAgB,OAAQ,CAAA,cAAA;AAAA,UACxB,QAAQ,OAAQ,CAAA,EAAA;AAAA,SACjB,CAAA,CAAA;AAAA,OACH;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACD,EAAO,OAAA,MAAA,CAAA;AACT,EAAA;AAGa,MAAA,WAAA,GAAc,CACzB,QAAA,EACA,QAGa,KAAA;AACb,EAAA,MAAM,UAA6B,EAAC,CAAA;AACpC,EAAS,QAAA,CAAA,OAAA,CAAQ,CAAC,IAAS,KAAA;AACzB,IAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,UAAA,GAAa,CAAG,EAAA;AAC/B,MAAQ,OAAA,CAAA,IAAA;AAAA,QACN,IAAA,CAAK,KAAK,MAAO,CAAA,IAAA,CAAK,OAAO,WAAY,CAAA,IAAA,CAAK,OAAS,EAAA,QAAQ,CAAC,CAAA;AAAA,OAClE,CAAA;AACA,MAAA,OAAA;AAAA,KACF;AACA,IAAQ,OAAA,CAAA,IAAA,CAAK,QAAS,CAAA,IAAI,CAAoB,CAAA,CAAA;AAAA,GAC/C,CAAA,CAAA;AAED,EAAO,OAAA,QAAA,CAAS,KAAK,OAAO,CAAA,CAAA;AAC9B;;;;"}
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ var react = require('@liveblocks/react');
4
+ var reactUi = require('@liveblocks/react-ui');
5
+ var _private = require('@liveblocks/react-ui/_private');
6
+ var react$1 = require('@tiptap/react');
7
+ var React = require('react');
8
+ var yProsemirror = require('y-prosemirror');
9
+ var yjs = require('yjs');
10
+ var classnames = require('../classnames.js');
11
+
12
+ const AUTHORS_TRUNCATE = 3;
13
+ const HistoryVersionPreview = React.forwardRef(({ version, editor: parentEditor, onVersionRestore, className, ...props }, forwardedRef) => {
14
+ const $ = reactUi.useOverrides();
15
+ const { isLoading, data, error } = react.useHistoryVersionData(version.id);
16
+ const previewEditor = react$1.useEditor({
17
+ editable: false,
18
+ extensions: parentEditor.extensionManager.extensions.filter((e) => e.type !== "extension")
19
+ });
20
+ React.useEffect(() => {
21
+ if (data && previewEditor) {
22
+ const doc = new yjs.Doc();
23
+ yjs.applyUpdate(doc, data);
24
+ const root = doc.getXmlFragment("default");
25
+ const node = yProsemirror.yXmlFragmentToProseMirrorRootNode(root, parentEditor.schema);
26
+ previewEditor.commands.setContent(node.toJSON());
27
+ }
28
+ }, [data, previewEditor, parentEditor]);
29
+ const restore = React.useCallback(() => {
30
+ parentEditor.commands.setContent(previewEditor?.getJSON() ?? "");
31
+ onVersionRestore?.(version);
32
+ }, [onVersionRestore, parentEditor, previewEditor, version]);
33
+ return /* @__PURE__ */ React.createElement("div", {
34
+ ...props,
35
+ className: classnames.classNames(
36
+ "lb-root lb-history-version-preview lb-tiptap-version-preview",
37
+ className
38
+ ),
39
+ ref: forwardedRef
40
+ }, isLoading ? /* @__PURE__ */ React.createElement("div", {
41
+ className: "lb-loading lb-history-version-preview-loading"
42
+ }, /* @__PURE__ */ React.createElement(_private.SpinnerIcon, null)) : error ? /* @__PURE__ */ React.createElement("div", {
43
+ className: "lb-error lb-history-version-preview-error"
44
+ }, $.HISTORY_VERSION_PREVIEW_ERROR(error)) : /* @__PURE__ */ React.createElement("div", {
45
+ className: "lb-history-version-preview-content lb-tiptap-editor-container lb-tiptap-version-preview-editor-container"
46
+ }, /* @__PURE__ */ React.createElement(react$1.EditorContent, {
47
+ editor: previewEditor
48
+ })), /* @__PURE__ */ React.createElement("div", {
49
+ className: "lb-history-version-preview-footer"
50
+ }, /* @__PURE__ */ React.createElement("span", {
51
+ className: "lb-history-version-preview-authors"
52
+ }, $.HISTORY_VERSION_PREVIEW_AUTHORS_LIST(
53
+ /* @__PURE__ */ React.createElement(_private.List, {
54
+ values: version.authors.map((author) => /* @__PURE__ */ React.createElement(_private.User, {
55
+ key: author.id,
56
+ userId: author.id,
57
+ replaceSelf: true
58
+ })),
59
+ formatRemaining: $.LIST_REMAINING_USERS,
60
+ truncate: AUTHORS_TRUNCATE,
61
+ locale: $.locale
62
+ })
63
+ )), /* @__PURE__ */ React.createElement("div", {
64
+ className: "lb-history-version-preview-actions"
65
+ }, /* @__PURE__ */ React.createElement(_private.Button, {
66
+ onClick: restore,
67
+ disabled: !data,
68
+ variant: "primary",
69
+ size: "large",
70
+ className: "lb-history-version-preview-action"
71
+ }, /* @__PURE__ */ React.createElement(_private.RestoreIcon, {
72
+ className: "lb-button-icon"
73
+ }), /* @__PURE__ */ React.createElement("span", {
74
+ className: "lb-button-label"
75
+ }, $.HISTORY_VERSION_PREVIEW_RESTORE)))));
76
+ });
77
+
78
+ exports.HistoryVersionPreview = HistoryVersionPreview;
79
+ //# sourceMappingURL=HistoryVersionPreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HistoryVersionPreview.js","sources":["../../src/version-history/HistoryVersionPreview.tsx"],"sourcesContent":["import type { HistoryVersion } from \"@liveblocks/core\";\nimport { useHistoryVersionData } from \"@liveblocks/react\";\nimport { useOverrides } from \"@liveblocks/react-ui\";\nimport {\n Button,\n List,\n RestoreIcon,\n SpinnerIcon,\n User,\n} from \"@liveblocks/react-ui/_private\";\nimport type { Content, Editor } from \"@tiptap/react\";\nimport { EditorContent, useEditor } from \"@tiptap/react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n} from \"react\";\nimport { yXmlFragmentToProseMirrorRootNode } from \"y-prosemirror\";\nimport { applyUpdate, Doc } from \"yjs\";\n\nimport { classNames } from \"../classnames\";\n\nconst AUTHORS_TRUNCATE = 3;\n\nexport interface HistoryVersionPreviewProps\n extends ComponentPropsWithoutRef<\"div\"> {\n version: HistoryVersion;\n editor: Editor;\n onVersionRestore?: (version: HistoryVersion) => void;\n}\n\n/**\n * Displays a specific version of the current TipTap document.\n *\n * @example\n * <HistoryVersionPreview version={version} />\n */\nexport const HistoryVersionPreview = forwardRef<\n HTMLDivElement,\n HistoryVersionPreviewProps\n>(({ version, editor: parentEditor, onVersionRestore, className, ...props }, forwardedRef) => {\n const $ = useOverrides();\n const { isLoading, data, error } = useHistoryVersionData(version.id);\n\n const previewEditor = useEditor({\n // ignore extensions, only get marks/nodes\n editable: false,\n extensions: parentEditor.extensionManager.extensions.filter((e) => e.type !== \"extension\"),\n });\n useEffect(() => {\n if (data && previewEditor) {\n const doc = new Doc();\n applyUpdate(doc, data);\n const root = doc.getXmlFragment(\"default\") // TODO: lookup field\n const node = yXmlFragmentToProseMirrorRootNode(root, parentEditor.schema);\n previewEditor.commands.setContent(node.toJSON() as Content)\n }\n }, [data, previewEditor, parentEditor]);\n const restore = useCallback(() => {\n parentEditor.commands.setContent(previewEditor?.getJSON() ?? \"\");\n onVersionRestore?.(version);\n }, [onVersionRestore, parentEditor, previewEditor, version]);\n\n return (\n <div\n {...props}\n className={classNames(\n \"lb-root lb-history-version-preview lb-tiptap-version-preview\",\n className\n )}\n ref={forwardedRef}\n >\n {isLoading ? (\n <div className=\"lb-loading lb-history-version-preview-loading\">\n <SpinnerIcon />\n </div>\n ) : error ? (\n <div className=\"lb-error lb-history-version-preview-error\">\n {$.HISTORY_VERSION_PREVIEW_ERROR(error)}\n </div>\n ) : (\n <div className=\"lb-history-version-preview-content lb-tiptap-editor-container lb-tiptap-version-preview-editor-container\">\n\n <EditorContent editor={previewEditor} />\n </div>\n )}\n <div className=\"lb-history-version-preview-footer\">\n <span className=\"lb-history-version-preview-authors\">\n {$.HISTORY_VERSION_PREVIEW_AUTHORS_LIST(\n <List\n values={version.authors.map((author) => (\n <User key={author.id} userId={author.id} replaceSelf />\n ))}\n formatRemaining={$.LIST_REMAINING_USERS}\n truncate={AUTHORS_TRUNCATE}\n locale={$.locale}\n />\n )}\n </span>\n <div className=\"lb-history-version-preview-actions\">\n <Button\n onClick={restore}\n disabled={!data}\n variant=\"primary\"\n size=\"large\"\n className=\"lb-history-version-preview-action\"\n >\n <RestoreIcon className=\"lb-button-icon\" />\n <span className=\"lb-button-label\">\n {$.HISTORY_VERSION_PREVIEW_RESTORE}\n </span>\n </Button>\n </div>\n </div>\n </div>\n );\n});\n"],"names":["forwardRef","useOverrides","useHistoryVersionData","useEditor","useEffect","Doc","applyUpdate","yXmlFragmentToProseMirrorRootNode","useCallback","classNames","SpinnerIcon","EditorContent","List","User","Button","RestoreIcon"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { useHistoryVersionData } from '@liveblocks/react';
2
+ import { useOverrides } from '@liveblocks/react-ui';
3
+ import { SpinnerIcon, List, User, Button, RestoreIcon } from '@liveblocks/react-ui/_private';
4
+ import { useEditor, EditorContent } from '@tiptap/react';
5
+ import React, { forwardRef, useEffect, useCallback } from 'react';
6
+ import { yXmlFragmentToProseMirrorRootNode } from 'y-prosemirror';
7
+ import { Doc, applyUpdate } from 'yjs';
8
+ import { classNames } from '../classnames.mjs';
9
+
10
+ const AUTHORS_TRUNCATE = 3;
11
+ const HistoryVersionPreview = forwardRef(({ version, editor: parentEditor, onVersionRestore, className, ...props }, forwardedRef) => {
12
+ const $ = useOverrides();
13
+ const { isLoading, data, error } = useHistoryVersionData(version.id);
14
+ const previewEditor = useEditor({
15
+ editable: false,
16
+ extensions: parentEditor.extensionManager.extensions.filter((e) => e.type !== "extension")
17
+ });
18
+ useEffect(() => {
19
+ if (data && previewEditor) {
20
+ const doc = new Doc();
21
+ applyUpdate(doc, data);
22
+ const root = doc.getXmlFragment("default");
23
+ const node = yXmlFragmentToProseMirrorRootNode(root, parentEditor.schema);
24
+ previewEditor.commands.setContent(node.toJSON());
25
+ }
26
+ }, [data, previewEditor, parentEditor]);
27
+ const restore = useCallback(() => {
28
+ parentEditor.commands.setContent(previewEditor?.getJSON() ?? "");
29
+ onVersionRestore?.(version);
30
+ }, [onVersionRestore, parentEditor, previewEditor, version]);
31
+ return /* @__PURE__ */ React.createElement("div", {
32
+ ...props,
33
+ className: classNames(
34
+ "lb-root lb-history-version-preview lb-tiptap-version-preview",
35
+ className
36
+ ),
37
+ ref: forwardedRef
38
+ }, isLoading ? /* @__PURE__ */ React.createElement("div", {
39
+ className: "lb-loading lb-history-version-preview-loading"
40
+ }, /* @__PURE__ */ React.createElement(SpinnerIcon, null)) : error ? /* @__PURE__ */ React.createElement("div", {
41
+ className: "lb-error lb-history-version-preview-error"
42
+ }, $.HISTORY_VERSION_PREVIEW_ERROR(error)) : /* @__PURE__ */ React.createElement("div", {
43
+ className: "lb-history-version-preview-content lb-tiptap-editor-container lb-tiptap-version-preview-editor-container"
44
+ }, /* @__PURE__ */ React.createElement(EditorContent, {
45
+ editor: previewEditor
46
+ })), /* @__PURE__ */ React.createElement("div", {
47
+ className: "lb-history-version-preview-footer"
48
+ }, /* @__PURE__ */ React.createElement("span", {
49
+ className: "lb-history-version-preview-authors"
50
+ }, $.HISTORY_VERSION_PREVIEW_AUTHORS_LIST(
51
+ /* @__PURE__ */ React.createElement(List, {
52
+ values: version.authors.map((author) => /* @__PURE__ */ React.createElement(User, {
53
+ key: author.id,
54
+ userId: author.id,
55
+ replaceSelf: true
56
+ })),
57
+ formatRemaining: $.LIST_REMAINING_USERS,
58
+ truncate: AUTHORS_TRUNCATE,
59
+ locale: $.locale
60
+ })
61
+ )), /* @__PURE__ */ React.createElement("div", {
62
+ className: "lb-history-version-preview-actions"
63
+ }, /* @__PURE__ */ React.createElement(Button, {
64
+ onClick: restore,
65
+ disabled: !data,
66
+ variant: "primary",
67
+ size: "large",
68
+ className: "lb-history-version-preview-action"
69
+ }, /* @__PURE__ */ React.createElement(RestoreIcon, {
70
+ className: "lb-button-icon"
71
+ }), /* @__PURE__ */ React.createElement("span", {
72
+ className: "lb-button-label"
73
+ }, $.HISTORY_VERSION_PREVIEW_RESTORE)))));
74
+ });
75
+
76
+ export { HistoryVersionPreview };
77
+ //# sourceMappingURL=HistoryVersionPreview.mjs.map