@sofereditor/react 0.5.0 → 0.6.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 CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  getBlockElement: () => getBlockElement,
39
39
  getCellElement: () => getCellElement,
40
40
  getFragmentForOffset: () => getFragmentForOffset,
41
+ htmlToSlice: () => htmlToSlice,
41
42
  isTableRectSelection: () => isTableRectSelection,
42
43
  locatePoint: () => locatePoint,
43
44
  readDomSelection: () => readDomSelection,
@@ -54,7 +55,7 @@ module.exports = __toCommonJS(index_exports);
54
55
 
55
56
  // src/Editor.tsx
56
57
  var import_react14 = require("react");
57
- var import_core6 = require("@sofereditor/core");
58
+ var import_core8 = require("@sofereditor/core");
58
59
 
59
60
  // src/dom-bridge.ts
60
61
  function findContainingBlockElement(node, root) {
@@ -329,6 +330,615 @@ function applyDomSelection(root, modelSel) {
329
330
  }
330
331
  }
331
332
 
333
+ // src/pastePlan.ts
334
+ var import_core2 = require("@sofereditor/core");
335
+
336
+ // src/htmlToSlice.ts
337
+ var import_core = require("@sofereditor/core");
338
+ function htmlToSlice(html) {
339
+ if (!html || html.trim().length === 0) return null;
340
+ let doc;
341
+ try {
342
+ doc = new DOMParser().parseFromString(html, "text/html");
343
+ } catch {
344
+ return null;
345
+ }
346
+ const body = doc.body;
347
+ if (!body) return null;
348
+ const blocks = [];
349
+ try {
350
+ walkBlockLevel(body, {}, blocks);
351
+ } catch {
352
+ return null;
353
+ }
354
+ if (blocks.length === 0) return null;
355
+ normalizeListLevels(blocks);
356
+ const temTexto = blocks.some((b) => b.text.trim().length > 0);
357
+ if (!temTexto) return null;
358
+ const blockLevel = blocks.length > 1 || blocks[0].type !== "paragraph";
359
+ return { blocks, openStart: false, openEnd: false, ...blockLevel ? { blockLevel: true } : {} };
360
+ }
361
+ var IGNORED_TAGS = /* @__PURE__ */ new Set(["script", "style", "meta", "link", "head", "title", "xml"]);
362
+ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
363
+ "p",
364
+ "div",
365
+ "section",
366
+ "article",
367
+ "header",
368
+ "footer",
369
+ "main",
370
+ "figure",
371
+ "figcaption",
372
+ "pre",
373
+ "address"
374
+ ]);
375
+ var BLOCK_TRIGGER_TAGS = /* @__PURE__ */ new Set([
376
+ "p",
377
+ "div",
378
+ "ul",
379
+ "ol",
380
+ "li",
381
+ "h1",
382
+ "h2",
383
+ "h3",
384
+ "h4",
385
+ "h5",
386
+ "h6",
387
+ "blockquote",
388
+ "table",
389
+ "tr",
390
+ "td",
391
+ "th"
392
+ ]);
393
+ function isNamespacedTag(tag) {
394
+ return tag.includes(":");
395
+ }
396
+ function hasBlockDescendant(el) {
397
+ const all = el.querySelectorAll("*");
398
+ for (const e of Array.from(all)) {
399
+ if (BLOCK_TRIGGER_TAGS.has(e.tagName.toLowerCase())) return true;
400
+ }
401
+ return false;
402
+ }
403
+ function walkBlockLevel(container, marks, blocks) {
404
+ let loose = [];
405
+ const flushLoose = () => {
406
+ if (loose.length === 0) return;
407
+ const nodes = loose;
408
+ loose = [];
409
+ const delta = inlineDeltaFromNodes(nodes, marks);
410
+ if (delta.length > 0) blocks.push(makeBlock("paragraph", delta, {}));
411
+ };
412
+ for (const node of Array.from(container.childNodes)) {
413
+ if (node.nodeType === Node.COMMENT_NODE) continue;
414
+ if (node.nodeType === Node.TEXT_NODE) {
415
+ loose.push(node);
416
+ continue;
417
+ }
418
+ if (node.nodeType !== Node.ELEMENT_NODE) continue;
419
+ const el = node;
420
+ const tag = el.tagName.toLowerCase();
421
+ if (IGNORED_TAGS.has(tag) || isNamespacedTag(tag)) continue;
422
+ switch (tag) {
423
+ case "ul":
424
+ case "ol": {
425
+ flushLoose();
426
+ handleList(el, tag === "ol" ? "ordered" : "bullet", 0, marks, blocks);
427
+ break;
428
+ }
429
+ case "h1":
430
+ case "h2":
431
+ case "h3":
432
+ case "h4":
433
+ case "h5":
434
+ case "h6": {
435
+ flushLoose();
436
+ const level = Number(tag[1]);
437
+ const attrs = { level };
438
+ const align = readAlign(el);
439
+ if (align) attrs.align = align;
440
+ const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
441
+ blocks.push(makeBlock("heading", delta, attrs));
442
+ break;
443
+ }
444
+ case "blockquote": {
445
+ flushLoose();
446
+ handleBlockquote(el, marks, blocks);
447
+ break;
448
+ }
449
+ case "table": {
450
+ flushLoose();
451
+ handleTable(el, marks, blocks);
452
+ break;
453
+ }
454
+ case "li": {
455
+ flushLoose();
456
+ const nestedLists = topLevelListDescendants(el);
457
+ const clone = el.cloneNode(true);
458
+ for (const l of topLevelListDescendants(clone)) l.remove();
459
+ const delta = inlineDeltaFromNodes(Array.from(clone.childNodes), marks);
460
+ blocks.push(makeBlock("listItem", delta, { listKind: "bullet", listLevel: 0 }));
461
+ for (const nested of nestedLists) {
462
+ const nestedKind = nested.tagName.toLowerCase() === "ol" ? "ordered" : "bullet";
463
+ handleList(nested, nestedKind, 1, marks, blocks);
464
+ }
465
+ break;
466
+ }
467
+ case "img":
468
+ break;
469
+ case "br":
470
+ loose.push(node);
471
+ break;
472
+ default: {
473
+ const styleAttr = el.getAttribute("style") ?? "";
474
+ const wordListLevel = parseWordListLevel(styleAttr);
475
+ if (wordListLevel != null && !hasBlockDescendant(el)) {
476
+ flushLoose();
477
+ const marker = findWordListMarker(el);
478
+ const listKind = marker ? detectWordListKind(marker) : "bullet";
479
+ const attrs = { listKind, listLevel: wordListLevel };
480
+ const align = readAlign(el);
481
+ if (align) attrs.align = align;
482
+ const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
483
+ blocks.push(makeBlock("listItem", delta, attrs));
484
+ break;
485
+ }
486
+ if (hasBlockDescendant(el)) {
487
+ flushLoose();
488
+ let nextMarks = applyTagMarks(tag, marks);
489
+ nextMarks = applyStyleMarks(el.getAttribute("style"), nextMarks);
490
+ walkBlockLevel(el, nextMarks, blocks);
491
+ break;
492
+ }
493
+ if (BLOCK_LEVEL_TAGS.has(tag)) {
494
+ flushLoose();
495
+ const attrs = {};
496
+ const align = readAlign(el);
497
+ if (align) attrs.align = align;
498
+ const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
499
+ blocks.push(makeBlock("paragraph", delta, attrs));
500
+ break;
501
+ }
502
+ loose.push(node);
503
+ }
504
+ }
505
+ }
506
+ flushLoose();
507
+ }
508
+ function handleList(listEl, kind, level, marks, blocks) {
509
+ for (const child of Array.from(listEl.children)) {
510
+ const tag = child.tagName.toLowerCase();
511
+ if (tag === "ul" || tag === "ol") {
512
+ const siblingKind = tag === "ol" ? "ordered" : "bullet";
513
+ handleList(child, siblingKind, level + 1, marks, blocks);
514
+ continue;
515
+ }
516
+ if (tag !== "li") continue;
517
+ const nestedLists = topLevelListDescendants(child);
518
+ const clone = child.cloneNode(true);
519
+ for (const l of topLevelListDescendants(clone)) l.remove();
520
+ const delta = inlineDeltaFromNodes(Array.from(clone.childNodes), marks);
521
+ const attrs = { listKind: kind, listLevel: clampLevel(level) };
522
+ const align = readAlign(child);
523
+ if (align) attrs.align = align;
524
+ blocks.push(makeBlock("listItem", delta, attrs));
525
+ for (const nested of nestedLists) {
526
+ const nestedKind = nested.tagName.toLowerCase() === "ol" ? "ordered" : "bullet";
527
+ handleList(nested, nestedKind, level + 1, marks, blocks);
528
+ }
529
+ }
530
+ }
531
+ function topLevelListDescendants(root) {
532
+ const all = Array.from(root.querySelectorAll("ul, ol"));
533
+ return all.filter((el) => {
534
+ let p = el.parentElement;
535
+ while (p && p !== root) {
536
+ const t = p.tagName.toLowerCase();
537
+ if (t === "ul" || t === "ol" || t === "table" || t === "td" || t === "th") return false;
538
+ p = p.parentElement;
539
+ }
540
+ return true;
541
+ });
542
+ }
543
+ function handleBlockquote(el, marks, blocks) {
544
+ if (!hasBlockDescendant(el)) {
545
+ const attrs = {};
546
+ const align = readAlign(el);
547
+ if (align) attrs.align = align;
548
+ const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
549
+ blocks.push(makeBlock("blockquote", delta, attrs));
550
+ return;
551
+ }
552
+ const nested = [];
553
+ walkBlockLevel(el, marks, nested);
554
+ for (const b of nested) {
555
+ blocks.push(b.type === "paragraph" ? { ...b, type: "blockquote" } : b);
556
+ }
557
+ }
558
+ function handleTable(table, marks, blocks) {
559
+ for (const row of directRows(table)) {
560
+ const cells = Array.from(row.children).filter(
561
+ (c) => ["td", "th"].includes(c.tagName.toLowerCase())
562
+ );
563
+ for (const cell of cells) {
564
+ const cellBlocks = [];
565
+ walkBlockLevel(cell, marks, cellBlocks);
566
+ for (const b of cellBlocks) {
567
+ const attrs = {};
568
+ if (b.attrs.align) attrs.align = b.attrs.align;
569
+ blocks.push(makeBlock("paragraph", b.delta, attrs));
570
+ }
571
+ }
572
+ }
573
+ }
574
+ function directRows(table) {
575
+ const rows = [];
576
+ for (const child of Array.from(table.children)) {
577
+ const tag = child.tagName.toLowerCase();
578
+ if (tag === "tr") {
579
+ rows.push(child);
580
+ } else if (tag === "tbody" || tag === "thead" || tag === "tfoot") {
581
+ for (const r of Array.from(child.children)) {
582
+ if (r.tagName.toLowerCase() === "tr") rows.push(r);
583
+ }
584
+ }
585
+ }
586
+ return rows;
587
+ }
588
+ function parseWordListLevel(styleAttr) {
589
+ const m = /mso-list\s*:\s*l\d+\s+level(\d+)/i.exec(styleAttr);
590
+ if (!m) return null;
591
+ const n = Number.parseInt(m[1], 10);
592
+ const fromLevelN = Number.isFinite(n) ? Math.max(0, n - 1) : 0;
593
+ const fromMargin = wordListLevelFromMarginLeft(marginLeftPt(styleAttr));
594
+ return clampLevel(Math.max(fromLevelN, fromMargin));
595
+ }
596
+ function marginLeftPt(styleAttr) {
597
+ const raw = parseStyle(styleAttr)["margin-left"];
598
+ if (!raw) return 0;
599
+ const m = /^(-?[\d.]+)\s*(pt|cm|in|px)$/i.exec(raw.trim());
600
+ if (!m) return 0;
601
+ const val = Number.parseFloat(m[1]);
602
+ if (!Number.isFinite(val) || val < 0) return 0;
603
+ switch (m[2].toLowerCase()) {
604
+ case "pt":
605
+ return val;
606
+ case "cm":
607
+ return val * 28.3465;
608
+ case "in":
609
+ return val * 72;
610
+ case "px":
611
+ return val * 0.75;
612
+ default:
613
+ return 0;
614
+ }
615
+ }
616
+ function wordListLevelFromMarginLeft(pt) {
617
+ if (pt <= 0) return 0;
618
+ return Math.max(0, Math.round(pt / 36) - 1);
619
+ }
620
+ function findWordListMarker(el) {
621
+ const all = el.querySelectorAll("*");
622
+ for (const e of Array.from(all)) {
623
+ const style = (e.getAttribute("style") ?? "").toLowerCase().replace(/\s+/g, "");
624
+ if (style.includes("mso-list:ignore")) return e;
625
+ }
626
+ return null;
627
+ }
628
+ function detectWordListKind(markerEl) {
629
+ const all = [markerEl, ...Array.from(markerEl.querySelectorAll("*"))];
630
+ for (const e of all) {
631
+ const style = (e.getAttribute("style") ?? "").toLowerCase();
632
+ if (style.includes("symbol") || style.includes("wingdings")) return "bullet";
633
+ }
634
+ const text = (markerEl.textContent ?? "").replace(/ /g, " ").trim();
635
+ if (/^[0-9]+[.)]/.test(text)) return "ordered";
636
+ if (/^[a-zA-Z][.)]/.test(text)) return "ordered";
637
+ return "bullet";
638
+ }
639
+ function inlineDeltaFromNodes(nodes, marks) {
640
+ const ops = [];
641
+ for (const n of nodes) walkInlineNode(n, marks, ops);
642
+ return trimEdgeWhitespace(collapseRepeatedSpaces(mergeAdjacentOps(ops)));
643
+ }
644
+ function collapseRepeatedSpaces(ops) {
645
+ return ops.map(
646
+ (op) => typeof op.insert === "string" ? { ...op, insert: op.insert.replace(/ {2,}/g, " ") } : op
647
+ );
648
+ }
649
+ function walkInlineNode(node, marks, ops) {
650
+ if (node.nodeType === Node.COMMENT_NODE) return;
651
+ if (node.nodeType === Node.TEXT_NODE) {
652
+ const text = normalizeWhitespace(node.textContent ?? "");
653
+ if (text.length > 0) pushOp(ops, text, marks);
654
+ return;
655
+ }
656
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
657
+ const el = node;
658
+ const tag = el.tagName.toLowerCase();
659
+ if (IGNORED_TAGS.has(tag) || isNamespacedTag(tag)) return;
660
+ if (tag === "img") return;
661
+ if (tag === "br") {
662
+ ops.push({ insert: " " });
663
+ return;
664
+ }
665
+ const styleAttr = (el.getAttribute("style") ?? "").toLowerCase().replace(/\s+/g, "");
666
+ if (styleAttr.includes("mso-list:ignore")) return;
667
+ let nextMarks = applyTagMarks(tag, marks);
668
+ nextMarks = applyStyleMarks(el.getAttribute("style"), nextMarks);
669
+ if (tag === "a") {
670
+ const href = el.getAttribute("href");
671
+ if (href) nextMarks = { ...nextMarks, link: { href } };
672
+ }
673
+ for (const child of Array.from(el.childNodes)) walkInlineNode(child, nextMarks, ops);
674
+ }
675
+ function applyTagMarks(tag, marks) {
676
+ switch (tag) {
677
+ case "b":
678
+ case "strong":
679
+ return { ...marks, bold: true };
680
+ case "i":
681
+ case "em":
682
+ return { ...marks, italic: true };
683
+ case "u":
684
+ return { ...marks, underline: true };
685
+ case "s":
686
+ case "strike":
687
+ case "del":
688
+ return { ...marks, strike: true };
689
+ default:
690
+ return marks;
691
+ }
692
+ }
693
+ function parseStyle(styleAttr) {
694
+ const out = {};
695
+ if (!styleAttr) return out;
696
+ for (const decl of styleAttr.split(";")) {
697
+ const idx = decl.indexOf(":");
698
+ if (idx === -1) continue;
699
+ const prop = decl.slice(0, idx).trim().toLowerCase();
700
+ const val = decl.slice(idx + 1).trim();
701
+ if (prop) out[prop] = val;
702
+ }
703
+ return out;
704
+ }
705
+ function applyStyleMarks(styleAttr, marks) {
706
+ const decls = parseStyle(styleAttr);
707
+ if (Object.keys(decls).length === 0) return marks;
708
+ const next = { ...marks };
709
+ if ("font-weight" in decls) {
710
+ const v = decls["font-weight"].toLowerCase();
711
+ if (v === "bold" || /^[5-9]00$/.test(v)) next.bold = true;
712
+ else if (v === "normal" || /^[1-4]00$/.test(v)) delete next.bold;
713
+ }
714
+ if ("font-style" in decls) {
715
+ const v = decls["font-style"].toLowerCase();
716
+ if (v === "italic" || v === "oblique") next.italic = true;
717
+ else if (v === "normal") delete next.italic;
718
+ }
719
+ const deco = decls["text-decoration-line"] ?? decls["text-decoration"];
720
+ if (deco !== void 0) {
721
+ const v = deco.toLowerCase();
722
+ delete next.underline;
723
+ delete next.strike;
724
+ if (v.includes("underline")) next.underline = true;
725
+ if (v.includes("line-through")) next.strike = true;
726
+ }
727
+ if ("color" in decls) {
728
+ const css = normalizeCssColor(decls.color);
729
+ if (css && !isBlack(css)) next.color = css;
730
+ else delete next.color;
731
+ }
732
+ const bg = decls["background-color"] ?? decls.background;
733
+ if (bg !== void 0) {
734
+ const css = normalizeCssColor(bg);
735
+ if (css && css !== "#ffffff") next.highlight = css;
736
+ else delete next.highlight;
737
+ }
738
+ if ("font-size" in decls) {
739
+ const pt = parseFontSizePt(decls["font-size"]);
740
+ if (pt != null) next.fontSize = formatFontSizePt(pt);
741
+ }
742
+ return next;
743
+ }
744
+ function parseFontSizePt(raw) {
745
+ const v = raw.trim().toLowerCase();
746
+ const m = /^(-?[\d.]+)\s*(pt|px|in)$/.exec(v);
747
+ if (!m) return void 0;
748
+ const num = Number.parseFloat(m[1]);
749
+ if (!Number.isFinite(num)) return void 0;
750
+ let pt;
751
+ switch (m[2]) {
752
+ case "pt":
753
+ pt = num;
754
+ break;
755
+ case "px":
756
+ pt = num * 0.75;
757
+ break;
758
+ case "in":
759
+ pt = num * 72;
760
+ break;
761
+ default:
762
+ return void 0;
763
+ }
764
+ const rounded = Math.round(pt * 10) / 10;
765
+ if (rounded <= 0 || rounded > 200) return void 0;
766
+ return rounded;
767
+ }
768
+ function formatFontSizePt(pt) {
769
+ const rounded = Math.round(pt * 10) / 10;
770
+ const str = Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
771
+ return `${str}pt`;
772
+ }
773
+ var NAMED_COLORS = {
774
+ black: "#000000",
775
+ white: "#ffffff",
776
+ red: "#ff0000",
777
+ green: "#008000",
778
+ blue: "#0000ff",
779
+ yellow: "#ffff00",
780
+ cyan: "#00ffff",
781
+ magenta: "#ff00ff",
782
+ gray: "#808080",
783
+ grey: "#808080",
784
+ orange: "#ffa500",
785
+ purple: "#800080"
786
+ };
787
+ function normalizeCssColor(raw) {
788
+ if (!raw) return void 0;
789
+ const v = raw.trim().toLowerCase();
790
+ if (!v || v === "transparent" || v === "none" || v === "inherit" || v === "initial") return void 0;
791
+ if (v.startsWith("#")) {
792
+ let hex = v.slice(1);
793
+ if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
794
+ return /^[0-9a-f]{6}$/.test(hex) ? `#${hex}` : void 0;
795
+ }
796
+ const rgbMatch = /^rgba?\(([^)]+)\)$/.exec(v);
797
+ if (rgbMatch) {
798
+ const parts = rgbMatch[1].split(",").map((s) => s.trim());
799
+ if (parts.length < 3) return void 0;
800
+ const alpha = parts[3] !== void 0 ? Number.parseFloat(parts[3]) : 1;
801
+ if (alpha === 0) return void 0;
802
+ const toHex = (n) => {
803
+ const num = Math.max(0, Math.min(255, Number.parseInt(n, 10) || 0));
804
+ return num.toString(16).padStart(2, "0");
805
+ };
806
+ return `#${toHex(parts[0])}${toHex(parts[1])}${toHex(parts[2])}`;
807
+ }
808
+ return NAMED_COLORS[v];
809
+ }
810
+ function isBlack(hex) {
811
+ return hex.toLowerCase() === "#000000";
812
+ }
813
+ function readAlign(el) {
814
+ const style = parseStyle(el.getAttribute("style"));
815
+ const v = style["text-align"];
816
+ if (!v) return void 0;
817
+ switch (v.toLowerCase()) {
818
+ case "left":
819
+ case "start":
820
+ return "left";
821
+ case "center":
822
+ return "center";
823
+ case "right":
824
+ case "end":
825
+ return "right";
826
+ case "justify":
827
+ return "justify";
828
+ default:
829
+ return void 0;
830
+ }
831
+ }
832
+ function clampLevel(n) {
833
+ if (!Number.isFinite(n)) return 0;
834
+ return Math.max(0, Math.min(import_core.MAX_LIST_LEVEL, Math.trunc(n)));
835
+ }
836
+ function normalizeListLevels(blocks) {
837
+ let i = 0;
838
+ while (i < blocks.length) {
839
+ if (blocks[i].type !== "listItem") {
840
+ i++;
841
+ continue;
842
+ }
843
+ let j = i + 1;
844
+ while (j < blocks.length && blocks[j].type === "listItem") j++;
845
+ if (j - i > 1) {
846
+ let min = Number.POSITIVE_INFINITY;
847
+ for (let k = i; k < j; k++) {
848
+ const lvl = blocks[k].attrs.listLevel ?? 0;
849
+ if (lvl < min) min = lvl;
850
+ }
851
+ if (min > 0) {
852
+ for (let k = i; k < j; k++) {
853
+ const lvl = blocks[k].attrs.listLevel ?? 0;
854
+ blocks[k].attrs.listLevel = clampLevel(lvl - min);
855
+ }
856
+ }
857
+ }
858
+ i = j;
859
+ }
860
+ }
861
+ function pushOp(ops, text, marks) {
862
+ const hasMarks = Object.keys(marks).length > 0;
863
+ ops.push(hasMarks ? { insert: text, attributes: { ...marks } } : { insert: text });
864
+ }
865
+ function normalizeWhitespace(raw) {
866
+ return raw.replace(/[ \t\r\n]+/g, " ");
867
+ }
868
+ function trimEdgeWhitespace(ops) {
869
+ let out = ops;
870
+ if (out.length > 0 && typeof out[0].insert === "string") {
871
+ const trimmed = out[0].insert.replace(/^ +/, "");
872
+ if (trimmed.length === 0) out = out.slice(1);
873
+ else if (trimmed !== out[0].insert) out = [{ ...out[0], insert: trimmed }, ...out.slice(1)];
874
+ }
875
+ if (out.length > 0 && typeof out[out.length - 1].insert === "string") {
876
+ const last = out[out.length - 1];
877
+ const trimmed = last.insert.replace(/ +$/, "");
878
+ if (trimmed.length === 0) out = out.slice(0, -1);
879
+ else if (trimmed !== last.insert) out = [...out.slice(0, -1), { ...last, insert: trimmed }];
880
+ }
881
+ return out;
882
+ }
883
+ function mergeAdjacentOps(ops) {
884
+ const out = [];
885
+ for (const op of ops) {
886
+ const prev = out[out.length - 1];
887
+ if (prev && typeof prev.insert === "string" && typeof op.insert === "string" && sameMarks(prev.attributes, op.attributes)) {
888
+ prev.insert = prev.insert + op.insert;
889
+ continue;
890
+ }
891
+ out.push({ ...op });
892
+ }
893
+ return out;
894
+ }
895
+ function sameMarks(a, b) {
896
+ const ak = a ? Object.keys(a).sort() : [];
897
+ const bk = b ? Object.keys(b).sort() : [];
898
+ if (ak.length !== bk.length) return false;
899
+ for (let i = 0; i < ak.length; i++) {
900
+ if (ak[i] !== bk[i]) return false;
901
+ const av = a[ak[i]];
902
+ const bv = b[bk[i]];
903
+ if (typeof av === "object" && av !== null && typeof bv === "object" && bv !== null) {
904
+ if (JSON.stringify(av) !== JSON.stringify(bv)) return false;
905
+ } else if (av !== bv) {
906
+ return false;
907
+ }
908
+ }
909
+ return true;
910
+ }
911
+ function deltaToText(delta) {
912
+ let s = "";
913
+ for (const op of delta) if (typeof op.insert === "string") s += op.insert;
914
+ return s;
915
+ }
916
+ function makeBlock(type, delta, attrs) {
917
+ return { type, text: deltaToText(delta), delta, attrs };
918
+ }
919
+
920
+ // src/pastePlan.ts
921
+ function planPaste(cd) {
922
+ const raw = cd.getData(import_core2.SOFER_MIME);
923
+ if (raw) {
924
+ try {
925
+ const slice = JSON.parse(raw);
926
+ if (slice && Array.isArray(slice.blocks)) return { kind: "sofer", slice };
927
+ } catch {
928
+ }
929
+ }
930
+ const html = cd.getData("text/html");
931
+ if (html) {
932
+ const slice = htmlToSlice(html);
933
+ if (slice) return { kind: "html", slice };
934
+ }
935
+ const files = Array.from(cd.files ?? []).filter((f) => f.type.startsWith("image/"));
936
+ if (files.length > 0) return { kind: "images", files };
937
+ const text = cd.getData("text/plain");
938
+ if (text.length > 0) return { kind: "text", text };
939
+ return { kind: "none" };
940
+ }
941
+
332
942
  // src/BehindImageSelectAffordance.tsx
