@blocknote/react 0.47.2 → 0.48.0
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.
- package/dist/FloatingComposerController-D4uLQfUX.js +89 -0
- package/dist/FloatingComposerController-D4uLQfUX.js.map +1 -0
- package/dist/FloatingComposerController-z3al33Dz.cjs +2 -0
- package/dist/FloatingComposerController-z3al33Dz.cjs.map +1 -0
- package/dist/FloatingThreadController-BMC2B9Lr.cjs +3 -0
- package/dist/FloatingThreadController-BMC2B9Lr.cjs.map +1 -0
- package/dist/FloatingThreadController-BuzLC5ea.js +398 -0
- package/dist/FloatingThreadController-BuzLC5ea.js.map +1 -0
- package/dist/blocknote-react.cjs +2 -35
- package/dist/blocknote-react.cjs.map +1 -1
- package/dist/blocknote-react.js +3244 -5773
- package/dist/blocknote-react.js.map +1 -1
- package/dist/defaultCommentEditorSchema-Bd70-hG9.js +229 -0
- package/dist/defaultCommentEditorSchema-Bd70-hG9.js.map +1 -0
- package/dist/defaultCommentEditorSchema-CxYfuFDM.cjs +2 -0
- package/dist/defaultCommentEditorSchema-CxYfuFDM.cjs.map +1 -0
- package/dist/rolldown-runtime-CAFD8bLK.js +11 -0
- package/dist/style.css +2 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +6 -6
- package/src/blocks/Audio/block.tsx +3 -0
- package/src/blocks/File/helpers/render/ResizableFileBlockWrapper.tsx +18 -16
- package/src/blocks/Image/block.tsx +4 -0
- package/src/blocks/Video/block.tsx +4 -0
- package/src/components/Comments/EmojiPicker.tsx +26 -28
- package/src/components/Popovers/GenericPopover.tsx +63 -16
- package/src/components/SideMenu/SideMenuController.tsx +38 -2
- package/src/components/TableHandles/TableHandlesController.tsx +38 -3
- package/src/editor/BlockNoteView.tsx +48 -24
- package/src/editor/ComponentsContext.tsx +1 -0
- package/src/editor/styles.css +7 -8
- package/src/hooks/useActiveStyles.ts +9 -0
- package/src/hooks/useEditorChange.ts +9 -0
- package/src/hooks/useEditorSelectionBoundingBox.ts +12 -0
- package/src/hooks/useEditorSelectionChange.ts +11 -0
- package/src/hooks/useEditorState.ts +1 -1
- package/src/hooks/useFocusWithin.ts +12 -0
- package/src/hooks/useOnUploadEnd.ts +8 -0
- package/src/hooks/useOnUploadStart.ts +8 -0
- package/src/hooks/usePrefersColorScheme.ts +9 -0
- package/src/hooks/useSelectedBlocks.ts +10 -0
- package/src/hooks/useUploadLoading.ts +7 -0
- package/src/schema/ReactBlockSpec.tsx +3 -0
- package/src/schema/ReactInlineContentSpec.tsx +13 -2
- package/src/schema/ReactStyleSpec.tsx +11 -2
- package/types/src/editor/ComponentsContext.d.ts +1 -0
- package/types/src/hooks/useActiveStyles.d.ts +9 -0
- package/types/src/hooks/useEditorChange.d.ts +9 -0
- package/types/src/hooks/useEditorSelectionBoundingBox.d.ts +12 -0
- package/types/src/hooks/useEditorSelectionChange.d.ts +11 -0
- package/types/src/hooks/useFocusWithin.d.ts +12 -0
- package/types/src/hooks/useOnUploadEnd.d.ts +8 -0
- package/types/src/hooks/useOnUploadStart.d.ts +8 -0
- package/types/src/hooks/usePrefersColorScheme.d.ts +9 -0
- package/types/src/hooks/useSelectedBlocks.d.ts +10 -0
- package/types/src/hooks/useUploadLoading.d.ts +7 -0
- package/types/src/schema/ReactInlineContentSpec.d.ts +13 -0
- package/types/src/schema/ReactStyleSpec.d.ts +11 -0
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
|
|
2
|
+
import { a as t, c as n, d as r, f as i, i as a, n as o, o as s, p as c, r as l, t as u } from "./defaultCommentEditorSchema-Bd70-hG9.js";
|
|
3
|
+
import { useMemo as d } from "react";
|
|
4
|
+
import { CommentsExtension as f } from "@blocknote/core/comments";
|
|
5
|
+
import { flip as p, offset as m, shift as h } from "@floating-ui/react";
|
|
6
|
+
import { mergeCSSClasses as g } from "@blocknote/core";
|
|
7
|
+
import { jsx as _ } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/Comments/FloatingComposer.tsx
|
|
9
|
+
function v() {
|
|
10
|
+
let e = r(f), t = n(), i = s(), a = l({
|
|
11
|
+
trailingBlock: !1,
|
|
12
|
+
dictionary: {
|
|
13
|
+
...i,
|
|
14
|
+
placeholders: { emptyDocument: i.placeholders.new_comment }
|
|
15
|
+
},
|
|
16
|
+
schema: e.commentEditorSchema || u
|
|
17
|
+
});
|
|
18
|
+
return /* @__PURE__ */ _(t.Comments.Card, {
|
|
19
|
+
className: "bn-thread",
|
|
20
|
+
children: /* @__PURE__ */ _(o, {
|
|
21
|
+
autoFocus: !0,
|
|
22
|
+
editable: !0,
|
|
23
|
+
editor: a,
|
|
24
|
+
actions: ({ isEmpty: n }) => /* @__PURE__ */ _(t.Generic.Toolbar.Root, {
|
|
25
|
+
className: g("bn-action-toolbar", "bn-comment-actions"),
|
|
26
|
+
variant: "action-toolbar",
|
|
27
|
+
children: /* @__PURE__ */ _(t.Generic.Toolbar.Button, {
|
|
28
|
+
className: "bn-button",
|
|
29
|
+
mainTooltip: "Save",
|
|
30
|
+
variant: "compact",
|
|
31
|
+
isDisabled: n,
|
|
32
|
+
onClick: async () => {
|
|
33
|
+
await e.createThread({ initialComment: { body: a.document } }), e.stopPendingComment();
|
|
34
|
+
},
|
|
35
|
+
children: "Save"
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/components/Comments/FloatingComposerController.tsx
|
|
43
|
+
var y = /* @__PURE__ */ e({ default: () => b });
|
|
44
|
+
function b(e) {
|
|
45
|
+
let n = c(), o = r(f), s = i(f, {
|
|
46
|
+
editor: n,
|
|
47
|
+
selector: (e) => e.pendingComment
|
|
48
|
+
}), l = t({
|
|
49
|
+
editor: n,
|
|
50
|
+
selector: ({ editor: e }) => s ? {
|
|
51
|
+
from: e.prosemirrorState.selection.from,
|
|
52
|
+
to: e.prosemirrorState.selection.to
|
|
53
|
+
} : void 0
|
|
54
|
+
}), u = d(() => ({
|
|
55
|
+
...e.floatingUIOptions,
|
|
56
|
+
useFloatingOptions: {
|
|
57
|
+
open: !!s,
|
|
58
|
+
onOpenChange: (e) => {
|
|
59
|
+
e || (o.stopPendingComment(), n.focus());
|
|
60
|
+
},
|
|
61
|
+
placement: "bottom",
|
|
62
|
+
middleware: [
|
|
63
|
+
m(10),
|
|
64
|
+
h(),
|
|
65
|
+
p()
|
|
66
|
+
],
|
|
67
|
+
...e.floatingUIOptions?.useFloatingOptions
|
|
68
|
+
},
|
|
69
|
+
focusManagerProps: { disabled: !1 },
|
|
70
|
+
elementProps: {
|
|
71
|
+
style: { zIndex: 60 },
|
|
72
|
+
...e.floatingUIOptions?.elementProps
|
|
73
|
+
}
|
|
74
|
+
}), [
|
|
75
|
+
o,
|
|
76
|
+
n,
|
|
77
|
+
s,
|
|
78
|
+
e.floatingUIOptions
|
|
79
|
+
]), g = e.floatingComposer || v;
|
|
80
|
+
return /* @__PURE__ */ _(a, {
|
|
81
|
+
position: l,
|
|
82
|
+
...u,
|
|
83
|
+
children: /* @__PURE__ */ _(g, {})
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { y as n, v as r, b as t };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=FloatingComposerController-D4uLQfUX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingComposerController-D4uLQfUX.js","names":[],"sources":["../src/components/Comments/FloatingComposer.tsx","../src/components/Comments/FloatingComposerController.tsx"],"sourcesContent":["import { mergeCSSClasses } from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\n\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useCreateBlockNote } from \"../../hooks/useCreateBlockNote.js\";\nimport { useExtension } from \"../../hooks/useExtension.js\";\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { CommentEditor } from \"./CommentEditor.js\";\nimport { defaultCommentEditorSchema } from \"./defaultCommentEditorSchema.js\";\n\n/**\n * The FloatingComposer component displays a comment editor \"floating\" card.\n *\n * It's used when the user highlights a parts of the document to create a new comment / thread.\n */\nexport function FloatingComposer() {\n const comments = useExtension(CommentsExtension);\n\n const Components = useComponentsContext()!;\n const dict = useDictionary();\n\n const newCommentEditor = useCreateBlockNote({\n trailingBlock: false,\n dictionary: {\n ...dict,\n placeholders: {\n emptyDocument: dict.placeholders.new_comment,\n },\n },\n schema: comments.commentEditorSchema || defaultCommentEditorSchema,\n });\n\n return (\n <Components.Comments.Card className={\"bn-thread\"}>\n <CommentEditor\n autoFocus={true}\n editable={true}\n editor={newCommentEditor}\n actions={({ isEmpty }) => (\n <Components.Generic.Toolbar.Root\n className={mergeCSSClasses(\n \"bn-action-toolbar\",\n \"bn-comment-actions\",\n )}\n variant=\"action-toolbar\"\n >\n <Components.Generic.Toolbar.Button\n className={\"bn-button\"}\n mainTooltip=\"Save\"\n variant=\"compact\"\n isDisabled={isEmpty}\n onClick={async () => {\n // (later) For REST API, we should implement a loading state and error state\n await comments.createThread({\n initialComment: {\n body: newCommentEditor.document,\n },\n });\n comments.stopPendingComment();\n }}\n >\n Save\n </Components.Generic.Toolbar.Button>\n </Components.Generic.Toolbar.Root>\n )}\n />\n </Components.Comments.Card>\n );\n}\n","import {\n BlockSchema,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\nimport { flip, offset, shift } from \"@floating-ui/react\";\nimport { ComponentProps, FC, useMemo } from \"react\";\n\nimport { useBlockNoteEditor } from \"../../hooks/useBlockNoteEditor.js\";\nimport { useEditorState } from \"../../hooks/useEditorState.js\";\nimport { useExtension, useExtensionState } from \"../../hooks/useExtension.js\";\nimport { FloatingUIOptions } from \"../Popovers/FloatingUIOptions.js\";\nimport { PositionPopover } from \"../Popovers/PositionPopover.js\";\nimport { FloatingComposer } from \"./FloatingComposer.js\";\n\nexport default function FloatingComposerController<\n B extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n>(props: {\n floatingComposer?: FC<ComponentProps<typeof FloatingComposer>>;\n floatingUIOptions?: FloatingUIOptions;\n}) {\n const editor = useBlockNoteEditor<B, I, S>();\n\n const comments = useExtension(CommentsExtension);\n\n const pendingComment = useExtensionState(CommentsExtension, {\n editor,\n selector: (state) => state.pendingComment,\n });\n\n const position = useEditorState({\n editor,\n selector: ({ editor }) =>\n pendingComment\n ? {\n from: editor.prosemirrorState.selection.from,\n to: editor.prosemirrorState.selection.to,\n }\n : undefined,\n });\n\n const floatingUIOptions = useMemo<FloatingUIOptions>(\n () => ({\n ...props.floatingUIOptions,\n useFloatingOptions: {\n open: !!pendingComment,\n // Needed as hooks like `useDismiss` call `onOpenChange` to change the\n // open state.\n onOpenChange: (open) => {\n if (!open) {\n comments.stopPendingComment();\n editor.focus();\n }\n },\n placement: \"bottom\",\n middleware: [offset(10), shift(), flip()],\n ...props.floatingUIOptions?.useFloatingOptions,\n },\n focusManagerProps: {\n disabled: false,\n },\n elementProps: {\n style: {\n zIndex: 60,\n },\n ...props.floatingUIOptions?.elementProps,\n },\n }),\n [comments, editor, pendingComment, props.floatingUIOptions],\n );\n\n // nice to have improvements would be:\n // - transition transform property so composer box animates when remote document is changed\n // - fade out on close\n\n const Component = props.floatingComposer || FloatingComposer;\n\n return (\n <PositionPopover position={position} {...floatingUIOptions}>\n <Component />\n </PositionPopover>\n );\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,IAAmB;CACjC,IAAM,IAAW,EAAa,EAAkB,EAE1C,IAAa,GAAsB,EACnC,IAAO,GAAe,EAEtB,IAAmB,EAAmB;EAC1C,eAAe;EACf,YAAY;GACV,GAAG;GACH,cAAc,EACZ,eAAe,EAAK,aAAa,aAClC;GACF;EACD,QAAQ,EAAS,uBAAuB;EACzC,CAAC;AAEF,QACE,kBAAC,EAAW,SAAS,MAArB;EAA0B,WAAW;YACnC,kBAAC,GAAD;GACE,WAAW;GACX,UAAU;GACV,QAAQ;GACR,UAAU,EAAE,iBACV,kBAAC,EAAW,QAAQ,QAAQ,MAA5B;IACE,WAAW,EACT,qBACA,qBACD;IACD,SAAQ;cAER,kBAAC,EAAW,QAAQ,QAAQ,QAA5B;KACE,WAAW;KACX,aAAY;KACZ,SAAQ;KACR,YAAY;KACZ,SAAS,YAAY;AAOnB,MALA,MAAM,EAAS,aAAa,EAC1B,gBAAgB,EACd,MAAM,EAAiB,UACxB,EACF,CAAC,EACF,EAAS,oBAAoB;;eAEhC;KAEmC,CAAA;IACJ,CAAA;GAEpC,CAAA;EACuB,CAAA;;;;;AC/C/B,SAAwB,EAItB,GAGC;CACD,IAAM,IAAS,GAA6B,EAEtC,IAAW,EAAa,EAAkB,EAE1C,IAAiB,EAAkB,GAAmB;EAC1D;EACA,WAAW,MAAU,EAAM;EAC5B,CAAC,EAEI,IAAW,EAAe;EAC9B;EACA,WAAW,EAAE,gBACX,IACI;GACE,MAAM,EAAO,iBAAiB,UAAU;GACxC,IAAI,EAAO,iBAAiB,UAAU;GACvC,GACD,KAAA;EACP,CAAC,EAEI,IAAoB,SACjB;EACL,GAAG,EAAM;EACT,oBAAoB;GAClB,MAAM,CAAC,CAAC;GAGR,eAAe,MAAS;AACtB,IAAK,MACH,EAAS,oBAAoB,EAC7B,EAAO,OAAO;;GAGlB,WAAW;GACX,YAAY;IAAC,EAAO,GAAG;IAAE,GAAO;IAAE,GAAM;IAAC;GACzC,GAAG,EAAM,mBAAmB;GAC7B;EACD,mBAAmB,EACjB,UAAU,IACX;EACD,cAAc;GACZ,OAAO,EACL,QAAQ,IACT;GACD,GAAG,EAAM,mBAAmB;GAC7B;EACF,GACD;EAAC;EAAU;EAAQ;EAAgB,EAAM;EAAkB,CAC5D,EAMK,IAAY,EAAM,oBAAoB;AAE5C,QACE,kBAAC,GAAD;EAA2B;EAAU,GAAI;YACvC,kBAAC,GAAD,EAAa,CAAA;EACG,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./defaultCommentEditorSchema-CxYfuFDM.cjs`);let t=require(`react`),n=require(`@blocknote/core/comments`),r=require(`@floating-ui/react`),i=require(`@blocknote/core`),a=require(`react/jsx-runtime`);function o(){let t=e.d(n.CommentsExtension),r=e.c(),o=e.o(),s=e.r({trailingBlock:!1,dictionary:{...o,placeholders:{emptyDocument:o.placeholders.new_comment}},schema:t.commentEditorSchema||e.t});return(0,a.jsx)(r.Comments.Card,{className:`bn-thread`,children:(0,a.jsx)(e.n,{autoFocus:!0,editable:!0,editor:s,actions:({isEmpty:e})=>(0,a.jsx)(r.Generic.Toolbar.Root,{className:(0,i.mergeCSSClasses)(`bn-action-toolbar`,`bn-comment-actions`),variant:`action-toolbar`,children:(0,a.jsx)(r.Generic.Toolbar.Button,{className:`bn-button`,mainTooltip:`Save`,variant:`compact`,isDisabled:e,onClick:async()=>{await t.createThread({initialComment:{body:s.document}}),t.stopPendingComment()},children:`Save`})})})})}var s=e.g({default:()=>c});function c(i){let s=e.p(),c=e.d(n.CommentsExtension),l=e.f(n.CommentsExtension,{editor:s,selector:e=>e.pendingComment}),u=e.a({editor:s,selector:({editor:e})=>l?{from:e.prosemirrorState.selection.from,to:e.prosemirrorState.selection.to}:void 0}),d=(0,t.useMemo)(()=>({...i.floatingUIOptions,useFloatingOptions:{open:!!l,onOpenChange:e=>{e||(c.stopPendingComment(),s.focus())},placement:`bottom`,middleware:[(0,r.offset)(10),(0,r.shift)(),(0,r.flip)()],...i.floatingUIOptions?.useFloatingOptions},focusManagerProps:{disabled:!1},elementProps:{style:{zIndex:60},...i.floatingUIOptions?.elementProps}}),[c,s,l,i.floatingUIOptions]),f=i.floatingComposer||o;return(0,a.jsx)(e.i,{position:u,...d,children:(0,a.jsx)(f,{})})}Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return c}});
|
|
2
|
+
//# sourceMappingURL=FloatingComposerController-z3al33Dz.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingComposerController-z3al33Dz.cjs","names":[],"sources":["../src/components/Comments/FloatingComposer.tsx","../src/components/Comments/FloatingComposerController.tsx"],"sourcesContent":["import { mergeCSSClasses } from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\n\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useCreateBlockNote } from \"../../hooks/useCreateBlockNote.js\";\nimport { useExtension } from \"../../hooks/useExtension.js\";\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { CommentEditor } from \"./CommentEditor.js\";\nimport { defaultCommentEditorSchema } from \"./defaultCommentEditorSchema.js\";\n\n/**\n * The FloatingComposer component displays a comment editor \"floating\" card.\n *\n * It's used when the user highlights a parts of the document to create a new comment / thread.\n */\nexport function FloatingComposer() {\n const comments = useExtension(CommentsExtension);\n\n const Components = useComponentsContext()!;\n const dict = useDictionary();\n\n const newCommentEditor = useCreateBlockNote({\n trailingBlock: false,\n dictionary: {\n ...dict,\n placeholders: {\n emptyDocument: dict.placeholders.new_comment,\n },\n },\n schema: comments.commentEditorSchema || defaultCommentEditorSchema,\n });\n\n return (\n <Components.Comments.Card className={\"bn-thread\"}>\n <CommentEditor\n autoFocus={true}\n editable={true}\n editor={newCommentEditor}\n actions={({ isEmpty }) => (\n <Components.Generic.Toolbar.Root\n className={mergeCSSClasses(\n \"bn-action-toolbar\",\n \"bn-comment-actions\",\n )}\n variant=\"action-toolbar\"\n >\n <Components.Generic.Toolbar.Button\n className={\"bn-button\"}\n mainTooltip=\"Save\"\n variant=\"compact\"\n isDisabled={isEmpty}\n onClick={async () => {\n // (later) For REST API, we should implement a loading state and error state\n await comments.createThread({\n initialComment: {\n body: newCommentEditor.document,\n },\n });\n comments.stopPendingComment();\n }}\n >\n Save\n </Components.Generic.Toolbar.Button>\n </Components.Generic.Toolbar.Root>\n )}\n />\n </Components.Comments.Card>\n );\n}\n","import {\n BlockSchema,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\nimport { flip, offset, shift } from \"@floating-ui/react\";\nimport { ComponentProps, FC, useMemo } from \"react\";\n\nimport { useBlockNoteEditor } from \"../../hooks/useBlockNoteEditor.js\";\nimport { useEditorState } from \"../../hooks/useEditorState.js\";\nimport { useExtension, useExtensionState } from \"../../hooks/useExtension.js\";\nimport { FloatingUIOptions } from \"../Popovers/FloatingUIOptions.js\";\nimport { PositionPopover } from \"../Popovers/PositionPopover.js\";\nimport { FloatingComposer } from \"./FloatingComposer.js\";\n\nexport default function FloatingComposerController<\n B extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema,\n>(props: {\n floatingComposer?: FC<ComponentProps<typeof FloatingComposer>>;\n floatingUIOptions?: FloatingUIOptions;\n}) {\n const editor = useBlockNoteEditor<B, I, S>();\n\n const comments = useExtension(CommentsExtension);\n\n const pendingComment = useExtensionState(CommentsExtension, {\n editor,\n selector: (state) => state.pendingComment,\n });\n\n const position = useEditorState({\n editor,\n selector: ({ editor }) =>\n pendingComment\n ? {\n from: editor.prosemirrorState.selection.from,\n to: editor.prosemirrorState.selection.to,\n }\n : undefined,\n });\n\n const floatingUIOptions = useMemo<FloatingUIOptions>(\n () => ({\n ...props.floatingUIOptions,\n useFloatingOptions: {\n open: !!pendingComment,\n // Needed as hooks like `useDismiss` call `onOpenChange` to change the\n // open state.\n onOpenChange: (open) => {\n if (!open) {\n comments.stopPendingComment();\n editor.focus();\n }\n },\n placement: \"bottom\",\n middleware: [offset(10), shift(), flip()],\n ...props.floatingUIOptions?.useFloatingOptions,\n },\n focusManagerProps: {\n disabled: false,\n },\n elementProps: {\n style: {\n zIndex: 60,\n },\n ...props.floatingUIOptions?.elementProps,\n },\n }),\n [comments, editor, pendingComment, props.floatingUIOptions],\n );\n\n // nice to have improvements would be:\n // - transition transform property so composer box animates when remote document is changed\n // - fade out on close\n\n const Component = props.floatingComposer || FloatingComposer;\n\n return (\n <PositionPopover position={position} {...floatingUIOptions}>\n <Component />\n </PositionPopover>\n );\n}\n"],"mappings":"sNAeA,SAAgB,GAAmB,CACjC,IAAM,EAAW,EAAA,EAAa,EAAA,kBAAkB,CAE1C,EAAa,EAAA,GAAsB,CACnC,EAAO,EAAA,GAAe,CAEtB,EAAmB,EAAA,EAAmB,CAC1C,cAAe,GACf,WAAY,CACV,GAAG,EACH,aAAc,CACZ,cAAe,EAAK,aAAa,YAClC,CACF,CACD,OAAQ,EAAS,qBAAuB,EAAA,EACzC,CAAC,CAEF,OACE,EAAA,EAAA,KAAC,EAAW,SAAS,KAArB,CAA0B,UAAW,sBACnC,EAAA,EAAA,KAAC,EAAA,EAAD,CACE,UAAW,GACX,SAAU,GACV,OAAQ,EACR,SAAU,CAAE,cACV,EAAA,EAAA,KAAC,EAAW,QAAQ,QAAQ,KAA5B,CACE,WAAA,EAAA,EAAA,iBACE,oBACA,qBACD,CACD,QAAQ,2BAER,EAAA,EAAA,KAAC,EAAW,QAAQ,QAAQ,OAA5B,CACE,UAAW,YACX,YAAY,OACZ,QAAQ,UACR,WAAY,EACZ,QAAS,SAAY,CAEnB,MAAM,EAAS,aAAa,CAC1B,eAAgB,CACd,KAAM,EAAiB,SACxB,CACF,CAAC,CACF,EAAS,oBAAoB,WAEhC,OAEmC,CAAA,CACJ,CAAA,CAEpC,CAAA,CACuB,CAAA,4BC/C/B,SAAwB,EAItB,EAGC,CACD,IAAM,EAAS,EAAA,GAA6B,CAEtC,EAAW,EAAA,EAAa,EAAA,kBAAkB,CAE1C,EAAiB,EAAA,EAAkB,EAAA,kBAAmB,CAC1D,SACA,SAAW,GAAU,EAAM,eAC5B,CAAC,CAEI,EAAW,EAAA,EAAe,CAC9B,SACA,UAAW,CAAE,YACX,EACI,CACE,KAAM,EAAO,iBAAiB,UAAU,KACxC,GAAI,EAAO,iBAAiB,UAAU,GACvC,CACD,IAAA,GACP,CAAC,CAEI,GAAA,EAAA,EAAA,cACG,CACL,GAAG,EAAM,kBACT,mBAAoB,CAClB,KAAM,CAAC,CAAC,EAGR,aAAe,GAAS,CACjB,IACH,EAAS,oBAAoB,CAC7B,EAAO,OAAO,GAGlB,UAAW,SACX,WAAY,cAAQ,GAAG,cAAS,aAAQ,CAAC,CACzC,GAAG,EAAM,mBAAmB,mBAC7B,CACD,kBAAmB,CACjB,SAAU,GACX,CACD,aAAc,CACZ,MAAO,CACL,OAAQ,GACT,CACD,GAAG,EAAM,mBAAmB,aAC7B,CACF,EACD,CAAC,EAAU,EAAQ,EAAgB,EAAM,kBAAkB,CAC5D,CAMK,EAAY,EAAM,kBAAoB,EAE5C,OACE,EAAA,EAAA,KAAC,EAAA,EAAD,CAA2B,WAAU,GAAI,YACvC,EAAA,EAAA,KAAC,EAAD,EAAa,CAAA,CACG,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const e=require(`./defaultCommentEditorSchema-CxYfuFDM.cjs`);let t=require(`react`);t=e._(t);let n=require(`@blocknote/core/comments`),r=require(`@floating-ui/react`),i=require(`@blocknote/core`),a=require(`react/jsx-runtime`),o=require(`react-icons/ri`);var s;async function c(){return s||(s=(async()=>{let[e,t]=await Promise.all([import(`emoji-mart`),import(`@emoji-mart/data`)]),n=`default`in e?e.default:e,r=`default`in t?t.default:t;return await n.init({data:r}),{emojiMart:n,emojiData:r}})(),s)}function l(e){let n=(0,t.useRef)(null),r=(0,t.useRef)(null);return r.current&&r.current.update(e),(0,t.useEffect)(()=>((async()=>{let{emojiMart:t}=await c();r.current=new t.Picker({...e,ref:n})})(),()=>{r.current=null}),[]),t.default.createElement(`div`,{ref:n})}var u=n=>{let[r,i]=(0,t.useState)(!1),o=e.c(),s=e.h(),c=s.editor?.portalElement;if(!c)throw Error(`Portal root not found`);return(0,a.jsxs)(o.Generic.Popover.Root,{open:r,portalRoot:c,children:[(0,a.jsx)(o.Generic.Popover.Trigger,{children:(0,a.jsx)(`div`,{onClick:e=>{e.preventDefault(),e.stopPropagation(),i(!r),n.onOpenChange?.(!r)},style:{display:`flex`,justifyContent:`center`,alignItems:`center`},children:n.children})}),(0,a.jsx)(o.Generic.Popover.Content,{className:`bn-emoji-picker-popover`,variant:`panel-popover`,children:(0,a.jsx)(l,{perLine:7,onClickOutside:()=>{i(!1),n.onOpenChange?.(!1)},onEmojiSelect:e=>{n.onEmojiSelect(e),i(!1),n.onOpenChange?.(!1)},theme:s?.colorSchemePreference})})]})};function d(e){return f([e]).get(e)}function f(r){let i=e.d(n.CommentsExtension).userStore,a=(0,t.useCallback)(()=>{let e=new Map;for(let t of r){let n=i.getUser(t);n&&e.set(t,n)}return e},[i,r]),o=(0,t.useMemo)(()=>({current:a()}),[a]);return(0,t.useSyncExternalStore)((0,t.useCallback)(e=>{let t=i.subscribe(t=>{o.current=a(),e()});return i.loadUsers(r),t},[i,a,r,o]),()=>o.current)}var p=r=>{let o=e.c(),s=e.o(),c=e.d(n.CommentsExtension),l=r.comment.reactions.find(e=>e.emoji===r.emoji);if(!l)throw Error(`Trying to render reaction badge for non-existing reaction`);let[u,d]=(0,t.useState)([]),p=f(u);return(0,a.jsx)(o.Generic.Badge.Root,{className:(0,i.mergeCSSClasses)(`bn-badge`,`bn-comment-reaction`),text:l.userIds.length.toString(),icon:l.emoji,isSelected:c.threadStore.auth.canDeleteReaction(r.comment,l.emoji),onClick:()=>r.onReactionSelect(l.emoji),onMouseEnter:()=>d(l.userIds),mainTooltip:s.comments.reactions.reacted_by,secondaryTooltip:`${Array.from(p.values()).map(e=>e.username).join(`
|
|
2
|
+
`)}`},l.emoji)},m=({comment:r,thread:s,showResolveButton:c})=>{let l=e.d(n.CommentsExtension),f=e.o(),m=e.r({initialContent:r.body,trailingBlock:!1,dictionary:{...f,placeholders:{emptyDocument:f.placeholders.edit_comment}},schema:l.commentEditorSchema||e.t}),h=e.c(),[g,_]=(0,t.useState)(!1),[v,y]=(0,t.useState)(!1),b=l.threadStore,x=(0,t.useCallback)(()=>{_(!0)},[]),S=(0,t.useCallback)(()=>{m.replaceBlocks(m.document,r.body),_(!1)},[m,r.body]),C=(0,t.useCallback)(async e=>{await b.updateComment({commentId:r.id,comment:{body:m.document},threadId:s.id}),_(!1)},[r,s.id,m,b]),w=(0,t.useCallback)(async()=>{await b.deleteComment({commentId:r.id,threadId:s.id})},[r,s.id,b]),T=(0,t.useCallback)(async e=>{b.auth.canAddReaction(r,e)?await b.addReaction({threadId:s.id,commentId:r.id,emoji:e}):b.auth.canDeleteReaction(r,e)&&await b.deleteReaction({threadId:s.id,commentId:r.id,emoji:e})},[b,r,s.id]),E=(0,t.useCallback)(async()=>{await b.resolveThread({threadId:s.id})},[s.id,b]),D=(0,t.useCallback)(async()=>{await b.unresolveThread({threadId:s.id})},[s.id,b]),O=d(r.userId);if(!r.body)return null;let k,A=b.auth.canAddReaction(r),j=b.auth.canDeleteComment(r),M=b.auth.canUpdateComment(r),N=c&&(s.resolved?b.auth.canUnresolveThread(s):b.auth.canResolveThread(s));g||(k=(0,a.jsxs)(h.Generic.Toolbar.Root,{className:(0,i.mergeCSSClasses)(`bn-action-toolbar`,`bn-comment-actions`),variant:`action-toolbar`,children:[A&&(0,a.jsx)(u,{onEmojiSelect:e=>T(e.native),onOpenChange:y,children:(0,a.jsx)(h.Generic.Toolbar.Button,{mainTooltip:f.comments.actions.add_reaction,variant:`compact`,children:(0,a.jsx)(o.RiEmotionLine,{size:16})},`add-reaction`)}),N&&(s.resolved?(0,a.jsx)(h.Generic.Toolbar.Button,{mainTooltip:`Re-open`,variant:`compact`,onClick:D,children:(0,a.jsx)(o.RiArrowGoBackFill,{size:16})},`reopen`):(0,a.jsx)(h.Generic.Toolbar.Button,{mainTooltip:f.comments.actions.resolve,variant:`compact`,onClick:E,children:(0,a.jsx)(o.RiCheckFill,{size:16})},`resolve`)),(j||M)&&(0,a.jsxs)(h.Generic.Menu.Root,{position:`bottom-start`,children:[(0,a.jsx)(h.Generic.Menu.Trigger,{children:(0,a.jsx)(h.Generic.Toolbar.Button,{mainTooltip:f.comments.actions.more_actions,variant:`compact`,children:(0,a.jsx)(o.RiMoreFill,{size:16})},`more-actions`)}),(0,a.jsxs)(h.Generic.Menu.Dropdown,{className:`bn-menu-dropdown`,children:[M&&(0,a.jsx)(h.Generic.Menu.Item,{icon:(0,a.jsx)(o.RiEditFill,{}),onClick:x,children:f.comments.actions.edit_comment},`edit-comment`),j&&(0,a.jsx)(h.Generic.Menu.Item,{icon:(0,a.jsx)(o.RiDeleteBinFill,{}),onClick:w,children:f.comments.actions.delete_comment},`delete-comment`)]})]})]}));let P=r.createdAt.toLocaleDateString(void 0,{month:`short`,day:`numeric`});if(!r.body)throw Error(`soft deletes are not yet supported`);return(0,a.jsx)(h.Comments.Comment,{authorInfo:O??`loading`,timeString:P,edited:r.updatedAt.getTime()!==r.createdAt.getTime(),showActions:`hover`,actions:k,className:`bn-thread-comment`,emojiPickerOpen:v,children:(0,a.jsx)(e.n,{autoFocus:g,editor:m,editable:g,actions:r.reactions.length>0||g?({isEmpty:e})=>(0,a.jsxs)(a.Fragment,{children:[r.reactions.length>0&&!g&&(0,a.jsxs)(h.Generic.Badge.Group,{className:(0,i.mergeCSSClasses)(`bn-badge-group`,`bn-comment-reactions`),children:[r.reactions.map(e=>(0,a.jsx)(p,{comment:r,emoji:e.emoji,onReactionSelect:T},e.emoji)),A&&(0,a.jsx)(u,{onEmojiSelect:e=>T(e.native),onOpenChange:y,children:(0,a.jsx)(h.Generic.Badge.Root,{className:(0,i.mergeCSSClasses)(`bn-badge`,`bn-comment-add-reaction`),text:`+`,icon:(0,a.jsx)(o.RiEmotionLine,{size:16}),mainTooltip:f.comments.actions.add_reaction})})]}),g&&(0,a.jsxs)(h.Generic.Toolbar.Root,{variant:`action-toolbar`,className:(0,i.mergeCSSClasses)(`bn-action-toolbar`,`bn-comment-actions`),children:[(0,a.jsx)(h.Generic.Toolbar.Button,{mainTooltip:f.comments.save_button_text,variant:`compact`,onClick:C,isDisabled:e,children:f.comments.save_button_text}),(0,a.jsx)(h.Generic.Toolbar.Button,{className:`bn-button`,mainTooltip:f.comments.cancel_button_text,variant:`compact`,onClick:S,children:f.comments.cancel_button_text})]})]}):void 0})})},h=({thread:t,maxCommentsBeforeCollapse:n})=>{let r=e.c(),i=e.o(),o=f(t.resolvedBy?[t.resolvedBy]:[]),s=t.comments.map((e,n)=>(0,a.jsx)(m,{thread:t,comment:e,showResolveButton:n===0},e.id+JSON.stringify(e.body||`{}`)));if(t.resolved&&t.resolvedUpdatedAt&&t.resolvedBy){if(!o.get(t.resolvedBy))throw Error(`User ${t.resolvedBy} resolved thread ${t.id}, but their data could not be found.`);let e=t.comments.findLastIndex(e=>t.resolvedUpdatedAt.getTime()>e.createdAt.getTime())+1;s.splice(e,0,(0,a.jsx)(r.Comments.Comment,{className:`bn-thread-comment`,authorInfo:t.resolvedBy&&o.get(t.resolvedBy)||`loading`,timeString:t.resolvedUpdatedAt.toLocaleDateString(void 0,{month:`short`,day:`numeric`}),edited:!1,showActions:!1,children:(0,a.jsx)(`div`,{className:`bn-resolved-text`,children:i.comments.sidebar.marked_as_resolved})},`resolved-comment`))}return n&&s.length>n&&s.splice(1,s.length-2,(0,a.jsx)(r.Comments.ExpandSectionsPrompt,{className:`bn-thread-expand-prompt`,children:i.comments.sidebar.more_replies(t.comments.length-2)},`expand-prompt`)),s},g=({thread:r,selected:o,referenceText:s,maxCommentsBeforeCollapse:c,onFocus:l,onBlur:u,tabIndex:d})=>{let f=e.c(),p=e.o(),m=e.d(n.CommentsExtension),g=e.r({trailingBlock:!1,dictionary:{...p,placeholders:{emptyDocument:p.placeholders.comment_reply}},schema:m.commentEditorSchema||e.t}),_=(0,t.useCallback)(async()=>{await m.threadStore.addComment({comment:{body:g.document},threadId:r.id}),g.removeBlocks(g.document)},[m,g,r.id]);return(0,a.jsxs)(f.Comments.Card,{className:`bn-thread`,headerText:s,onFocus:l,onBlur:u,selected:o,tabIndex:d,children:[(0,a.jsx)(f.Comments.CardSection,{className:`bn-thread-comments`,children:(0,a.jsx)(h,{thread:r,maxCommentsBeforeCollapse:o?void 0:c||5})}),o&&(0,a.jsx)(f.Comments.CardSection,{className:`bn-thread-composer`,children:(0,a.jsx)(e.n,{autoFocus:!1,editable:!0,editor:g,actions:({isEmpty:e})=>e?null:(0,a.jsx)(f.Generic.Toolbar.Root,{variant:`action-toolbar`,className:(0,i.mergeCSSClasses)(`bn-action-toolbar`,`bn-comment-actions`),children:(0,a.jsx)(f.Generic.Toolbar.Button,{mainTooltip:p.comments.save_button_text,variant:`compact`,isDisabled:e,onClick:_,children:p.comments.save_button_text})})})})]})};function _(){let r=e.d(n.CommentsExtension).threadStore,i=(0,t.useRef)(void 0);return i.current||=r.getThreads(),(0,t.useSyncExternalStore)((0,t.useCallback)(e=>r.subscribe(t=>{i.current=t,e()}),[r]),()=>i.current)}var v=e.g({default:()=>y});function y(i){let o=e.p(),s=e.d(n.CommentsExtension),c=e.f(n.CommentsExtension,{editor:o,selector:e=>e.selectedThreadId?{id:e.selectedThreadId,position:e.threadPositions.get(e.selectedThreadId)}:void 0}),l=_(),u=(0,t.useMemo)(()=>c?l.get(c.id):void 0,[c,l]),d=(0,t.useMemo)(()=>({...i.floatingUIOptions,useFloatingOptions:{open:!!c,onOpenChange:(e,t,n)=>{n===`escape-key`&&o.focus(),e||s.selectThread(void 0)},placement:`bottom`,middleware:[(0,r.offset)(10),(0,r.shift)(),(0,r.flip)()],...i.floatingUIOptions?.useFloatingOptions},focusManagerProps:{disabled:!0,...i.floatingUIOptions?.focusManagerProps},elementProps:{style:{zIndex:30},...i.floatingUIOptions?.elementProps}}),[s,o,i.floatingUIOptions,c]),f=i.floatingThread||g;return(0,a.jsx)(e.i,{position:c?.position,...d,children:u&&(0,a.jsx)(f,{thread:u,selected:!0})})}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return y}});
|
|
3
|
+
//# sourceMappingURL=FloatingThreadController-BMC2B9Lr.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FloatingThreadController-BMC2B9Lr.cjs","names":[],"sources":["../src/components/Comments/EmojiMartPicker.tsx","../src/components/Comments/EmojiPicker.tsx","../src/components/Comments/useUsers.ts","../src/components/Comments/ReactionBadge.tsx","../src/components/Comments/Comment.tsx","../src/components/Comments/Comments.tsx","../src/components/Comments/Thread.tsx","../src/components/Comments/useThreads.ts","../src/components/Comments/FloatingThreadController.tsx"],"sourcesContent":["// From https://github.com/missive/emoji-mart/blob/main/packages/emoji-mart-react/react.tsx\nimport type { EmojiMartData } from \"@emoji-mart/data\";\nimport React, { useEffect, useRef } from \"react\";\n\n// Temporary fix for https://github.com/missive/emoji-mart/pull/929\nlet emojiLoadingPromise:\n | Promise<{\n emojiMart: typeof import(\"emoji-mart\");\n emojiData: EmojiMartData;\n }>\n | undefined;\n\nasync function loadEmojiMart() {\n if (emojiLoadingPromise) {\n return emojiLoadingPromise;\n }\n\n emojiLoadingPromise = (async () => {\n // load dynamically because emoji-mart doesn't specify type: module and breaks in nodejs\n const [emojiMartModule, emojiDataModule] = await Promise.all([\n import(\"emoji-mart\"),\n // use a dynamic import to encourage bundle-splitting\n // and a smaller initial client bundle size\n import(\"@emoji-mart/data\"),\n ]);\n\n const emojiMart =\n \"default\" in emojiMartModule ? emojiMartModule.default : emojiMartModule;\n const emojiData =\n \"default\" in emojiDataModule\n ? (emojiDataModule.default as EmojiMartData)\n : (emojiDataModule as EmojiMartData);\n\n await emojiMart.init({ data: emojiData });\n\n return { emojiMart, emojiData };\n })();\n\n return emojiLoadingPromise;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default function EmojiPicker(props: any) {\n const ref = useRef(null);\n const instance = useRef(null) as any;\n\n if (instance.current) {\n instance.current.update(props);\n }\n\n useEffect(() => {\n (async () => {\n const { emojiMart } = await loadEmojiMart();\n\n instance.current = new emojiMart.Picker({ ...props, ref });\n })();\n\n return () => {\n instance.current = null;\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n return React.createElement(\"div\", { ref });\n}\n","import { ReactNode, useState } from \"react\";\n\nimport { useBlockNoteContext } from \"../../editor/BlockNoteContext.js\";\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport Picker from \"./EmojiMartPicker.js\";\n\nexport const EmojiPicker = (props: {\n onEmojiSelect: (emoji: { native: string }) => void;\n onOpenChange?: (open: boolean) => void;\n children: ReactNode;\n}) => {\n const [open, setOpen] = useState(false);\n\n const Components = useComponentsContext()!;\n const blockNoteContext = useBlockNoteContext()!;\n const portalRoot = blockNoteContext.editor?.portalElement;\n\n if (!portalRoot) {\n throw new Error(\"Portal root not found\");\n }\n\n return (\n <Components.Generic.Popover.Root open={open} portalRoot={portalRoot}>\n <Components.Generic.Popover.Trigger>\n <div\n onClick={(event) => {\n // Needed as the Picker component's onClickOutside handler\n // fires immediately after otherwise, preventing the popover\n // from opening.\n event.preventDefault();\n event.stopPropagation();\n setOpen(!open);\n props.onOpenChange?.(!open);\n }}\n style={{\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n >\n {props.children}\n </div>\n </Components.Generic.Popover.Trigger>\n <Components.Generic.Popover.Content\n className={\"bn-emoji-picker-popover\"}\n variant={\"panel-popover\"}\n >\n <Picker\n perLine={7}\n onClickOutside={() => {\n setOpen(false);\n props.onOpenChange?.(false);\n }}\n onEmojiSelect={(emoji: { native: string }) => {\n props.onEmojiSelect(emoji);\n setOpen(false);\n props.onOpenChange?.(false);\n }}\n theme={blockNoteContext?.colorSchemePreference}\n />\n </Components.Generic.Popover.Content>\n </Components.Generic.Popover.Root>\n );\n};\n","import { CommentsExtension } from \"@blocknote/core/comments\";\nimport { User } from \"@blocknote/core/comments\";\nimport { useCallback, useMemo, useSyncExternalStore } from \"react\";\n\nimport { useExtension } from \"../../hooks/useExtension.js\";\n\nexport function useUser(userId: string) {\n return useUsers([userId]).get(userId);\n}\n\n/**\n * Bridges the UserStore to React using useSyncExternalStore.\n */\nexport function useUsers(userIds: string[]) {\n const comments = useExtension(CommentsExtension);\n\n const store = comments.userStore;\n\n const getUpdatedSnapshot = useCallback(() => {\n const map = new Map<string, User>();\n for (const id of userIds) {\n const user = store.getUser(id);\n if (user) {\n map.set(id, user);\n }\n }\n return map;\n }, [store, userIds]);\n\n // this ref / memoworks around this error:\n // https://react.dev/reference/react/useSyncExternalStore#im-getting-an-error-the-result-of-getsnapshot-should-be-cached\n // however, might not be a good practice to work around it this way\n\n // We need to use a memo instead of a ref to make sure the snapshot is updated when the userIds change\n const ref = useMemo(() => {\n return {\n current: getUpdatedSnapshot(),\n };\n }, [getUpdatedSnapshot]);\n\n // note: this is inefficient as it will trigger a re-render even if other users (not in userIds) are updated\n const subscribe = useCallback(\n (cb: () => void) => {\n const ret = store.subscribe((_users) => {\n // update ref when changed\n ref.current = getUpdatedSnapshot();\n\n // calling cb() will make sure `useSyncExternalStore` will fetch the latest snapshot (which is ref.current)\n cb();\n });\n store.loadUsers(userIds);\n return ret;\n },\n [store, getUpdatedSnapshot, userIds, ref],\n );\n\n return useSyncExternalStore(subscribe, () => ref.current!);\n}\n","import { mergeCSSClasses } from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\nimport { CommentData } from \"@blocknote/core/comments\";\nimport { useState } from \"react\";\n\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useUsers } from \"./useUsers.js\";\nimport { useExtension } from \"../../hooks/useExtension.js\";\n\nexport const ReactionBadge = (props: {\n comment: CommentData;\n emoji: string;\n onReactionSelect: (emoji: string) => void;\n}) => {\n const Components = useComponentsContext()!;\n const dict = useDictionary();\n\n const comments = useExtension(CommentsExtension);\n\n const reaction = props.comment.reactions.find(\n (reaction) => reaction.emoji === props.emoji,\n );\n if (!reaction) {\n throw new Error(\n \"Trying to render reaction badge for non-existing reaction\",\n );\n }\n\n const [userIds, setUserIds] = useState<string[]>([]);\n const users = useUsers(userIds);\n\n return (\n <Components.Generic.Badge.Root\n key={reaction.emoji}\n className={mergeCSSClasses(\"bn-badge\", \"bn-comment-reaction\")}\n text={reaction.userIds.length.toString()}\n icon={reaction.emoji}\n isSelected={comments.threadStore.auth.canDeleteReaction(\n props.comment,\n reaction.emoji,\n )}\n onClick={() => props.onReactionSelect(reaction.emoji)}\n onMouseEnter={() => setUserIds(reaction.userIds)}\n mainTooltip={dict.comments.reactions.reacted_by}\n secondaryTooltip={`${Array.from(users.values())\n .map((user) => user.username)\n .join(\"\\n\")}`}\n />\n );\n};\n","\"use client\";\n\nimport { mergeCSSClasses } from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\nimport type { CommentData, ThreadData } from \"@blocknote/core/comments\";\nimport { MouseEvent, ReactNode, useCallback, useState } from \"react\";\nimport {\n RiArrowGoBackFill,\n RiCheckFill,\n RiDeleteBinFill,\n RiEditFill,\n RiEmotionLine,\n RiMoreFill,\n} from \"react-icons/ri\";\n\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useCreateBlockNote } from \"../../hooks/useCreateBlockNote.js\";\nimport { useExtension } from \"../../hooks/useExtension.js\";\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { CommentEditor } from \"./CommentEditor.js\";\nimport { EmojiPicker } from \"./EmojiPicker.js\";\nimport { ReactionBadge } from \"./ReactionBadge.js\";\nimport { defaultCommentEditorSchema } from \"./defaultCommentEditorSchema.js\";\nimport { useUser } from \"./useUsers.js\";\n\nexport type CommentProps = {\n comment: CommentData;\n thread: ThreadData;\n showResolveButton?: boolean;\n};\n\n/**\n * The Comment component displays a single comment with actions,\n * a reaction list and an editor when editing.\n *\n * It's generally used in the `Thread` component for comments that have already been created.\n *\n */\nexport const Comment = ({\n comment,\n thread,\n showResolveButton,\n}: CommentProps) => {\n // TODO: if REST API becomes popular, all interactions (click handlers) should implement a loading state and error state\n // (or optimistic local updates)\n const comments = useExtension(CommentsExtension);\n\n const dict = useDictionary();\n\n const commentEditor = useCreateBlockNote({\n initialContent: comment.body,\n trailingBlock: false,\n dictionary: {\n ...dict,\n placeholders: {\n emptyDocument: dict.placeholders.edit_comment,\n },\n },\n schema: comments.commentEditorSchema || defaultCommentEditorSchema,\n });\n\n const Components = useComponentsContext()!;\n\n const [isEditing, setEditing] = useState(false);\n const [emojiPickerOpen, setEmojiPickerOpen] = useState(false);\n\n const threadStore = comments.threadStore;\n\n const handleEdit = useCallback(() => {\n setEditing(true);\n }, []);\n\n const onEditCancel = useCallback(() => {\n commentEditor.replaceBlocks(commentEditor.document, comment.body);\n setEditing(false);\n }, [commentEditor, comment.body]);\n\n const onEditSubmit = useCallback(\n async (_event: MouseEvent) => {\n await threadStore.updateComment({\n commentId: comment.id,\n comment: {\n body: commentEditor.document,\n },\n threadId: thread.id,\n });\n\n setEditing(false);\n },\n [comment, thread.id, commentEditor, threadStore],\n );\n\n const onDelete = useCallback(async () => {\n await threadStore.deleteComment({\n commentId: comment.id,\n threadId: thread.id,\n });\n }, [comment, thread.id, threadStore]);\n\n const onReactionSelect = useCallback(\n async (emoji: string) => {\n if (threadStore.auth.canAddReaction(comment, emoji)) {\n await threadStore.addReaction({\n threadId: thread.id,\n commentId: comment.id,\n emoji,\n });\n } else if (threadStore.auth.canDeleteReaction(comment, emoji)) {\n await threadStore.deleteReaction({\n threadId: thread.id,\n commentId: comment.id,\n emoji,\n });\n }\n },\n [threadStore, comment, thread.id],\n );\n\n const onResolve = useCallback(async () => {\n await threadStore.resolveThread({\n threadId: thread.id,\n });\n }, [thread.id, threadStore]);\n\n const onReopen = useCallback(async () => {\n await threadStore.unresolveThread({\n threadId: thread.id,\n });\n }, [thread.id, threadStore]);\n\n const user = useUser(comment.userId);\n\n if (!comment.body) {\n return null;\n }\n\n let actions: ReactNode | undefined = undefined;\n const canAddReaction = threadStore.auth.canAddReaction(comment);\n const canDeleteComment = threadStore.auth.canDeleteComment(comment);\n const canEditComment = threadStore.auth.canUpdateComment(comment);\n\n const showResolveOrReopen =\n showResolveButton &&\n (thread.resolved\n ? threadStore.auth.canUnresolveThread(thread)\n : threadStore.auth.canResolveThread(thread));\n\n if (!isEditing) {\n actions = (\n <Components.Generic.Toolbar.Root\n className={mergeCSSClasses(\"bn-action-toolbar\", \"bn-comment-actions\")}\n variant={\"action-toolbar\"}\n >\n {canAddReaction && (\n <EmojiPicker\n onEmojiSelect={(emoji: { native: string }) =>\n onReactionSelect(emoji.native)\n }\n onOpenChange={setEmojiPickerOpen}\n >\n <Components.Generic.Toolbar.Button\n key={\"add-reaction\"}\n mainTooltip={dict.comments.actions.add_reaction}\n variant=\"compact\"\n >\n <RiEmotionLine size={16} />\n </Components.Generic.Toolbar.Button>\n </EmojiPicker>\n )}\n {showResolveOrReopen &&\n (thread.resolved ? (\n <Components.Generic.Toolbar.Button\n key={\"reopen\"}\n mainTooltip=\"Re-open\"\n variant=\"compact\"\n onClick={onReopen}\n >\n <RiArrowGoBackFill size={16} />\n </Components.Generic.Toolbar.Button>\n ) : (\n <Components.Generic.Toolbar.Button\n key={\"resolve\"}\n mainTooltip={dict.comments.actions.resolve}\n variant=\"compact\"\n onClick={onResolve}\n >\n <RiCheckFill size={16} />\n </Components.Generic.Toolbar.Button>\n ))}\n {(canDeleteComment || canEditComment) && (\n <Components.Generic.Menu.Root position={\"bottom-start\"}>\n <Components.Generic.Menu.Trigger>\n <Components.Generic.Toolbar.Button\n key={\"more-actions\"}\n mainTooltip={dict.comments.actions.more_actions}\n variant=\"compact\"\n >\n <RiMoreFill size={16} />\n </Components.Generic.Toolbar.Button>\n </Components.Generic.Menu.Trigger>\n <Components.Generic.Menu.Dropdown className={\"bn-menu-dropdown\"}>\n {canEditComment && (\n <Components.Generic.Menu.Item\n key={\"edit-comment\"}\n icon={<RiEditFill />}\n onClick={handleEdit}\n >\n {dict.comments.actions.edit_comment}\n </Components.Generic.Menu.Item>\n )}\n {canDeleteComment && (\n <Components.Generic.Menu.Item\n key={\"delete-comment\"}\n icon={<RiDeleteBinFill />}\n onClick={onDelete}\n >\n {dict.comments.actions.delete_comment}\n </Components.Generic.Menu.Item>\n )}\n </Components.Generic.Menu.Dropdown>\n </Components.Generic.Menu.Root>\n )}\n </Components.Generic.Toolbar.Root>\n );\n }\n\n const timeString = comment.createdAt.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n });\n\n if (!comment.body) {\n throw new Error(\"soft deletes are not yet supported\");\n }\n\n return (\n <Components.Comments.Comment\n authorInfo={user ?? \"loading\"}\n timeString={timeString}\n edited={comment.updatedAt.getTime() !== comment.createdAt.getTime()}\n showActions={\"hover\"}\n actions={actions}\n className={\"bn-thread-comment\"}\n emojiPickerOpen={emojiPickerOpen}\n >\n <CommentEditor\n autoFocus={isEditing}\n editor={commentEditor}\n editable={isEditing}\n actions={\n comment.reactions.length > 0 || isEditing\n ? ({ isEmpty }) => (\n <>\n {comment.reactions.length > 0 && !isEditing && (\n <Components.Generic.Badge.Group\n className={mergeCSSClasses(\n \"bn-badge-group\",\n \"bn-comment-reactions\",\n )}\n >\n {comment.reactions.map((reaction) => (\n <ReactionBadge\n key={reaction.emoji}\n comment={comment}\n emoji={reaction.emoji}\n onReactionSelect={onReactionSelect}\n />\n ))}\n {canAddReaction && (\n <EmojiPicker\n onEmojiSelect={(emoji: { native: string }) =>\n onReactionSelect(emoji.native)\n }\n onOpenChange={setEmojiPickerOpen}\n >\n <Components.Generic.Badge.Root\n className={mergeCSSClasses(\n \"bn-badge\",\n \"bn-comment-add-reaction\",\n )}\n text={\"+\"}\n icon={<RiEmotionLine size={16} />}\n mainTooltip={dict.comments.actions.add_reaction}\n />\n </EmojiPicker>\n )}\n </Components.Generic.Badge.Group>\n )}\n {isEditing && (\n <Components.Generic.Toolbar.Root\n variant=\"action-toolbar\"\n className={mergeCSSClasses(\n \"bn-action-toolbar\",\n \"bn-comment-actions\",\n )}\n >\n <Components.Generic.Toolbar.Button\n mainTooltip={dict.comments.save_button_text}\n variant=\"compact\"\n onClick={onEditSubmit}\n isDisabled={isEmpty}\n >\n {dict.comments.save_button_text}\n </Components.Generic.Toolbar.Button>\n <Components.Generic.Toolbar.Button\n className={\"bn-button\"}\n mainTooltip={dict.comments.cancel_button_text}\n variant=\"compact\"\n onClick={onEditCancel}\n >\n {dict.comments.cancel_button_text}\n </Components.Generic.Toolbar.Button>\n </Components.Generic.Toolbar.Root>\n )}\n </>\n )\n : undefined\n }\n />\n </Components.Comments.Comment>\n );\n};\n","import { ThreadData } from \"@blocknote/core/comments\";\n\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { Comment } from \"./Comment.js\";\nimport { useUsers } from \"./useUsers.js\";\n\nexport type CommentsProps = {\n thread: ThreadData;\n maxCommentsBeforeCollapse?: number;\n};\n\nexport const Comments = ({\n thread,\n maxCommentsBeforeCollapse,\n}: CommentsProps) => {\n const Components = useComponentsContext()!;\n const dict = useDictionary();\n const users = useUsers(thread.resolvedBy ? [thread.resolvedBy] : []);\n\n // Maps all comments to elements.\n const comments = thread.comments.map((comment, index) => (\n <Comment\n key={comment.id + JSON.stringify(comment.body || \"{}\")}\n thread={thread}\n comment={comment}\n showResolveButton={index === 0}\n />\n ));\n\n // Adds \"resolved by\" comment if needed.\n if (thread.resolved && thread.resolvedUpdatedAt && thread.resolvedBy) {\n const resolvedByUser = users.get(thread.resolvedBy);\n if (!resolvedByUser) {\n throw new Error(\n `User ${thread.resolvedBy} resolved thread ${thread.id}, but their data could not be found.`,\n );\n }\n\n const resolvedCommentIndex =\n thread.comments.findLastIndex(\n (comment) =>\n thread.resolvedUpdatedAt!.getTime() > comment.createdAt.getTime(),\n ) + 1;\n\n comments.splice(\n resolvedCommentIndex,\n 0,\n <Components.Comments.Comment\n key={\"resolved-comment\"}\n className={\"bn-thread-comment\"}\n authorInfo={\n (thread.resolvedBy && users.get(thread.resolvedBy)) || \"loading\"\n }\n timeString={thread.resolvedUpdatedAt.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n })}\n edited={false}\n showActions={false}\n >\n <div className={\"bn-resolved-text\"}>\n {dict.comments.sidebar.marked_as_resolved}\n </div>\n </Components.Comments.Comment>,\n );\n }\n\n // Collapses replies if needed.\n if (\n maxCommentsBeforeCollapse &&\n comments.length > maxCommentsBeforeCollapse\n ) {\n comments.splice(\n 1,\n comments.length - 2,\n <Components.Comments.ExpandSectionsPrompt\n key={\"expand-prompt\"}\n className={\"bn-thread-expand-prompt\"}\n >\n {dict.comments.sidebar.more_replies(thread.comments.length - 2)}\n </Components.Comments.ExpandSectionsPrompt>,\n );\n }\n\n return comments;\n};\n","import { mergeCSSClasses } from \"@blocknote/core\";\nimport { CommentsExtension } from \"@blocknote/core/comments\";\nimport { ThreadData } from \"@blocknote/core/comments\";\nimport { FocusEvent, useCallback } from \"react\";\n\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useCreateBlockNote } from \"../../hooks/useCreateBlockNote.js\";\nimport { useExtension } from \"../../hooks/useExtension.js\";\nimport { useDictionary } from \"../../i18n/dictionary.js\";\nimport { CommentEditor } from \"./CommentEditor.js\";\nimport { Comments } from \"./Comments.js\";\nimport { defaultCommentEditorSchema } from \"./defaultCommentEditorSchema.js\";\n\nexport type ThreadProps = {\n /**\n * The thread to display - you can use the `useThreads` hook to retrieve a\n * `Map` of all threads in the editor, mapped by their IDs.\n */\n thread: ThreadData;\n /**\n * A boolean flag for whether the thread is selected. Selected threads show an\n * editor for replies, and add a `selected` CSS class to the thread.\n */\n selected?: boolean;\n /**\n * The text in the editor that the thread refers to. See the\n * [`ThreadsSidebar`](https://github.com/TypeCellOS/BlockNote/tree/main/packages/react/src/components/Comments/ThreadsSidebar.tsx#L137)\n * component to find out how to get this.\n */\n referenceText?: string;\n /**\n * The maximum number of comments that can be in a thread before the replies\n * get collapsed.\n */\n maxCommentsBeforeCollapse?: number;\n /**\n * A function to call when the thread is focused.\n */\n onFocus?: (event: FocusEvent) => void;\n /**\n * A function to call when the thread is blurred.\n */\n onBlur?: (event: FocusEvent) => void;\n /**\n * The tab index for the thread.\n */\n tabIndex?: number;\n};\n\n/**\n * The Thread component displays a (main) comment with a list of replies (other comments).\n *\n * It also includes a composer to reply to the thread.\n */\nexport const Thread = ({\n thread,\n selected,\n referenceText,\n maxCommentsBeforeCollapse,\n onFocus,\n onBlur,\n tabIndex,\n}: ThreadProps) => {\n // TODO: if REST API becomes popular, all interactions (click handlers) should implement a loading state and error state\n // (or optimistic local updates)\n\n const Components = useComponentsContext()!;\n const dict = useDictionary();\n\n const comments = useExtension(CommentsExtension);\n\n const newCommentEditor = useCreateBlockNote({\n trailingBlock: false,\n dictionary: {\n ...dict,\n placeholders: {\n emptyDocument: dict.placeholders.comment_reply,\n },\n },\n schema: comments.commentEditorSchema || defaultCommentEditorSchema,\n });\n\n const onNewCommentSave = useCallback(async () => {\n await comments.threadStore.addComment({\n comment: {\n body: newCommentEditor.document,\n },\n threadId: thread.id,\n });\n\n // reset editor\n newCommentEditor.removeBlocks(newCommentEditor.document);\n }, [comments, newCommentEditor, thread.id]);\n\n return (\n <Components.Comments.Card\n className={\"bn-thread\"}\n headerText={referenceText}\n onFocus={onFocus}\n onBlur={onBlur}\n selected={selected}\n tabIndex={tabIndex}\n >\n <Components.Comments.CardSection className=\"bn-thread-comments\">\n <Comments\n thread={thread}\n maxCommentsBeforeCollapse={\n !selected ? maxCommentsBeforeCollapse || 5 : undefined\n }\n />\n </Components.Comments.CardSection>\n {selected && (\n <Components.Comments.CardSection className={\"bn-thread-composer\"}>\n <CommentEditor\n autoFocus={false}\n editable={true}\n editor={newCommentEditor}\n actions={({ isEmpty }) => {\n if (isEmpty) {\n return null;\n }\n\n return (\n <Components.Generic.Toolbar.Root\n variant=\"action-toolbar\"\n className={mergeCSSClasses(\n \"bn-action-toolbar\",\n \"bn-comment-actions\",\n )}\n >\n <Components.Generic.Toolbar.Button\n mainTooltip={dict.comments.save_button_text}\n variant=\"compact\"\n isDisabled={isEmpty}\n onClick={onNewCommentSave}\n >\n {dict.comments.save_button_text}\n </Components.Generic.Toolbar.Button>\n </Components.Generic.Toolbar.Root>\n );\n }}\n />\n </Components.Comments.CardSection>\n )}\n </Components.Comments.Card>\n );\n};\n","import { CommentsExtension } from \"@blocknote/core/comments\";\nimport { ThreadData } from \"@blocknote/core/comments\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\n\nimport { useExtension } from \"../../hooks/useExtension.js\";\n\n/**\n * Bridges the ThreadStore to React using useSyncExternalStore.\n */\nexport function useThreads() {\n const comments = useExtension(CommentsExtension);\n\n const store = comments.threadStore;\n\n // this ref works around this error:\n // https://react.dev/reference/react/useSyncExternalStore#im-getting-an-error-the-result-of-getsnapshot-should-be-cached\n // however, might not be a good practice to work around it this way\n const threadsRef = useRef<Map<string, ThreadData> | undefined>(undefined);\n\n if (!threadsRef.current) {\n threadsRef.current = store.getThreads();\n }\n\n const subscribe = useCallback(\n (cb: () => void) => {\n return store.subscribe((threads) => {\n // update ref when changed\n threadsRef.current = threads;\n cb();\n });\n },\n [store],\n );\n\n return useSyncExternalStore(subscribe, () => threadsRef.current!);\n}\n","import { CommentsExtension } from \"@blocknote/core/comments\";\nimport { flip, offset, shift } from \"@floating-ui/react\";\nimport { ComponentProps, FC, useMemo } from \"react\";\n\nimport { useBlockNoteEditor } from \"../../hooks/useBlockNoteEditor.js\";\nimport { useExtension, useExtensionState } from \"../../hooks/useExtension.js\";\nimport { FloatingUIOptions } from \"../Popovers/FloatingUIOptions.js\";\nimport { PositionPopover } from \"../Popovers/PositionPopover.js\";\nimport { Thread } from \"./Thread.js\";\nimport { useThreads } from \"./useThreads.js\";\n\n/**\n * This component is used to display a thread in a floating card.\n * It can be used when the user clicks on a thread / comment in the document.\n */\nexport default function FloatingThreadController(props: {\n floatingThread?: FC<ComponentProps<typeof Thread>>;\n floatingUIOptions?: FloatingUIOptions;\n}) {\n const editor = useBlockNoteEditor<any, any, any>();\n\n const comments = useExtension(CommentsExtension);\n const selectedThread = useExtensionState(CommentsExtension, {\n editor,\n selector: (state) =>\n state.selectedThreadId\n ? {\n id: state.selectedThreadId,\n position: state.threadPositions.get(state.selectedThreadId),\n }\n : undefined,\n });\n\n const threads = useThreads();\n\n const thread = useMemo(\n () => (selectedThread ? threads.get(selectedThread.id) : undefined),\n [selectedThread, threads],\n );\n\n const floatingUIOptions = useMemo<FloatingUIOptions>(\n () => ({\n ...props.floatingUIOptions,\n useFloatingOptions: {\n open: !!selectedThread,\n // Needed as hooks like `useDismiss` call `onOpenChange` to change the\n // open state.\n onOpenChange: (open, _event, reason) => {\n if (reason === \"escape-key\") {\n editor.focus();\n }\n\n if (!open) {\n comments.selectThread(undefined);\n }\n },\n placement: \"bottom\",\n middleware: [offset(10), shift(), flip()],\n ...props.floatingUIOptions?.useFloatingOptions,\n },\n focusManagerProps: {\n disabled: true,\n ...props.floatingUIOptions?.focusManagerProps,\n },\n elementProps: {\n style: {\n zIndex: 30,\n },\n ...props.floatingUIOptions?.elementProps,\n },\n }),\n [comments, editor, props.floatingUIOptions, selectedThread],\n );\n\n // nice to have improvements:\n // - transition transform property so composer box animates when remote document is changed\n\n const Component = props.floatingThread || Thread;\n\n return (\n <PositionPopover position={selectedThread?.position} {...floatingUIOptions}>\n {thread && <Component thread={thread} selected={true} />}\n </PositionPopover>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
|
|
2
|
+
import { c as t, d as n, f as r, h as i, i as a, n as o, o as s, p as c, r as l, t as u } from "./defaultCommentEditorSchema-Bd70-hG9.js";
|
|
3
|
+
import d, { useCallback as f, useEffect as p, useMemo as m, useRef as h, useState as g, useSyncExternalStore as _ } from "react";
|
|
4
|
+
import { CommentsExtension as v } from "@blocknote/core/comments";
|
|
5
|
+
import { flip as y, offset as b, shift as x } from "@floating-ui/react";
|
|
6
|
+
import { mergeCSSClasses as S } from "@blocknote/core";
|
|
7
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
8
|
+
import { RiArrowGoBackFill as E, RiCheckFill as D, RiDeleteBinFill as O, RiEditFill as k, RiEmotionLine as A, RiMoreFill as j } from "react-icons/ri";
|
|
9
|
+
//#region src/components/Comments/EmojiMartPicker.tsx
|
|
10
|
+
var M;
|
|
11
|
+
async function N() {
|
|
12
|
+
return M || (M = (async () => {
|
|
13
|
+
let [e, t] = await Promise.all([import("emoji-mart"), import("@emoji-mart/data")]), n = "default" in e ? e.default : e, r = "default" in t ? t.default : t;
|
|
14
|
+
return await n.init({ data: r }), {
|
|
15
|
+
emojiMart: n,
|
|
16
|
+
emojiData: r
|
|
17
|
+
};
|
|
18
|
+
})(), M);
|
|
19
|
+
}
|
|
20
|
+
function P(e) {
|
|
21
|
+
let t = h(null), n = h(null);
|
|
22
|
+
return n.current && n.current.update(e), p(() => ((async () => {
|
|
23
|
+
let { emojiMart: r } = await N();
|
|
24
|
+
n.current = new r.Picker({
|
|
25
|
+
...e,
|
|
26
|
+
ref: t
|
|
27
|
+
});
|
|
28
|
+
})(), () => {
|
|
29
|
+
n.current = null;
|
|
30
|
+
}), []), d.createElement("div", { ref: t });
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/components/Comments/EmojiPicker.tsx
|
|
34
|
+
var F = (e) => {
|
|
35
|
+
let [n, r] = g(!1), a = t(), o = i(), s = o.editor?.portalElement;
|
|
36
|
+
if (!s) throw Error("Portal root not found");
|
|
37
|
+
return /* @__PURE__ */ T(a.Generic.Popover.Root, {
|
|
38
|
+
open: n,
|
|
39
|
+
portalRoot: s,
|
|
40
|
+
children: [/* @__PURE__ */ w(a.Generic.Popover.Trigger, { children: /* @__PURE__ */ w("div", {
|
|
41
|
+
onClick: (t) => {
|
|
42
|
+
t.preventDefault(), t.stopPropagation(), r(!n), e.onOpenChange?.(!n);
|
|
43
|
+
},
|
|
44
|
+
style: {
|
|
45
|
+
display: "flex",
|
|
46
|
+
justifyContent: "center",
|
|
47
|
+
alignItems: "center"
|
|
48
|
+
},
|
|
49
|
+
children: e.children
|
|
50
|
+
}) }), /* @__PURE__ */ w(a.Generic.Popover.Content, {
|
|
51
|
+
className: "bn-emoji-picker-popover",
|
|
52
|
+
variant: "panel-popover",
|
|
53
|
+
children: /* @__PURE__ */ w(P, {
|
|
54
|
+
perLine: 7,
|
|
55
|
+
onClickOutside: () => {
|
|
56
|
+
r(!1), e.onOpenChange?.(!1);
|
|
57
|
+
},
|
|
58
|
+
onEmojiSelect: (t) => {
|
|
59
|
+
e.onEmojiSelect(t), r(!1), e.onOpenChange?.(!1);
|
|
60
|
+
},
|
|
61
|
+
theme: o?.colorSchemePreference
|
|
62
|
+
})
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/components/Comments/useUsers.ts
|
|
68
|
+
function I(e) {
|
|
69
|
+
return L([e]).get(e);
|
|
70
|
+
}
|
|
71
|
+
function L(e) {
|
|
72
|
+
let t = n(v).userStore, r = f(() => {
|
|
73
|
+
let n = /* @__PURE__ */ new Map();
|
|
74
|
+
for (let r of e) {
|
|
75
|
+
let e = t.getUser(r);
|
|
76
|
+
e && n.set(r, e);
|
|
77
|
+
}
|
|
78
|
+
return n;
|
|
79
|
+
}, [t, e]), i = m(() => ({ current: r() }), [r]);
|
|
80
|
+
return _(f((n) => {
|
|
81
|
+
let a = t.subscribe((e) => {
|
|
82
|
+
i.current = r(), n();
|
|
83
|
+
});
|
|
84
|
+
return t.loadUsers(e), a;
|
|
85
|
+
}, [
|
|
86
|
+
t,
|
|
87
|
+
r,
|
|
88
|
+
e,
|
|
89
|
+
i
|
|
90
|
+
]), () => i.current);
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/components/Comments/ReactionBadge.tsx
|
|
94
|
+
var R = (e) => {
|
|
95
|
+
let r = t(), i = s(), a = n(v), o = e.comment.reactions.find((t) => t.emoji === e.emoji);
|
|
96
|
+
if (!o) throw Error("Trying to render reaction badge for non-existing reaction");
|
|
97
|
+
let [c, l] = g([]), u = L(c);
|
|
98
|
+
return /* @__PURE__ */ w(r.Generic.Badge.Root, {
|
|
99
|
+
className: S("bn-badge", "bn-comment-reaction"),
|
|
100
|
+
text: o.userIds.length.toString(),
|
|
101
|
+
icon: o.emoji,
|
|
102
|
+
isSelected: a.threadStore.auth.canDeleteReaction(e.comment, o.emoji),
|
|
103
|
+
onClick: () => e.onReactionSelect(o.emoji),
|
|
104
|
+
onMouseEnter: () => l(o.userIds),
|
|
105
|
+
mainTooltip: i.comments.reactions.reacted_by,
|
|
106
|
+
secondaryTooltip: `${Array.from(u.values()).map((e) => e.username).join("\n")}`
|
|
107
|
+
}, o.emoji);
|
|
108
|
+
}, z = ({ comment: e, thread: r, showResolveButton: i }) => {
|
|
109
|
+
let a = n(v), c = s(), d = l({
|
|
110
|
+
initialContent: e.body,
|
|
111
|
+
trailingBlock: !1,
|
|
112
|
+
dictionary: {
|
|
113
|
+
...c,
|
|
114
|
+
placeholders: { emptyDocument: c.placeholders.edit_comment }
|
|
115
|
+
},
|
|
116
|
+
schema: a.commentEditorSchema || u
|
|
117
|
+
}), p = t(), [m, h] = g(!1), [_, y] = g(!1), b = a.threadStore, x = f(() => {
|
|
118
|
+
h(!0);
|
|
119
|
+
}, []), M = f(() => {
|
|
120
|
+
d.replaceBlocks(d.document, e.body), h(!1);
|
|
121
|
+
}, [d, e.body]), N = f(async (t) => {
|
|
122
|
+
await b.updateComment({
|
|
123
|
+
commentId: e.id,
|
|
124
|
+
comment: { body: d.document },
|
|
125
|
+
threadId: r.id
|
|
126
|
+
}), h(!1);
|
|
127
|
+
}, [
|
|
128
|
+
e,
|
|
129
|
+
r.id,
|
|
130
|
+
d,
|
|
131
|
+
b
|
|
132
|
+
]), P = f(async () => {
|
|
133
|
+
await b.deleteComment({
|
|
134
|
+
commentId: e.id,
|
|
135
|
+
threadId: r.id
|
|
136
|
+
});
|
|
137
|
+
}, [
|
|
138
|
+
e,
|
|
139
|
+
r.id,
|
|
140
|
+
b
|
|
141
|
+
]), L = f(async (t) => {
|
|
142
|
+
b.auth.canAddReaction(e, t) ? await b.addReaction({
|
|
143
|
+
threadId: r.id,
|
|
144
|
+
commentId: e.id,
|
|
145
|
+
emoji: t
|
|
146
|
+
}) : b.auth.canDeleteReaction(e, t) && await b.deleteReaction({
|
|
147
|
+
threadId: r.id,
|
|
148
|
+
commentId: e.id,
|
|
149
|
+
emoji: t
|
|
150
|
+
});
|
|
151
|
+
}, [
|
|
152
|
+
b,
|
|
153
|
+
e,
|
|
154
|
+
r.id
|
|
155
|
+
]), z = f(async () => {
|
|
156
|
+
await b.resolveThread({ threadId: r.id });
|
|
157
|
+
}, [r.id, b]), B = f(async () => {
|
|
158
|
+
await b.unresolveThread({ threadId: r.id });
|
|
159
|
+
}, [r.id, b]), V = I(e.userId);
|
|
160
|
+
if (!e.body) return null;
|
|
161
|
+
let H, U = b.auth.canAddReaction(e), W = b.auth.canDeleteComment(e), G = b.auth.canUpdateComment(e), K = i && (r.resolved ? b.auth.canUnresolveThread(r) : b.auth.canResolveThread(r));
|
|
162
|
+
m || (H = /* @__PURE__ */ T(p.Generic.Toolbar.Root, {
|
|
163
|
+
className: S("bn-action-toolbar", "bn-comment-actions"),
|
|
164
|
+
variant: "action-toolbar",
|
|
165
|
+
children: [
|
|
166
|
+
U && /* @__PURE__ */ w(F, {
|
|
167
|
+
onEmojiSelect: (e) => L(e.native),
|
|
168
|
+
onOpenChange: y,
|
|
169
|
+
children: /* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
170
|
+
mainTooltip: c.comments.actions.add_reaction,
|
|
171
|
+
variant: "compact",
|
|
172
|
+
children: /* @__PURE__ */ w(A, { size: 16 })
|
|
173
|
+
}, "add-reaction")
|
|
174
|
+
}),
|
|
175
|
+
K && (r.resolved ? /* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
176
|
+
mainTooltip: "Re-open",
|
|
177
|
+
variant: "compact",
|
|
178
|
+
onClick: B,
|
|
179
|
+
children: /* @__PURE__ */ w(E, { size: 16 })
|
|
180
|
+
}, "reopen") : /* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
181
|
+
mainTooltip: c.comments.actions.resolve,
|
|
182
|
+
variant: "compact",
|
|
183
|
+
onClick: z,
|
|
184
|
+
children: /* @__PURE__ */ w(D, { size: 16 })
|
|
185
|
+
}, "resolve")),
|
|
186
|
+
(W || G) && /* @__PURE__ */ T(p.Generic.Menu.Root, {
|
|
187
|
+
position: "bottom-start",
|
|
188
|
+
children: [/* @__PURE__ */ w(p.Generic.Menu.Trigger, { children: /* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
189
|
+
mainTooltip: c.comments.actions.more_actions,
|
|
190
|
+
variant: "compact",
|
|
191
|
+
children: /* @__PURE__ */ w(j, { size: 16 })
|
|
192
|
+
}, "more-actions") }), /* @__PURE__ */ T(p.Generic.Menu.Dropdown, {
|
|
193
|
+
className: "bn-menu-dropdown",
|
|
194
|
+
children: [G && /* @__PURE__ */ w(p.Generic.Menu.Item, {
|
|
195
|
+
icon: /* @__PURE__ */ w(k, {}),
|
|
196
|
+
onClick: x,
|
|
197
|
+
children: c.comments.actions.edit_comment
|
|
198
|
+
}, "edit-comment"), W && /* @__PURE__ */ w(p.Generic.Menu.Item, {
|
|
199
|
+
icon: /* @__PURE__ */ w(O, {}),
|
|
200
|
+
onClick: P,
|
|
201
|
+
children: c.comments.actions.delete_comment
|
|
202
|
+
}, "delete-comment")]
|
|
203
|
+
})]
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
}));
|
|
207
|
+
let q = e.createdAt.toLocaleDateString(void 0, {
|
|
208
|
+
month: "short",
|
|
209
|
+
day: "numeric"
|
|
210
|
+
});
|
|
211
|
+
if (!e.body) throw Error("soft deletes are not yet supported");
|
|
212
|
+
return /* @__PURE__ */ w(p.Comments.Comment, {
|
|
213
|
+
authorInfo: V ?? "loading",
|
|
214
|
+
timeString: q,
|
|
215
|
+
edited: e.updatedAt.getTime() !== e.createdAt.getTime(),
|
|
216
|
+
showActions: "hover",
|
|
217
|
+
actions: H,
|
|
218
|
+
className: "bn-thread-comment",
|
|
219
|
+
emojiPickerOpen: _,
|
|
220
|
+
children: /* @__PURE__ */ w(o, {
|
|
221
|
+
autoFocus: m,
|
|
222
|
+
editor: d,
|
|
223
|
+
editable: m,
|
|
224
|
+
actions: e.reactions.length > 0 || m ? ({ isEmpty: t }) => /* @__PURE__ */ T(C, { children: [e.reactions.length > 0 && !m && /* @__PURE__ */ T(p.Generic.Badge.Group, {
|
|
225
|
+
className: S("bn-badge-group", "bn-comment-reactions"),
|
|
226
|
+
children: [e.reactions.map((t) => /* @__PURE__ */ w(R, {
|
|
227
|
+
comment: e,
|
|
228
|
+
emoji: t.emoji,
|
|
229
|
+
onReactionSelect: L
|
|
230
|
+
}, t.emoji)), U && /* @__PURE__ */ w(F, {
|
|
231
|
+
onEmojiSelect: (e) => L(e.native),
|
|
232
|
+
onOpenChange: y,
|
|
233
|
+
children: /* @__PURE__ */ w(p.Generic.Badge.Root, {
|
|
234
|
+
className: S("bn-badge", "bn-comment-add-reaction"),
|
|
235
|
+
text: "+",
|
|
236
|
+
icon: /* @__PURE__ */ w(A, { size: 16 }),
|
|
237
|
+
mainTooltip: c.comments.actions.add_reaction
|
|
238
|
+
})
|
|
239
|
+
})]
|
|
240
|
+
}), m && /* @__PURE__ */ T(p.Generic.Toolbar.Root, {
|
|
241
|
+
variant: "action-toolbar",
|
|
242
|
+
className: S("bn-action-toolbar", "bn-comment-actions"),
|
|
243
|
+
children: [/* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
244
|
+
mainTooltip: c.comments.save_button_text,
|
|
245
|
+
variant: "compact",
|
|
246
|
+
onClick: N,
|
|
247
|
+
isDisabled: t,
|
|
248
|
+
children: c.comments.save_button_text
|
|
249
|
+
}), /* @__PURE__ */ w(p.Generic.Toolbar.Button, {
|
|
250
|
+
className: "bn-button",
|
|
251
|
+
mainTooltip: c.comments.cancel_button_text,
|
|
252
|
+
variant: "compact",
|
|
253
|
+
onClick: M,
|
|
254
|
+
children: c.comments.cancel_button_text
|
|
255
|
+
})]
|
|
256
|
+
})] }) : void 0
|
|
257
|
+
})
|
|
258
|
+
});
|
|
259
|
+
}, B = ({ thread: e, maxCommentsBeforeCollapse: n }) => {
|
|
260
|
+
let r = t(), i = s(), a = L(e.resolvedBy ? [e.resolvedBy] : []), o = e.comments.map((t, n) => /* @__PURE__ */ w(z, {
|
|
261
|
+
thread: e,
|
|
262
|
+
comment: t,
|
|
263
|
+
showResolveButton: n === 0
|
|
264
|
+
}, t.id + JSON.stringify(t.body || "{}")));
|
|
265
|
+
if (e.resolved && e.resolvedUpdatedAt && e.resolvedBy) {
|
|
266
|
+
if (!a.get(e.resolvedBy)) throw Error(`User ${e.resolvedBy} resolved thread ${e.id}, but their data could not be found.`);
|
|
267
|
+
let t = e.comments.findLastIndex((t) => e.resolvedUpdatedAt.getTime() > t.createdAt.getTime()) + 1;
|
|
268
|
+
o.splice(t, 0, /* @__PURE__ */ w(r.Comments.Comment, {
|
|
269
|
+
className: "bn-thread-comment",
|
|
270
|
+
authorInfo: e.resolvedBy && a.get(e.resolvedBy) || "loading",
|
|
271
|
+
timeString: e.resolvedUpdatedAt.toLocaleDateString(void 0, {
|
|
272
|
+
month: "short",
|
|
273
|
+
day: "numeric"
|
|
274
|
+
}),
|
|
275
|
+
edited: !1,
|
|
276
|
+
showActions: !1,
|
|
277
|
+
children: /* @__PURE__ */ w("div", {
|
|
278
|
+
className: "bn-resolved-text",
|
|
279
|
+
children: i.comments.sidebar.marked_as_resolved
|
|
280
|
+
})
|
|
281
|
+
}, "resolved-comment"));
|
|
282
|
+
}
|
|
283
|
+
return n && o.length > n && o.splice(1, o.length - 2, /* @__PURE__ */ w(r.Comments.ExpandSectionsPrompt, {
|
|
284
|
+
className: "bn-thread-expand-prompt",
|
|
285
|
+
children: i.comments.sidebar.more_replies(e.comments.length - 2)
|
|
286
|
+
}, "expand-prompt")), o;
|
|
287
|
+
}, V = ({ thread: e, selected: r, referenceText: i, maxCommentsBeforeCollapse: a, onFocus: c, onBlur: d, tabIndex: p }) => {
|
|
288
|
+
let m = t(), h = s(), g = n(v), _ = l({
|
|
289
|
+
trailingBlock: !1,
|
|
290
|
+
dictionary: {
|
|
291
|
+
...h,
|
|
292
|
+
placeholders: { emptyDocument: h.placeholders.comment_reply }
|
|
293
|
+
},
|
|
294
|
+
schema: g.commentEditorSchema || u
|
|
295
|
+
}), y = f(async () => {
|
|
296
|
+
await g.threadStore.addComment({
|
|
297
|
+
comment: { body: _.document },
|
|
298
|
+
threadId: e.id
|
|
299
|
+
}), _.removeBlocks(_.document);
|
|
300
|
+
}, [
|
|
301
|
+
g,
|
|
302
|
+
_,
|
|
303
|
+
e.id
|
|
304
|
+
]);
|
|
305
|
+
return /* @__PURE__ */ T(m.Comments.Card, {
|
|
306
|
+
className: "bn-thread",
|
|
307
|
+
headerText: i,
|
|
308
|
+
onFocus: c,
|
|
309
|
+
onBlur: d,
|
|
310
|
+
selected: r,
|
|
311
|
+
tabIndex: p,
|
|
312
|
+
children: [/* @__PURE__ */ w(m.Comments.CardSection, {
|
|
313
|
+
className: "bn-thread-comments",
|
|
314
|
+
children: /* @__PURE__ */ w(B, {
|
|
315
|
+
thread: e,
|
|
316
|
+
maxCommentsBeforeCollapse: r ? void 0 : a || 5
|
|
317
|
+
})
|
|
318
|
+
}), r && /* @__PURE__ */ w(m.Comments.CardSection, {
|
|
319
|
+
className: "bn-thread-composer",
|
|
320
|
+
children: /* @__PURE__ */ w(o, {
|
|
321
|
+
autoFocus: !1,
|
|
322
|
+
editable: !0,
|
|
323
|
+
editor: _,
|
|
324
|
+
actions: ({ isEmpty: e }) => e ? null : /* @__PURE__ */ w(m.Generic.Toolbar.Root, {
|
|
325
|
+
variant: "action-toolbar",
|
|
326
|
+
className: S("bn-action-toolbar", "bn-comment-actions"),
|
|
327
|
+
children: /* @__PURE__ */ w(m.Generic.Toolbar.Button, {
|
|
328
|
+
mainTooltip: h.comments.save_button_text,
|
|
329
|
+
variant: "compact",
|
|
330
|
+
isDisabled: e,
|
|
331
|
+
onClick: y,
|
|
332
|
+
children: h.comments.save_button_text
|
|
333
|
+
})
|
|
334
|
+
})
|
|
335
|
+
})
|
|
336
|
+
})]
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/components/Comments/useThreads.ts
|
|
341
|
+
function H() {
|
|
342
|
+
let e = n(v).threadStore, t = h(void 0);
|
|
343
|
+
return t.current ||= e.getThreads(), _(f((n) => e.subscribe((e) => {
|
|
344
|
+
t.current = e, n();
|
|
345
|
+
}), [e]), () => t.current);
|
|
346
|
+
}
|
|
347
|
+
//#endregion
|
|
348
|
+
//#region src/components/Comments/FloatingThreadController.tsx
|
|
349
|
+
var U = /* @__PURE__ */ e({ default: () => W });
|
|
350
|
+
function W(e) {
|
|
351
|
+
let t = c(), i = n(v), o = r(v, {
|
|
352
|
+
editor: t,
|
|
353
|
+
selector: (e) => e.selectedThreadId ? {
|
|
354
|
+
id: e.selectedThreadId,
|
|
355
|
+
position: e.threadPositions.get(e.selectedThreadId)
|
|
356
|
+
} : void 0
|
|
357
|
+
}), s = H(), l = m(() => o ? s.get(o.id) : void 0, [o, s]), u = m(() => ({
|
|
358
|
+
...e.floatingUIOptions,
|
|
359
|
+
useFloatingOptions: {
|
|
360
|
+
open: !!o,
|
|
361
|
+
onOpenChange: (e, n, r) => {
|
|
362
|
+
r === "escape-key" && t.focus(), e || i.selectThread(void 0);
|
|
363
|
+
},
|
|
364
|
+
placement: "bottom",
|
|
365
|
+
middleware: [
|
|
366
|
+
b(10),
|
|
367
|
+
x(),
|
|
368
|
+
y()
|
|
369
|
+
],
|
|
370
|
+
...e.floatingUIOptions?.useFloatingOptions
|
|
371
|
+
},
|
|
372
|
+
focusManagerProps: {
|
|
373
|
+
disabled: !0,
|
|
374
|
+
...e.floatingUIOptions?.focusManagerProps
|
|
375
|
+
},
|
|
376
|
+
elementProps: {
|
|
377
|
+
style: { zIndex: 30 },
|
|
378
|
+
...e.floatingUIOptions?.elementProps
|
|
379
|
+
}
|
|
380
|
+
}), [
|
|
381
|
+
i,
|
|
382
|
+
t,
|
|
383
|
+
e.floatingUIOptions,
|
|
384
|
+
o
|
|
385
|
+
]), d = e.floatingThread || V;
|
|
386
|
+
return /* @__PURE__ */ w(a, {
|
|
387
|
+
position: o?.position,
|
|
388
|
+
...u,
|
|
389
|
+
children: l && /* @__PURE__ */ w(d, {
|
|
390
|
+
thread: l,
|
|
391
|
+
selected: !0
|
|
392
|
+
})
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
396
|
+
export { B as a, L as c, V as i, U as n, z as o, H as r, I as s, W as t };
|
|
397
|
+
|
|
398
|
+
//# sourceMappingURL=FloatingThreadController-BuzLC5ea.js.map
|