@arbidocs/blocks 0.4.95 → 0.4.97
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/agents/index.cjs +283 -283
- package/dist/agents/index.js +7 -7
- package/dist/chat/index.cjs +127 -127
- package/dist/chat/index.js +4 -4
- package/dist/{chunk-DCZGYCN2.cjs → chunk-3US5OIDQ.cjs} +5 -5
- package/dist/{chunk-DCZGYCN2.cjs.map → chunk-3US5OIDQ.cjs.map} +1 -1
- package/dist/{chunk-QQH2NI5U.js → chunk-5NQIBJPP.js} +8 -8
- package/dist/{chunk-QQH2NI5U.js.map → chunk-5NQIBJPP.js.map} +1 -1
- package/dist/{chunk-KBPHLW2R.cjs → chunk-B4SRYJLM.cjs} +3 -3
- package/dist/{chunk-KBPHLW2R.cjs.map → chunk-B4SRYJLM.cjs.map} +1 -1
- package/dist/chunk-D54JXTPG.cjs +164 -0
- package/dist/chunk-D54JXTPG.cjs.map +1 -0
- package/dist/{chunk-VQ65UHTV.cjs → chunk-DDYXFALG.cjs} +47 -47
- package/dist/{chunk-VQ65UHTV.cjs.map → chunk-DDYXFALG.cjs.map} +1 -1
- package/dist/{chunk-RZGVMV6B.cjs → chunk-EHB7J6SR.cjs} +5 -5
- package/dist/{chunk-RZGVMV6B.cjs.map → chunk-EHB7J6SR.cjs.map} +1 -1
- package/dist/{chunk-EJAYB7PP.js → chunk-EWSEQEPL.js} +4 -4
- package/dist/{chunk-EJAYB7PP.js.map → chunk-EWSEQEPL.js.map} +1 -1
- package/dist/{chunk-3OXWJ3CZ.cjs → chunk-GVOTXXZG.cjs} +5 -5
- package/dist/{chunk-3OXWJ3CZ.cjs.map → chunk-GVOTXXZG.cjs.map} +1 -1
- package/dist/{chunk-CKYA2IG5.cjs → chunk-HBF4BDRU.cjs} +3 -3
- package/dist/{chunk-CKYA2IG5.cjs.map → chunk-HBF4BDRU.cjs.map} +1 -1
- package/dist/{chunk-E2AAIMXO.cjs → chunk-HGJGALLN.cjs} +832 -219
- package/dist/chunk-HGJGALLN.cjs.map +1 -0
- package/dist/{chunk-24CS7JWU.js → chunk-HOXKR26S.js} +3 -3
- package/dist/{chunk-24CS7JWU.js.map → chunk-HOXKR26S.js.map} +1 -1
- package/dist/{chunk-PDEHIGJ5.js → chunk-ICBAFX5B.js} +3 -3
- package/dist/{chunk-PDEHIGJ5.js.map → chunk-ICBAFX5B.js.map} +1 -1
- package/dist/{chunk-OYMYNYFV.cjs → chunk-IF6VAYIA.cjs} +5 -5
- package/dist/{chunk-OYMYNYFV.cjs.map → chunk-IF6VAYIA.cjs.map} +1 -1
- package/dist/{chunk-TOVSTC2M.cjs → chunk-LENXDIMY.cjs} +5 -5
- package/dist/{chunk-TOVSTC2M.cjs.map → chunk-LENXDIMY.cjs.map} +1 -1
- package/dist/{chunk-VYKMBLDX.cjs → chunk-MP6FK43E.cjs} +8 -8
- package/dist/{chunk-VYKMBLDX.cjs.map → chunk-MP6FK43E.cjs.map} +1 -1
- package/dist/{chunk-HUFLBZWI.js → chunk-PGDL26TQ.js} +4 -4
- package/dist/{chunk-HUFLBZWI.js.map → chunk-PGDL26TQ.js.map} +1 -1
- package/dist/{chunk-WXLKMEMB.js → chunk-QIEEFBZ5.js} +834 -221
- package/dist/chunk-QIEEFBZ5.js.map +1 -0
- package/dist/{chunk-YPKSLTL5.js → chunk-RSUOOMPT.js} +3 -3
- package/dist/{chunk-YPKSLTL5.js.map → chunk-RSUOOMPT.js.map} +1 -1
- package/dist/{chunk-UMY6Y6BM.js → chunk-VLOPZHFH.js} +3 -3
- package/dist/{chunk-UMY6Y6BM.js.map → chunk-VLOPZHFH.js.map} +1 -1
- package/dist/{chunk-GNHOB2ZB.cjs → chunk-XMBYDLZQ.cjs} +4 -4
- package/dist/{chunk-GNHOB2ZB.cjs.map → chunk-XMBYDLZQ.cjs.map} +1 -1
- package/dist/{chunk-YG7DGGCA.js → chunk-XQDM6T6C.js} +3 -3
- package/dist/{chunk-YG7DGGCA.js.map → chunk-XQDM6T6C.js.map} +1 -1
- package/dist/{chunk-ZNDAXSDP.js → chunk-YH6SSJDW.js} +3 -3
- package/dist/{chunk-ZNDAXSDP.js.map → chunk-YH6SSJDW.js.map} +1 -1
- package/dist/{chunk-EOEDGJ75.js → chunk-Z3G65XHZ.js} +3 -3
- package/dist/{chunk-EOEDGJ75.js.map → chunk-Z3G65XHZ.js.map} +1 -1
- package/dist/chunk-ZCOVDK2E.js +153 -0
- package/dist/chunk-ZCOVDK2E.js.map +1 -0
- package/dist/components/DetailPanel.d.ts +106 -0
- package/dist/connect/docx.cjs +6 -6
- package/dist/connect/docx.js +4 -4
- package/dist/connect/index.cjs +47 -47
- package/dist/connect/index.js +17 -17
- package/dist/databases/DatabaseRowDetail.d.ts +32 -0
- package/dist/databases/DatabaseTable.d.ts +3 -1
- package/dist/databases/DatabaseToolbar.d.ts +9 -1
- package/dist/databases/PickCellEditor.d.ts +8 -1
- package/dist/databases/SelectCellEditor.d.ts +6 -1
- package/dist/databases/column-types.d.ts +5 -0
- package/dist/databases/databaseColumns.d.ts +7 -0
- package/dist/databases/index.cjs +381 -11
- package/dist/databases/index.cjs.map +1 -1
- package/dist/databases/index.d.ts +7 -5
- package/dist/databases/index.js +379 -14
- package/dist/databases/index.js.map +1 -1
- package/dist/databases/linkCells.d.ts +4 -2
- package/dist/docx/NativeDocxEditor.d.ts +3 -1
- package/dist/docx/RibbonMenu.d.ts +15 -0
- package/dist/docx/StyleGallery.d.ts +9 -0
- package/dist/docx/WordReferences.d.ts +21 -0
- package/dist/docx/index.cjs +24 -24
- package/dist/docx/index.js +3 -3
- package/dist/docx/review/DocxEditorReview.d.ts +4 -2
- package/dist/docx/review/commentText.d.ts +7 -0
- package/dist/docx/wordStyles.d.ts +21 -0
- package/dist/facts/index.cjs +5 -5
- package/dist/facts/index.js +2 -2
- package/dist/files/index.cjs +308 -0
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.js +298 -2
- package/dist/files/index.js.map +1 -1
- package/dist/files/views/gridViews.d.ts +80 -0
- package/dist/files/views/index.d.ts +2 -0
- package/dist/files/views/useGridViews.d.ts +38 -0
- package/dist/index.cjs +1237 -1237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +100 -139
- package/dist/index.js.map +1 -1
- package/dist/settings/index.cjs +1 -1
- package/dist/settings/index.js +1 -1
- package/dist/shell/index.cjs +67 -67
- package/dist/shell/index.js +3 -3
- package/dist/studio/index.cjs +7 -7
- package/dist/studio/index.js +6 -6
- package/dist/tags/TagDetail.d.ts +1 -0
- package/dist/workflow-canvas/index.cjs +51 -51
- package/dist/workflow-canvas/index.js +8 -8
- package/package.json +4 -4
- package/src/docx/styles.css +564 -91
- package/dist/chunk-E2AAIMXO.cjs.map +0 -1
- package/dist/chunk-WXLKMEMB.js.map +0 -1
|
@@ -7,14 +7,14 @@ var fflate = require('fflate');
|
|
|
7
7
|
var store = require('@docx-editor.dev/core/store');
|
|
8
8
|
var React3 = require('react');
|
|
9
9
|
var react = require('@docx-editor.dev/react');
|
|
10
|
+
var ui = require('@arbidocs/react/ui');
|
|
11
|
+
var lucideReact = require('lucide-react');
|
|
10
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
11
13
|
var reactDom = require('react-dom');
|
|
12
|
-
var ui = require('@arbidocs/react/ui');
|
|
13
14
|
var server = require('react-dom/server');
|
|
14
15
|
var Y = require('yjs');
|
|
15
16
|
var coedit = require('@arbidocs/coedit');
|
|
16
17
|
var hocuspocus = require('@arbidocs/coedit/hocuspocus');
|
|
17
|
-
var lucideReact = require('lucide-react');
|
|
18
18
|
|
|
19
19
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
20
|
|
|
@@ -161,7 +161,25 @@ var ReviewItemContext = React3.createContext(null);
|
|
|
161
161
|
function useReviewItem() {
|
|
162
162
|
return React3.useContext(ReviewItemContext);
|
|
163
163
|
}
|
|
164
|
+
|
|
165
|
+
// src/docx/review/commentText.ts
|
|
166
|
+
var SKIP = /* @__PURE__ */ new Set(["delText", "instrText", "delInstrText", "pPr", "rPr"]);
|
|
167
|
+
function inline(node) {
|
|
168
|
+
if (node.kind === "textValue") return node.value ?? "";
|
|
169
|
+
if (node.localName && SKIP.has(node.localName)) return "";
|
|
170
|
+
if (node.localName === "br" || node.localName === "cr") return "\n";
|
|
171
|
+
if (node.localName === "tab") return " ";
|
|
172
|
+
return (node.children ?? []).map(inline).join("");
|
|
173
|
+
}
|
|
174
|
+
function commentText(entry) {
|
|
175
|
+
if (entry.kind !== "comment") return entry.text;
|
|
176
|
+
const blocks = entry.item?.comment?.blocks ?? [];
|
|
177
|
+
const text = blocks.map(inline).join("\n").trim();
|
|
178
|
+
return text || entry.text;
|
|
179
|
+
}
|
|
164
180
|
var CARD_GAP = 8;
|
|
181
|
+
var CLUSTER_GAP = 24;
|
|
182
|
+
var REVIEW_MARGIN_MIN_WIDTH = 900;
|
|
165
183
|
var REVISION_LABELS = {
|
|
166
184
|
insert: "Inserted",
|
|
167
185
|
delete: "Deleted",
|
|
@@ -177,33 +195,102 @@ function isTopLevel(entry) {
|
|
|
177
195
|
if (entry.kind === "custom") return entry.item.carded;
|
|
178
196
|
return true;
|
|
179
197
|
}
|
|
180
|
-
function
|
|
181
|
-
if (
|
|
198
|
+
function kindLabel(entry) {
|
|
199
|
+
if (entry.kind === "revision") return REVISION_LABELS[entry.revisionKind] ?? "Change";
|
|
200
|
+
if (entry.kind === "comment") return entry.resolved ? "Resolved" : "Comment";
|
|
201
|
+
return "Note";
|
|
202
|
+
}
|
|
203
|
+
function parseDate(value) {
|
|
204
|
+
if (!value) return null;
|
|
182
205
|
const date = new Date(value);
|
|
183
|
-
return Number.isNaN(date.getTime()) ?
|
|
206
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
207
|
+
}
|
|
208
|
+
function relativeDate(date) {
|
|
209
|
+
const seconds = (Date.now() - date.getTime()) / 1e3;
|
|
210
|
+
if (seconds < 45) return "just now";
|
|
211
|
+
if (seconds < 45 * 60) return `${Math.round(seconds / 60)}m ago`;
|
|
212
|
+
if (seconds < 22 * 3600) return `${Math.round(seconds / 3600)}h ago`;
|
|
213
|
+
if (seconds < 7 * 86400) return `${Math.round(seconds / 86400)}d ago`;
|
|
214
|
+
const sameYear = date.getFullYear() === (/* @__PURE__ */ new Date()).getFullYear();
|
|
215
|
+
return date.toLocaleDateString(void 0, {
|
|
216
|
+
day: "numeric",
|
|
217
|
+
month: "short",
|
|
218
|
+
year: sameYear ? void 0 : "numeric"
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
function authorHue(author) {
|
|
222
|
+
let hash = 0;
|
|
223
|
+
for (const char of author) hash = hash * 31 + char.charCodeAt(0) | 0;
|
|
224
|
+
return Math.abs(hash) % 360;
|
|
184
225
|
}
|
|
185
226
|
function Avatar({ entry }) {
|
|
186
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
228
|
+
"span",
|
|
229
|
+
{
|
|
230
|
+
className: "native-docx-review-avatar",
|
|
231
|
+
"aria-hidden": "true",
|
|
232
|
+
style: { "--review-author-hue": authorHue(entry.author || "") },
|
|
233
|
+
children: entry.initials
|
|
234
|
+
}
|
|
235
|
+
);
|
|
187
236
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
237
|
+
function Byline({ entry, children }) {
|
|
238
|
+
const date = parseDate(entry.date);
|
|
239
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-byline", children: [
|
|
240
|
+
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { entry }),
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-who", children: [
|
|
192
242
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-review-author", children: entry.author || "Reviewer" }),
|
|
193
|
-
/* @__PURE__ */ jsxRuntime.
|
|
243
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "native-docx-review-meta", children: [
|
|
244
|
+
kindLabel(entry),
|
|
245
|
+
date && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
246
|
+
" \xB7 ",
|
|
247
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
248
|
+
"time",
|
|
249
|
+
{
|
|
250
|
+
className: "native-docx-review-date",
|
|
251
|
+
dateTime: date.toISOString(),
|
|
252
|
+
title: date.toLocaleString(),
|
|
253
|
+
children: relativeDate(date)
|
|
254
|
+
}
|
|
255
|
+
)
|
|
256
|
+
] })
|
|
257
|
+
] })
|
|
258
|
+
] }),
|
|
259
|
+
children
|
|
260
|
+
] });
|
|
261
|
+
}
|
|
262
|
+
function ChangeText({ entry }) {
|
|
263
|
+
const removed = entry.revisionKind === "replace" ? entry.replacedText : void 0;
|
|
264
|
+
const struck = entry.revisionKind === "delete" || entry.revisionKind === "moveFrom";
|
|
265
|
+
const added = entry.revisionKind === "insert" || entry.revisionKind === "moveTo" || removed !== void 0;
|
|
266
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "native-docx-review-change", "data-testid": "review-text", children: [
|
|
267
|
+
removed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
268
|
+
/* @__PURE__ */ jsxRuntime.jsx("del", { children: removed }),
|
|
269
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-review-arrow", "aria-hidden": "true", children: "\u2192" })
|
|
194
270
|
] }),
|
|
195
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
271
|
+
struck ? /* @__PURE__ */ jsxRuntime.jsx("del", { children: entry.text }) : added ? /* @__PURE__ */ jsxRuntime.jsx("ins", { children: entry.text }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: entry.text })
|
|
272
|
+
] });
|
|
273
|
+
}
|
|
274
|
+
function CommentText({ text, testId }) {
|
|
275
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-review-text", "data-testid": testId, children: /* @__PURE__ */ jsxRuntime.jsx(ui.AiMarkdown, { className: "native-docx-review-markdown", allowHtml: false, children: text }) });
|
|
276
|
+
}
|
|
277
|
+
function Reply({ entry }) {
|
|
278
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-message", children: [
|
|
279
|
+
/* @__PURE__ */ jsxRuntime.jsx(Byline, { entry }),
|
|
280
|
+
/* @__PURE__ */ jsxRuntime.jsx(CommentText, { text: commentText(entry) })
|
|
196
281
|
] });
|
|
197
282
|
}
|
|
198
283
|
function ReplyForm({
|
|
199
284
|
entry,
|
|
200
|
-
review
|
|
285
|
+
review,
|
|
286
|
+
onDismiss
|
|
201
287
|
}) {
|
|
202
288
|
const [text, setText] = React3.useState("");
|
|
203
289
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
204
290
|
"form",
|
|
205
291
|
{
|
|
206
292
|
className: "native-docx-review-reply",
|
|
293
|
+
onClick: (event) => event.stopPropagation(),
|
|
207
294
|
onSubmit: (event) => {
|
|
208
295
|
event.preventDefault();
|
|
209
296
|
const value = text.trim();
|
|
@@ -215,25 +302,39 @@ function ReplyForm({
|
|
|
215
302
|
{
|
|
216
303
|
"data-testid": "review-reply-input",
|
|
217
304
|
"aria-label": "Reply",
|
|
218
|
-
placeholder: "Reply",
|
|
305
|
+
placeholder: "Reply\u2026",
|
|
219
306
|
value: text,
|
|
220
307
|
onChange: (event) => setText(event.target.value),
|
|
221
308
|
onKeyDown: (event) => {
|
|
222
309
|
if (event.key === "Escape") {
|
|
310
|
+
event.preventDefault();
|
|
223
311
|
event.stopPropagation();
|
|
224
|
-
|
|
312
|
+
onDismiss();
|
|
225
313
|
}
|
|
226
314
|
}
|
|
227
315
|
}
|
|
228
316
|
),
|
|
229
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
317
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
318
|
+
"button",
|
|
319
|
+
{
|
|
320
|
+
type: "submit",
|
|
321
|
+
className: "native-docx-review-icon native-docx-review-send",
|
|
322
|
+
"aria-label": "Reply",
|
|
323
|
+
title: "Reply",
|
|
324
|
+
disabled: !text.trim(),
|
|
325
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendHorizontal, { size: 14 })
|
|
326
|
+
}
|
|
327
|
+
),
|
|
230
328
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
231
329
|
"button",
|
|
232
330
|
{
|
|
233
331
|
type: "button",
|
|
332
|
+
className: "native-docx-review-icon",
|
|
234
333
|
"data-testid": "review-reply-cancel",
|
|
235
|
-
|
|
236
|
-
|
|
334
|
+
"aria-label": "Cancel",
|
|
335
|
+
title: "Cancel",
|
|
336
|
+
onClick: onDismiss,
|
|
337
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 })
|
|
237
338
|
}
|
|
238
339
|
)
|
|
239
340
|
]
|
|
@@ -246,7 +347,8 @@ function Card({
|
|
|
246
347
|
review,
|
|
247
348
|
extra,
|
|
248
349
|
cardRef,
|
|
249
|
-
top
|
|
350
|
+
top,
|
|
351
|
+
onDismiss
|
|
250
352
|
}) {
|
|
251
353
|
const resolved = entry.kind === "comment" && entry.resolved;
|
|
252
354
|
return /* @__PURE__ */ jsxRuntime.jsx(ReviewItemContext.Provider, { value: entry, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -265,60 +367,85 @@ function Card({
|
|
|
265
367
|
},
|
|
266
368
|
"data-testid": "review-card",
|
|
267
369
|
"data-kind": entry.kind,
|
|
370
|
+
"data-change": entry.kind === "revision" ? entry.revisionKind : void 0,
|
|
268
371
|
"data-active": entry.isActive || void 0,
|
|
269
372
|
"data-resolved": resolved || void 0,
|
|
270
|
-
|
|
373
|
+
"data-floating": top === void 0 || void 0,
|
|
374
|
+
style: top === void 0 ? void 0 : { top },
|
|
271
375
|
onClick: () => {
|
|
272
376
|
if (entry.activatable && !entry.isActive) review.setActive(entry.key);
|
|
273
377
|
},
|
|
274
378
|
children: [
|
|
275
|
-
entry.kind === "
|
|
276
|
-
|
|
277
|
-
|
|
379
|
+
/* @__PURE__ */ jsxRuntime.jsx(Byline, { entry, children: entry.kind === "comment" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-tools", children: [
|
|
380
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
381
|
+
"button",
|
|
382
|
+
{
|
|
383
|
+
type: "button",
|
|
384
|
+
className: "native-docx-review-icon",
|
|
385
|
+
"data-testid": "review-resolve",
|
|
386
|
+
"aria-label": entry.resolved ? "Reopen" : "Resolve",
|
|
387
|
+
title: entry.resolved ? "Reopen" : "Resolve",
|
|
388
|
+
onClick: (event) => {
|
|
389
|
+
event.stopPropagation();
|
|
390
|
+
review.resolve(entry, !entry.resolved);
|
|
391
|
+
},
|
|
392
|
+
children: entry.resolved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, { size: 14 })
|
|
393
|
+
}
|
|
394
|
+
),
|
|
395
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
396
|
+
"button",
|
|
397
|
+
{
|
|
398
|
+
type: "button",
|
|
399
|
+
className: "native-docx-review-icon",
|
|
400
|
+
"data-testid": "review-delete",
|
|
401
|
+
"aria-label": "Delete",
|
|
402
|
+
title: "Delete",
|
|
403
|
+
onClick: (event) => {
|
|
404
|
+
event.stopPropagation();
|
|
405
|
+
review.remove(entry);
|
|
406
|
+
},
|
|
407
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 14 })
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
] }) }),
|
|
411
|
+
entry.kind === "revision" ? /* @__PURE__ */ jsxRuntime.jsx(ChangeText, { entry }) : /* @__PURE__ */ jsxRuntime.jsx(CommentText, { text: commentText(entry), testId: "review-text" }),
|
|
412
|
+
replies.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-review-thread", children: replies.map((reply) => /* @__PURE__ */ jsxRuntime.jsx(Reply, { entry: reply }, reply.key)) }),
|
|
278
413
|
extra,
|
|
279
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
{
|
|
313
|
-
type: "button",
|
|
314
|
-
"data-testid": "review-delete",
|
|
315
|
-
onClick: () => review.remove(entry),
|
|
316
|
-
children: "Delete"
|
|
317
|
-
}
|
|
318
|
-
)
|
|
319
|
-
] })
|
|
414
|
+
entry.kind === "revision" && !entry.readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-decide", children: [
|
|
415
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
416
|
+
"button",
|
|
417
|
+
{
|
|
418
|
+
type: "button",
|
|
419
|
+
className: "native-docx-review-accept",
|
|
420
|
+
"data-testid": "review-accept",
|
|
421
|
+
onClick: (event) => {
|
|
422
|
+
event.stopPropagation();
|
|
423
|
+
review.accept(entry);
|
|
424
|
+
},
|
|
425
|
+
children: [
|
|
426
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 14 }),
|
|
427
|
+
"Accept"
|
|
428
|
+
]
|
|
429
|
+
}
|
|
430
|
+
),
|
|
431
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
432
|
+
"button",
|
|
433
|
+
{
|
|
434
|
+
type: "button",
|
|
435
|
+
className: "native-docx-review-reject",
|
|
436
|
+
"data-testid": "review-reject",
|
|
437
|
+
onClick: (event) => {
|
|
438
|
+
event.stopPropagation();
|
|
439
|
+
review.reject(entry);
|
|
440
|
+
},
|
|
441
|
+
children: [
|
|
442
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }),
|
|
443
|
+
"Reject"
|
|
444
|
+
]
|
|
445
|
+
}
|
|
446
|
+
)
|
|
320
447
|
] }),
|
|
321
|
-
entry.isActive && entry.kind !== "custom" && /* @__PURE__ */ jsxRuntime.jsx(ReplyForm, { entry, review })
|
|
448
|
+
entry.isActive && entry.kind !== "custom" && /* @__PURE__ */ jsxRuntime.jsx(ReplyForm, { entry, review, onDismiss })
|
|
322
449
|
]
|
|
323
450
|
}
|
|
324
451
|
) });
|
|
@@ -338,7 +465,8 @@ function Draft({
|
|
|
338
465
|
ref: formRef,
|
|
339
466
|
className: "native-docx-review-card native-docx-review-draft",
|
|
340
467
|
"data-testid": "review-draft",
|
|
341
|
-
|
|
468
|
+
"data-floating": top === void 0 || void 0,
|
|
469
|
+
style: top === void 0 ? void 0 : { top },
|
|
342
470
|
onSubmit: (event) => {
|
|
343
471
|
event.preventDefault();
|
|
344
472
|
if (text.trim()) onSubmit(text.trim());
|
|
@@ -350,22 +478,53 @@ function Draft({
|
|
|
350
478
|
ref: input,
|
|
351
479
|
"data-testid": "review-draft-input",
|
|
352
480
|
"aria-label": "Comment",
|
|
353
|
-
placeholder: "Add a comment",
|
|
481
|
+
placeholder: "Add a comment\u2026",
|
|
354
482
|
value: text,
|
|
355
483
|
onChange: (event) => setText(event.target.value),
|
|
356
484
|
onKeyDown: (event) => {
|
|
357
|
-
if (event.key === "Escape")
|
|
485
|
+
if (event.key === "Escape") {
|
|
486
|
+
event.preventDefault();
|
|
487
|
+
event.stopPropagation();
|
|
488
|
+
onCancel();
|
|
489
|
+
}
|
|
358
490
|
}
|
|
359
491
|
}
|
|
360
492
|
),
|
|
361
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-
|
|
362
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: !text.trim(), children: "Comment" }),
|
|
363
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-decide", children: [
|
|
494
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "native-docx-review-accept", disabled: !text.trim(), children: "Comment" }),
|
|
495
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
496
|
+
"button",
|
|
497
|
+
{
|
|
498
|
+
type: "button",
|
|
499
|
+
className: "native-docx-review-plain",
|
|
500
|
+
"data-testid": "review-draft-cancel",
|
|
501
|
+
onClick: onCancel,
|
|
502
|
+
children: "Cancel"
|
|
503
|
+
}
|
|
504
|
+
)
|
|
364
505
|
] })
|
|
365
506
|
]
|
|
366
507
|
}
|
|
367
508
|
);
|
|
368
509
|
}
|
|
510
|
+
function useScrollArea(anchor, ready) {
|
|
511
|
+
const [area, setArea] = React3.useState({
|
|
512
|
+
element: null,
|
|
513
|
+
width: 0
|
|
514
|
+
});
|
|
515
|
+
React3.useLayoutEffect(() => {
|
|
516
|
+
const element = anchor.current?.closest(".docx-editor__scroll-container") ?? null;
|
|
517
|
+
const measure = () => setArea(
|
|
518
|
+
(previous) => previous.element === element && previous.width === (element?.clientWidth ?? 0) ? previous : { element, width: element?.clientWidth ?? 0 }
|
|
519
|
+
);
|
|
520
|
+
measure();
|
|
521
|
+
if (!element || typeof ResizeObserver === "undefined") return;
|
|
522
|
+
const observer = new ResizeObserver(measure);
|
|
523
|
+
observer.observe(element);
|
|
524
|
+
return () => observer.disconnect();
|
|
525
|
+
}, [anchor, ready]);
|
|
526
|
+
return area;
|
|
527
|
+
}
|
|
369
528
|
function DocxEditorReviewRail({
|
|
370
529
|
children
|
|
371
530
|
}) {
|
|
@@ -376,6 +535,10 @@ function DocxEditorReviewRail({
|
|
|
376
535
|
const [tops, setTops] = React3.useState({});
|
|
377
536
|
const [showResolved, setShowResolved] = React3.useState(true);
|
|
378
537
|
const elements = React3.useRef(/* @__PURE__ */ new Map());
|
|
538
|
+
const anchor = React3.useRef(null);
|
|
539
|
+
const toolbar = React3.useRef(null);
|
|
540
|
+
const area = useScrollArea(anchor, review.ready);
|
|
541
|
+
const layout = area.width === 0 || area.width >= REVIEW_MARGIN_MIN_WIDTH ? "margin" : "compact";
|
|
379
542
|
const openDraft = React3.useCallback(() => {
|
|
380
543
|
const placement = editor?.getSelectionPlacement();
|
|
381
544
|
if (!placement) return;
|
|
@@ -384,9 +547,22 @@ function DocxEditorReviewRail({
|
|
|
384
547
|
}, [editor, review.setPaneOpen]);
|
|
385
548
|
React3.useEffect(() => registry?.register(), [registry]);
|
|
386
549
|
React3.useEffect(() => registry?.registerCommentDraft(openDraft), [registry, openDraft]);
|
|
550
|
+
const shownLayout = React3.useRef(null);
|
|
551
|
+
React3.useEffect(() => {
|
|
552
|
+
if (!review.ready || area.width === 0 || shownLayout.current === layout) return;
|
|
553
|
+
editor?.setReviewPaneOptions({ opening: layout === "margin" ? "auto" : "manual" });
|
|
554
|
+
const deepLinked = shownLayout.current === null && review.activeKey !== null;
|
|
555
|
+
shownLayout.current = layout;
|
|
556
|
+
if (layout === "margin") review.setPaneOpen(true);
|
|
557
|
+
else if (!deepLinked) {
|
|
558
|
+
setDraft(null);
|
|
559
|
+
review.setPaneOpen(false);
|
|
560
|
+
}
|
|
561
|
+
}, [editor, layout, area.width, review.ready, review.setPaneOpen]);
|
|
387
562
|
const scale = editor?.getRenderScale() ?? 1;
|
|
388
563
|
const top = review.items.filter(isTopLevel).filter((entry) => entry.anchorY !== null).filter((entry) => showResolved || entry.kind !== "comment" || !entry.resolved);
|
|
389
|
-
const
|
|
564
|
+
const changes = review.items.filter((entry) => entry.kind === "revision").length;
|
|
565
|
+
const comments = top.filter((entry) => entry.kind === "comment").length;
|
|
390
566
|
const hasResolved = review.items.some((entry) => entry.kind === "comment" && entry.resolved);
|
|
391
567
|
const repliesOf = React3.useCallback(
|
|
392
568
|
(entry) => review.items.filter(
|
|
@@ -394,10 +570,49 @@ function DocxEditorReviewRail({
|
|
|
394
570
|
),
|
|
395
571
|
[review.items]
|
|
396
572
|
);
|
|
573
|
+
const column = layout === "margin" && review.paneOpen && (top.length > 0 || draft !== null);
|
|
574
|
+
const bubbleOpen = layout === "compact" && (review.paneOpen || draft !== null);
|
|
575
|
+
React3.useEffect(() => {
|
|
576
|
+
const element = area.element;
|
|
577
|
+
if (!element) return;
|
|
578
|
+
if (column) element.setAttribute("data-review-margin", "");
|
|
579
|
+
else element.removeAttribute("data-review-margin");
|
|
580
|
+
return () => element.removeAttribute("data-review-margin");
|
|
581
|
+
}, [area.element, column]);
|
|
582
|
+
const dismiss = React3.useCallback(() => {
|
|
583
|
+
setDraft(null);
|
|
584
|
+
if (layout === "compact") review.setPaneOpen(false);
|
|
585
|
+
else review.setActive(null);
|
|
586
|
+
}, [layout, review.setPaneOpen, review.setActive]);
|
|
587
|
+
React3.useEffect(() => {
|
|
588
|
+
const element = area.element;
|
|
589
|
+
if (!element || !bubbleOpen) return;
|
|
590
|
+
const close = (event) => {
|
|
591
|
+
const target = event.target;
|
|
592
|
+
if (target instanceof Element && target.closest(
|
|
593
|
+
".native-docx-review-bubble, .native-docx-review-marker, .native-docx-review-add"
|
|
594
|
+
))
|
|
595
|
+
return;
|
|
596
|
+
dismiss();
|
|
597
|
+
};
|
|
598
|
+
const escape = (event) => {
|
|
599
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
600
|
+
if (!(event.target instanceof Node) || !element.contains(event.target)) return;
|
|
601
|
+
event.preventDefault();
|
|
602
|
+
dismiss();
|
|
603
|
+
};
|
|
604
|
+
const document2 = element.ownerDocument;
|
|
605
|
+
element.addEventListener("pointerdown", close);
|
|
606
|
+
document2.addEventListener("keydown", escape);
|
|
607
|
+
return () => {
|
|
608
|
+
element.removeEventListener("pointerdown", close);
|
|
609
|
+
document2.removeEventListener("keydown", escape);
|
|
610
|
+
};
|
|
611
|
+
}, [area.element, bubbleOpen, dismiss]);
|
|
397
612
|
React3.useLayoutEffect(() => {
|
|
398
|
-
if (!
|
|
613
|
+
if (!column) return;
|
|
399
614
|
const next = {};
|
|
400
|
-
let floor = 0;
|
|
615
|
+
let floor = (toolbar.current?.offsetHeight ?? 0) + CARD_GAP;
|
|
401
616
|
const rows = top.map((entry) => ({
|
|
402
617
|
key: entry.key,
|
|
403
618
|
y: (entry.anchorY ?? 0) * scale
|
|
@@ -415,7 +630,7 @@ function DocxEditorReviewRail({
|
|
|
415
630
|
return same ? previous : next;
|
|
416
631
|
});
|
|
417
632
|
});
|
|
418
|
-
if (!review.ready) return
|
|
633
|
+
if (!review.ready) return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: anchor, className: "native-docx-review" });
|
|
419
634
|
const selection = editor?.getSelectionPlacement();
|
|
420
635
|
const addComment = selection && /* @__PURE__ */ jsxRuntime.jsx(
|
|
421
636
|
"button",
|
|
@@ -424,108 +639,254 @@ function DocxEditorReviewRail({
|
|
|
424
639
|
className: "native-docx-review-add",
|
|
425
640
|
"data-testid": "review-add-comment",
|
|
426
641
|
"aria-label": "Add comment",
|
|
642
|
+
title: "Add comment",
|
|
427
643
|
style: { top: selection.anchorY * scale },
|
|
428
644
|
onMouseDown: (event) => event.preventDefault(),
|
|
429
645
|
onClick: openDraft,
|
|
430
|
-
children:
|
|
646
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquarePlus, { size: 14 })
|
|
431
647
|
}
|
|
432
648
|
);
|
|
433
|
-
if (
|
|
434
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
649
|
+
if (column) {
|
|
650
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: anchor, className: "native-docx-review", children: /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "native-docx-review-pane", "data-testid": "review-pane", "aria-label": "Review", children: [
|
|
435
651
|
addComment,
|
|
652
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: toolbar, className: "native-docx-review-toolbar", "data-testid": "review-toolbar", children: [
|
|
653
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-review-summary", children: [
|
|
654
|
+
changes && `${changes} ${changes === 1 ? "change" : "changes"}`,
|
|
655
|
+
comments && `${comments} ${comments === 1 ? "comment" : "comments"}`
|
|
656
|
+
].filter(Boolean).join(" \xB7 ") || "Review" }),
|
|
657
|
+
hasResolved && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "native-docx-review-switch", children: [
|
|
658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
659
|
+
"input",
|
|
660
|
+
{
|
|
661
|
+
type: "checkbox",
|
|
662
|
+
"data-testid": "review-show-resolved",
|
|
663
|
+
checked: showResolved,
|
|
664
|
+
onChange: (event) => setShowResolved(event.target.checked)
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
"Resolved"
|
|
668
|
+
] }),
|
|
669
|
+
changes > 0 && /* @__PURE__ */ jsxRuntime.jsx(BulkActions, { review, navigate: true })
|
|
670
|
+
] }),
|
|
671
|
+
draft && /* @__PURE__ */ jsxRuntime.jsx(
|
|
672
|
+
Draft,
|
|
673
|
+
{
|
|
674
|
+
top: tops.__draft ?? draft.anchorY * scale,
|
|
675
|
+
formRef: (element) => {
|
|
676
|
+
if (element) elements.current.set("__draft", element);
|
|
677
|
+
},
|
|
678
|
+
onCancel: () => setDraft(null),
|
|
679
|
+
onSubmit: (text) => {
|
|
680
|
+
if (review.addComment(text)) setDraft(null);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
),
|
|
436
684
|
top.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
685
|
+
Card,
|
|
686
|
+
{
|
|
687
|
+
entry,
|
|
688
|
+
replies: repliesOf(entry),
|
|
689
|
+
review,
|
|
690
|
+
extra: children?.(entry),
|
|
691
|
+
top: tops[entry.key] ?? (entry.anchorY ?? 0) * scale,
|
|
692
|
+
onDismiss: dismiss,
|
|
693
|
+
cardRef: (element) => {
|
|
694
|
+
if (element) elements.current.set(entry.key, element);
|
|
695
|
+
else elements.current.delete(entry.key);
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
entry.key
|
|
699
|
+
))
|
|
700
|
+
] }) });
|
|
701
|
+
}
|
|
702
|
+
const clusters = [];
|
|
703
|
+
for (const entry of [...top].sort((a, b) => (a.anchorY ?? 0) - (b.anchorY ?? 0))) {
|
|
704
|
+
const y = (entry.anchorY ?? 0) * scale;
|
|
705
|
+
const last = clusters[clusters.length - 1];
|
|
706
|
+
if (last && y - last.y < CLUSTER_GAP) last.entries.push(entry);
|
|
707
|
+
else clusters.push({ y, entries: [entry] });
|
|
708
|
+
}
|
|
709
|
+
const shown = bubbleOpen ? draft ? null : clusters.find((cluster) => cluster.entries.some((entry) => entry.isActive)) ?? clusters[0] : void 0;
|
|
710
|
+
const focus = shown?.entries.find((entry) => entry.isActive) ?? shown?.entries[0];
|
|
711
|
+
const position = focus ? top.indexOf(focus) : -1;
|
|
712
|
+
const step = (offset) => {
|
|
713
|
+
const next = top[position + offset];
|
|
714
|
+
if (next) review.setActive(next.key);
|
|
715
|
+
};
|
|
716
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: anchor, className: "native-docx-review", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-markers", "data-testid": "review-markers", children: [
|
|
717
|
+
addComment,
|
|
718
|
+
clusters.map((cluster) => {
|
|
719
|
+
const [first] = cluster.entries;
|
|
720
|
+
const comment = cluster.entries.some((entry) => entry.kind === "comment");
|
|
721
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
437
722
|
"button",
|
|
438
723
|
{
|
|
439
724
|
type: "button",
|
|
440
725
|
className: "native-docx-review-marker",
|
|
441
726
|
"data-testid": "review-marker",
|
|
442
|
-
"data-kind":
|
|
443
|
-
"
|
|
444
|
-
|
|
727
|
+
"data-kind": comment ? "comment" : first.kind,
|
|
728
|
+
"data-active": cluster === shown || void 0,
|
|
729
|
+
"aria-label": cluster.entries.length === 1 ? `${first.author}: ${first.text.slice(0, 60)}` : `${cluster.entries.length} comments and changes`,
|
|
730
|
+
"aria-expanded": layout === "compact" ? cluster === shown : void 0,
|
|
731
|
+
style: { top: cluster.y },
|
|
445
732
|
onClick: () => {
|
|
733
|
+
if (layout === "compact" && cluster === shown) return dismiss();
|
|
734
|
+
setDraft(null);
|
|
446
735
|
review.setPaneOpen(true);
|
|
447
|
-
review.setActive(
|
|
448
|
-
}
|
|
736
|
+
review.setActive(first.key);
|
|
737
|
+
},
|
|
738
|
+
children: [
|
|
739
|
+
comment ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquare, { size: 13 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PencilLine, { size: 13 }),
|
|
740
|
+
cluster.entries.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-review-count", children: cluster.entries.length })
|
|
741
|
+
]
|
|
449
742
|
},
|
|
450
|
-
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
{
|
|
471
|
-
type: "button",
|
|
472
|
-
"data-testid": "review-accept-all",
|
|
473
|
-
onClick: () => review.resolveAll("accept"),
|
|
474
|
-
children: "Accept all"
|
|
475
|
-
}
|
|
476
|
-
),
|
|
477
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
478
|
-
"button",
|
|
479
|
-
{
|
|
480
|
-
type: "button",
|
|
481
|
-
"data-testid": "review-reject-all",
|
|
482
|
-
onClick: () => review.resolveAll("reject"),
|
|
483
|
-
children: "Reject all"
|
|
743
|
+
first.key
|
|
744
|
+
);
|
|
745
|
+
}),
|
|
746
|
+
bubbleOpen && (draft || shown || top.length === 0) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
747
|
+
"div",
|
|
748
|
+
{
|
|
749
|
+
className: "native-docx-review-bubble",
|
|
750
|
+
"data-testid": "review-bubble",
|
|
751
|
+
role: "dialog",
|
|
752
|
+
"data-state": "open",
|
|
753
|
+
"aria-label": "Review",
|
|
754
|
+
style: {
|
|
755
|
+
top: draft ? draft.anchorY * scale : shown?.y ?? 0,
|
|
756
|
+
width: Math.max(220, Math.min(340, area.width - 56))
|
|
757
|
+
},
|
|
758
|
+
onKeyDown: (event) => {
|
|
759
|
+
if (event.key === "Escape") {
|
|
760
|
+
event.preventDefault();
|
|
761
|
+
event.stopPropagation();
|
|
762
|
+
dismiss();
|
|
484
763
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
489
|
-
"input",
|
|
764
|
+
},
|
|
765
|
+
children: draft ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
766
|
+
Draft,
|
|
490
767
|
{
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
768
|
+
onCancel: dismiss,
|
|
769
|
+
onSubmit: (text) => {
|
|
770
|
+
if (review.addComment(text)) setDraft(null);
|
|
771
|
+
}
|
|
495
772
|
}
|
|
496
|
-
),
|
|
497
|
-
|
|
498
|
-
|
|
773
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
774
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-bubble-head", children: [
|
|
775
|
+
top.length > 1 && position >= 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
776
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
777
|
+
"button",
|
|
778
|
+
{
|
|
779
|
+
type: "button",
|
|
780
|
+
className: "native-docx-review-icon",
|
|
781
|
+
"data-testid": "review-bubble-previous",
|
|
782
|
+
"aria-label": "Previous",
|
|
783
|
+
disabled: position === 0,
|
|
784
|
+
onClick: () => step(-1),
|
|
785
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { size: 14 })
|
|
786
|
+
}
|
|
787
|
+
),
|
|
788
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "native-docx-review-summary", children: [
|
|
789
|
+
position + 1,
|
|
790
|
+
" of ",
|
|
791
|
+
top.length
|
|
792
|
+
] }),
|
|
793
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
794
|
+
"button",
|
|
795
|
+
{
|
|
796
|
+
type: "button",
|
|
797
|
+
className: "native-docx-review-icon",
|
|
798
|
+
"data-testid": "review-bubble-next",
|
|
799
|
+
"aria-label": "Next",
|
|
800
|
+
disabled: position === top.length - 1,
|
|
801
|
+
onClick: () => step(1),
|
|
802
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 14 })
|
|
803
|
+
}
|
|
804
|
+
)
|
|
805
|
+
] }),
|
|
806
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
807
|
+
"button",
|
|
808
|
+
{
|
|
809
|
+
type: "button",
|
|
810
|
+
className: "native-docx-review-icon native-docx-review-close",
|
|
811
|
+
"data-testid": "review-bubble-close",
|
|
812
|
+
"aria-label": "Close",
|
|
813
|
+
onClick: dismiss,
|
|
814
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 })
|
|
815
|
+
}
|
|
816
|
+
)
|
|
817
|
+
] }),
|
|
818
|
+
shown?.entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
819
|
+
Card,
|
|
820
|
+
{
|
|
821
|
+
entry,
|
|
822
|
+
replies: repliesOf(entry),
|
|
823
|
+
review,
|
|
824
|
+
extra: children?.(entry),
|
|
825
|
+
onDismiss: dismiss
|
|
826
|
+
},
|
|
827
|
+
entry.key
|
|
828
|
+
)),
|
|
829
|
+
!shown && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "native-docx-review-empty", "data-testid": "review-empty", children: "No comments or changes." }),
|
|
830
|
+
changes > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-review-bubble-foot", children: /* @__PURE__ */ jsxRuntime.jsx(BulkActions, { review }) })
|
|
831
|
+
] })
|
|
832
|
+
}
|
|
833
|
+
)
|
|
834
|
+
] }) });
|
|
835
|
+
}
|
|
836
|
+
function BulkActions({ review, navigate }) {
|
|
837
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-review-bulk", children: [
|
|
838
|
+
navigate && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "native-docx-review-segment", children: [
|
|
839
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
840
|
+
"button",
|
|
841
|
+
{
|
|
842
|
+
type: "button",
|
|
843
|
+
className: "native-docx-review-icon",
|
|
844
|
+
"data-testid": "review-previous",
|
|
845
|
+
"aria-label": "Previous change",
|
|
846
|
+
title: "Previous change",
|
|
847
|
+
onClick: () => review.navigate("previous"),
|
|
848
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { size: 14 })
|
|
849
|
+
}
|
|
850
|
+
),
|
|
851
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
852
|
+
"button",
|
|
853
|
+
{
|
|
854
|
+
type: "button",
|
|
855
|
+
className: "native-docx-review-icon",
|
|
856
|
+
"data-testid": "review-next",
|
|
857
|
+
"aria-label": "Next change",
|
|
858
|
+
title: "Next change",
|
|
859
|
+
onClick: () => review.navigate("next"),
|
|
860
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 14 })
|
|
861
|
+
}
|
|
862
|
+
)
|
|
499
863
|
] }),
|
|
500
|
-
|
|
501
|
-
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
865
|
+
"button",
|
|
502
866
|
{
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
867
|
+
type: "button",
|
|
868
|
+
className: "native-docx-review-accept",
|
|
869
|
+
"data-testid": "review-accept-all",
|
|
870
|
+
onClick: () => review.resolveAll("accept"),
|
|
871
|
+
children: [
|
|
872
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { size: 14 }),
|
|
873
|
+
"Accept all"
|
|
874
|
+
]
|
|
511
875
|
}
|
|
512
876
|
),
|
|
513
|
-
|
|
514
|
-
|
|
877
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
878
|
+
"button",
|
|
515
879
|
{
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
review,
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
entry.key
|
|
527
|
-
)),
|
|
528
|
-
top.length === 0 && !draft && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "native-docx-review-empty", "data-testid": "review-empty", children: "No comments or changes." })
|
|
880
|
+
type: "button",
|
|
881
|
+
className: "native-docx-review-reject",
|
|
882
|
+
"data-testid": "review-reject-all",
|
|
883
|
+
onClick: () => review.resolveAll("reject"),
|
|
884
|
+
children: [
|
|
885
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }),
|
|
886
|
+
"Reject all"
|
|
887
|
+
]
|
|
888
|
+
}
|
|
889
|
+
)
|
|
529
890
|
] });
|
|
530
891
|
}
|
|
531
892
|
function ReviewCardSlot({ children }) {
|
|
@@ -607,14 +968,7 @@ function DocxCommentActivity() {
|
|
|
607
968
|
/* @__PURE__ */ jsxRuntime.jsx(ui.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.DialogTitle, { children: "Document comment" }) }),
|
|
608
969
|
thread.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-b pb-4 last:border-0", children: [
|
|
609
970
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: entry.author || "Reviewer" }),
|
|
610
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
611
|
-
"p",
|
|
612
|
-
{
|
|
613
|
-
className: "whitespace-pre-wrap break-words text-sm",
|
|
614
|
-
"data-testid": "docx-full-comment-text",
|
|
615
|
-
children: entry.text
|
|
616
|
-
}
|
|
617
|
-
)
|
|
971
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "docx-full-comment-text", children: /* @__PURE__ */ jsxRuntime.jsx(ui.AiMarkdown, { allowHtml: false, children: commentText(entry) }) })
|
|
618
972
|
] }, entry.key)),
|
|
619
973
|
statuses.map(([id, run]) => /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "text-sm", children: [
|
|
620
974
|
run.label,
|
|
@@ -1880,57 +2234,12 @@ var WordDraftStream = class {
|
|
|
1880
2234
|
}
|
|
1881
2235
|
}
|
|
1882
2236
|
};
|
|
1883
|
-
function contentPath(documentId) {
|
|
1884
|
-
const match = /^(doc-[A-Za-z0-9]+)@v([1-9][0-9]*)$/.exec(documentId);
|
|
1885
|
-
return match ? `/${encodeURIComponent(match[1])}/content?version=${match[2]}` : `/${encodeURIComponent(documentId)}/content`;
|
|
1886
|
-
}
|
|
1887
|
-
var drafts = /* @__PURE__ */ new Map();
|
|
1888
|
-
var stateBytes = (room) => Y__namespace.encodeStateAsUpdate(room.ydoc);
|
|
1889
|
-
var encodeState = (room) => {
|
|
1890
|
-
let binary = "";
|
|
1891
|
-
for (const byte of stateBytes(room)) binary += String.fromCharCode(byte);
|
|
1892
|
-
return btoa(binary);
|
|
1893
|
-
};
|
|
1894
|
-
function covered(room, vector, receipt) {
|
|
1895
|
-
const decode = (value) => Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
|
|
1896
|
-
const server = Y__namespace.decodeStateVector(decode(vector)), local = Y__namespace.decodeStateVector(Y__namespace.encodeStateVector(room.ydoc));
|
|
1897
|
-
for (const [client, clock] of local) if ((server.get(client) || 0) < clock) return false;
|
|
1898
|
-
const deleted = Y__namespace.decodeUpdate(stateBytes(room)).ds.clients;
|
|
1899
|
-
const saved = Y__namespace.decodeUpdate(decode(receipt)).ds.clients;
|
|
1900
|
-
for (const [client, ranges] of deleted)
|
|
1901
|
-
for (const range of ranges) {
|
|
1902
|
-
if (!(saved.get(client) || []).some(
|
|
1903
|
-
(s) => s.clock <= range.clock && s.clock + s.len >= range.clock + range.len
|
|
1904
|
-
))
|
|
1905
|
-
return false;
|
|
1906
|
-
}
|
|
1907
|
-
return true;
|
|
1908
|
-
}
|
|
1909
|
-
var EditorBoundary = class extends React3__default.default.Component {
|
|
1910
|
-
state = {};
|
|
1911
|
-
static getDerivedStateFromError(error) {
|
|
1912
|
-
return { error };
|
|
1913
|
-
}
|
|
1914
|
-
render() {
|
|
1915
|
-
return this.state.error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: "native-docx-error", children: [
|
|
1916
|
-
"Could not render this Word document: ",
|
|
1917
|
-
this.state.error.message
|
|
1918
|
-
] }) : this.props.children;
|
|
1919
|
-
}
|
|
1920
|
-
};
|
|
1921
|
-
function DocxParticipants({ session }) {
|
|
1922
|
-
const [people, setPeople] = React3.useState([]);
|
|
1923
|
-
React3.useEffect(() => {
|
|
1924
|
-
if (!session) return;
|
|
1925
|
-
setPeople(session.participants());
|
|
1926
|
-
return session.subscribeParticipants(setPeople);
|
|
1927
|
-
}, [session]);
|
|
1928
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-presence", "aria-label": "People viewing this document", children: people.map((p) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-avatar", title: p.name, children: p.name.split(" ").map((s) => s[0]).slice(0, 2).join("") }, p.actorId)) });
|
|
1929
|
-
}
|
|
1930
2237
|
function RibbonMenu({
|
|
1931
2238
|
label,
|
|
1932
2239
|
icon,
|
|
1933
|
-
children
|
|
2240
|
+
children,
|
|
2241
|
+
className,
|
|
2242
|
+
testId
|
|
1934
2243
|
}) {
|
|
1935
2244
|
const [open, setOpen] = React3.useState(false);
|
|
1936
2245
|
const element = React3.useRef(null);
|
|
@@ -1954,10 +2263,11 @@ function RibbonMenu({
|
|
|
1954
2263
|
"button",
|
|
1955
2264
|
{
|
|
1956
2265
|
type: "button",
|
|
1957
|
-
className: "native-docx-ribbon-trigger",
|
|
2266
|
+
className: ["native-docx-ribbon-trigger", className].filter(Boolean).join(" "),
|
|
1958
2267
|
"aria-label": label,
|
|
1959
2268
|
title: label,
|
|
1960
2269
|
"aria-expanded": open,
|
|
2270
|
+
"data-testid": testId,
|
|
1961
2271
|
onMouseDown: (event) => event.preventDefault(),
|
|
1962
2272
|
onClick: () => setOpen((value) => !value),
|
|
1963
2273
|
children: icon
|
|
@@ -1973,11 +2283,295 @@ function RibbonMenu({
|
|
|
1973
2283
|
if (!(event.target instanceof HTMLInputElement || event.target instanceof HTMLSelectElement))
|
|
1974
2284
|
event.preventDefault();
|
|
1975
2285
|
},
|
|
1976
|
-
children
|
|
2286
|
+
children: typeof children === "function" ? children(() => setOpen(false)) : children
|
|
2287
|
+
}
|
|
2288
|
+
)
|
|
2289
|
+
] });
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
// src/docx/wordStyles.ts
|
|
2293
|
+
var QUICK_STYLES = ["Normal", "Title", "heading 1", "heading 2", "heading 3"];
|
|
2294
|
+
function findStyle(options, name) {
|
|
2295
|
+
const wanted = name.toLowerCase();
|
|
2296
|
+
const id = name.replace(/(^|\s)(\w)/g, (_, _s, c) => c.toUpperCase());
|
|
2297
|
+
return options.find((o) => o.name.toLowerCase() === wanted) ?? options.find((o) => o.styleId.toLowerCase() === id.toLowerCase());
|
|
2298
|
+
}
|
|
2299
|
+
function styleLabel(name) {
|
|
2300
|
+
return name === name.toLowerCase() ? name.replace(/(^|\s)(\w)/g, (m) => m.toUpperCase()) : name;
|
|
2301
|
+
}
|
|
2302
|
+
function wordShortcut(event) {
|
|
2303
|
+
const mod = event.ctrlKey || event.metaKey;
|
|
2304
|
+
if (!mod) return null;
|
|
2305
|
+
if (event.altKey && !event.shiftKey) {
|
|
2306
|
+
switch (event.code) {
|
|
2307
|
+
case "KeyF":
|
|
2308
|
+
return "footnote";
|
|
2309
|
+
case "KeyD":
|
|
2310
|
+
return "endnote";
|
|
2311
|
+
case "Digit1":
|
|
2312
|
+
case "Numpad1":
|
|
2313
|
+
return "heading 1";
|
|
2314
|
+
case "Digit2":
|
|
2315
|
+
case "Numpad2":
|
|
2316
|
+
return "heading 2";
|
|
2317
|
+
case "Digit3":
|
|
2318
|
+
case "Numpad3":
|
|
2319
|
+
return "heading 3";
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
if (event.shiftKey && !event.altKey && event.code === "KeyN") return "Normal";
|
|
2323
|
+
return null;
|
|
2324
|
+
}
|
|
2325
|
+
var FILTER_FROM = 8;
|
|
2326
|
+
function previewStyle(option) {
|
|
2327
|
+
const { fontFamily, fontSizePt, bold, italic, color } = option.preview;
|
|
2328
|
+
return {
|
|
2329
|
+
fontFamily: fontFamily ? `"${fontFamily}", serif` : void 0,
|
|
2330
|
+
// In the face of the style, but within a row: 9-18pt.
|
|
2331
|
+
fontSize: fontSizePt ? `${Math.min(18, Math.max(9, fontSizePt))}pt` : void 0,
|
|
2332
|
+
fontWeight: bold ? 700 : void 0,
|
|
2333
|
+
fontStyle: italic ? "italic" : void 0,
|
|
2334
|
+
color: color ? `#${color}` : void 0
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
function Gallery({ close }) {
|
|
2338
|
+
const { value, setValue, options, isEnabled } = react.useParagraphStyle();
|
|
2339
|
+
const editor = react.useDocxEditor();
|
|
2340
|
+
const [query, setQuery] = React3.useState("");
|
|
2341
|
+
const quick = React3.useMemo(
|
|
2342
|
+
() => QUICK_STYLES.map((name) => findStyle(options, name)).filter(
|
|
2343
|
+
(o) => !!o
|
|
2344
|
+
),
|
|
2345
|
+
[options]
|
|
2346
|
+
);
|
|
2347
|
+
const shown = React3.useMemo(() => {
|
|
2348
|
+
const q = query.trim().toLowerCase();
|
|
2349
|
+
return q ? options.filter(
|
|
2350
|
+
(o) => o.name.toLowerCase().includes(q) || o.styleId.toLowerCase().includes(q)
|
|
2351
|
+
) : options;
|
|
2352
|
+
}, [options, query]);
|
|
2353
|
+
const apply = (option) => {
|
|
2354
|
+
setValue(option.styleId);
|
|
2355
|
+
close();
|
|
2356
|
+
editor?.surface?.focus();
|
|
2357
|
+
};
|
|
2358
|
+
const nav = chunk7UTB4PHM_cjs.useListKeyNav({
|
|
2359
|
+
open: true,
|
|
2360
|
+
items: shown,
|
|
2361
|
+
onPick: apply,
|
|
2362
|
+
onDismiss: close,
|
|
2363
|
+
resetKey: query
|
|
2364
|
+
});
|
|
2365
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-style-gallery", "data-testid": "docx-style-gallery", children: [
|
|
2366
|
+
quick.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-style-quick", role: "group", "aria-label": "Quick styles", children: quick.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2367
|
+
"button",
|
|
2368
|
+
{
|
|
2369
|
+
type: "button",
|
|
2370
|
+
"aria-pressed": value === option.styleId,
|
|
2371
|
+
disabled: !isEnabled,
|
|
2372
|
+
"data-style-id": option.styleId,
|
|
2373
|
+
title: styleLabel(option.name),
|
|
2374
|
+
onClick: () => apply(option),
|
|
2375
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: previewStyle(option), children: styleLabel(option.name) })
|
|
2376
|
+
},
|
|
2377
|
+
option.styleId
|
|
2378
|
+
)) }),
|
|
2379
|
+
options.length > FILTER_FROM && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2380
|
+
"input",
|
|
2381
|
+
{
|
|
2382
|
+
className: "native-docx-style-filter",
|
|
2383
|
+
placeholder: "Find a style",
|
|
2384
|
+
"aria-label": "Find a style",
|
|
2385
|
+
value: query,
|
|
2386
|
+
autoFocus: true,
|
|
2387
|
+
onChange: (event) => setQuery(event.target.value),
|
|
2388
|
+
onKeyDown: (event) => {
|
|
2389
|
+
nav.handleKeyDown(event);
|
|
2390
|
+
},
|
|
2391
|
+
...nav.comboboxProps
|
|
2392
|
+
}
|
|
2393
|
+
),
|
|
2394
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2395
|
+
"ul",
|
|
2396
|
+
{
|
|
2397
|
+
className: "native-docx-style-list",
|
|
2398
|
+
role: "listbox",
|
|
2399
|
+
id: nav.listboxId,
|
|
2400
|
+
"aria-label": "Document styles",
|
|
2401
|
+
children: [
|
|
2402
|
+
shown.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
|
+
"li",
|
|
2404
|
+
{
|
|
2405
|
+
id: chunk7UTB4PHM_cjs.listOptionId(nav.listboxId, index),
|
|
2406
|
+
role: "option",
|
|
2407
|
+
"aria-selected": value === option.styleId,
|
|
2408
|
+
"aria-disabled": !isEnabled,
|
|
2409
|
+
"data-active": index === nav.selectedIndex || void 0,
|
|
2410
|
+
"data-style-id": option.styleId,
|
|
2411
|
+
onMouseEnter: () => nav.setSelectedIndex(index),
|
|
2412
|
+
onClick: () => isEnabled && apply(option),
|
|
2413
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: previewStyle(option), children: styleLabel(option.name) })
|
|
2414
|
+
},
|
|
2415
|
+
option.styleId
|
|
2416
|
+
)),
|
|
2417
|
+
shown.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("li", { className: "native-docx-style-empty", children: "No matching style" })
|
|
2418
|
+
]
|
|
2419
|
+
}
|
|
2420
|
+
)
|
|
2421
|
+
] });
|
|
2422
|
+
}
|
|
2423
|
+
function StyleGallery() {
|
|
2424
|
+
const { value, options } = react.useParagraphStyle();
|
|
2425
|
+
const current = options.find((o) => o.styleId === value);
|
|
2426
|
+
const name = current ? styleLabel(current.name) : "Styles";
|
|
2427
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2428
|
+
RibbonMenu,
|
|
2429
|
+
{
|
|
2430
|
+
label: "Styles",
|
|
2431
|
+
className: "native-docx-style-trigger",
|
|
2432
|
+
testId: "docx-style-trigger",
|
|
2433
|
+
icon: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2434
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-style-current", "data-testid": "docx-current-style", children: name }),
|
|
2435
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 12, "aria-hidden": true })
|
|
2436
|
+
] }),
|
|
2437
|
+
children: (close) => /* @__PURE__ */ jsxRuntime.jsx(Gallery, { close })
|
|
2438
|
+
}
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
function useInsertNote(kind) {
|
|
2442
|
+
const command = react.useEditorCommand(kind === "footnote" ? "insert.footnote" : "insert.endnote");
|
|
2443
|
+
const { options } = react.useParagraphStyle();
|
|
2444
|
+
const editor = react.useDocxEditor();
|
|
2445
|
+
const insert = () => {
|
|
2446
|
+
if (!command.execute()) return false;
|
|
2447
|
+
const text = findStyle(options, `${kind} text`);
|
|
2448
|
+
if (text && editor)
|
|
2449
|
+
withDirectEditing(
|
|
2450
|
+
editor,
|
|
2451
|
+
() => editor.exec({ type: "setParagraphStyle", styleId: text.styleId })
|
|
2452
|
+
);
|
|
2453
|
+
return true;
|
|
2454
|
+
};
|
|
2455
|
+
return { insert, isEnabled: command.isEnabled, disabledReason: command.disabledReason };
|
|
2456
|
+
}
|
|
2457
|
+
function NoteAction({
|
|
2458
|
+
kind,
|
|
2459
|
+
label,
|
|
2460
|
+
shortcut,
|
|
2461
|
+
icon
|
|
2462
|
+
}) {
|
|
2463
|
+
const note = useInsertNote(kind);
|
|
2464
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2465
|
+
react.DocxEditor.Toolbar.Action,
|
|
2466
|
+
{
|
|
2467
|
+
label: `${label} (${shortcut})`,
|
|
2468
|
+
icon,
|
|
2469
|
+
disabled: !note.isEnabled,
|
|
2470
|
+
disabledReason: note.disabledReason ?? void 0,
|
|
2471
|
+
onSelect: () => void note.insert(),
|
|
2472
|
+
className: `native-docx-insert-${kind}`
|
|
2473
|
+
}
|
|
2474
|
+
);
|
|
2475
|
+
}
|
|
2476
|
+
function NoteButtons() {
|
|
2477
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2478
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2479
|
+
NoteAction,
|
|
2480
|
+
{
|
|
2481
|
+
kind: "footnote",
|
|
2482
|
+
label: "Insert footnote",
|
|
2483
|
+
shortcut: "Ctrl+Alt+F",
|
|
2484
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Superscript, { size: 16 })
|
|
2485
|
+
}
|
|
2486
|
+
),
|
|
2487
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2488
|
+
NoteAction,
|
|
2489
|
+
{
|
|
2490
|
+
kind: "endnote",
|
|
2491
|
+
label: "Insert endnote",
|
|
2492
|
+
shortcut: "Ctrl+Alt+D",
|
|
2493
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.NotebookText, { size: 16 })
|
|
1977
2494
|
}
|
|
1978
2495
|
)
|
|
1979
2496
|
] });
|
|
1980
2497
|
}
|
|
2498
|
+
function WordShortcuts({ scope }) {
|
|
2499
|
+
const footnote = useInsertNote("footnote");
|
|
2500
|
+
const endnote = useInsertNote("endnote");
|
|
2501
|
+
const styles = react.useParagraphStyle();
|
|
2502
|
+
const editor = react.useDocxEditor();
|
|
2503
|
+
const latest = React3.useRef({ footnote, endnote, styles, editor });
|
|
2504
|
+
latest.current = { footnote, endnote, styles, editor };
|
|
2505
|
+
React3.useEffect(() => {
|
|
2506
|
+
const element = scope.current;
|
|
2507
|
+
if (!element) return;
|
|
2508
|
+
const onKeyDown = (event) => {
|
|
2509
|
+
const action = wordShortcut(event);
|
|
2510
|
+
if (!action) return;
|
|
2511
|
+
const { footnote: footnote2, endnote: endnote2, styles: styles2, editor: editor2 } = latest.current;
|
|
2512
|
+
if (action === "footnote" || action === "endnote") {
|
|
2513
|
+
if (!(action === "footnote" ? footnote2 : endnote2).insert()) return;
|
|
2514
|
+
} else {
|
|
2515
|
+
const style = findStyle(styles2.options, action);
|
|
2516
|
+
if (!style) return;
|
|
2517
|
+
styles2.setValue(style.styleId);
|
|
2518
|
+
}
|
|
2519
|
+
event.preventDefault();
|
|
2520
|
+
event.stopPropagation();
|
|
2521
|
+
editor2?.surface?.focus();
|
|
2522
|
+
};
|
|
2523
|
+
element.addEventListener("keydown", onKeyDown, true);
|
|
2524
|
+
return () => element.removeEventListener("keydown", onKeyDown, true);
|
|
2525
|
+
}, [scope]);
|
|
2526
|
+
return null;
|
|
2527
|
+
}
|
|
2528
|
+
function contentPath(documentId) {
|
|
2529
|
+
const match = /^(doc-[A-Za-z0-9]+)@v([1-9][0-9]*)$/.exec(documentId);
|
|
2530
|
+
return match ? `/${encodeURIComponent(match[1])}/content?version=${match[2]}` : `/${encodeURIComponent(documentId)}/content`;
|
|
2531
|
+
}
|
|
2532
|
+
var drafts = /* @__PURE__ */ new Map();
|
|
2533
|
+
var stateBytes = (room) => Y__namespace.encodeStateAsUpdate(room.ydoc);
|
|
2534
|
+
var encodeState = (room) => {
|
|
2535
|
+
let binary = "";
|
|
2536
|
+
for (const byte of stateBytes(room)) binary += String.fromCharCode(byte);
|
|
2537
|
+
return btoa(binary);
|
|
2538
|
+
};
|
|
2539
|
+
function covered(room, vector, receipt) {
|
|
2540
|
+
const decode = (value) => Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
|
|
2541
|
+
const server = Y__namespace.decodeStateVector(decode(vector)), local = Y__namespace.decodeStateVector(Y__namespace.encodeStateVector(room.ydoc));
|
|
2542
|
+
for (const [client, clock] of local) if ((server.get(client) || 0) < clock) return false;
|
|
2543
|
+
const deleted = Y__namespace.decodeUpdate(stateBytes(room)).ds.clients;
|
|
2544
|
+
const saved = Y__namespace.decodeUpdate(decode(receipt)).ds.clients;
|
|
2545
|
+
for (const [client, ranges] of deleted)
|
|
2546
|
+
for (const range of ranges) {
|
|
2547
|
+
if (!(saved.get(client) || []).some(
|
|
2548
|
+
(s) => s.clock <= range.clock && s.clock + s.len >= range.clock + range.len
|
|
2549
|
+
))
|
|
2550
|
+
return false;
|
|
2551
|
+
}
|
|
2552
|
+
return true;
|
|
2553
|
+
}
|
|
2554
|
+
var EditorBoundary = class extends React3__default.default.Component {
|
|
2555
|
+
state = {};
|
|
2556
|
+
static getDerivedStateFromError(error) {
|
|
2557
|
+
return { error };
|
|
2558
|
+
}
|
|
2559
|
+
render() {
|
|
2560
|
+
return this.state.error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", className: "native-docx-error", children: [
|
|
2561
|
+
"Could not render this Word document: ",
|
|
2562
|
+
this.state.error.message
|
|
2563
|
+
] }) : this.props.children;
|
|
2564
|
+
}
|
|
2565
|
+
};
|
|
2566
|
+
function DocxParticipants({ session }) {
|
|
2567
|
+
const [people, setPeople] = React3.useState([]);
|
|
2568
|
+
React3.useEffect(() => {
|
|
2569
|
+
if (!session) return;
|
|
2570
|
+
setPeople(session.participants());
|
|
2571
|
+
return session.subscribeParticipants(setPeople);
|
|
2572
|
+
}, [session]);
|
|
2573
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "native-docx-presence", "aria-label": "People viewing this document", children: people.map((p) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-avatar", title: p.name, children: p.name.split(" ").map((s) => s[0]).slice(0, 2).join("") }, p.actorId)) });
|
|
2574
|
+
}
|
|
1981
2575
|
function DefinedTermButtons() {
|
|
1982
2576
|
const terms = useDefinedTerms();
|
|
1983
2577
|
if (!terms) return null;
|
|
@@ -2010,13 +2604,17 @@ function DefinedTermButtons() {
|
|
|
2010
2604
|
)
|
|
2011
2605
|
] });
|
|
2012
2606
|
}
|
|
2013
|
-
function DocxRibbon({
|
|
2607
|
+
function DocxRibbon({
|
|
2608
|
+
onSave,
|
|
2609
|
+
badge
|
|
2610
|
+
}) {
|
|
2014
2611
|
const [tab, setTab] = React3.useState("Home");
|
|
2015
2612
|
const t = react.useChromeTranslate();
|
|
2016
2613
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "native-docx-ribbon", children: [
|
|
2017
2614
|
/* @__PURE__ */ jsxRuntime.jsxs("select", { "aria-label": "Ribbon tab", value: tab, onChange: (event) => setTab(event.target.value), children: [
|
|
2018
2615
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Home" }),
|
|
2019
2616
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Insert" }),
|
|
2617
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "References" }),
|
|
2020
2618
|
/* @__PURE__ */ jsxRuntime.jsx("option", { children: "Review" })
|
|
2021
2619
|
] }),
|
|
2022
2620
|
/* @__PURE__ */ jsxRuntime.jsxs(react.DocxEditor.Toolbar, { t, preset: false, onSave, children: [
|
|
@@ -2024,6 +2622,7 @@ function DocxRibbon({ onSave }) {
|
|
|
2024
2622
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Redo, {}),
|
|
2025
2623
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Save, {}),
|
|
2026
2624
|
tab === "Home" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2625
|
+
/* @__PURE__ */ jsxRuntime.jsx(StyleGallery, {}),
|
|
2027
2626
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Bold, {}),
|
|
2028
2627
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Italic, {}),
|
|
2029
2628
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Underline, {}),
|
|
@@ -2034,7 +2633,6 @@ function DocxRibbon({ onSave }) {
|
|
|
2034
2633
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Highlight, {})
|
|
2035
2634
|
] }),
|
|
2036
2635
|
/* @__PURE__ */ jsxRuntime.jsxs(RibbonMenu, { label: "More formatting", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { size: 16 }), children: [
|
|
2037
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.StylePicker, {}),
|
|
2038
2636
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Alignment, {}),
|
|
2039
2637
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.BulletList, {}),
|
|
2040
2638
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.NumberedList, {}),
|
|
@@ -2051,12 +2649,14 @@ function DocxRibbon({ onSave }) {
|
|
|
2051
2649
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Link, {}),
|
|
2052
2650
|
/* @__PURE__ */ jsxRuntime.jsx(DefinedTermButtons, {})
|
|
2053
2651
|
] }),
|
|
2652
|
+
tab === "References" && /* @__PURE__ */ jsxRuntime.jsx(NoteButtons, {}),
|
|
2054
2653
|
tab === "Review" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2055
2654
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.EditingMode, {}),
|
|
2056
2655
|
/* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Comments, {}),
|
|
2057
2656
|
/* @__PURE__ */ jsxRuntime.jsx(RibbonMenu, { label: "Review options", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, { size: 16 }), children: /* @__PURE__ */ jsxRuntime.jsx(react.DocxEditor.Toolbar.Reviewers, {}) })
|
|
2058
2657
|
] })
|
|
2059
|
-
] })
|
|
2658
|
+
] }),
|
|
2659
|
+
badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "native-docx-ribbon-badge", "data-testid": "docx-ribbon-badge", children: badge })
|
|
2060
2660
|
] });
|
|
2061
2661
|
}
|
|
2062
2662
|
var fixedZoomMode = { type: "fixed" };
|
|
@@ -2321,7 +2921,10 @@ function NativeDocxEditor({
|
|
|
2321
2921
|
const resize = new ResizeObserver(fit);
|
|
2322
2922
|
const chrome = new MutationObserver(fit);
|
|
2323
2923
|
resize.observe(viewport);
|
|
2324
|
-
chrome.observe(viewport, {
|
|
2924
|
+
chrome.observe(viewport, {
|
|
2925
|
+
attributes: true,
|
|
2926
|
+
attributeFilter: ["style", "data-review-pane", "data-review-margin"]
|
|
2927
|
+
});
|
|
2325
2928
|
fit();
|
|
2326
2929
|
fitCleanup.current = () => {
|
|
2327
2930
|
resize.disconnect();
|
|
@@ -2403,7 +3006,17 @@ function NativeDocxEditor({
|
|
|
2403
3006
|
trackMoves: true
|
|
2404
3007
|
}
|
|
2405
3008
|
),
|
|
2406
|
-
!stream && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3009
|
+
!stream && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3010
|
+
DocxRibbon,
|
|
3011
|
+
{
|
|
3012
|
+
onSave: () => void saveVersion(),
|
|
3013
|
+
badge: (
|
|
3014
|
+
// Says the document is shared live, in place of a title row above the ribbon.
|
|
3015
|
+
ready.room && ready.canEdit && !snapshot ? /* @__PURE__ */ jsxRuntime.jsx("span", { title: "Edits sync live with everyone who has this document open", children: "Co-edit mode" }) : void 0
|
|
3016
|
+
)
|
|
3017
|
+
}
|
|
3018
|
+
),
|
|
3019
|
+
!stream && /* @__PURE__ */ jsxRuntime.jsx(WordShortcuts, { scope: stageRef }),
|
|
2407
3020
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2408
3021
|
"div",
|
|
2409
3022
|
{
|
|
@@ -2554,5 +3167,5 @@ exports.useDefinedTerms = useDefinedTerms;
|
|
|
2554
3167
|
exports.useReview = useReview;
|
|
2555
3168
|
exports.useReviewItem = useReviewItem;
|
|
2556
3169
|
exports.withDirectEditing = withDirectEditing;
|
|
2557
|
-
//# sourceMappingURL=chunk-
|
|
2558
|
-
//# sourceMappingURL=chunk-
|
|
3170
|
+
//# sourceMappingURL=chunk-HGJGALLN.cjs.map
|
|
3171
|
+
//# sourceMappingURL=chunk-HGJGALLN.cjs.map
|