dishui 0.0.71 → 0.0.73
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/components/Button/index.d.ts +4 -4
- package/dist/components/Button/index.js +18 -17
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/Metric.d.ts +17 -0
- package/dist/components/Card/Metric2.js +50 -0
- package/dist/components/Card/Metric2.js.map +1 -0
- package/dist/components/Card/index.d.ts +3 -0
- package/dist/components/Card/index.js +118 -117
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Group/index.d.ts +2 -0
- package/dist/components/GroupButton/index.d.ts +16 -0
- package/dist/components/GroupButton/index.js +41 -0
- package/dist/components/GroupButton/index.js.map +1 -0
- package/dist/components/GroupedTable/index.d.ts +38 -0
- package/dist/components/GroupedTable/index.js +92 -0
- package/dist/components/GroupedTable/index.js.map +1 -0
- package/dist/components/Layout/index.d.ts +4 -2
- package/dist/components/Layout/index.js +1 -1
- package/dist/components/Layout/index.js.map +1 -1
- package/dist/components/NavigationList/index.d.ts +17 -0
- package/dist/components/NavigationList/index.js +48 -0
- package/dist/components/NavigationList/index.js.map +1 -0
- package/dist/components/Section/index.d.ts +28 -0
- package/dist/components/Section/index.js +58 -0
- package/dist/components/Section/index.js.map +1 -0
- package/dist/components/Select/index.d.ts +2 -0
- package/dist/components/Select/index.js +83 -82
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.d.ts +16 -1
- package/dist/components/SidebarToggleButton/index.js +90 -30
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/Skeleton/index.d.ts +7 -0
- package/dist/components/Skeleton/index.js +21 -0
- package/dist/components/Skeleton/index.js.map +1 -0
- package/dist/components/Tree/Tree.js +5 -2
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js +114 -72
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js +315 -196
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.d.ts +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js +69 -33
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.d.ts +2 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js +100 -81
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.d.ts +2 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js +92 -68
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js +24 -22
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SearchReplace.d.ts +7 -0
- package/dist/components/pro/RichTextEditor/SlashMenu.js +136 -73
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +346 -313
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +114 -146
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CommentMark.js +2 -2
- package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js +178 -163
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FontSize.js +8 -5
- package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.d.ts +6 -0
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js +85 -74
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/components/pro/RichTextEditor/searchUtils.d.ts +23 -0
- package/dist/contexts/AppContext.js +47 -45
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +119 -114
- package/dist/layouts/MainLayout.js +9 -10
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Sidebar.d.ts +9 -0
- package/dist/layouts/Sidebar.js +99 -80
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.d.ts +1 -1
- package/dist/layouts/headbar/Headbar.js +2 -2
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/lite.d.ts +19 -1
- package/dist/lite.js +17 -8
- package/dist/styles/themeStyles.js +6 -6
- package/dist/styles/themeStyles.js.map +1 -1
- package/dist/utils/i18n.d.ts +3 -0
- package/dist/utils/i18n.js +78 -0
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js +23 -6
- package/dist/utils/menu.js.map +1 -1
- package/package.json +8 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { forwardRef as e, useCallback as t, useEffect as n, useImperativeHandle as r, useRef as i, useState as a } from "react";
|
|
2
2
|
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
3
|
+
import { useEditorState as l } from "@tiptap/react";
|
|
3
4
|
//#region src/components/pro/RichTextEditor/CommentPanel.tsx
|
|
4
|
-
function
|
|
5
|
+
function u() {
|
|
5
6
|
return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
6
7
|
}
|
|
7
|
-
function
|
|
8
|
+
function d(e) {
|
|
8
9
|
let t = Date.now() - e, n = Math.floor(t / 1e3);
|
|
9
10
|
if (n < 60) return "just now";
|
|
10
11
|
let r = Math.floor(n / 60);
|
|
@@ -12,83 +13,97 @@ function u(e) {
|
|
|
12
13
|
let i = Math.floor(r / 60);
|
|
13
14
|
return i < 24 ? `${i}h ago` : `${Math.floor(i / 24)}d ago`;
|
|
14
15
|
}
|
|
15
|
-
var
|
|
16
|
-
let [
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
var f = e(({ editor: e, threads: f, onThreadsChange: p, onRequestAddComment: m, currentUser: h = "User", editable: g = !0 }, _) => {
|
|
17
|
+
let [v, y] = a(null), [b, x] = a(""), S = i(null), C = i(/* @__PURE__ */ new Map()), w = i(null), T = i({
|
|
18
|
+
editable: g,
|
|
19
|
+
threads: f
|
|
20
|
+
});
|
|
21
|
+
T.current = {
|
|
22
|
+
editable: g,
|
|
23
|
+
threads: f
|
|
24
|
+
};
|
|
25
|
+
let E = l({
|
|
26
|
+
editor: e,
|
|
27
|
+
selector: ({ editor: e }) => e.isEditable
|
|
28
|
+
}), D = g && E;
|
|
29
|
+
r(_, () => ({ scrollToThread: (e) => {
|
|
30
|
+
let t = C.current.get(e);
|
|
19
31
|
t && (t.scrollIntoView({
|
|
20
32
|
behavior: "smooth",
|
|
21
33
|
block: "center"
|
|
22
34
|
}), t.classList.add("rte-comments__thread--highlight"), setTimeout(() => t.classList.remove("rte-comments__thread--highlight"), 1500));
|
|
23
35
|
} })), n(() => {
|
|
24
|
-
|
|
25
|
-
}, [
|
|
26
|
-
let
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}));
|
|
36
|
+
v && S.current && S.current.focus();
|
|
37
|
+
}, [v]);
|
|
38
|
+
let O = t((t) => {
|
|
39
|
+
if (!T.current.editable || !e.isEditable) return;
|
|
40
|
+
let n = T.current.threads.find((e) => e.id === t);
|
|
41
|
+
if (!n) return;
|
|
42
|
+
let r = !n.resolved, i = e.state.tr;
|
|
43
|
+
e.state.doc.descendants((e, n) => {
|
|
44
|
+
e.marks.forEach((a) => {
|
|
45
|
+
a.type.name === "comment" && a.attrs.commentId === t && i.removeMark(n, n + e.nodeSize, a).addMark(n, n + e.nodeSize, a.type.create({
|
|
46
|
+
...a.attrs,
|
|
47
|
+
resolved: r
|
|
48
|
+
}));
|
|
49
|
+
});
|
|
50
|
+
}), i.docChanged && e.view.dispatch(i), p(T.current.threads.map((e) => e.id === t ? {
|
|
51
|
+
...e,
|
|
52
|
+
resolved: r
|
|
53
|
+
} : e));
|
|
42
54
|
}, [
|
|
43
55
|
e,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
]),
|
|
47
|
-
if (!
|
|
48
|
-
let
|
|
49
|
-
id:
|
|
50
|
-
author:
|
|
51
|
-
text:
|
|
56
|
+
f,
|
|
57
|
+
p
|
|
58
|
+
]), k = t((t) => {
|
|
59
|
+
if (!T.current.editable || !e.isEditable || !b.trim() || !T.current.threads.some((e) => e.id === t && !e.resolved)) return;
|
|
60
|
+
let n = {
|
|
61
|
+
id: u(),
|
|
62
|
+
author: h,
|
|
63
|
+
text: b.trim(),
|
|
52
64
|
createdAt: Date.now()
|
|
53
65
|
};
|
|
54
|
-
|
|
55
|
-
...
|
|
56
|
-
comments: [...
|
|
57
|
-
} :
|
|
66
|
+
p(T.current.threads.map((e) => e.id === t ? {
|
|
67
|
+
...e,
|
|
68
|
+
comments: [...e.comments, n]
|
|
69
|
+
} : e)), x(""), y(null);
|
|
58
70
|
}, [
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
e,
|
|
72
|
+
b,
|
|
61
73
|
f,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
p,
|
|
75
|
+
h
|
|
76
|
+
]), A = t((t) => {
|
|
77
|
+
if (!T.current.editable || !e.isEditable || !T.current.threads.some((e) => e.id === t)) return;
|
|
78
|
+
let n = e.state.tr;
|
|
79
|
+
e.state.doc.descendants((e, r) => {
|
|
80
|
+
e.marks.forEach((i) => {
|
|
81
|
+
i.type.name === "comment" && i.attrs.commentId === t && n.removeMark(r, r + e.nodeSize, i);
|
|
67
82
|
});
|
|
68
|
-
}),
|
|
83
|
+
}), n.docChanged && e.view.dispatch(n), p(T.current.threads.filter((e) => e.id !== t));
|
|
69
84
|
}, [
|
|
70
85
|
e,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
]),
|
|
74
|
-
ref: (
|
|
75
|
-
|
|
86
|
+
f,
|
|
87
|
+
p
|
|
88
|
+
]), j = f.filter((e) => !e.resolved), M = f.filter((e) => e.resolved), N = (t) => /* @__PURE__ */ c("div", {
|
|
89
|
+
ref: (e) => {
|
|
90
|
+
e ? C.current.set(t.id, e) : C.current.delete(t.id);
|
|
76
91
|
},
|
|
77
|
-
className: `rte-comments__thread ${
|
|
92
|
+
className: `rte-comments__thread ${t.resolved ? "rte-comments__thread--resolved" : ""}`,
|
|
78
93
|
children: [
|
|
79
94
|
/* @__PURE__ */ c("div", {
|
|
80
95
|
className: "rte-comments__thread-header",
|
|
81
96
|
children: [/* @__PURE__ */ s("span", {
|
|
82
|
-
className: `rte-comments__status ${
|
|
83
|
-
children:
|
|
84
|
-
}), /* @__PURE__ */ c("div", {
|
|
97
|
+
className: `rte-comments__status ${t.resolved ? "rte-comments__status--resolved" : ""}`,
|
|
98
|
+
children: t.resolved ? "✓ Resolved" : "Open"
|
|
99
|
+
}), D && /* @__PURE__ */ c("div", {
|
|
85
100
|
className: "rte-comments__thread-actions",
|
|
86
101
|
children: [/* @__PURE__ */ s("button", {
|
|
87
102
|
type: "button",
|
|
88
103
|
className: "rte-comments__icon-btn",
|
|
89
|
-
onClick: () =>
|
|
90
|
-
title:
|
|
91
|
-
children:
|
|
104
|
+
onClick: () => O(t.id),
|
|
105
|
+
title: t.resolved ? "Unresolve" : "Resolve",
|
|
106
|
+
children: t.resolved ? /* @__PURE__ */ s("svg", {
|
|
92
107
|
width: "14",
|
|
93
108
|
height: "14",
|
|
94
109
|
viewBox: "0 0 24 24",
|
|
@@ -108,7 +123,7 @@ var d = e(({ editor: e, threads: d, onThreadsChange: f, onRequestAddComment: p,
|
|
|
108
123
|
}), /* @__PURE__ */ s("button", {
|
|
109
124
|
type: "button",
|
|
110
125
|
className: "rte-comments__icon-btn rte-comments__icon-btn--danger",
|
|
111
|
-
onClick: () =>
|
|
126
|
+
onClick: () => A(t.id),
|
|
112
127
|
title: "Delete thread",
|
|
113
128
|
children: /* @__PURE__ */ c("svg", {
|
|
114
129
|
width: "14",
|
|
@@ -132,7 +147,7 @@ var d = e(({ editor: e, threads: d, onThreadsChange: f, onRequestAddComment: p,
|
|
|
132
147
|
})]
|
|
133
148
|
})]
|
|
134
149
|
}),
|
|
135
|
-
|
|
150
|
+
t.comments.map((e) => /* @__PURE__ */ c("div", {
|
|
136
151
|
className: "rte-comments__comment",
|
|
137
152
|
children: [/* @__PURE__ */ c("div", {
|
|
138
153
|
className: "rte-comments__comment-meta",
|
|
@@ -141,28 +156,28 @@ var d = e(({ editor: e, threads: d, onThreadsChange: f, onRequestAddComment: p,
|
|
|
141
156
|
children: e.author
|
|
142
157
|
}), /* @__PURE__ */ s("span", {
|
|
143
158
|
className: "rte-comments__time",
|
|
144
|
-
children:
|
|
159
|
+
children: d(e.createdAt)
|
|
145
160
|
})]
|
|
146
161
|
}), /* @__PURE__ */ s("div", {
|
|
147
162
|
className: "rte-comments__comment-text",
|
|
148
163
|
children: e.text
|
|
149
164
|
})]
|
|
150
165
|
}, e.id)),
|
|
151
|
-
|
|
166
|
+
D && !t.resolved && (v === t.id ? /* @__PURE__ */ c("div", {
|
|
152
167
|
className: "rte-comments__reply-form",
|
|
153
168
|
children: [/* @__PURE__ */ s("input", {
|
|
154
|
-
ref:
|
|
169
|
+
ref: S,
|
|
155
170
|
className: "rte-comments__reply-input",
|
|
156
|
-
value:
|
|
157
|
-
onChange: (e) =>
|
|
158
|
-
onKeyDown: (
|
|
159
|
-
|
|
171
|
+
value: b,
|
|
172
|
+
onChange: (e) => x(e.target.value),
|
|
173
|
+
onKeyDown: (e) => {
|
|
174
|
+
e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229 || (e.key === "Enter" && (e.preventDefault(), k(t.id)), e.key === "Escape" && (y(null), x("")));
|
|
160
175
|
},
|
|
161
176
|
placeholder: "Reply..."
|
|
162
177
|
}), /* @__PURE__ */ s("button", {
|
|
163
178
|
type: "button",
|
|
164
179
|
className: "rte-comments__reply-send",
|
|
165
|
-
onClick: () =>
|
|
180
|
+
onClick: () => k(t.id),
|
|
166
181
|
children: /* @__PURE__ */ c("svg", {
|
|
167
182
|
width: "14",
|
|
168
183
|
height: "14",
|
|
@@ -181,25 +196,29 @@ var d = e(({ editor: e, threads: d, onThreadsChange: f, onRequestAddComment: p,
|
|
|
181
196
|
}) : /* @__PURE__ */ s("button", {
|
|
182
197
|
type: "button",
|
|
183
198
|
className: "rte-comments__reply-trigger",
|
|
184
|
-
onClick: () =>
|
|
199
|
+
onClick: () => {
|
|
200
|
+
T.current.editable && e.isEditable && T.current.threads.some((e) => e.id === t.id && !e.resolved) && y(t.id);
|
|
201
|
+
},
|
|
185
202
|
children: "Reply..."
|
|
186
|
-
})
|
|
203
|
+
}))
|
|
187
204
|
]
|
|
188
|
-
},
|
|
205
|
+
}, t.id);
|
|
189
206
|
return /* @__PURE__ */ c("div", {
|
|
190
207
|
className: "rte-comments",
|
|
191
208
|
children: [/* @__PURE__ */ c("div", {
|
|
192
209
|
className: "rte-comments__header",
|
|
193
210
|
children: [/* @__PURE__ */ c("span", {
|
|
194
211
|
className: "rte-comments__title",
|
|
195
|
-
children: ["Comments",
|
|
212
|
+
children: ["Comments", j.length > 0 && /* @__PURE__ */ s("span", {
|
|
196
213
|
className: "rte-comments__badge",
|
|
197
|
-
children:
|
|
214
|
+
children: j.length
|
|
198
215
|
})]
|
|
199
|
-
}), /* @__PURE__ */ s("button", {
|
|
216
|
+
}), D && /* @__PURE__ */ s("button", {
|
|
200
217
|
type: "button",
|
|
201
218
|
className: "rte-comments__add-btn",
|
|
202
|
-
onClick:
|
|
219
|
+
onClick: () => {
|
|
220
|
+
T.current.editable && e.isEditable && m();
|
|
221
|
+
},
|
|
203
222
|
title: "Add comment to selection",
|
|
204
223
|
children: /* @__PURE__ */ c("svg", {
|
|
205
224
|
width: "14",
|
|
@@ -222,24 +241,24 @@ var d = e(({ editor: e, threads: d, onThreadsChange: f, onRequestAddComment: p,
|
|
|
222
241
|
})
|
|
223
242
|
})]
|
|
224
243
|
}), /* @__PURE__ */ s("div", {
|
|
225
|
-
ref:
|
|
244
|
+
ref: w,
|
|
226
245
|
className: "rte-comments__list",
|
|
227
|
-
children:
|
|
246
|
+
children: f.length === 0 ? /* @__PURE__ */ s("div", {
|
|
228
247
|
className: "rte-comments__empty",
|
|
229
|
-
children: "Select text and click + to add a comment"
|
|
230
|
-
}) : /* @__PURE__ */ c(o, { children: [
|
|
248
|
+
children: D ? "Select text and click + to add a comment" : "No comments"
|
|
249
|
+
}) : /* @__PURE__ */ c(o, { children: [j.map(N), M.length > 0 && /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ c("div", {
|
|
231
250
|
className: "rte-comments__section-label",
|
|
232
251
|
children: [
|
|
233
252
|
"Resolved (",
|
|
234
|
-
|
|
253
|
+
M.length,
|
|
235
254
|
")"
|
|
236
255
|
]
|
|
237
|
-
}),
|
|
256
|
+
}), M.map(N)] })] })
|
|
238
257
|
})]
|
|
239
258
|
});
|
|
240
259
|
});
|
|
241
|
-
|
|
260
|
+
f.displayName = "CommentPanel";
|
|
242
261
|
//#endregion
|
|
243
|
-
export {
|
|
262
|
+
export { f as default };
|
|
244
263
|
|
|
245
264
|
//# sourceMappingURL=CommentPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentPanel.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/CommentPanel.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useImperativeHandle, forwardRef } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { CommentThread, CommentItem } from './extensions/CommentMark';\n\nexport interface CommentPanelHandle {\n scrollToThread: (id: string) => void;\n}\n\ninterface CommentPanelProps {\n editor: Editor;\n threads: CommentThread[];\n onThreadsChange: (threads: CommentThread[]) => void;\n onRequestAddComment: () => void;\n currentUser?: string;\n}\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const sec = Math.floor(diff / 1000);\n if (sec < 60) return 'just now';\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const d = Math.floor(hr / 24);\n return `${d}d ago`;\n}\n\nconst CommentPanel = forwardRef<CommentPanelHandle, CommentPanelProps>(({\n editor,\n threads,\n onThreadsChange,\n onRequestAddComment,\n currentUser = 'User',\n}, ref) => {\n const [replyingTo, setReplyingTo] = useState<string | null>(null);\n const [replyText, setReplyText] = useState('');\n const replyInputRef = useRef<HTMLInputElement>(null);\n const threadRefs = useRef<Map<string, HTMLDivElement>>(new Map());\n const listRef = useRef<HTMLDivElement>(null);\n\n useImperativeHandle(ref, () => ({\n scrollToThread: (id: string) => {\n const el = threadRefs.current.get(id);\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.add('rte-comments__thread--highlight');\n setTimeout(() => el.classList.remove('rte-comments__thread--highlight'), 1500);\n }\n },\n }));\n\n useEffect(() => {\n if (replyingTo && replyInputRef.current) {\n replyInputRef.current.focus();\n }\n }, [replyingTo]);\n\n const toggleResolve = useCallback((threadId: string) => {\n const updated = threads.map((t) => {\n if (t.id !== threadId) return t;\n const newResolved = !t.resolved;\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === threadId) {\n editor.view.dispatch(\n editor.state.tr\n .removeMark(pos, pos + node.nodeSize, mark)\n .addMark(pos, pos + node.nodeSize, mark.type.create({ ...mark.attrs, resolved: newResolved }))\n );\n }\n });\n });\n return { ...t, resolved: newResolved };\n });\n onThreadsChange(updated);\n }, [editor, threads, onThreadsChange]);\n\n const addReply = useCallback((threadId: string) => {\n if (!replyText.trim()) return;\n const reply: CommentItem = {\n id: generateId(),\n author: currentUser,\n text: replyText.trim(),\n createdAt: Date.now(),\n };\n const updated = threads.map((t) =>\n t.id === threadId ? { ...t, comments: [...t.comments, reply] } : t\n );\n onThreadsChange(updated);\n setReplyText('');\n setReplyingTo(null);\n }, [replyText, threads, onThreadsChange, currentUser]);\n\n const deleteThread = useCallback((threadId: string) => {\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === threadId) {\n editor.view.dispatch(\n editor.state.tr.removeMark(pos, pos + node.nodeSize, mark)\n );\n }\n });\n });\n onThreadsChange(threads.filter((t) => t.id !== threadId));\n }, [editor, threads, onThreadsChange]);\n\n const activeThreads = threads.filter((t) => !t.resolved);\n const resolvedThreads = threads.filter((t) => t.resolved);\n\n const renderThread = (thread: CommentThread) => (\n <div\n key={thread.id}\n ref={(el) => { if (el) threadRefs.current.set(thread.id, el); else threadRefs.current.delete(thread.id); }}\n className={`rte-comments__thread ${thread.resolved ? 'rte-comments__thread--resolved' : ''}`}\n >\n <div className=\"rte-comments__thread-header\">\n <span className={`rte-comments__status ${thread.resolved ? 'rte-comments__status--resolved' : ''}`}>\n {thread.resolved ? '✓ Resolved' : 'Open'}\n </span>\n <div className=\"rte-comments__thread-actions\">\n <button\n type=\"button\"\n className=\"rte-comments__icon-btn\"\n onClick={() => toggleResolve(thread.id)}\n title={thread.resolved ? 'Unresolve' : 'Resolve'}\n >\n {thread.resolved ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0h4\" /></svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n )}\n </button>\n <button\n type=\"button\"\n className=\"rte-comments__icon-btn rte-comments__icon-btn--danger\"\n onClick={() => deleteThread(thread.id)}\n title=\"Delete thread\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" /></svg>\n </button>\n </div>\n </div>\n\n {thread.comments.map((c) => (\n <div key={c.id} className=\"rte-comments__comment\">\n <div className=\"rte-comments__comment-meta\">\n <span className=\"rte-comments__author\">{c.author}</span>\n <span className=\"rte-comments__time\">{timeAgo(c.createdAt)}</span>\n </div>\n <div className=\"rte-comments__comment-text\">{c.text}</div>\n </div>\n ))}\n\n {replyingTo === thread.id ? (\n <div className=\"rte-comments__reply-form\">\n <input\n ref={replyInputRef}\n className=\"rte-comments__reply-input\"\n value={replyText}\n onChange={(e) => setReplyText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') addReply(thread.id);\n if (e.key === 'Escape') { setReplyingTo(null); setReplyText(''); }\n }}\n placeholder=\"Reply...\"\n />\n <button type=\"button\" className=\"rte-comments__reply-send\" onClick={() => addReply(thread.id)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" /><polygon points=\"22 2 15 22 11 13 2 9 22 2\" /></svg>\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n className=\"rte-comments__reply-trigger\"\n onClick={() => setReplyingTo(thread.id)}\n >\n Reply...\n </button>\n )}\n </div>\n );\n\n return (\n <div className=\"rte-comments\">\n <div className=\"rte-comments__header\">\n <span className=\"rte-comments__title\">\n Comments\n {activeThreads.length > 0 && <span className=\"rte-comments__badge\">{activeThreads.length}</span>}\n </span>\n <button\n type=\"button\"\n className=\"rte-comments__add-btn\"\n onClick={onRequestAddComment}\n title=\"Add comment to selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></svg>\n </button>\n </div>\n\n <div ref={listRef} className=\"rte-comments__list\">\n {threads.length === 0 ? (\n <div className=\"rte-comments__empty\">Select text and click + to add a comment</div>\n ) : (\n <>\n {activeThreads.map(renderThread)}\n {resolvedThreads.length > 0 && (\n <>\n <div className=\"rte-comments__section-label\">Resolved ({resolvedThreads.length})</div>\n {resolvedThreads.map(renderThread)}\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n});\n\nCommentPanel.displayName = 'CommentPanel';\n\nexport default CommentPanel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentPanel.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/CommentPanel.tsx"],"sourcesContent":["import React, { useState, useCallback, useRef, useEffect, useImperativeHandle, forwardRef } from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport type { CommentThread, CommentItem } from './extensions/CommentMark';\n\nexport interface CommentPanelHandle {\n scrollToThread: (id: string) => void;\n}\n\ninterface CommentPanelProps {\n editor: Editor;\n threads: CommentThread[];\n onThreadsChange: (threads: CommentThread[]) => void;\n onRequestAddComment: () => void;\n currentUser?: string;\n editable?: boolean;\n}\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const sec = Math.floor(diff / 1000);\n if (sec < 60) return 'just now';\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const d = Math.floor(hr / 24);\n return `${d}d ago`;\n}\n\nconst CommentPanel = forwardRef<CommentPanelHandle, CommentPanelProps>(({\n editor,\n threads,\n onThreadsChange,\n onRequestAddComment,\n currentUser = 'User',\n editable = true,\n}, ref) => {\n const [replyingTo, setReplyingTo] = useState<string | null>(null);\n const [replyText, setReplyText] = useState('');\n const replyInputRef = useRef<HTMLInputElement>(null);\n const threadRefs = useRef<Map<string, HTMLDivElement>>(new Map());\n const listRef = useRef<HTMLDivElement>(null);\n const latest = useRef({ editable, threads });\n latest.current = { editable, threads };\n const editorEditable = useEditorState({ editor, selector: ({ editor }) => editor.isEditable });\n const canEdit = editable && editorEditable;\n\n useImperativeHandle(ref, () => ({\n scrollToThread: (id: string) => {\n const el = threadRefs.current.get(id);\n if (el) {\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.add('rte-comments__thread--highlight');\n setTimeout(() => el.classList.remove('rte-comments__thread--highlight'), 1500);\n }\n },\n }));\n\n useEffect(() => {\n if (replyingTo && replyInputRef.current) {\n replyInputRef.current.focus();\n }\n }, [replyingTo]);\n\n const toggleResolve = useCallback((threadId: string) => {\n if (!latest.current.editable || !editor.isEditable) return;\n const thread = latest.current.threads.find((t) => t.id === threadId);\n if (!thread) return;\n const resolved = !thread.resolved;\n const tr = editor.state.tr;\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === threadId) {\n tr.removeMark(pos, pos + node.nodeSize, mark)\n .addMark(pos, pos + node.nodeSize, mark.type.create({ ...mark.attrs, resolved }));\n }\n });\n });\n if (tr.docChanged) editor.view.dispatch(tr);\n onThreadsChange(latest.current.threads.map((t) => t.id === threadId ? { ...t, resolved } : t));\n }, [editor, threads, onThreadsChange]);\n\n const addReply = useCallback((threadId: string) => {\n if (!latest.current.editable || !editor.isEditable || !replyText.trim()) return;\n if (!latest.current.threads.some((t) => t.id === threadId && !t.resolved)) return;\n const reply: CommentItem = {\n id: generateId(),\n author: currentUser,\n text: replyText.trim(),\n createdAt: Date.now(),\n };\n const updated = latest.current.threads.map((t) =>\n t.id === threadId ? { ...t, comments: [...t.comments, reply] } : t\n );\n onThreadsChange(updated);\n setReplyText('');\n setReplyingTo(null);\n }, [editor, replyText, threads, onThreadsChange, currentUser]);\n\n const deleteThread = useCallback((threadId: string) => {\n if (!latest.current.editable || !editor.isEditable) return;\n if (!latest.current.threads.some((t) => t.id === threadId)) return;\n const tr = editor.state.tr;\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === threadId) {\n tr.removeMark(pos, pos + node.nodeSize, mark);\n }\n });\n });\n if (tr.docChanged) editor.view.dispatch(tr);\n onThreadsChange(latest.current.threads.filter((t) => t.id !== threadId));\n }, [editor, threads, onThreadsChange]);\n\n const activeThreads = threads.filter((t) => !t.resolved);\n const resolvedThreads = threads.filter((t) => t.resolved);\n\n const renderThread = (thread: CommentThread) => (\n <div\n key={thread.id}\n ref={(el) => { if (el) threadRefs.current.set(thread.id, el); else threadRefs.current.delete(thread.id); }}\n className={`rte-comments__thread ${thread.resolved ? 'rte-comments__thread--resolved' : ''}`}\n >\n <div className=\"rte-comments__thread-header\">\n <span className={`rte-comments__status ${thread.resolved ? 'rte-comments__status--resolved' : ''}`}>\n {thread.resolved ? '✓ Resolved' : 'Open'}\n </span>\n {canEdit && <div className=\"rte-comments__thread-actions\">\n <button\n type=\"button\"\n className=\"rte-comments__icon-btn\"\n onClick={() => toggleResolve(thread.id)}\n title={thread.resolved ? 'Unresolve' : 'Resolve'}\n >\n {thread.resolved ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0h4\" /></svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n )}\n </button>\n <button\n type=\"button\"\n className=\"rte-comments__icon-btn rte-comments__icon-btn--danger\"\n onClick={() => deleteThread(thread.id)}\n title=\"Delete thread\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" /></svg>\n </button>\n </div>}\n </div>\n\n {thread.comments.map((c) => (\n <div key={c.id} className=\"rte-comments__comment\">\n <div className=\"rte-comments__comment-meta\">\n <span className=\"rte-comments__author\">{c.author}</span>\n <span className=\"rte-comments__time\">{timeAgo(c.createdAt)}</span>\n </div>\n <div className=\"rte-comments__comment-text\">{c.text}</div>\n </div>\n ))}\n\n {canEdit && !thread.resolved && (replyingTo === thread.id ? (\n <div className=\"rte-comments__reply-form\">\n <input\n ref={replyInputRef}\n className=\"rte-comments__reply-input\"\n value={replyText}\n onChange={(e) => setReplyText(e.target.value)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Enter') { e.preventDefault(); addReply(thread.id); }\n if (e.key === 'Escape') { setReplyingTo(null); setReplyText(''); }\n }}\n placeholder=\"Reply...\"\n />\n <button type=\"button\" className=\"rte-comments__reply-send\" onClick={() => addReply(thread.id)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" /><polygon points=\"22 2 15 22 11 13 2 9 22 2\" /></svg>\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n className=\"rte-comments__reply-trigger\"\n onClick={() => {\n if (!latest.current.editable || !editor.isEditable) return;\n if (!latest.current.threads.some((t) => t.id === thread.id && !t.resolved)) return;\n setReplyingTo(thread.id);\n }}\n >\n Reply...\n </button>\n ))}\n </div>\n );\n\n return (\n <div className=\"rte-comments\">\n <div className=\"rte-comments__header\">\n <span className=\"rte-comments__title\">\n Comments\n {activeThreads.length > 0 && <span className=\"rte-comments__badge\">{activeThreads.length}</span>}\n </span>\n {canEdit && <button\n type=\"button\"\n className=\"rte-comments__add-btn\"\n onClick={() => {\n if (latest.current.editable && editor.isEditable) onRequestAddComment();\n }}\n title=\"Add comment to selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></svg>\n </button>}\n </div>\n\n <div ref={listRef} className=\"rte-comments__list\">\n {threads.length === 0 ? (\n <div className=\"rte-comments__empty\">{canEdit ? 'Select text and click + to add a comment' : 'No comments'}</div>\n ) : (\n <>\n {activeThreads.map(renderThread)}\n {resolvedThreads.length > 0 && (\n <>\n <div className=\"rte-comments__section-label\">Resolved ({resolvedThreads.length})</div>\n {resolvedThreads.map(renderThread)}\n </>\n )}\n </>\n )}\n </div>\n </div>\n );\n});\n\nCommentPanel.displayName = 'CommentPanel';\n\nexport default CommentPanel;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type
|
|
2
|
+
import { type Editor } from '@tiptap/react';
|
|
3
3
|
import type { CommentThread } from './extensions/CommentMark';
|
|
4
4
|
interface CommentPopoverProps {
|
|
5
5
|
editor: Editor;
|
|
@@ -9,6 +9,7 @@ interface CommentPopoverProps {
|
|
|
9
9
|
onOpenPanel: () => void;
|
|
10
10
|
onScrollToThread: (id: string) => void;
|
|
11
11
|
currentUser?: string;
|
|
12
|
+
editable?: boolean;
|
|
12
13
|
}
|
|
13
14
|
declare const CommentPopover: React.FC<CommentPopoverProps>;
|
|
14
15
|
export default CommentPopover;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
|
|
2
2
|
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
3
|
+
import { useEditorState as o } from "@tiptap/react";
|
|
3
4
|
//#region src/components/pro/RichTextEditor/CommentPopover.tsx
|
|
4
|
-
function
|
|
5
|
+
function s() {
|
|
5
6
|
return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
6
7
|
}
|
|
7
|
-
function
|
|
8
|
+
function c(e) {
|
|
8
9
|
let t = Date.now() - e, n = Math.floor(t / 1e3);
|
|
9
10
|
if (n < 60) return "just now";
|
|
10
11
|
let r = Math.floor(n / 60);
|
|
@@ -12,91 +13,114 @@ function s(e) {
|
|
|
12
13
|
let i = Math.floor(r / 60);
|
|
13
14
|
return i < 24 ? `${i}h ago` : `${Math.floor(i / 24)}d ago`;
|
|
14
15
|
}
|
|
15
|
-
var
|
|
16
|
-
let [
|
|
16
|
+
var l = ({ editor: l, threads: u, onThreadsChange: d, showPanel: f, onOpenPanel: p, onScrollToThread: m, currentUser: h = "User", editable: g = !0 }) => {
|
|
17
|
+
let [_, v] = r(null), y = u.find((e) => e.id === _ && !e.resolved), b = n({
|
|
18
|
+
editable: g,
|
|
19
|
+
threads: u,
|
|
20
|
+
activeThreadId: _
|
|
21
|
+
});
|
|
22
|
+
b.current = {
|
|
23
|
+
editable: g,
|
|
24
|
+
threads: u,
|
|
25
|
+
activeThreadId: _
|
|
26
|
+
};
|
|
27
|
+
let x = o({
|
|
28
|
+
editor: l,
|
|
29
|
+
selector: ({ editor: e }) => e.isEditable
|
|
30
|
+
}), S = g && x, [C, w] = r({
|
|
17
31
|
x: 0,
|
|
18
32
|
y: 0
|
|
19
|
-
}), [
|
|
33
|
+
}), [T, E] = r(""), D = n(null), O = n(null);
|
|
20
34
|
t(() => {
|
|
21
|
-
let e =
|
|
35
|
+
let e = l.view.dom, t = (t) => {
|
|
22
36
|
let n = t.target.closest(".rte-comment-mark");
|
|
23
37
|
if (!n) {
|
|
24
|
-
|
|
38
|
+
v(null);
|
|
25
39
|
return;
|
|
26
40
|
}
|
|
27
|
-
let r = n.getAttribute("data-comment-id");
|
|
28
|
-
if (!r)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
let r = n.getAttribute("data-comment-id"), i = b.current.threads.find((e) => e.id === r);
|
|
42
|
+
if (!r || !i || i.resolved) {
|
|
43
|
+
v(null);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (f) {
|
|
47
|
+
m(r), v(null);
|
|
33
48
|
return;
|
|
34
49
|
}
|
|
35
50
|
let a = e.closest(".rte-editor-wrapper");
|
|
36
51
|
if (!a) return;
|
|
37
52
|
let o = a.getBoundingClientRect(), s = n.getBoundingClientRect();
|
|
38
|
-
|
|
53
|
+
w({
|
|
39
54
|
x: s.left - o.left + s.width / 2,
|
|
40
55
|
y: s.bottom - o.top + 6
|
|
41
|
-
}),
|
|
56
|
+
}), v(i.id), E("");
|
|
42
57
|
};
|
|
43
58
|
return e.addEventListener("click", t), () => e.removeEventListener("click", t);
|
|
44
59
|
}, [
|
|
45
|
-
c,
|
|
46
60
|
l,
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
u,
|
|
62
|
+
f,
|
|
63
|
+
m
|
|
49
64
|
]), t(() => {
|
|
50
|
-
if (!
|
|
65
|
+
if (!y) return;
|
|
51
66
|
let e = (e) => {
|
|
52
|
-
|
|
67
|
+
D.current && !D.current.contains(e.target) && v(null);
|
|
53
68
|
};
|
|
54
69
|
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
55
|
-
}, [
|
|
56
|
-
|
|
57
|
-
}, [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
}, [y]), t(() => {
|
|
71
|
+
_ && O.current && O.current.focus();
|
|
72
|
+
}, [_, S]), t(() => {
|
|
73
|
+
(!y || f) && (v(null), E(""));
|
|
74
|
+
}, [y, f]);
|
|
75
|
+
let k = e(() => {
|
|
76
|
+
if (!b.current.editable || !l.isEditable) return;
|
|
77
|
+
let e = b.current.threads.find((e) => e.id === b.current.activeThreadId && !e.resolved);
|
|
78
|
+
if (!e) return;
|
|
79
|
+
let t = l.state.tr;
|
|
80
|
+
l.state.doc.descendants((n, r) => {
|
|
81
|
+
n.marks.forEach((i) => {
|
|
82
|
+
i.type.name === "comment" && i.attrs.commentId === e.id && t.removeMark(r, r + n.nodeSize, i).addMark(r, r + n.nodeSize, i.type.create({
|
|
83
|
+
...i.attrs,
|
|
63
84
|
resolved: !0
|
|
64
|
-
}))
|
|
85
|
+
}));
|
|
65
86
|
});
|
|
66
|
-
}), {
|
|
67
|
-
...
|
|
87
|
+
}), t.docChanged && l.view.dispatch(t), d(b.current.threads.map((t) => t.id === e.id ? {
|
|
88
|
+
...t,
|
|
68
89
|
resolved: !0
|
|
69
|
-
}
|
|
90
|
+
} : t)), v(null);
|
|
70
91
|
}, [
|
|
71
|
-
|
|
72
|
-
c,
|
|
92
|
+
y,
|
|
73
93
|
l,
|
|
74
|
-
u
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
u,
|
|
95
|
+
d
|
|
96
|
+
]), A = e(() => {
|
|
97
|
+
if (!b.current.editable || !l.isEditable || !T.trim()) return;
|
|
98
|
+
let e = b.current.threads.find((e) => e.id === b.current.activeThreadId && !e.resolved);
|
|
99
|
+
if (!e) return;
|
|
100
|
+
let t = {
|
|
101
|
+
id: s(),
|
|
102
|
+
author: h,
|
|
103
|
+
text: T.trim(),
|
|
81
104
|
createdAt: Date.now()
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
};
|
|
106
|
+
d(b.current.threads.map((n) => n.id === e.id ? {
|
|
107
|
+
...n,
|
|
108
|
+
comments: [...n.comments, t]
|
|
109
|
+
} : n)), E("");
|
|
87
110
|
}, [
|
|
88
|
-
h,
|
|
89
|
-
y,
|
|
90
111
|
l,
|
|
112
|
+
y,
|
|
113
|
+
T,
|
|
91
114
|
u,
|
|
92
|
-
|
|
115
|
+
d,
|
|
116
|
+
h
|
|
93
117
|
]);
|
|
94
|
-
return
|
|
95
|
-
ref:
|
|
118
|
+
return !y || f ? null : /* @__PURE__ */ a("div", {
|
|
119
|
+
ref: D,
|
|
96
120
|
className: "rte-comment-popover",
|
|
97
121
|
style: {
|
|
98
|
-
left:
|
|
99
|
-
top:
|
|
122
|
+
left: C.x,
|
|
123
|
+
top: C.y
|
|
100
124
|
},
|
|
101
125
|
children: [
|
|
102
126
|
/* @__PURE__ */ a("div", {
|
|
@@ -107,10 +131,10 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
107
131
|
}), /* @__PURE__ */ a("div", {
|
|
108
132
|
className: "rte-comment-popover__actions",
|
|
109
133
|
children: [
|
|
110
|
-
/* @__PURE__ */ i("button", {
|
|
134
|
+
S && /* @__PURE__ */ i("button", {
|
|
111
135
|
type: "button",
|
|
112
136
|
className: "rte-comments__icon-btn",
|
|
113
|
-
onClick:
|
|
137
|
+
onClick: k,
|
|
114
138
|
title: "Resolve",
|
|
115
139
|
children: /* @__PURE__ */ i("svg", {
|
|
116
140
|
width: "14",
|
|
@@ -126,7 +150,7 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
126
150
|
type: "button",
|
|
127
151
|
className: "rte-comments__icon-btn",
|
|
128
152
|
onClick: () => {
|
|
129
|
-
|
|
153
|
+
p(), v(null);
|
|
130
154
|
},
|
|
131
155
|
title: "Open panel",
|
|
132
156
|
children: /* @__PURE__ */ a("svg", {
|
|
@@ -157,7 +181,7 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
157
181
|
/* @__PURE__ */ i("button", {
|
|
158
182
|
type: "button",
|
|
159
183
|
className: "rte-comments__icon-btn",
|
|
160
|
-
onClick: () =>
|
|
184
|
+
onClick: () => v(null),
|
|
161
185
|
title: "Close",
|
|
162
186
|
children: /* @__PURE__ */ a("svg", {
|
|
163
187
|
width: "14",
|
|
@@ -182,7 +206,7 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
182
206
|
]
|
|
183
207
|
})]
|
|
184
208
|
}),
|
|
185
|
-
|
|
209
|
+
y.comments.map((e) => /* @__PURE__ */ a("div", {
|
|
186
210
|
className: "rte-comment-popover__comment",
|
|
187
211
|
children: [/* @__PURE__ */ a("div", {
|
|
188
212
|
className: "rte-comments__comment-meta",
|
|
@@ -191,29 +215,29 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
191
215
|
children: e.author
|
|
192
216
|
}), /* @__PURE__ */ i("span", {
|
|
193
217
|
className: "rte-comments__time",
|
|
194
|
-
children:
|
|
218
|
+
children: c(e.createdAt)
|
|
195
219
|
})]
|
|
196
220
|
}), /* @__PURE__ */ i("div", {
|
|
197
221
|
className: "rte-comments__comment-text",
|
|
198
222
|
children: e.text
|
|
199
223
|
})]
|
|
200
224
|
}, e.id)),
|
|
201
|
-
/* @__PURE__ */ a("div", {
|
|
225
|
+
S && /* @__PURE__ */ a("div", {
|
|
202
226
|
className: "rte-comment-popover__reply",
|
|
203
227
|
children: [/* @__PURE__ */ i("input", {
|
|
204
|
-
ref:
|
|
228
|
+
ref: O,
|
|
205
229
|
className: "rte-comments__reply-input",
|
|
206
|
-
value:
|
|
207
|
-
onChange: (e) =>
|
|
230
|
+
value: T,
|
|
231
|
+
onChange: (e) => E(e.target.value),
|
|
208
232
|
onKeyDown: (e) => {
|
|
209
|
-
e.key === "Enter" &&
|
|
233
|
+
e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229 || (e.key === "Enter" && (e.preventDefault(), A()), e.key === "Escape" && v(null));
|
|
210
234
|
},
|
|
211
235
|
placeholder: "Reply..."
|
|
212
236
|
}), /* @__PURE__ */ i("button", {
|
|
213
237
|
type: "button",
|
|
214
238
|
className: "rte-comments__reply-send",
|
|
215
|
-
onClick:
|
|
216
|
-
disabled: !
|
|
239
|
+
onClick: A,
|
|
240
|
+
disabled: !T.trim(),
|
|
217
241
|
children: /* @__PURE__ */ a("svg", {
|
|
218
242
|
width: "12",
|
|
219
243
|
height: "12",
|
|
@@ -231,9 +255,9 @@ var c = ({ editor: c, threads: l, onThreadsChange: u, showPanel: d, onOpenPanel:
|
|
|
231
255
|
})]
|
|
232
256
|
})
|
|
233
257
|
]
|
|
234
|
-
})
|
|
258
|
+
});
|
|
235
259
|
};
|
|
236
260
|
//#endregion
|
|
237
|
-
export {
|
|
261
|
+
export { l as default };
|
|
238
262
|
|
|
239
263
|
//# sourceMappingURL=CommentPopover.js.map
|