rich-html-editor 0.2.1 → 1.0.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.mjs CHANGED
@@ -16,10 +16,12 @@ import {
16
16
  LABEL_BOLD,
17
17
  LABEL_ITALIC,
18
18
  LABEL_LINK,
19
+ LABEL_ORDERED_LIST,
19
20
  LABEL_REDO,
20
21
  LABEL_STRIKETHROUGH,
21
22
  LABEL_UNDERLINE,
22
23
  LABEL_UNDO,
24
+ LABEL_UNORDERED_LIST,
23
25
  SIZE_OPTIONS,
24
26
  STYLE_ID,
25
27
  TOOLBAR_BG,
@@ -37,7 +39,7 @@ import {
37
39
  getEditorEventEmitter,
38
40
  pushStandaloneSnapshot,
39
41
  sanitizeHtml
40
- } from "./chunk-ZDGUOGND.mjs";
42
+ } from "./chunk-W3ULZ2LR.mjs";
41
43
 
42
44
  // src/dom/styles.ts
43
45
  function injectStyles(doc) {
@@ -317,218 +319,73 @@ function injectStyles(doc) {
317
319
  styleEl.textContent = css;
318
320
  }
319
321
 
320
- // src/toolbar/toolbar.ts
321
- function injectToolbar(doc, options) {
322
- const existing = doc.getElementById(TOOLBAR_ID);
323
- if (existing) existing.remove();
324
- const toolbar = doc.createElement("div");
325
- toolbar.id = TOOLBAR_ID;
326
- toolbar.setAttribute("role", "toolbar");
327
- toolbar.setAttribute("aria-label", "Rich text editor toolbar");
328
- function makeButton(label, title, command, value, isActive, disabled) {
329
- const btn = doc.createElement("button");
330
- btn.type = "button";
331
- if (label && label.trim().startsWith("<")) {
332
- btn.innerHTML = label;
333
- } else {
334
- btn.textContent = label;
322
+ // src/toolbar/color.ts
323
+ function makeColorInput(doc, options, title, command, initialColor) {
324
+ const input = doc.createElement("input");
325
+ input.type = "color";
326
+ input.className = "toolbar-color-input";
327
+ const wrapper = doc.createElement("label");
328
+ wrapper.className = "color-label";
329
+ wrapper.appendChild(doc.createTextNode(title + " "));
330
+ wrapper.appendChild(input);
331
+ let savedRange = null;
332
+ input.addEventListener("pointerdown", () => {
333
+ const s = doc.getSelection();
334
+ if (s && s.rangeCount) savedRange = s.getRangeAt(0).cloneRange();
335
+ });
336
+ input.onchange = (e) => {
337
+ try {
338
+ const s = doc.getSelection();
339
+ if (savedRange && s) {
340
+ s.removeAllRanges();
341
+ s.addRange(savedRange);
342
+ }
343
+ } catch (err) {
335
344
  }
336
- btn.title = title;
337
- btn.setAttribute("aria-label", title);
338
- if (typeof isActive !== "undefined")
339
- btn.setAttribute("aria-pressed", String(!!isActive));
340
- btn.tabIndex = 0;
341
- if (disabled) btn.disabled = true;
342
- btn.onclick = () => options.onCommand(command, value);
343
- btn.addEventListener("keydown", (ev) => {
344
- if (ev.key === "Enter" || ev.key === " ") {
345
- ev.preventDefault();
346
- btn.click();
345
+ options.onCommand(command, e.target.value);
346
+ savedRange = null;
347
+ };
348
+ function rgbToHex(input2) {
349
+ if (!input2) return null;
350
+ const v = input2.trim();
351
+ if (v.startsWith("#")) {
352
+ if (v.length === 4) {
353
+ return ("#" + v[1] + v[1] + v[2] + v[2] + v[3] + v[3]).toLowerCase();
347
354
  }
348
- });
349
- return btn;
350
- }
351
- function makeSelect(title, command, optionsList, initialValue) {
352
- const select = doc.createElement("select");
353
- select.title = title;
354
- select.setAttribute("aria-label", title);
355
- select.appendChild(new Option(title, "", true, true));
356
- for (const opt of optionsList) {
357
- select.appendChild(new Option(opt.label, opt.value));
355
+ return v.toLowerCase();
358
356
  }
359
- try {
360
- if (initialValue) select.value = initialValue;
361
- } catch (e) {
357
+ const rgbMatch = v.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
358
+ if (rgbMatch) {
359
+ const r = Number(rgbMatch[1]);
360
+ const g = Number(rgbMatch[2]);
361
+ const b = Number(rgbMatch[3]);
362
+ const hex = "#" + [r, g, b].map((n) => n.toString(16).padStart(2, "0")).join("").toLowerCase();
363
+ return hex;
362
364
  }
363
- select.onchange = (e) => {
364
- const val = e.target.value;
365
- options.onCommand(command, val);
366
- select.selectedIndex = 0;
367
- };
368
- return select;
365
+ return null;
369
366
  }
370
- function makeColorInput(title, command, initialColor) {
371
- const input = doc.createElement("input");
372
- input.type = "color";
373
- input.className = "toolbar-color-input";
374
- const wrapper = doc.createElement("label");
375
- wrapper.className = "color-label";
376
- wrapper.appendChild(doc.createTextNode(title + " "));
377
- wrapper.appendChild(input);
378
- let savedRange = null;
379
- input.addEventListener("pointerdown", () => {
380
- const s = doc.getSelection();
381
- if (s && s.rangeCount) savedRange = s.getRangeAt(0).cloneRange();
382
- });
383
- input.onchange = (e) => {
384
- try {
385
- const s = doc.getSelection();
386
- if (savedRange && s) {
387
- s.removeAllRanges();
388
- s.addRange(savedRange);
389
- }
390
- } catch (err) {
391
- }
392
- options.onCommand(command, e.target.value);
393
- savedRange = null;
394
- };
395
- function rgbToHex(input2) {
396
- if (!input2) return null;
397
- const v = input2.trim();
398
- if (v.startsWith("#")) {
399
- if (v.length === 4) {
400
- return ("#" + v[1] + v[1] + v[2] + v[2] + v[3] + v[3]).toLowerCase();
401
- }
402
- return v.toLowerCase();
403
- }
404
- const rgbMatch = v.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i);
405
- if (rgbMatch) {
406
- const r = Number(rgbMatch[1]);
407
- const g = Number(rgbMatch[2]);
408
- const b = Number(rgbMatch[3]);
409
- const hex = "#" + [r, g, b].map((n) => n.toString(16).padStart(2, "0")).join("").toLowerCase();
410
- return hex;
367
+ const setColor = (val) => {
368
+ if (!val) return;
369
+ const hex = rgbToHex(val) || val;
370
+ try {
371
+ if (hex && hex.startsWith("#") && input.value !== hex) {
372
+ input.value = hex;
411
373
  }
412
- return null;
374
+ } catch (e) {
413
375
  }
414
- const setColor = (val) => {
415
- if (!val) return;
416
- const hex = rgbToHex(val) || val;
417
- try {
418
- if (hex && hex.startsWith("#") && input.value !== hex) {
419
- input.value = hex;
420
- }
421
- } catch (e) {
422
- }
423
- };
424
- if (initialColor) setColor(initialColor);
425
- input.addEventListener("input", (e) => {
426
- const val = e.target.value;
427
- setColor(val);
428
- });
429
- input.title = title;
430
- input.setAttribute("aria-label", title);
431
- return wrapper;
432
- }
433
- const format = options.getFormatState();
434
- function makeGroup() {
435
- const g = doc.createElement("div");
436
- g.className = "toolbar-group";
437
- return g;
438
- }
439
- function makeSep() {
440
- const s = doc.createElement("div");
441
- s.className = "toolbar-sep";
442
- return s;
443
- }
444
- const undoBtn = makeButton(
445
- LABEL_UNDO,
446
- "Undo",
447
- "undo",
448
- void 0,
449
- false,
450
- !options.canUndo()
451
- );
452
- undoBtn.onclick = () => options.onUndo();
453
- const redoBtn = makeButton(
454
- LABEL_REDO,
455
- "Redo",
456
- "redo",
457
- void 0,
458
- false,
459
- !options.canRedo()
460
- );
461
- redoBtn.onclick = () => options.onRedo();
462
- const grp1 = makeGroup();
463
- grp1.appendChild(undoBtn);
464
- grp1.appendChild(redoBtn);
465
- toolbar.appendChild(grp1);
466
- toolbar.appendChild(makeSep());
467
- const grp2 = makeGroup();
468
- grp2.className = "toolbar-group collapse-on-small";
469
- grp2.appendChild(
470
- makeSelect(
471
- "Format",
472
- "formatBlock",
473
- FORMAT_OPTIONS,
474
- format.formatBlock
475
- )
476
- );
477
- grp2.appendChild(
478
- makeSelect("Font", "fontName", FONT_OPTIONS, format.fontName)
479
- );
480
- grp2.appendChild(
481
- makeSelect("Size", "fontSize", SIZE_OPTIONS, format.fontSize)
482
- );
483
- toolbar.appendChild(grp2);
484
- toolbar.appendChild(makeSep());
485
- const grp3 = makeGroup();
486
- grp3.appendChild(
487
- makeButton(LABEL_BOLD, "Bold", "bold", void 0, format.bold)
488
- );
489
- grp3.appendChild(
490
- makeButton(LABEL_ITALIC, "Italic", "italic", void 0, format.italic)
491
- );
492
- grp3.appendChild(
493
- makeButton(
494
- LABEL_UNDERLINE,
495
- "Underline",
496
- "underline",
497
- void 0,
498
- format.underline
499
- )
500
- );
501
- grp3.appendChild(makeButton(LABEL_STRIKETHROUGH, "Strikethrough", "strike"));
502
- toolbar.appendChild(grp3);
503
- toolbar.appendChild(makeSep());
504
- const grp4 = makeGroup();
505
- grp4.appendChild(makeButton(LABEL_ALIGN_LEFT, "Align left", "align", "left"));
506
- grp4.appendChild(
507
- makeButton(LABEL_ALIGN_CENTER, "Align center", "align", "center")
508
- );
509
- grp4.appendChild(
510
- makeButton(LABEL_ALIGN_RIGHT, "Align right", "align", "right")
511
- );
512
- toolbar.appendChild(grp4);
513
- toolbar.appendChild(makeSep());
514
- const grp5 = makeGroup();
515
- grp5.className = "toolbar-group collapse-on-small";
516
- grp5.appendChild(
517
- makeColorInput("Text color", "foreColor", format.foreColor)
518
- );
519
- grp5.appendChild(
520
- makeColorInput(
521
- "Highlight color",
522
- "hiliteColor",
523
- format.hiliteColor
524
- )
525
- );
526
- toolbar.appendChild(grp5);
527
- toolbar.appendChild(makeSep());
528
- const grp6 = makeGroup();
529
- grp6.className = "toolbar-group collapse-on-small";
530
- grp6.appendChild(makeButton(LABEL_LINK, "Insert link", "link"));
531
- toolbar.appendChild(grp6);
376
+ };
377
+ if (initialColor) setColor(initialColor);
378
+ input.addEventListener("input", (e) => {
379
+ const val = e.target.value;
380
+ setColor(val);
381
+ });
382
+ input.title = title;
383
+ input.setAttribute("aria-label", title);
384
+ return wrapper;
385
+ }
386
+
387
+ // src/toolbar/overflow.ts
388
+ function setupOverflow(doc, toolbar, options, format, helpers) {
532
389
  const overflowBtn = doc.createElement("button");
533
390
  overflowBtn.type = "button";
534
391
  overflowBtn.className = "toolbar-overflow-btn";
@@ -555,7 +412,7 @@ function injectToolbar(doc, options) {
555
412
  overflowBtn.setAttribute("aria-expanded", "false");
556
413
  overflowBtn.focus();
557
414
  }
558
- overflowBtn.addEventListener("click", (e) => {
415
+ overflowBtn.addEventListener("click", () => {
559
416
  if (overflowMenu.hidden) openOverflow();
560
417
  else closeOverflow();
561
418
  });
@@ -582,35 +439,105 @@ function injectToolbar(doc, options) {
582
439
  }
583
440
  });
584
441
  overflowMenu.appendChild(
585
- makeSelect(
442
+ helpers.makeSelect(
586
443
  "Format",
587
444
  "formatBlock",
588
- FORMAT_OPTIONS,
445
+ window.RHE_FORMAT_OPTIONS || [],
589
446
  format.formatBlock
590
447
  )
591
448
  );
592
449
  overflowMenu.appendChild(
593
- makeSelect("Font", "fontName", FONT_OPTIONS, format.fontName)
450
+ helpers.makeSelect(
451
+ "Font",
452
+ "fontName",
453
+ window.RHE_FONT_OPTIONS || [],
454
+ format.fontName
455
+ )
594
456
  );
595
457
  overflowMenu.appendChild(
596
- makeSelect("Size", "fontSize", SIZE_OPTIONS, format.fontSize)
458
+ helpers.makeSelect(
459
+ "Size",
460
+ "fontSize",
461
+ window.RHE_SIZE_OPTIONS || [],
462
+ format.fontSize
463
+ )
597
464
  );
598
465
  overflowMenu.appendChild(
599
- makeColorInput("Text color", "foreColor", format.foreColor)
466
+ helpers.makeColorInput("Text color", "foreColor", format.foreColor)
600
467
  );
601
468
  overflowMenu.appendChild(
602
- makeColorInput(
469
+ helpers.makeColorInput(
603
470
  "Highlight color",
604
471
  "hiliteColor",
605
472
  format.hiliteColor
606
473
  )
607
474
  );
608
- overflowMenu.appendChild(makeButton(LABEL_LINK, "Insert link", "link"));
609
- const overflowWrap = makeGroup();
475
+ overflowMenu.appendChild(helpers.makeButton("Link", "Insert link", "link"));
476
+ const overflowWrap = helpers.makeGroup();
610
477
  overflowWrap.className = "toolbar-group toolbar-overflow-wrap";
611
478
  overflowWrap.appendChild(overflowBtn);
612
479
  overflowWrap.appendChild(overflowMenu);
613
480
  toolbar.appendChild(overflowWrap);
481
+ }
482
+
483
+ // src/toolbar/buttons.ts
484
+ function makeButton(doc, options, label, title, command, value, isActive, disabled) {
485
+ const btn = doc.createElement("button");
486
+ btn.type = "button";
487
+ if (label && label.trim().startsWith("<")) {
488
+ btn.innerHTML = label;
489
+ } else {
490
+ btn.textContent = label;
491
+ }
492
+ btn.title = title;
493
+ btn.setAttribute("aria-label", title);
494
+ if (typeof isActive !== "undefined")
495
+ btn.setAttribute("aria-pressed", String(!!isActive));
496
+ btn.tabIndex = 0;
497
+ if (disabled) btn.disabled = true;
498
+ btn.onclick = () => options.onCommand(command, value);
499
+ btn.addEventListener("keydown", (ev) => {
500
+ if (ev.key === "Enter" || ev.key === " ") {
501
+ ev.preventDefault();
502
+ btn.click();
503
+ }
504
+ });
505
+ return btn;
506
+ }
507
+ function makeGroup(doc) {
508
+ const g = doc.createElement("div");
509
+ g.className = "toolbar-group";
510
+ return g;
511
+ }
512
+ function makeSep(doc) {
513
+ const s = doc.createElement("div");
514
+ s.className = "toolbar-sep";
515
+ return s;
516
+ }
517
+
518
+ // src/toolbar/selects.ts
519
+ function makeSelect(doc, options, title, command, optionsList, initialValue) {
520
+ const select = doc.createElement("select");
521
+ select.title = title;
522
+ select.setAttribute("aria-label", title);
523
+ select.appendChild(new Option(title, "", true, true));
524
+ for (const opt of optionsList) {
525
+ select.appendChild(new Option(opt.label, opt.value));
526
+ }
527
+ try {
528
+ if (initialValue) select.value = initialValue;
529
+ } catch (e) {
530
+ }
531
+ select.onchange = (e) => {
532
+ const val = e.target.value;
533
+ options.onCommand(command, val);
534
+ select.selectedIndex = 0;
535
+ };
536
+ return select;
537
+ }
538
+
539
+ // src/toolbar/navigation.ts
540
+ function setupNavigation(toolbar) {
614
541
  toolbar.addEventListener("keydown", (e) => {
615
542
  const focusable = Array.from(
616
543
  toolbar.querySelectorAll("button, select, input, [tabindex]")
@@ -633,6 +560,158 @@ function injectToolbar(doc, options) {
633
560
  focusable[focusable.length - 1].focus();
634
561
  }
635
562
  });
563
+ }
564
+
565
+ // src/toolbar/render.ts
566
+ function injectToolbar(doc, options) {
567
+ const existing = doc.getElementById(TOOLBAR_ID);
568
+ if (existing) existing.remove();
569
+ const toolbar = doc.createElement("div");
570
+ toolbar.id = TOOLBAR_ID;
571
+ toolbar.setAttribute("role", "toolbar");
572
+ toolbar.setAttribute("aria-label", "Rich text editor toolbar");
573
+ const makeButton2 = (label, title, command, value, isActive, disabled) => makeButton(
574
+ doc,
575
+ { onCommand: options.onCommand },
576
+ label,
577
+ title,
578
+ command,
579
+ value,
580
+ isActive,
581
+ disabled
582
+ );
583
+ const makeSelect2 = (title, command, optionsList, initialValue) => makeSelect(
584
+ doc,
585
+ { onCommand: options.onCommand },
586
+ title,
587
+ command,
588
+ optionsList,
589
+ initialValue
590
+ );
591
+ const format = options.getFormatState();
592
+ const makeGroup2 = () => makeGroup(doc);
593
+ const makeSep2 = () => makeSep(doc);
594
+ const undoBtn = makeButton2(
595
+ LABEL_UNDO,
596
+ "Undo",
597
+ "undo",
598
+ void 0,
599
+ false,
600
+ !options.canUndo()
601
+ );
602
+ undoBtn.onclick = () => options.onUndo();
603
+ const redoBtn = makeButton2(
604
+ LABEL_REDO,
605
+ "Redo",
606
+ "redo",
607
+ void 0,
608
+ false,
609
+ !options.canRedo()
610
+ );
611
+ redoBtn.onclick = () => options.onRedo();
612
+ const grp1 = makeGroup2();
613
+ grp1.appendChild(undoBtn);
614
+ grp1.appendChild(redoBtn);
615
+ toolbar.appendChild(grp1);
616
+ toolbar.appendChild(makeSep2());
617
+ const grp2 = makeGroup2();
618
+ grp2.className = "toolbar-group collapse-on-small";
619
+ grp2.appendChild(
620
+ makeSelect2(
621
+ "Format",
622
+ "formatBlock",
623
+ FORMAT_OPTIONS,
624
+ format.formatBlock
625
+ )
626
+ );
627
+ grp2.appendChild(
628
+ makeSelect2("Font", "fontName", FONT_OPTIONS, format.fontName)
629
+ );
630
+ grp2.appendChild(
631
+ makeSelect2("Size", "fontSize", SIZE_OPTIONS, format.fontSize)
632
+ );
633
+ toolbar.appendChild(grp2);
634
+ toolbar.appendChild(makeSep2());
635
+ const grp3 = makeGroup2();
636
+ grp3.appendChild(
637
+ makeButton2(LABEL_BOLD, "Bold", "bold", void 0, format.bold)
638
+ );
639
+ grp3.appendChild(
640
+ makeButton2(LABEL_ITALIC, "Italic", "italic", void 0, format.italic)
641
+ );
642
+ grp3.appendChild(
643
+ makeButton2(
644
+ LABEL_UNDERLINE,
645
+ "Underline",
646
+ "underline",
647
+ void 0,
648
+ format.underline
649
+ )
650
+ );
651
+ grp3.appendChild(makeButton2(LABEL_STRIKETHROUGH, "Strikethrough", "strike"));
652
+ grp3.appendChild(
653
+ makeButton2(
654
+ LABEL_UNORDERED_LIST,
655
+ "Unordered list",
656
+ "unorderedList",
657
+ void 0,
658
+ format.listType === "ul"
659
+ )
660
+ );
661
+ grp3.appendChild(
662
+ makeButton2(
663
+ LABEL_ORDERED_LIST,
664
+ "Ordered list",
665
+ "orderedList",
666
+ void 0,
667
+ format.listType === "ol"
668
+ )
669
+ );
670
+ toolbar.appendChild(grp3);
671
+ toolbar.appendChild(makeSep2());
672
+ const grp4 = makeGroup2();
673
+ grp4.appendChild(makeButton2(LABEL_ALIGN_LEFT, "Align left", "align", "left"));
674
+ grp4.appendChild(
675
+ makeButton2(LABEL_ALIGN_CENTER, "Align center", "align", "center")
676
+ );
677
+ grp4.appendChild(
678
+ makeButton2(LABEL_ALIGN_RIGHT, "Align right", "align", "right")
679
+ );
680
+ toolbar.appendChild(grp4);
681
+ toolbar.appendChild(makeSep2());
682
+ const grp5 = makeGroup2();
683
+ grp5.className = "toolbar-group collapse-on-small";
684
+ grp5.appendChild(
685
+ makeColorInput(
686
+ doc,
687
+ options,
688
+ "Text color",
689
+ "foreColor",
690
+ format.foreColor
691
+ )
692
+ );
693
+ grp5.appendChild(
694
+ makeColorInput(
695
+ doc,
696
+ options,
697
+ "Highlight color",
698
+ "hiliteColor",
699
+ format.hiliteColor
700
+ )
701
+ );
702
+ toolbar.appendChild(grp5);
703
+ toolbar.appendChild(makeSep2());
704
+ const grp6 = makeGroup2();
705
+ grp6.className = "toolbar-group collapse-on-small";
706
+ grp6.appendChild(makeButton2(LABEL_LINK, "Insert link", "link"));
707
+ toolbar.appendChild(grp6);
708
+ setupOverflow(doc, toolbar, options, format, {
709
+ makeSelect: makeSelect2,
710
+ makeColorInput: (title, command, initial) => makeColorInput(doc, options, title, command, initial),
711
+ makeButton: makeButton2,
712
+ makeGroup: makeGroup2
713
+ });
714
+ setupNavigation(toolbar);
636
715
  doc.body.insertBefore(toolbar, doc.body.firstChild);
637
716
  }
638
717
 
@@ -672,7 +751,8 @@ function computeFormatState(doc) {
672
751
  hiliteColor: null,
673
752
  fontName: null,
674
753
  fontSize: null,
675
- formatBlock: null
754
+ formatBlock: null,
755
+ listType: null
676
756
  };
677
757
  const computed = (_a = doc.defaultView) == null ? void 0 : _a.getComputedStyle(el);
678
758
  const bold = !!(el.closest("strong, b") || computed && (computed.fontWeight === "700" || Number(computed.fontWeight) >= 700));
@@ -708,6 +788,18 @@ function computeFormatState(doc) {
708
788
  blockEl = blockEl.parentElement;
709
789
  }
710
790
  const formatBlock = blockEl ? blockEl.tagName.toLowerCase() : null;
791
+ let listType = null;
792
+ try {
793
+ if (blockEl && blockEl.tagName === "LI") {
794
+ const list = blockEl.closest("ul,ol");
795
+ if (list) listType = list.tagName.toLowerCase();
796
+ } else {
797
+ const possible = el.closest("ul,ol");
798
+ if (possible) listType = possible.tagName.toLowerCase();
799
+ }
800
+ } catch (e) {
801
+ listType = null;
802
+ }
711
803
  return {
712
804
  bold,
713
805
  italic,
@@ -716,7 +808,8 @@ function computeFormatState(doc) {
716
808
  hiliteColor,
717
809
  fontName,
718
810
  fontSize,
719
- formatBlock
811
+ formatBlock,
812
+ listType
720
813
  };
721
814
  } catch (err) {
722
815
  return {
@@ -727,7 +820,8 @@ function computeFormatState(doc) {
727
820
  hiliteColor: null,
728
821
  fontName: null,
729
822
  fontSize: null,
730
- formatBlock: null
823
+ formatBlock: null,
824
+ listType: null
731
825
  };
732
826
  }
733
827
  }
@@ -1120,6 +1214,9 @@ function applyStandaloneCommand(command, value) {
1120
1214
  } else {
1121
1215
  wrapSelectionWithElement(doc, tag);
1122
1216
  }
1217
+ } else if (command === "unorderedList" || command === "orderedList") {
1218
+ const tag = command === "unorderedList" ? "ul" : "ol";
1219
+ toggleList(doc, tag);
1123
1220
  }
1124
1221
  pushStandaloneSnapshot();
1125
1222
  } catch (error) {
@@ -1155,6 +1252,57 @@ function wrapSelectionWithElement(doc, tagName, style) {
1155
1252
  newRange.selectNodeContents(wrapper);
1156
1253
  sel.addRange(newRange);
1157
1254
  }
1255
+ function toggleList(doc, listTag) {
1256
+ var _a, _b;
1257
+ const sel = doc.getSelection();
1258
+ if (!sel || !sel.rangeCount) return;
1259
+ const node = sel.anchorNode || null;
1260
+ const block = findBlockAncestor(node);
1261
+ if (block && block.tagName === "LI" && block.parentElement) {
1262
+ const parentList = block.parentElement;
1263
+ const parentTag = parentList.tagName.toLowerCase();
1264
+ if (parentTag === listTag) {
1265
+ const frag = doc.createDocumentFragment();
1266
+ Array.from(parentList.children).forEach((li2) => {
1267
+ const p = doc.createElement("p");
1268
+ while (li2.firstChild) p.appendChild(li2.firstChild);
1269
+ frag.appendChild(p);
1270
+ });
1271
+ (_a = parentList.parentElement) == null ? void 0 : _a.replaceChild(frag, parentList);
1272
+ return;
1273
+ } else {
1274
+ const newList = doc.createElement(listTag);
1275
+ while (parentList.firstChild) newList.appendChild(parentList.firstChild);
1276
+ (_b = parentList.parentElement) == null ? void 0 : _b.replaceChild(newList, parentList);
1277
+ return;
1278
+ }
1279
+ }
1280
+ const range = sel.getRangeAt(0);
1281
+ if (range.collapsed) {
1282
+ const list2 = doc.createElement(listTag);
1283
+ const li2 = doc.createElement("li");
1284
+ const zw = doc.createTextNode("\u200B");
1285
+ li2.appendChild(zw);
1286
+ list2.appendChild(li2);
1287
+ range.insertNode(list2);
1288
+ const newRange2 = doc.createRange();
1289
+ newRange2.setStart(zw, 1);
1290
+ newRange2.collapse(true);
1291
+ sel.removeAllRanges();
1292
+ sel.addRange(newRange2);
1293
+ return;
1294
+ }
1295
+ const content = range.extractContents();
1296
+ const list = doc.createElement(listTag);
1297
+ const li = doc.createElement("li");
1298
+ li.appendChild(content);
1299
+ list.appendChild(li);
1300
+ range.insertNode(list);
1301
+ sel.removeAllRanges();
1302
+ const newRange = doc.createRange();
1303
+ newRange.selectNodeContents(li);
1304
+ sel.addRange(newRange);
1305
+ }
1158
1306
  function findBlockAncestor(node) {
1159
1307
  let n = node;
1160
1308
  const BLOCKS = [
@@ -1296,6 +1444,33 @@ function attachStandaloneHandlers(doc) {
1296
1444
  },
1297
1445
  true
1298
1446
  );
1447
+ doc.addEventListener(
1448
+ "keydown",
1449
+ (e) => {
1450
+ if (e.key !== "Enter") return;
1451
+ if (e.shiftKey) return;
1452
+ const sel = doc.getSelection();
1453
+ if (!sel || !sel.rangeCount) return;
1454
+ const node = sel.anchorNode;
1455
+ const el = node && node.nodeType === Node.ELEMENT_NODE ? node : node && node.parentElement || null;
1456
+ if (!el) return;
1457
+ const li = el.closest("li");
1458
+ if (!li || !li.parentElement) return;
1459
+ e.preventDefault();
1460
+ const list = li.parentElement;
1461
+ const newLi = doc.createElement("li");
1462
+ const zw = doc.createTextNode("\u200B");
1463
+ newLi.appendChild(zw);
1464
+ if (li.nextSibling) list.insertBefore(newLi, li.nextSibling);
1465
+ else list.appendChild(newLi);
1466
+ const range = doc.createRange();
1467
+ range.setStart(zw, 1);
1468
+ range.collapse(true);
1469
+ sel.removeAllRanges();
1470
+ sel.addRange(range);
1471
+ },
1472
+ true
1473
+ );
1299
1474
  }
1300
1475
 
1301
1476
  // src/core/editor.ts
@@ -1316,7 +1491,7 @@ function initRichEditor(iframe, config) {
1316
1491
  _setRedoStack([]);
1317
1492
  _setCurrentEditable(null);
1318
1493
  if (config == null ? void 0 : config.maxStackSize) {
1319
- import("./state-CZIMHTJ3.mjs").then((m) => m.setMaxStackSize(config.maxStackSize)).catch(() => {
1494
+ import("./state-DA3PGFTN.mjs").then((m) => m.setMaxStackSize(config.maxStackSize)).catch(() => {
1320
1495
  });
1321
1496
  }
1322
1497
  attachStandaloneHandlers(doc);