@sofereditor/react 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1563 -489
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -6
- package/dist/index.d.ts +82 -6
- package/dist/index.js +1513 -420
- package/dist/index.js.map +1 -1
- package/package.json +30 -17
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
LinkDialog: () => LinkDialog,
|
|
28
28
|
NodeView: () => NodeView,
|
|
29
29
|
PageConfigDialog: () => PageConfigDialog,
|
|
30
|
+
RemoteCursorsOverlay: () => RemoteCursorsOverlay,
|
|
30
31
|
Toolbar: () => Toolbar,
|
|
31
32
|
applyDomSelection: () => applyDomSelection,
|
|
32
33
|
contentHeight: () => contentHeight,
|
|
@@ -38,6 +39,7 @@ __export(index_exports, {
|
|
|
38
39
|
getCellElement: () => getCellElement,
|
|
39
40
|
getFragmentForOffset: () => getFragmentForOffset,
|
|
40
41
|
isTableRectSelection: () => isTableRectSelection,
|
|
42
|
+
locatePoint: () => locatePoint,
|
|
41
43
|
readDomSelection: () => readDomSelection,
|
|
42
44
|
renderInline: () => renderInline,
|
|
43
45
|
selectionsEqual: () => selectionsEqual,
|
|
@@ -51,8 +53,8 @@ __export(index_exports, {
|
|
|
51
53
|
module.exports = __toCommonJS(index_exports);
|
|
52
54
|
|
|
53
55
|
// src/Editor.tsx
|
|
54
|
-
var
|
|
55
|
-
var
|
|
56
|
+
var import_react14 = require("react");
|
|
57
|
+
var import_core6 = require("@sofereditor/core");
|
|
56
58
|
|
|
57
59
|
// src/dom-bridge.ts
|
|
58
60
|
function findContainingBlockElement(node, root) {
|
|
@@ -252,6 +254,7 @@ function locatePoint(root, pos) {
|
|
|
252
254
|
let remaining = Math.max(0, pos.offset - containerStart);
|
|
253
255
|
let result = null;
|
|
254
256
|
let lastImg = null;
|
|
257
|
+
let lastText = null;
|
|
255
258
|
function visit(n) {
|
|
256
259
|
if (result) return;
|
|
257
260
|
if (n.nodeType === Node.TEXT_NODE) {
|
|
@@ -262,6 +265,7 @@ function locatePoint(root, pos) {
|
|
|
262
265
|
}
|
|
263
266
|
remaining -= len;
|
|
264
267
|
lastImg = null;
|
|
268
|
+
lastText = n;
|
|
265
269
|
return;
|
|
266
270
|
}
|
|
267
271
|
if (n.nodeType !== Node.ELEMENT_NODE) return;
|
|
@@ -291,6 +295,10 @@ function locatePoint(root, pos) {
|
|
|
291
295
|
const parent = lastImg.parentNode;
|
|
292
296
|
if (parent) return { node: parent, offset: indexInParent(lastImg) + 1 };
|
|
293
297
|
}
|
|
298
|
+
if (lastText) {
|
|
299
|
+
const t = lastText;
|
|
300
|
+
return { node: t, offset: (t.textContent ?? "").length };
|
|
301
|
+
}
|
|
294
302
|
return { node: container, offset: 0 };
|
|
295
303
|
}
|
|
296
304
|
function selectionsEqual(a, b) {
|
|
@@ -311,6 +319,9 @@ function applyDomSelection(root, modelSel) {
|
|
|
311
319
|
const anchorPt = locatePoint(root, modelSel.anchor);
|
|
312
320
|
const focusPt = locatePoint(root, modelSel.focus);
|
|
313
321
|
if (!anchorPt || !focusPt) return;
|
|
322
|
+
if (domSel.anchorNode === anchorPt.node && domSel.anchorOffset === anchorPt.offset && domSel.focusNode === focusPt.node && domSel.focusOffset === focusPt.offset) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
314
325
|
try {
|
|
315
326
|
domSel.removeAllRanges();
|
|
316
327
|
domSel.setBaseAndExtent(anchorPt.node, anchorPt.offset, focusPt.node, focusPt.offset);
|
|
@@ -318,18 +329,253 @@ function applyDomSelection(root, modelSel) {
|
|
|
318
329
|
}
|
|
319
330
|
}
|
|
320
331
|
|
|
332
|
+
// src/BehindImageSelectAffordance.tsx
|
|
333
|
+
var import_react = require("react");
|
|
334
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
335
|
+
var ACCENT = "#3b82f6";
|
|
336
|
+
function BehindImageSelectAffordance({
|
|
337
|
+
blockIndex,
|
|
338
|
+
offset,
|
|
339
|
+
cellIndex,
|
|
340
|
+
rootRef,
|
|
341
|
+
onSelect
|
|
342
|
+
}) {
|
|
343
|
+
const [rect, setRect] = (0, import_react.useState)(null);
|
|
344
|
+
const locateImage = (0, import_react.useCallback)(() => {
|
|
345
|
+
const root = rootRef.current;
|
|
346
|
+
if (!root) return null;
|
|
347
|
+
let container = null;
|
|
348
|
+
if (cellIndex != null) {
|
|
349
|
+
container = root.querySelector(
|
|
350
|
+
`[data-block-index="${blockIndex}"] [data-cell-index="${cellIndex}"]`
|
|
351
|
+
);
|
|
352
|
+
} else {
|
|
353
|
+
container = getFragmentForOffset(root, blockIndex, offset);
|
|
354
|
+
}
|
|
355
|
+
if (!container) return null;
|
|
356
|
+
const fragmentStart = container.dataset.fragmentStart ? Number.parseInt(container.dataset.fragmentStart, 10) || 0 : 0;
|
|
357
|
+
const localOffset = offset - fragmentStart;
|
|
358
|
+
return container.querySelector(
|
|
359
|
+
`img[data-embed="image"][data-embed-offset="${localOffset}"]`
|
|
360
|
+
);
|
|
361
|
+
}, [rootRef, blockIndex, offset, cellIndex]);
|
|
362
|
+
const measure = (0, import_react.useCallback)(() => {
|
|
363
|
+
const img = locateImage();
|
|
364
|
+
const root = rootRef.current;
|
|
365
|
+
if (!img || !root) {
|
|
366
|
+
setRect((prev) => prev === null ? prev : null);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const r = img.getBoundingClientRect();
|
|
370
|
+
const rr = root.getBoundingClientRect();
|
|
371
|
+
const next = {
|
|
372
|
+
top: r.top - rr.top + root.scrollTop,
|
|
373
|
+
left: r.left - rr.left + root.scrollLeft,
|
|
374
|
+
width: r.width,
|
|
375
|
+
height: r.height
|
|
376
|
+
};
|
|
377
|
+
setRect(
|
|
378
|
+
(prev) => prev && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
379
|
+
);
|
|
380
|
+
}, [locateImage, rootRef]);
|
|
381
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
382
|
+
measure();
|
|
383
|
+
let cancelled = false;
|
|
384
|
+
const remeasure = () => {
|
|
385
|
+
if (!cancelled) measure();
|
|
386
|
+
};
|
|
387
|
+
const id = typeof requestAnimationFrame === "function" ? requestAnimationFrame(remeasure) : (queueMicrotask(remeasure), 0);
|
|
388
|
+
return () => {
|
|
389
|
+
cancelled = true;
|
|
390
|
+
if (typeof cancelAnimationFrame === "function" && typeof id === "number" && id > 0) {
|
|
391
|
+
cancelAnimationFrame(id);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}, [measure]);
|
|
395
|
+
(0, import_react.useEffect)(() => {
|
|
396
|
+
const root = rootRef.current;
|
|
397
|
+
if (!root) return;
|
|
398
|
+
const onScroll = () => measure();
|
|
399
|
+
window.addEventListener("resize", onScroll);
|
|
400
|
+
root.addEventListener("scroll", onScroll);
|
|
401
|
+
return () => {
|
|
402
|
+
window.removeEventListener("resize", onScroll);
|
|
403
|
+
root.removeEventListener("scroll", onScroll);
|
|
404
|
+
};
|
|
405
|
+
}, [measure, rootRef]);
|
|
406
|
+
if (!rect) return null;
|
|
407
|
+
const outlineStyle = {
|
|
408
|
+
position: "absolute",
|
|
409
|
+
top: rect.top,
|
|
410
|
+
left: rect.left,
|
|
411
|
+
width: rect.width,
|
|
412
|
+
height: rect.height,
|
|
413
|
+
border: `1.5px dashed ${ACCENT}`,
|
|
414
|
+
borderRadius: 2,
|
|
415
|
+
boxSizing: "border-box",
|
|
416
|
+
pointerEvents: "none",
|
|
417
|
+
zIndex: 4
|
|
418
|
+
};
|
|
419
|
+
const badgeStyle = {
|
|
420
|
+
position: "absolute",
|
|
421
|
+
top: rect.top - 2,
|
|
422
|
+
left: rect.left - 2,
|
|
423
|
+
width: 24,
|
|
424
|
+
height: 24,
|
|
425
|
+
display: "flex",
|
|
426
|
+
alignItems: "center",
|
|
427
|
+
justifyContent: "center",
|
|
428
|
+
background: ACCENT,
|
|
429
|
+
color: "#fff",
|
|
430
|
+
borderRadius: 4,
|
|
431
|
+
cursor: "pointer",
|
|
432
|
+
pointerEvents: "auto",
|
|
433
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.3)",
|
|
434
|
+
zIndex: 5
|
|
435
|
+
};
|
|
436
|
+
const onBadgeDown = (e) => {
|
|
437
|
+
if (e.button !== 0) return;
|
|
438
|
+
e.preventDefault();
|
|
439
|
+
e.stopPropagation();
|
|
440
|
+
onSelect();
|
|
441
|
+
};
|
|
442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: outlineStyle, contentEditable: false, "aria-hidden": true }),
|
|
444
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
445
|
+
"div",
|
|
446
|
+
{
|
|
447
|
+
style: badgeStyle,
|
|
448
|
+
contentEditable: false,
|
|
449
|
+
onPointerDown: onBadgeDown,
|
|
450
|
+
role: "button",
|
|
451
|
+
"aria-label": "Selecionar imagem",
|
|
452
|
+
title: "Selecionar imagem",
|
|
453
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
454
|
+
"svg",
|
|
455
|
+
{
|
|
456
|
+
width: "14",
|
|
457
|
+
height: "14",
|
|
458
|
+
viewBox: "0 0 24 24",
|
|
459
|
+
fill: "none",
|
|
460
|
+
stroke: "currentColor",
|
|
461
|
+
strokeWidth: "2",
|
|
462
|
+
strokeLinecap: "round",
|
|
463
|
+
strokeLinejoin: "round",
|
|
464
|
+
"aria-hidden": true,
|
|
465
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 9l-3 3 3 3M9 5l3-3 3 3M15 19l-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20" })
|
|
466
|
+
}
|
|
467
|
+
)
|
|
468
|
+
}
|
|
469
|
+
)
|
|
470
|
+
] });
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/LinkHoverTooltip.tsx
|
|
474
|
+
var import_react_dom = require("react-dom");
|
|
475
|
+
|
|
476
|
+
// src/platform.ts
|
|
477
|
+
var IS_MAC = (() => {
|
|
478
|
+
if (typeof navigator === "undefined") return false;
|
|
479
|
+
const platform = navigator.userAgentData?.platform || navigator.platform || navigator.userAgent || "";
|
|
480
|
+
return /mac|iphone|ipad|ipod/i.test(platform);
|
|
481
|
+
})();
|
|
482
|
+
var MOD_SYMBOL = IS_MAC ? "\u2318" : "\u2303";
|
|
483
|
+
function hasOpenModifier(e) {
|
|
484
|
+
return IS_MAC ? e.metaKey : e.ctrlKey;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/LinkHoverTooltip.tsx
|
|
488
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
489
|
+
var MAX_WIDTH = 360;
|
|
490
|
+
var GAP = 6;
|
|
491
|
+
function LinkHoverTooltip({ href, rect }) {
|
|
492
|
+
const above = rect.top > 48;
|
|
493
|
+
const viewportW = typeof window !== "undefined" ? window.innerWidth : MAX_WIDTH + 16;
|
|
494
|
+
const left = Math.max(8, Math.min(rect.left, viewportW - MAX_WIDTH - 8));
|
|
495
|
+
const style = {
|
|
496
|
+
position: "fixed",
|
|
497
|
+
left,
|
|
498
|
+
top: above ? rect.top - GAP : rect.bottom + GAP,
|
|
499
|
+
transform: above ? "translateY(-100%)" : void 0,
|
|
500
|
+
maxWidth: MAX_WIDTH,
|
|
501
|
+
background: "#1f2937",
|
|
502
|
+
color: "#fff",
|
|
503
|
+
fontSize: 12,
|
|
504
|
+
lineHeight: 1.4,
|
|
505
|
+
padding: "6px 9px",
|
|
506
|
+
borderRadius: 6,
|
|
507
|
+
boxShadow: "0 4px 14px rgba(0,0,0,0.28)",
|
|
508
|
+
zIndex: 60,
|
|
509
|
+
pointerEvents: "none"
|
|
510
|
+
};
|
|
511
|
+
const urlStyle = {
|
|
512
|
+
display: "block",
|
|
513
|
+
maxWidth: MAX_WIDTH - 18,
|
|
514
|
+
overflow: "hidden",
|
|
515
|
+
textOverflow: "ellipsis",
|
|
516
|
+
whiteSpace: "nowrap",
|
|
517
|
+
fontWeight: 600
|
|
518
|
+
};
|
|
519
|
+
const hintStyle = {
|
|
520
|
+
display: "flex",
|
|
521
|
+
alignItems: "center",
|
|
522
|
+
gap: 4,
|
|
523
|
+
marginTop: 3,
|
|
524
|
+
fontSize: 11,
|
|
525
|
+
opacity: 0.85
|
|
526
|
+
};
|
|
527
|
+
const keycapStyle = {
|
|
528
|
+
display: "inline-flex",
|
|
529
|
+
alignItems: "center",
|
|
530
|
+
justifyContent: "center",
|
|
531
|
+
minWidth: 16,
|
|
532
|
+
height: 16,
|
|
533
|
+
padding: "0 4px",
|
|
534
|
+
fontSize: 11,
|
|
535
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
536
|
+
background: "rgba(255,255,255,0.16)",
|
|
537
|
+
border: "1px solid rgba(255,255,255,0.4)",
|
|
538
|
+
borderRadius: 4,
|
|
539
|
+
boxShadow: "inset 0 -1px 0 rgba(0,0,0,0.25)"
|
|
540
|
+
};
|
|
541
|
+
if (typeof document === "undefined") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
|
|
542
|
+
return (0, import_react_dom.createPortal)(
|
|
543
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style, contentEditable: false, "aria-hidden": true, role: "tooltip", children: [
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: urlStyle, children: href }),
|
|
545
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: hintStyle, children: [
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("kbd", { style: keycapStyle, children: MOD_SYMBOL }),
|
|
547
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { opacity: 0.8 }, children: "+ clique para abrir" })
|
|
548
|
+
] })
|
|
549
|
+
] }),
|
|
550
|
+
document.body
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
321
554
|
// src/EditorContext.tsx
|
|
322
|
-
var
|
|
555
|
+
var import_react5 = require("react");
|
|
323
556
|
|
|
324
557
|
// src/LinkDialog.tsx
|
|
325
|
-
var
|
|
326
|
-
|
|
558
|
+
var import_react2 = require("react");
|
|
559
|
+
|
|
560
|
+
// src/dialogCenterStyle.ts
|
|
561
|
+
var DIALOG_CENTER_STYLE = {
|
|
562
|
+
position: "fixed",
|
|
563
|
+
top: "50%",
|
|
564
|
+
left: "50%",
|
|
565
|
+
transform: "translate(-50%, -50%)",
|
|
566
|
+
margin: 0,
|
|
567
|
+
maxHeight: "90vh",
|
|
568
|
+
overflow: "auto"
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// src/LinkDialog.tsx
|
|
572
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
327
573
|
function LinkDialog() {
|
|
328
574
|
const { linkRequest, resolveLinkRequest } = useEditorContext();
|
|
329
|
-
const dialogRef = (0,
|
|
330
|
-
const inputRef = (0,
|
|
331
|
-
const [href, setHref] = (0,
|
|
332
|
-
(0,
|
|
575
|
+
const dialogRef = (0, import_react2.useRef)(null);
|
|
576
|
+
const inputRef = (0, import_react2.useRef)(null);
|
|
577
|
+
const [href, setHref] = (0, import_react2.useState)("");
|
|
578
|
+
(0, import_react2.useEffect)(() => {
|
|
333
579
|
const dialog = dialogRef.current;
|
|
334
580
|
if (!dialog) return;
|
|
335
581
|
if (linkRequest) {
|
|
@@ -357,20 +603,21 @@ function LinkDialog() {
|
|
|
357
603
|
const onCancel = () => {
|
|
358
604
|
resolveLinkRequest(null);
|
|
359
605
|
};
|
|
360
|
-
return /* @__PURE__ */ (0,
|
|
606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
361
607
|
"dialog",
|
|
362
608
|
{
|
|
363
609
|
ref: dialogRef,
|
|
364
610
|
className: "ed-link-dialog",
|
|
611
|
+
style: DIALOG_CENTER_STYLE,
|
|
365
612
|
onClose: onCancel,
|
|
366
613
|
onCancel: (e) => {
|
|
367
614
|
e.preventDefault();
|
|
368
615
|
onCancel();
|
|
369
616
|
},
|
|
370
|
-
children: /* @__PURE__ */ (0,
|
|
371
|
-
/* @__PURE__ */ (0,
|
|
372
|
-
/* @__PURE__ */ (0,
|
|
373
|
-
/* @__PURE__ */ (0,
|
|
617
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { onSubmit, className: "ed-link-dialog-form", children: [
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "ed-link-dialog-row", children: [
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { htmlFor: "ed-link-href", children: "URL" }),
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
374
621
|
"input",
|
|
375
622
|
{
|
|
376
623
|
id: "ed-link-href",
|
|
@@ -384,11 +631,11 @@ function LinkDialog() {
|
|
|
384
631
|
}
|
|
385
632
|
)
|
|
386
633
|
] }),
|
|
387
|
-
/* @__PURE__ */ (0,
|
|
388
|
-
linkRequest.initialHref ? /* @__PURE__ */ (0,
|
|
389
|
-
/* @__PURE__ */ (0,
|
|
390
|
-
/* @__PURE__ */ (0,
|
|
391
|
-
/* @__PURE__ */ (0,
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "ed-link-dialog-actions", children: [
|
|
635
|
+
linkRequest.initialHref ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: onRemove, className: "ed-link-dialog-remove", children: "Remover link" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", {}),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "ed-link-dialog-confirm", children: [
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", onClick: onCancel, children: "Cancelar" }),
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "ed-link-dialog-apply", children: "Aplicar" })
|
|
392
639
|
] })
|
|
393
640
|
] })
|
|
394
641
|
] })
|
|
@@ -397,21 +644,21 @@ function LinkDialog() {
|
|
|
397
644
|
}
|
|
398
645
|
|
|
399
646
|
// src/PageConfigDialog.tsx
|
|
400
|
-
var
|
|
647
|
+
var import_react3 = require("react");
|
|
401
648
|
var import_core = require("@sofereditor/core");
|
|
402
|
-
var
|
|
649
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
403
650
|
function PageConfigDialog() {
|
|
404
651
|
const { pageConfigRequest, resolvePageConfigRequest, setPageSettings } = useEditorContext();
|
|
405
|
-
const dialogRef = (0,
|
|
406
|
-
const [sizePreset, setSizePreset] = (0,
|
|
407
|
-
const [widthMm, setWidthMm] = (0,
|
|
408
|
-
const [heightMm, setHeightMm] = (0,
|
|
409
|
-
const [marginPreset, setMarginPreset] = (0,
|
|
410
|
-
const [marginTopMm, setMarginTopMm] = (0,
|
|
411
|
-
const [marginBottomMm, setMarginBottomMm] = (0,
|
|
412
|
-
const [marginLeftMm, setMarginLeftMm] = (0,
|
|
413
|
-
const [marginRightMm, setMarginRightMm] = (0,
|
|
414
|
-
(0,
|
|
652
|
+
const dialogRef = (0, import_react3.useRef)(null);
|
|
653
|
+
const [sizePreset, setSizePreset] = (0, import_react3.useState)("a4");
|
|
654
|
+
const [widthMm, setWidthMm] = (0, import_react3.useState)(210);
|
|
655
|
+
const [heightMm, setHeightMm] = (0, import_react3.useState)(297);
|
|
656
|
+
const [marginPreset, setMarginPreset] = (0, import_react3.useState)("normal");
|
|
657
|
+
const [marginTopMm, setMarginTopMm] = (0, import_react3.useState)(25.4);
|
|
658
|
+
const [marginBottomMm, setMarginBottomMm] = (0, import_react3.useState)(25.4);
|
|
659
|
+
const [marginLeftMm, setMarginLeftMm] = (0, import_react3.useState)(25.4);
|
|
660
|
+
const [marginRightMm, setMarginRightMm] = (0, import_react3.useState)(25.4);
|
|
661
|
+
(0, import_react3.useEffect)(() => {
|
|
415
662
|
const dialog = dialogRef.current;
|
|
416
663
|
if (!dialog) return;
|
|
417
664
|
if (pageConfigRequest) {
|
|
@@ -430,13 +677,13 @@ function PageConfigDialog() {
|
|
|
430
677
|
dialog.close();
|
|
431
678
|
}
|
|
432
679
|
}, [pageConfigRequest]);
|
|
433
|
-
(0,
|
|
680
|
+
(0, import_react3.useEffect)(() => {
|
|
434
681
|
if (sizePreset === "custom") return;
|
|
435
682
|
const p = import_core.PAGE_PRESETS[sizePreset];
|
|
436
683
|
setWidthMm(roundMm((0, import_core.pxToMm)(p.width)));
|
|
437
684
|
setHeightMm(roundMm((0, import_core.pxToMm)(p.height)));
|
|
438
685
|
}, [sizePreset]);
|
|
439
|
-
(0,
|
|
686
|
+
(0, import_react3.useEffect)(() => {
|
|
440
687
|
if (marginPreset === "custom") return;
|
|
441
688
|
const px = import_core.MARGIN_PRESETS[marginPreset];
|
|
442
689
|
const mm = roundMm((0, import_core.pxToMm)(px));
|
|
@@ -446,7 +693,7 @@ function PageConfigDialog() {
|
|
|
446
693
|
setMarginRightMm(mm);
|
|
447
694
|
}, [marginPreset]);
|
|
448
695
|
const customWidth = sizePreset === "custom";
|
|
449
|
-
const previewPx = (0,
|
|
696
|
+
const previewPx = (0, import_react3.useMemo)(
|
|
450
697
|
() => ({
|
|
451
698
|
width: Math.round((0, import_core.mmToPx)(widthMm)),
|
|
452
699
|
height: Math.round((0, import_core.mmToPx)(heightMm))
|
|
@@ -468,23 +715,24 @@ function PageConfigDialog() {
|
|
|
468
715
|
resolvePageConfigRequest(true);
|
|
469
716
|
};
|
|
470
717
|
const onCancel = () => resolvePageConfigRequest(false);
|
|
471
|
-
return /* @__PURE__ */ (0,
|
|
718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
472
719
|
"dialog",
|
|
473
720
|
{
|
|
474
721
|
ref: dialogRef,
|
|
475
722
|
className: "ed-page-config-dialog",
|
|
723
|
+
style: DIALOG_CENTER_STYLE,
|
|
476
724
|
onClose: onCancel,
|
|
477
725
|
onCancel: (e) => {
|
|
478
726
|
e.preventDefault();
|
|
479
727
|
onCancel();
|
|
480
728
|
},
|
|
481
|
-
children: /* @__PURE__ */ (0,
|
|
482
|
-
/* @__PURE__ */ (0,
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
484
|
-
/* @__PURE__ */ (0,
|
|
485
|
-
/* @__PURE__ */ (0,
|
|
486
|
-
/* @__PURE__ */ (0,
|
|
487
|
-
/* @__PURE__ */ (0,
|
|
729
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("form", { onSubmit: onApply, className: "ed-page-config-form", children: [
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { children: "Configurar p\xE1gina" }),
|
|
731
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("fieldset", { children: [
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("legend", { children: "Tamanho" }),
|
|
733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ed-page-config-row", children: [
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
735
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
488
736
|
"input",
|
|
489
737
|
{
|
|
490
738
|
type: "radio",
|
|
@@ -496,8 +744,8 @@ function PageConfigDialog() {
|
|
|
496
744
|
" ",
|
|
497
745
|
"A4 (210 \xD7 297 mm)"
|
|
498
746
|
] }),
|
|
499
|
-
/* @__PURE__ */ (0,
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
747
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
748
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
501
749
|
"input",
|
|
502
750
|
{
|
|
503
751
|
type: "radio",
|
|
@@ -509,8 +757,8 @@ function PageConfigDialog() {
|
|
|
509
757
|
" ",
|
|
510
758
|
"Carta (216 \xD7 279 mm)"
|
|
511
759
|
] }),
|
|
512
|
-
/* @__PURE__ */ (0,
|
|
513
|
-
/* @__PURE__ */ (0,
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
761
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
514
762
|
"input",
|
|
515
763
|
{
|
|
516
764
|
type: "radio",
|
|
@@ -522,8 +770,8 @@ function PageConfigDialog() {
|
|
|
522
770
|
" ",
|
|
523
771
|
"Of\xEDcio (216 \xD7 330 mm)"
|
|
524
772
|
] }),
|
|
525
|
-
/* @__PURE__ */ (0,
|
|
526
|
-
/* @__PURE__ */ (0,
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
527
775
|
"input",
|
|
528
776
|
{
|
|
529
777
|
type: "radio",
|
|
@@ -536,11 +784,11 @@ function PageConfigDialog() {
|
|
|
536
784
|
"Personalizado"
|
|
537
785
|
] })
|
|
538
786
|
] }),
|
|
539
|
-
/* @__PURE__ */ (0,
|
|
540
|
-
/* @__PURE__ */ (0,
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ed-page-config-row", children: [
|
|
788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
541
789
|
"Largura (mm)",
|
|
542
790
|
" ",
|
|
543
|
-
/* @__PURE__ */ (0,
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
544
792
|
"input",
|
|
545
793
|
{
|
|
546
794
|
type: "number",
|
|
@@ -553,10 +801,10 @@ function PageConfigDialog() {
|
|
|
553
801
|
}
|
|
554
802
|
)
|
|
555
803
|
] }),
|
|
556
|
-
/* @__PURE__ */ (0,
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
557
805
|
"Altura (mm)",
|
|
558
806
|
" ",
|
|
559
|
-
/* @__PURE__ */ (0,
|
|
807
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
560
808
|
"input",
|
|
561
809
|
{
|
|
562
810
|
type: "number",
|
|
@@ -569,7 +817,7 @@ function PageConfigDialog() {
|
|
|
569
817
|
}
|
|
570
818
|
)
|
|
571
819
|
] }),
|
|
572
|
-
/* @__PURE__ */ (0,
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "ed-page-config-preview", children: [
|
|
573
821
|
previewPx.width,
|
|
574
822
|
" \xD7 ",
|
|
575
823
|
previewPx.height,
|
|
@@ -577,11 +825,11 @@ function PageConfigDialog() {
|
|
|
577
825
|
] })
|
|
578
826
|
] })
|
|
579
827
|
] }),
|
|
580
|
-
/* @__PURE__ */ (0,
|
|
581
|
-
/* @__PURE__ */ (0,
|
|
582
|
-
/* @__PURE__ */ (0,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
584
|
-
/* @__PURE__ */ (0,
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("fieldset", { children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("legend", { children: "Margens" }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ed-page-config-row", children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
585
833
|
"input",
|
|
586
834
|
{
|
|
587
835
|
type: "radio",
|
|
@@ -593,8 +841,8 @@ function PageConfigDialog() {
|
|
|
593
841
|
" ",
|
|
594
842
|
"Normal (25,4 mm)"
|
|
595
843
|
] }),
|
|
596
|
-
/* @__PURE__ */ (0,
|
|
597
|
-
/* @__PURE__ */ (0,
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
598
846
|
"input",
|
|
599
847
|
{
|
|
600
848
|
type: "radio",
|
|
@@ -606,8 +854,8 @@ function PageConfigDialog() {
|
|
|
606
854
|
" ",
|
|
607
855
|
"Estreita (12,7 mm)"
|
|
608
856
|
] }),
|
|
609
|
-
/* @__PURE__ */ (0,
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
858
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
611
859
|
"input",
|
|
612
860
|
{
|
|
613
861
|
type: "radio",
|
|
@@ -619,8 +867,8 @@ function PageConfigDialog() {
|
|
|
619
867
|
" ",
|
|
620
868
|
"Larga (50,8 mm)"
|
|
621
869
|
] }),
|
|
622
|
-
/* @__PURE__ */ (0,
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
624
872
|
"input",
|
|
625
873
|
{
|
|
626
874
|
type: "radio",
|
|
@@ -633,11 +881,11 @@ function PageConfigDialog() {
|
|
|
633
881
|
"Personalizada"
|
|
634
882
|
] })
|
|
635
883
|
] }),
|
|
636
|
-
/* @__PURE__ */ (0,
|
|
637
|
-
/* @__PURE__ */ (0,
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ed-page-config-row", children: [
|
|
885
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
638
886
|
"Topo",
|
|
639
887
|
" ",
|
|
640
|
-
/* @__PURE__ */ (0,
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
641
889
|
"input",
|
|
642
890
|
{
|
|
643
891
|
type: "number",
|
|
@@ -652,10 +900,10 @@ function PageConfigDialog() {
|
|
|
652
900
|
}
|
|
653
901
|
)
|
|
654
902
|
] }),
|
|
655
|
-
/* @__PURE__ */ (0,
|
|
903
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
656
904
|
"Inferior",
|
|
657
905
|
" ",
|
|
658
|
-
/* @__PURE__ */ (0,
|
|
906
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
659
907
|
"input",
|
|
660
908
|
{
|
|
661
909
|
type: "number",
|
|
@@ -670,10 +918,10 @@ function PageConfigDialog() {
|
|
|
670
918
|
}
|
|
671
919
|
)
|
|
672
920
|
] }),
|
|
673
|
-
/* @__PURE__ */ (0,
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
674
922
|
"Esquerda",
|
|
675
923
|
" ",
|
|
676
|
-
/* @__PURE__ */ (0,
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
677
925
|
"input",
|
|
678
926
|
{
|
|
679
927
|
type: "number",
|
|
@@ -688,10 +936,10 @@ function PageConfigDialog() {
|
|
|
688
936
|
}
|
|
689
937
|
)
|
|
690
938
|
] }),
|
|
691
|
-
/* @__PURE__ */ (0,
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { children: [
|
|
692
940
|
"Direita",
|
|
693
941
|
" ",
|
|
694
|
-
/* @__PURE__ */ (0,
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
695
943
|
"input",
|
|
696
944
|
{
|
|
697
945
|
type: "number",
|
|
@@ -708,9 +956,9 @@ function PageConfigDialog() {
|
|
|
708
956
|
] })
|
|
709
957
|
] })
|
|
710
958
|
] }),
|
|
711
|
-
/* @__PURE__ */ (0,
|
|
712
|
-
/* @__PURE__ */ (0,
|
|
713
|
-
/* @__PURE__ */ (0,
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ed-page-config-actions", children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", onClick: onCancel, children: "Cancelar" }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "ed-page-config-apply", children: "Aplicar" })
|
|
714
962
|
] })
|
|
715
963
|
] })
|
|
716
964
|
}
|
|
@@ -745,15 +993,15 @@ function detectMarginPreset(s) {
|
|
|
745
993
|
}
|
|
746
994
|
|
|
747
995
|
// src/ImageCaptionDialog.tsx
|
|
748
|
-
var
|
|
749
|
-
var
|
|
996
|
+
var import_react4 = require("react");
|
|
997
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
750
998
|
function ImageCaptionDialog() {
|
|
751
999
|
const { imageCaptionRequest, resolveImageCaptionRequest } = useEditorContext();
|
|
752
|
-
const dialogRef = (0,
|
|
753
|
-
const inputRef = (0,
|
|
754
|
-
const [caption, setCaption] = (0,
|
|
755
|
-
const [align, setAlign] = (0,
|
|
756
|
-
(0,
|
|
1000
|
+
const dialogRef = (0, import_react4.useRef)(null);
|
|
1001
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
1002
|
+
const [caption, setCaption] = (0, import_react4.useState)("");
|
|
1003
|
+
const [align, setAlign] = (0, import_react4.useState)("center");
|
|
1004
|
+
(0, import_react4.useEffect)(() => {
|
|
757
1005
|
const dialog = dialogRef.current;
|
|
758
1006
|
if (!dialog) return;
|
|
759
1007
|
if (imageCaptionRequest) {
|
|
@@ -778,20 +1026,21 @@ function ImageCaptionDialog() {
|
|
|
778
1026
|
};
|
|
779
1027
|
const onRemove = () => resolveImageCaptionRequest({ caption: "", align });
|
|
780
1028
|
const onCancel = () => resolveImageCaptionRequest(null);
|
|
781
|
-
return /* @__PURE__ */ (0,
|
|
1029
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
782
1030
|
"dialog",
|
|
783
1031
|
{
|
|
784
1032
|
ref: dialogRef,
|
|
785
1033
|
className: "ed-caption-dialog ed-link-dialog",
|
|
1034
|
+
style: DIALOG_CENTER_STYLE,
|
|
786
1035
|
onClose: onCancel,
|
|
787
1036
|
onCancel: (e) => {
|
|
788
1037
|
e.preventDefault();
|
|
789
1038
|
onCancel();
|
|
790
1039
|
},
|
|
791
|
-
children: /* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
1040
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("form", { onSubmit, className: "ed-link-dialog-form", children: [
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ed-link-dialog-row", children: [
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { htmlFor: "ed-caption-input", children: "Legenda" }),
|
|
1043
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
795
1044
|
"input",
|
|
796
1045
|
{
|
|
797
1046
|
id: "ed-caption-input",
|
|
@@ -804,10 +1053,10 @@ function ImageCaptionDialog() {
|
|
|
804
1053
|
}
|
|
805
1054
|
)
|
|
806
1055
|
] }),
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
809
|
-
/* @__PURE__ */ (0,
|
|
810
|
-
/* @__PURE__ */ (0,
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ed-link-dialog-row", children: [
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Alinhamento" }),
|
|
1058
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ed-caption-align-group", role: "radiogroup", "aria-label": "Alinhamento da legenda", children: ["left", "center", "right"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "ed-caption-align-option", children: [
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
811
1060
|
"input",
|
|
812
1061
|
{
|
|
813
1062
|
type: "radio",
|
|
@@ -820,11 +1069,11 @@ function ImageCaptionDialog() {
|
|
|
820
1069
|
value === "left" ? "Esquerda" : value === "center" ? "Centro" : "Direita"
|
|
821
1070
|
] }, value)) })
|
|
822
1071
|
] }),
|
|
823
|
-
/* @__PURE__ */ (0,
|
|
824
|
-
imageCaptionRequest.initialCaption ? /* @__PURE__ */ (0,
|
|
825
|
-
/* @__PURE__ */ (0,
|
|
826
|
-
/* @__PURE__ */ (0,
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
1072
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ed-link-dialog-actions", children: [
|
|
1073
|
+
imageCaptionRequest.initialCaption ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", onClick: onRemove, className: "ed-link-dialog-remove", children: "Remover legenda" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {}),
|
|
1074
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ed-link-dialog-confirm", children: [
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", onClick: onCancel, children: "Cancelar" }),
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "submit", className: "ed-link-dialog-apply", children: "Aplicar" })
|
|
828
1077
|
] })
|
|
829
1078
|
] })
|
|
830
1079
|
] })
|
|
@@ -833,18 +1082,18 @@ function ImageCaptionDialog() {
|
|
|
833
1082
|
}
|
|
834
1083
|
|
|
835
1084
|
// src/EditorContext.tsx
|
|
836
|
-
var
|
|
837
|
-
var EditorContext = (0,
|
|
1085
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1086
|
+
var EditorContext = (0, import_react5.createContext)(null);
|
|
838
1087
|
function EditorProvider({ editor, children }) {
|
|
839
|
-
return /* @__PURE__ */ (0,
|
|
1088
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(EditorContext.Provider, { value: editor, children: [
|
|
840
1089
|
children,
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
842
|
-
/* @__PURE__ */ (0,
|
|
843
|
-
/* @__PURE__ */ (0,
|
|
1090
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LinkDialog, {}),
|
|
1091
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PageConfigDialog, {}),
|
|
1092
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ImageCaptionDialog, {})
|
|
844
1093
|
] });
|
|
845
1094
|
}
|
|
846
1095
|
function useEditorContext() {
|
|
847
|
-
const ctx = (0,
|
|
1096
|
+
const ctx = (0, import_react5.useContext)(EditorContext);
|
|
848
1097
|
if (!ctx) {
|
|
849
1098
|
throw new Error("useEditorContext must be used inside an <EditorProvider>");
|
|
850
1099
|
}
|
|
@@ -852,8 +1101,8 @@ function useEditorContext() {
|
|
|
852
1101
|
}
|
|
853
1102
|
|
|
854
1103
|
// src/ImageResizeOverlay.tsx
|
|
855
|
-
var
|
|
856
|
-
var
|
|
1104
|
+
var import_react6 = require("react");
|
|
1105
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
857
1106
|
function ImageResizeOverlay({
|
|
858
1107
|
rootRef,
|
|
859
1108
|
blockIndex,
|
|
@@ -861,11 +1110,13 @@ function ImageResizeOverlay({
|
|
|
861
1110
|
cellIndex,
|
|
862
1111
|
embed,
|
|
863
1112
|
onCommit,
|
|
864
|
-
onCommitMove
|
|
1113
|
+
onCommitMove,
|
|
1114
|
+
onReanchor
|
|
865
1115
|
}) {
|
|
866
|
-
const [rect, setRect] = (0,
|
|
867
|
-
const
|
|
868
|
-
const
|
|
1116
|
+
const [rect, setRect] = (0, import_react6.useState)(null);
|
|
1117
|
+
const [isMoving, setIsMoving] = (0, import_react6.useState)(false);
|
|
1118
|
+
const imgRef = (0, import_react6.useRef)(null);
|
|
1119
|
+
const locateImage = (0, import_react6.useCallback)(() => {
|
|
869
1120
|
const root = rootRef.current;
|
|
870
1121
|
if (!root) return null;
|
|
871
1122
|
let container = null;
|
|
@@ -883,7 +1134,7 @@ function ImageResizeOverlay({
|
|
|
883
1134
|
`img[data-embed="image"][data-embed-offset="${localOffset}"]`
|
|
884
1135
|
);
|
|
885
1136
|
}, [rootRef, blockIndex, offset, cellIndex]);
|
|
886
|
-
const measure = (0,
|
|
1137
|
+
const measure = (0, import_react6.useCallback)(() => {
|
|
887
1138
|
const img = locateImage();
|
|
888
1139
|
if (!img) {
|
|
889
1140
|
setRect((prev) => prev === null ? prev : null);
|
|
@@ -904,22 +1155,28 @@ function ImageResizeOverlay({
|
|
|
904
1155
|
(prev) => prev && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
905
1156
|
);
|
|
906
1157
|
}, [locateImage, rootRef]);
|
|
907
|
-
(0,
|
|
1158
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
908
1159
|
measure();
|
|
909
1160
|
let cancelled = false;
|
|
1161
|
+
let frame = 0;
|
|
1162
|
+
let rafId = 0;
|
|
910
1163
|
const remeasure = () => {
|
|
911
1164
|
if (cancelled) return;
|
|
912
1165
|
measure();
|
|
1166
|
+
if (!locateImage() && frame++ < 30) {
|
|
1167
|
+
rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(remeasure) : (queueMicrotask(remeasure), 0);
|
|
1168
|
+
}
|
|
913
1169
|
};
|
|
914
|
-
|
|
1170
|
+
rafId = typeof requestAnimationFrame === "function" ? requestAnimationFrame(remeasure) : (queueMicrotask(remeasure), 0);
|
|
915
1171
|
return () => {
|
|
916
1172
|
cancelled = true;
|
|
917
|
-
if (typeof cancelAnimationFrame === "function" && typeof
|
|
918
|
-
cancelAnimationFrame(
|
|
1173
|
+
if (typeof cancelAnimationFrame === "function" && typeof rafId === "number" && rafId > 0) {
|
|
1174
|
+
cancelAnimationFrame(rafId);
|
|
919
1175
|
}
|
|
920
1176
|
};
|
|
921
1177
|
}, [
|
|
922
1178
|
measure,
|
|
1179
|
+
locateImage,
|
|
923
1180
|
embed.width,
|
|
924
1181
|
embed.height,
|
|
925
1182
|
embed.align,
|
|
@@ -928,7 +1185,7 @@ function ImageResizeOverlay({
|
|
|
928
1185
|
embed.offsetX,
|
|
929
1186
|
embed.offsetY
|
|
930
1187
|
]);
|
|
931
|
-
(0,
|
|
1188
|
+
(0, import_react6.useEffect)(() => {
|
|
932
1189
|
const root = rootRef.current;
|
|
933
1190
|
if (!root) return;
|
|
934
1191
|
const onScroll = () => measure();
|
|
@@ -939,7 +1196,7 @@ function ImageResizeOverlay({
|
|
|
939
1196
|
root.removeEventListener("scroll", onScroll);
|
|
940
1197
|
};
|
|
941
1198
|
}, [measure, rootRef]);
|
|
942
|
-
(0,
|
|
1199
|
+
(0, import_react6.useEffect)(() => {
|
|
943
1200
|
if (typeof ResizeObserver === "undefined") return;
|
|
944
1201
|
const img = locateImage();
|
|
945
1202
|
const root = rootRef.current;
|
|
@@ -952,14 +1209,36 @@ function ImageResizeOverlay({
|
|
|
952
1209
|
if (!rect) return null;
|
|
953
1210
|
const layout = embed.layout ?? "inline";
|
|
954
1211
|
const movable = layout !== "inline" && onCommitMove !== void 0;
|
|
955
|
-
return /* @__PURE__ */ (0,
|
|
1212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
956
1213
|
"div",
|
|
957
1214
|
{
|
|
958
1215
|
className: "ed-image-overlay",
|
|
959
1216
|
style: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },
|
|
960
1217
|
contentEditable: false,
|
|
961
1218
|
children: [
|
|
962
|
-
|
|
1219
|
+
isMoving && // Non-clipped drag preview (Tier 2): the overlay lives in .ed-root and
|
|
1220
|
+
// follows the cursor, so the image stays visible while it crosses the
|
|
1221
|
+
// page boundary (the real, clipped figure is hidden during the drag).
|
|
1222
|
+
// Inline styles only — the package does not ship CSS.
|
|
1223
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1224
|
+
"img",
|
|
1225
|
+
{
|
|
1226
|
+
src: embed.src,
|
|
1227
|
+
alt: "",
|
|
1228
|
+
"aria-hidden": true,
|
|
1229
|
+
draggable: false,
|
|
1230
|
+
style: {
|
|
1231
|
+
position: "absolute",
|
|
1232
|
+
inset: 0,
|
|
1233
|
+
width: "100%",
|
|
1234
|
+
height: "100%",
|
|
1235
|
+
objectFit: "fill",
|
|
1236
|
+
opacity: 0.8,
|
|
1237
|
+
pointerEvents: "none"
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
),
|
|
1241
|
+
movable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
963
1242
|
MoveHandle,
|
|
964
1243
|
{
|
|
965
1244
|
layout,
|
|
@@ -967,10 +1246,17 @@ function ImageResizeOverlay({
|
|
|
967
1246
|
startOffsetY: embed.offsetY ?? 0,
|
|
968
1247
|
imgRef,
|
|
969
1248
|
onCommit: onCommitMove,
|
|
970
|
-
onLiveChange: measure
|
|
1249
|
+
onLiveChange: measure,
|
|
1250
|
+
rootRef,
|
|
1251
|
+
blockIndex,
|
|
1252
|
+
offset,
|
|
1253
|
+
cellIndex,
|
|
1254
|
+
onReanchor,
|
|
1255
|
+
onMoveStart: () => setIsMoving(true),
|
|
1256
|
+
onMoveEnd: () => setIsMoving(false)
|
|
971
1257
|
}
|
|
972
1258
|
),
|
|
973
|
-
/* @__PURE__ */ (0,
|
|
1259
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
974
1260
|
Handle,
|
|
975
1261
|
{
|
|
976
1262
|
corner: "nw",
|
|
@@ -981,7 +1267,7 @@ function ImageResizeOverlay({
|
|
|
981
1267
|
onLiveChange: measure
|
|
982
1268
|
}
|
|
983
1269
|
),
|
|
984
|
-
/* @__PURE__ */ (0,
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
985
1271
|
Handle,
|
|
986
1272
|
{
|
|
987
1273
|
corner: "ne",
|
|
@@ -992,7 +1278,7 @@ function ImageResizeOverlay({
|
|
|
992
1278
|
onLiveChange: measure
|
|
993
1279
|
}
|
|
994
1280
|
),
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
1281
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
996
1282
|
Handle,
|
|
997
1283
|
{
|
|
998
1284
|
corner: "sw",
|
|
@@ -1003,7 +1289,7 @@ function ImageResizeOverlay({
|
|
|
1003
1289
|
onLiveChange: measure
|
|
1004
1290
|
}
|
|
1005
1291
|
),
|
|
1006
|
-
/* @__PURE__ */ (0,
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1007
1293
|
Handle,
|
|
1008
1294
|
{
|
|
1009
1295
|
corner: "se",
|
|
@@ -1024,9 +1310,16 @@ function MoveHandle({
|
|
|
1024
1310
|
startOffsetY,
|
|
1025
1311
|
imgRef,
|
|
1026
1312
|
onCommit,
|
|
1027
|
-
onLiveChange
|
|
1313
|
+
onLiveChange,
|
|
1314
|
+
rootRef,
|
|
1315
|
+
blockIndex,
|
|
1316
|
+
offset,
|
|
1317
|
+
cellIndex,
|
|
1318
|
+
onReanchor,
|
|
1319
|
+
onMoveStart,
|
|
1320
|
+
onMoveEnd
|
|
1028
1321
|
}) {
|
|
1029
|
-
const dragRef = (0,
|
|
1322
|
+
const dragRef = (0, import_react6.useRef)(null);
|
|
1030
1323
|
const onPointerDown = (e) => {
|
|
1031
1324
|
if (e.button !== 0) return;
|
|
1032
1325
|
if (!imgRef.current) return;
|
|
@@ -1039,35 +1332,65 @@ function MoveHandle({
|
|
|
1039
1332
|
liveOX: startOffsetX,
|
|
1040
1333
|
liveOY: startOffsetY
|
|
1041
1334
|
};
|
|
1335
|
+
const styled = imgRef.current.closest(".ed-figure") ?? imgRef.current;
|
|
1336
|
+
styled.style.opacity = "0";
|
|
1337
|
+
onMoveStart?.();
|
|
1042
1338
|
};
|
|
1043
1339
|
const onPointerMove = (e) => {
|
|
1044
1340
|
const d = dragRef.current;
|
|
1045
1341
|
if (!d || !imgRef.current) return;
|
|
1046
1342
|
const dx = e.clientX - d.startX;
|
|
1047
1343
|
const dy = e.clientY - d.startY;
|
|
1048
|
-
const
|
|
1344
|
+
const styled = imgRef.current.closest(".ed-figure") ?? imgRef.current;
|
|
1049
1345
|
let nox = startOffsetX;
|
|
1050
1346
|
let noy = startOffsetY;
|
|
1051
1347
|
if (layout === "wrap-left") {
|
|
1052
1348
|
nox = Math.max(8, startOffsetX + dx);
|
|
1053
1349
|
noy = Math.max(0, startOffsetY + dy);
|
|
1054
|
-
|
|
1055
|
-
|
|
1350
|
+
styled.style.marginRight = `${nox}px`;
|
|
1351
|
+
styled.style.marginTop = `${noy}px`;
|
|
1056
1352
|
} else if (layout === "wrap-right") {
|
|
1057
1353
|
nox = Math.max(8, startOffsetX - dx);
|
|
1058
1354
|
noy = Math.max(0, startOffsetY + dy);
|
|
1059
|
-
|
|
1060
|
-
|
|
1355
|
+
styled.style.marginLeft = `${nox}px`;
|
|
1356
|
+
styled.style.marginTop = `${noy}px`;
|
|
1061
1357
|
} else if (layout === "behind" || layout === "front") {
|
|
1062
1358
|
nox = startOffsetX + dx;
|
|
1063
1359
|
noy = startOffsetY + dy;
|
|
1064
|
-
|
|
1065
|
-
|
|
1360
|
+
styled.style.left = `${nox}px`;
|
|
1361
|
+
styled.style.top = `${noy}px`;
|
|
1066
1362
|
}
|
|
1067
1363
|
d.liveOX = nox;
|
|
1068
1364
|
d.liveOY = noy;
|
|
1069
1365
|
onLiveChange();
|
|
1070
1366
|
};
|
|
1367
|
+
const clampOffsetToFragment = (frag, oy) => {
|
|
1368
|
+
const img = imgRef.current;
|
|
1369
|
+
if (!img) return oy;
|
|
1370
|
+
const page = frag.closest(".ed-page");
|
|
1371
|
+
const content = page?.querySelector(".ed-page-content");
|
|
1372
|
+
if (!content) return oy;
|
|
1373
|
+
const fragRect = frag.getBoundingClientRect();
|
|
1374
|
+
const contentRect = content.getBoundingClientRect();
|
|
1375
|
+
const imgH = img.getBoundingClientRect().height;
|
|
1376
|
+
const minLocalTop = contentRect.top - fragRect.top;
|
|
1377
|
+
const maxLocalTop = contentRect.bottom - fragRect.top - imgH;
|
|
1378
|
+
return Math.round(Math.max(minLocalTop, Math.min(oy, maxLocalTop)));
|
|
1379
|
+
};
|
|
1380
|
+
const clampedCommit = (ox, oy) => {
|
|
1381
|
+
const img = imgRef.current;
|
|
1382
|
+
const root = rootRef.current;
|
|
1383
|
+
if (!img || !root || layout !== "behind" && layout !== "front") {
|
|
1384
|
+
onCommit(ox, oy);
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
const frag = getFragmentForOffset(root, blockIndex, offset);
|
|
1388
|
+
if (!frag) {
|
|
1389
|
+
onCommit(ox, oy);
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
onCommit(ox, clampOffsetToFragment(frag, oy));
|
|
1393
|
+
};
|
|
1071
1394
|
const finish = (e) => {
|
|
1072
1395
|
const d = dragRef.current;
|
|
1073
1396
|
if (!d) return;
|
|
@@ -1076,9 +1399,77 @@ function MoveHandle({
|
|
|
1076
1399
|
e.target.releasePointerCapture(e.pointerId);
|
|
1077
1400
|
} catch {
|
|
1078
1401
|
}
|
|
1079
|
-
|
|
1402
|
+
if (imgRef.current) {
|
|
1403
|
+
const styled = imgRef.current.closest(".ed-figure") ?? imgRef.current;
|
|
1404
|
+
styled.style.opacity = "";
|
|
1405
|
+
}
|
|
1406
|
+
onMoveEnd?.();
|
|
1407
|
+
const img = imgRef.current;
|
|
1408
|
+
const root = rootRef.current;
|
|
1409
|
+
const liveOX = Math.round(d.liveOX);
|
|
1410
|
+
const liveOY = Math.round(d.liveOY);
|
|
1411
|
+
if (!img || !root || onReanchor === void 0 || cellIndex != null) {
|
|
1412
|
+
clampedCommit(liveOX, liveOY);
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
const imgRect = img.getBoundingClientRect();
|
|
1416
|
+
const centerY = imgRect.top + imgRect.height / 2;
|
|
1417
|
+
const pages = Array.from(root.querySelectorAll(".ed-page"));
|
|
1418
|
+
let destPage = null;
|
|
1419
|
+
let bestPageDist = Infinity;
|
|
1420
|
+
for (const pg of pages) {
|
|
1421
|
+
const r = pg.getBoundingClientRect();
|
|
1422
|
+
if (centerY >= r.top && centerY <= r.bottom) {
|
|
1423
|
+
destPage = pg;
|
|
1424
|
+
break;
|
|
1425
|
+
}
|
|
1426
|
+
const dist = centerY < r.top ? r.top - centerY : centerY - r.bottom;
|
|
1427
|
+
if (dist < bestPageDist) {
|
|
1428
|
+
bestPageDist = dist;
|
|
1429
|
+
destPage = pg;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
const currentFrag = getFragmentForOffset(root, blockIndex, offset);
|
|
1433
|
+
const currentPage = currentFrag?.closest(".ed-page") ?? null;
|
|
1434
|
+
if (destPage == null || destPage === currentPage) {
|
|
1435
|
+
clampedCommit(liveOX, liveOY);
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
const blocksOnPage = Array.from(
|
|
1439
|
+
destPage.querySelectorAll("[data-block-index]")
|
|
1440
|
+
);
|
|
1441
|
+
let destFrag = null;
|
|
1442
|
+
let bestBlockDist = Infinity;
|
|
1443
|
+
for (const b of blocksOnPage) {
|
|
1444
|
+
const dist = Math.abs(b.getBoundingClientRect().top - imgRect.top);
|
|
1445
|
+
if (dist < bestBlockDist) {
|
|
1446
|
+
bestBlockDist = dist;
|
|
1447
|
+
destFrag = b;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
if (!destFrag) {
|
|
1451
|
+
clampedCommit(liveOX, liveOY);
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
const destBlockIndex = findBlockIndex(destFrag, root);
|
|
1455
|
+
if (destBlockIndex == null) {
|
|
1456
|
+
clampedCommit(liveOX, liveOY);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const destOffset = destFrag.dataset.fragmentStart ? Number.parseInt(destFrag.dataset.fragmentStart, 10) || 0 : 0;
|
|
1460
|
+
const fragRect = destFrag.getBoundingClientRect();
|
|
1461
|
+
const newOffsetX = Math.round(imgRect.left - fragRect.left);
|
|
1462
|
+
const newOffsetY = clampOffsetToFragment(
|
|
1463
|
+
destFrag,
|
|
1464
|
+
Math.round(imgRect.top - fragRect.top)
|
|
1465
|
+
);
|
|
1466
|
+
onReanchor(
|
|
1467
|
+
{ blockIndex: destBlockIndex, offset: destOffset, cellIndex: void 0 },
|
|
1468
|
+
newOffsetX,
|
|
1469
|
+
newOffsetY
|
|
1470
|
+
);
|
|
1080
1471
|
};
|
|
1081
|
-
return /* @__PURE__ */ (0,
|
|
1472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1082
1473
|
"div",
|
|
1083
1474
|
{
|
|
1084
1475
|
className: "ed-image-move",
|
|
@@ -1098,7 +1489,7 @@ function Handle({
|
|
|
1098
1489
|
onCommit,
|
|
1099
1490
|
onLiveChange
|
|
1100
1491
|
}) {
|
|
1101
|
-
const dragRef = (0,
|
|
1492
|
+
const dragRef = (0, import_react6.useRef)(null);
|
|
1102
1493
|
const onPointerDown = (e) => {
|
|
1103
1494
|
if (e.button !== 0) return;
|
|
1104
1495
|
if (!imgRef.current) return;
|
|
@@ -1141,7 +1532,7 @@ function Handle({
|
|
|
1141
1532
|
}
|
|
1142
1533
|
onCommit(Math.round(d.liveW), Math.round(d.liveH));
|
|
1143
1534
|
};
|
|
1144
|
-
return /* @__PURE__ */ (0,
|
|
1535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1145
1536
|
"div",
|
|
1146
1537
|
{
|
|
1147
1538
|
className: `ed-image-handle ${corner}`,
|
|
@@ -1153,17 +1544,187 @@ function Handle({
|
|
|
1153
1544
|
);
|
|
1154
1545
|
}
|
|
1155
1546
|
|
|
1547
|
+
// src/RemoteCursorsOverlay.tsx
|
|
1548
|
+
var import_react7 = require("react");
|
|
1549
|
+
var import_core2 = require("@sofereditor/core");
|
|
1550
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1551
|
+
var DEFAULT_COLOR = "#3b82f6";
|
|
1552
|
+
function RemoteCursorsOverlay({
|
|
1553
|
+
rootRef,
|
|
1554
|
+
doc,
|
|
1555
|
+
awareness,
|
|
1556
|
+
revision
|
|
1557
|
+
}) {
|
|
1558
|
+
const [views, setViews] = (0, import_react7.useState)([]);
|
|
1559
|
+
const rafRef = (0, import_react7.useRef)(null);
|
|
1560
|
+
const measure = (0, import_react7.useCallback)(() => {
|
|
1561
|
+
const root = rootRef.current;
|
|
1562
|
+
if (!root) {
|
|
1563
|
+
setViews((prev) => prev.length === 0 ? prev : []);
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1566
|
+
const rr = root.getBoundingClientRect();
|
|
1567
|
+
const out = [];
|
|
1568
|
+
awareness.getStates().forEach((state, clientId) => {
|
|
1569
|
+
if (clientId === awareness.clientID) return;
|
|
1570
|
+
const s = state;
|
|
1571
|
+
if (!s.cursor) return;
|
|
1572
|
+
const sel = (0, import_core2.decodeSelection)(doc, s.cursor);
|
|
1573
|
+
if (!sel) return;
|
|
1574
|
+
const color = s.user?.color || DEFAULT_COLOR;
|
|
1575
|
+
const name = s.user?.name || "An\xF4nimo";
|
|
1576
|
+
const focus = locatePoint(root, sel.focus);
|
|
1577
|
+
let caret = null;
|
|
1578
|
+
if (focus) {
|
|
1579
|
+
try {
|
|
1580
|
+
const range = document.createRange();
|
|
1581
|
+
range.setStart(focus.node, focus.offset);
|
|
1582
|
+
range.collapse(true);
|
|
1583
|
+
let rect = range.getBoundingClientRect();
|
|
1584
|
+
if (rect.height === 0 && focus.node.nodeType === Node.ELEMENT_NODE) {
|
|
1585
|
+
rect = focus.node.getBoundingClientRect();
|
|
1586
|
+
}
|
|
1587
|
+
caret = {
|
|
1588
|
+
top: rect.top - rr.top + root.scrollTop,
|
|
1589
|
+
left: rect.left - rr.left + root.scrollLeft,
|
|
1590
|
+
height: rect.height || 18
|
|
1591
|
+
};
|
|
1592
|
+
} catch {
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
const collapsed = sel.anchor.blockIndex === sel.focus.blockIndex && (sel.anchor.cellIndex ?? -1) === (sel.focus.cellIndex ?? -1) && sel.anchor.offset === sel.focus.offset;
|
|
1596
|
+
const selection = [];
|
|
1597
|
+
if (!collapsed && focus) {
|
|
1598
|
+
const anchor = locatePoint(root, sel.anchor);
|
|
1599
|
+
if (anchor) {
|
|
1600
|
+
try {
|
|
1601
|
+
const r = document.createRange();
|
|
1602
|
+
r.setStart(anchor.node, anchor.offset);
|
|
1603
|
+
r.setEnd(focus.node, focus.offset);
|
|
1604
|
+
if (r.collapsed) {
|
|
1605
|
+
r.setStart(focus.node, focus.offset);
|
|
1606
|
+
r.setEnd(anchor.node, anchor.offset);
|
|
1607
|
+
}
|
|
1608
|
+
for (const cr of Array.from(r.getClientRects())) {
|
|
1609
|
+
if (cr.width === 0 || cr.height === 0) continue;
|
|
1610
|
+
selection.push({
|
|
1611
|
+
top: cr.top - rr.top + root.scrollTop,
|
|
1612
|
+
left: cr.left - rr.left + root.scrollLeft,
|
|
1613
|
+
width: cr.width,
|
|
1614
|
+
height: cr.height
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
} catch {
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
out.push({ clientId, name, color, caret, selection });
|
|
1622
|
+
});
|
|
1623
|
+
setViews(out);
|
|
1624
|
+
}, [rootRef, doc, awareness]);
|
|
1625
|
+
const scheduleMeasure = (0, import_react7.useCallback)(() => {
|
|
1626
|
+
if (rafRef.current != null) return;
|
|
1627
|
+
const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(() => cb(0), 16);
|
|
1628
|
+
rafRef.current = raf(() => {
|
|
1629
|
+
rafRef.current = null;
|
|
1630
|
+
measure();
|
|
1631
|
+
});
|
|
1632
|
+
}, [measure]);
|
|
1633
|
+
(0, import_react7.useEffect)(() => {
|
|
1634
|
+
const onChange = () => scheduleMeasure();
|
|
1635
|
+
awareness.on("change", onChange);
|
|
1636
|
+
scheduleMeasure();
|
|
1637
|
+
return () => awareness.off("change", onChange);
|
|
1638
|
+
}, [awareness, scheduleMeasure]);
|
|
1639
|
+
(0, import_react7.useEffect)(() => {
|
|
1640
|
+
scheduleMeasure();
|
|
1641
|
+
}, [revision, scheduleMeasure]);
|
|
1642
|
+
(0, import_react7.useEffect)(() => {
|
|
1643
|
+
const root = rootRef.current;
|
|
1644
|
+
if (!root) return;
|
|
1645
|
+
const onScroll = () => scheduleMeasure();
|
|
1646
|
+
root.addEventListener("scroll", onScroll, { passive: true });
|
|
1647
|
+
let ro = null;
|
|
1648
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1649
|
+
ro = new ResizeObserver(() => scheduleMeasure());
|
|
1650
|
+
ro.observe(root);
|
|
1651
|
+
}
|
|
1652
|
+
return () => {
|
|
1653
|
+
root.removeEventListener("scroll", onScroll);
|
|
1654
|
+
ro?.disconnect();
|
|
1655
|
+
};
|
|
1656
|
+
}, [rootRef, scheduleMeasure]);
|
|
1657
|
+
if (views.length === 0) return null;
|
|
1658
|
+
const layer = {
|
|
1659
|
+
position: "absolute",
|
|
1660
|
+
inset: 0,
|
|
1661
|
+
pointerEvents: "none",
|
|
1662
|
+
zIndex: 6
|
|
1663
|
+
};
|
|
1664
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "ed-remote-cursors", "aria-hidden": true, style: layer, children: views.map((v) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
1665
|
+
v.selection.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1666
|
+
"div",
|
|
1667
|
+
{
|
|
1668
|
+
style: {
|
|
1669
|
+
position: "absolute",
|
|
1670
|
+
top: r.top,
|
|
1671
|
+
left: r.left,
|
|
1672
|
+
width: r.width,
|
|
1673
|
+
height: r.height,
|
|
1674
|
+
background: v.color,
|
|
1675
|
+
opacity: 0.22,
|
|
1676
|
+
borderRadius: 2
|
|
1677
|
+
}
|
|
1678
|
+
},
|
|
1679
|
+
i
|
|
1680
|
+
)),
|
|
1681
|
+
v.caret && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1682
|
+
"div",
|
|
1683
|
+
{
|
|
1684
|
+
style: {
|
|
1685
|
+
position: "absolute",
|
|
1686
|
+
top: v.caret.top,
|
|
1687
|
+
left: v.caret.left,
|
|
1688
|
+
height: v.caret.height,
|
|
1689
|
+
width: 2,
|
|
1690
|
+
background: v.color
|
|
1691
|
+
},
|
|
1692
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1693
|
+
"span",
|
|
1694
|
+
{
|
|
1695
|
+
style: {
|
|
1696
|
+
position: "absolute",
|
|
1697
|
+
top: -15,
|
|
1698
|
+
left: -1,
|
|
1699
|
+
fontSize: 10,
|
|
1700
|
+
lineHeight: "14px",
|
|
1701
|
+
padding: "0 4px",
|
|
1702
|
+
borderRadius: 3,
|
|
1703
|
+
color: "#fff",
|
|
1704
|
+
background: v.color,
|
|
1705
|
+
whiteSpace: "nowrap",
|
|
1706
|
+
fontFamily: "system-ui, sans-serif",
|
|
1707
|
+
userSelect: "none"
|
|
1708
|
+
},
|
|
1709
|
+
children: v.name
|
|
1710
|
+
}
|
|
1711
|
+
)
|
|
1712
|
+
}
|
|
1713
|
+
)
|
|
1714
|
+
] }, v.clientId)) });
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1156
1717
|
// src/NodeView.tsx
|
|
1157
|
-
var
|
|
1158
|
-
var
|
|
1718
|
+
var import_react10 = require("react");
|
|
1719
|
+
var import_core4 = require("@sofereditor/core");
|
|
1159
1720
|
|
|
1160
1721
|
// src/renderInline.tsx
|
|
1161
|
-
var
|
|
1162
|
-
var
|
|
1163
|
-
var
|
|
1722
|
+
var import_react8 = require("react");
|
|
1723
|
+
var import_core3 = require("@sofereditor/core");
|
|
1724
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1164
1725
|
function renderInline(delta, keyPrefix) {
|
|
1165
1726
|
if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
|
|
1166
|
-
return /* @__PURE__ */ (0,
|
|
1727
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", { "data-empty": "true" });
|
|
1167
1728
|
}
|
|
1168
1729
|
let offset = 0;
|
|
1169
1730
|
const wrapAnchors = [];
|
|
@@ -1173,17 +1734,18 @@ function renderInline(delta, keyPrefix) {
|
|
|
1173
1734
|
const text = op.insert;
|
|
1174
1735
|
if (text.length === 0) continue;
|
|
1175
1736
|
const key = `${keyPrefix}-${offset}`;
|
|
1176
|
-
body.push(/* @__PURE__ */ (0,
|
|
1737
|
+
body.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: wrap(text, op.attributes) }, key));
|
|
1177
1738
|
offset += text.length;
|
|
1178
|
-
} else if ((0,
|
|
1739
|
+
} else if ((0, import_core3.isImageEmbed)(op.insert)) {
|
|
1179
1740
|
const key = `${keyPrefix}-${offset}`;
|
|
1180
1741
|
const layout = op.insert.layout ?? "inline";
|
|
1742
|
+
const commentMarkId = op.attributes?.comment?.markId;
|
|
1181
1743
|
if (layout === "wrap-left" || layout === "wrap-right") {
|
|
1182
1744
|
wrapAnchors.push(
|
|
1183
|
-
/* @__PURE__ */ (0,
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ImageEmbedView, { embed: op.insert, offset, wrapAnchor: true }, `${key}-anchor`)
|
|
1184
1746
|
);
|
|
1185
1747
|
body.push(
|
|
1186
|
-
/* @__PURE__ */ (0,
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1187
1749
|
"span",
|
|
1188
1750
|
{
|
|
1189
1751
|
"data-embed-phantom": "true",
|
|
@@ -1195,14 +1757,21 @@ function renderInline(delta, keyPrefix) {
|
|
|
1195
1757
|
)
|
|
1196
1758
|
);
|
|
1197
1759
|
} else {
|
|
1198
|
-
|
|
1760
|
+
const imgNode = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ImageEmbedView, { embed: op.insert, offset }, key);
|
|
1761
|
+
if (commentMarkId) {
|
|
1762
|
+
body.push(
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-comment-id": commentMarkId, className: "ed-comment", children: imgNode }, `${key}-cmt`)
|
|
1764
|
+
);
|
|
1765
|
+
} else {
|
|
1766
|
+
body.push(imgNode);
|
|
1767
|
+
}
|
|
1199
1768
|
}
|
|
1200
1769
|
offset += 1;
|
|
1201
1770
|
} else if (op.insert != null) {
|
|
1202
1771
|
offset += 1;
|
|
1203
1772
|
}
|
|
1204
1773
|
}
|
|
1205
|
-
if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ (0,
|
|
1774
|
+
if (wrapAnchors.length === 0 && body.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", { "data-empty": "true" });
|
|
1206
1775
|
return [...wrapAnchors, ...body];
|
|
1207
1776
|
}
|
|
1208
1777
|
var PHANTOM_STYLE = {
|
|
@@ -1212,6 +1781,11 @@ var PHANTOM_STYLE = {
|
|
|
1212
1781
|
overflow: "hidden",
|
|
1213
1782
|
verticalAlign: "baseline"
|
|
1214
1783
|
};
|
|
1784
|
+
var LINK_STYLE = {
|
|
1785
|
+
color: "#2563eb",
|
|
1786
|
+
textDecoration: "underline",
|
|
1787
|
+
cursor: "text"
|
|
1788
|
+
};
|
|
1215
1789
|
function imageEmbedPropsEqual(a, b) {
|
|
1216
1790
|
if (a.offset !== b.offset || a.wrapAnchor !== b.wrapAnchor) return false;
|
|
1217
1791
|
const x = a.embed;
|
|
@@ -1222,7 +1796,7 @@ function imageEmbedPropsEqual(a, b) {
|
|
|
1222
1796
|
// because Y.js stores the embed in its content map and re-exposes it.
|
|
1223
1797
|
x.src === y.src;
|
|
1224
1798
|
}
|
|
1225
|
-
var ImageEmbedView = (0,
|
|
1799
|
+
var ImageEmbedView = (0, import_react8.memo)(ImageEmbedViewImpl, imageEmbedPropsEqual);
|
|
1226
1800
|
function ImageEmbedViewImpl({
|
|
1227
1801
|
embed,
|
|
1228
1802
|
offset,
|
|
@@ -1277,8 +1851,12 @@ function ImageEmbedViewImpl({
|
|
|
1277
1851
|
};
|
|
1278
1852
|
break;
|
|
1279
1853
|
}
|
|
1280
|
-
const imgStyle =
|
|
1281
|
-
|
|
1854
|
+
const imgStyle = {
|
|
1855
|
+
width: embed.width,
|
|
1856
|
+
height: embed.height,
|
|
1857
|
+
display: "block"
|
|
1858
|
+
};
|
|
1859
|
+
const img = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1282
1860
|
"img",
|
|
1283
1861
|
{
|
|
1284
1862
|
src: embed.src,
|
|
@@ -1286,6 +1864,8 @@ function ImageEmbedViewImpl({
|
|
|
1286
1864
|
height: embed.height,
|
|
1287
1865
|
contentEditable: false,
|
|
1288
1866
|
draggable: false,
|
|
1867
|
+
decoding: "sync",
|
|
1868
|
+
loading: "eager",
|
|
1289
1869
|
"data-embed": "image",
|
|
1290
1870
|
"data-embed-offset": offset,
|
|
1291
1871
|
"data-embed-align": align ?? "",
|
|
@@ -1295,19 +1875,18 @@ function ImageEmbedViewImpl({
|
|
|
1295
1875
|
alt: ""
|
|
1296
1876
|
}
|
|
1297
1877
|
);
|
|
1298
|
-
if (!hasCaption) return img;
|
|
1299
1878
|
const captionAlign = embed.captionAlign ?? "center";
|
|
1300
|
-
return /* @__PURE__ */ (0,
|
|
1879
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1301
1880
|
"figure",
|
|
1302
1881
|
{
|
|
1303
1882
|
className: "ed-figure",
|
|
1304
1883
|
contentEditable: false,
|
|
1305
|
-
"data-embed-figure": "true",
|
|
1884
|
+
"data-embed-figure": hasCaption ? "true" : void 0,
|
|
1306
1885
|
"data-embed-layout": layout,
|
|
1307
1886
|
style: outerStyle,
|
|
1308
1887
|
children: [
|
|
1309
1888
|
img,
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1889
|
+
hasCaption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1311
1890
|
"figcaption",
|
|
1312
1891
|
{
|
|
1313
1892
|
className: "ed-figcaption",
|
|
@@ -1323,34 +1902,38 @@ function ImageEmbedViewImpl({
|
|
|
1323
1902
|
function wrap(text, attrs) {
|
|
1324
1903
|
let node = text;
|
|
1325
1904
|
if (!attrs) return node;
|
|
1326
|
-
if (attrs.bold) node = /* @__PURE__ */ (0,
|
|
1327
|
-
if (attrs.italic) node = /* @__PURE__ */ (0,
|
|
1328
|
-
if (attrs.underline) node = /* @__PURE__ */ (0,
|
|
1329
|
-
if (attrs.strike) node = /* @__PURE__ */ (0,
|
|
1905
|
+
if (attrs.bold) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: node });
|
|
1906
|
+
if (attrs.italic) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("em", { children: node });
|
|
1907
|
+
if (attrs.underline) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("u", { children: node });
|
|
1908
|
+
if (attrs.strike) node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("s", { children: node });
|
|
1330
1909
|
const styleParts = {};
|
|
1331
1910
|
if (attrs.color) styleParts.color = attrs.color;
|
|
1332
1911
|
if (attrs.fontFamily) styleParts.fontFamily = attrs.fontFamily;
|
|
1333
1912
|
if (attrs.fontSize) styleParts.fontSize = attrs.fontSize;
|
|
1334
1913
|
if (Object.keys(styleParts).length > 0) {
|
|
1335
|
-
node = /* @__PURE__ */ (0,
|
|
1914
|
+
node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styleParts, children: node });
|
|
1336
1915
|
}
|
|
1337
1916
|
if (attrs.link?.href) {
|
|
1338
|
-
node = /* @__PURE__ */ (0,
|
|
1917
|
+
node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1339
1918
|
"a",
|
|
1340
1919
|
{
|
|
1341
1920
|
href: attrs.link.href,
|
|
1342
1921
|
title: attrs.link.title,
|
|
1343
1922
|
rel: "noopener noreferrer",
|
|
1344
1923
|
target: "_blank",
|
|
1924
|
+
style: LINK_STYLE,
|
|
1345
1925
|
onClick: (e) => {
|
|
1346
|
-
|
|
1926
|
+
e.preventDefault();
|
|
1927
|
+
if (hasOpenModifier(e) && attrs.link?.href) {
|
|
1928
|
+
window.open(attrs.link.href, "_blank", "noopener,noreferrer");
|
|
1929
|
+
}
|
|
1347
1930
|
},
|
|
1348
1931
|
children: node
|
|
1349
1932
|
}
|
|
1350
1933
|
);
|
|
1351
1934
|
}
|
|
1352
1935
|
if (attrs.comment?.markId) {
|
|
1353
|
-
node = /* @__PURE__ */ (0,
|
|
1936
|
+
node = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-comment-id": attrs.comment.markId, className: "ed-comment", children: node });
|
|
1354
1937
|
}
|
|
1355
1938
|
return node;
|
|
1356
1939
|
}
|
|
@@ -1394,14 +1977,14 @@ function sliceDelta(delta, start, end) {
|
|
|
1394
1977
|
}
|
|
1395
1978
|
|
|
1396
1979
|
// src/TableResizeOverlay.tsx
|
|
1397
|
-
var
|
|
1398
|
-
var
|
|
1980
|
+
var import_react9 = require("react");
|
|
1981
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1399
1982
|
function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
1400
1983
|
const editor = useEditorContext();
|
|
1401
|
-
const [positions, setPositions] = (0,
|
|
1402
|
-
const [layout, setLayout] = (0,
|
|
1403
|
-
const draggingRef = (0,
|
|
1404
|
-
const measure = (0,
|
|
1984
|
+
const [positions, setPositions] = (0, import_react9.useState)(null);
|
|
1985
|
+
const [layout, setLayout] = (0, import_react9.useState)(null);
|
|
1986
|
+
const draggingRef = (0, import_react9.useRef)(null);
|
|
1987
|
+
const measure = (0, import_react9.useCallback)(() => {
|
|
1405
1988
|
const table = tableRef.current;
|
|
1406
1989
|
if (!table) return;
|
|
1407
1990
|
const tableRect = table.getBoundingClientRect();
|
|
@@ -1431,17 +2014,17 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
|
1431
2014
|
}
|
|
1432
2015
|
setLayout({ rights, height: tableRect.height });
|
|
1433
2016
|
}, [cols, tableRef]);
|
|
1434
|
-
(0,
|
|
2017
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
1435
2018
|
measure();
|
|
1436
2019
|
}, [measure]);
|
|
1437
|
-
(0,
|
|
2020
|
+
(0, import_react9.useEffect)(() => {
|
|
1438
2021
|
const table = tableRef.current;
|
|
1439
2022
|
if (!table) return;
|
|
1440
2023
|
const ro = new ResizeObserver(() => measure());
|
|
1441
2024
|
ro.observe(table);
|
|
1442
2025
|
return () => ro.disconnect();
|
|
1443
2026
|
}, [measure, tableRef]);
|
|
1444
|
-
const onPointerDown = (0,
|
|
2027
|
+
const onPointerDown = (0, import_react9.useCallback)(
|
|
1445
2028
|
(col) => (e) => {
|
|
1446
2029
|
e.preventDefault();
|
|
1447
2030
|
e.stopPropagation();
|
|
@@ -1455,7 +2038,7 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
|
1455
2038
|
},
|
|
1456
2039
|
[layout, tableRef]
|
|
1457
2040
|
);
|
|
1458
|
-
const onPointerMove = (0,
|
|
2041
|
+
const onPointerMove = (0, import_react9.useCallback)(
|
|
1459
2042
|
(e) => {
|
|
1460
2043
|
const d = draggingRef.current;
|
|
1461
2044
|
if (!d) return;
|
|
@@ -1465,7 +2048,7 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
|
1465
2048
|
},
|
|
1466
2049
|
[blockIndex, editor]
|
|
1467
2050
|
);
|
|
1468
|
-
const onPointerUp = (0,
|
|
2051
|
+
const onPointerUp = (0, import_react9.useCallback)((e) => {
|
|
1469
2052
|
draggingRef.current = null;
|
|
1470
2053
|
setPositions(null);
|
|
1471
2054
|
try {
|
|
@@ -1484,7 +2067,7 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
|
1484
2067
|
zIndex: 5
|
|
1485
2068
|
});
|
|
1486
2069
|
void positions;
|
|
1487
|
-
return /* @__PURE__ */ (0,
|
|
2070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: layout.rights.map((x, c) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1488
2071
|
"div",
|
|
1489
2072
|
{
|
|
1490
2073
|
contentEditable: false,
|
|
@@ -1501,10 +2084,10 @@ function TableResizeOverlay({ tableRef, blockIndex, cols }) {
|
|
|
1501
2084
|
}
|
|
1502
2085
|
|
|
1503
2086
|
// src/NodeView.tsx
|
|
1504
|
-
var
|
|
2087
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1505
2088
|
function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
1506
2089
|
if (block.type === "table") {
|
|
1507
|
-
return /* @__PURE__ */ (0,
|
|
2090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableView, { block, index, tableFragment });
|
|
1508
2091
|
}
|
|
1509
2092
|
const inline = fragment ? renderInline(sliceDelta(block.delta, fragment.start, fragment.end), index) : renderInline(block.delta, index);
|
|
1510
2093
|
const common = commonBlockProps(block.attrs, index, block.type, fragment);
|
|
@@ -1512,7 +2095,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
|
1512
2095
|
case "heading": {
|
|
1513
2096
|
const level = clampLevel(block.attrs.level);
|
|
1514
2097
|
const Tag = `h${level}`;
|
|
1515
|
-
return /* @__PURE__ */ (0,
|
|
2098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1516
2099
|
Tag,
|
|
1517
2100
|
{
|
|
1518
2101
|
...common,
|
|
@@ -1522,7 +2105,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
|
1522
2105
|
);
|
|
1523
2106
|
}
|
|
1524
2107
|
case "blockquote":
|
|
1525
|
-
return /* @__PURE__ */ (0,
|
|
2108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1526
2109
|
"blockquote",
|
|
1527
2110
|
{
|
|
1528
2111
|
...common,
|
|
@@ -1531,18 +2114,18 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
|
1531
2114
|
}
|
|
1532
2115
|
);
|
|
1533
2116
|
case "codeBlock":
|
|
1534
|
-
return /* @__PURE__ */ (0,
|
|
2117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1535
2118
|
"pre",
|
|
1536
2119
|
{
|
|
1537
2120
|
...common,
|
|
1538
2121
|
"data-language": block.attrs.language ?? void 0,
|
|
1539
2122
|
className: `ed-block ed-codeblock${alignClass(block.attrs.align)}`,
|
|
1540
|
-
children: /* @__PURE__ */ (0,
|
|
2123
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", { children: inline })
|
|
1541
2124
|
}
|
|
1542
2125
|
);
|
|
1543
2126
|
case "listItem": {
|
|
1544
2127
|
const level = clampListLevel(block.attrs.listLevel);
|
|
1545
|
-
return /* @__PURE__ */ (0,
|
|
2128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1546
2129
|
"li",
|
|
1547
2130
|
{
|
|
1548
2131
|
...common,
|
|
@@ -1558,7 +2141,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
|
1558
2141
|
}
|
|
1559
2142
|
case "paragraph":
|
|
1560
2143
|
default:
|
|
1561
|
-
return /* @__PURE__ */ (0,
|
|
2144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1562
2145
|
"div",
|
|
1563
2146
|
{
|
|
1564
2147
|
...common,
|
|
@@ -1603,18 +2186,18 @@ function TableView({ block, index, tableFragment }) {
|
|
|
1603
2186
|
const cols = clampPositive(block.attrs.cols);
|
|
1604
2187
|
const cells = block.cells ?? [];
|
|
1605
2188
|
const widths = readColWidths(block.attrs.colWidths, cols);
|
|
1606
|
-
const tableRef = (0,
|
|
2189
|
+
const tableRef = (0, import_react10.useRef)(null);
|
|
1607
2190
|
const rowStart = tableFragment?.rowStart ?? 0;
|
|
1608
2191
|
const rowEnd = tableFragment?.rowEnd ?? rows;
|
|
1609
2192
|
const isFirstFragment = !tableFragment || tableFragment.index === 0;
|
|
1610
2193
|
const editor = useEditorContext();
|
|
1611
|
-
const rect = (0,
|
|
2194
|
+
const rect = (0, import_react10.useMemo)(() => {
|
|
1612
2195
|
if (editor.selection.anchor.blockIndex !== index) return null;
|
|
1613
2196
|
if (editor.selection.focus.blockIndex !== index) return null;
|
|
1614
|
-
return (0,
|
|
2197
|
+
return (0, import_core4.tableRectSelection)(editor.doc, editor.selection);
|
|
1615
2198
|
}, [editor.doc, editor.selection, index]);
|
|
1616
|
-
return /* @__PURE__ */ (0,
|
|
1617
|
-
/* @__PURE__ */ (0,
|
|
2199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ed-table-wrap", children: [
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1618
2201
|
"table",
|
|
1619
2202
|
{
|
|
1620
2203
|
ref: tableRef,
|
|
@@ -1622,10 +2205,10 @@ function TableView({ block, index, tableFragment }) {
|
|
|
1622
2205
|
"data-block-type": "table",
|
|
1623
2206
|
className: "ed-block ed-table",
|
|
1624
2207
|
children: [
|
|
1625
|
-
widths && /* @__PURE__ */ (0,
|
|
1626
|
-
/* @__PURE__ */ (0,
|
|
2208
|
+
widths && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("colgroup", { children: widths.map((w, c) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("col", { style: w != null ? { width: `${w}px` } : void 0 }, c)) }),
|
|
2209
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: Array.from({ length: rowEnd - rowStart }, (_, i) => {
|
|
1627
2210
|
const r = rowStart + i;
|
|
1628
|
-
return /* @__PURE__ */ (0,
|
|
2211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tr", { "data-cell-row": r, children: Array.from({ length: cols }, (_2, c) => {
|
|
1629
2212
|
const flat = r * cols + c;
|
|
1630
2213
|
const cell = cells[flat];
|
|
1631
2214
|
if (cell?.attrs.covered === true) return null;
|
|
@@ -1633,7 +2216,7 @@ function TableView({ block, index, tableFragment }) {
|
|
|
1633
2216
|
const colspan = spanAttr(cell?.attrs.colspan);
|
|
1634
2217
|
const delta = cell?.delta ?? [];
|
|
1635
2218
|
const inRect = rect !== null && r >= rect.top && r <= rect.bottom && c >= rect.left && c <= rect.right;
|
|
1636
|
-
return /* @__PURE__ */ (0,
|
|
2219
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1637
2220
|
"td",
|
|
1638
2221
|
{
|
|
1639
2222
|
"data-cell-index": flat,
|
|
@@ -1643,6 +2226,7 @@ function TableView({ block, index, tableFragment }) {
|
|
|
1643
2226
|
"data-cell-colspan": colspan,
|
|
1644
2227
|
rowSpan: rowspan > 1 ? rowspan : void 0,
|
|
1645
2228
|
colSpan: colspan > 1 ? colspan : void 0,
|
|
2229
|
+
style: cell?.attrs.align ? { textAlign: cell.attrs.align } : void 0,
|
|
1646
2230
|
className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
|
|
1647
2231
|
children: renderInline(delta, `t${index}-c${flat}`)
|
|
1648
2232
|
},
|
|
@@ -1653,7 +2237,7 @@ function TableView({ block, index, tableFragment }) {
|
|
|
1653
2237
|
]
|
|
1654
2238
|
}
|
|
1655
2239
|
),
|
|
1656
|
-
isFirstFragment && /* @__PURE__ */ (0,
|
|
2240
|
+
isFirstFragment && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableResizeOverlay, { tableRef, blockIndex: index, cols })
|
|
1657
2241
|
] });
|
|
1658
2242
|
}
|
|
1659
2243
|
function readColWidths(raw, cols) {
|
|
@@ -1675,7 +2259,7 @@ function clampPositive(n) {
|
|
|
1675
2259
|
}
|
|
1676
2260
|
|
|
1677
2261
|
// src/usePagination.ts
|
|
1678
|
-
var
|
|
2262
|
+
var import_react11 = require("react");
|
|
1679
2263
|
var A4_PAGE = {
|
|
1680
2264
|
width: 794,
|
|
1681
2265
|
height: 1123,
|
|
@@ -1684,8 +2268,9 @@ var A4_PAGE = {
|
|
|
1684
2268
|
marginLeft: 96,
|
|
1685
2269
|
marginRight: 96
|
|
1686
2270
|
};
|
|
1687
|
-
function contentHeight(g) {
|
|
1688
|
-
|
|
2271
|
+
function contentHeight(g, pageIndex = 0) {
|
|
2272
|
+
const extra = pageIndex === 0 ? g.firstPageExtraTop ?? 0 : 0;
|
|
2273
|
+
return g.height - g.marginTop - g.marginBottom - extra;
|
|
1689
2274
|
}
|
|
1690
2275
|
function contentWidth(g) {
|
|
1691
2276
|
return g.width - g.marginLeft - g.marginRight;
|
|
@@ -1700,17 +2285,22 @@ function defaultPageLayout(topLevelCount) {
|
|
|
1700
2285
|
};
|
|
1701
2286
|
}
|
|
1702
2287
|
function usePageLayout(rootRef, geometry, topLevelCount, deps) {
|
|
1703
|
-
const [phase, setPhase] = (0,
|
|
1704
|
-
const [layout, setLayout] = (0,
|
|
1705
|
-
const lastDepsRef = (0,
|
|
1706
|
-
|
|
1707
|
-
|
|
2288
|
+
const [phase, setPhase] = (0, import_react11.useState)("measure");
|
|
2289
|
+
const [layout, setLayout] = (0, import_react11.useState)(() => defaultPageLayout(topLevelCount));
|
|
2290
|
+
const lastDepsRef = (0, import_react11.useRef)(null);
|
|
2291
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2292
|
+
const currentDeps = [...deps, topLevelCount, geometry];
|
|
2293
|
+
if (lastDepsRef.current !== null && shallowArrayEqual(lastDepsRef.current, currentDeps)) {
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
1708
2296
|
lastDepsRef.current = currentDeps;
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
2297
|
+
setLayout((prev) => {
|
|
2298
|
+
const next = defaultPageLayout(topLevelCount);
|
|
2299
|
+
return layoutsDeepEqual(prev, next) ? prev : next;
|
|
2300
|
+
});
|
|
2301
|
+
setPhase("measure");
|
|
2302
|
+
});
|
|
2303
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
1714
2304
|
if (phase !== "measure") return;
|
|
1715
2305
|
const root = rootRef.current;
|
|
1716
2306
|
if (!root) return;
|
|
@@ -1719,19 +2309,20 @@ function usePageLayout(rootRef, geometry, topLevelCount, deps) {
|
|
|
1719
2309
|
if (!layoutsDeepEqual(layout, next)) setLayout(next);
|
|
1720
2310
|
setPhase("stable");
|
|
1721
2311
|
}, [phase, layout, geometry, topLevelCount, rootRef]);
|
|
1722
|
-
return layout;
|
|
2312
|
+
return { layout, phase };
|
|
1723
2313
|
}
|
|
1724
2314
|
function isUnfragmented(layout) {
|
|
1725
2315
|
return layout.pages.length === 1 && layout.pages[0].slots.every(
|
|
1726
|
-
(s) => s.fragment === void 0 && s.tableFragment === void 0
|
|
2316
|
+
(s) => s.fragment === void 0 && s.tableFragment === void 0 && s.listFragment === void 0
|
|
1727
2317
|
);
|
|
1728
2318
|
}
|
|
1729
2319
|
function computeLayout(root, geometry, topLevelCount) {
|
|
1730
2320
|
const tops = collectTopLevelElements(root);
|
|
1731
2321
|
if (tops.length === 0) return defaultPageLayout(topLevelCount);
|
|
1732
|
-
const
|
|
2322
|
+
const limitFor = (pageIndex) => contentHeight(geometry, pageIndex);
|
|
1733
2323
|
const pages = [{ slots: [] }];
|
|
1734
2324
|
let currentPage = pages[0];
|
|
2325
|
+
let limit = limitFor(0);
|
|
1735
2326
|
let used = 0;
|
|
1736
2327
|
const cap = Math.min(tops.length, topLevelCount);
|
|
1737
2328
|
for (let i = 0; i < cap; i++) {
|
|
@@ -1743,14 +2334,23 @@ function computeLayout(root, geometry, topLevelCount) {
|
|
|
1743
2334
|
continue;
|
|
1744
2335
|
}
|
|
1745
2336
|
if (isFragmentable(el)) {
|
|
1746
|
-
const result = placeFragmentedBlock(el, i, pages, used,
|
|
2337
|
+
const result = placeFragmentedBlock(el, i, pages, used, limitFor);
|
|
1747
2338
|
currentPage = pages[pages.length - 1];
|
|
2339
|
+
limit = limitFor(pages.length - 1);
|
|
1748
2340
|
used = result.lastUsed;
|
|
1749
2341
|
continue;
|
|
1750
2342
|
}
|
|
1751
2343
|
if (isTableTopLevel(el)) {
|
|
1752
|
-
const result = placeFragmentedTable(el, i, pages, used,
|
|
2344
|
+
const result = placeFragmentedTable(el, i, pages, used, limitFor);
|
|
2345
|
+
currentPage = pages[pages.length - 1];
|
|
2346
|
+
limit = limitFor(pages.length - 1);
|
|
2347
|
+
used = result.lastUsed;
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
if (isListTopLevel(el)) {
|
|
2351
|
+
const result = placeFragmentedList(el, i, pages, used, limitFor);
|
|
1753
2352
|
currentPage = pages[pages.length - 1];
|
|
2353
|
+
limit = limitFor(pages.length - 1);
|
|
1754
2354
|
used = result.lastUsed;
|
|
1755
2355
|
continue;
|
|
1756
2356
|
}
|
|
@@ -1758,10 +2358,12 @@ function computeLayout(root, geometry, topLevelCount) {
|
|
|
1758
2358
|
currentPage.slots.push({ topLevelIndex: i });
|
|
1759
2359
|
pages.push({ slots: [] });
|
|
1760
2360
|
currentPage = pages[pages.length - 1];
|
|
2361
|
+
limit = limitFor(pages.length - 1);
|
|
1761
2362
|
used = 0;
|
|
1762
2363
|
} else {
|
|
1763
2364
|
pages.push({ slots: [] });
|
|
1764
2365
|
currentPage = pages[pages.length - 1];
|
|
2366
|
+
limit = limitFor(pages.length - 1);
|
|
1765
2367
|
currentPage.slots.push({ topLevelIndex: i });
|
|
1766
2368
|
used = h;
|
|
1767
2369
|
}
|
|
@@ -1769,7 +2371,8 @@ function computeLayout(root, geometry, topLevelCount) {
|
|
|
1769
2371
|
if (pages.length > 1 && pages[pages.length - 1].slots.length === 0) pages.pop();
|
|
1770
2372
|
return { pages };
|
|
1771
2373
|
}
|
|
1772
|
-
function placeFragmentedBlock(el, topLevelIndex, pages, startUsed,
|
|
2374
|
+
function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limitFor) {
|
|
2375
|
+
let limit = limitFor(pages.length - 1);
|
|
1773
2376
|
const totalChars = getBlockTextLength(el);
|
|
1774
2377
|
if (totalChars === 0) {
|
|
1775
2378
|
const h = elTotalHeight(el);
|
|
@@ -1777,6 +2380,7 @@ function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1777
2380
|
if (startUsed + h > limit && currentPage2.slots.length > 0) {
|
|
1778
2381
|
pages.push({ slots: [] });
|
|
1779
2382
|
currentPage2 = pages[pages.length - 1];
|
|
2383
|
+
limit = limitFor(pages.length - 1);
|
|
1780
2384
|
startUsed = 0;
|
|
1781
2385
|
}
|
|
1782
2386
|
currentPage2.slots.push({ topLevelIndex });
|
|
@@ -1789,6 +2393,7 @@ function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1789
2393
|
if (startUsed + h > limit && currentPage2.slots.length > 0) {
|
|
1790
2394
|
pages.push({ slots: [] });
|
|
1791
2395
|
currentPage2 = pages[pages.length - 1];
|
|
2396
|
+
limit = limitFor(pages.length - 1);
|
|
1792
2397
|
startUsed = 0;
|
|
1793
2398
|
}
|
|
1794
2399
|
currentPage2.slots.push({ topLevelIndex });
|
|
@@ -1803,6 +2408,7 @@ function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1803
2408
|
if (available <= 0) {
|
|
1804
2409
|
pages.push({ slots: [] });
|
|
1805
2410
|
currentPage = pages[pages.length - 1];
|
|
2411
|
+
limit = limitFor(pages.length - 1);
|
|
1806
2412
|
used = 0;
|
|
1807
2413
|
continue;
|
|
1808
2414
|
}
|
|
@@ -1819,6 +2425,7 @@ function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1819
2425
|
} else {
|
|
1820
2426
|
pages.push({ slots: [] });
|
|
1821
2427
|
currentPage = pages[pages.length - 1];
|
|
2428
|
+
limit = limitFor(pages.length - 1);
|
|
1822
2429
|
used = 0;
|
|
1823
2430
|
continue;
|
|
1824
2431
|
}
|
|
@@ -1836,6 +2443,7 @@ function placeFragmentedBlock(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1836
2443
|
if (lineIdx < lines.length) {
|
|
1837
2444
|
pages.push({ slots: [] });
|
|
1838
2445
|
currentPage = pages[pages.length - 1];
|
|
2446
|
+
limit = limitFor(pages.length - 1);
|
|
1839
2447
|
used = 0;
|
|
1840
2448
|
}
|
|
1841
2449
|
}
|
|
@@ -1924,7 +2532,8 @@ function isFragmentable(el) {
|
|
|
1924
2532
|
function isTableTopLevel(el) {
|
|
1925
2533
|
return el.querySelector(':scope > table[data-block-type="table"]') !== null;
|
|
1926
2534
|
}
|
|
1927
|
-
function placeFragmentedTable(el, topLevelIndex, pages, startUsed,
|
|
2535
|
+
function placeFragmentedTable(el, topLevelIndex, pages, startUsed, limitFor) {
|
|
2536
|
+
let limit = limitFor(pages.length - 1);
|
|
1928
2537
|
const table = el.querySelector(':scope > table[data-block-type="table"]');
|
|
1929
2538
|
const tbody = table?.querySelector(":scope > tbody");
|
|
1930
2539
|
const trs = tbody ? Array.from(tbody.children) : [];
|
|
@@ -1934,6 +2543,7 @@ function placeFragmentedTable(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1934
2543
|
if (startUsed + h > limit && currentPage2.slots.length > 0) {
|
|
1935
2544
|
pages.push({ slots: [] });
|
|
1936
2545
|
currentPage2 = pages[pages.length - 1];
|
|
2546
|
+
limit = limitFor(pages.length - 1);
|
|
1937
2547
|
startUsed = 0;
|
|
1938
2548
|
}
|
|
1939
2549
|
currentPage2.slots.push({ topLevelIndex });
|
|
@@ -1965,6 +2575,7 @@ function placeFragmentedTable(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1965
2575
|
if (available <= 0) {
|
|
1966
2576
|
pages.push({ slots: [] });
|
|
1967
2577
|
currentPage = pages[pages.length - 1];
|
|
2578
|
+
limit = limitFor(pages.length - 1);
|
|
1968
2579
|
used = 0;
|
|
1969
2580
|
continue;
|
|
1970
2581
|
}
|
|
@@ -1983,6 +2594,7 @@ function placeFragmentedTable(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
1983
2594
|
} else {
|
|
1984
2595
|
pages.push({ slots: [] });
|
|
1985
2596
|
currentPage = pages[pages.length - 1];
|
|
2597
|
+
limit = limitFor(pages.length - 1);
|
|
1986
2598
|
used = 0;
|
|
1987
2599
|
continue;
|
|
1988
2600
|
}
|
|
@@ -2000,6 +2612,77 @@ function placeFragmentedTable(el, topLevelIndex, pages, startUsed, limit) {
|
|
|
2000
2612
|
if (rowIdx < trs.length) {
|
|
2001
2613
|
pages.push({ slots: [] });
|
|
2002
2614
|
currentPage = pages[pages.length - 1];
|
|
2615
|
+
limit = limitFor(pages.length - 1);
|
|
2616
|
+
used = 0;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
return { lastUsed: used };
|
|
2620
|
+
}
|
|
2621
|
+
function isListTopLevel(el) {
|
|
2622
|
+
if (el.tagName !== "OL" && el.tagName !== "UL") return false;
|
|
2623
|
+
return el.classList.contains("ed-list");
|
|
2624
|
+
}
|
|
2625
|
+
function placeFragmentedList(el, topLevelIndex, pages, startUsed, limitFor) {
|
|
2626
|
+
let limit = limitFor(pages.length - 1);
|
|
2627
|
+
const items = [];
|
|
2628
|
+
for (const c of Array.from(el.children)) {
|
|
2629
|
+
if (c instanceof HTMLLIElement && c.classList.contains("ed-listitem")) {
|
|
2630
|
+
items.push(c);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
if (items.length === 0) {
|
|
2634
|
+
const h = elTotalHeight(el);
|
|
2635
|
+
let currentPage2 = pages[pages.length - 1];
|
|
2636
|
+
if (startUsed + h > limit && currentPage2.slots.length > 0) {
|
|
2637
|
+
pages.push({ slots: [] });
|
|
2638
|
+
currentPage2 = pages[pages.length - 1];
|
|
2639
|
+
limit = limitFor(pages.length - 1);
|
|
2640
|
+
startUsed = 0;
|
|
2641
|
+
}
|
|
2642
|
+
currentPage2.slots.push({ topLevelIndex });
|
|
2643
|
+
return { lastUsed: startUsed + h };
|
|
2644
|
+
}
|
|
2645
|
+
const heights = items.map((li) => elTotalHeight(li));
|
|
2646
|
+
const sumHeights = heights.reduce((a, b) => a + b, 0);
|
|
2647
|
+
const wrapperOverhead = Math.max(0, elTotalHeight(el) - sumHeights);
|
|
2648
|
+
let i = 0;
|
|
2649
|
+
let currentPage = pages[pages.length - 1];
|
|
2650
|
+
let used = startUsed;
|
|
2651
|
+
let fragIndex = 0;
|
|
2652
|
+
while (i < items.length) {
|
|
2653
|
+
const available = Math.max(0, limit - used);
|
|
2654
|
+
const isFirstFragment = fragIndex === 0;
|
|
2655
|
+
let bestK = -1;
|
|
2656
|
+
let runningH = isFirstFragment ? wrapperOverhead : 0;
|
|
2657
|
+
for (let k = i; k < items.length; k++) {
|
|
2658
|
+
runningH += heights[k];
|
|
2659
|
+
if (runningH <= available) bestK = k;
|
|
2660
|
+
else break;
|
|
2661
|
+
}
|
|
2662
|
+
if (bestK < 0) {
|
|
2663
|
+
if (currentPage.slots.length === 0) {
|
|
2664
|
+
bestK = i;
|
|
2665
|
+
} else {
|
|
2666
|
+
pages.push({ slots: [] });
|
|
2667
|
+
currentPage = pages[pages.length - 1];
|
|
2668
|
+
limit = limitFor(pages.length - 1);
|
|
2669
|
+
used = 0;
|
|
2670
|
+
continue;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
currentPage.slots.push({
|
|
2674
|
+
topLevelIndex,
|
|
2675
|
+
listFragment: { index: fragIndex, itemStart: i, itemEnd: bestK + 1 }
|
|
2676
|
+
});
|
|
2677
|
+
let consumed = isFirstFragment ? wrapperOverhead : 0;
|
|
2678
|
+
for (let k = i; k <= bestK; k++) consumed += heights[k];
|
|
2679
|
+
used += consumed;
|
|
2680
|
+
i = bestK + 1;
|
|
2681
|
+
fragIndex++;
|
|
2682
|
+
if (i < items.length) {
|
|
2683
|
+
pages.push({ slots: [] });
|
|
2684
|
+
currentPage = pages[pages.length - 1];
|
|
2685
|
+
limit = limitFor(pages.length - 1);
|
|
2003
2686
|
used = 0;
|
|
2004
2687
|
}
|
|
2005
2688
|
}
|
|
@@ -2075,54 +2758,62 @@ function layoutsDeepEqual(a, b) {
|
|
|
2075
2758
|
return false;
|
|
2076
2759
|
}
|
|
2077
2760
|
}
|
|
2761
|
+
const lA = sA[j].listFragment;
|
|
2762
|
+
const lB = sB[j].listFragment;
|
|
2763
|
+
if (lA || lB) {
|
|
2764
|
+
if (!lA || !lB) return false;
|
|
2765
|
+
if (lA.index !== lB.index || lA.itemStart !== lB.itemStart || lA.itemEnd !== lB.itemEnd) {
|
|
2766
|
+
return false;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2078
2769
|
}
|
|
2079
2770
|
}
|
|
2080
2771
|
return true;
|
|
2081
2772
|
}
|
|
2082
2773
|
|
|
2083
2774
|
// src/useEditor.ts
|
|
2084
|
-
var
|
|
2775
|
+
var import_react13 = require("react");
|
|
2085
2776
|
|
|
2086
2777
|
// src/usePageSettings.ts
|
|
2087
|
-
var
|
|
2778
|
+
var import_react12 = require("react");
|
|
2088
2779
|
function usePageSettings(doc) {
|
|
2089
|
-
const cacheRef = (0,
|
|
2090
|
-
const subscribe = (0,
|
|
2780
|
+
const cacheRef = (0, import_react12.useRef)(null);
|
|
2781
|
+
const subscribe = (0, import_react12.useCallback)(
|
|
2091
2782
|
(notify) => doc.observePageSettings(notify),
|
|
2092
2783
|
[doc]
|
|
2093
2784
|
);
|
|
2094
|
-
const getSnapshot = (0,
|
|
2785
|
+
const getSnapshot = (0, import_react12.useCallback)(() => {
|
|
2095
2786
|
const next = doc.getPageSettings();
|
|
2096
2787
|
const prev = cacheRef.current;
|
|
2097
2788
|
if (prev && shallowEqual(prev, next)) return prev;
|
|
2098
2789
|
cacheRef.current = next;
|
|
2099
2790
|
return next;
|
|
2100
2791
|
}, [doc]);
|
|
2101
|
-
return (0,
|
|
2792
|
+
return (0, import_react12.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
2102
2793
|
}
|
|
2103
2794
|
function shallowEqual(a, b) {
|
|
2104
|
-
return a.width === b.width && a.height === b.height && a.marginTop === b.marginTop && a.marginBottom === b.marginBottom && a.marginLeft === b.marginLeft && a.marginRight === b.marginRight && a.preset === b.preset;
|
|
2795
|
+
return a.width === b.width && a.height === b.height && a.marginTop === b.marginTop && a.marginBottom === b.marginBottom && a.marginLeft === b.marginLeft && a.marginRight === b.marginRight && a.preset === b.preset && a.systemHeaderTitle === b.systemHeaderTitle && a.systemHeaderAuthor === b.systemHeaderAuthor;
|
|
2105
2796
|
}
|
|
2106
2797
|
|
|
2107
2798
|
// src/useEditor.ts
|
|
2108
|
-
var
|
|
2799
|
+
var import_core5 = require("@sofereditor/core");
|
|
2109
2800
|
var MAX_INSERT_WIDTH = 600;
|
|
2110
2801
|
function useEditor(opts = {}) {
|
|
2111
|
-
const doc = (0,
|
|
2112
|
-
const history = (0,
|
|
2113
|
-
const [snapshot, setSnapshot] = (0,
|
|
2114
|
-
const [selection, setSelectionState] = (0,
|
|
2115
|
-
() => (0,
|
|
2802
|
+
const doc = (0, import_react13.useMemo)(() => opts.document ?? new import_core5.EditorDocument(), [opts.document]);
|
|
2803
|
+
const history = (0, import_react13.useMemo)(() => new import_core5.EditorHistory(doc), [doc]);
|
|
2804
|
+
const [snapshot, setSnapshot] = (0, import_react13.useState)(() => doc.toJSON());
|
|
2805
|
+
const [selection, setSelectionState] = (0, import_react13.useState)(
|
|
2806
|
+
() => (0, import_core5.collapsedSelection)({ blockIndex: 0, offset: 0 })
|
|
2116
2807
|
);
|
|
2117
|
-
const selectionRef = (0,
|
|
2808
|
+
const selectionRef = (0, import_react13.useRef)(selection);
|
|
2118
2809
|
selectionRef.current = selection;
|
|
2119
|
-
const pendingMarksRef = (0,
|
|
2120
|
-
const [pendingMarks, setPendingMarksState] = (0,
|
|
2121
|
-
const setPendingMarks = (0,
|
|
2810
|
+
const pendingMarksRef = (0, import_react13.useRef)({});
|
|
2811
|
+
const [pendingMarks, setPendingMarksState] = (0, import_react13.useState)({});
|
|
2812
|
+
const setPendingMarks = (0, import_react13.useCallback)((next) => {
|
|
2122
2813
|
pendingMarksRef.current = next;
|
|
2123
2814
|
setPendingMarksState(next);
|
|
2124
2815
|
}, []);
|
|
2125
|
-
(0,
|
|
2816
|
+
(0, import_react13.useEffect)(() => {
|
|
2126
2817
|
let scheduled = false;
|
|
2127
2818
|
let cancelled = false;
|
|
2128
2819
|
let frame = 0;
|
|
@@ -2149,8 +2840,8 @@ function useEditor(opts = {}) {
|
|
|
2149
2840
|
doc.ydoc.off("afterTransaction", schedule);
|
|
2150
2841
|
};
|
|
2151
2842
|
}, [doc]);
|
|
2152
|
-
const getSelection = (0,
|
|
2153
|
-
const setSelection = (0,
|
|
2843
|
+
const getSelection = (0, import_react13.useCallback)(() => selectionRef.current, []);
|
|
2844
|
+
const setSelection = (0, import_react13.useCallback)(
|
|
2154
2845
|
(sel) => {
|
|
2155
2846
|
const prev = selectionRef.current;
|
|
2156
2847
|
selectionRef.current = sel;
|
|
@@ -2165,19 +2856,19 @@ function useEditor(opts = {}) {
|
|
|
2165
2856
|
},
|
|
2166
2857
|
[]
|
|
2167
2858
|
);
|
|
2168
|
-
const ctxRef = (0,
|
|
2859
|
+
const ctxRef = (0, import_react13.useRef)({ doc, getSelection, setSelection });
|
|
2169
2860
|
ctxRef.current = { doc, getSelection, setSelection };
|
|
2170
|
-
const consumePendingMarks = (0,
|
|
2861
|
+
const consumePendingMarks = (0, import_react13.useCallback)(() => {
|
|
2171
2862
|
const current = pendingMarksRef.current;
|
|
2172
2863
|
if (Object.keys(current).length === 0) return void 0;
|
|
2173
2864
|
pendingMarksRef.current = {};
|
|
2174
2865
|
setPendingMarksState({});
|
|
2175
2866
|
return current;
|
|
2176
2867
|
}, []);
|
|
2177
|
-
const isMarkActive = (0,
|
|
2868
|
+
const isMarkActive = (0, import_react13.useCallback)(
|
|
2178
2869
|
(name, value) => {
|
|
2179
2870
|
const sel = selectionRef.current;
|
|
2180
|
-
const { start, end } = (0,
|
|
2871
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2181
2872
|
if (start.blockIndex === end.blockIndex && start.offset === end.offset) {
|
|
2182
2873
|
const pending = pendingMarksRef.current[name];
|
|
2183
2874
|
if (pending !== void 0) {
|
|
@@ -2186,7 +2877,7 @@ function useEditor(opts = {}) {
|
|
|
2186
2877
|
}
|
|
2187
2878
|
const yText2 = doc.getBlockText(start.blockIndex);
|
|
2188
2879
|
if (!yText2 || start.offset === 0) return false;
|
|
2189
|
-
return (0,
|
|
2880
|
+
return (0, import_core5.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
|
|
2190
2881
|
}
|
|
2191
2882
|
if (start.blockIndex !== end.blockIndex) {
|
|
2192
2883
|
for (let i = start.blockIndex; i <= end.blockIndex; i++) {
|
|
@@ -2195,19 +2886,19 @@ function useEditor(opts = {}) {
|
|
|
2195
2886
|
const s = i === start.blockIndex ? start.offset : 0;
|
|
2196
2887
|
const e = i === end.blockIndex ? end.offset : yText2.length;
|
|
2197
2888
|
if (s >= e) continue;
|
|
2198
|
-
if (!(0,
|
|
2889
|
+
if (!(0, import_core5.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
|
|
2199
2890
|
}
|
|
2200
2891
|
return true;
|
|
2201
2892
|
}
|
|
2202
2893
|
const yText = doc.getBlockText(start.blockIndex);
|
|
2203
2894
|
if (!yText) return false;
|
|
2204
|
-
return (0,
|
|
2895
|
+
return (0, import_core5.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
|
|
2205
2896
|
},
|
|
2206
2897
|
[doc]
|
|
2207
2898
|
);
|
|
2208
|
-
const getActiveMarks = (0,
|
|
2899
|
+
const getActiveMarks = (0, import_react13.useCallback)(() => {
|
|
2209
2900
|
const sel = selectionRef.current;
|
|
2210
|
-
const { start, end } = (0,
|
|
2901
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2211
2902
|
if (start.blockIndex !== end.blockIndex) {
|
|
2212
2903
|
return {};
|
|
2213
2904
|
}
|
|
@@ -2215,14 +2906,14 @@ function useEditor(opts = {}) {
|
|
|
2215
2906
|
if (!yText) return {};
|
|
2216
2907
|
if (start.offset === end.offset) {
|
|
2217
2908
|
if (start.offset === 0) return {};
|
|
2218
|
-
return (0,
|
|
2909
|
+
return (0, import_core5.getMarksInRange)(yText, start.offset - 1, start.offset);
|
|
2219
2910
|
}
|
|
2220
|
-
return (0,
|
|
2911
|
+
return (0, import_core5.getMarksInRange)(yText, start.offset, end.offset);
|
|
2221
2912
|
}, [doc]);
|
|
2222
|
-
const toggleMark = (0,
|
|
2913
|
+
const toggleMark = (0, import_react13.useCallback)(
|
|
2223
2914
|
(name, value) => {
|
|
2224
2915
|
const sel = selectionRef.current;
|
|
2225
|
-
const { start, end } = (0,
|
|
2916
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2226
2917
|
const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
|
|
2227
2918
|
if (isCollapsed) {
|
|
2228
2919
|
const next = { ...pendingMarksRef.current };
|
|
@@ -2235,39 +2926,39 @@ function useEditor(opts = {}) {
|
|
|
2235
2926
|
setPendingMarks(next);
|
|
2236
2927
|
return;
|
|
2237
2928
|
}
|
|
2238
|
-
(0,
|
|
2929
|
+
(0, import_core5.toggleMark)(ctxRef.current, name, value);
|
|
2239
2930
|
},
|
|
2240
2931
|
[isMarkActive, setPendingMarks]
|
|
2241
2932
|
);
|
|
2242
|
-
const setMark = (0,
|
|
2933
|
+
const setMark = (0, import_react13.useCallback)(
|
|
2243
2934
|
(name, value) => {
|
|
2244
2935
|
const sel = selectionRef.current;
|
|
2245
|
-
const { start, end } = (0,
|
|
2936
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2246
2937
|
const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
|
|
2247
2938
|
if (isCollapsed) {
|
|
2248
2939
|
setPendingMarks({ ...pendingMarksRef.current, [name]: value });
|
|
2249
2940
|
return;
|
|
2250
2941
|
}
|
|
2251
|
-
(0,
|
|
2942
|
+
(0, import_core5.setMark)(ctxRef.current, name, value);
|
|
2252
2943
|
},
|
|
2253
2944
|
[setPendingMarks]
|
|
2254
2945
|
);
|
|
2255
|
-
const removeMark = (0,
|
|
2946
|
+
const removeMark = (0, import_react13.useCallback)(
|
|
2256
2947
|
(name) => {
|
|
2257
2948
|
const sel = selectionRef.current;
|
|
2258
|
-
const { start, end } = (0,
|
|
2949
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2259
2950
|
const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
|
|
2260
2951
|
if (isCollapsed) {
|
|
2261
2952
|
setPendingMarks({ ...pendingMarksRef.current, [name]: null });
|
|
2262
2953
|
return;
|
|
2263
2954
|
}
|
|
2264
|
-
(0,
|
|
2955
|
+
(0, import_core5.removeMark)(ctxRef.current, name);
|
|
2265
2956
|
},
|
|
2266
2957
|
[setPendingMarks]
|
|
2267
2958
|
);
|
|
2268
|
-
const getBlockType = (0,
|
|
2959
|
+
const getBlockType = (0, import_react13.useCallback)(() => {
|
|
2269
2960
|
const sel = selectionRef.current;
|
|
2270
|
-
const { start, end } = (0,
|
|
2961
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2271
2962
|
const first = doc.getBlockType(start.blockIndex);
|
|
2272
2963
|
if (first === void 0) return "paragraph";
|
|
2273
2964
|
for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
|
|
@@ -2275,10 +2966,10 @@ function useEditor(opts = {}) {
|
|
|
2275
2966
|
}
|
|
2276
2967
|
return first;
|
|
2277
2968
|
}, [doc]);
|
|
2278
|
-
const getBlockAttr = (0,
|
|
2969
|
+
const getBlockAttr = (0, import_react13.useCallback)(
|
|
2279
2970
|
(key) => {
|
|
2280
2971
|
const sel = selectionRef.current;
|
|
2281
|
-
const { start, end } = (0,
|
|
2972
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2282
2973
|
const first = doc.getBlockAttrs(start.blockIndex)[key];
|
|
2283
2974
|
for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
|
|
2284
2975
|
const next = doc.getBlockAttrs(i)[key];
|
|
@@ -2288,19 +2979,32 @@ function useEditor(opts = {}) {
|
|
|
2288
2979
|
},
|
|
2289
2980
|
[doc]
|
|
2290
2981
|
);
|
|
2291
|
-
const setBlockType = (0,
|
|
2292
|
-
(0,
|
|
2982
|
+
const setBlockType = (0, import_react13.useCallback)((type, attrs) => {
|
|
2983
|
+
(0, import_core5.setBlockType)(ctxRef.current, type, attrs);
|
|
2293
2984
|
}, []);
|
|
2294
|
-
const setBlockAttr = (0,
|
|
2985
|
+
const setBlockAttr = (0, import_react13.useCallback)(
|
|
2295
2986
|
(key, value) => {
|
|
2296
|
-
(0,
|
|
2987
|
+
(0, import_core5.setBlockAttr)(ctxRef.current, key, value);
|
|
2297
2988
|
},
|
|
2298
2989
|
[]
|
|
2299
2990
|
);
|
|
2300
|
-
const
|
|
2991
|
+
const setAlign = (0, import_react13.useCallback)((value) => {
|
|
2992
|
+
const sel = selectionRef.current;
|
|
2993
|
+
const inCell = sel.focus.cellIndex != null;
|
|
2994
|
+
if (inCell) (0, import_core5.setCellAttr)(ctxRef.current, "align", value);
|
|
2995
|
+
else (0, import_core5.setBlockAttr)(ctxRef.current, "align", value);
|
|
2996
|
+
}, []);
|
|
2997
|
+
const getAlign = (0, import_react13.useCallback)(() => {
|
|
2998
|
+
const sel = selectionRef.current;
|
|
2999
|
+
if (sel.focus.cellIndex != null && doc.isTable(sel.focus.blockIndex)) {
|
|
3000
|
+
return doc.getCellAttrs(sel.focus.blockIndex, sel.focus.cellIndex).align;
|
|
3001
|
+
}
|
|
3002
|
+
return getBlockAttr("align");
|
|
3003
|
+
}, [doc, getBlockAttr]);
|
|
3004
|
+
const isListActive = (0, import_react13.useCallback)(
|
|
2301
3005
|
(kind) => {
|
|
2302
3006
|
const sel = selectionRef.current;
|
|
2303
|
-
const { start, end } = (0,
|
|
3007
|
+
const { start, end } = (0, import_core5.orderedRange)(sel);
|
|
2304
3008
|
for (let i = start.blockIndex; i <= end.blockIndex; i++) {
|
|
2305
3009
|
if (doc.getBlockType(i) !== "listItem") return false;
|
|
2306
3010
|
if (doc.getBlockAttrs(i).listKind !== kind) return false;
|
|
@@ -2309,110 +3013,116 @@ function useEditor(opts = {}) {
|
|
|
2309
3013
|
},
|
|
2310
3014
|
[doc]
|
|
2311
3015
|
);
|
|
2312
|
-
const toggleList = (0,
|
|
2313
|
-
(0,
|
|
3016
|
+
const toggleList = (0, import_react13.useCallback)((kind) => {
|
|
3017
|
+
(0, import_core5.toggleList)(ctxRef.current, kind);
|
|
2314
3018
|
}, []);
|
|
2315
|
-
const indentList = (0,
|
|
2316
|
-
(0,
|
|
3019
|
+
const indentList = (0, import_react13.useCallback)(() => {
|
|
3020
|
+
(0, import_core5.indentList)(ctxRef.current);
|
|
2317
3021
|
}, []);
|
|
2318
|
-
const dedentList = (0,
|
|
2319
|
-
(0,
|
|
3022
|
+
const dedentList = (0, import_react13.useCallback)(() => {
|
|
3023
|
+
(0, import_core5.dedentList)(ctxRef.current);
|
|
2320
3024
|
}, []);
|
|
2321
|
-
const splitListItem = (0,
|
|
2322
|
-
return (0,
|
|
3025
|
+
const splitListItem = (0, import_react13.useCallback)(() => {
|
|
3026
|
+
return (0, import_core5.splitListItem)(ctxRef.current);
|
|
2323
3027
|
}, []);
|
|
2324
|
-
const isInTable = (0,
|
|
3028
|
+
const isInTable = (0, import_react13.useCallback)(() => {
|
|
2325
3029
|
return selectionRef.current.focus.cellIndex != null;
|
|
2326
3030
|
}, []);
|
|
2327
|
-
const getTableLocation = (0,
|
|
2328
|
-
return (0,
|
|
3031
|
+
const getTableLocation = (0, import_react13.useCallback)(() => {
|
|
3032
|
+
return (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2329
3033
|
}, [doc]);
|
|
2330
|
-
const insertTable = (0,
|
|
2331
|
-
(0,
|
|
3034
|
+
const insertTable = (0, import_react13.useCallback)((rows, cols) => {
|
|
3035
|
+
(0, import_core5.insertTable)(ctxRef.current, rows, cols);
|
|
2332
3036
|
}, []);
|
|
2333
|
-
const deleteTable = (0,
|
|
3037
|
+
const deleteTable = (0, import_react13.useCallback)((blockIndex) => {
|
|
2334
3038
|
const idx = blockIndex ?? selectionRef.current.focus.blockIndex;
|
|
2335
|
-
(0,
|
|
3039
|
+
(0, import_core5.deleteTable)(ctxRef.current, idx);
|
|
2336
3040
|
}, []);
|
|
2337
|
-
const insertRowAbove = (0,
|
|
2338
|
-
const loc = (0,
|
|
3041
|
+
const insertRowAbove = (0, import_react13.useCallback)(() => {
|
|
3042
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2339
3043
|
if (!loc) return;
|
|
2340
|
-
(0,
|
|
3044
|
+
(0, import_core5.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
|
|
2341
3045
|
}, [doc]);
|
|
2342
|
-
const insertRowBelow = (0,
|
|
2343
|
-
const loc = (0,
|
|
3046
|
+
const insertRowBelow = (0, import_react13.useCallback)(() => {
|
|
3047
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2344
3048
|
if (!loc) return;
|
|
2345
|
-
(0,
|
|
3049
|
+
(0, import_core5.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
|
|
2346
3050
|
}, [doc]);
|
|
2347
|
-
const deleteCurrentRow = (0,
|
|
2348
|
-
const loc = (0,
|
|
3051
|
+
const deleteCurrentRow = (0, import_react13.useCallback)(() => {
|
|
3052
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2349
3053
|
if (!loc) return;
|
|
2350
|
-
(0,
|
|
3054
|
+
(0, import_core5.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
|
|
2351
3055
|
}, [doc]);
|
|
2352
|
-
const insertColumnLeft = (0,
|
|
2353
|
-
const loc = (0,
|
|
3056
|
+
const insertColumnLeft = (0, import_react13.useCallback)(() => {
|
|
3057
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2354
3058
|
if (!loc) return;
|
|
2355
|
-
(0,
|
|
3059
|
+
(0, import_core5.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
|
|
2356
3060
|
}, [doc]);
|
|
2357
|
-
const insertColumnRight = (0,
|
|
2358
|
-
const loc = (0,
|
|
3061
|
+
const insertColumnRight = (0, import_react13.useCallback)(() => {
|
|
3062
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2359
3063
|
if (!loc) return;
|
|
2360
|
-
(0,
|
|
3064
|
+
(0, import_core5.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
|
|
2361
3065
|
}, [doc]);
|
|
2362
|
-
const deleteCurrentColumn = (0,
|
|
2363
|
-
const loc = (0,
|
|
3066
|
+
const deleteCurrentColumn = (0, import_react13.useCallback)(() => {
|
|
3067
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2364
3068
|
if (!loc) return;
|
|
2365
|
-
(0,
|
|
3069
|
+
(0, import_core5.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
|
|
2366
3070
|
}, [doc]);
|
|
2367
|
-
const moveToNextCell = (0,
|
|
2368
|
-
(0,
|
|
3071
|
+
const moveToNextCell = (0, import_react13.useCallback)(() => {
|
|
3072
|
+
(0, import_core5.moveToNextCell)(ctxRef.current);
|
|
2369
3073
|
}, []);
|
|
2370
|
-
const moveToPrevCell = (0,
|
|
2371
|
-
(0,
|
|
3074
|
+
const moveToPrevCell = (0, import_react13.useCallback)(() => {
|
|
3075
|
+
(0, import_core5.moveToPrevCell)(ctxRef.current);
|
|
2372
3076
|
}, []);
|
|
2373
|
-
const mergeRight = (0,
|
|
2374
|
-
const loc = (0,
|
|
3077
|
+
const mergeRight = (0, import_react13.useCallback)(() => {
|
|
3078
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2375
3079
|
if (!loc) return false;
|
|
2376
|
-
return (0,
|
|
3080
|
+
return (0, import_core5.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
|
|
2377
3081
|
}, [doc]);
|
|
2378
|
-
const mergeDown = (0,
|
|
2379
|
-
const loc = (0,
|
|
3082
|
+
const mergeDown = (0, import_react13.useCallback)(() => {
|
|
3083
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2380
3084
|
if (!loc) return false;
|
|
2381
|
-
return (0,
|
|
3085
|
+
return (0, import_core5.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
|
|
2382
3086
|
}, [doc]);
|
|
2383
|
-
const splitCell = (0,
|
|
2384
|
-
const loc = (0,
|
|
3087
|
+
const splitCell = (0, import_react13.useCallback)(() => {
|
|
3088
|
+
const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
|
|
2385
3089
|
if (!loc) return false;
|
|
2386
|
-
return (0,
|
|
3090
|
+
return (0, import_core5.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
|
|
2387
3091
|
}, [doc]);
|
|
2388
|
-
const setColumnWidth = (0,
|
|
3092
|
+
const setColumnWidth = (0, import_react13.useCallback)(
|
|
2389
3093
|
(blockIndex, col, widthPx) => {
|
|
2390
|
-
(0,
|
|
3094
|
+
(0, import_core5.setColumnWidth)(ctxRef.current, blockIndex, col, widthPx);
|
|
2391
3095
|
},
|
|
2392
3096
|
[]
|
|
2393
3097
|
);
|
|
2394
|
-
const getTableRect = (0,
|
|
2395
|
-
() => (0,
|
|
3098
|
+
const getTableRect = (0, import_react13.useCallback)(
|
|
3099
|
+
() => (0, import_core5.tableRectSelection)(doc, selectionRef.current),
|
|
2396
3100
|
[doc]
|
|
2397
3101
|
);
|
|
2398
|
-
const hasTableRectSelection = (0,
|
|
2399
|
-
return (0,
|
|
3102
|
+
const hasTableRectSelection = (0, import_react13.useCallback)(() => {
|
|
3103
|
+
return (0, import_core5.tableRectSelection)(doc, selectionRef.current) !== null;
|
|
2400
3104
|
}, [doc]);
|
|
2401
|
-
const mergeSelection = (0,
|
|
2402
|
-
return (0,
|
|
3105
|
+
const mergeSelection = (0, import_react13.useCallback)(() => {
|
|
3106
|
+
return (0, import_core5.mergeSelection)(ctxRef.current);
|
|
2403
3107
|
}, []);
|
|
2404
|
-
const insertImage = (0,
|
|
2405
|
-
(0,
|
|
3108
|
+
const insertImage = (0, import_react13.useCallback)((embed) => {
|
|
3109
|
+
(0, import_core5.insertImage)(ctxRef.current, embed);
|
|
2406
3110
|
}, []);
|
|
2407
|
-
const setImageAttrs = (0,
|
|
3111
|
+
const setImageAttrs = (0, import_react13.useCallback)(
|
|
2408
3112
|
(blockIndex, offset, partial, cellIndex, newOffset) => {
|
|
2409
|
-
(0,
|
|
3113
|
+
(0, import_core5.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
|
|
3114
|
+
},
|
|
3115
|
+
[]
|
|
3116
|
+
);
|
|
3117
|
+
const moveEmbedAnchor = (0, import_react13.useCallback)(
|
|
3118
|
+
(from, to, newOffsetX, newOffsetY) => {
|
|
3119
|
+
(0, import_core5.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
|
|
2410
3120
|
},
|
|
2411
3121
|
[]
|
|
2412
3122
|
);
|
|
2413
|
-
const uploadImageRef = (0,
|
|
3123
|
+
const uploadImageRef = (0, import_react13.useRef)(opts.uploadImage);
|
|
2414
3124
|
uploadImageRef.current = opts.uploadImage;
|
|
2415
|
-
const insertImageFromFile = (0,
|
|
3125
|
+
const insertImageFromFile = (0, import_react13.useCallback)(async (file) => {
|
|
2416
3126
|
if (!file.type.startsWith("image/")) return;
|
|
2417
3127
|
const dataUrl = await readAsDataURL(file);
|
|
2418
3128
|
const dims = await readImageDimensions(dataUrl);
|
|
@@ -2424,9 +3134,9 @@ function useEditor(opts = {}) {
|
|
|
2424
3134
|
}
|
|
2425
3135
|
const upload = uploadImageRef.current;
|
|
2426
3136
|
const src = upload ? await upload(file) : dataUrl;
|
|
2427
|
-
(0,
|
|
3137
|
+
(0, import_core5.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
|
|
2428
3138
|
}, []);
|
|
2429
|
-
const getSelectedEmbed = (0,
|
|
3139
|
+
const getSelectedEmbed = (0, import_react13.useCallback)(() => {
|
|
2430
3140
|
const sel = selectionRef.current;
|
|
2431
3141
|
if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;
|
|
2432
3142
|
if ((sel.anchor.cellIndex ?? -1) !== (sel.focus.cellIndex ?? -1)) return null;
|
|
@@ -2443,7 +3153,7 @@ function useEditor(opts = {}) {
|
|
|
2443
3153
|
cursor += op.insert.length;
|
|
2444
3154
|
continue;
|
|
2445
3155
|
}
|
|
2446
|
-
if (cursor === start && (0,
|
|
3156
|
+
if (cursor === start && (0, import_core5.isImageEmbed)(op.insert)) {
|
|
2447
3157
|
return {
|
|
2448
3158
|
blockIndex: sel.anchor.blockIndex,
|
|
2449
3159
|
cellIndex: sel.anchor.cellIndex,
|
|
@@ -2455,39 +3165,48 @@ function useEditor(opts = {}) {
|
|
|
2455
3165
|
}
|
|
2456
3166
|
return null;
|
|
2457
3167
|
}, [doc]);
|
|
2458
|
-
const [linkRequest, setLinkRequest] = (0,
|
|
2459
|
-
const
|
|
3168
|
+
const [linkRequest, setLinkRequest] = (0, import_react13.useState)(null);
|
|
3169
|
+
const linkRequestRef = (0, import_react13.useRef)(null);
|
|
3170
|
+
const requestLink = (0, import_react13.useCallback)((initialHref = "") => {
|
|
2460
3171
|
return new Promise((resolve) => {
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
const resolveLinkRequest = (0, import_react11.useCallback)((href) => {
|
|
2465
|
-
setLinkRequest((prev) => {
|
|
2466
|
-
if (prev) prev.resolve(href);
|
|
2467
|
-
return null;
|
|
3172
|
+
const req = { initialHref, resolve, selection: selectionRef.current };
|
|
3173
|
+
linkRequestRef.current = req;
|
|
3174
|
+
setLinkRequest(req);
|
|
2468
3175
|
});
|
|
2469
3176
|
}, []);
|
|
3177
|
+
const resolveLinkRequest = (0, import_react13.useCallback)(
|
|
3178
|
+
(href) => {
|
|
3179
|
+
const req = linkRequestRef.current;
|
|
3180
|
+
linkRequestRef.current = null;
|
|
3181
|
+
setLinkRequest(null);
|
|
3182
|
+
if (req) {
|
|
3183
|
+
setSelection(req.selection);
|
|
3184
|
+
req.resolve(href);
|
|
3185
|
+
}
|
|
3186
|
+
},
|
|
3187
|
+
[setSelection]
|
|
3188
|
+
);
|
|
2470
3189
|
const pageSettings = usePageSettings(doc);
|
|
2471
|
-
const setPageSettings = (0,
|
|
3190
|
+
const setPageSettings = (0, import_react13.useCallback)(
|
|
2472
3191
|
(partial) => {
|
|
2473
3192
|
doc.setPageSettings(partial);
|
|
2474
3193
|
},
|
|
2475
3194
|
[doc]
|
|
2476
3195
|
);
|
|
2477
|
-
const [pageConfigRequest, setPageConfigRequest] = (0,
|
|
2478
|
-
const requestPageConfig = (0,
|
|
3196
|
+
const [pageConfigRequest, setPageConfigRequest] = (0, import_react13.useState)(null);
|
|
3197
|
+
const requestPageConfig = (0, import_react13.useCallback)(() => {
|
|
2479
3198
|
return new Promise((resolve) => {
|
|
2480
3199
|
setPageConfigRequest({ initial: doc.getPageSettings(), resolve });
|
|
2481
3200
|
});
|
|
2482
3201
|
}, [doc]);
|
|
2483
|
-
const resolvePageConfigRequest = (0,
|
|
3202
|
+
const resolvePageConfigRequest = (0, import_react13.useCallback)((applied) => {
|
|
2484
3203
|
setPageConfigRequest((prev) => {
|
|
2485
3204
|
if (prev) prev.resolve(applied);
|
|
2486
3205
|
return null;
|
|
2487
3206
|
});
|
|
2488
3207
|
}, []);
|
|
2489
|
-
const [imageCaptionRequest, setImageCaptionRequest] = (0,
|
|
2490
|
-
const requestImageCaption = (0,
|
|
3208
|
+
const [imageCaptionRequest, setImageCaptionRequest] = (0, import_react13.useState)(null);
|
|
3209
|
+
const requestImageCaption = (0, import_react13.useCallback)(
|
|
2491
3210
|
(initialCaption = "", initialAlign = "center") => {
|
|
2492
3211
|
return new Promise((resolve) => {
|
|
2493
3212
|
setImageCaptionRequest({ initialCaption, initialAlign, resolve });
|
|
@@ -2495,7 +3214,7 @@ function useEditor(opts = {}) {
|
|
|
2495
3214
|
},
|
|
2496
3215
|
[]
|
|
2497
3216
|
);
|
|
2498
|
-
const resolveImageCaptionRequest = (0,
|
|
3217
|
+
const resolveImageCaptionRequest = (0, import_react13.useCallback)((result) => {
|
|
2499
3218
|
setImageCaptionRequest((prev) => {
|
|
2500
3219
|
if (prev) prev.resolve(result);
|
|
2501
3220
|
return null;
|
|
@@ -2519,6 +3238,8 @@ function useEditor(opts = {}) {
|
|
|
2519
3238
|
getBlockAttr,
|
|
2520
3239
|
setBlockType,
|
|
2521
3240
|
setBlockAttr,
|
|
3241
|
+
setAlign,
|
|
3242
|
+
getAlign,
|
|
2522
3243
|
isListActive,
|
|
2523
3244
|
toggleList,
|
|
2524
3245
|
indentList,
|
|
@@ -2548,6 +3269,7 @@ function useEditor(opts = {}) {
|
|
|
2548
3269
|
mergeSelection,
|
|
2549
3270
|
insertImage,
|
|
2550
3271
|
setImageAttrs,
|
|
3272
|
+
moveEmbedAnchor,
|
|
2551
3273
|
insertImageFromFile,
|
|
2552
3274
|
getSelectedEmbed,
|
|
2553
3275
|
pageSettings,
|
|
@@ -2589,54 +3311,99 @@ function sameValue(a, b) {
|
|
|
2589
3311
|
}
|
|
2590
3312
|
|
|
2591
3313
|
// src/Editor.tsx
|
|
2592
|
-
var
|
|
3314
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2593
3315
|
var defaultFooter = ({ pageNumber, pageCount }) => `${pageNumber} / ${pageCount}`;
|
|
2594
3316
|
function Editor({
|
|
2595
3317
|
editor: providedEditor,
|
|
2596
3318
|
className,
|
|
2597
3319
|
pageGeometry,
|
|
2598
3320
|
renderPageHeader,
|
|
2599
|
-
renderPageFooter = defaultFooter
|
|
3321
|
+
renderPageFooter = defaultFooter,
|
|
3322
|
+
awareness
|
|
2600
3323
|
}) {
|
|
2601
3324
|
const internal = useEditor();
|
|
2602
3325
|
const editor = providedEditor ?? internal;
|
|
2603
3326
|
const { doc, history, snapshot, getSelection, setSelection } = editor;
|
|
2604
|
-
const rootRef = (0,
|
|
2605
|
-
const isComposingRef = (0,
|
|
2606
|
-
const
|
|
2607
|
-
const
|
|
3327
|
+
const rootRef = (0, import_react14.useRef)(null);
|
|
3328
|
+
const isComposingRef = (0, import_react14.useRef)(false);
|
|
3329
|
+
const [hoveredBehind, setHoveredBehind] = (0, import_react14.useState)(null);
|
|
3330
|
+
const hoveredBehindRef = (0, import_react14.useRef)(null);
|
|
3331
|
+
const [hoveredLink, setHoveredLink] = (0, import_react14.useState)(null);
|
|
3332
|
+
const hoveredLinkElRef = (0, import_react14.useRef)(null);
|
|
3333
|
+
const suppressSelectionSyncRef = (0, import_react14.useRef)(false);
|
|
3334
|
+
(0, import_react14.useEffect)(() => {
|
|
3335
|
+
if (!awareness) return;
|
|
3336
|
+
const root = rootRef.current;
|
|
3337
|
+
if (!root) return;
|
|
3338
|
+
let raf = null;
|
|
3339
|
+
const publish = () => {
|
|
3340
|
+
raf = null;
|
|
3341
|
+
const sel = readDomSelection(root);
|
|
3342
|
+
awareness.setLocalStateField(
|
|
3343
|
+
"cursor",
|
|
3344
|
+
sel ? (0, import_core6.encodeSelection)(doc, sel) ?? null : null
|
|
3345
|
+
);
|
|
3346
|
+
};
|
|
3347
|
+
const onSelChange = () => {
|
|
3348
|
+
const s = document.getSelection();
|
|
3349
|
+
if (!s || s.rangeCount === 0) return;
|
|
3350
|
+
if (s.anchorNode && !root.contains(s.anchorNode)) return;
|
|
3351
|
+
if (raf != null) return;
|
|
3352
|
+
raf = requestAnimationFrame(publish);
|
|
3353
|
+
};
|
|
3354
|
+
const onBlur = () => awareness.setLocalStateField("cursor", null);
|
|
3355
|
+
document.addEventListener("selectionchange", onSelChange);
|
|
3356
|
+
root.addEventListener("blur", onBlur, true);
|
|
3357
|
+
return () => {
|
|
3358
|
+
document.removeEventListener("selectionchange", onSelChange);
|
|
3359
|
+
root.removeEventListener("blur", onBlur, true);
|
|
3360
|
+
if (raf != null) cancelAnimationFrame(raf);
|
|
3361
|
+
awareness.setLocalStateField("cursor", null);
|
|
3362
|
+
};
|
|
3363
|
+
}, [awareness, doc]);
|
|
3364
|
+
const ctxRef = (0, import_react14.useRef)({ doc, getSelection, setSelection });
|
|
2608
3365
|
ctxRef.current = { doc, getSelection, setSelection };
|
|
2609
|
-
const historyRef = (0,
|
|
3366
|
+
const historyRef = (0, import_react14.useRef)(history);
|
|
2610
3367
|
historyRef.current = history;
|
|
2611
|
-
const editorRef = (0,
|
|
3368
|
+
const editorRef = (0, import_react14.useRef)(editor);
|
|
2612
3369
|
editorRef.current = editor;
|
|
2613
|
-
(0,
|
|
3370
|
+
(0, import_react14.useLayoutEffect)(() => {
|
|
2614
3371
|
const root = rootRef.current;
|
|
2615
3372
|
if (!root) return;
|
|
2616
3373
|
if (isComposingRef.current) return;
|
|
2617
3374
|
if (document.activeElement !== root) return;
|
|
2618
3375
|
const current = readDomSelection(root);
|
|
2619
3376
|
if (current && selectionsEqual(current, editor.selection)) return;
|
|
3377
|
+
if (isTableRectSelection(editor.selection)) {
|
|
3378
|
+
applyDomSelection(root, editor.selection);
|
|
3379
|
+
suppressSelectionSyncRef.current = false;
|
|
3380
|
+
return;
|
|
3381
|
+
}
|
|
2620
3382
|
suppressSelectionSyncRef.current = true;
|
|
2621
3383
|
applyDomSelection(root, editor.selection);
|
|
2622
|
-
queueMicrotask(() => {
|
|
2623
|
-
suppressSelectionSyncRef.current = false;
|
|
2624
|
-
});
|
|
2625
3384
|
});
|
|
2626
|
-
(0,
|
|
3385
|
+
(0, import_react14.useEffect)(() => {
|
|
2627
3386
|
const root = rootRef.current;
|
|
2628
3387
|
if (!root) return;
|
|
2629
3388
|
const handler = () => {
|
|
2630
|
-
if (suppressSelectionSyncRef.current) return;
|
|
2631
3389
|
if (isComposingRef.current) return;
|
|
2632
|
-
if (document.activeElement !== root)
|
|
3390
|
+
if (document.activeElement !== root) {
|
|
3391
|
+
suppressSelectionSyncRef.current = false;
|
|
3392
|
+
return;
|
|
3393
|
+
}
|
|
2633
3394
|
const modelSel = readDomSelection(root);
|
|
3395
|
+
if (suppressSelectionSyncRef.current) {
|
|
3396
|
+
if (modelSel && selectionsEqual(modelSel, editorRef.current.getSelection())) {
|
|
3397
|
+
suppressSelectionSyncRef.current = false;
|
|
3398
|
+
}
|
|
3399
|
+
return;
|
|
3400
|
+
}
|
|
2634
3401
|
if (modelSel) setSelection(modelSel);
|
|
2635
3402
|
};
|
|
2636
3403
|
document.addEventListener("selectionchange", handler);
|
|
2637
3404
|
return () => document.removeEventListener("selectionchange", handler);
|
|
2638
3405
|
}, [setSelection]);
|
|
2639
|
-
(0,
|
|
3406
|
+
(0, import_react14.useEffect)(() => {
|
|
2640
3407
|
const root = rootRef.current;
|
|
2641
3408
|
if (!root) return;
|
|
2642
3409
|
let drag = null;
|
|
@@ -2707,7 +3474,7 @@ function Editor({
|
|
|
2707
3474
|
document.removeEventListener("pointerup", onPointerUp);
|
|
2708
3475
|
};
|
|
2709
3476
|
}, []);
|
|
2710
|
-
(0,
|
|
3477
|
+
(0, import_react14.useEffect)(() => {
|
|
2711
3478
|
const root = rootRef.current;
|
|
2712
3479
|
if (!root) return;
|
|
2713
3480
|
const onDragOver = (e) => {
|
|
@@ -2745,7 +3512,7 @@ function Editor({
|
|
|
2745
3512
|
root.removeEventListener("drop", onDrop);
|
|
2746
3513
|
};
|
|
2747
3514
|
}, []);
|
|
2748
|
-
(0,
|
|
3515
|
+
(0, import_react14.useEffect)(() => {
|
|
2749
3516
|
const root = rootRef.current;
|
|
2750
3517
|
if (!root) return;
|
|
2751
3518
|
const onPointerDown = (e) => {
|
|
@@ -2773,7 +3540,95 @@ function Editor({
|
|
|
2773
3540
|
root.addEventListener("pointerdown", onPointerDown);
|
|
2774
3541
|
return () => root.removeEventListener("pointerdown", onPointerDown);
|
|
2775
3542
|
}, []);
|
|
2776
|
-
(0,
|
|
3543
|
+
(0, import_react14.useEffect)(() => {
|
|
3544
|
+
const root = rootRef.current;
|
|
3545
|
+
if (!root) return;
|
|
3546
|
+
const same = (a, b) => a === b || !!a && !!b && a.blockIndex === b.blockIndex && a.offset === b.offset && (a.cellIndex ?? -1) === (b.cellIndex ?? -1);
|
|
3547
|
+
const set = (next) => {
|
|
3548
|
+
if (same(next, hoveredBehindRef.current)) return;
|
|
3549
|
+
hoveredBehindRef.current = next;
|
|
3550
|
+
setHoveredBehind(next);
|
|
3551
|
+
};
|
|
3552
|
+
let raf = 0;
|
|
3553
|
+
const onMove = (e) => {
|
|
3554
|
+
if (raf) return;
|
|
3555
|
+
const x = e.clientX;
|
|
3556
|
+
const y = e.clientY;
|
|
3557
|
+
raf = requestAnimationFrame(() => {
|
|
3558
|
+
raf = 0;
|
|
3559
|
+
const imgs = root.querySelectorAll(
|
|
3560
|
+
'img[data-embed="image"][data-embed-layout="behind"]'
|
|
3561
|
+
);
|
|
3562
|
+
let hit = null;
|
|
3563
|
+
for (const img of imgs) {
|
|
3564
|
+
const r = img.getBoundingClientRect();
|
|
3565
|
+
if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) {
|
|
3566
|
+
hit = img;
|
|
3567
|
+
break;
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
if (!hit) {
|
|
3571
|
+
set(null);
|
|
3572
|
+
return;
|
|
3573
|
+
}
|
|
3574
|
+
const blockEl = hit.closest("[data-block-index]");
|
|
3575
|
+
const offsetAttr = hit.dataset.embedOffset;
|
|
3576
|
+
if (!blockEl || offsetAttr == null) {
|
|
3577
|
+
set(null);
|
|
3578
|
+
return;
|
|
3579
|
+
}
|
|
3580
|
+
const blockIndex = Number.parseInt(blockEl.dataset.blockIndex, 10);
|
|
3581
|
+
const fragmentStart = Number.parseInt(blockEl.dataset.fragmentStart ?? "0", 10) || 0;
|
|
3582
|
+
const cellEl = hit.closest("[data-cell-index]");
|
|
3583
|
+
const cellIndex = cellEl ? Number.parseInt(cellEl.dataset.cellIndex, 10) : void 0;
|
|
3584
|
+
set({ blockIndex, offset: fragmentStart + Number.parseInt(offsetAttr, 10), cellIndex });
|
|
3585
|
+
});
|
|
3586
|
+
};
|
|
3587
|
+
const onLeave = () => set(null);
|
|
3588
|
+
root.addEventListener("pointermove", onMove);
|
|
3589
|
+
root.addEventListener("pointerleave", onLeave);
|
|
3590
|
+
return () => {
|
|
3591
|
+
root.removeEventListener("pointermove", onMove);
|
|
3592
|
+
root.removeEventListener("pointerleave", onLeave);
|
|
3593
|
+
if (raf) cancelAnimationFrame(raf);
|
|
3594
|
+
};
|
|
3595
|
+
}, []);
|
|
3596
|
+
(0, import_react14.useEffect)(() => {
|
|
3597
|
+
const root = rootRef.current;
|
|
3598
|
+
if (!root) return;
|
|
3599
|
+
const clear = () => {
|
|
3600
|
+
if (hoveredLinkElRef.current) {
|
|
3601
|
+
hoveredLinkElRef.current = null;
|
|
3602
|
+
setHoveredLink(null);
|
|
3603
|
+
}
|
|
3604
|
+
};
|
|
3605
|
+
const onOver = (e) => {
|
|
3606
|
+
const target = e.target;
|
|
3607
|
+
const a = target?.closest?.("a[href]");
|
|
3608
|
+
if (a && root.contains(a)) {
|
|
3609
|
+
if (hoveredLinkElRef.current === a) return;
|
|
3610
|
+
hoveredLinkElRef.current = a;
|
|
3611
|
+
const r = a.getBoundingClientRect();
|
|
3612
|
+
setHoveredLink({
|
|
3613
|
+
href: a.getAttribute("href") ?? "",
|
|
3614
|
+
rect: { top: r.top, left: r.left, bottom: r.bottom, width: r.width }
|
|
3615
|
+
});
|
|
3616
|
+
} else {
|
|
3617
|
+
clear();
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
root.addEventListener("mouseover", onOver);
|
|
3621
|
+
root.addEventListener("mouseleave", clear);
|
|
3622
|
+
root.addEventListener("scroll", clear, true);
|
|
3623
|
+
window.addEventListener("scroll", clear, true);
|
|
3624
|
+
return () => {
|
|
3625
|
+
root.removeEventListener("mouseover", onOver);
|
|
3626
|
+
root.removeEventListener("mouseleave", clear);
|
|
3627
|
+
root.removeEventListener("scroll", clear, true);
|
|
3628
|
+
window.removeEventListener("scroll", clear, true);
|
|
3629
|
+
};
|
|
3630
|
+
}, []);
|
|
3631
|
+
(0, import_react14.useEffect)(() => {
|
|
2777
3632
|
const root = rootRef.current;
|
|
2778
3633
|
if (!root) return;
|
|
2779
3634
|
const handler = (e) => {
|
|
@@ -2787,12 +3642,37 @@ function Editor({
|
|
|
2787
3642
|
const data = e.data ?? "";
|
|
2788
3643
|
if (data.length > 0) {
|
|
2789
3644
|
e.preventDefault();
|
|
2790
|
-
(0,
|
|
3645
|
+
(0, import_core6.insertText)(ctx, data, ed.consumePendingMarks());
|
|
2791
3646
|
}
|
|
2792
3647
|
return;
|
|
2793
3648
|
}
|
|
2794
|
-
case "insertParagraph":
|
|
2795
3649
|
case "insertLineBreak": {
|
|
3650
|
+
e.preventDefault();
|
|
3651
|
+
if (ed.getBlockType() === "listItem") {
|
|
3652
|
+
(0, import_core6.insertText)(ctx, "\n", ed.consumePendingMarks());
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
3655
|
+
const selEmbed = ed.getSelectedEmbed();
|
|
3656
|
+
if (selEmbed) {
|
|
3657
|
+
const off = selEmbed.offset + 1;
|
|
3658
|
+
ctx.setSelection({
|
|
3659
|
+
anchor: {
|
|
3660
|
+
blockIndex: selEmbed.blockIndex,
|
|
3661
|
+
cellIndex: selEmbed.cellIndex,
|
|
3662
|
+
offset: off
|
|
3663
|
+
},
|
|
3664
|
+
focus: {
|
|
3665
|
+
blockIndex: selEmbed.blockIndex,
|
|
3666
|
+
cellIndex: selEmbed.cellIndex,
|
|
3667
|
+
offset: off
|
|
3668
|
+
}
|
|
3669
|
+
});
|
|
3670
|
+
}
|
|
3671
|
+
if (ed.splitListItem()) return;
|
|
3672
|
+
(0, import_core6.insertParagraph)(ctx);
|
|
3673
|
+
return;
|
|
3674
|
+
}
|
|
3675
|
+
case "insertParagraph": {
|
|
2796
3676
|
e.preventDefault();
|
|
2797
3677
|
const selectedEmbed2 = ed.getSelectedEmbed();
|
|
2798
3678
|
if (selectedEmbed2) {
|
|
@@ -2811,35 +3691,19 @@ function Editor({
|
|
|
2811
3691
|
});
|
|
2812
3692
|
}
|
|
2813
3693
|
if (ed.splitListItem()) return;
|
|
2814
|
-
(0,
|
|
3694
|
+
(0, import_core6.insertParagraph)(ctx);
|
|
2815
3695
|
return;
|
|
2816
3696
|
}
|
|
2817
3697
|
case "insertReplacementText": {
|
|
2818
3698
|
const text = e.data ?? e.dataTransfer?.getData("text/plain") ?? "";
|
|
2819
3699
|
if (text.length > 0) {
|
|
2820
3700
|
e.preventDefault();
|
|
2821
|
-
(0,
|
|
3701
|
+
(0, import_core6.insertText)(ctx, text, ed.consumePendingMarks());
|
|
2822
3702
|
}
|
|
2823
3703
|
return;
|
|
2824
3704
|
}
|
|
2825
3705
|
case "insertFromPaste": {
|
|
2826
3706
|
e.preventDefault();
|
|
2827
|
-
const images = Array.from(e.dataTransfer?.files ?? []).filter(
|
|
2828
|
-
(f) => f.type.startsWith("image/")
|
|
2829
|
-
);
|
|
2830
|
-
if (images.length > 0) {
|
|
2831
|
-
void (async () => {
|
|
2832
|
-
for (const f of images) await editorRef.current.insertImageFromFile(f);
|
|
2833
|
-
})();
|
|
2834
|
-
return;
|
|
2835
|
-
}
|
|
2836
|
-
const text = e.dataTransfer?.getData("text/plain") ?? "";
|
|
2837
|
-
if (text.length === 0) return;
|
|
2838
|
-
const lines = text.split(/\r\n|\r|\n/);
|
|
2839
|
-
lines.forEach((line, i) => {
|
|
2840
|
-
if (i > 0) (0, import_core5.insertParagraph)(ctx);
|
|
2841
|
-
if (line.length > 0) (0, import_core5.insertText)(ctx, line);
|
|
2842
|
-
});
|
|
2843
3707
|
return;
|
|
2844
3708
|
}
|
|
2845
3709
|
case "deleteContentBackward":
|
|
@@ -2847,7 +3711,7 @@ function Editor({
|
|
|
2847
3711
|
case "deleteSoftLineBackward":
|
|
2848
3712
|
case "deleteHardLineBackward": {
|
|
2849
3713
|
e.preventDefault();
|
|
2850
|
-
(0,
|
|
3714
|
+
(0, import_core6.deleteBackward)(ctx);
|
|
2851
3715
|
return;
|
|
2852
3716
|
}
|
|
2853
3717
|
case "deleteContentForward":
|
|
@@ -2855,7 +3719,7 @@ function Editor({
|
|
|
2855
3719
|
case "deleteSoftLineForward":
|
|
2856
3720
|
case "deleteHardLineForward": {
|
|
2857
3721
|
e.preventDefault();
|
|
2858
|
-
(0,
|
|
3722
|
+
(0, import_core6.deleteForward)(ctx);
|
|
2859
3723
|
return;
|
|
2860
3724
|
}
|
|
2861
3725
|
case "historyUndo": {
|
|
@@ -2877,7 +3741,67 @@ function Editor({
|
|
|
2877
3741
|
root.addEventListener("beforeinput", handler);
|
|
2878
3742
|
return () => root.removeEventListener("beforeinput", handler);
|
|
2879
3743
|
}, []);
|
|
2880
|
-
|
|
3744
|
+
(0, import_react14.useEffect)(() => {
|
|
3745
|
+
const root = rootRef.current;
|
|
3746
|
+
if (!root) return;
|
|
3747
|
+
const writeSlice = (e) => {
|
|
3748
|
+
const ctx = ctxRef.current;
|
|
3749
|
+
const slice = (0, import_core6.serializeSelection)(ctx.doc, ctx.getSelection());
|
|
3750
|
+
if (!slice || !e.clipboardData) return false;
|
|
3751
|
+
e.clipboardData.setData(import_core6.SOFER_MIME, JSON.stringify(slice));
|
|
3752
|
+
e.clipboardData.setData("text/plain", (0, import_core6.sliceToText)(slice));
|
|
3753
|
+
return true;
|
|
3754
|
+
};
|
|
3755
|
+
const onCopy = (e) => {
|
|
3756
|
+
if (writeSlice(e)) e.preventDefault();
|
|
3757
|
+
};
|
|
3758
|
+
const onCut = (e) => {
|
|
3759
|
+
e.preventDefault();
|
|
3760
|
+
if (writeSlice(e)) (0, import_core6.deleteSelection)(ctxRef.current);
|
|
3761
|
+
};
|
|
3762
|
+
const onPaste = (e) => {
|
|
3763
|
+
const ctx = ctxRef.current;
|
|
3764
|
+
const cd = e.clipboardData;
|
|
3765
|
+
if (!cd) return;
|
|
3766
|
+
const raw = cd.getData(import_core6.SOFER_MIME);
|
|
3767
|
+
if (raw) {
|
|
3768
|
+
try {
|
|
3769
|
+
const slice = JSON.parse(raw);
|
|
3770
|
+
if (slice && Array.isArray(slice.blocks)) {
|
|
3771
|
+
e.preventDefault();
|
|
3772
|
+
(0, import_core6.insertSlice)(ctx, slice);
|
|
3773
|
+
return;
|
|
3774
|
+
}
|
|
3775
|
+
} catch {
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
const images = Array.from(cd.files ?? []).filter((f) => f.type.startsWith("image/"));
|
|
3779
|
+
if (images.length > 0) {
|
|
3780
|
+
e.preventDefault();
|
|
3781
|
+
void (async () => {
|
|
3782
|
+
for (const f of images) await editorRef.current.insertImageFromFile(f);
|
|
3783
|
+
})();
|
|
3784
|
+
return;
|
|
3785
|
+
}
|
|
3786
|
+
const text = cd.getData("text/plain");
|
|
3787
|
+
if (text.length === 0) return;
|
|
3788
|
+
e.preventDefault();
|
|
3789
|
+
const lines = text.split(/\r\n|\r|\n/);
|
|
3790
|
+
lines.forEach((line, i) => {
|
|
3791
|
+
if (i > 0) (0, import_core6.insertParagraph)(ctx);
|
|
3792
|
+
if (line.length > 0) (0, import_core6.insertText)(ctx, line);
|
|
3793
|
+
});
|
|
3794
|
+
};
|
|
3795
|
+
root.addEventListener("copy", onCopy);
|
|
3796
|
+
root.addEventListener("cut", onCut);
|
|
3797
|
+
root.addEventListener("paste", onPaste);
|
|
3798
|
+
return () => {
|
|
3799
|
+
root.removeEventListener("copy", onCopy);
|
|
3800
|
+
root.removeEventListener("cut", onCut);
|
|
3801
|
+
root.removeEventListener("paste", onPaste);
|
|
3802
|
+
};
|
|
3803
|
+
}, []);
|
|
3804
|
+
const onKeyDown = (0, import_react14.useCallback)((e) => {
|
|
2881
3805
|
const ed = editorRef.current;
|
|
2882
3806
|
const mod = e.metaKey || e.ctrlKey;
|
|
2883
3807
|
if (e.key === "Tab") {
|
|
@@ -2891,6 +3815,20 @@ function Editor({
|
|
|
2891
3815
|
else ed.indentList();
|
|
2892
3816
|
return;
|
|
2893
3817
|
}
|
|
3818
|
+
if (!mod && (e.key === "Home" || e.key === "End")) {
|
|
3819
|
+
const root = rootRef.current;
|
|
3820
|
+
const sel = window.getSelection();
|
|
3821
|
+
const sm = sel?.modify;
|
|
3822
|
+
if (root && sel && sel.rangeCount > 0 && typeof sm === "function") {
|
|
3823
|
+
e.preventDefault();
|
|
3824
|
+
const alter = e.shiftKey ? "extend" : "move";
|
|
3825
|
+
const direction = e.key === "Home" ? "left" : "right";
|
|
3826
|
+
sm.call(sel, alter, direction, "lineboundary");
|
|
3827
|
+
const modelSel = readDomSelection(root);
|
|
3828
|
+
if (modelSel) ctxRef.current.setSelection(modelSel);
|
|
3829
|
+
}
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
2894
3832
|
if (!mod) return;
|
|
2895
3833
|
const key = e.key.toLowerCase();
|
|
2896
3834
|
if (!e.shiftKey && !e.altKey && key === "z") {
|
|
@@ -2937,37 +3875,58 @@ function Editor({
|
|
|
2937
3875
|
});
|
|
2938
3876
|
}
|
|
2939
3877
|
}, []);
|
|
2940
|
-
const onCompositionStart = (0,
|
|
3878
|
+
const onCompositionStart = (0, import_react14.useCallback)(() => {
|
|
2941
3879
|
isComposingRef.current = true;
|
|
2942
3880
|
}, []);
|
|
2943
|
-
const onCompositionEnd = (0,
|
|
3881
|
+
const onCompositionEnd = (0, import_react14.useCallback)((e) => {
|
|
2944
3882
|
isComposingRef.current = false;
|
|
2945
3883
|
if (e.data && e.data.length > 0) {
|
|
2946
|
-
(0,
|
|
3884
|
+
(0, import_core6.insertText)(ctxRef.current, e.data);
|
|
2947
3885
|
}
|
|
2948
3886
|
}, []);
|
|
2949
|
-
const topLevels = (0,
|
|
3887
|
+
const topLevels = (0, import_react14.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
|
|
3888
|
+
const topLevelsStructuralKey = (0, import_react14.useMemo)(
|
|
3889
|
+
() => topLevels.map(
|
|
3890
|
+
(t) => t.kind === "list" ? `L:${t.listKind}:${t.items.length}:${t.ordinalStart}` : `B:${t.block.type}:${t.block.attrs.level ?? ""}`
|
|
3891
|
+
).join("|"),
|
|
3892
|
+
[topLevels]
|
|
3893
|
+
);
|
|
2950
3894
|
const docSettings = usePageSettings(editor.doc);
|
|
2951
3895
|
const propIsSet = pageGeometry !== void 0;
|
|
2952
3896
|
const geom = propIsSet ? pageGeometry ?? A4_PAGE : docSettings;
|
|
2953
3897
|
const paginated = pageGeometry !== null;
|
|
2954
3898
|
const selectedEmbed = editor.getSelectedEmbed();
|
|
2955
|
-
const layout = usePageLayout(
|
|
3899
|
+
const { layout, phase: paginationPhase } = usePageLayout(
|
|
2956
3900
|
rootRef,
|
|
2957
3901
|
geom,
|
|
2958
3902
|
topLevels.length,
|
|
2959
|
-
|
|
3903
|
+
// Usar a chave estrutural (string) em vez do array `topLevels` direto:
|
|
3904
|
+
// o array reference muda a cada keystroke, mas a chave só muda quando
|
|
3905
|
+
// a SHAPE dos top-levels muda. `usePageLayout` compara deps via
|
|
3906
|
+
// `shallowArrayEqual` — string equality cobre isso.
|
|
3907
|
+
[topLevelsStructuralKey, pageGeometry]
|
|
2960
3908
|
);
|
|
2961
3909
|
const effectiveLayout = paginated ? layout : defaultPageLayout(topLevels.length);
|
|
2962
|
-
const pageStyle =
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3910
|
+
const pageStyle = (0, import_react14.useMemo)(
|
|
3911
|
+
() => paginated ? {
|
|
3912
|
+
"--ed-page-width": `${geom.width}px`,
|
|
3913
|
+
"--ed-page-height": `${geom.height}px`,
|
|
3914
|
+
"--ed-page-margin-top": `${geom.marginTop}px`,
|
|
3915
|
+
"--ed-page-margin-bottom": `${geom.marginBottom}px`,
|
|
3916
|
+
"--ed-page-margin-left": `${geom.marginLeft}px`,
|
|
3917
|
+
"--ed-page-margin-right": `${geom.marginRight}px`
|
|
3918
|
+
} : void 0,
|
|
3919
|
+
[
|
|
3920
|
+
paginated,
|
|
3921
|
+
geom.width,
|
|
3922
|
+
geom.height,
|
|
3923
|
+
geom.marginTop,
|
|
3924
|
+
geom.marginBottom,
|
|
3925
|
+
geom.marginLeft,
|
|
3926
|
+
geom.marginRight
|
|
3927
|
+
]
|
|
3928
|
+
);
|
|
3929
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2971
3930
|
"div",
|
|
2972
3931
|
{
|
|
2973
3932
|
ref: rootRef,
|
|
@@ -2979,6 +3938,7 @@ function Editor({
|
|
|
2979
3938
|
role: "textbox",
|
|
2980
3939
|
"aria-multiline": "true",
|
|
2981
3940
|
className: (className ?? "ed-root") + (paginated ? " ed-root--paged" : " ed-root--flat"),
|
|
3941
|
+
"data-pagination-phase": paginated ? paginationPhase : void 0,
|
|
2982
3942
|
style: pageStyle,
|
|
2983
3943
|
onKeyDown,
|
|
2984
3944
|
onCompositionStart,
|
|
@@ -2989,22 +3949,26 @@ function Editor({
|
|
|
2989
3949
|
pageNumber: pi + 1,
|
|
2990
3950
|
pageCount: effectiveLayout.pages.length
|
|
2991
3951
|
};
|
|
2992
|
-
|
|
3952
|
+
const pageInlineStyle = pi === 0 && geom.firstPageExtraTop ? {
|
|
3953
|
+
"--ed-page-margin-top": `${geom.marginTop + geom.firstPageExtraTop}px`
|
|
3954
|
+
} : void 0;
|
|
3955
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2993
3956
|
"div",
|
|
2994
3957
|
{
|
|
2995
3958
|
className: "ed-page",
|
|
2996
3959
|
"data-page-number": ctx.pageNumber,
|
|
2997
3960
|
"data-page-total": ctx.pageCount,
|
|
3961
|
+
style: pageInlineStyle,
|
|
2998
3962
|
children: [
|
|
2999
|
-
renderPageHeader && /* @__PURE__ */ (0,
|
|
3000
|
-
/* @__PURE__ */ (0,
|
|
3001
|
-
renderPageFooter && /* @__PURE__ */ (0,
|
|
3963
|
+
renderPageHeader && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-header", contentEditable: false, children: renderPageHeader(ctx) }),
|
|
3964
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-content", children: page.slots.map((slot) => renderSlot(slot, topLevels)) }),
|
|
3965
|
+
renderPageFooter && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ed-page-footer", contentEditable: false, children: renderPageFooter(ctx) })
|
|
3002
3966
|
]
|
|
3003
3967
|
},
|
|
3004
3968
|
`page-${pi}`
|
|
3005
3969
|
);
|
|
3006
3970
|
}) : topLevels.map((t) => renderTopLevel(t)),
|
|
3007
|
-
selectedEmbed && /* @__PURE__ */ (0,
|
|
3971
|
+
selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3008
3972
|
ImageResizeOverlay,
|
|
3009
3973
|
{
|
|
3010
3974
|
rootRef,
|
|
@@ -3023,13 +3987,54 @@ function Editor({
|
|
|
3023
3987
|
selectedEmbed.offset,
|
|
3024
3988
|
{ offsetX: ox, offsetY: oy },
|
|
3025
3989
|
selectedEmbed.cellIndex
|
|
3990
|
+
),
|
|
3991
|
+
onReanchor: (to, ox, oy) => editor.moveEmbedAnchor(
|
|
3992
|
+
{
|
|
3993
|
+
blockIndex: selectedEmbed.blockIndex,
|
|
3994
|
+
offset: selectedEmbed.offset,
|
|
3995
|
+
cellIndex: selectedEmbed.cellIndex
|
|
3996
|
+
},
|
|
3997
|
+
to,
|
|
3998
|
+
ox,
|
|
3999
|
+
oy
|
|
3026
4000
|
)
|
|
3027
4001
|
}
|
|
4002
|
+
),
|
|
4003
|
+
hoveredBehind && !(selectedEmbed && selectedEmbed.blockIndex === hoveredBehind.blockIndex && selectedEmbed.offset === hoveredBehind.offset && (selectedEmbed.cellIndex ?? -1) === (hoveredBehind.cellIndex ?? -1)) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4004
|
+
BehindImageSelectAffordance,
|
|
4005
|
+
{
|
|
4006
|
+
rootRef,
|
|
4007
|
+
blockIndex: hoveredBehind.blockIndex,
|
|
4008
|
+
offset: hoveredBehind.offset,
|
|
4009
|
+
cellIndex: hoveredBehind.cellIndex,
|
|
4010
|
+
onSelect: () => setSelection({
|
|
4011
|
+
anchor: {
|
|
4012
|
+
blockIndex: hoveredBehind.blockIndex,
|
|
4013
|
+
cellIndex: hoveredBehind.cellIndex,
|
|
4014
|
+
offset: hoveredBehind.offset
|
|
4015
|
+
},
|
|
4016
|
+
focus: {
|
|
4017
|
+
blockIndex: hoveredBehind.blockIndex,
|
|
4018
|
+
cellIndex: hoveredBehind.cellIndex,
|
|
4019
|
+
offset: hoveredBehind.offset + 1
|
|
4020
|
+
}
|
|
4021
|
+
})
|
|
4022
|
+
}
|
|
4023
|
+
),
|
|
4024
|
+
hoveredLink && hoveredLink.href && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LinkHoverTooltip, { href: hoveredLink.href, rect: hoveredLink.rect }),
|
|
4025
|
+
awareness && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4026
|
+
RemoteCursorsOverlay,
|
|
4027
|
+
{
|
|
4028
|
+
rootRef,
|
|
4029
|
+
doc,
|
|
4030
|
+
awareness,
|
|
4031
|
+
revision: snapshot
|
|
4032
|
+
}
|
|
3028
4033
|
)
|
|
3029
4034
|
]
|
|
3030
4035
|
}
|
|
3031
4036
|
);
|
|
3032
|
-
return /* @__PURE__ */ (0,
|
|
4037
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(EditorProvider, { editor, children: body });
|
|
3033
4038
|
}
|
|
3034
4039
|
function groupTopLevels(snapshot) {
|
|
3035
4040
|
const out = [];
|
|
@@ -3040,11 +4045,29 @@ function groupTopLevels(snapshot) {
|
|
|
3040
4045
|
const groupStart = i;
|
|
3041
4046
|
const items = [];
|
|
3042
4047
|
const kind = block.attrs.listKind === "ordered" ? "ordered" : "bullet";
|
|
3043
|
-
|
|
3044
|
-
|
|
4048
|
+
const groupStyle = block.attrs.listStyle;
|
|
4049
|
+
while (i < snapshot.length) {
|
|
4050
|
+
const b = snapshot[i];
|
|
4051
|
+
if (b.type !== "listItem") break;
|
|
4052
|
+
if ((b.attrs.listKind ?? "bullet") !== kind) break;
|
|
4053
|
+
if (i > groupStart) {
|
|
4054
|
+
if (typeof b.attrs.listStart === "number") break;
|
|
4055
|
+
const itemStyle = b.attrs.listStyle;
|
|
4056
|
+
if (itemStyle !== void 0 && itemStyle !== groupStyle) break;
|
|
4057
|
+
}
|
|
4058
|
+
items.push({ block: b, index: i });
|
|
3045
4059
|
i++;
|
|
3046
4060
|
}
|
|
3047
|
-
|
|
4061
|
+
const firstAttrs = items[0].block.attrs;
|
|
4062
|
+
const ordinalStart = typeof firstAttrs.listStart === "number" && firstAttrs.listStart > 0 ? firstAttrs.listStart : 1;
|
|
4063
|
+
out.push({
|
|
4064
|
+
kind: "list",
|
|
4065
|
+
items,
|
|
4066
|
+
listKind: kind,
|
|
4067
|
+
ordinalStart,
|
|
4068
|
+
listStyle: groupStyle,
|
|
4069
|
+
key: groupStart
|
|
4070
|
+
});
|
|
3048
4071
|
continue;
|
|
3049
4072
|
}
|
|
3050
4073
|
out.push({ kind: "block", block, blockIndex: i, key: i });
|
|
@@ -3061,7 +4084,7 @@ function renderSlot(slot, topLevels) {
|
|
|
3061
4084
|
start: slot.fragment.start,
|
|
3062
4085
|
end: slot.fragment.end
|
|
3063
4086
|
};
|
|
3064
|
-
return /* @__PURE__ */ (0,
|
|
4087
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3065
4088
|
NodeView,
|
|
3066
4089
|
{
|
|
3067
4090
|
block: top.block,
|
|
@@ -3072,7 +4095,7 @@ function renderSlot(slot, topLevels) {
|
|
|
3072
4095
|
);
|
|
3073
4096
|
}
|
|
3074
4097
|
if (slot.tableFragment && top.kind === "block" && top.block.type === "table") {
|
|
3075
|
-
return /* @__PURE__ */ (0,
|
|
4098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3076
4099
|
NodeView,
|
|
3077
4100
|
{
|
|
3078
4101
|
block: top.block,
|
|
@@ -3082,14 +4105,42 @@ function renderSlot(slot, topLevels) {
|
|
|
3082
4105
|
`${top.key}-tf${slot.tableFragment.index}`
|
|
3083
4106
|
);
|
|
3084
4107
|
}
|
|
4108
|
+
if (slot.listFragment && top.kind === "list") {
|
|
4109
|
+
return renderListFragment(top, slot.listFragment);
|
|
4110
|
+
}
|
|
3085
4111
|
return renderTopLevel(top);
|
|
3086
4112
|
}
|
|
3087
4113
|
function renderTopLevel(top) {
|
|
3088
4114
|
if (top.kind === "list") {
|
|
3089
4115
|
const tree = buildListTree(top.items);
|
|
3090
|
-
return renderListTree(tree, top.
|
|
4116
|
+
return renderListTree(tree, top, top.ordinalStart, `list-${top.key}`);
|
|
3091
4117
|
}
|
|
3092
|
-
return /* @__PURE__ */ (0,
|
|
4118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: top.block, index: top.blockIndex }, top.key);
|
|
4119
|
+
}
|
|
4120
|
+
function renderListFragment(top, frag) {
|
|
4121
|
+
const ranges = topLevelItemRanges(top.items);
|
|
4122
|
+
const startRange = ranges[frag.itemStart];
|
|
4123
|
+
const endRange = ranges[frag.itemEnd - 1];
|
|
4124
|
+
if (!startRange || !endRange) return renderTopLevel(top);
|
|
4125
|
+
const sliced = top.items.slice(startRange[0], endRange[1]);
|
|
4126
|
+
const ordinalStart = top.ordinalStart + frag.itemStart;
|
|
4127
|
+
const key = `list-${top.key}-f${frag.index}`;
|
|
4128
|
+
const slicedTop = { ...top, items: sliced };
|
|
4129
|
+
const tree = buildListTree(sliced);
|
|
4130
|
+
return renderListTree(tree, slicedTop, ordinalStart, key);
|
|
4131
|
+
}
|
|
4132
|
+
function topLevelItemRanges(items) {
|
|
4133
|
+
const out = [];
|
|
4134
|
+
let currentStart = -1;
|
|
4135
|
+
items.forEach((it, idx) => {
|
|
4136
|
+
const level = clampListLevel2(it.block.attrs.listLevel);
|
|
4137
|
+
if (level === 0) {
|
|
4138
|
+
if (currentStart >= 0) out.push([currentStart, idx]);
|
|
4139
|
+
currentStart = idx;
|
|
4140
|
+
}
|
|
4141
|
+
});
|
|
4142
|
+
if (currentStart >= 0) out.push([currentStart, items.length]);
|
|
4143
|
+
return out;
|
|
3093
4144
|
}
|
|
3094
4145
|
function buildListTree(items) {
|
|
3095
4146
|
const roots = [];
|
|
@@ -3103,9 +4154,28 @@ function buildListTree(items) {
|
|
|
3103
4154
|
}
|
|
3104
4155
|
return roots;
|
|
3105
4156
|
}
|
|
3106
|
-
function renderListTree(tree,
|
|
4157
|
+
function renderListTree(tree, top, start, key) {
|
|
4158
|
+
const className = `ed-list ed-list-${top.listKind}`;
|
|
4159
|
+
const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
|
|
4160
|
+
const items = tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, top.listKind, `nested-${node.entry.index}`) : null }, node.entry.index));
|
|
4161
|
+
if (top.listKind === "ordered") {
|
|
4162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4163
|
+
"ol",
|
|
4164
|
+
{
|
|
4165
|
+
className,
|
|
4166
|
+
"data-list-kind": "ordered",
|
|
4167
|
+
start: start > 1 ? start : void 0,
|
|
4168
|
+
style,
|
|
4169
|
+
children: items
|
|
4170
|
+
},
|
|
4171
|
+
key
|
|
4172
|
+
);
|
|
4173
|
+
}
|
|
4174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
|
|
4175
|
+
}
|
|
4176
|
+
function renderNestedListTree(tree, kind, key) {
|
|
3107
4177
|
const Tag = kind === "ordered" ? "ol" : "ul";
|
|
3108
|
-
return /* @__PURE__ */ (0,
|
|
4178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children, kind, `nested-${node.entry.index}`) : null }, node.entry.index)) }, key);
|
|
3109
4179
|
}
|
|
3110
4180
|
function clampListLevel2(l) {
|
|
3111
4181
|
if (typeof l !== "number" || !Number.isFinite(l)) return 0;
|
|
@@ -3133,8 +4203,8 @@ function caretRangeFromPoint(x, y) {
|
|
|
3133
4203
|
}
|
|
3134
4204
|
|
|
3135
4205
|
// src/Toolbar.tsx
|
|
3136
|
-
var
|
|
3137
|
-
var
|
|
4206
|
+
var import_react15 = require("react");
|
|
4207
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
3138
4208
|
var FONT_FAMILIES = ["Arial"];
|
|
3139
4209
|
var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
|
|
3140
4210
|
var BLOCK_OPTIONS = [
|
|
@@ -3174,6 +4244,8 @@ function Toolbar({ className }) {
|
|
|
3174
4244
|
getBlockAttr,
|
|
3175
4245
|
setBlockType,
|
|
3176
4246
|
setBlockAttr,
|
|
4247
|
+
setAlign,
|
|
4248
|
+
getAlign,
|
|
3177
4249
|
isListActive,
|
|
3178
4250
|
toggleList,
|
|
3179
4251
|
indentList,
|
|
@@ -3182,7 +4254,7 @@ function Toolbar({ className }) {
|
|
|
3182
4254
|
const active = getActiveMarks();
|
|
3183
4255
|
const blockType = getBlockType();
|
|
3184
4256
|
const blockLevel = getBlockAttr("level");
|
|
3185
|
-
const blockAlign =
|
|
4257
|
+
const blockAlign = getAlign();
|
|
3186
4258
|
const blockDir = getBlockAttr("dir");
|
|
3187
4259
|
const stop = (e) => {
|
|
3188
4260
|
const t = e.target;
|
|
@@ -3225,16 +4297,16 @@ function Toolbar({ className }) {
|
|
|
3225
4297
|
);
|
|
3226
4298
|
return;
|
|
3227
4299
|
}
|
|
3228
|
-
|
|
4300
|
+
setAlign(value);
|
|
3229
4301
|
};
|
|
3230
|
-
const onInsertImageClick = (0,
|
|
4302
|
+
const onInsertImageClick = (0, import_react15.useCallback)(
|
|
3231
4303
|
(e) => {
|
|
3232
4304
|
e.preventDefault();
|
|
3233
4305
|
imageInputRef.current?.click();
|
|
3234
4306
|
},
|
|
3235
4307
|
[]
|
|
3236
4308
|
);
|
|
3237
|
-
const onImageInputChange = (0,
|
|
4309
|
+
const onImageInputChange = (0, import_react15.useCallback)(
|
|
3238
4310
|
(e) => {
|
|
3239
4311
|
const file = e.target.files?.[0];
|
|
3240
4312
|
if (file) void editor.insertImageFromFile(file);
|
|
@@ -3242,14 +4314,14 @@ function Toolbar({ className }) {
|
|
|
3242
4314
|
},
|
|
3243
4315
|
[editor]
|
|
3244
4316
|
);
|
|
3245
|
-
const imageInputRef = (0,
|
|
4317
|
+
const imageInputRef = (0, import_react15.useRef)(null);
|
|
3246
4318
|
const onToggleDir = (e) => {
|
|
3247
4319
|
e.preventDefault();
|
|
3248
4320
|
const next = blockDir === "rtl" ? "ltr" : "rtl";
|
|
3249
4321
|
setBlockAttr("dir", next);
|
|
3250
4322
|
};
|
|
3251
4323
|
const linkActive = isMarkActive("link");
|
|
3252
|
-
const onLinkClick = (0,
|
|
4324
|
+
const onLinkClick = (0, import_react15.useCallback)(
|
|
3253
4325
|
(e) => {
|
|
3254
4326
|
e.preventDefault();
|
|
3255
4327
|
const currentHref = active.link && typeof active.link === "object" && "href" in active.link ? active.link.href : "";
|
|
@@ -3279,7 +4351,7 @@ function Toolbar({ className }) {
|
|
|
3279
4351
|
sel.cellIndex
|
|
3280
4352
|
);
|
|
3281
4353
|
};
|
|
3282
|
-
return /* @__PURE__ */ (0,
|
|
4354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3283
4355
|
"div",
|
|
3284
4356
|
{
|
|
3285
4357
|
className: className ?? "ed-toolbar",
|
|
@@ -3287,7 +4359,7 @@ function Toolbar({ className }) {
|
|
|
3287
4359
|
"aria-label": "Editor toolbar",
|
|
3288
4360
|
onMouseDown: stop,
|
|
3289
4361
|
children: [
|
|
3290
|
-
/* @__PURE__ */ (0,
|
|
4362
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3291
4363
|
"select",
|
|
3292
4364
|
{
|
|
3293
4365
|
className: "ed-toolbar-select",
|
|
@@ -3296,23 +4368,23 @@ function Toolbar({ className }) {
|
|
|
3296
4368
|
onMouseDown: stop,
|
|
3297
4369
|
"aria-label": "Tipo de bloco",
|
|
3298
4370
|
children: [
|
|
3299
|
-
blockValue === "" && /* @__PURE__ */ (0,
|
|
3300
|
-
BLOCK_OPTIONS.map((o) => /* @__PURE__ */ (0,
|
|
4371
|
+
blockValue === "" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "\u2014 (misto)" }),
|
|
4372
|
+
BLOCK_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: o.value, children: o.label }, o.value))
|
|
3301
4373
|
]
|
|
3302
4374
|
}
|
|
3303
4375
|
) }),
|
|
3304
|
-
/* @__PURE__ */ (0,
|
|
3305
|
-
/* @__PURE__ */ (0,
|
|
3306
|
-
/* @__PURE__ */ (0,
|
|
3307
|
-
/* @__PURE__ */ (0,
|
|
3308
|
-
/* @__PURE__ */ (0,
|
|
4376
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4377
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Negrito (\u2318B)", pressed: isMarkActive("bold"), onClick: onToggle("bold"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: "B" }) }),
|
|
4378
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "It\xE1lico (\u2318I)", pressed: isMarkActive("italic"), onClick: onToggle("italic"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("em", { children: "I" }) }),
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Sublinhado (\u2318U)", pressed: isMarkActive("underline"), onClick: onToggle("underline"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("u", { children: "U" }) }),
|
|
4380
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MarkButton, { title: "Tachado (\u2318\u21E7X)", pressed: isMarkActive("strike"), onClick: onToggle("strike"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("s", { children: "S" }) })
|
|
3309
4381
|
] }),
|
|
3310
|
-
/* @__PURE__ */ (0,
|
|
3311
|
-
/* @__PURE__ */ (0,
|
|
3312
|
-
/* @__PURE__ */ (0,
|
|
3313
|
-
/* @__PURE__ */ (0,
|
|
4382
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4383
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "ed-toolbar-label", children: [
|
|
4384
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ed-toolbar-swatch", "aria-hidden": true, style: { background: colorValue } }),
|
|
4385
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: colorValue, onChange: onColorChange, onMouseDown: stop, "aria-label": "Cor do texto" })
|
|
3314
4386
|
] }),
|
|
3315
|
-
/* @__PURE__ */ (0,
|
|
4387
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3316
4388
|
"button",
|
|
3317
4389
|
{
|
|
3318
4390
|
type: "button",
|
|
@@ -3327,8 +4399,8 @@ function Toolbar({ className }) {
|
|
|
3327
4399
|
}
|
|
3328
4400
|
)
|
|
3329
4401
|
] }),
|
|
3330
|
-
/* @__PURE__ */ (0,
|
|
3331
|
-
/* @__PURE__ */ (0,
|
|
4402
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4403
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3332
4404
|
"select",
|
|
3333
4405
|
{
|
|
3334
4406
|
className: "ed-toolbar-select",
|
|
@@ -3337,12 +4409,12 @@ function Toolbar({ className }) {
|
|
|
3337
4409
|
onMouseDown: stop,
|
|
3338
4410
|
"aria-label": "Fam\xEDlia da fonte",
|
|
3339
4411
|
children: [
|
|
3340
|
-
/* @__PURE__ */ (0,
|
|
3341
|
-
FONT_FAMILIES.map((f) => /* @__PURE__ */ (0,
|
|
4412
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Fonte\u2026" }),
|
|
4413
|
+
FONT_FAMILIES.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: f, children: f }, f))
|
|
3342
4414
|
]
|
|
3343
4415
|
}
|
|
3344
4416
|
),
|
|
3345
|
-
/* @__PURE__ */ (0,
|
|
4417
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3346
4418
|
"select",
|
|
3347
4419
|
{
|
|
3348
4420
|
className: "ed-toolbar-select",
|
|
@@ -3351,13 +4423,13 @@ function Toolbar({ className }) {
|
|
|
3351
4423
|
onMouseDown: stop,
|
|
3352
4424
|
"aria-label": "Tamanho da fonte",
|
|
3353
4425
|
children: [
|
|
3354
|
-
/* @__PURE__ */ (0,
|
|
3355
|
-
FONT_SIZES.map((s) => /* @__PURE__ */ (0,
|
|
4426
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "", children: "Tamanho\u2026" }),
|
|
4427
|
+
FONT_SIZES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: s, children: s }, s))
|
|
3356
4428
|
]
|
|
3357
4429
|
}
|
|
3358
4430
|
)
|
|
3359
4431
|
] }),
|
|
3360
|
-
/* @__PURE__ */ (0,
|
|
4432
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: ALIGN_OPTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3361
4433
|
"button",
|
|
3362
4434
|
{
|
|
3363
4435
|
type: "button",
|
|
@@ -3370,7 +4442,7 @@ function Toolbar({ className }) {
|
|
|
3370
4442
|
},
|
|
3371
4443
|
a.value
|
|
3372
4444
|
)) }),
|
|
3373
|
-
/* @__PURE__ */ (0,
|
|
4445
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3374
4446
|
"button",
|
|
3375
4447
|
{
|
|
3376
4448
|
type: "button",
|
|
@@ -3382,8 +4454,8 @@ function Toolbar({ className }) {
|
|
|
3382
4454
|
children: blockDir === "rtl" ? "RTL" : "LTR"
|
|
3383
4455
|
}
|
|
3384
4456
|
) }),
|
|
3385
|
-
/* @__PURE__ */ (0,
|
|
3386
|
-
/* @__PURE__ */ (0,
|
|
4457
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4458
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3387
4459
|
"button",
|
|
3388
4460
|
{
|
|
3389
4461
|
type: "button",
|
|
@@ -3398,7 +4470,7 @@ function Toolbar({ className }) {
|
|
|
3398
4470
|
children: "\u2022"
|
|
3399
4471
|
}
|
|
3400
4472
|
),
|
|
3401
|
-
/* @__PURE__ */ (0,
|
|
4473
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3402
4474
|
"button",
|
|
3403
4475
|
{
|
|
3404
4476
|
type: "button",
|
|
@@ -3413,7 +4485,7 @@ function Toolbar({ className }) {
|
|
|
3413
4485
|
children: "1."
|
|
3414
4486
|
}
|
|
3415
4487
|
),
|
|
3416
|
-
/* @__PURE__ */ (0,
|
|
4488
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3417
4489
|
"button",
|
|
3418
4490
|
{
|
|
3419
4491
|
type: "button",
|
|
@@ -3427,7 +4499,7 @@ function Toolbar({ className }) {
|
|
|
3427
4499
|
children: "\u21E4"
|
|
3428
4500
|
}
|
|
3429
4501
|
),
|
|
3430
|
-
/* @__PURE__ */ (0,
|
|
4502
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3431
4503
|
"button",
|
|
3432
4504
|
{
|
|
3433
4505
|
type: "button",
|
|
@@ -3442,7 +4514,7 @@ function Toolbar({ className }) {
|
|
|
3442
4514
|
}
|
|
3443
4515
|
)
|
|
3444
4516
|
] }),
|
|
3445
|
-
/* @__PURE__ */ (0,
|
|
4517
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3446
4518
|
"button",
|
|
3447
4519
|
{
|
|
3448
4520
|
type: "button",
|
|
@@ -3454,9 +4526,9 @@ function Toolbar({ className }) {
|
|
|
3454
4526
|
children: "\u{1F517}"
|
|
3455
4527
|
}
|
|
3456
4528
|
) }),
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3458
|
-
/* @__PURE__ */ (0,
|
|
3459
|
-
/* @__PURE__ */ (0,
|
|
4529
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TableMenu, {}) }),
|
|
4530
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4531
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3460
4532
|
"button",
|
|
3461
4533
|
{
|
|
3462
4534
|
type: "button",
|
|
@@ -3467,7 +4539,7 @@ function Toolbar({ className }) {
|
|
|
3467
4539
|
children: "\u{1F5BC}"
|
|
3468
4540
|
}
|
|
3469
4541
|
),
|
|
3470
|
-
/* @__PURE__ */ (0,
|
|
4542
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3471
4543
|
"input",
|
|
3472
4544
|
{
|
|
3473
4545
|
ref: imageInputRef,
|
|
@@ -3478,8 +4550,8 @@ function Toolbar({ className }) {
|
|
|
3478
4550
|
}
|
|
3479
4551
|
)
|
|
3480
4552
|
] }),
|
|
3481
|
-
selectedEmbed && /* @__PURE__ */ (0,
|
|
3482
|
-
IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ (0,
|
|
4553
|
+
selectedEmbed && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Group, { children: [
|
|
4554
|
+
IMAGE_LAYOUT_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3483
4555
|
"button",
|
|
3484
4556
|
{
|
|
3485
4557
|
type: "button",
|
|
@@ -3492,7 +4564,7 @@ function Toolbar({ className }) {
|
|
|
3492
4564
|
},
|
|
3493
4565
|
opt.value
|
|
3494
4566
|
)),
|
|
3495
|
-
/* @__PURE__ */ (0,
|
|
4567
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3496
4568
|
"button",
|
|
3497
4569
|
{
|
|
3498
4570
|
type: "button",
|
|
@@ -3522,7 +4594,7 @@ function Toolbar({ className }) {
|
|
|
3522
4594
|
}
|
|
3523
4595
|
)
|
|
3524
4596
|
] }),
|
|
3525
|
-
/* @__PURE__ */ (0,
|
|
4597
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Group, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3526
4598
|
"button",
|
|
3527
4599
|
{
|
|
3528
4600
|
type: "button",
|
|
@@ -3543,9 +4615,9 @@ function Toolbar({ className }) {
|
|
|
3543
4615
|
function TableMenu() {
|
|
3544
4616
|
const editor = useEditorContext();
|
|
3545
4617
|
const inTable = editor.isInTable();
|
|
3546
|
-
const [open, setOpen] = (0,
|
|
3547
|
-
const rootRef = (0,
|
|
3548
|
-
(0,
|
|
4618
|
+
const [open, setOpen] = (0, import_react15.useState)(false);
|
|
4619
|
+
const rootRef = (0, import_react15.useRef)(null);
|
|
4620
|
+
(0, import_react15.useEffect)(() => {
|
|
3549
4621
|
if (!open) return;
|
|
3550
4622
|
const onDown = (e) => {
|
|
3551
4623
|
if (!rootRef.current) return;
|
|
@@ -3555,8 +4627,8 @@ function TableMenu() {
|
|
|
3555
4627
|
document.addEventListener("mousedown", onDown);
|
|
3556
4628
|
return () => document.removeEventListener("mousedown", onDown);
|
|
3557
4629
|
}, [open]);
|
|
3558
|
-
return /* @__PURE__ */ (0,
|
|
3559
|
-
/* @__PURE__ */ (0,
|
|
4630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
|
|
4631
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3560
4632
|
"button",
|
|
3561
4633
|
{
|
|
3562
4634
|
type: "button",
|
|
@@ -3571,7 +4643,7 @@ function TableMenu() {
|
|
|
3571
4643
|
children: "\u25A6"
|
|
3572
4644
|
}
|
|
3573
4645
|
),
|
|
3574
|
-
open && /* @__PURE__ */ (0,
|
|
4646
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3575
4647
|
"div",
|
|
3576
4648
|
{
|
|
3577
4649
|
className: "ed-table-popover",
|
|
@@ -3583,7 +4655,7 @@ function TableMenu() {
|
|
|
3583
4655
|
}
|
|
3584
4656
|
},
|
|
3585
4657
|
children: [
|
|
3586
|
-
/* @__PURE__ */ (0,
|
|
4658
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3587
4659
|
TableSizePicker,
|
|
3588
4660
|
{
|
|
3589
4661
|
onPick: (rows, cols) => {
|
|
@@ -3592,34 +4664,34 @@ function TableMenu() {
|
|
|
3592
4664
|
}
|
|
3593
4665
|
}
|
|
3594
4666
|
),
|
|
3595
|
-
inTable && /* @__PURE__ */ (0,
|
|
3596
|
-
/* @__PURE__ */ (0,
|
|
3597
|
-
/* @__PURE__ */ (0,
|
|
4667
|
+
inTable && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-actions", children: [
|
|
4668
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
|
|
4669
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3598
4670
|
setOpen(false);
|
|
3599
4671
|
editor.insertRowAbove();
|
|
3600
4672
|
}, children: "Inserir linha acima" }),
|
|
3601
|
-
/* @__PURE__ */ (0,
|
|
4673
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3602
4674
|
setOpen(false);
|
|
3603
4675
|
editor.insertRowBelow();
|
|
3604
4676
|
}, children: "Inserir linha abaixo" }),
|
|
3605
|
-
/* @__PURE__ */ (0,
|
|
4677
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3606
4678
|
setOpen(false);
|
|
3607
4679
|
editor.insertColumnLeft();
|
|
3608
4680
|
}, children: "Inserir coluna \xE0 esquerda" }),
|
|
3609
|
-
/* @__PURE__ */ (0,
|
|
4681
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3610
4682
|
setOpen(false);
|
|
3611
4683
|
editor.insertColumnRight();
|
|
3612
4684
|
}, children: "Inserir coluna \xE0 direita" }),
|
|
3613
|
-
/* @__PURE__ */ (0,
|
|
4685
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3614
4686
|
setOpen(false);
|
|
3615
4687
|
editor.deleteCurrentRow();
|
|
3616
4688
|
}, children: "Excluir linha" }),
|
|
3617
|
-
/* @__PURE__ */ (0,
|
|
4689
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3618
4690
|
setOpen(false);
|
|
3619
4691
|
editor.deleteCurrentColumn();
|
|
3620
4692
|
}, children: "Excluir coluna" }),
|
|
3621
|
-
/* @__PURE__ */ (0,
|
|
3622
|
-
editor.hasTableRectSelection() && /* @__PURE__ */ (0,
|
|
4693
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("hr", {}),
|
|
4694
|
+
editor.hasTableRectSelection() && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3623
4695
|
"button",
|
|
3624
4696
|
{
|
|
3625
4697
|
type: "button",
|
|
@@ -3630,19 +4702,19 @@ function TableMenu() {
|
|
|
3630
4702
|
children: "Mesclar c\xE9lulas selecionadas"
|
|
3631
4703
|
}
|
|
3632
4704
|
),
|
|
3633
|
-
/* @__PURE__ */ (0,
|
|
4705
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3634
4706
|
setOpen(false);
|
|
3635
4707
|
editor.mergeRight();
|
|
3636
4708
|
}, children: "Mesclar com c\xE9lula \xE0 direita" }),
|
|
3637
|
-
/* @__PURE__ */ (0,
|
|
4709
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3638
4710
|
setOpen(false);
|
|
3639
4711
|
editor.mergeDown();
|
|
3640
4712
|
}, children: "Mesclar com c\xE9lula abaixo" }),
|
|
3641
|
-
/* @__PURE__ */ (0,
|
|
4713
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: () => {
|
|
3642
4714
|
setOpen(false);
|
|
3643
4715
|
editor.splitCell();
|
|
3644
4716
|
}, children: "Dividir c\xE9lulas mescladas" }),
|
|
3645
|
-
/* @__PURE__ */ (0,
|
|
4717
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3646
4718
|
"button",
|
|
3647
4719
|
{
|
|
3648
4720
|
type: "button",
|
|
@@ -3663,11 +4735,11 @@ function TableMenu() {
|
|
|
3663
4735
|
var PICKER_MAX_ROWS = 8;
|
|
3664
4736
|
var PICKER_MAX_COLS = 10;
|
|
3665
4737
|
function TableSizePicker({ onPick }) {
|
|
3666
|
-
const [hover, setHover] = (0,
|
|
4738
|
+
const [hover, setHover] = (0, import_react15.useState)(null);
|
|
3667
4739
|
const label = hover ? `${hover.r + 1} \xD7 ${hover.c + 1}` : "Inserir tabela";
|
|
3668
|
-
return /* @__PURE__ */ (0,
|
|
3669
|
-
/* @__PURE__ */ (0,
|
|
3670
|
-
/* @__PURE__ */ (0,
|
|
4740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "ed-table-picker", children: [
|
|
4741
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-table-picker-label", children: label }),
|
|
4742
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3671
4743
|
"div",
|
|
3672
4744
|
{
|
|
3673
4745
|
className: "ed-table-picker-grid",
|
|
@@ -3680,7 +4752,7 @@ function TableSizePicker({ onPick }) {
|
|
|
3680
4752
|
{ length: PICKER_MAX_ROWS },
|
|
3681
4753
|
(_, r) => Array.from({ length: PICKER_MAX_COLS }, (_2, c) => {
|
|
3682
4754
|
const filled = hover != null && r <= hover.r && c <= hover.c;
|
|
3683
|
-
return /* @__PURE__ */ (0,
|
|
4755
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3684
4756
|
"button",
|
|
3685
4757
|
{
|
|
3686
4758
|
type: "button",
|
|
@@ -3710,10 +4782,10 @@ function blockSelectValue(type, level) {
|
|
|
3710
4782
|
return type;
|
|
3711
4783
|
}
|
|
3712
4784
|
function Group({ children }) {
|
|
3713
|
-
return /* @__PURE__ */ (0,
|
|
4785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ed-toolbar-group", children });
|
|
3714
4786
|
}
|
|
3715
4787
|
function MarkButton({ title, pressed, onClick, children }) {
|
|
3716
|
-
return /* @__PURE__ */ (0,
|
|
4788
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3717
4789
|
"button",
|
|
3718
4790
|
{
|
|
3719
4791
|
type: "button",
|
|
@@ -3735,6 +4807,7 @@ function MarkButton({ title, pressed, onClick, children }) {
|
|
|
3735
4807
|
LinkDialog,
|
|
3736
4808
|
NodeView,
|
|
3737
4809
|
PageConfigDialog,
|
|
4810
|
+
RemoteCursorsOverlay,
|
|
3738
4811
|
Toolbar,
|
|
3739
4812
|
applyDomSelection,
|
|
3740
4813
|
contentHeight,
|
|
@@ -3746,6 +4819,7 @@ function MarkButton({ title, pressed, onClick, children }) {
|
|
|
3746
4819
|
getCellElement,
|
|
3747
4820
|
getFragmentForOffset,
|
|
3748
4821
|
isTableRectSelection,
|
|
4822
|
+
locatePoint,
|
|
3749
4823
|
readDomSelection,
|
|
3750
4824
|
renderInline,
|
|
3751
4825
|
selectionsEqual,
|