@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,65 @@
1
+ import { BaseMetadata, DM, ThreadData, HistoryVersion } from '@liveblocks/core';
2
+ import { ThreadProps, ComposerProps } from '@liveblocks/react-ui';
3
+ import { Editor } from '@tiptap/react';
4
+ import React, { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } from 'react';
5
+ import { BaseMetadata as BaseMetadata$1 } from '@liveblocks/client';
6
+ import { Extension } from '@tiptap/core';
7
+
8
+ declare type AnchoredThreadsComponents = {
9
+ Thread: ComponentType<ThreadProps>;
10
+ };
11
+ interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
12
+ /**
13
+ * The threads to display.
14
+ */
15
+ threads: ThreadData<M>[];
16
+ /**
17
+ * Override the component's components.
18
+ */
19
+ components?: Partial<AnchoredThreadsComponents>;
20
+ /**
21
+ * The tiptap editor
22
+ */
23
+ editor: Editor | null;
24
+ }
25
+ declare function AnchoredThreads({ threads, components, className, style, editor, ...props }: AnchoredThreadsProps): React.JSX.Element | null;
26
+
27
+ declare const FloatingComposer: React.ForwardRefExoticComponent<Omit<ComposerProps<BaseMetadata$1>, "threadId" | "commentId"> & {
28
+ editor: Editor | null;
29
+ } & React.RefAttributes<HTMLFormElement>>;
30
+
31
+ declare type ThreadPanelComponents = {
32
+ Thread: ComponentType<ThreadProps>;
33
+ };
34
+ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
35
+ /**
36
+ * The threads to display.
37
+ */
38
+ threads: ThreadData<M>[];
39
+ /**
40
+ * Override the component's components.
41
+ */
42
+ components?: Partial<ThreadPanelComponents>;
43
+ /**
44
+ * The tiptap editor
45
+ */
46
+ editor: Editor | null;
47
+ }
48
+ declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): React.JSX.Element | null;
49
+
50
+ declare const useLiveblocksExtension: () => Extension;
51
+
52
+ interface HistoryVersionPreviewProps extends ComponentPropsWithoutRef<"div"> {
53
+ version: HistoryVersion;
54
+ editor: Editor;
55
+ onVersionRestore?: (version: HistoryVersion) => void;
56
+ }
57
+ /**
58
+ * Displays a specific version of the current TipTap document.
59
+ *
60
+ * @example
61
+ * <HistoryVersionPreview version={version} />
62
+ */
63
+ declare const HistoryVersionPreview: React.ForwardRefExoticComponent<HistoryVersionPreviewProps & React.RefAttributes<HTMLDivElement>>;
64
+
65
+ export { AnchoredThreads, FloatingComposer, FloatingThreads, HistoryVersionPreview, useLiveblocksExtension };
@@ -0,0 +1,65 @@
1
+ import { BaseMetadata, DM, ThreadData, HistoryVersion } from '@liveblocks/core';
2
+ import { ThreadProps, ComposerProps } from '@liveblocks/react-ui';
3
+ import { Editor } from '@tiptap/react';
4
+ import React, { ComponentPropsWithoutRef, ComponentType, HTMLAttributes } from 'react';
5
+ import { BaseMetadata as BaseMetadata$1 } from '@liveblocks/client';
6
+ import { Extension } from '@tiptap/core';
7
+
8
+ declare type AnchoredThreadsComponents = {
9
+ Thread: ComponentType<ThreadProps>;
10
+ };
11
+ interface AnchoredThreadsProps<M extends BaseMetadata = DM> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
12
+ /**
13
+ * The threads to display.
14
+ */
15
+ threads: ThreadData<M>[];
16
+ /**
17
+ * Override the component's components.
18
+ */
19
+ components?: Partial<AnchoredThreadsComponents>;
20
+ /**
21
+ * The tiptap editor
22
+ */
23
+ editor: Editor | null;
24
+ }
25
+ declare function AnchoredThreads({ threads, components, className, style, editor, ...props }: AnchoredThreadsProps): React.JSX.Element | null;
26
+
27
+ declare const FloatingComposer: React.ForwardRefExoticComponent<Omit<ComposerProps<BaseMetadata$1>, "threadId" | "commentId"> & {
28
+ editor: Editor | null;
29
+ } & React.RefAttributes<HTMLFormElement>>;
30
+
31
+ declare type ThreadPanelComponents = {
32
+ Thread: ComponentType<ThreadProps>;
33
+ };
34
+ interface FloatingThreadsProps<M extends BaseMetadata = DM> extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
35
+ /**
36
+ * The threads to display.
37
+ */
38
+ threads: ThreadData<M>[];
39
+ /**
40
+ * Override the component's components.
41
+ */
42
+ components?: Partial<ThreadPanelComponents>;
43
+ /**
44
+ * The tiptap editor
45
+ */
46
+ editor: Editor | null;
47
+ }
48
+ declare function FloatingThreads({ threads, components, editor, ...props }: FloatingThreadsProps): React.JSX.Element | null;
49
+
50
+ declare const useLiveblocksExtension: () => Extension;
51
+
52
+ interface HistoryVersionPreviewProps extends ComponentPropsWithoutRef<"div"> {
53
+ version: HistoryVersion;
54
+ editor: Editor;
55
+ onVersionRestore?: (version: HistoryVersion) => void;
56
+ }
57
+ /**
58
+ * Displays a specific version of the current TipTap document.
59
+ *
60
+ * @example
61
+ * <HistoryVersionPreview version={version} />
62
+ */
63
+ declare const HistoryVersionPreview: React.ForwardRefExoticComponent<HistoryVersionPreviewProps & React.RefAttributes<HTMLDivElement>>;
64
+
65
+ export { AnchoredThreads, FloatingComposer, FloatingThreads, HistoryVersionPreview, useLiveblocksExtension };
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var core = require('@liveblocks/core');
4
+ var version = require('./version.js');
5
+ var AnchoredThreads = require('./comments/AnchoredThreads.js');
6
+ var FloatingComposer = require('./comments/FloatingComposer.js');
7
+ var FloatingThreads = require('./comments/FloatingThreads.js');
8
+ var LiveblocksExtension = require('./LiveblocksExtension.js');
9
+ var HistoryVersionPreview = require('./version-history/HistoryVersionPreview.js');
10
+
11
+ core.detectDupes(version.PKG_NAME, version.PKG_VERSION, version.PKG_FORMAT);
12
+
13
+ exports.AnchoredThreads = AnchoredThreads.AnchoredThreads;
14
+ exports.FloatingComposer = FloatingComposer.FloatingComposer;
15
+ exports.FloatingThreads = FloatingThreads.FloatingThreads;
16
+ exports.useLiveblocksExtension = LiveblocksExtension.useLiveblocksExtension;
17
+ exports.HistoryVersionPreview = HistoryVersionPreview.HistoryVersionPreview;
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n"],"names":["detectDupes","PKG_NAME","PKG_VERSION","PKG_FORMAT"],"mappings":";;;;;;;;;;AAIAA,gBAAY,CAAAC,gBAAA,EAAUC,qBAAaC,kBAAU,CAAA;;;;;;;;"}
package/dist/index.mjs ADDED
@@ -0,0 +1,10 @@
1
+ import { detectDupes } from '@liveblocks/core';
2
+ import { PKG_NAME, PKG_VERSION, PKG_FORMAT } from './version.mjs';
3
+ export { AnchoredThreads } from './comments/AnchoredThreads.mjs';
4
+ export { FloatingComposer } from './comments/FloatingComposer.mjs';
5
+ export { FloatingThreads } from './comments/FloatingThreads.mjs';
6
+ export { useLiveblocksExtension } from './LiveblocksExtension.mjs';
7
+ export { HistoryVersionPreview } from './version-history/HistoryVersionPreview.mjs';
8
+
9
+ detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
10
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import { detectDupes } from \"@liveblocks/core\";\n\nimport { PKG_FORMAT, PKG_NAME, PKG_VERSION } from \"./version\";\n\ndetectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);\n\nexport { AnchoredThreads } from \"./comments/AnchoredThreads\";\nexport { FloatingComposer } from \"./comments/FloatingComposer\";\nexport { FloatingThreads } from \"./comments/FloatingThreads\";\nexport { useLiveblocksExtension } from \"./LiveblocksExtension\";\nexport { HistoryVersionPreview } from \"./version-history/HistoryVersionPreview\";\n"],"names":[],"mappings":";;;;;;;;AAIA,WAAY,CAAA,QAAA,EAAU,aAAa,UAAU,CAAA"}
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var react = require('@liveblocks/react');
4
+ var React = require('react');
5
+ var classnames = require('../classnames.js');
6
+
7
+ const Avatar = React.forwardRef(
8
+ function Avatar2(props, forwardedRef) {
9
+ const { userId, className, ...spanProps } = props;
10
+ const { user, isLoading } = react.useUser(userId);
11
+ const avatar = user ? user.avatar : void 0;
12
+ const name = user ? user.name : void 0;
13
+ function Initials() {
14
+ const initials = name ? getInitials(name) : void 0;
15
+ if (initials) {
16
+ return /* @__PURE__ */ React.createElement("span", {
17
+ "aria-hidden": true,
18
+ className: "lb-avatar-fallback"
19
+ }, initials);
20
+ }
21
+ if (isLoading)
22
+ return null;
23
+ if (user === void 0)
24
+ return null;
25
+ return /* @__PURE__ */ React.createElement("span", {
26
+ "aria-label": userId,
27
+ title: userId,
28
+ className: "lb-avatar-fallback"
29
+ }, getInitials(userId));
30
+ }
31
+ return /* @__PURE__ */ React.createElement("span", {
32
+ "data-loading": isLoading ? "" : void 0,
33
+ ...spanProps,
34
+ className: classnames.classNames("lb-avatar", className),
35
+ ref: forwardedRef
36
+ }, avatar && /* @__PURE__ */ React.createElement("img", {
37
+ src: avatar,
38
+ alt: name,
39
+ className: "lb-avatar-image"
40
+ }), /* @__PURE__ */ React.createElement(Initials, null));
41
+ }
42
+ );
43
+ function getInitials(name) {
44
+ return name.trim().split(" ").reduce((initials, name2, index, array) => {
45
+ if (index === 0 || index === array.length - 1) {
46
+ initials += name2.charAt(0).toLocaleUpperCase();
47
+ }
48
+ return initials;
49
+ }, "");
50
+ }
51
+
52
+ exports.Avatar = Avatar;
53
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","sources":["../../src/mentions/Avatar.tsx"],"sourcesContent":["import { useUser } from \"@liveblocks/react\";\nimport type { HTMLAttributes } from \"react\";\nimport React, { forwardRef } from \"react\";\n\nimport { classNames } from \"../classnames\";\n\nexport interface AvatarProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n userId: string;\n}\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(\n function Avatar(props, forwardedRef) {\n const { userId, className, ...spanProps } = props;\n\n const { user, isLoading } = useUser(userId);\n\n const avatar = user ? user.avatar : undefined;\n\n const name = user ? user.name : undefined;\n\n function Initials() {\n const initials = name ? getInitials(name) : undefined;\n if (initials) {\n return (\n <span aria-hidden className=\"lb-avatar-fallback\">\n {initials}\n </span>\n );\n }\n\n if (isLoading) return null;\n\n if (user === undefined) return null;\n\n return (\n <span aria-label={userId} title={userId} className=\"lb-avatar-fallback\">\n {getInitials(userId)}\n </span>\n );\n }\n\n return (\n <span\n data-loading={isLoading ? \"\" : undefined}\n {...spanProps}\n className={classNames(\"lb-avatar\", className)}\n ref={forwardedRef}\n >\n {avatar && <img src={avatar} alt={name} className=\"lb-avatar-image\" />}\n\n <Initials />\n </span>\n );\n }\n);\n\nfunction getInitials(name: string) {\n return name\n .trim()\n .split(\" \")\n .reduce((initials, name, index, array) => {\n if (index === 0 || index === array.length - 1) {\n initials += name.charAt(0).toLocaleUpperCase();\n }\n\n return initials;\n }, \"\");\n}\n"],"names":["forwardRef","Avatar","useUser","classNames","name"],"mappings":";;;;;;AAWO,MAAM,MAAS,GAAAA,gBAAA;AAAA,EACpB,SAASC,OAAO,CAAA,KAAA,EAAO,YAAc,EAAA;AACnC,IAAA,MAAM,EAAE,MAAA,EAAQ,SAAc,EAAA,GAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AAE5C,IAAA,MAAM,EAAE,IAAA,EAAM,SAAU,EAAA,GAAIC,cAAQ,MAAM,CAAA,CAAA;AAE1C,IAAM,MAAA,MAAA,GAAS,IAAO,GAAA,IAAA,CAAK,MAAS,GAAA,KAAA,CAAA,CAAA;AAEpC,IAAM,MAAA,IAAA,GAAO,IAAO,GAAA,IAAA,CAAK,IAAO,GAAA,KAAA,CAAA,CAAA;AAEhC,IAAA,SAAS,QAAW,GAAA;AAClB,MAAA,MAAM,QAAW,GAAA,IAAA,GAAO,WAAY,CAAA,IAAI,CAAI,GAAA,KAAA,CAAA,CAAA;AAC5C,MAAA,IAAI,QAAU,EAAA;AACZ,QAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,UAAK,aAAW,EAAA,IAAA;AAAA,UAAC,SAAU,EAAA,oBAAA;AAAA,SAAA,EACzB,QACH,CAAA,CAAA;AAAA,OAEJ;AAEA,MAAI,IAAA,SAAA;AAAW,QAAO,OAAA,IAAA,CAAA;AAEtB,MAAA,IAAI,IAAS,KAAA,KAAA,CAAA;AAAW,QAAO,OAAA,IAAA,CAAA;AAE/B,MAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,QAAK,YAAY,EAAA,MAAA;AAAA,QAAQ,KAAO,EAAA,MAAA;AAAA,QAAQ,SAAU,EAAA,oBAAA;AAAA,OAChD,EAAA,WAAA,CAAY,MAAM,CACrB,CAAA,CAAA;AAAA,KAEJ;AAEA,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,MACC,cAAA,EAAc,YAAY,EAAK,GAAA,KAAA,CAAA;AAAA,MAC9B,GAAG,SAAA;AAAA,MACJ,SAAA,EAAWC,qBAAW,CAAA,WAAA,EAAa,SAAS,CAAA;AAAA,MAC5C,GAAK,EAAA,YAAA;AAAA,KAAA,EAEJ,0BAAW,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,MAAI,GAAK,EAAA,MAAA;AAAA,MAAQ,GAAK,EAAA,IAAA;AAAA,MAAM,SAAU,EAAA,iBAAA;AAAA,KAAkB,CAAA,kBAEnE,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,CACZ,CAAA,CAAA;AAAA,GAEJ;AACF,EAAA;AAEA,SAAS,YAAY,IAAc,EAAA;AACjC,EAAO,OAAA,IAAA,CACJ,IAAK,EAAA,CACL,KAAM,CAAA,GAAG,CACT,CAAA,MAAA,CAAO,CAAC,QAAA,EAAUC,KAAM,EAAA,KAAA,EAAO,KAAU,KAAA;AACxC,IAAA,IAAI,KAAU,KAAA,CAAA,IAAK,KAAU,KAAA,KAAA,CAAM,SAAS,CAAG,EAAA;AAC7C,MAAA,QAAA,IAAYA,KAAK,CAAA,MAAA,CAAO,CAAC,CAAA,CAAE,iBAAkB,EAAA,CAAA;AAAA,KAC/C;AAEA,IAAO,OAAA,QAAA,CAAA;AAAA,KACN,EAAE,CAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,51 @@
1
+ import { useUser } from '@liveblocks/react';
2
+ import React, { forwardRef } from 'react';
3
+ import { classNames } from '../classnames.mjs';
4
+
5
+ const Avatar = forwardRef(
6
+ function Avatar2(props, forwardedRef) {
7
+ const { userId, className, ...spanProps } = props;
8
+ const { user, isLoading } = useUser(userId);
9
+ const avatar = user ? user.avatar : void 0;
10
+ const name = user ? user.name : void 0;
11
+ function Initials() {
12
+ const initials = name ? getInitials(name) : void 0;
13
+ if (initials) {
14
+ return /* @__PURE__ */ React.createElement("span", {
15
+ "aria-hidden": true,
16
+ className: "lb-avatar-fallback"
17
+ }, initials);
18
+ }
19
+ if (isLoading)
20
+ return null;
21
+ if (user === void 0)
22
+ return null;
23
+ return /* @__PURE__ */ React.createElement("span", {
24
+ "aria-label": userId,
25
+ title: userId,
26
+ className: "lb-avatar-fallback"
27
+ }, getInitials(userId));
28
+ }
29
+ return /* @__PURE__ */ React.createElement("span", {
30
+ "data-loading": isLoading ? "" : void 0,
31
+ ...spanProps,
32
+ className: classNames("lb-avatar", className),
33
+ ref: forwardedRef
34
+ }, avatar && /* @__PURE__ */ React.createElement("img", {
35
+ src: avatar,
36
+ alt: name,
37
+ className: "lb-avatar-image"
38
+ }), /* @__PURE__ */ React.createElement(Initials, null));
39
+ }
40
+ );
41
+ function getInitials(name) {
42
+ return name.trim().split(" ").reduce((initials, name2, index, array) => {
43
+ if (index === 0 || index === array.length - 1) {
44
+ initials += name2.charAt(0).toLocaleUpperCase();
45
+ }
46
+ return initials;
47
+ }, "");
48
+ }
49
+
50
+ export { Avatar };
51
+ //# sourceMappingURL=Avatar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.mjs","sources":["../../src/mentions/Avatar.tsx"],"sourcesContent":["import { useUser } from \"@liveblocks/react\";\nimport type { HTMLAttributes } from \"react\";\nimport React, { forwardRef } from \"react\";\n\nimport { classNames } from \"../classnames\";\n\nexport interface AvatarProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n userId: string;\n}\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(\n function Avatar(props, forwardedRef) {\n const { userId, className, ...spanProps } = props;\n\n const { user, isLoading } = useUser(userId);\n\n const avatar = user ? user.avatar : undefined;\n\n const name = user ? user.name : undefined;\n\n function Initials() {\n const initials = name ? getInitials(name) : undefined;\n if (initials) {\n return (\n <span aria-hidden className=\"lb-avatar-fallback\">\n {initials}\n </span>\n );\n }\n\n if (isLoading) return null;\n\n if (user === undefined) return null;\n\n return (\n <span aria-label={userId} title={userId} className=\"lb-avatar-fallback\">\n {getInitials(userId)}\n </span>\n );\n }\n\n return (\n <span\n data-loading={isLoading ? \"\" : undefined}\n {...spanProps}\n className={classNames(\"lb-avatar\", className)}\n ref={forwardedRef}\n >\n {avatar && <img src={avatar} alt={name} className=\"lb-avatar-image\" />}\n\n <Initials />\n </span>\n );\n }\n);\n\nfunction getInitials(name: string) {\n return name\n .trim()\n .split(\" \")\n .reduce((initials, name, index, array) => {\n if (index === 0 || index === array.length - 1) {\n initials += name.charAt(0).toLocaleUpperCase();\n }\n\n return initials;\n }, \"\");\n}\n"],"names":["Avatar","name"],"mappings":";;;;AAWO,MAAM,MAAS,GAAA,UAAA;AAAA,EACpB,SAASA,OAAO,CAAA,KAAA,EAAO,YAAc,EAAA;AACnC,IAAA,MAAM,EAAE,MAAA,EAAQ,SAAc,EAAA,GAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AAE5C,IAAA,MAAM,EAAE,IAAA,EAAM,SAAU,EAAA,GAAI,QAAQ,MAAM,CAAA,CAAA;AAE1C,IAAM,MAAA,MAAA,GAAS,IAAO,GAAA,IAAA,CAAK,MAAS,GAAA,KAAA,CAAA,CAAA;AAEpC,IAAM,MAAA,IAAA,GAAO,IAAO,GAAA,IAAA,CAAK,IAAO,GAAA,KAAA,CAAA,CAAA;AAEhC,IAAA,SAAS,QAAW,GAAA;AAClB,MAAA,MAAM,QAAW,GAAA,IAAA,GAAO,WAAY,CAAA,IAAI,CAAI,GAAA,KAAA,CAAA,CAAA;AAC5C,MAAA,IAAI,QAAU,EAAA;AACZ,QAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,UAAK,aAAW,EAAA,IAAA;AAAA,UAAC,SAAU,EAAA,oBAAA;AAAA,SAAA,EACzB,QACH,CAAA,CAAA;AAAA,OAEJ;AAEA,MAAI,IAAA,SAAA;AAAW,QAAO,OAAA,IAAA,CAAA;AAEtB,MAAA,IAAI,IAAS,KAAA,KAAA,CAAA;AAAW,QAAO,OAAA,IAAA,CAAA;AAE/B,MAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,QAAK,YAAY,EAAA,MAAA;AAAA,QAAQ,KAAO,EAAA,MAAA;AAAA,QAAQ,SAAU,EAAA,oBAAA;AAAA,OAChD,EAAA,WAAA,CAAY,MAAM,CACrB,CAAA,CAAA;AAAA,KAEJ;AAEA,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA;AAAA,MACC,cAAA,EAAc,YAAY,EAAK,GAAA,KAAA,CAAA;AAAA,MAC9B,GAAG,SAAA;AAAA,MACJ,SAAA,EAAW,UAAW,CAAA,WAAA,EAAa,SAAS,CAAA;AAAA,MAC5C,GAAK,EAAA,YAAA;AAAA,KAAA,EAEJ,0BAAW,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,MAAI,GAAK,EAAA,MAAA;AAAA,MAAQ,GAAK,EAAA,IAAA;AAAA,MAAM,SAAU,EAAA,iBAAA;AAAA,KAAkB,CAAA,kBAEnE,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,CACZ,CAAA,CAAA;AAAA,GAEJ;AACF,EAAA;AAEA,SAAS,YAAY,IAAc,EAAA;AACjC,EAAO,OAAA,IAAA,CACJ,IAAK,EAAA,CACL,KAAM,CAAA,GAAG,CACT,CAAA,MAAA,CAAO,CAAC,QAAA,EAAUC,KAAM,EAAA,KAAA,EAAO,KAAU,KAAA;AACxC,IAAA,IAAI,KAAU,KAAA,CAAA,IAAK,KAAU,KAAA,KAAA,CAAM,SAAS,CAAG,EAAA;AAC7C,MAAA,QAAA,IAAYA,KAAK,CAAA,MAAA,CAAO,CAAC,CAAA,CAAE,iBAAkB,EAAA,CAAA;AAAA,KAC/C;AAEA,IAAO,OAAA,QAAA,CAAA;AAAA,KACN,EAAE,CAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var react = require('@tiptap/react');
4
+ var React = require('react');
5
+ var classnames = require('../classnames.js');
6
+ var MentionsList = require('./MentionsList.js');
7
+
8
+ const MENTION_CHARACTER = "@";
9
+ const Mention = React.forwardRef(
10
+ (props, forwardedRef) => {
11
+ const id = props.node.attrs.id;
12
+ const classnames$1 = classnames.classNames("lb-root", "lb-tiptap-mention", props.selected ? "lb-mention-selected" : null);
13
+ return /* @__PURE__ */ React.createElement(react.NodeViewWrapper, {
14
+ className: classnames$1,
15
+ as: "span",
16
+ ref: forwardedRef
17
+ }, MENTION_CHARACTER, /* @__PURE__ */ React.createElement(MentionsList.User, {
18
+ userId: id
19
+ }));
20
+ }
21
+ );
22
+
23
+ exports.Mention = Mention;
24
+ //# sourceMappingURL=Mention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mention.js","sources":["../../src/mentions/Mention.tsx"],"sourcesContent":["import type { Node } from \"@tiptap/pm/model\";\nimport { NodeViewWrapper } from \"@tiptap/react\";\nimport React, { forwardRef } from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { User } from \"./MentionsList\";\n\nconst MENTION_CHARACTER = \"@\";\n\nexport const Mention = forwardRef<HTMLSpanElement, { node: Node, selected: boolean }>(\n (props, forwardedRef) => {\n const id = (props.node.attrs as { id: string }).id;\n const classnames = classNames(\"lb-root\", \"lb-tiptap-mention\", props.selected ? \"lb-mention-selected\" : null);\n return (\n <NodeViewWrapper className={classnames} as=\"span\"\n ref={forwardedRef}>\n {MENTION_CHARACTER}\n <User userId={id} />\n </NodeViewWrapper>\n )\n }\n);\n"],"names":["forwardRef","classnames","classNames","NodeViewWrapper","User"],"mappings":";;;;;;;AAOA,MAAM,iBAAoB,GAAA,GAAA,CAAA;AAEnB,MAAM,OAAU,GAAAA,gBAAA;AAAA,EACrB,CAAC,OAAO,YAAiB,KAAA;AACvB,IAAM,MAAA,EAAA,GAAM,KAAM,CAAA,IAAA,CAAK,KAAyB,CAAA,EAAA,CAAA;AAChD,IAAA,MAAMC,eAAaC,qBAAW,CAAA,SAAA,EAAW,qBAAqB,KAAM,CAAA,QAAA,GAAW,wBAAwB,IAAI,CAAA,CAAA;AAC3G,IAAA,uBACG,KAAA,CAAA,aAAA,CAAAC,qBAAA,EAAA;AAAA,MAAgB,SAAW,EAAAF,YAAA;AAAA,MAAY,EAAG,EAAA,MAAA;AAAA,MACzC,GAAK,EAAA,YAAA;AAAA,KAAA,EACJ,mCACA,KAAA,CAAA,aAAA,CAAAG,iBAAA,EAAA;AAAA,MAAK,MAAQ,EAAA,EAAA;AAAA,KAAI,CACpB,CAAA,CAAA;AAAA,GAEJ;AACF;;;;"}
@@ -0,0 +1,22 @@
1
+ import { NodeViewWrapper } from '@tiptap/react';
2
+ import React, { forwardRef } from 'react';
3
+ import { classNames } from '../classnames.mjs';
4
+ import { User } from './MentionsList.mjs';
5
+
6
+ const MENTION_CHARACTER = "@";
7
+ const Mention = forwardRef(
8
+ (props, forwardedRef) => {
9
+ const id = props.node.attrs.id;
10
+ const classnames = classNames("lb-root", "lb-tiptap-mention", props.selected ? "lb-mention-selected" : null);
11
+ return /* @__PURE__ */ React.createElement(NodeViewWrapper, {
12
+ className: classnames,
13
+ as: "span",
14
+ ref: forwardedRef
15
+ }, MENTION_CHARACTER, /* @__PURE__ */ React.createElement(User, {
16
+ userId: id
17
+ }));
18
+ }
19
+ );
20
+
21
+ export { Mention };
22
+ //# sourceMappingURL=Mention.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mention.mjs","sources":["../../src/mentions/Mention.tsx"],"sourcesContent":["import type { Node } from \"@tiptap/pm/model\";\nimport { NodeViewWrapper } from \"@tiptap/react\";\nimport React, { forwardRef } from \"react\";\n\nimport { classNames } from \"../classnames\";\nimport { User } from \"./MentionsList\";\n\nconst MENTION_CHARACTER = \"@\";\n\nexport const Mention = forwardRef<HTMLSpanElement, { node: Node, selected: boolean }>(\n (props, forwardedRef) => {\n const id = (props.node.attrs as { id: string }).id;\n const classnames = classNames(\"lb-root\", \"lb-tiptap-mention\", props.selected ? \"lb-mention-selected\" : null);\n return (\n <NodeViewWrapper className={classnames} as=\"span\"\n ref={forwardedRef}>\n {MENTION_CHARACTER}\n <User userId={id} />\n </NodeViewWrapper>\n )\n }\n);\n"],"names":[],"mappings":";;;;;AAOA,MAAM,iBAAoB,GAAA,GAAA,CAAA;AAEnB,MAAM,OAAU,GAAA,UAAA;AAAA,EACrB,CAAC,OAAO,YAAiB,KAAA;AACvB,IAAM,MAAA,EAAA,GAAM,KAAM,CAAA,IAAA,CAAK,KAAyB,CAAA,EAAA,CAAA;AAChD,IAAA,MAAM,aAAa,UAAW,CAAA,SAAA,EAAW,qBAAqB,KAAM,CAAA,QAAA,GAAW,wBAAwB,IAAI,CAAA,CAAA;AAC3G,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA;AAAA,MAAgB,SAAW,EAAA,UAAA;AAAA,MAAY,EAAG,EAAA,MAAA;AAAA,MACzC,GAAK,EAAA,YAAA;AAAA,KAAA,EACJ,mCACA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA;AAAA,MAAK,MAAQ,EAAA,EAAA;AAAA,KAAI,CACpB,CAAA,CAAA;AAAA,GAEJ;AACF;;;;"}
@@ -0,0 +1,221 @@
1
+ 'use strict';
2
+
3
+ var core = require('@liveblocks/core');
4
+ var core$1 = require('@tiptap/core');
5
+ var model = require('@tiptap/pm/model');
6
+ var state = require('@tiptap/pm/state');
7
+ var react = require('@tiptap/react');
8
+ var Suggestion = require('@tiptap/suggestion');
9
+ var yProsemirror = require('y-prosemirror');
10
+ var types = require('../types.js');
11
+ var utils = require('../utils.js');
12
+ var Mention = require('./Mention.js');
13
+ var MentionsList = require('./MentionsList.js');
14
+
15
+ const mentionPasteHandler = () => {
16
+ return new state.Plugin({
17
+ key: types.LIVEBLOCKS_MENTION_PASTE_KEY,
18
+ props: {
19
+ transformPasted: (slice) => {
20
+ const getNewNotificationIds = (node) => {
21
+ if (node.type.name === types.LIVEBLOCKS_MENTION_TYPE) {
22
+ return node.type.create(
23
+ { ...node.attrs, notificationId: core.createInboxNotificationId() },
24
+ node.content
25
+ );
26
+ }
27
+ return node.copy(node.content);
28
+ };
29
+ const fragment = utils.mapFragment(slice.content, getNewNotificationIds);
30
+ return new model.Slice(fragment, slice.openStart, slice.openEnd);
31
+ }
32
+ }
33
+ });
34
+ };
35
+ const notifier = ({
36
+ onCreateMention,
37
+ onDeleteMention
38
+ }) => {
39
+ return new state.Plugin({
40
+ key: types.LIVEBLOCKS_MENTION_NOTIFIER_KEY,
41
+ appendTransaction: (transactions, oldState, newState) => {
42
+ const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
43
+ if (!docChanges) {
44
+ return;
45
+ }
46
+ if (transactions.some((transaction) => transaction.getMeta(yProsemirror.ySyncPluginKey))) {
47
+ return;
48
+ }
49
+ const transform = core$1.combineTransactionSteps(oldState.doc, [
50
+ ...transactions
51
+ ]);
52
+ const changes = core$1.getChangedRanges(transform);
53
+ changes.forEach(({ newRange, oldRange }) => {
54
+ const newMentions = utils.getMentionsFromNode(newState.doc, newRange);
55
+ const oldMentions = utils.getMentionsFromNode(oldState.doc, oldRange);
56
+ if (oldMentions.length || newMentions.length) {
57
+ newMentions.forEach((mention) => {
58
+ if (!oldMentions.includes(mention)) {
59
+ onCreateMention(mention.userId, mention.notificationId);
60
+ }
61
+ });
62
+ oldMentions.forEach((mention) => {
63
+ if (!newMentions.includes(mention)) {
64
+ onDeleteMention(mention.notificationId);
65
+ }
66
+ });
67
+ }
68
+ });
69
+ return void 0;
70
+ }
71
+ });
72
+ };
73
+ const MentionExtension = core$1.Node.create({
74
+ name: types.LIVEBLOCKS_MENTION_TYPE,
75
+ group: "inline",
76
+ inline: true,
77
+ selectable: true,
78
+ atom: true,
79
+ parseHTML() {
80
+ return [
81
+ {
82
+ tag: "liveblocks-mention"
83
+ }
84
+ ];
85
+ },
86
+ renderHTML({ HTMLAttributes }) {
87
+ return ["liveblocks-mention", core$1.mergeAttributes(HTMLAttributes)];
88
+ },
89
+ addNodeView() {
90
+ return react.ReactNodeViewRenderer(Mention.Mention, {
91
+ contentDOMElementTag: "span"
92
+ });
93
+ },
94
+ addAttributes() {
95
+ return {
96
+ id: {
97
+ default: null,
98
+ parseHTML: (element) => element.getAttribute("data-id"),
99
+ renderHTML: (attributes) => {
100
+ if (!attributes.id) {
101
+ return {};
102
+ }
103
+ return {
104
+ "data-id": attributes.id
105
+ };
106
+ }
107
+ },
108
+ notificationId: {
109
+ default: null,
110
+ parseHTML: (element) => element.getAttribute("data-notification-id"),
111
+ renderHTML: (attributes) => {
112
+ if (!attributes.notificationId) {
113
+ return {};
114
+ }
115
+ return {
116
+ "data-notification-id": attributes.notificationId
117
+ };
118
+ }
119
+ }
120
+ };
121
+ },
122
+ addKeyboardShortcuts() {
123
+ return {
124
+ Backspace: () => this.editor.commands.command(({ tr, state }) => {
125
+ let isMention = false;
126
+ const { selection } = state;
127
+ const { empty, anchor } = selection;
128
+ if (!empty) {
129
+ return false;
130
+ }
131
+ state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
132
+ if (node.type.name === this.name) {
133
+ isMention = true;
134
+ tr.insertText("", pos, pos + node.nodeSize);
135
+ }
136
+ });
137
+ return isMention;
138
+ })
139
+ };
140
+ },
141
+ addOptions() {
142
+ return {
143
+ onCreateMention: () => {
144
+ },
145
+ onDeleteMention: () => {
146
+ }
147
+ };
148
+ },
149
+ addProseMirrorPlugins() {
150
+ return [
151
+ Suggestion({
152
+ editor: this.editor,
153
+ char: "@",
154
+ pluginKey: types.LIVEBLOCKS_MENTION_KEY,
155
+ command: ({ editor, range, props }) => {
156
+ const nodeAfter = editor.view.state.selection.$to.nodeAfter;
157
+ const overrideSpace = nodeAfter?.text?.startsWith(" ");
158
+ if (overrideSpace) {
159
+ range.to += 1;
160
+ }
161
+ editor.chain().focus().insertContentAt(range, [
162
+ {
163
+ type: this.name,
164
+ attrs: props
165
+ },
166
+ {
167
+ type: "text",
168
+ text: " "
169
+ }
170
+ ]).run();
171
+ editor.view.dom.ownerDocument.defaultView?.getSelection()?.collapseToEnd();
172
+ },
173
+ allow: ({ state, range }) => {
174
+ const $from = state.doc.resolve(range.from);
175
+ const type = state.schema.nodes[this.name];
176
+ const allow = !!$from.parent.type.contentMatch.matchType(type);
177
+ return allow;
178
+ },
179
+ allowSpaces: true,
180
+ items: () => [],
181
+ render: () => {
182
+ let component;
183
+ return {
184
+ onStart: (props) => {
185
+ component = new react.ReactRenderer(MentionsList.MentionsList, {
186
+ props,
187
+ editor: props.editor
188
+ });
189
+ if (!props.clientRect) {
190
+ return;
191
+ }
192
+ document.body.appendChild(component.element);
193
+ },
194
+ onUpdate(props) {
195
+ component.updateProps(props);
196
+ },
197
+ onKeyDown(props) {
198
+ if (props.event.key === "Escape") {
199
+ component.updateProps({
200
+ ...props,
201
+ hide: true
202
+ });
203
+ return true;
204
+ }
205
+ return component.ref?.onKeyDown(props) ?? false;
206
+ },
207
+ onExit() {
208
+ document.body.removeChild(component.element);
209
+ component.destroy();
210
+ }
211
+ };
212
+ }
213
+ }),
214
+ notifier(this.options),
215
+ mentionPasteHandler()
216
+ ];
217
+ }
218
+ });
219
+
220
+ exports.MentionExtension = MentionExtension;
221
+ //# sourceMappingURL=MentionExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MentionExtension.js","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":["Plugin","LIVEBLOCKS_MENTION_PASTE_KEY","LIVEBLOCKS_MENTION_TYPE","createInboxNotificationId","mapFragment","Slice","LIVEBLOCKS_MENTION_NOTIFIER_KEY","ySyncPluginKey","combineTransactionSteps","getChangedRanges","getMentionsFromNode","Node","mergeAttributes","ReactNodeViewRenderer","Mention","LIVEBLOCKS_MENTION_KEY","ReactRenderer","MentionsList"],"mappings":"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"}