333
943
  var import_react = require("react");
334
944
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -645,7 +1255,7 @@ function LinkDialog() {
645
1255
 
646
1256
  // src/PageConfigDialog.tsx
647
1257
  var import_react3 = require("react");
648
- var import_core = require("@sofereditor/core");
1258
+ var import_core3 = require("@sofereditor/core");
649
1259
  var import_jsx_runtime4 = require("react/jsx-runtime");
650
1260
  function PageConfigDialog() {
651
1261
  const { pageConfigRequest, resolvePageConfigRequest, setPageSettings } = useEditorContext();
@@ -679,14 +1289,14 @@ function PageConfigDialog() {
679
1289
  }, [pageConfigRequest]);
680
1290
  (0, import_react3.useEffect)(() => {
681
1291
  if (sizePreset === "custom") return;
682
- const p = import_core.PAGE_PRESETS[sizePreset];
683
- setWidthMm(roundMm((0, import_core.pxToMm)(p.width)));
684
- setHeightMm(roundMm((0, import_core.pxToMm)(p.height)));
1292
+ const p = import_core3.PAGE_PRESETS[sizePreset];
1293
+ setWidthMm(roundMm((0, import_core3.pxToMm)(p.width)));
1294
+ setHeightMm(roundMm((0, import_core3.pxToMm)(p.height)));
685
1295
  }, [sizePreset]);
686
1296
  (0, import_react3.useEffect)(() => {
687
1297
  if (marginPreset === "custom") return;
688
- const px = import_core.MARGIN_PRESETS[marginPreset];
689
- const mm = roundMm((0, import_core.pxToMm)(px));
1298
+ const px = import_core3.MARGIN_PRESETS[marginPreset];
1299
+ const mm = roundMm((0, import_core3.pxToMm)(px));
690
1300
  setMarginTopMm(mm);
691
1301
  setMarginBottomMm(mm);
692
1302
  setMarginLeftMm(mm);
@@ -695,8 +1305,8 @@ function PageConfigDialog() {
695
1305
  const customWidth = sizePreset === "custom";
696
1306
  const previewPx = (0, import_react3.useMemo)(
697
1307
  () => ({
698
- width: Math.round((0, import_core.mmToPx)(widthMm)),
699
- height: Math.round((0, import_core.mmToPx)(heightMm))
1308
+ width: Math.round((0, import_core3.mmToPx)(widthMm)),
1309
+ height: Math.round((0, import_core3.mmToPx)(heightMm))
700
1310
  }),
701
1311
  [widthMm, heightMm]
702
1312
  );
@@ -704,12 +1314,12 @@ function PageConfigDialog() {
704
1314
  const onApply = (e) => {
705
1315
  e.preventDefault();
706
1316
  const next = {
707
- width: (0, import_core.mmToPx)(widthMm),
708
- height: (0, import_core.mmToPx)(heightMm),
709
- marginTop: (0, import_core.mmToPx)(marginTopMm),
710
- marginBottom: (0, import_core.mmToPx)(marginBottomMm),
711
- marginLeft: (0, import_core.mmToPx)(marginLeftMm),
712
- marginRight: (0, import_core.mmToPx)(marginRightMm)
1317
+ width: (0, import_core3.mmToPx)(widthMm),
1318
+ height: (0, import_core3.mmToPx)(heightMm),
1319
+ marginTop: (0, import_core3.mmToPx)(marginTopMm),
1320
+ marginBottom: (0, import_core3.mmToPx)(marginBottomMm),
1321
+ marginLeft: (0, import_core3.mmToPx)(marginLeftMm),
1322
+ marginRight: (0, import_core3.mmToPx)(marginRightMm)
713
1323
  };
714
1324
  setPageSettings(next);
715
1325
  resolvePageConfigRequest(true);
@@ -968,14 +1578,14 @@ function roundMm(mm) {
968
1578
  return Math.round(mm * 10) / 10;
969
1579
  }
970
1580
  function hydrateFromSettings(s, setters) {
971
- const preset = (0, import_core.detectPreset)(s.width, s.height);
1581
+ const preset = (0, import_core3.detectPreset)(s.width, s.height);
972
1582
  setters.setSizePreset(preset);
973
- setters.setWidthMm(roundMm((0, import_core.pxToMm)(s.width)));
974
- setters.setHeightMm(roundMm((0, import_core.pxToMm)(s.height)));
975
- const top = roundMm((0, import_core.pxToMm)(s.marginTop));
976
- const bottom = roundMm((0, import_core.pxToMm)(s.marginBottom));
977
- const left = roundMm((0, import_core.pxToMm)(s.marginLeft));
978
- const right = roundMm((0, import_core.pxToMm)(s.marginRight));
1583
+ setters.setWidthMm(roundMm((0, import_core3.pxToMm)(s.width)));
1584
+ setters.setHeightMm(roundMm((0, import_core3.pxToMm)(s.height)));
1585
+ const top = roundMm((0, import_core3.pxToMm)(s.marginTop));
1586
+ const bottom = roundMm((0, import_core3.pxToMm)(s.marginBottom));
1587
+ const left = roundMm((0, import_core3.pxToMm)(s.marginLeft));
1588
+ const right = roundMm((0, import_core3.pxToMm)(s.marginRight));
979
1589
  setters.setMarginTopMm(top);
980
1590
  setters.setMarginBottomMm(bottom);
981
1591
  setters.setMarginLeftMm(left);
@@ -986,7 +1596,7 @@ function detectMarginPreset(s) {
986
1596
  const TOL = 1;
987
1597
  const allEqual = Math.abs(s.marginTop - s.marginBottom) <= TOL && Math.abs(s.marginTop - s.marginLeft) <= TOL && Math.abs(s.marginTop - s.marginRight) <= TOL;
988
1598
  if (!allEqual) return "custom";
989
- for (const [name, px] of Object.entries(import_core.MARGIN_PRESETS)) {
1599
+ for (const [name, px] of Object.entries(import_core3.MARGIN_PRESETS)) {
990
1600
  if (Math.abs(s.marginTop - px) <= TOL) return name;
991
1601
  }
992
1602
  return "custom";
@@ -1546,7 +2156,7 @@ function Handle({
1546
2156
 
1547
2157
  // src/RemoteCursorsOverlay.tsx
1548
2158
  var import_react7 = require("react");
1549
- var import_core2 = require("@sofereditor/core");
2159
+ var import_core4 = require("@sofereditor/core");
1550
2160
  var import_jsx_runtime8 = require("react/jsx-runtime");
1551
2161
  var DEFAULT_COLOR = "#3b82f6";
1552
2162
  function RemoteCursorsOverlay({
@@ -1569,7 +2179,7 @@ function RemoteCursorsOverlay({
1569
2179
  if (clientId === awareness.clientID) return;
1570
2180
  const s = state;
1571
2181
  if (!s.cursor) return;
1572
- const sel = (0, import_core2.decodeSelection)(doc, s.cursor);
2182
+ const sel = (0, import_core4.decodeSelection)(doc, s.cursor);
1573
2183
  if (!sel) return;
1574
2184
  const color = s.user?.color || DEFAULT_COLOR;
1575
2185
  const name = s.user?.name || "An\xF4nimo";
@@ -1716,11 +2326,11 @@ function RemoteCursorsOverlay({
1716
2326
 
1717
2327
  // src/NodeView.tsx
1718
2328
  var import_react10 = require("react");
1719
- var import_core4 = require("@sofereditor/core");
2329
+ var import_core6 = require("@sofereditor/core");
1720
2330
 
1721
2331
  // src/renderInline.tsx
1722
2332
  var import_react8 = require("react");
1723
- var import_core3 = require("@sofereditor/core");
2333
+ var import_core5 = require("@sofereditor/core");
1724
2334
  var import_jsx_runtime9 = require("react/jsx-runtime");
1725
2335
  function renderInline(delta, keyPrefix) {
1726
2336
  if (delta.length === 0 || delta.length === 1 && typeof delta[0].insert === "string" && delta[0].insert === "") {
@@ -1736,7 +2346,7 @@ function renderInline(delta, keyPrefix) {
1736
2346
  const key = `${keyPrefix}-${offset}`;
1737
2347
  body.push(/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: wrap(text, op.attributes) }, key));
1738
2348
  offset += text.length;
1739
- } else if ((0, import_core3.isImageEmbed)(op.insert)) {
2349
+ } else if ((0, import_core5.isImageEmbed)(op.insert)) {
1740
2350
  const key = `${keyPrefix}-${offset}`;
1741
2351
  const layout = op.insert.layout ?? "inline";
1742
2352
  const commentMarkId = op.attributes?.comment?.markId;
@@ -1900,10 +2510,10 @@ function ImageEmbedViewImpl({
1900
2510
  );
1901
2511
  }
1902
2512
  function decorateBlanks(text) {
1903
- const segs = (0, import_core3.splitUnderscoreRuns)(text);
2513
+ const segs = (0, import_core5.splitUnderscoreRuns)(text);
1904
2514
  if (segs.length === 1 && !segs[0].blank) return text;
1905
2515
  return segs.map(
1906
- (s, i) => s.blank ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-blank": "true", style: import_core3.BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: s.text }, i)
2516
+ (s, i) => s.blank ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { "data-blank": "true", style: import_core5.BLANK_STYLE, children: s.text }, i) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react8.Fragment, { children: s.text }, i)
1907
2517
  );
1908
2518
  }
1909
2519
  function wrap(text, attrs) {
@@ -2101,7 +2711,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2101
2711
  const common = commonBlockProps(block.attrs, index, block.type, fragment);
2102
2712
  switch (block.type) {
2103
2713
  case "heading": {
2104
- const level = clampLevel(block.attrs.level);
2714
+ const level = clampLevel2(block.attrs.level);
2105
2715
  const Tag = `h${level}`;
2106
2716
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2107
2717
  Tag,
@@ -2162,7 +2772,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
2162
2772
  function commonBlockProps(attrs, index, type, fragment) {
2163
2773
  const style = {};
2164
2774
  if (attrs.align) style.textAlign = attrs.align;
2165
- Object.assign(style, (0, import_core4.answerLineStyle)(attrs) ?? {});
2775
+ Object.assign(style, (0, import_core6.answerLineStyle)(attrs) ?? {});
2166
2776
  const base = {
2167
2777
  "data-block-index": index,
2168
2778
  "data-block-type": type,
@@ -2188,7 +2798,7 @@ function cellStyle(attrs, border) {
2188
2798
  if (attrs?.bgColor) style.backgroundColor = attrs.bgColor;
2189
2799
  return Object.keys(style).length > 0 ? style : void 0;
2190
2800
  }
2191
- function clampLevel(l) {
2801
+ function clampLevel2(l) {
2192
2802
  if (l === 2 || l === 3 || l === 4 || l === 5 || l === 6) return l;
2193
2803
  return 1;
2194
2804
  }
@@ -2209,7 +2819,7 @@ function TableView({ block, index, tableFragment }) {
2209
2819
  const rect = (0, import_react10.useMemo)(() => {
2210
2820
  if (editor.selection.anchor.blockIndex !== index) return null;
2211
2821
  if (editor.selection.focus.blockIndex !== index) return null;
2212
- return (0, import_core4.tableRectSelection)(editor.doc, editor.selection);
2822
+ return (0, import_core6.tableRectSelection)(editor.doc, editor.selection);
2213
2823
  }, [editor.doc, editor.selection, index]);
2214
2824
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "ed-table-wrap", children: [
2215
2825
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
@@ -2245,7 +2855,7 @@ function TableView({ block, index, tableFragment }) {
2245
2855
  cell?.attrs,
2246
2856
  // rowStart/rowEnd são os limites do FRAGMENTO: numa tabela
2247
2857
  // quebrada entre páginas, cada página fecha a própria caixa.
2248
- (0, import_core4.cellBorderStyle)(
2858
+ (0, import_core6.cellBorderStyle)(
2249
2859
  block.attrs.borderPreset,
2250
2860
  { row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
2251
2861
  "screen",
@@ -2821,14 +3431,14 @@ function shallowEqual(a, b) {
2821
3431
  }
2822
3432
 
2823
3433
  // src/useEditor.ts
2824
- var import_core5 = require("@sofereditor/core");
3434
+ var import_core7 = require("@sofereditor/core");
2825
3435
  var MAX_INSERT_WIDTH = 600;
2826
3436
  function useEditor(opts = {}) {
2827
- const doc = (0, import_react13.useMemo)(() => opts.document ?? new import_core5.EditorDocument(), [opts.document]);
2828
- const history = (0, import_react13.useMemo)(() => new import_core5.EditorHistory(doc), [doc]);
3437
+ const doc = (0, import_react13.useMemo)(() => opts.document ?? new import_core7.EditorDocument(), [opts.document]);
3438
+ const history = (0, import_react13.useMemo)(() => new import_core7.EditorHistory(doc), [doc]);
2829
3439
  const [snapshot, setSnapshot] = (0, import_react13.useState)(() => doc.toJSON());
2830
3440
  const [selection, setSelectionState] = (0, import_react13.useState)(
2831
- () => (0, import_core5.collapsedSelection)({ blockIndex: 0, offset: 0 })
3441
+ () => (0, import_core7.collapsedSelection)({ blockIndex: 0, offset: 0 })
2832
3442
  );
2833
3443
  const selectionRef = (0, import_react13.useRef)(selection);
2834
3444
  selectionRef.current = selection;
@@ -2893,7 +3503,7 @@ function useEditor(opts = {}) {
2893
3503
  const isMarkActive = (0, import_react13.useCallback)(
2894
3504
  (name, value) => {
2895
3505
  const sel = selectionRef.current;
2896
- const { start, end } = (0, import_core5.orderedRange)(sel);
3506
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2897
3507
  if (start.blockIndex === end.blockIndex && start.offset === end.offset) {
2898
3508
  const pending = pendingMarksRef.current[name];
2899
3509
  if (pending !== void 0) {
@@ -2902,7 +3512,7 @@ function useEditor(opts = {}) {
2902
3512
  }
2903
3513
  const yText2 = doc.getBlockText(start.blockIndex);
2904
3514
  if (!yText2 || start.offset === 0) return false;
2905
- return (0, import_core5.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
3515
+ return (0, import_core7.isMarkUniformInRange)(yText2, start.offset - 1, start.offset, name, value);
2906
3516
  }
2907
3517
  if (start.blockIndex !== end.blockIndex) {
2908
3518
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
@@ -2911,19 +3521,19 @@ function useEditor(opts = {}) {
2911
3521
  const s = i === start.blockIndex ? start.offset : 0;
2912
3522
  const e = i === end.blockIndex ? end.offset : yText2.length;
2913
3523
  if (s >= e) continue;
2914
- if (!(0, import_core5.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
3524
+ if (!(0, import_core7.isMarkUniformInRange)(yText2, s, e, name, value)) return false;
2915
3525
  }
2916
3526
  return true;
2917
3527
  }
2918
3528
  const yText = doc.getBlockText(start.blockIndex);
2919
3529
  if (!yText) return false;
2920
- return (0, import_core5.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
3530
+ return (0, import_core7.isMarkUniformInRange)(yText, start.offset, end.offset, name, value);
2921
3531
  },
2922
3532
  [doc]
2923
3533
  );
2924
3534
  const getActiveMarks = (0, import_react13.useCallback)(() => {
2925
3535
  const sel = selectionRef.current;
2926
- const { start, end } = (0, import_core5.orderedRange)(sel);
3536
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2927
3537
  if (start.blockIndex !== end.blockIndex) {
2928
3538
  return {};
2929
3539
  }
@@ -2931,14 +3541,14 @@ function useEditor(opts = {}) {
2931
3541
  if (!yText) return {};
2932
3542
  if (start.offset === end.offset) {
2933
3543
  if (start.offset === 0) return {};
2934
- return (0, import_core5.getMarksInRange)(yText, start.offset - 1, start.offset);
3544
+ return (0, import_core7.getMarksInRange)(yText, start.offset - 1, start.offset);
2935
3545
  }
2936
- return (0, import_core5.getMarksInRange)(yText, start.offset, end.offset);
3546
+ return (0, import_core7.getMarksInRange)(yText, start.offset, end.offset);
2937
3547
  }, [doc]);
2938
3548
  const toggleMark = (0, import_react13.useCallback)(
2939
3549
  (name, value) => {
2940
3550
  const sel = selectionRef.current;
2941
- const { start, end } = (0, import_core5.orderedRange)(sel);
3551
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2942
3552
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
2943
3553
  if (isCollapsed) {
2944
3554
  const next = { ...pendingMarksRef.current };
@@ -2951,39 +3561,39 @@ function useEditor(opts = {}) {
2951
3561
  setPendingMarks(next);
2952
3562
  return;
2953
3563
  }
2954
- (0, import_core5.toggleMark)(ctxRef.current, name, value);
3564
+ (0, import_core7.toggleMark)(ctxRef.current, name, value);
2955
3565
  },
2956
3566
  [isMarkActive, setPendingMarks]
2957
3567
  );
2958
3568
  const setMark = (0, import_react13.useCallback)(
2959
3569
  (name, value) => {
2960
3570
  const sel = selectionRef.current;
2961
- const { start, end } = (0, import_core5.orderedRange)(sel);
3571
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2962
3572
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
2963
3573
  if (isCollapsed) {
2964
3574
  setPendingMarks({ ...pendingMarksRef.current, [name]: value });
2965
3575
  return;
2966
3576
  }
2967
- (0, import_core5.setMark)(ctxRef.current, name, value);
3577
+ (0, import_core7.setMark)(ctxRef.current, name, value);
2968
3578
  },
2969
3579
  [setPendingMarks]
2970
3580
  );
2971
3581
  const removeMark = (0, import_react13.useCallback)(
2972
3582
  (name) => {
2973
3583
  const sel = selectionRef.current;
2974
- const { start, end } = (0, import_core5.orderedRange)(sel);
3584
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2975
3585
  const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;
2976
3586
  if (isCollapsed) {
2977
3587
  setPendingMarks({ ...pendingMarksRef.current, [name]: null });
2978
3588
  return;
2979
3589
  }
2980
- (0, import_core5.removeMark)(ctxRef.current, name);
3590
+ (0, import_core7.removeMark)(ctxRef.current, name);
2981
3591
  },
2982
3592
  [setPendingMarks]
2983
3593
  );
2984
3594
  const getBlockType = (0, import_react13.useCallback)(() => {
2985
3595
  const sel = selectionRef.current;
2986
- const { start, end } = (0, import_core5.orderedRange)(sel);
3596
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2987
3597
  const first = doc.getBlockType(start.blockIndex);
2988
3598
  if (first === void 0) return "paragraph";
2989
3599
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
@@ -2994,7 +3604,7 @@ function useEditor(opts = {}) {
2994
3604
  const getBlockAttr = (0, import_react13.useCallback)(
2995
3605
  (key) => {
2996
3606
  const sel = selectionRef.current;
2997
- const { start, end } = (0, import_core5.orderedRange)(sel);
3607
+ const { start, end } = (0, import_core7.orderedRange)(sel);
2998
3608
  const first = doc.getBlockAttrs(start.blockIndex)[key];
2999
3609
  for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {
3000
3610
  const next = doc.getBlockAttrs(i)[key];
@@ -3005,19 +3615,19 @@ function useEditor(opts = {}) {
3005
3615
  [doc]
3006
3616
  );
3007
3617
  const setBlockType = (0, import_react13.useCallback)((type, attrs) => {
3008
- (0, import_core5.setBlockType)(ctxRef.current, type, attrs);
3618
+ (0, import_core7.setBlockType)(ctxRef.current, type, attrs);
3009
3619
  }, []);
3010
3620
  const setBlockAttr = (0, import_react13.useCallback)(
3011
3621
  (key, value) => {
3012
- (0, import_core5.setBlockAttr)(ctxRef.current, key, value);
3622
+ (0, import_core7.setBlockAttr)(ctxRef.current, key, value);
3013
3623
  },
3014
3624
  []
3015
3625
  );
3016
3626
  const setAlign = (0, import_react13.useCallback)((value) => {
3017
3627
  const sel = selectionRef.current;
3018
3628
  const inCell = sel.focus.cellIndex != null;
3019
- if (inCell) (0, import_core5.setCellAttr)(ctxRef.current, "align", value);
3020
- else (0, import_core5.setBlockAttr)(ctxRef.current, "align", value);
3629
+ if (inCell) (0, import_core7.setCellAttr)(ctxRef.current, "align", value);
3630
+ else (0, import_core7.setBlockAttr)(ctxRef.current, "align", value);
3021
3631
  }, []);
3022
3632
  const getAlign = (0, import_react13.useCallback)(() => {
3023
3633
  const sel = selectionRef.current;
@@ -3027,7 +3637,7 @@ function useEditor(opts = {}) {
3027
3637
  return getBlockAttr("align");
3028
3638
  }, [doc, getBlockAttr]);
3029
3639
  const setCellBackground = (0, import_react13.useCallback)((color) => {
3030
- (0, import_core5.setCellAttr)(ctxRef.current, "bgColor", color);
3640
+ (0, import_core7.setCellAttr)(ctxRef.current, "bgColor", color);
3031
3641
  }, []);
3032
3642
  const getCellBackground = (0, import_react13.useCallback)(() => {
3033
3643
  const sel = selectionRef.current;
@@ -3037,7 +3647,7 @@ function useEditor(opts = {}) {
3037
3647
  const setTableBorderPreset = (0, import_react13.useCallback)((preset) => {
3038
3648
  const sel = selectionRef.current;
3039
3649
  if (!doc.isTable(sel.focus.blockIndex)) return;
3040
- (0, import_core5.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
3650
+ (0, import_core7.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderPreset", preset);
3041
3651
  }, [doc]);
3042
3652
  const getTableBorderPreset = (0, import_react13.useCallback)(() => {
3043
3653
  const sel = selectionRef.current;
@@ -3047,7 +3657,7 @@ function useEditor(opts = {}) {
3047
3657
  const setTableBorderColor = (0, import_react13.useCallback)((color) => {
3048
3658
  const sel = selectionRef.current;
3049
3659
  if (!doc.isTable(sel.focus.blockIndex)) return;
3050
- (0, import_core5.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
3660
+ (0, import_core7.setBlockAttrAtIndex)(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
3051
3661
  }, [doc]);
3052
3662
  const getTableBorderColor = (0, import_react13.useCallback)(() => {
3053
3663
  const sel = selectionRef.current;
@@ -3057,7 +3667,7 @@ function useEditor(opts = {}) {
3057
3667
  const isListActive = (0, import_react13.useCallback)(
3058
3668
  (kind) => {
3059
3669
  const sel = selectionRef.current;
3060
- const { start, end } = (0, import_core5.orderedRange)(sel);
3670
+ const { start, end } = (0, import_core7.orderedRange)(sel);
3061
3671
  for (let i = start.blockIndex; i <= end.blockIndex; i++) {
3062
3672
  if (doc.getBlockType(i) !== "listItem") return false;
3063
3673
  if (doc.getBlockAttrs(i).listKind !== kind) return false;
@@ -3067,112 +3677,112 @@ function useEditor(opts = {}) {
3067
3677
  [doc]
3068
3678
  );
3069
3679
  const toggleList = (0, import_react13.useCallback)((kind) => {
3070
- (0, import_core5.toggleList)(ctxRef.current, kind);
3680
+ (0, import_core7.toggleList)(ctxRef.current, kind);
3071
3681
  }, []);
3072
3682
  const indentList = (0, import_react13.useCallback)(() => {
3073
- (0, import_core5.indentList)(ctxRef.current);
3683
+ (0, import_core7.indentList)(ctxRef.current);
3074
3684
  }, []);
3075
3685
  const dedentList = (0, import_react13.useCallback)(() => {
3076
- (0, import_core5.dedentList)(ctxRef.current);
3686
+ (0, import_core7.dedentList)(ctxRef.current);
3077
3687
  }, []);
3078
3688
  const splitListItem = (0, import_react13.useCallback)(() => {
3079
- return (0, import_core5.splitListItem)(ctxRef.current);
3689
+ return (0, import_core7.splitListItem)(ctxRef.current);
3080
3690
  }, []);
3081
3691
  const isInTable = (0, import_react13.useCallback)(() => {
3082
3692
  return selectionRef.current.focus.cellIndex != null;
3083
3693
  }, []);
3084
3694
  const getTableLocation = (0, import_react13.useCallback)(() => {
3085
- return (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3695
+ return (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3086
3696
  }, [doc]);
3087
3697
  const insertTable = (0, import_react13.useCallback)((rows, cols) => {
3088
- (0, import_core5.insertTable)(ctxRef.current, rows, cols);
3698
+ (0, import_core7.insertTable)(ctxRef.current, rows, cols);
3089
3699
  }, []);
3090
3700
  const insertAnswerLines = (0, import_react13.useCallback)((count, spacing) => {
3091
- (0, import_core5.insertAnswerLines)(ctxRef.current, count, spacing);
3701
+ (0, import_core7.insertAnswerLines)(ctxRef.current, count, spacing);
3092
3702
  }, []);
3093
3703
  const deleteTable = (0, import_react13.useCallback)((blockIndex) => {
3094
3704
  const idx = blockIndex ?? selectionRef.current.focus.blockIndex;
3095
- (0, import_core5.deleteTable)(ctxRef.current, idx);
3705
+ (0, import_core7.deleteTable)(ctxRef.current, idx);
3096
3706
  }, []);
3097
3707
  const insertRowAbove = (0, import_react13.useCallback)(() => {
3098
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3708
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3099
3709
  if (!loc) return;
3100
- (0, import_core5.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
3710
+ (0, import_core7.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "before");
3101
3711
  }, [doc]);
3102
3712
  const insertRowBelow = (0, import_react13.useCallback)(() => {
3103
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3713
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3104
3714
  if (!loc) return;
3105
- (0, import_core5.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
3715
+ (0, import_core7.insertTableRow)(ctxRef.current, loc.blockIndex, loc.row, "after");
3106
3716
  }, [doc]);
3107
3717
  const deleteCurrentRow = (0, import_react13.useCallback)(() => {
3108
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3718
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3109
3719
  if (!loc) return;
3110
- (0, import_core5.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
3720
+ (0, import_core7.deleteTableRow)(ctxRef.current, loc.blockIndex, loc.row);
3111
3721
  }, [doc]);
3112
3722
  const insertColumnLeft = (0, import_react13.useCallback)(() => {
3113
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3723
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3114
3724
  if (!loc) return;
3115
- (0, import_core5.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
3725
+ (0, import_core7.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "before");
3116
3726
  }, [doc]);
3117
3727
  const insertColumnRight = (0, import_react13.useCallback)(() => {
3118
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3728
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3119
3729
  if (!loc) return;
3120
- (0, import_core5.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
3730
+ (0, import_core7.insertTableColumn)(ctxRef.current, loc.blockIndex, loc.col, "after");
3121
3731
  }, [doc]);
3122
3732
  const deleteCurrentColumn = (0, import_react13.useCallback)(() => {
3123
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3733
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3124
3734
  if (!loc) return;
3125
- (0, import_core5.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
3735
+ (0, import_core7.deleteTableColumn)(ctxRef.current, loc.blockIndex, loc.col);
3126
3736
  }, [doc]);
3127
3737
  const moveToNextCell = (0, import_react13.useCallback)(() => {
3128
- (0, import_core5.moveToNextCell)(ctxRef.current);
3738
+ (0, import_core7.moveToNextCell)(ctxRef.current);
3129
3739
  }, []);
3130
3740
  const moveToPrevCell = (0, import_react13.useCallback)(() => {
3131
- (0, import_core5.moveToPrevCell)(ctxRef.current);
3741
+ (0, import_core7.moveToPrevCell)(ctxRef.current);
3132
3742
  }, []);
3133
3743
  const mergeRight = (0, import_react13.useCallback)(() => {
3134
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3744
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3135
3745
  if (!loc) return false;
3136
- return (0, import_core5.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3746
+ return (0, import_core7.mergeRight)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3137
3747
  }, [doc]);
3138
3748
  const mergeDown = (0, import_react13.useCallback)(() => {
3139
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3749
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3140
3750
  if (!loc) return false;
3141
- return (0, import_core5.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3751
+ return (0, import_core7.mergeDown)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3142
3752
  }, [doc]);
3143
3753
  const splitCell = (0, import_react13.useCallback)(() => {
3144
- const loc = (0, import_core5.tableLocationOf)(doc, selectionRef.current.focus);
3754
+ const loc = (0, import_core7.tableLocationOf)(doc, selectionRef.current.focus);
3145
3755
  if (!loc) return false;
3146
- return (0, import_core5.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3756
+ return (0, import_core7.splitCell)(ctxRef.current, loc.blockIndex, loc.row, loc.col);
3147
3757
  }, [doc]);
3148
3758
  const setColumnWidth = (0, import_react13.useCallback)(
3149
3759
  (blockIndex, col, widthPx) => {
3150
- (0, import_core5.setColumnWidth)(ctxRef.current, blockIndex, col, widthPx);
3760
+ (0, import_core7.setColumnWidth)(ctxRef.current, blockIndex, col, widthPx);
3151
3761
  },
3152
3762
  []
3153
3763
  );
3154
3764
  const getTableRect = (0, import_react13.useCallback)(
3155
- () => (0, import_core5.tableRectSelection)(doc, selectionRef.current),
3765
+ () => (0, import_core7.tableRectSelection)(doc, selectionRef.current),
3156
3766
  [doc]
3157
3767
  );
3158
3768
  const hasTableRectSelection = (0, import_react13.useCallback)(() => {
3159
- return (0, import_core5.tableRectSelection)(doc, selectionRef.current) !== null;
3769
+ return (0, import_core7.tableRectSelection)(doc, selectionRef.current) !== null;
3160
3770
  }, [doc]);
3161
3771
  const mergeSelection = (0, import_react13.useCallback)(() => {
3162
- return (0, import_core5.mergeSelection)(ctxRef.current);
3772
+ return (0, import_core7.mergeSelection)(ctxRef.current);
3163
3773
  }, []);
3164
3774
  const insertImage = (0, import_react13.useCallback)((embed) => {
3165
- (0, import_core5.insertImage)(ctxRef.current, embed);
3775
+ (0, import_core7.insertImage)(ctxRef.current, embed);
3166
3776
  }, []);
3167
3777
  const setImageAttrs = (0, import_react13.useCallback)(
3168
3778
  (blockIndex, offset, partial, cellIndex, newOffset) => {
3169
- (0, import_core5.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
3779
+ (0, import_core7.setImageAttrs)(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);
3170
3780
  },
3171
3781
  []
3172
3782
  );
3173
3783
  const moveEmbedAnchor = (0, import_react13.useCallback)(
3174
3784
  (from, to, newOffsetX, newOffsetY) => {
3175
- (0, import_core5.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
3785
+ (0, import_core7.moveEmbedAnchor)(ctxRef.current, from, to, newOffsetX, newOffsetY);
3176
3786
  },
3177
3787
  []
3178
3788
  );
@@ -3190,7 +3800,7 @@ function useEditor(opts = {}) {
3190
3800
  }
3191
3801
  const upload = uploadImageRef.current;
3192
3802
  const src = upload ? await upload(file) : dataUrl;
3193
- (0, import_core5.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
3803
+ (0, import_core7.insertImage)(ctxRef.current, { type: "image", src, width: w, height: h });
3194
3804
  }, []);
3195
3805
  const getSelectedEmbed = (0, import_react13.useCallback)(() => {
3196
3806
  const sel = selectionRef.current;
@@ -3209,7 +3819,7 @@ function useEditor(opts = {}) {
3209
3819
  cursor += op.insert.length;
3210
3820
  continue;
3211
3821
  }
3212
- if (cursor === start && (0, import_core5.isImageEmbed)(op.insert)) {
3822
+ if (cursor === start && (0, import_core7.isImageEmbed)(op.insert)) {
3213
3823
  return {
3214
3824
  blockIndex: sel.anchor.blockIndex,
3215
3825
  cellIndex: sel.anchor.cellIndex,
@@ -3404,7 +4014,7 @@ function Editor({
3404
4014
  const sel = readDomSelection(root);
3405
4015
  awareness.setLocalStateField(
3406
4016
  "cursor",
3407
- sel ? (0, import_core6.encodeSelection)(doc, sel) ?? null : null
4017
+ sel ? (0, import_core8.encodeSelection)(doc, sel) ?? null : null
3408
4018
  );
3409
4019
  };
3410
4020
  const onSelChange = () => {
@@ -3705,14 +4315,14 @@ function Editor({
3705
4315
  const data = e.data ?? "";
3706
4316
  if (data.length > 0) {
3707
4317
  e.preventDefault();
3708
- (0, import_core6.insertText)(ctx, data, ed.consumePendingMarks());
4318
+ (0, import_core8.insertText)(ctx, data, ed.consumePendingMarks());
3709
4319
  }
3710
4320
  return;
3711
4321
  }
3712
4322
  case "insertLineBreak": {
3713
4323
  e.preventDefault();
3714
4324
  if (ed.getBlockType() === "listItem") {
3715
- (0, import_core6.insertText)(ctx, "\n", ed.consumePendingMarks());
4325
+ (0, import_core8.insertText)(ctx, "\n", ed.consumePendingMarks());
3716
4326
  return;
3717
4327
  }
3718
4328
  const selEmbed = ed.getSelectedEmbed();
@@ -3732,7 +4342,7 @@ function Editor({
3732
4342
  });
3733
4343
  }
3734
4344
  if (ed.splitListItem()) return;
3735
- (0, import_core6.insertParagraph)(ctx);
4345
+ (0, import_core8.insertParagraph)(ctx);
3736
4346
  return;
3737
4347
  }
3738
4348
  case "insertParagraph": {
@@ -3754,14 +4364,14 @@ function Editor({
3754
4364
  });
3755
4365
  }
3756
4366
  if (ed.splitListItem()) return;
3757
- (0, import_core6.insertParagraph)(ctx);
4367
+ (0, import_core8.insertParagraph)(ctx);
3758
4368
  return;
3759
4369
  }
3760
4370
  case "insertReplacementText": {
3761
4371
  const text = e.data ?? e.dataTransfer?.getData("text/plain") ?? "";
3762
4372
  if (text.length > 0) {
3763
4373
  e.preventDefault();
3764
- (0, import_core6.insertText)(ctx, text, ed.consumePendingMarks());
4374
+ (0, import_core8.insertText)(ctx, text, ed.consumePendingMarks());
3765
4375
  }
3766
4376
  return;
3767
4377
  }
@@ -3774,7 +4384,7 @@ function Editor({
3774
4384
  case "deleteSoftLineBackward":
3775
4385
  case "deleteHardLineBackward": {
3776
4386
  e.preventDefault();
3777
- (0, import_core6.deleteBackward)(ctx);
4387
+ (0, import_core8.deleteBackward)(ctx);
3778
4388
  return;
3779
4389
  }
3780
4390
  case "deleteContentForward":
@@ -3782,7 +4392,7 @@ function Editor({
3782
4392
  case "deleteSoftLineForward":
3783
4393
  case "deleteHardLineForward": {
3784
4394
  e.preventDefault();
3785
- (0, import_core6.deleteForward)(ctx);
4395
+ (0, import_core8.deleteForward)(ctx);
3786
4396
  return;
3787
4397
  }
3788
4398
  case "historyUndo": {
@@ -3809,10 +4419,10 @@ function Editor({
3809
4419
  if (!root) return;
3810
4420
  const writeSlice = (e) => {
3811
4421
  const ctx = ctxRef.current;
3812
- const slice = (0, import_core6.serializeSelection)(ctx.doc, ctx.getSelection());
4422
+ const slice = (0, import_core8.serializeSelection)(ctx.doc, ctx.getSelection());
3813
4423
  if (!slice || !e.clipboardData) return false;
3814
- e.clipboardData.setData(import_core6.SOFER_MIME, JSON.stringify(slice));
3815
- e.clipboardData.setData("text/plain", (0, import_core6.sliceToText)(slice));
4424
+ e.clipboardData.setData(import_core8.SOFER_MIME, JSON.stringify(slice));
4425
+ e.clipboardData.setData("text/plain", (0, import_core8.sliceToText)(slice));
3816
4426
  return true;
3817
4427
  };
3818
4428
  const onCopy = (e) => {
@@ -3820,40 +4430,34 @@ function Editor({
3820
4430
  };
3821
4431
  const onCut = (e) => {
3822
4432
  e.preventDefault();
3823
- if (writeSlice(e)) (0, import_core6.deleteSelection)(ctxRef.current);
4433
+ if (writeSlice(e)) (0, import_core8.deleteSelection)(ctxRef.current);
3824
4434
  };
3825
4435
  const onPaste = (e) => {
3826
4436
  const ctx = ctxRef.current;
3827
4437
  const cd = e.clipboardData;
3828
4438
  if (!cd) return;
3829
- const raw = cd.getData(import_core6.SOFER_MIME);
3830
- if (raw) {
3831
- try {
3832
- const slice = JSON.parse(raw);
3833
- if (slice && Array.isArray(slice.blocks)) {
3834
- e.preventDefault();
3835
- (0, import_core6.insertSlice)(ctx, slice);
3836
- return;
3837
- }
3838
- } catch {
4439
+ const plan = planPaste(cd);
4440
+ if (plan.kind === "none") return;
4441
+ e.preventDefault();
4442
+ switch (plan.kind) {
4443
+ case "sofer":
4444
+ case "html":
4445
+ (0, import_core8.insertSlice)(ctx, plan.slice);
4446
+ return;
4447
+ case "images":
4448
+ void (async () => {
4449
+ for (const f of plan.files) await editorRef.current.insertImageFromFile(f);
4450
+ })();
4451
+ return;
4452
+ case "text": {
4453
+ const lines = plan.text.split(/\r\n|\r|\n/);
4454
+ lines.forEach((line, i) => {
4455
+ if (i > 0) (0, import_core8.insertParagraph)(ctx);
4456
+ if (line.length > 0) (0, import_core8.insertText)(ctx, line);
4457
+ });
4458
+ return;
3839
4459
  }
3840
4460
  }
3841
- const images = Array.from(cd.files ?? []).filter((f) => f.type.startsWith("image/"));
3842
- if (images.length > 0) {
3843
- e.preventDefault();
3844
- void (async () => {
3845
- for (const f of images) await editorRef.current.insertImageFromFile(f);
3846
- })();
3847
- return;
3848
- }
3849
- const text = cd.getData("text/plain");
3850
- if (text.length === 0) return;
3851
- e.preventDefault();
3852
- const lines = text.split(/\r\n|\r|\n/);
3853
- lines.forEach((line, i) => {
3854
- if (i > 0) (0, import_core6.insertParagraph)(ctx);
3855
- if (line.length > 0) (0, import_core6.insertText)(ctx, line);
3856
- });
3857
4461
  };
3858
4462
  root.addEventListener("copy", onCopy);
3859
4463
  root.addEventListener("cut", onCut);
@@ -3944,7 +4548,7 @@ function Editor({
3944
4548
  const onCompositionEnd = (0, import_react14.useCallback)((e) => {
3945
4549
  isComposingRef.current = false;
3946
4550
  if (e.data && e.data.length > 0) {
3947
- (0, import_core6.insertText)(ctxRef.current, e.data);
4551
+ (0, import_core8.insertText)(ctxRef.current, e.data);
3948
4552
  }
3949
4553
  }, []);
3950
4554
  const topLevels = (0, import_react14.useMemo)(() => groupTopLevels(snapshot.blocks), [snapshot]);
@@ -4108,11 +4712,15 @@ function groupTopLevels(snapshot) {
4108
4712
  const groupStart = i;
4109
4713
  const items = [];
4110
4714
  const kind = block.attrs.listKind === "ordered" ? "ordered" : "bullet";
4715
+ const leaderLevel = clampListLevel2(block.attrs.listLevel);
4111
4716
  const groupStyle = block.attrs.listStyle;
4112
4717
  while (i < snapshot.length) {
4113
4718
  const b = snapshot[i];
4114
4719
  if (b.type !== "listItem") break;
4115
- if ((b.attrs.listKind ?? "bullet") !== kind) break;
4720
+ const bLevel = clampListLevel2(b.attrs.listLevel);
4721
+ if (bLevel <= leaderLevel && (b.attrs.listKind ?? "bullet") !== kind) {
4722
+ break;
4723
+ }
4116
4724
  if (i > groupStart) {
4117
4725
  if (typeof b.attrs.listStart === "number") break;
4118
4726
  const itemStyle = b.attrs.listStyle;
@@ -4220,7 +4828,7 @@ function buildListTree(items) {
4220
4828
  function renderListTree(tree, top, start, key) {
4221
4829
  const className = `ed-list ed-list-${top.listKind}`;
4222
4830
  const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
4223
- 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));
4831
+ 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, `nested-${node.entry.index}`) : null }, node.entry.index));
4224
4832
  if (top.listKind === "ordered") {
4225
4833
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4226
4834
  "ol",
@@ -4236,9 +4844,10 @@ function renderListTree(tree, top, start, key) {
4236
4844
  }
4237
4845
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
4238
4846
  }
4239
- function renderNestedListTree(tree, kind, key) {
4847
+ function renderNestedListTree(tree, key) {
4848
+ const kind = tree[0]?.entry.block.attrs.listKind === "ordered" ? "ordered" : "bullet";
4240
4849
  const Tag = kind === "ordered" ? "ol" : "ul";
4241
- 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);
4850
+ 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, `nested-${node.entry.index}`) : null }, node.entry.index)) }, key);
4242
4851
  }
4243
4852
  function clampListLevel2(l) {
4244
4853
  if (typeof l !== "number" || !Number.isFinite(l)) return 0;
@@ -4267,7 +4876,7 @@ function caretRangeFromPoint(x, y) {
4267
4876
 
4268
4877
  // src/Toolbar.tsx
4269
4878
  var import_react15 = require("react");
4270
- var import_core7 = require("@sofereditor/core");
4879
+ var import_core9 = require("@sofereditor/core");
4271
4880
  var import_jsx_runtime13 = require("react/jsx-runtime");
4272
4881
  var FONT_FAMILIES = ["Arial"];
4273
4882
  var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
@@ -4739,7 +5348,7 @@ function AnswerLinesMenu() {
4739
5348
  document.addEventListener("mousedown", onDown);
4740
5349
  return () => document.removeEventListener("mousedown", onDown);
4741
5350
  }, [open]);
4742
- const clamped = Math.max(1, Math.min(import_core7.ANSWER_LINE_MAX, Math.trunc(count) || 1));
5351
+ const clamped = Math.max(1, Math.min(import_core9.ANSWER_LINE_MAX, Math.trunc(count) || 1));
4743
5352
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { ref: rootRef, className: "ed-toolbar-tablemenu", children: [
4744
5353
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4745
5354
  "button",
@@ -4772,7 +5381,7 @@ function AnswerLinesMenu() {
4772
5381
  {
4773
5382
  type: "number",
4774
5383
  min: 1,
4775
- max: import_core7.ANSWER_LINE_MAX,
5384
+ max: import_core9.ANSWER_LINE_MAX,
4776
5385
  value: count,
4777
5386
  onChange: (e) => setCount(Number(e.target.value)),
4778
5387
  "aria-label": "Quantidade de linhas"
@@ -4965,7 +5574,7 @@ function TableMenu() {
4965
5574
  {
4966
5575
  className: "ed-toolbar-swatch",
4967
5576
  "aria-hidden": true,
4968
- style: { background: editor.getTableBorderColor() ?? import_core7.TABLE_BORDER_COLOR }
5577
+ style: { background: editor.getTableBorderColor() ?? import_core9.TABLE_BORDER_COLOR }
4969
5578
  }
4970
5579
  ),
4971
5580
  "Cor da borda",
@@ -4973,7 +5582,7 @@ function TableMenu() {
4973
5582
  "input",
4974
5583
  {
4975
5584
  type: "color",
4976
- value: editor.getTableBorderColor() ?? import_core7.TABLE_BORDER_COLOR,
5585
+ value: editor.getTableBorderColor() ?? import_core9.TABLE_BORDER_COLOR,
4977
5586
  onChange: (e) => editor.setTableBorderColor(e.target.value),
4978
5587
  "aria-label": "Cor da borda"
4979
5588
  }
@@ -5095,6 +5704,7 @@ function MarkButton({ title, pressed, onClick, children }) {
5095
5704
  getBlockElement,
5096
5705
  getCellElement,
5097
5706
  getFragmentForOffset,
5707
+ htmlToSlice,
5098
5708
  isTableRectSelection,
5099
5709
  locatePoint,
5100
5710
  readDomSelection,