@37signals/lexxy 0.1.17-beta → 0.1.19-beta

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.
Files changed (2) hide show
  1. package/dist/lexxy.esm.js +42 -13
  2. package/package.json +1 -1
package/dist/lexxy.esm.js CHANGED
@@ -756,6 +756,10 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
756
756
  return new ActionTextAttachmentUploadNode({ ...node }, node.__key)
757
757
  }
758
758
 
759
+ static importJSON(serializedNode) {
760
+ return new ActionTextAttachmentUploadNode({ ...serializedNode })
761
+ }
762
+
759
763
  constructor({ file, uploadUrl, blobUrlTemplate, editor, progress }, key) {
760
764
  super({ contentType: file.type }, key);
761
765
  this.file = file;
@@ -795,6 +799,17 @@ class ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
795
799
  return { element: img }
796
800
  }
797
801
 
802
+ exportJSON() {
803
+ return {
804
+ type: "action_text_attachment_upload",
805
+ version: 1,
806
+ progress: this.progress,
807
+ uploadUrl: this.uploadUrl,
808
+ blobUrlTemplate: this.blobUrlTemplate,
809
+ ...super.exportJSON()
810
+ }
811
+ }
812
+
798
813
  #createDOMForImage() {
799
814
  return createElement("img")
800
815
  }
@@ -1661,22 +1676,24 @@ class Selection {
1661
1676
  const node = this.nodeAfterCursor;
1662
1677
  if (node instanceof DecoratorNode) {
1663
1678
  this.#selectInLexical(node);
1679
+ return true
1664
1680
  } else {
1665
1681
  this.#contents.deleteSelectedNodes();
1666
1682
  }
1667
1683
 
1668
- return true
1684
+ return false
1669
1685
  }
1670
1686
 
1671
1687
  #deletePreviousOrNext() {
1672
1688
  const node = this.nodeBeforeCursor;
1673
1689
  if (node instanceof DecoratorNode) {
1674
1690
  this.#selectInLexical(node);
1691
+ return true
1675
1692
  } else {
1676
1693
  this.#contents.deleteSelectedNodes();
1677
1694
  }
1678
1695
 
1679
- return true
1696
+ return false
1680
1697
  }
1681
1698
 
1682
1699
  #getValidSelectionRange() {
@@ -2288,10 +2305,10 @@ class Contents {
2288
2305
  const selection = $getSelection();
2289
2306
  if (!$isRangeSelection(selection)) return
2290
2307
 
2291
- const topLevelElement = selection.anchor.getNode().getTopLevelElementOrThrow();
2308
+ const topLevelElement = selection.anchor.getNode().getTopLevelElement();
2292
2309
 
2293
2310
  // Check if format is already applied
2294
- if (isFormatAppliedFn(topLevelElement)) {
2311
+ if (topLevelElement && isFormatAppliedFn(topLevelElement)) {
2295
2312
  this.#unwrap(topLevelElement);
2296
2313
  } else {
2297
2314
  this.#insertNodeWrappingAllSelectedNodes(newNodeFn);
@@ -2521,10 +2538,7 @@ class Contents {
2521
2538
  const node = $getNodeByKey(nodeKey);
2522
2539
  if (!node) return
2523
2540
 
2524
- let previousNode = node;
2525
- try {
2526
- previousNode = node.getTopLevelElementOrThrow();
2527
- } catch {}
2541
+ const previousNode = node.getTopLevelElement() || node;
2528
2542
 
2529
2543
  const newNode = options.attachment ? this.#createCustomAttachmentNodeWithHtml(html, options.attachment) : this.#createHtmlNodeWith(html);
2530
2544
  previousNode.insertAfter(newNode);
@@ -2551,16 +2565,21 @@ class Contents {
2551
2565
  if (!$isRangeSelection(selection)) return
2552
2566
 
2553
2567
  const selectedNodes = selection.extract();
2554
- if (selectedNodes.length === 0) return
2555
-
2568
+ if (selectedNodes.length === 0) {
2569
+ return
2570
+ }
2556
2571
  const topLevelElements = new Set();
2557
2572
  selectedNodes.forEach((node) => {
2558
2573
  const topLevel = node.getTopLevelElementOrThrow();
2559
2574
  topLevelElements.add(topLevel);
2560
2575
  });
2561
2576
 
2562
- const elements = this.#removeTrailingEmptyParagraphs(Array.from(topLevelElements));
2563
- if (elements.length === 0) return
2577
+ const elements = this.#withoutTrailingEmptyParagraphs(Array.from(topLevelElements));
2578
+ if (elements.length === 0) {
2579
+ this.#removeStandaloneEmptyParagraph();
2580
+ this.insertAtCursor(newNodeFn());
2581
+ return
2582
+ }
2564
2583
 
2565
2584
  const wrappingNode = newNodeFn();
2566
2585
  elements[0].insertBefore(wrappingNode);
@@ -2572,7 +2591,7 @@ class Contents {
2572
2591
  });
2573
2592
  }
2574
2593
 
2575
- #removeTrailingEmptyParagraphs(elements) {
2594
+ #withoutTrailingEmptyParagraphs(elements) {
2576
2595
  let lastNonEmptyIndex = elements.length - 1;
2577
2596
 
2578
2597
  // Find the last non-empty paragraph
@@ -2596,6 +2615,16 @@ class Contents {
2596
2615
  return children.length === 0 || children.every(child => $isLineBreakNode(child))
2597
2616
  }
2598
2617
 
2618
+ #removeStandaloneEmptyParagraph() {
2619
+ const root = $getRoot();
2620
+ if (root.getChildrenSize() === 1) {
2621
+ const firstChild = root.getFirstChild();
2622
+ if (firstChild && $isParagraphNode(firstChild) && this.#isElementEmpty(firstChild)) {
2623
+ firstChild.remove();
2624
+ }
2625
+ }
2626
+ }
2627
+
2599
2628
  #insertNodeWrappingAllSelectedLines(newNodeFn) {
2600
2629
  this.editor.update(() => {
2601
2630
  const selection = $getSelection();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/lexxy",
3
- "version": "0.1.17-beta",
3
+ "version": "0.1.19-beta",
4
4
  "description": "Lexxy - A modern rich text editor for Rails.",
5
5
  "module": "dist/lexxy.esm.js",
6
6
  "type": "module",