@sofereditor/react 0.4.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 +811 -157
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +701 -48
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
insertText,
|
|
18
18
|
serializeSelection,
|
|
19
19
|
sliceToText,
|
|
20
|
-
SOFER_MIME
|
|
20
|
+
SOFER_MIME as SOFER_MIME2
|
|
21
21
|
} from "@sofereditor/core";
|
|
22
22
|
|
|
23
23
|
// src/dom-bridge.ts
|
|
@@ -293,6 +293,615 @@ function applyDomSelection(root, modelSel) {
|
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
+
// src/pastePlan.ts
|
|
297
|
+
import { SOFER_MIME } from "@sofereditor/core";
|
|
298
|
+
|
|
299
|
+
// src/htmlToSlice.ts
|
|
300
|
+
import { MAX_LIST_LEVEL } from "@sofereditor/core";
|
|
301
|
+
function htmlToSlice(html) {
|
|
302
|
+
if (!html || html.trim().length === 0) return null;
|
|
303
|
+
let doc;
|
|
304
|
+
try {
|
|
305
|
+
doc = new DOMParser().parseFromString(html, "text/html");
|
|
306
|
+
} catch {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const body = doc.body;
|
|
310
|
+
if (!body) return null;
|
|
311
|
+
const blocks = [];
|
|
312
|
+
try {
|
|
313
|
+
walkBlockLevel(body, {}, blocks);
|
|
314
|
+
} catch {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
if (blocks.length === 0) return null;
|
|
318
|
+
normalizeListLevels(blocks);
|
|
319
|
+
const temTexto = blocks.some((b) => b.text.trim().length > 0);
|
|
320
|
+
if (!temTexto) return null;
|
|
321
|
+
const blockLevel = blocks.length > 1 || blocks[0].type !== "paragraph";
|
|
322
|
+
return { blocks, openStart: false, openEnd: false, ...blockLevel ? { blockLevel: true } : {} };
|
|
323
|
+
}
|
|
324
|
+
var IGNORED_TAGS = /* @__PURE__ */ new Set(["script", "style", "meta", "link", "head", "title", "xml"]);
|
|
325
|
+
var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
326
|
+
"p",
|
|
327
|
+
"div",
|
|
328
|
+
"section",
|
|
329
|
+
"article",
|
|
330
|
+
"header",
|
|
331
|
+
"footer",
|
|
332
|
+
"main",
|
|
333
|
+
"figure",
|
|
334
|
+
"figcaption",
|
|
335
|
+
"pre",
|
|
336
|
+
"address"
|
|
337
|
+
]);
|
|
338
|
+
var BLOCK_TRIGGER_TAGS = /* @__PURE__ */ new Set([
|
|
339
|
+
"p",
|
|
340
|
+
"div",
|
|
341
|
+
"ul",
|
|
342
|
+
"ol",
|
|
343
|
+
"li",
|
|
344
|
+
"h1",
|
|
345
|
+
"h2",
|
|
346
|
+
"h3",
|
|
347
|
+
"h4",
|
|
348
|
+
"h5",
|
|
349
|
+
"h6",
|
|
350
|
+
"blockquote",
|
|
351
|
+
"table",
|
|
352
|
+
"tr",
|
|
353
|
+
"td",
|
|
354
|
+
"th"
|
|
355
|
+
]);
|
|
356
|
+
function isNamespacedTag(tag) {
|
|
357
|
+
return tag.includes(":");
|
|
358
|
+
}
|
|
359
|
+
function hasBlockDescendant(el) {
|
|
360
|
+
const all = el.querySelectorAll("*");
|
|
361
|
+
for (const e of Array.from(all)) {
|
|
362
|
+
if (BLOCK_TRIGGER_TAGS.has(e.tagName.toLowerCase())) return true;
|
|
363
|
+
}
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
function walkBlockLevel(container, marks, blocks) {
|
|
367
|
+
let loose = [];
|
|
368
|
+
const flushLoose = () => {
|
|
369
|
+
if (loose.length === 0) return;
|
|
370
|
+
const nodes = loose;
|
|
371
|
+
loose = [];
|
|
372
|
+
const delta = inlineDeltaFromNodes(nodes, marks);
|
|
373
|
+
if (delta.length > 0) blocks.push(makeBlock("paragraph", delta, {}));
|
|
374
|
+
};
|
|
375
|
+
for (const node of Array.from(container.childNodes)) {
|
|
376
|
+
if (node.nodeType === Node.COMMENT_NODE) continue;
|
|
377
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
378
|
+
loose.push(node);
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
382
|
+
const el = node;
|
|
383
|
+
const tag = el.tagName.toLowerCase();
|
|
384
|
+
if (IGNORED_TAGS.has(tag) || isNamespacedTag(tag)) continue;
|
|
385
|
+
switch (tag) {
|
|
386
|
+
case "ul":
|
|
387
|
+
case "ol": {
|
|
388
|
+
flushLoose();
|
|
389
|
+
handleList(el, tag === "ol" ? "ordered" : "bullet", 0, marks, blocks);
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
case "h1":
|
|
393
|
+
case "h2":
|
|
394
|
+
case "h3":
|
|
395
|
+
case "h4":
|
|
396
|
+
case "h5":
|
|
397
|
+
case "h6": {
|
|
398
|
+
flushLoose();
|
|
399
|
+
const level = Number(tag[1]);
|
|
400
|
+
const attrs = { level };
|
|
401
|
+
const align = readAlign(el);
|
|
402
|
+
if (align) attrs.align = align;
|
|
403
|
+
const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
|
|
404
|
+
blocks.push(makeBlock("heading", delta, attrs));
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
case "blockquote": {
|
|
408
|
+
flushLoose();
|
|
409
|
+
handleBlockquote(el, marks, blocks);
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case "table": {
|
|
413
|
+
flushLoose();
|
|
414
|
+
handleTable(el, marks, blocks);
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
case "li": {
|
|
418
|
+
flushLoose();
|
|
419
|
+
const nestedLists = topLevelListDescendants(el);
|
|
420
|
+
const clone = el.cloneNode(true);
|
|
421
|
+
for (const l of topLevelListDescendants(clone)) l.remove();
|
|
422
|
+
const delta = inlineDeltaFromNodes(Array.from(clone.childNodes), marks);
|
|
423
|
+
blocks.push(makeBlock("listItem", delta, { listKind: "bullet", listLevel: 0 }));
|
|
424
|
+
for (const nested of nestedLists) {
|
|
425
|
+
const nestedKind = nested.tagName.toLowerCase() === "ol" ? "ordered" : "bullet";
|
|
426
|
+
handleList(nested, nestedKind, 1, marks, blocks);
|
|
427
|
+
}
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
case "img":
|
|
431
|
+
break;
|
|
432
|
+
case "br":
|
|
433
|
+
loose.push(node);
|
|
434
|
+
break;
|
|
435
|
+
default: {
|
|
436
|
+
const styleAttr = el.getAttribute("style") ?? "";
|
|
437
|
+
const wordListLevel = parseWordListLevel(styleAttr);
|
|
438
|
+
if (wordListLevel != null && !hasBlockDescendant(el)) {
|
|
439
|
+
flushLoose();
|
|
440
|
+
const marker = findWordListMarker(el);
|
|
441
|
+
const listKind = marker ? detectWordListKind(marker) : "bullet";
|
|
442
|
+
const attrs = { listKind, listLevel: wordListLevel };
|
|
443
|
+
const align = readAlign(el);
|
|
444
|
+
if (align) attrs.align = align;
|
|
445
|
+
const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
|
|
446
|
+
blocks.push(makeBlock("listItem", delta, attrs));
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
if (hasBlockDescendant(el)) {
|
|
450
|
+
flushLoose();
|
|
451
|
+
let nextMarks = applyTagMarks(tag, marks);
|
|
452
|
+
nextMarks = applyStyleMarks(el.getAttribute("style"), nextMarks);
|
|
453
|
+
walkBlockLevel(el, nextMarks, blocks);
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
if (BLOCK_LEVEL_TAGS.has(tag)) {
|
|
457
|
+
flushLoose();
|
|
458
|
+
const attrs = {};
|
|
459
|
+
const align = readAlign(el);
|
|
460
|
+
if (align) attrs.align = align;
|
|
461
|
+
const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
|
|
462
|
+
blocks.push(makeBlock("paragraph", delta, attrs));
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
loose.push(node);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
flushLoose();
|
|
470
|
+
}
|
|
471
|
+
function handleList(listEl, kind, level, marks, blocks) {
|
|
472
|
+
for (const child of Array.from(listEl.children)) {
|
|
473
|
+
const tag = child.tagName.toLowerCase();
|
|
474
|
+
if (tag === "ul" || tag === "ol") {
|
|
475
|
+
const siblingKind = tag === "ol" ? "ordered" : "bullet";
|
|
476
|
+
handleList(child, siblingKind, level + 1, marks, blocks);
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
if (tag !== "li") continue;
|
|
480
|
+
const nestedLists = topLevelListDescendants(child);
|
|
481
|
+
const clone = child.cloneNode(true);
|
|
482
|
+
for (const l of topLevelListDescendants(clone)) l.remove();
|
|
483
|
+
const delta = inlineDeltaFromNodes(Array.from(clone.childNodes), marks);
|
|
484
|
+
const attrs = { listKind: kind, listLevel: clampLevel(level) };
|
|
485
|
+
const align = readAlign(child);
|
|
486
|
+
if (align) attrs.align = align;
|
|
487
|
+
blocks.push(makeBlock("listItem", delta, attrs));
|
|
488
|
+
for (const nested of nestedLists) {
|
|
489
|
+
const nestedKind = nested.tagName.toLowerCase() === "ol" ? "ordered" : "bullet";
|
|
490
|
+
handleList(nested, nestedKind, level + 1, marks, blocks);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function topLevelListDescendants(root) {
|
|
495
|
+
const all = Array.from(root.querySelectorAll("ul, ol"));
|
|
496
|
+
return all.filter((el) => {
|
|
497
|
+
let p = el.parentElement;
|
|
498
|
+
while (p && p !== root) {
|
|
499
|
+
const t = p.tagName.toLowerCase();
|
|
500
|
+
if (t === "ul" || t === "ol" || t === "table" || t === "td" || t === "th") return false;
|
|
501
|
+
p = p.parentElement;
|
|
502
|
+
}
|
|
503
|
+
return true;
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
function handleBlockquote(el, marks, blocks) {
|
|
507
|
+
if (!hasBlockDescendant(el)) {
|
|
508
|
+
const attrs = {};
|
|
509
|
+
const align = readAlign(el);
|
|
510
|
+
if (align) attrs.align = align;
|
|
511
|
+
const delta = inlineDeltaFromNodes(Array.from(el.childNodes), marks);
|
|
512
|
+
blocks.push(makeBlock("blockquote", delta, attrs));
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const nested = [];
|
|
516
|
+
walkBlockLevel(el, marks, nested);
|
|
517
|
+
for (const b of nested) {
|
|
518
|
+
blocks.push(b.type === "paragraph" ? { ...b, type: "blockquote" } : b);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function handleTable(table, marks, blocks) {
|
|
522
|
+
for (const row of directRows(table)) {
|
|
523
|
+
const cells = Array.from(row.children).filter(
|
|
524
|
+
(c) => ["td", "th"].includes(c.tagName.toLowerCase())
|
|
525
|
+
);
|
|
526
|
+
for (const cell of cells) {
|
|
527
|
+
const cellBlocks = [];
|
|
528
|
+
walkBlockLevel(cell, marks, cellBlocks);
|
|
529
|
+
for (const b of cellBlocks) {
|
|
530
|
+
const attrs = {};
|
|
531
|
+
if (b.attrs.align) attrs.align = b.attrs.align;
|
|
532
|
+
blocks.push(makeBlock("paragraph", b.delta, attrs));
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function directRows(table) {
|
|
538
|
+
const rows = [];
|
|
539
|
+
for (const child of Array.from(table.children)) {
|
|
540
|
+
const tag = child.tagName.toLowerCase();
|
|
541
|
+
if (tag === "tr") {
|
|
542
|
+
rows.push(child);
|
|
543
|
+
} else if (tag === "tbody" || tag === "thead" || tag === "tfoot") {
|
|
544
|
+
for (const r of Array.from(child.children)) {
|
|
545
|
+
if (r.tagName.toLowerCase() === "tr") rows.push(r);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return rows;
|
|
550
|
+
}
|
|
551
|
+
function parseWordListLevel(styleAttr) {
|
|
552
|
+
const m = /mso-list\s*:\s*l\d+\s+level(\d+)/i.exec(styleAttr);
|
|
553
|
+
if (!m) return null;
|
|
554
|
+
const n = Number.parseInt(m[1], 10);
|
|
555
|
+
const fromLevelN = Number.isFinite(n) ? Math.max(0, n - 1) : 0;
|
|
556
|
+
const fromMargin = wordListLevelFromMarginLeft(marginLeftPt(styleAttr));
|
|
557
|
+
return clampLevel(Math.max(fromLevelN, fromMargin));
|
|
558
|
+
}
|
|
559
|
+
function marginLeftPt(styleAttr) {
|
|
560
|
+
const raw = parseStyle(styleAttr)["margin-left"];
|
|
561
|
+
if (!raw) return 0;
|
|
562
|
+
const m = /^(-?[\d.]+)\s*(pt|cm|in|px)$/i.exec(raw.trim());
|
|
563
|
+
if (!m) return 0;
|
|
564
|
+
const val = Number.parseFloat(m[1]);
|
|
565
|
+
if (!Number.isFinite(val) || val < 0) return 0;
|
|
566
|
+
switch (m[2].toLowerCase()) {
|
|
567
|
+
case "pt":
|
|
568
|
+
return val;
|
|
569
|
+
case "cm":
|
|
570
|
+
return val * 28.3465;
|
|
571
|
+
case "in":
|
|
572
|
+
return val * 72;
|
|
573
|
+
case "px":
|
|
574
|
+
return val * 0.75;
|
|
575
|
+
default:
|
|
576
|
+
return 0;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function wordListLevelFromMarginLeft(pt) {
|
|
580
|
+
if (pt <= 0) return 0;
|
|
581
|
+
return Math.max(0, Math.round(pt / 36) - 1);
|
|
582
|
+
}
|
|
583
|
+
function findWordListMarker(el) {
|
|
584
|
+
const all = el.querySelectorAll("*");
|
|
585
|
+
for (const e of Array.from(all)) {
|
|
586
|
+
const style = (e.getAttribute("style") ?? "").toLowerCase().replace(/\s+/g, "");
|
|
587
|
+
if (style.includes("mso-list:ignore")) return e;
|
|
588
|
+
}
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
function detectWordListKind(markerEl) {
|
|
592
|
+
const all = [markerEl, ...Array.from(markerEl.querySelectorAll("*"))];
|
|
593
|
+
for (const e of all) {
|
|
594
|
+
const style = (e.getAttribute("style") ?? "").toLowerCase();
|
|
595
|
+
if (style.includes("symbol") || style.includes("wingdings")) return "bullet";
|
|
596
|
+
}
|
|
597
|
+
const text = (markerEl.textContent ?? "").replace(/ /g, " ").trim();
|
|
598
|
+
if (/^[0-9]+[.)]/.test(text)) return "ordered";
|
|
599
|
+
if (/^[a-zA-Z][.)]/.test(text)) return "ordered";
|
|
600
|
+
return "bullet";
|
|
601
|
+
}
|
|
602
|
+
function inlineDeltaFromNodes(nodes, marks) {
|
|
603
|
+
const ops = [];
|
|
604
|
+
for (const n of nodes) walkInlineNode(n, marks, ops);
|
|
605
|
+
return trimEdgeWhitespace(collapseRepeatedSpaces(mergeAdjacentOps(ops)));
|
|
606
|
+
}
|
|
607
|
+
function collapseRepeatedSpaces(ops) {
|
|
608
|
+
return ops.map(
|
|
609
|
+
(op) => typeof op.insert === "string" ? { ...op, insert: op.insert.replace(/ {2,}/g, " ") } : op
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
function walkInlineNode(node, marks, ops) {
|
|
613
|
+
if (node.nodeType === Node.COMMENT_NODE) return;
|
|
614
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
615
|
+
const text = normalizeWhitespace(node.textContent ?? "");
|
|
616
|
+
if (text.length > 0) pushOp(ops, text, marks);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
620
|
+
const el = node;
|
|
621
|
+
const tag = el.tagName.toLowerCase();
|
|
622
|
+
if (IGNORED_TAGS.has(tag) || isNamespacedTag(tag)) return;
|
|
623
|
+
if (tag === "img") return;
|
|
624
|
+
if (tag === "br") {
|
|
625
|
+
ops.push({ insert: " " });
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
const styleAttr = (el.getAttribute("style") ?? "").toLowerCase().replace(/\s+/g, "");
|
|
629
|
+
if (styleAttr.includes("mso-list:ignore")) return;
|
|
630
|
+
let nextMarks = applyTagMarks(tag, marks);
|
|
631
|
+
nextMarks = applyStyleMarks(el.getAttribute("style"), nextMarks);
|
|
632
|
+
if (tag === "a") {
|
|
633
|
+
const href = el.getAttribute("href");
|
|
634
|
+
if (href) nextMarks = { ...nextMarks, link: { href } };
|
|
635
|
+
}
|
|
636
|
+
for (const child of Array.from(el.childNodes)) walkInlineNode(child, nextMarks, ops);
|
|
637
|
+
}
|
|
638
|
+
function applyTagMarks(tag, marks) {
|
|
639
|
+
switch (tag) {
|
|
640
|
+
case "b":
|
|
641
|
+
case "strong":
|
|
642
|
+
return { ...marks, bold: true };
|
|
643
|
+
case "i":
|
|
644
|
+
case "em":
|
|
645
|
+
return { ...marks, italic: true };
|
|
646
|
+
case "u":
|
|
647
|
+
return { ...marks, underline: true };
|
|
648
|
+
case "s":
|
|
649
|
+
case "strike":
|
|
650
|
+
case "del":
|
|
651
|
+
return { ...marks, strike: true };
|
|
652
|
+
default:
|
|
653
|
+
return marks;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
function parseStyle(styleAttr) {
|
|
657
|
+
const out = {};
|
|
658
|
+
if (!styleAttr) return out;
|
|
659
|
+
for (const decl of styleAttr.split(";")) {
|
|
660
|
+
const idx = decl.indexOf(":");
|
|
661
|
+
if (idx === -1) continue;
|
|
662
|
+
const prop = decl.slice(0, idx).trim().toLowerCase();
|
|
663
|
+
const val = decl.slice(idx + 1).trim();
|
|
664
|
+
if (prop) out[prop] = val;
|
|
665
|
+
}
|
|
666
|
+
return out;
|
|
667
|
+
}
|
|
668
|
+
function applyStyleMarks(styleAttr, marks) {
|
|
669
|
+
const decls = parseStyle(styleAttr);
|
|
670
|
+
if (Object.keys(decls).length === 0) return marks;
|
|
671
|
+
const next = { ...marks };
|
|
672
|
+
if ("font-weight" in decls) {
|
|
673
|
+
const v = decls["font-weight"].toLowerCase();
|
|
674
|
+
if (v === "bold" || /^[5-9]00$/.test(v)) next.bold = true;
|
|
675
|
+
else if (v === "normal" || /^[1-4]00$/.test(v)) delete next.bold;
|
|
676
|
+
}
|
|
677
|
+
if ("font-style" in decls) {
|
|
678
|
+
const v = decls["font-style"].toLowerCase();
|
|
679
|
+
if (v === "italic" || v === "oblique") next.italic = true;
|
|
680
|
+
else if (v === "normal") delete next.italic;
|
|
681
|
+
}
|
|
682
|
+
const deco = decls["text-decoration-line"] ?? decls["text-decoration"];
|
|
683
|
+
if (deco !== void 0) {
|
|
684
|
+
const v = deco.toLowerCase();
|
|
685
|
+
delete next.underline;
|
|
686
|
+
delete next.strike;
|
|
687
|
+
if (v.includes("underline")) next.underline = true;
|
|
688
|
+
if (v.includes("line-through")) next.strike = true;
|
|
689
|
+
}
|
|
690
|
+
if ("color" in decls) {
|
|
691
|
+
const css = normalizeCssColor(decls.color);
|
|
692
|
+
if (css && !isBlack(css)) next.color = css;
|
|
693
|
+
else delete next.color;
|
|
694
|
+
}
|
|
695
|
+
const bg = decls["background-color"] ?? decls.background;
|
|
696
|
+
if (bg !== void 0) {
|
|
697
|
+
const css = normalizeCssColor(bg);
|
|
698
|
+
if (css && css !== "#ffffff") next.highlight = css;
|
|
699
|
+
else delete next.highlight;
|
|
700
|
+
}
|
|
701
|
+
if ("font-size" in decls) {
|
|
702
|
+
const pt = parseFontSizePt(decls["font-size"]);
|
|
703
|
+
if (pt != null) next.fontSize = formatFontSizePt(pt);
|
|
704
|
+
}
|
|
705
|
+
return next;
|
|
706
|
+
}
|
|
707
|
+
function parseFontSizePt(raw) {
|
|
708
|
+
const v = raw.trim().toLowerCase();
|
|
709
|
+
const m = /^(-?[\d.]+)\s*(pt|px|in)$/.exec(v);
|
|
710
|
+
if (!m) return void 0;
|
|
711
|
+
const num = Number.parseFloat(m[1]);
|
|
712
|
+
if (!Number.isFinite(num)) return void 0;
|
|
713
|
+
let pt;
|
|
714
|
+
switch (m[2]) {
|
|
715
|
+
case "pt":
|
|
716
|
+
pt = num;
|
|
717
|
+
break;
|
|
718
|
+
case "px":
|
|
719
|
+
pt = num * 0.75;
|
|
720
|
+
break;
|
|
721
|
+
case "in":
|
|
722
|
+
pt = num * 72;
|
|
723
|
+
break;
|
|
724
|
+
default:
|
|
725
|
+
return void 0;
|
|
726
|
+
}
|
|
727
|
+
const rounded = Math.round(pt * 10) / 10;
|
|
728
|
+
if (rounded <= 0 || rounded > 200) return void 0;
|
|
729
|
+
return rounded;
|
|
730
|
+
}
|
|
731
|
+
function formatFontSizePt(pt) {
|
|
732
|
+
const rounded = Math.round(pt * 10) / 10;
|
|
733
|
+
const str = Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
|
|
734
|
+
return `${str}pt`;
|
|
735
|
+
}
|
|
736
|
+
var NAMED_COLORS = {
|
|
737
|
+
black: "#000000",
|
|
738
|
+
white: "#ffffff",
|
|
739
|
+
red: "#ff0000",
|
|
740
|
+
green: "#008000",
|
|
741
|
+
blue: "#0000ff",
|
|
742
|
+
yellow: "#ffff00",
|
|
743
|
+
cyan: "#00ffff",
|
|
744
|
+
magenta: "#ff00ff",
|
|
745
|
+
gray: "#808080",
|
|
746
|
+
grey: "#808080",
|
|
747
|
+
orange: "#ffa500",
|
|
748
|
+
purple: "#800080"
|
|
749
|
+
};
|
|
750
|
+
function normalizeCssColor(raw) {
|
|
751
|
+
if (!raw) return void 0;
|
|
752
|
+
const v = raw.trim().toLowerCase();
|
|
753
|
+
if (!v || v === "transparent" || v === "none" || v === "inherit" || v === "initial") return void 0;
|
|
754
|
+
if (v.startsWith("#")) {
|
|
755
|
+
let hex = v.slice(1);
|
|
756
|
+
if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
|
|
757
|
+
return /^[0-9a-f]{6}$/.test(hex) ? `#${hex}` : void 0;
|
|
758
|
+
}
|
|
759
|
+
const rgbMatch = /^rgba?\(([^)]+)\)$/.exec(v);
|
|
760
|
+
if (rgbMatch) {
|
|
761
|
+
const parts = rgbMatch[1].split(",").map((s) => s.trim());
|
|
762
|
+
if (parts.length < 3) return void 0;
|
|
763
|
+
const alpha = parts[3] !== void 0 ? Number.parseFloat(parts[3]) : 1;
|
|
764
|
+
if (alpha === 0) return void 0;
|
|
765
|
+
const toHex = (n) => {
|
|
766
|
+
const num = Math.max(0, Math.min(255, Number.parseInt(n, 10) || 0));
|
|
767
|
+
return num.toString(16).padStart(2, "0");
|
|
768
|
+
};
|
|
769
|
+
return `#${toHex(parts[0])}${toHex(parts[1])}${toHex(parts[2])}`;
|
|
770
|
+
}
|
|
771
|
+
return NAMED_COLORS[v];
|
|
772
|
+
}
|
|
773
|
+
function isBlack(hex) {
|
|
774
|
+
return hex.toLowerCase() === "#000000";
|
|
775
|
+
}
|
|
776
|
+
function readAlign(el) {
|
|
777
|
+
const style = parseStyle(el.getAttribute("style"));
|
|
778
|
+
const v = style["text-align"];
|
|
779
|
+
if (!v) return void 0;
|
|
780
|
+
switch (v.toLowerCase()) {
|
|
781
|
+
case "left":
|
|
782
|
+
case "start":
|
|
783
|
+
return "left";
|
|
784
|
+
case "center":
|
|
785
|
+
return "center";
|
|
786
|
+
case "right":
|
|
787
|
+
case "end":
|
|
788
|
+
return "right";
|
|
789
|
+
case "justify":
|
|
790
|
+
return "justify";
|
|
791
|
+
default:
|
|
792
|
+
return void 0;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function clampLevel(n) {
|
|
796
|
+
if (!Number.isFinite(n)) return 0;
|
|
797
|
+
return Math.max(0, Math.min(MAX_LIST_LEVEL, Math.trunc(n)));
|
|
798
|
+
}
|
|
799
|
+
function normalizeListLevels(blocks) {
|
|
800
|
+
let i = 0;
|
|
801
|
+
while (i < blocks.length) {
|
|
802
|
+
if (blocks[i].type !== "listItem") {
|
|
803
|
+
i++;
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
let j = i + 1;
|
|
807
|
+
while (j < blocks.length && blocks[j].type === "listItem") j++;
|
|
808
|
+
if (j - i > 1) {
|
|
809
|
+
let min = Number.POSITIVE_INFINITY;
|
|
810
|
+
for (let k = i; k < j; k++) {
|
|
811
|
+
const lvl = blocks[k].attrs.listLevel ?? 0;
|
|
812
|
+
if (lvl < min) min = lvl;
|
|
813
|
+
}
|
|
814
|
+
if (min > 0) {
|
|
815
|
+
for (let k = i; k < j; k++) {
|
|
816
|
+
const lvl = blocks[k].attrs.listLevel ?? 0;
|
|
817
|
+
blocks[k].attrs.listLevel = clampLevel(lvl - min);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
i = j;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
function pushOp(ops, text, marks) {
|
|
825
|
+
const hasMarks = Object.keys(marks).length > 0;
|
|
826
|
+
ops.push(hasMarks ? { insert: text, attributes: { ...marks } } : { insert: text });
|
|
827
|
+
}
|
|
828
|
+
function normalizeWhitespace(raw) {
|
|
829
|
+
return raw.replace(/[ \t\r\n]+/g, " ");
|
|
830
|
+
}
|
|
831
|
+
function trimEdgeWhitespace(ops) {
|
|
832
|
+
let out = ops;
|
|
833
|
+
if (out.length > 0 && typeof out[0].insert === "string") {
|
|
834
|
+
const trimmed = out[0].insert.replace(/^ +/, "");
|
|
835
|
+
if (trimmed.length === 0) out = out.slice(1);
|
|
836
|
+
else if (trimmed !== out[0].insert) out = [{ ...out[0], insert: trimmed }, ...out.slice(1)];
|
|
837
|
+
}
|
|
838
|
+
if (out.length > 0 && typeof out[out.length - 1].insert === "string") {
|
|
839
|
+
const last = out[out.length - 1];
|
|
840
|
+
const trimmed = last.insert.replace(/ +$/, "");
|
|
841
|
+
if (trimmed.length === 0) out = out.slice(0, -1);
|
|
842
|
+
else if (trimmed !== last.insert) out = [...out.slice(0, -1), { ...last, insert: trimmed }];
|
|
843
|
+
}
|
|
844
|
+
return out;
|
|
845
|
+
}
|
|
846
|
+
function mergeAdjacentOps(ops) {
|
|
847
|
+
const out = [];
|
|
848
|
+
for (const op of ops) {
|
|
849
|
+
const prev = out[out.length - 1];
|
|
850
|
+
if (prev && typeof prev.insert === "string" && typeof op.insert === "string" && sameMarks(prev.attributes, op.attributes)) {
|
|
851
|
+
prev.insert = prev.insert + op.insert;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
out.push({ ...op });
|
|
855
|
+
}
|
|
856
|
+
return out;
|
|
857
|
+
}
|
|
858
|
+
function sameMarks(a, b) {
|
|
859
|
+
const ak = a ? Object.keys(a).sort() : [];
|
|
860
|
+
const bk = b ? Object.keys(b).sort() : [];
|
|
861
|
+
if (ak.length !== bk.length) return false;
|
|
862
|
+
for (let i = 0; i < ak.length; i++) {
|
|
863
|
+
if (ak[i] !== bk[i]) return false;
|
|
864
|
+
const av = a[ak[i]];
|
|
865
|
+
const bv = b[bk[i]];
|
|
866
|
+
if (typeof av === "object" && av !== null && typeof bv === "object" && bv !== null) {
|
|
867
|
+
if (JSON.stringify(av) !== JSON.stringify(bv)) return false;
|
|
868
|
+
} else if (av !== bv) {
|
|
869
|
+
return false;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return true;
|
|
873
|
+
}
|
|
874
|
+
function deltaToText(delta) {
|
|
875
|
+
let s = "";
|
|
876
|
+
for (const op of delta) if (typeof op.insert === "string") s += op.insert;
|
|
877
|
+
return s;
|
|
878
|
+
}
|
|
879
|
+
function makeBlock(type, delta, attrs) {
|
|
880
|
+
return { type, text: deltaToText(delta), delta, attrs };
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// src/pastePlan.ts
|
|
884
|
+
function planPaste(cd) {
|
|
885
|
+
const raw = cd.getData(SOFER_MIME);
|
|
886
|
+
if (raw) {
|
|
887
|
+
try {
|
|
888
|
+
const slice = JSON.parse(raw);
|
|
889
|
+
if (slice && Array.isArray(slice.blocks)) return { kind: "sofer", slice };
|
|
890
|
+
} catch {
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
const html = cd.getData("text/html");
|
|
894
|
+
if (html) {
|
|
895
|
+
const slice = htmlToSlice(html);
|
|
896
|
+
if (slice) return { kind: "html", slice };
|
|
897
|
+
}
|
|
898
|
+
const files = Array.from(cd.files ?? []).filter((f) => f.type.startsWith("image/"));
|
|
899
|
+
if (files.length > 0) return { kind: "images", files };
|
|
900
|
+
const text = cd.getData("text/plain");
|
|
901
|
+
if (text.length > 0) return { kind: "text", text };
|
|
902
|
+
return { kind: "none" };
|
|
903
|
+
}
|
|
904
|
+
|
|
296
905
|
// src/BehindImageSelectAffordance.tsx
|
|
297
906
|
import {
|
|
298
907
|
useCallback,
|
|
@@ -2107,7 +2716,7 @@ function NodeView({ block, index, children, fragment, tableFragment }) {
|
|
|
2107
2716
|
const common = commonBlockProps(block.attrs, index, block.type, fragment);
|
|
2108
2717
|
switch (block.type) {
|
|
2109
2718
|
case "heading": {
|
|
2110
|
-
const level =
|
|
2719
|
+
const level = clampLevel2(block.attrs.level);
|
|
2111
2720
|
const Tag = `h${level}`;
|
|
2112
2721
|
return /* @__PURE__ */ jsx11(
|
|
2113
2722
|
Tag,
|
|
@@ -2194,7 +2803,7 @@ function cellStyle(attrs, border) {
|
|
|
2194
2803
|
if (attrs?.bgColor) style.backgroundColor = attrs.bgColor;
|
|
2195
2804
|
return Object.keys(style).length > 0 ? style : void 0;
|
|
2196
2805
|
}
|
|
2197
|
-
function
|
|
2806
|
+
function clampLevel2(l) {
|
|
2198
2807
|
if (l === 2 || l === 3 || l === 4 || l === 5 || l === 6) return l;
|
|
2199
2808
|
return 1;
|
|
2200
2809
|
}
|
|
@@ -2254,7 +2863,8 @@ function TableView({ block, index, tableFragment }) {
|
|
|
2254
2863
|
cellBorderStyle(
|
|
2255
2864
|
block.attrs.borderPreset,
|
|
2256
2865
|
{ row: r, col: c, rowspan, colspan, cols, rowStart, rowEnd },
|
|
2257
|
-
"screen"
|
|
2866
|
+
"screen",
|
|
2867
|
+
block.attrs.borderColor
|
|
2258
2868
|
)
|
|
2259
2869
|
),
|
|
2260
2870
|
className: inRect ? "ed-cell ed-cell--selected" : "ed-cell",
|
|
@@ -3087,6 +3697,16 @@ function useEditor(opts = {}) {
|
|
|
3087
3697
|
if (!doc.isTable(sel.focus.blockIndex)) return "all";
|
|
3088
3698
|
return doc.getBlockAttrs(sel.focus.blockIndex).borderPreset ?? "all";
|
|
3089
3699
|
}, [doc]);
|
|
3700
|
+
const setTableBorderColor = useCallback6((color) => {
|
|
3701
|
+
const sel = selectionRef.current;
|
|
3702
|
+
if (!doc.isTable(sel.focus.blockIndex)) return;
|
|
3703
|
+
cmdSetBlockAttrAtIndex(ctxRef.current, sel.focus.blockIndex, "borderColor", color);
|
|
3704
|
+
}, [doc]);
|
|
3705
|
+
const getTableBorderColor = useCallback6(() => {
|
|
3706
|
+
const sel = selectionRef.current;
|
|
3707
|
+
if (!doc.isTable(sel.focus.blockIndex)) return void 0;
|
|
3708
|
+
return doc.getBlockAttrs(sel.focus.blockIndex).borderColor;
|
|
3709
|
+
}, [doc]);
|
|
3090
3710
|
const isListActive = useCallback6(
|
|
3091
3711
|
(kind) => {
|
|
3092
3712
|
const sel = selectionRef.current;
|
|
@@ -3333,6 +3953,8 @@ function useEditor(opts = {}) {
|
|
|
3333
3953
|
getCellBackground,
|
|
3334
3954
|
setTableBorderPreset,
|
|
3335
3955
|
getTableBorderPreset,
|
|
3956
|
+
setTableBorderColor,
|
|
3957
|
+
getTableBorderColor,
|
|
3336
3958
|
isListActive,
|
|
3337
3959
|
toggleList,
|
|
3338
3960
|
indentList,
|
|
@@ -3842,7 +4464,7 @@ function Editor({
|
|
|
3842
4464
|
const ctx = ctxRef.current;
|
|
3843
4465
|
const slice = serializeSelection(ctx.doc, ctx.getSelection());
|
|
3844
4466
|
if (!slice || !e.clipboardData) return false;
|
|
3845
|
-
e.clipboardData.setData(
|
|
4467
|
+
e.clipboardData.setData(SOFER_MIME2, JSON.stringify(slice));
|
|
3846
4468
|
e.clipboardData.setData("text/plain", sliceToText(slice));
|
|
3847
4469
|
return true;
|
|
3848
4470
|
};
|
|
@@ -3857,34 +4479,28 @@ function Editor({
|
|
|
3857
4479
|
const ctx = ctxRef.current;
|
|
3858
4480
|
const cd = e.clipboardData;
|
|
3859
4481
|
if (!cd) return;
|
|
3860
|
-
const
|
|
3861
|
-
if (
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
4482
|
+
const plan = planPaste(cd);
|
|
4483
|
+
if (plan.kind === "none") return;
|
|
4484
|
+
e.preventDefault();
|
|
4485
|
+
switch (plan.kind) {
|
|
4486
|
+
case "sofer":
|
|
4487
|
+
case "html":
|
|
4488
|
+
insertSlice(ctx, plan.slice);
|
|
4489
|
+
return;
|
|
4490
|
+
case "images":
|
|
4491
|
+
void (async () => {
|
|
4492
|
+
for (const f of plan.files) await editorRef.current.insertImageFromFile(f);
|
|
4493
|
+
})();
|
|
4494
|
+
return;
|
|
4495
|
+
case "text": {
|
|
4496
|
+
const lines = plan.text.split(/\r\n|\r|\n/);
|
|
4497
|
+
lines.forEach((line, i) => {
|
|
4498
|
+
if (i > 0) insertParagraph(ctx);
|
|
4499
|
+
if (line.length > 0) insertText(ctx, line);
|
|
4500
|
+
});
|
|
4501
|
+
return;
|
|
3870
4502
|
}
|
|
3871
4503
|
}
|
|
3872
|
-
const images = Array.from(cd.files ?? []).filter((f) => f.type.startsWith("image/"));
|
|
3873
|
-
if (images.length > 0) {
|
|
3874
|
-
e.preventDefault();
|
|
3875
|
-
void (async () => {
|
|
3876
|
-
for (const f of images) await editorRef.current.insertImageFromFile(f);
|
|
3877
|
-
})();
|
|
3878
|
-
return;
|
|
3879
|
-
}
|
|
3880
|
-
const text = cd.getData("text/plain");
|
|
3881
|
-
if (text.length === 0) return;
|
|
3882
|
-
e.preventDefault();
|
|
3883
|
-
const lines = text.split(/\r\n|\r|\n/);
|
|
3884
|
-
lines.forEach((line, i) => {
|
|
3885
|
-
if (i > 0) insertParagraph(ctx);
|
|
3886
|
-
if (line.length > 0) insertText(ctx, line);
|
|
3887
|
-
});
|
|
3888
4504
|
};
|
|
3889
4505
|
root.addEventListener("copy", onCopy);
|
|
3890
4506
|
root.addEventListener("cut", onCut);
|
|
@@ -4139,11 +4755,15 @@ function groupTopLevels(snapshot) {
|
|
|
4139
4755
|
const groupStart = i;
|
|
4140
4756
|
const items = [];
|
|
4141
4757
|
const kind = block.attrs.listKind === "ordered" ? "ordered" : "bullet";
|
|
4758
|
+
const leaderLevel = clampListLevel2(block.attrs.listLevel);
|
|
4142
4759
|
const groupStyle = block.attrs.listStyle;
|
|
4143
4760
|
while (i < snapshot.length) {
|
|
4144
4761
|
const b = snapshot[i];
|
|
4145
4762
|
if (b.type !== "listItem") break;
|
|
4146
|
-
|
|
4763
|
+
const bLevel = clampListLevel2(b.attrs.listLevel);
|
|
4764
|
+
if (bLevel <= leaderLevel && (b.attrs.listKind ?? "bullet") !== kind) {
|
|
4765
|
+
break;
|
|
4766
|
+
}
|
|
4147
4767
|
if (i > groupStart) {
|
|
4148
4768
|
if (typeof b.attrs.listStart === "number") break;
|
|
4149
4769
|
const itemStyle = b.attrs.listStyle;
|
|
@@ -4251,7 +4871,7 @@ function buildListTree(items) {
|
|
|
4251
4871
|
function renderListTree(tree, top, start, key) {
|
|
4252
4872
|
const className = `ed-list ed-list-${top.listKind}`;
|
|
4253
4873
|
const style = top.listStyle ? { listStyleType: top.listStyle } : void 0;
|
|
4254
|
-
const items = tree.map((node) => /* @__PURE__ */ jsx12(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children,
|
|
4874
|
+
const items = tree.map((node) => /* @__PURE__ */ jsx12(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));
|
|
4255
4875
|
if (top.listKind === "ordered") {
|
|
4256
4876
|
return /* @__PURE__ */ jsx12(
|
|
4257
4877
|
"ol",
|
|
@@ -4267,9 +4887,10 @@ function renderListTree(tree, top, start, key) {
|
|
|
4267
4887
|
}
|
|
4268
4888
|
return /* @__PURE__ */ jsx12("ul", { className, "data-list-kind": "bullet", style, children: items }, key);
|
|
4269
4889
|
}
|
|
4270
|
-
function renderNestedListTree(tree,
|
|
4890
|
+
function renderNestedListTree(tree, key) {
|
|
4891
|
+
const kind = tree[0]?.entry.block.attrs.listKind === "ordered" ? "ordered" : "bullet";
|
|
4271
4892
|
const Tag = kind === "ordered" ? "ol" : "ul";
|
|
4272
|
-
return /* @__PURE__ */ jsx12(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ jsx12(NodeView, { block: node.entry.block, index: node.entry.index, children: node.children.length > 0 ? renderNestedListTree(node.children,
|
|
4893
|
+
return /* @__PURE__ */ jsx12(Tag, { className: `ed-list ed-list-${kind}`, "data-list-kind": kind, children: tree.map((node) => /* @__PURE__ */ jsx12(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);
|
|
4273
4894
|
}
|
|
4274
4895
|
function clampListLevel2(l) {
|
|
4275
4896
|
if (typeof l !== "number" || !Number.isFinite(l)) return 0;
|
|
@@ -4303,7 +4924,7 @@ import {
|
|
|
4303
4924
|
useRef as useRef12,
|
|
4304
4925
|
useState as useState11
|
|
4305
4926
|
} from "react";
|
|
4306
|
-
import { ANSWER_LINE_MAX } from "@sofereditor/core";
|
|
4927
|
+
import { ANSWER_LINE_MAX, TABLE_BORDER_COLOR } from "@sofereditor/core";
|
|
4307
4928
|
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4308
4929
|
var FONT_FAMILIES = ["Arial"];
|
|
4309
4930
|
var FONT_SIZES = ["8pt", "10pt", "11pt", "12pt", "14pt", "16pt", "18pt", "24pt", "32pt", "48pt"];
|
|
@@ -4325,6 +4946,15 @@ var ALIGN_OPTIONS = [
|
|
|
4325
4946
|
{ value: "justify", label: "\u2630", title: "Justificar" }
|
|
4326
4947
|
];
|
|
4327
4948
|
var IMAGE_ALIGN_VALUES = /* @__PURE__ */ new Set(["left", "center", "right"]);
|
|
4949
|
+
var NATIVE_CONTROL_TAGS = /* @__PURE__ */ new Set(["SELECT", "INPUT", "OPTION"]);
|
|
4950
|
+
function isNativeControl(t) {
|
|
4951
|
+
const el = t;
|
|
4952
|
+
return !!el && NATIVE_CONTROL_TAGS.has(el.tagName);
|
|
4953
|
+
}
|
|
4954
|
+
function keepsOwnMouseDown(t) {
|
|
4955
|
+
const el = t;
|
|
4956
|
+
return !!el && (NATIVE_CONTROL_TAGS.has(el.tagName) || el.tagName === "BUTTON");
|
|
4957
|
+
}
|
|
4328
4958
|
var IMAGE_LAYOUT_OPTIONS = [
|
|
4329
4959
|
{ value: "inline", label: "\u2194", title: "Inline (no fluxo do texto)" },
|
|
4330
4960
|
{ value: "wrap-left", label: "\u25E7", title: "Texto contorna \xE0 direita" },
|
|
@@ -4357,10 +4987,7 @@ function Toolbar({ className }) {
|
|
|
4357
4987
|
const blockAlign = getAlign();
|
|
4358
4988
|
const blockDir = getBlockAttr("dir");
|
|
4359
4989
|
const stop = (e) => {
|
|
4360
|
-
|
|
4361
|
-
if (t && (t.tagName === "SELECT" || t.tagName === "INPUT" || t.tagName === "OPTION")) {
|
|
4362
|
-
return;
|
|
4363
|
-
}
|
|
4990
|
+
if (isNativeControl(e.target)) return;
|
|
4364
4991
|
e.preventDefault();
|
|
4365
4992
|
};
|
|
4366
4993
|
const onToggle = (name) => (e) => {
|
|
@@ -4792,10 +5419,7 @@ function AnswerLinesMenu() {
|
|
|
4792
5419
|
className: "ed-table-popover ed-answerlines-popover",
|
|
4793
5420
|
role: "menu",
|
|
4794
5421
|
onMouseDown: (e) => {
|
|
4795
|
-
|
|
4796
|
-
if (!t || t.tagName !== "INPUT" && t.tagName !== "BUTTON" && t.tagName !== "SELECT") {
|
|
4797
|
-
e.preventDefault();
|
|
4798
|
-
}
|
|
5422
|
+
if (!keepsOwnMouseDown(e.target)) e.preventDefault();
|
|
4799
5423
|
},
|
|
4800
5424
|
children: [
|
|
4801
5425
|
/* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label", children: [
|
|
@@ -4886,10 +5510,7 @@ function TableMenu() {
|
|
|
4886
5510
|
className: "ed-table-popover",
|
|
4887
5511
|
role: "menu",
|
|
4888
5512
|
onMouseDown: (e) => {
|
|
4889
|
-
|
|
4890
|
-
if (!t || t.tagName !== "INPUT" && t.tagName !== "BUTTON") {
|
|
4891
|
-
e.preventDefault();
|
|
4892
|
-
}
|
|
5513
|
+
if (!keepsOwnMouseDown(e.target)) e.preventDefault();
|
|
4893
5514
|
},
|
|
4894
5515
|
children: [
|
|
4895
5516
|
/* @__PURE__ */ jsx13(
|
|
@@ -4995,6 +5616,37 @@ function TableMenu() {
|
|
|
4995
5616
|
}
|
|
4996
5617
|
)
|
|
4997
5618
|
] }),
|
|
5619
|
+
/* @__PURE__ */ jsxs12("label", { className: "ed-toolbar-label ed-table-bgcolor", children: [
|
|
5620
|
+
/* @__PURE__ */ jsx13(
|
|
5621
|
+
"span",
|
|
5622
|
+
{
|
|
5623
|
+
className: "ed-toolbar-swatch",
|
|
5624
|
+
"aria-hidden": true,
|
|
5625
|
+
style: { background: editor.getTableBorderColor() ?? TABLE_BORDER_COLOR }
|
|
5626
|
+
}
|
|
5627
|
+
),
|
|
5628
|
+
"Cor da borda",
|
|
5629
|
+
/* @__PURE__ */ jsx13(
|
|
5630
|
+
"input",
|
|
5631
|
+
{
|
|
5632
|
+
type: "color",
|
|
5633
|
+
value: editor.getTableBorderColor() ?? TABLE_BORDER_COLOR,
|
|
5634
|
+
onChange: (e) => editor.setTableBorderColor(e.target.value),
|
|
5635
|
+
"aria-label": "Cor da borda"
|
|
5636
|
+
}
|
|
5637
|
+
)
|
|
5638
|
+
] }),
|
|
5639
|
+
/* @__PURE__ */ jsx13(
|
|
5640
|
+
"button",
|
|
5641
|
+
{
|
|
5642
|
+
type: "button",
|
|
5643
|
+
onClick: () => {
|
|
5644
|
+
setOpen(false);
|
|
5645
|
+
editor.setTableBorderColor(null);
|
|
5646
|
+
},
|
|
5647
|
+
children: "Restaurar cor padr\xE3o"
|
|
5648
|
+
}
|
|
5649
|
+
),
|
|
4998
5650
|
/* @__PURE__ */ jsx13("hr", {}),
|
|
4999
5651
|
/* @__PURE__ */ jsx13(
|
|
5000
5652
|
"button",
|
|
@@ -5099,6 +5751,7 @@ export {
|
|
|
5099
5751
|
getBlockElement,
|
|
5100
5752
|
getCellElement,
|
|
5101
5753
|
getFragmentForOffset,
|
|
5754
|
+
htmlToSlice,
|
|
5102
5755
|
isTableRectSelection,
|
|
5103
5756
|
locatePoint,
|
|
5104
5757
|
readDomSelection,
|