slate-angular 17.0.0 → 17.1.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.
Files changed (57) hide show
  1. package/components/children/children-outlet.component.d.ts +9 -0
  2. package/components/children/children.component.d.ts +1 -6
  3. package/components/editable/editable.component.d.ts +15 -5
  4. package/components/leaf/token.d.ts +4 -0
  5. package/components/leaves/leaves.component.d.ts +1 -14
  6. package/components/string/default-string.component.d.ts +1 -1
  7. package/components/string/string.component.d.ts +8 -0
  8. package/components/text/token.d.ts +5 -0
  9. package/components/text/void-text.component.d.ts +0 -1
  10. package/esm2022/components/block-card/block-card.component.mjs +2 -2
  11. package/esm2022/components/children/children-outlet.component.mjs +22 -0
  12. package/esm2022/components/children/children.component.mjs +5 -33
  13. package/esm2022/components/editable/editable.component.mjs +141 -48
  14. package/esm2022/components/element/default-element.component.mjs +3 -3
  15. package/esm2022/components/element/element.component.mjs +3 -3
  16. package/esm2022/components/leaf/token.mjs +3 -0
  17. package/esm2022/components/leaves/leaves.component.mjs +5 -50
  18. package/esm2022/components/string/default-string.component.mjs +1 -1
  19. package/esm2022/components/string/string.component.mjs +16 -6
  20. package/esm2022/components/text/default-text.component.mjs +3 -3
  21. package/esm2022/components/text/token.mjs +4 -0
  22. package/esm2022/components/text/void-text.component.mjs +3 -7
  23. package/esm2022/module.mjs +7 -22
  24. package/esm2022/plugins/angular-editor.mjs +65 -20
  25. package/esm2022/plugins/with-angular.mjs +5 -4
  26. package/esm2022/public-api.mjs +3 -2
  27. package/esm2022/utils/constants.mjs +2 -0
  28. package/esm2022/utils/index.mjs +2 -1
  29. package/esm2022/utils/throttle.mjs +18 -0
  30. package/esm2022/view/base.mjs +71 -17
  31. package/esm2022/view/container.mjs +2 -82
  32. package/esm2022/view/context-change.mjs +13 -0
  33. package/esm2022/view/context.mjs +1 -1
  34. package/esm2022/view/render/leaves-render.mjs +107 -0
  35. package/esm2022/view/render/list-render.mjs +292 -0
  36. package/esm2022/view/render/utils.mjs +115 -0
  37. package/fesm2022/slate-angular.mjs +1159 -786
  38. package/fesm2022/slate-angular.mjs.map +1 -1
  39. package/module.d.ts +7 -8
  40. package/package.json +7 -7
  41. package/plugins/angular-editor.d.ts +16 -5
  42. package/public-api.d.ts +2 -1
  43. package/utils/constants.d.ts +1 -0
  44. package/utils/index.d.ts +1 -0
  45. package/utils/throttle.d.ts +2 -0
  46. package/view/base.d.ts +17 -4
  47. package/view/container.d.ts +3 -7
  48. package/view/{before-context-change.d.ts → context-change.d.ts} +4 -0
  49. package/view/context.d.ts +7 -2
  50. package/view/render/leaves-render.d.ts +21 -0
  51. package/view/render/list-render.d.ts +35 -0
  52. package/view/render/utils.d.ts +11 -0
  53. package/components/descendant/descendant.component.d.ts +0 -35
  54. package/components/leaf/leaf.component.d.ts +0 -16
  55. package/esm2022/components/descendant/descendant.component.mjs +0 -186
  56. package/esm2022/components/leaf/leaf.component.mjs +0 -38
  57. package/esm2022/view/before-context-change.mjs +0 -7
@@ -1,7 +1,7 @@
1
- import { Editor, Range, Transforms, Path, Element, Text as Text$1, Node } from 'slate';
1
+ import { Editor, Range, Element, Transforms, Path, Text as Text$1, Node } from 'slate';
2
2
  import { isKeyHotkey } from 'is-hotkey';
3
3
  import * as i0 from '@angular/core';
4
- import { TemplateRef, Component, ChangeDetectionStrategy, ViewChild, Directive, Input, HostBinding, ViewChildren, InjectionToken, Inject, forwardRef, ElementRef, NgModule } from '@angular/core';
4
+ import { TemplateRef, Component, ChangeDetectionStrategy, ViewChild, Directive, Input, InjectionToken, ComponentRef, IterableDiffers, HostBinding, inject, ViewContainerRef, forwardRef, ElementRef, Inject, NgModule } from '@angular/core';
5
5
  import { direction } from 'direction';
6
6
  import scrollIntoView from 'scroll-into-view-if-needed';
7
7
  import { Subject } from 'rxjs';
@@ -415,7 +415,7 @@ const AngularEditor = {
415
415
  const [start, end] = Range.edges(selection);
416
416
  const endBlock = Editor.above(editor, {
417
417
  at: end,
418
- match: node => Editor.isBlock(editor, node)
418
+ match: node => Element.isElement(node) && Editor.isBlock(editor, node)
419
419
  });
420
420
  return Editor.isStart(editor, end, endBlock[1]);
421
421
  },
@@ -610,13 +610,17 @@ const AngularEditor = {
610
610
  /**
611
611
  * Find a Slate node from a native DOM `element`.
612
612
  */
613
- toSlateNode(editor, domNode) {
613
+ toSlateNode(editor, domNode, options) {
614
+ const { suppressThrow } = options || { suppressThrow: false };
614
615
  let domEl = isDOMElement(domNode) ? domNode : domNode.parentElement;
615
616
  if (domEl && !domEl.hasAttribute('data-slate-node')) {
616
617
  domEl = domEl.closest(`[data-slate-node]`);
617
618
  }
618
619
  const node = domEl ? ELEMENT_TO_NODE.get(domEl) : null;
619
620
  if (!node) {
621
+ if (suppressThrow) {
622
+ return null;
623
+ }
620
624
  throw new Error(`Cannot resolve a Slate node from DOM node: ${domEl}`);
621
625
  }
622
626
  return node;
@@ -632,12 +636,12 @@ const AngularEditor = {
632
636
  if (x == null || y == null) {
633
637
  throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
634
638
  }
635
- const node = AngularEditor.toSlateNode(editor, event.target);
639
+ const node = AngularEditor.toSlateNode(editor, event.target, { suppressThrow: false });
636
640
  const path = AngularEditor.findPath(editor, node);
637
641
  // If the drop target is inside a void node, move it into either the
638
642
  // next or previous node, depending on which side the `x` and `y`
639
643
  // coordinates are closest to.
640
- if (Editor.isVoid(editor, node)) {
644
+ if (Element.isElement(node) && Editor.isVoid(editor, node)) {
641
645
  const rect = target.getBoundingClientRect();
642
646
  const isPrev = editor.isInline(node) ? x - rect.left < rect.left + rect.width - x : y - rect.top < rect.top + rect.height - y;
643
647
  const edge = Editor.point(editor, path, {
@@ -668,18 +672,25 @@ const AngularEditor = {
668
672
  throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
669
673
  }
670
674
  // Resolve a Slate range from the DOM range.
671
- const range = AngularEditor.toSlateRange(editor, domRange);
675
+ const range = AngularEditor.toSlateRange(editor, domRange, { suppressThrow: false });
672
676
  return range;
673
677
  },
674
- isLeafInEditor(editor, leafNode) {
678
+ isLeafInEditor(editor, leafNode, options) {
679
+ const { suppressThrow } = options;
675
680
  const textNode = leafNode.closest('[data-slate-node="text"]');
676
- const node = AngularEditor.toSlateNode(editor, textNode);
677
- return AngularEditor.isNodeInEditor(editor, node);
681
+ const node = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
682
+ if (node && AngularEditor.isNodeInEditor(editor, node)) {
683
+ return true;
684
+ }
685
+ else {
686
+ return false;
687
+ }
678
688
  },
679
689
  /**
680
690
  * Find a Slate point from a DOM selection's `domNode` and `domOffset`.
681
691
  */
682
- toSlatePoint(editor, domPoint) {
692
+ toSlatePoint(editor, domPoint, options) {
693
+ const { exactMatch, suppressThrow } = options;
683
694
  const [domNode] = domPoint;
684
695
  const [nearestNode, nearestOffset] = normalizeDOMPoint(domPoint);
685
696
  let parentNode = nearestNode.parentNode;
@@ -726,7 +737,7 @@ const AngularEditor = {
726
737
  let domNode = null;
727
738
  // Calculate how far into the text node the `nearestNode` is, so that we
728
739
  // can determine what the offset relative to the text node is.
729
- if (leafNode && AngularEditor.isLeafInEditor(editor, leafNode)) {
740
+ if (leafNode && AngularEditor.isLeafInEditor(editor, leafNode, { suppressThrow: true })) {
730
741
  textNode = leafNode.closest('[data-slate-node="text"]');
731
742
  const window = AngularEditor.getWindow(editor);
732
743
  const range = window.document.createRange();
@@ -751,9 +762,10 @@ const AngularEditor = {
751
762
  else if (voidNode) {
752
763
  // For void nodes, the element with the offset key will be a cousin, not an
753
764
  // ancestor, so find it by going down from the nearest void parent.
754
- leafNode = voidNode.querySelector('[data-slate-leaf]');
755
- parentNode = voidNode.querySelector('[data-slate-length="0"]');
756
- textNode = leafNode.closest('[data-slate-node="text"]');
765
+ const spacer = voidNode.querySelector('[data-slate-spacer="true"]');
766
+ leafNode = spacer.firstElementChild;
767
+ parentNode = leafNode.firstElementChild;
768
+ textNode = spacer;
757
769
  domNode = leafNode;
758
770
  offset = domNode.textContent.length;
759
771
  }
@@ -767,19 +779,26 @@ const AngularEditor = {
767
779
  }
768
780
  }
769
781
  if (!textNode) {
782
+ if (suppressThrow) {
783
+ return null;
784
+ }
770
785
  throw new Error(`Cannot resolve a Slate point from DOM point: ${domPoint}`);
771
786
  }
772
787
  // COMPAT: If someone is clicking from one Slate editor into another,
773
788
  // the select event fires twice, once for the old editor's `element`
774
789
  // first, and then afterwards for the correct `element`. (2017/03/03)
775
- const slateNode = AngularEditor.toSlateNode(editor, textNode);
790
+ const slateNode = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
791
+ if (!slateNode && suppressThrow) {
792
+ return null;
793
+ }
776
794
  const path = AngularEditor.findPath(editor, slateNode);
777
795
  return { path, offset };
778
796
  },
779
797
  /**
780
798
  * Find a Slate range from a DOM range or selection.
781
799
  */
782
- toSlateRange(editor, domRange) {
800
+ toSlateRange(editor, domRange, options) {
801
+ const { exactMatch, suppressThrow } = options || {};
783
802
  const el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer;
784
803
  let anchorNode;
785
804
  let anchorOffset;
@@ -814,9 +833,35 @@ const AngularEditor = {
814
833
  if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
815
834
  throw new Error(`Cannot resolve a Slate range from DOM range: ${domRange}`);
816
835
  }
817
- const anchor = AngularEditor.toSlatePoint(editor, [anchorNode, anchorOffset]);
818
- const focus = isCollapsed ? anchor : AngularEditor.toSlatePoint(editor, [focusNode, focusOffset]);
819
- return { anchor, focus };
836
+ // COMPAT: Triple-clicking a word in chrome will sometimes place the focus
837
+ // inside a `contenteditable="false"` DOM node following the word, which
838
+ // will cause `toSlatePoint` to throw an error. (2023/03/07)
839
+ if ('getAttribute' in focusNode &&
840
+ focusNode.getAttribute('contenteditable') === 'false' &&
841
+ focusNode.getAttribute('data-slate-void') !== 'true') {
842
+ focusNode = anchorNode;
843
+ focusOffset = anchorNode.textContent?.length || 0;
844
+ }
845
+ const anchor = AngularEditor.toSlatePoint(editor, [anchorNode, anchorOffset], { suppressThrow, exactMatch });
846
+ if (!anchor) {
847
+ return null;
848
+ }
849
+ const focus = isCollapsed ? anchor : AngularEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
850
+ if (!focus) {
851
+ return null;
852
+ }
853
+ let range = { anchor: anchor, focus: focus };
854
+ // if the selection is a hanging range that ends in a void
855
+ // and the DOM focus is an Element
856
+ // (meaning that the selection ends before the element)
857
+ // unhang the range to avoid mistakenly including the void
858
+ if (Range.isExpanded(range) &&
859
+ Range.isForward(range) &&
860
+ isDOMElement(focusNode) &&
861
+ Editor.void(editor, { at: range.focus, mode: 'highest' })) {
862
+ range = Editor.unhangRange(editor, range, { voids: true });
863
+ }
864
+ return range;
820
865
  },
821
866
  isLeafBlock(editor, node) {
822
867
  return Element.isElement(node) && !editor.isInline(node) && Editor.hasInlines(editor, node);
@@ -835,7 +880,7 @@ const AngularEditor = {
835
880
  },
836
881
  toSlateCardEntry(editor, node) {
837
882
  const element = node.parentElement.closest('.slate-block-card')?.querySelector('[card-target="card-center"]').firstElementChild;
838
- const slateNode = AngularEditor.toSlateNode(editor, element);
883
+ const slateNode = AngularEditor.toSlateNode(editor, element, { suppressThrow: false });
839
884
  const path = AngularEditor.findPath(editor, slateNode);
840
885
  return [slateNode, path];
841
886
  },
@@ -1008,6 +1053,24 @@ function normalize(document) {
1008
1053
  return document.filter(value => Element.isElement(value) && isValid(value));
1009
1054
  }
1010
1055
 
1056
+ const createThrottleRAF = () => {
1057
+ let timerId = null;
1058
+ const throttleRAF = (fn) => {
1059
+ const scheduleFunc = () => {
1060
+ timerId = requestAnimationFrame(() => {
1061
+ timerId = null;
1062
+ fn();
1063
+ });
1064
+ };
1065
+ if (timerId !== null) {
1066
+ cancelAnimationFrame(timerId);
1067
+ timerId = null;
1068
+ }
1069
+ scheduleFunc();
1070
+ };
1071
+ return throttleRAF;
1072
+ };
1073
+
1011
1074
  /**
1012
1075
  * Utilities for single-line deletion
1013
1076
  */
@@ -1061,7 +1124,7 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1061
1124
  }
1062
1125
  if (editor.selection && Range.isCollapsed(editor.selection)) {
1063
1126
  const parentBlockEntry = Editor.above(editor, {
1064
- match: n => Editor.isBlock(editor, n),
1127
+ match: n => Element.isElement(n) && Editor.isBlock(editor, n),
1065
1128
  at: editor.selection
1066
1129
  });
1067
1130
  if (parentBlockEntry) {
@@ -1211,7 +1274,7 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1211
1274
  }
1212
1275
  else {
1213
1276
  const node = Node.parent(editor, selection.anchor.path);
1214
- if (Editor.isVoid(editor, node)) {
1277
+ if (Element.isElement(node) && Editor.isVoid(editor, node)) {
1215
1278
  Transforms.delete(editor);
1216
1279
  }
1217
1280
  }
@@ -1254,6 +1317,7 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1254
1317
  e.onKeydown = () => { };
1255
1318
  e.onClick = () => { };
1256
1319
  e.isBlockCard = element => false;
1320
+ e.isExpanded = element => true;
1257
1321
  e.onError = (errorData) => {
1258
1322
  if (errorData.nativeError) {
1259
1323
  console.error(errorData.nativeError);
@@ -1663,6 +1727,64 @@ function restoreDom(editor, execute) {
1663
1727
  }, 0);
1664
1728
  }
1665
1729
 
1730
+ /**
1731
+ * @deprecated
1732
+ * the special container for angular template
1733
+ * Add the rootNodes of each child component to the parentElement
1734
+ * Remove useless DOM elements, eg: comment...
1735
+ */
1736
+ class ViewContainer {
1737
+ constructor(elementRef, differs) {
1738
+ this.elementRef = elementRef;
1739
+ this.differs = differs;
1740
+ }
1741
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainer, deps: [{ token: i0.ElementRef }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Directive }); }
1742
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: ViewContainer, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
1743
+ }
1744
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainer, decorators: [{
1745
+ type: Directive
1746
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.IterableDiffers }], propDecorators: { viewContext: [{
1747
+ type: Input
1748
+ }] } });
1749
+
1750
+ class SlateChildren extends ViewContainer {
1751
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildren, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1752
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateChildren, isStandalone: true, selector: "slate-children", inputs: { children: "children", context: "context", viewContext: "viewContext" }, usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1753
+ }
1754
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildren, decorators: [{
1755
+ type: Component,
1756
+ args: [{
1757
+ selector: 'slate-children',
1758
+ template: ``,
1759
+ changeDetection: ChangeDetectionStrategy.OnPush,
1760
+ standalone: true
1761
+ }]
1762
+ }], propDecorators: { children: [{
1763
+ type: Input
1764
+ }], context: [{
1765
+ type: Input
1766
+ }], viewContext: [{
1767
+ type: Input
1768
+ }] } });
1769
+
1770
+ const SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN = new InjectionToken('slate-default-element-token');
1771
+
1772
+ const SLATE_DEFAULT_TEXT_COMPONENT_TOKEN = new InjectionToken('slate-default-text-token');
1773
+ const SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN = new InjectionToken('slate-default-void-text-token');
1774
+
1775
+ function hasBeforeContextChange(value) {
1776
+ if (value.beforeContextChange) {
1777
+ return true;
1778
+ }
1779
+ return false;
1780
+ }
1781
+ function hasAfterContextChange(value) {
1782
+ if (value.afterContextChange) {
1783
+ return true;
1784
+ }
1785
+ return false;
1786
+ }
1787
+
1666
1788
  class SlateBlockCard {
1667
1789
  get nativeElement() {
1668
1790
  return this.elementRef.nativeElement;
@@ -1674,7 +1796,6 @@ class SlateBlockCard {
1674
1796
  this.elementRef = elementRef;
1675
1797
  }
1676
1798
  ngOnInit() {
1677
- this.append();
1678
1799
  this.nativeElement.classList.add(`slate-block-card`);
1679
1800
  }
1680
1801
  append() {
@@ -1682,6 +1803,7 @@ class SlateBlockCard {
1682
1803
  }
1683
1804
  initializeCenter(rootNodes) {
1684
1805
  this.centerRootNodes = rootNodes;
1806
+ this.append();
1685
1807
  }
1686
1808
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateBlockCard, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1687
1809
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateBlockCard, isStandalone: true, selector: "slate-block-card, [slateBlockCard]", viewQueries: [{ propertyName: "centerContianer", first: true, predicate: ["centerContianer"], descendants: true, static: true }], ngImport: i0, template: "<span card-target=\"card-left\" class=\"card-left\">{{ '\\uFEFF' }}</span>\n<div card-target=\"card-center\" #centerContianer></div>\n<span card-target=\"card-right\" class=\"card-right\">{{ '\\uFEFF' }}</span>\n" }); }
@@ -1694,141 +1816,557 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
1694
1816
  args: ['centerContianer', { static: true }]
1695
1817
  }] } });
1696
1818
 
1697
- /**
1698
- * Dynamically create/update components or templates
1699
- * Provide rootNodes for the view container
1700
- * If the dynamically created component uses onpush mode, then it must call markForCheck when setting the context
1701
- */
1702
- class ViewContainerItem {
1703
- get rootNodes() {
1704
- return this.getRootNodes();
1819
+ function createEmbeddedViewOrComponent(viewType, context, viewContext, viewContainerRef) {
1820
+ if (isTemplateRef(viewType)) {
1821
+ const embeddedViewContext = {
1822
+ context,
1823
+ viewContext
1824
+ };
1825
+ const embeddedViewRef = viewContainerRef.createEmbeddedView(viewType, embeddedViewContext);
1826
+ embeddedViewRef.detectChanges();
1827
+ return embeddedViewRef;
1705
1828
  }
1706
- getRootNodes() {
1707
- if (this.embeddedViewRef) {
1708
- return this.embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode));
1829
+ if (isComponentType(viewType)) {
1830
+ const componentRef = viewContainerRef.createComponent(viewType, {
1831
+ injector: viewContainerRef.injector
1832
+ });
1833
+ componentRef.instance.viewContext = viewContext;
1834
+ componentRef.instance.context = context;
1835
+ componentRef.changeDetectorRef.detectChanges();
1836
+ return componentRef;
1837
+ }
1838
+ }
1839
+ function executeAfterViewInit(view) {
1840
+ if (view instanceof ComponentRef && view.instance.afterViewInit) {
1841
+ view.instance.afterViewInit();
1842
+ }
1843
+ }
1844
+ function updateContext(view, newContext, viewContext) {
1845
+ if (view instanceof ComponentRef) {
1846
+ view.instance.context = newContext;
1847
+ }
1848
+ else {
1849
+ const embeddedViewContext = {
1850
+ context: newContext,
1851
+ viewContext
1852
+ };
1853
+ view.context = embeddedViewContext;
1854
+ view.detectChanges();
1855
+ }
1856
+ }
1857
+ function mount(views, blockCards, outletParent, outletElement) {
1858
+ if (views.length > 0) {
1859
+ const fragment = document.createDocumentFragment();
1860
+ views.forEach((view, index) => {
1861
+ const blockCard = blockCards ? blockCards[index] : undefined;
1862
+ fragment.append(...getRootNodes(view, blockCard));
1863
+ });
1864
+ if (outletElement) {
1865
+ outletElement.parentElement.insertBefore(fragment, outletElement);
1866
+ outletElement.remove();
1709
1867
  }
1710
- if (this.componentRef) {
1711
- return [this.componentRef.instance.nativeElement];
1868
+ else {
1869
+ outletParent.prepend(fragment);
1712
1870
  }
1713
- return [];
1714
1871
  }
1715
- constructor(viewContainerRef) {
1716
- this.viewContainerRef = viewContainerRef;
1717
- this.initialized = false;
1872
+ }
1873
+ function getRootNodes(ref, blockCard) {
1874
+ if (blockCard) {
1875
+ return [blockCard.instance.nativeElement];
1876
+ }
1877
+ if (ref instanceof ComponentRef) {
1878
+ ref.hostView.rootNodes.forEach(ele => {
1879
+ if (!(ele instanceof HTMLElement)) {
1880
+ ele.remove();
1881
+ }
1882
+ });
1883
+ return [ref.instance.nativeElement];
1718
1884
  }
1719
- destroyView() {
1720
- if (this.embeddedViewRef) {
1721
- this.embeddedViewRef.destroy();
1722
- this.embeddedViewRef = null;
1885
+ else {
1886
+ const result = [];
1887
+ ref.rootNodes.forEach(rootNode => {
1888
+ const isHTMLElement = rootNode instanceof HTMLElement;
1889
+ const isSlateNodeOfLeaf = isHTMLElement && (rootNode.hasAttribute('data-slate-node') || rootNode.hasAttribute('data-slate-leaf'));
1890
+ if (isSlateNodeOfLeaf && result.every(item => !item.contains(rootNode))) {
1891
+ result.push(rootNode);
1892
+ }
1893
+ if (!isHTMLElement) {
1894
+ rootNode.remove();
1895
+ }
1896
+ });
1897
+ return result;
1898
+ }
1899
+ }
1900
+ function mountOnItemChange(index, item, views, blockCards, outletParent, firstRootNode, viewContext) {
1901
+ const view = views[index];
1902
+ let rootNodes = getRootNodes(view);
1903
+ if (blockCards) {
1904
+ const isBlockCard = viewContext.editor.isBlockCard(item);
1905
+ if (isBlockCard) {
1906
+ const blockCard = blockCards[index];
1907
+ rootNodes = [blockCard.instance.nativeElement];
1908
+ }
1909
+ }
1910
+ if (index === 0) {
1911
+ if (firstRootNode) {
1912
+ rootNodes.forEach(rootNode => {
1913
+ firstRootNode.insertAdjacentElement('beforebegin', rootNode);
1914
+ });
1723
1915
  }
1724
- if (this.componentRef) {
1725
- this.componentRef.destroy();
1726
- this.componentRef = null;
1916
+ else {
1917
+ outletParent.prepend(...rootNodes);
1727
1918
  }
1728
1919
  }
1729
- createView() {
1920
+ else {
1921
+ const previousView = views[index - 1];
1922
+ const blockCard = blockCards ? blockCards[index - 1] : null;
1923
+ const previousRootNodes = getRootNodes(previousView, blockCard);
1924
+ let previousRootNode = previousRootNodes[previousRootNodes.length - 1];
1925
+ rootNodes.forEach(rootNode => {
1926
+ previousRootNode.insertAdjacentElement('afterend', rootNode);
1927
+ previousRootNode = rootNode;
1928
+ });
1929
+ }
1930
+ }
1931
+
1932
+ class ListRender {
1933
+ constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
1934
+ this.viewContext = viewContext;
1935
+ this.viewContainerRef = viewContainerRef;
1936
+ this.getOutletParent = getOutletParent;
1937
+ this.getOutletElement = getOutletElement;
1938
+ this.views = [];
1939
+ this.addedViews = [];
1940
+ this.blockCards = [];
1941
+ this.contexts = [];
1942
+ this.viewTypes = [];
1943
+ this.differ = null;
1944
+ this.initialized = false;
1945
+ }
1946
+ initialize(children, parent, childrenContext) {
1730
1947
  this.initialized = true;
1731
- this.viewType = this.getViewType();
1732
- const context = this.getContext();
1733
- if (isTemplateRef(this.viewType)) {
1734
- this.embeddedViewContext = {
1735
- context,
1736
- viewContext: this.viewContext
1737
- };
1738
- const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
1739
- this.embeddedViewRef = embeddedViewRef;
1740
- }
1741
- if (isComponentType(this.viewType)) {
1742
- const componentRef = this.viewContainerRef.createComponent(this.viewType);
1743
- componentRef.instance.viewContext = this.viewContext;
1744
- componentRef.instance.context = context;
1745
- this.componentRef = componentRef;
1948
+ this.children = children;
1949
+ const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
1950
+ children.forEach((descendant, index) => {
1951
+ NODE_TO_INDEX.set(descendant, index);
1952
+ NODE_TO_PARENT.set(descendant, parent);
1953
+ const context = getContext$1(index, descendant, parentPath, childrenContext, this.viewContext);
1954
+ const viewType = getViewType$1(descendant, parent, this.viewContext);
1955
+ const view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1956
+ const blockCard = createBlockCard(descendant, view, this.viewContainerRef, this.viewContext);
1957
+ this.views.push(view);
1958
+ this.addedViews.push(view);
1959
+ this.contexts.push(context);
1960
+ this.viewTypes.push(viewType);
1961
+ this.blockCards.push(blockCard);
1962
+ });
1963
+ mount(this.views, this.blockCards, this.getOutletParent(), this.getOutletElement());
1964
+ const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
1965
+ this.differ = newDiffers.find(children).create(trackBy$1(this.viewContext));
1966
+ this.differ.diff(children);
1967
+ if (parent === this.viewContext.editor) {
1968
+ this.afterViewInit();
1746
1969
  }
1747
1970
  }
1748
- updateView() {
1749
- const viewType = this.getViewType();
1750
- const context = this.getContext();
1751
- if (this.viewType === viewType) {
1752
- if (this.componentRef) {
1753
- if (this.memoizedContext(this.componentRef.instance.context, context)) {
1754
- return;
1971
+ update(children, parent, childrenContext) {
1972
+ if (!this.initialized || this.children.length === 0) {
1973
+ this.initialize(children, parent, childrenContext);
1974
+ return;
1975
+ }
1976
+ if (!this.differ) {
1977
+ throw new Error('Exception: Can not find differ ');
1978
+ }
1979
+ const outletParent = this.getOutletParent();
1980
+ const diffResult = this.differ.diff(children);
1981
+ const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
1982
+ if (diffResult) {
1983
+ let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
1984
+ const newContexts = [];
1985
+ const newViewTypes = [];
1986
+ const newViews = [];
1987
+ const newBlockCards = [];
1988
+ diffResult.forEachItem(record => {
1989
+ NODE_TO_INDEX.set(record.item, record.currentIndex);
1990
+ NODE_TO_PARENT.set(record.item, parent);
1991
+ let context = getContext$1(record.currentIndex, record.item, parentPath, childrenContext, this.viewContext);
1992
+ const viewType = getViewType$1(record.item, parent, this.viewContext);
1993
+ newViewTypes.push(viewType);
1994
+ let view;
1995
+ let blockCard;
1996
+ if (record.previousIndex === null) {
1997
+ view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1998
+ blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
1999
+ newContexts.push(context);
2000
+ newViews.push(view);
2001
+ this.addedViews.push(view);
2002
+ newBlockCards.push(blockCard);
2003
+ mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
1755
2004
  }
1756
- this.componentRef.instance.context = context;
1757
- }
1758
- if (this.embeddedViewRef) {
1759
- if (this.memoizedContext(this.embeddedViewContext.context, context)) {
1760
- return;
2005
+ else {
2006
+ const previousView = this.views[record.previousIndex];
2007
+ const previousViewType = this.viewTypes[record.previousIndex];
2008
+ const previousContext = this.contexts[record.previousIndex];
2009
+ const previousBlockCard = this.blockCards[record.previousIndex];
2010
+ if (previousViewType !== viewType) {
2011
+ view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
2012
+ this.addedViews.push(view);
2013
+ blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
2014
+ const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
2015
+ const newRootNodes = getRootNodes(view, blockCard);
2016
+ firstRootNode.replaceWith(...newRootNodes);
2017
+ previousView.destroy();
2018
+ previousBlockCard?.destroy();
2019
+ }
2020
+ else {
2021
+ view = previousView;
2022
+ blockCard = previousBlockCard;
2023
+ if (memoizedContext(this.viewContext, record.item, previousContext, context)) {
2024
+ context = previousContext;
2025
+ }
2026
+ else {
2027
+ updateContext(previousView, context, this.viewContext);
2028
+ }
2029
+ }
2030
+ newContexts.push(context);
2031
+ newViews.push(view);
2032
+ newBlockCards.push(blockCard);
1761
2033
  }
1762
- this.embeddedViewContext.context = context;
2034
+ });
2035
+ diffResult.forEachOperation(record => {
2036
+ // removed
2037
+ if (record.currentIndex === null) {
2038
+ const view = this.views[record.previousIndex];
2039
+ const blockCard = this.blockCards[record.previousIndex];
2040
+ view.destroy();
2041
+ blockCard?.destroy();
2042
+ }
2043
+ // moved
2044
+ if (record.previousIndex !== null && record.currentIndex !== null) {
2045
+ mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
2046
+ // Solve the block-card DOMElement loss when moving nodes
2047
+ newBlockCards[record.currentIndex]?.instance.append();
2048
+ }
2049
+ });
2050
+ this.viewTypes = newViewTypes;
2051
+ this.views = newViews;
2052
+ this.contexts = newContexts;
2053
+ this.children = children;
2054
+ this.blockCards = newBlockCards;
2055
+ if (parent === this.viewContext.editor) {
2056
+ this.afterViewInit();
1763
2057
  }
1764
2058
  }
1765
2059
  else {
1766
- this.viewType = viewType;
1767
- const firstRootNode = this.rootNodes[0];
1768
- if (isTemplateRef(this.viewType)) {
1769
- this.embeddedViewContext = {
1770
- context,
1771
- viewContext: this.viewContext
1772
- };
1773
- const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
1774
- firstRootNode.replaceWith(...embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode)));
1775
- this.destroyView();
1776
- this.embeddedViewRef = embeddedViewRef;
2060
+ const newContexts = [];
2061
+ this.children.forEach((child, index) => {
2062
+ NODE_TO_INDEX.set(child, index);
2063
+ NODE_TO_PARENT.set(child, parent);
2064
+ let context = getContext$1(index, child, parentPath, childrenContext, this.viewContext);
2065
+ const previousContext = this.contexts[index];
2066
+ if (memoizedContext(this.viewContext, child, previousContext, context)) {
2067
+ context = previousContext;
2068
+ }
2069
+ else {
2070
+ updateContext(this.views[index], context, this.viewContext);
2071
+ }
2072
+ newContexts.push(context);
2073
+ });
2074
+ this.contexts = newContexts;
2075
+ }
2076
+ }
2077
+ afterViewInit() {
2078
+ this.addedViews.forEach(view => {
2079
+ executeAfterViewInit(view);
2080
+ });
2081
+ this.addedViews = [];
2082
+ }
2083
+ destroy() {
2084
+ this.children.forEach((element, index) => {
2085
+ if (this.views[index]) {
2086
+ this.views[index].destroy();
1777
2087
  }
1778
- if (isComponentType(this.viewType)) {
1779
- const componentRef = this.viewContainerRef.createComponent(this.viewType);
1780
- componentRef.instance.viewContext = this.viewContext;
1781
- componentRef.instance.context = context;
1782
- firstRootNode.replaceWith(componentRef.instance.nativeElement);
1783
- this.destroyView();
1784
- this.componentRef = componentRef;
2088
+ if (this.blockCards[index]) {
2089
+ this.blockCards[index].destroy();
1785
2090
  }
1786
- }
2091
+ });
2092
+ this.views = [];
2093
+ this.blockCards = [];
2094
+ this.contexts = [];
2095
+ this.viewTypes = [];
2096
+ this.initialized = false;
2097
+ this.differ = null;
1787
2098
  }
1788
- appendBlockCardElement() {
1789
- if (this.blockCardComponentRef) {
1790
- this.blockCardComponentRef.instance.append();
2099
+ }
2100
+ function getContext$1(index, item, parentPath, childrenContext, viewContext) {
2101
+ if (Element.isElement(item)) {
2102
+ const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
2103
+ const key = AngularEditor.findKey(viewContext.editor, item);
2104
+ const isInline = viewContext.editor.isInline(item);
2105
+ const isVoid = viewContext.editor.isVoid(item);
2106
+ const elementContext = {
2107
+ element: item,
2108
+ ...computedContext,
2109
+ attributes: {
2110
+ 'data-slate-node': 'element',
2111
+ 'data-slate-key': key.id
2112
+ },
2113
+ decorate: childrenContext.decorate,
2114
+ readonly: childrenContext.readonly
2115
+ };
2116
+ if (isInline) {
2117
+ elementContext.attributes['data-slate-inline'] = true;
2118
+ }
2119
+ if (isVoid) {
2120
+ elementContext.attributes['data-slate-void'] = true;
2121
+ elementContext.contentEditable = false;
1791
2122
  }
2123
+ return elementContext;
1792
2124
  }
1793
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainerItem, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1794
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: ViewContainerItem, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
1795
- }
1796
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainerItem, decorators: [{
1797
- type: Directive
1798
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { viewContext: [{
1799
- type: Input
1800
- }] } });
1801
-
1802
- function hasBeforeContextChange(value) {
1803
- if (value.beforeContextChange) {
1804
- return true;
2125
+ else {
2126
+ const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
2127
+ const isLeafBlock = AngularEditor.isLeafBlock(viewContext.editor, childrenContext.parent);
2128
+ const textContext = {
2129
+ decorations: computedContext.decorations,
2130
+ isLast: isLeafBlock && index === childrenContext.parent.children.length - 1,
2131
+ parent: childrenContext.parent,
2132
+ text: item
2133
+ };
2134
+ return textContext;
1805
2135
  }
1806
- return false;
1807
2136
  }
1808
-
1809
- /**
1810
- * base class for custom element component or text component
1811
- */
1812
- class BaseComponent {
1813
- set context(value) {
1814
- if (hasBeforeContextChange(this)) {
1815
- this.beforeContextChange(value);
2137
+ function getCommonContext(index, item, parentPath, viewContext, childrenContext) {
2138
+ const p = parentPath.concat(index);
2139
+ try {
2140
+ const ds = childrenContext.decorate([item, p]);
2141
+ // [list-render] performance optimization: reduce the number of calls to the `Editor.range(viewContext.editor, p)` method
2142
+ if (childrenContext.selection || childrenContext.decorations.length > 0) {
2143
+ const range = Editor.range(viewContext.editor, p);
2144
+ const sel = childrenContext.selection && Range.intersection(range, childrenContext.selection);
2145
+ for (const dec of childrenContext.decorations) {
2146
+ const d = Range.intersection(dec, range);
2147
+ if (d) {
2148
+ ds.push(d);
2149
+ }
2150
+ }
2151
+ return { selection: sel, decorations: ds };
2152
+ }
2153
+ else {
2154
+ return { selection: null, decorations: ds };
1816
2155
  }
1817
- this._context = value;
1818
- this.onContextChange();
1819
2156
  }
1820
- get context() {
1821
- return this._context;
2157
+ catch (error) {
2158
+ viewContext.editor.onError({
2159
+ code: SlateErrorCode.GetStartPointError,
2160
+ nativeError: error
2161
+ });
2162
+ return { selection: null, decorations: [] };
1822
2163
  }
1823
- get editor() {
1824
- return this.viewContext && this.viewContext.editor;
2164
+ }
2165
+ function getViewType$1(item, parent, viewContext) {
2166
+ if (Element.isElement(item)) {
2167
+ return (viewContext.renderElement && viewContext.renderElement(item)) || viewContext.defaultElement;
1825
2168
  }
1826
- get nativeElement() {
1827
- return this.elementRef.nativeElement;
2169
+ else {
2170
+ const isVoid = viewContext.editor.isVoid(parent);
2171
+ return isVoid ? viewContext.defaultVoidText : (viewContext.renderText && viewContext.renderText(item)) || viewContext.defaultText;
1828
2172
  }
1829
- constructor(elementRef, cdr) {
1830
- this.elementRef = elementRef;
2173
+ }
2174
+ function createBlockCard(item, view, viewContainerRef, viewContext) {
2175
+ const isBlockCard = viewContext.editor.isBlockCard(item);
2176
+ if (isBlockCard) {
2177
+ const rootNodes = getRootNodes(view);
2178
+ const blockCardComponentRef = viewContainerRef.createComponent(SlateBlockCard, {
2179
+ injector: viewContainerRef.injector
2180
+ });
2181
+ blockCardComponentRef.instance.initializeCenter(rootNodes);
2182
+ blockCardComponentRef.changeDetectorRef.detectChanges();
2183
+ return blockCardComponentRef;
2184
+ }
2185
+ else {
2186
+ return null;
2187
+ }
2188
+ }
2189
+ function trackBy$1(viewContext) {
2190
+ return (index, node) => {
2191
+ return viewContext.trackBy(node) || AngularEditor.findKey(viewContext.editor, node);
2192
+ };
2193
+ }
2194
+ function memoizedContext(viewContext, descendant, prev, next) {
2195
+ if (Element.isElement(descendant)) {
2196
+ return memoizedElementContext(viewContext, prev, next);
2197
+ }
2198
+ else {
2199
+ return memoizedTextContext(prev, next);
2200
+ }
2201
+ }
2202
+ function memoizedElementContext(viewContext, prev, next) {
2203
+ return (prev.element === next.element &&
2204
+ (!viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
2205
+ prev.readonly === next.readonly &&
2206
+ isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
2207
+ (prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
2208
+ }
2209
+ function memoizedTextContext(prev, next) {
2210
+ return (next.parent === prev.parent &&
2211
+ next.isLast === prev.isLast &&
2212
+ next.text === prev.text &&
2213
+ isDecoratorRangeListEqual(next.decorations, prev.decorations));
2214
+ }
2215
+
2216
+ class LeavesRender {
2217
+ constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
2218
+ this.viewContext = viewContext;
2219
+ this.viewContainerRef = viewContainerRef;
2220
+ this.getOutletParent = getOutletParent;
2221
+ this.getOutletElement = getOutletElement;
2222
+ this.views = [];
2223
+ this.contexts = [];
2224
+ this.viewTypes = [];
2225
+ }
2226
+ initialize(context) {
2227
+ const { leaves, contexts } = this.getLeaves(context);
2228
+ this.leaves = leaves;
2229
+ this.contexts = contexts;
2230
+ this.leaves.forEach((leaf, index) => {
2231
+ const context = getContext(index, this.contexts);
2232
+ const viewType = getViewType(context, this.viewContext);
2233
+ const view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
2234
+ this.views.push(view);
2235
+ this.contexts.push(context);
2236
+ this.viewTypes.push(viewType);
2237
+ });
2238
+ mount(this.views, null, this.getOutletParent(), this.getOutletElement());
2239
+ const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
2240
+ this.differ = newDiffers.find(this.leaves).create(trackBy(this.viewContext));
2241
+ this.differ.diff(this.leaves);
2242
+ }
2243
+ update(context) {
2244
+ const { leaves, contexts } = this.getLeaves(context);
2245
+ const outletParent = this.getOutletParent();
2246
+ const diffResult = this.differ.diff(leaves);
2247
+ if (diffResult) {
2248
+ let firstRootNode = getRootNodes(this.views[0])[0];
2249
+ const newContexts = [];
2250
+ const newViewTypes = [];
2251
+ const newViews = [];
2252
+ diffResult.forEachItem(record => {
2253
+ let context = getContext(record.currentIndex, contexts);
2254
+ const viewType = getViewType(context, this.viewContext);
2255
+ newViewTypes.push(viewType);
2256
+ let view;
2257
+ if (record.previousIndex === null) {
2258
+ view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
2259
+ newContexts.push(context);
2260
+ newViews.push(view);
2261
+ mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
2262
+ }
2263
+ else {
2264
+ const previousView = this.views[record.previousIndex];
2265
+ const previousViewType = this.viewTypes[record.previousIndex];
2266
+ if (previousViewType !== viewType) {
2267
+ view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
2268
+ const firstRootNode = getRootNodes(previousView, null)[0];
2269
+ const newRootNodes = getRootNodes(view, null);
2270
+ firstRootNode.replaceWith(...newRootNodes);
2271
+ previousView.destroy();
2272
+ }
2273
+ else {
2274
+ view = previousView;
2275
+ updateContext(previousView, context, this.viewContext);
2276
+ }
2277
+ newContexts.push(context);
2278
+ newViews.push(view);
2279
+ }
2280
+ });
2281
+ diffResult.forEachRemovedItem(record => {
2282
+ const view = this.views[record.previousIndex];
2283
+ view.destroy();
2284
+ });
2285
+ diffResult.forEachMovedItem(record => {
2286
+ mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
2287
+ });
2288
+ this.viewTypes = newViewTypes;
2289
+ this.views = newViews;
2290
+ this.contexts = newContexts;
2291
+ this.leaves = leaves;
2292
+ }
2293
+ }
2294
+ getLeaves(context) {
2295
+ const leaves = Text$1.decorations(context.text, context.decorations);
2296
+ const contexts = leaves.map((leaf, index) => {
2297
+ return {
2298
+ leaf,
2299
+ text: context.text,
2300
+ parent: context.parent,
2301
+ index,
2302
+ isLast: context.isLast && index === leaves.length - 1
2303
+ };
2304
+ });
2305
+ return { leaves, contexts };
2306
+ }
2307
+ }
2308
+ function getContext(index, leafContexts) {
2309
+ return leafContexts[index];
2310
+ }
2311
+ function getViewType(leafContext, viewContext) {
2312
+ return (viewContext.renderLeaf && viewContext.renderLeaf(leafContext.leaf)) || viewContext.defaultLeaf;
2313
+ }
2314
+ function trackBy(viewContext) {
2315
+ return (index, node) => {
2316
+ return index;
2317
+ };
2318
+ }
2319
+
2320
+ class SlateChildrenOutlet {
2321
+ constructor(elementRef) {
2322
+ this.elementRef = elementRef;
2323
+ }
2324
+ getNativeElement() {
2325
+ return this.elementRef.nativeElement;
2326
+ }
2327
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildrenOutlet, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
2328
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateChildrenOutlet, isStandalone: true, selector: "slate-children-outlet", ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2329
+ }
2330
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildrenOutlet, decorators: [{
2331
+ type: Component,
2332
+ args: [{
2333
+ selector: 'slate-children-outlet',
2334
+ template: ``,
2335
+ changeDetection: ChangeDetectionStrategy.OnPush,
2336
+ standalone: true
2337
+ }]
2338
+ }], ctorParameters: () => [{ type: i0.ElementRef }] });
2339
+
2340
+ /**
2341
+ * base class for custom element component or text component
2342
+ */
2343
+ class BaseComponent {
2344
+ set context(value) {
2345
+ if (hasBeforeContextChange(this)) {
2346
+ this.beforeContextChange(value);
2347
+ }
2348
+ this._context = value;
2349
+ this.onContextChange();
2350
+ if (this.initialized) {
2351
+ this.cdr.detectChanges();
2352
+ }
2353
+ if (hasAfterContextChange(this)) {
2354
+ this.afterContextChange();
2355
+ }
2356
+ }
2357
+ get context() {
2358
+ return this._context;
2359
+ }
2360
+ get editor() {
2361
+ return this.viewContext && this.viewContext.editor;
2362
+ }
2363
+ get nativeElement() {
2364
+ return this.elementRef.nativeElement;
2365
+ }
2366
+ constructor(elementRef, cdr) {
2367
+ this.elementRef = elementRef;
1831
2368
  this.cdr = cdr;
2369
+ this.initialized = false;
1832
2370
  }
1833
2371
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: BaseComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1834
2372
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: BaseComponent, inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0 }); }
@@ -1846,7 +2384,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
1846
2384
  class BaseLeafComponent extends BaseComponent {
1847
2385
  constructor() {
1848
2386
  super(...arguments);
1849
- this.initialized = false;
1850
2387
  this.isSlateLeaf = true;
1851
2388
  }
1852
2389
  get text() {
@@ -1862,7 +2399,6 @@ class BaseLeafComponent extends BaseComponent {
1862
2399
  if (!this.initialized) {
1863
2400
  return;
1864
2401
  }
1865
- this.cdr.markForCheck();
1866
2402
  }
1867
2403
  renderPlaceholder() {
1868
2404
  // issue-1: IME input was interrupted
@@ -1914,7 +2450,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
1914
2450
  class BaseElementComponent extends BaseComponent {
1915
2451
  constructor() {
1916
2452
  super(...arguments);
1917
- this.initialized = false;
2453
+ this.viewContainerRef = inject(ViewContainerRef);
2454
+ this.getOutletParent = () => {
2455
+ return this.elementRef.nativeElement;
2456
+ };
2457
+ this.getOutletElement = () => {
2458
+ if (this.childrenOutletInstance) {
2459
+ return this.childrenOutletInstance.getNativeElement();
2460
+ }
2461
+ return null;
2462
+ };
1918
2463
  }
1919
2464
  get element() {
1920
2465
  return this._context && this._context.element;
@@ -1938,11 +2483,20 @@ class BaseElementComponent extends BaseComponent {
1938
2483
  return this._context && this._context.readonly;
1939
2484
  }
1940
2485
  ngOnInit() {
1941
- this.updateWeakMap();
1942
2486
  for (const key in this._context.attributes) {
1943
2487
  this.nativeElement.setAttribute(key, this._context.attributes[key]);
1944
2488
  }
1945
2489
  this.initialized = true;
2490
+ this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
2491
+ if (this.editor.isExpanded(this.element)) {
2492
+ this.listRender.initialize(this.children, this.element, this.childrenContext);
2493
+ }
2494
+ }
2495
+ afterViewInit() {
2496
+ if (this._context.contentEditable !== undefined) {
2497
+ this.nativeElement.setAttribute('contenteditable', this._context.contentEditable + '');
2498
+ }
2499
+ this.listRender.afterViewInit();
1946
2500
  }
1947
2501
  updateWeakMap() {
1948
2502
  NODE_TO_ELEMENT.set(this.element, this.nativeElement);
@@ -1953,17 +2507,28 @@ class BaseElementComponent extends BaseComponent {
1953
2507
  if (NODE_TO_ELEMENT.get(this.element) === this.nativeElement) {
1954
2508
  NODE_TO_ELEMENT.delete(this.element);
1955
2509
  }
2510
+ ELEMENT_TO_NODE.delete(this.nativeElement);
1956
2511
  if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
1957
2512
  ELEMENT_TO_COMPONENT.delete(this.element);
1958
2513
  }
1959
2514
  }
1960
2515
  onContextChange() {
1961
2516
  this.childrenContext = this.getChildrenContext();
2517
+ this.updateWeakMap();
1962
2518
  if (!this.initialized) {
1963
2519
  return;
1964
2520
  }
1965
- this.cdr.markForCheck();
1966
- this.updateWeakMap();
2521
+ this.updateChildrenView();
2522
+ }
2523
+ updateChildrenView() {
2524
+ if (this.editor.isExpanded(this.element)) {
2525
+ this.listRender.update(this.children, this.element, this.childrenContext);
2526
+ }
2527
+ else {
2528
+ if (this.listRender.initialized) {
2529
+ this.listRender.destroy();
2530
+ }
2531
+ }
1967
2532
  }
1968
2533
  getChildrenContext() {
1969
2534
  return {
@@ -1975,25 +2540,38 @@ class BaseElementComponent extends BaseComponent {
1975
2540
  };
1976
2541
  }
1977
2542
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: BaseElementComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1978
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: BaseElementComponent, usesInheritance: true, ngImport: i0 }); }
2543
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: BaseElementComponent, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
1979
2544
  }
1980
2545
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: BaseElementComponent, decorators: [{
1981
2546
  type: Directive
1982
- }] });
2547
+ }], propDecorators: { childrenOutletInstance: [{
2548
+ type: ViewChild,
2549
+ args: [SlateChildrenOutlet, { static: true }]
2550
+ }] } });
1983
2551
  /**
1984
2552
  * base class for custom text component
1985
2553
  */
1986
2554
  class BaseTextComponent extends BaseComponent {
1987
2555
  constructor() {
1988
2556
  super(...arguments);
1989
- this.initialized = false;
2557
+ this.viewContainerRef = inject(ViewContainerRef);
2558
+ this.getOutletParent = () => {
2559
+ return this.elementRef.nativeElement;
2560
+ };
2561
+ this.getOutletElement = () => {
2562
+ if (this.childrenOutletInstance) {
2563
+ return this.childrenOutletInstance.getNativeElement();
2564
+ }
2565
+ return null;
2566
+ };
1990
2567
  }
1991
2568
  get text() {
1992
2569
  return this._context && this._context.text;
1993
2570
  }
1994
2571
  ngOnInit() {
1995
- this.updateWeakMap();
1996
2572
  this.initialized = true;
2573
+ this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
2574
+ this.leavesRender.initialize(this.context);
1997
2575
  }
1998
2576
  updateWeakMap() {
1999
2577
  ELEMENT_TO_NODE.set(this.nativeElement, this.text);
@@ -2003,681 +2581,421 @@ class BaseTextComponent extends BaseComponent {
2003
2581
  if (NODE_TO_ELEMENT.get(this.text) === this.nativeElement) {
2004
2582
  NODE_TO_ELEMENT.delete(this.text);
2005
2583
  }
2584
+ ELEMENT_TO_NODE.delete(this.nativeElement);
2006
2585
  }
2007
2586
  onContextChange() {
2587
+ this.updateWeakMap();
2008
2588
  if (!this.initialized) {
2009
2589
  return;
2010
2590
  }
2011
- this.cdr.markForCheck();
2012
- this.updateWeakMap();
2591
+ this.leavesRender.update(this.context);
2013
2592
  }
2014
2593
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: BaseTextComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
2015
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: BaseTextComponent, usesInheritance: true, ngImport: i0 }); }
2594
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: BaseTextComponent, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
2016
2595
  }
2017
2596
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: BaseTextComponent, decorators: [{
2018
2597
  type: Directive
2019
- }] });
2020
-
2021
- /**
2022
- * the special container for angular template
2023
- * Add the rootNodes of each child component to the parentElement
2024
- * Remove useless DOM elements, eg: comment...
2025
- */
2026
- class ViewContainer {
2027
- constructor(elementRef, differs) {
2028
- this.elementRef = elementRef;
2029
- this.differs = differs;
2030
- }
2031
- ngAfterViewInit() {
2032
- const differ = this.differs.find(this.childrenComponent).create((index, item) => {
2033
- return item;
2034
- });
2035
- // first diff
2036
- differ.diff(this.childrenComponent);
2037
- const parentElement = this.elementRef.nativeElement.parentElement;
2038
- if (this.childrenComponent.length > 0) {
2039
- parentElement.insertBefore(this.createFragment(), this.elementRef.nativeElement);
2040
- this.elementRef.nativeElement.remove();
2041
- }
2042
- this.childrenComponent.changes.subscribe(value => {
2043
- const iterableChanges = differ.diff(this.childrenComponent);
2044
- if (iterableChanges) {
2045
- iterableChanges.forEachOperation((record, previousIndex, currentIndex) => {
2046
- // removed
2047
- if (currentIndex === null) {
2048
- return;
2049
- }
2050
- // added or moved
2051
- this.handleContainerItemChange(record, parentElement);
2052
- });
2053
- }
2054
- });
2055
- }
2056
- getPreviousRootNode(currentIndex) {
2057
- if (currentIndex === 0) {
2058
- return null;
2059
- }
2060
- const previousComponent = this.childrenComponent.find((item, index) => index === currentIndex - 1);
2061
- let previousRootNode = previousComponent.rootNodes[previousComponent.rootNodes.length - 1];
2062
- if (previousRootNode) {
2063
- return previousRootNode;
2064
- }
2065
- else {
2066
- return this.getPreviousRootNode(currentIndex - 1);
2067
- }
2068
- }
2069
- createFragment() {
2070
- const fragment = document.createDocumentFragment();
2071
- this.childrenComponent.forEach((component, index) => {
2072
- fragment.append(...component.rootNodes);
2073
- });
2074
- return fragment;
2075
- }
2076
- handleContainerItemChange(record, parentElement) {
2077
- // first insert
2078
- if (this.elementRef.nativeElement.parentElement && this.elementRef.nativeElement.parentElement === parentElement) {
2079
- const fragment = document.createDocumentFragment();
2080
- fragment.append(...record.item.rootNodes);
2081
- parentElement.insertBefore(fragment, this.elementRef.nativeElement);
2082
- this.elementRef.nativeElement.remove();
2083
- return;
2084
- }
2085
- // insert at start location
2086
- if (record.currentIndex === 0) {
2087
- const fragment = document.createDocumentFragment();
2088
- fragment.append(...record.item.rootNodes);
2089
- parentElement.prepend(fragment);
2090
- }
2091
- else {
2092
- // insert afterend of previous component end
2093
- let previousRootNode = this.getPreviousRootNode(record.currentIndex);
2094
- if (previousRootNode) {
2095
- record.item.rootNodes.forEach(rootNode => {
2096
- previousRootNode.insertAdjacentElement('afterend', rootNode);
2097
- previousRootNode = rootNode;
2098
- });
2099
- }
2100
- else {
2101
- this.viewContext.editor.onError({
2102
- code: SlateErrorCode.NotFoundPreviousRootNodeError,
2103
- name: 'not found previous rootNode',
2104
- nativeError: null
2105
- });
2106
- }
2107
- }
2108
- // Solve the block-card DOMElement loss when moving nodes
2109
- record.item.appendBlockCardElement();
2110
- }
2111
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainer, deps: [{ token: i0.ElementRef }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Directive }); }
2112
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: ViewContainer, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
2113
- }
2114
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainer, decorators: [{
2115
- type: Directive
2116
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.IterableDiffers }], propDecorators: { viewContext: [{
2117
- type: Input
2598
+ }], propDecorators: { childrenOutletInstance: [{
2599
+ type: ViewChild,
2600
+ args: [SlateChildrenOutlet, { static: true }]
2118
2601
  }] } });
2119
2602
 
2120
- class SlateDefaultString extends BaseComponent {
2121
- constructor(elementRef, cdr) {
2122
- super(elementRef, cdr);
2123
- this.elementRef = elementRef;
2124
- this.cdr = cdr;
2125
- }
2126
- beforeContextChange(value) {
2127
- if (this.context) {
2128
- if (this.context.type === 'lineBreakEmptyString') {
2129
- if (value.type === 'string') {
2130
- this.removeLineBreakEmptyStringDOM();
2131
- }
2132
- else {
2133
- this.textNode?.remove();
2134
- this.brNode?.remove();
2135
- }
2136
- }
2137
- if (this.context.type === 'string') {
2138
- if (value.type === 'lineBreakEmptyString') {
2139
- this.removeStringDOM();
2140
- }
2141
- }
2142
- }
2143
- }
2144
- onContextChange() {
2145
- if (this.context.type === 'string') {
2146
- this.createStringDOM();
2147
- }
2148
- else if (this.context.type === 'lineBreakEmptyString') {
2149
- this.createLineBreakEmptyStringDOM();
2150
- }
2151
- }
2152
- createLineBreakEmptyStringDOM() {
2153
- this.nativeElement.setAttribute('data-slate-zero-width', 'n');
2154
- this.nativeElement.setAttribute('data-slate-length', `${this.context.elementStringLength}`);
2155
- this.textNode = document.createTextNode(`\uFEFF`);
2156
- this.brNode = document.createElement('br');
2157
- this.nativeElement.append(this.textNode, this.brNode);
2158
- }
2159
- removeLineBreakEmptyStringDOM() {
2160
- this.brNode?.remove();
2161
- // remove zero width character
2162
- const zeroWidthCharacterIndex = this.textNode?.textContent.indexOf(`\uFEFF`);
2163
- this.textNode?.deleteData(zeroWidthCharacterIndex, 1);
2164
- this.nativeElement.removeAttribute('data-slate-zero-width');
2165
- this.nativeElement.removeAttribute('data-slate-length');
2166
- }
2167
- createStringDOM() {
2168
- this.nativeElement.setAttribute('data-slate-string', 'true');
2169
- this.updateStringDOM();
2170
- }
2171
- updateStringDOM() {
2172
- // Avoid breaking some browser default behaviors, such as spellCheck, android composition input state
2173
- if (this.nativeElement.textContent !== this.context.text) {
2174
- this.nativeElement.textContent = this.context.text;
2175
- }
2176
- }
2177
- removeStringDOM() {
2178
- this.nativeElement.removeAttribute('data-slate-string');
2179
- this.nativeElement.textContent = '';
2180
- }
2181
- ngOnInit() {
2182
- this.nativeElement.setAttribute('editable-text', '');
2603
+ class SlateLeaves extends ViewContainer {
2604
+ constructor() {
2605
+ super(...arguments);
2606
+ this.initialized = false;
2183
2607
  }
2184
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultString, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2185
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultString, isStandalone: true, selector: "span[slateDefaultString]", usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2608
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaves, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2609
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateLeaves, isStandalone: true, selector: "slate-leaves", inputs: { context: "context" }, usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2186
2610
  }
2187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultString, decorators: [{
2611
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaves, decorators: [{
2188
2612
  type: Component,
2189
2613
  args: [{
2190
- selector: 'span[slateDefaultString]',
2191
- template: '',
2614
+ selector: 'slate-leaves',
2615
+ template: ``,
2192
2616
  changeDetection: ChangeDetectionStrategy.OnPush,
2193
- standalone: true
2617
+ standalone: true,
2618
+ imports: [NgFor]
2194
2619
  }]
2195
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }] });
2620
+ }], propDecorators: { context: [{
2621
+ type: Input
2622
+ }] } });
2196
2623
 
2197
- class SlateString extends ViewContainerItem {
2198
- constructor(elementRef, viewContainerRef) {
2199
- super(viewContainerRef);
2200
- this.elementRef = elementRef;
2201
- this.viewContainerRef = viewContainerRef;
2202
- }
2624
+ class SlateVoidText extends BaseTextComponent {
2203
2625
  ngOnInit() {
2204
- this.createView();
2626
+ super.ngOnInit();
2205
2627
  }
2206
2628
  ngOnChanges() {
2207
2629
  if (!this.initialized) {
2208
2630
  return;
2209
2631
  }
2210
- this.updateView();
2211
- }
2212
- ngAfterViewInit() {
2213
- this.elementRef.nativeElement.remove();
2214
- }
2215
- // COMPAT: If this is the last text node in an empty block, render a zero-
2216
- // width space that will convert into a line break when copying and pasting
2217
- // to support expected plain text.
2218
- isLineBreakEmptyString() {
2219
- const path = AngularEditor.findPath(this.viewContext.editor, this.context.text);
2220
- const parentPath = Path.parent(path);
2221
- return (this.context.leaf.text === '' &&
2222
- this.context.parent.children[this.context.parent.children.length - 1] === this.context.text &&
2223
- !this.viewContext.editor.isInline(this.context.parent) &&
2224
- Editor.string(this.viewContext.editor, parentPath) === '');
2225
2632
  }
2226
- // COMPAT: If the text is empty, it's because it's on the edge of an inline
2227
- // node, so we render a zero-width space so that the selection can be
2228
- // inserted next to it still.
2229
- isEmptyText() {
2230
- return this.context.leaf.text === '';
2231
- }
2232
- // COMPAT: Browsers will collapse trailing new lines at the end of blocks,
2233
- // so we need to add an extra trailing new lines to prevent that.
2234
- isCompatibleString() {
2235
- return this.context.isLast && this.context.leaf.text.slice(-1) === '\n';
2236
- }
2237
- // COMPAT: Render text inside void nodes with a zero-width space.
2238
- // So the node can contain selection but the text is not visible.
2239
- isVoid() {
2240
- return this.viewContext.editor.isVoid(this.context.parent);
2241
- }
2242
- getViewType() {
2243
- if (this.isVoid()) {
2244
- return this.viewContext.templateComponent.voidStringTemplate;
2245
- }
2246
- if (this.isLineBreakEmptyString()) {
2247
- return SlateDefaultString;
2248
- }
2249
- if (this.isEmptyText()) {
2250
- return this.viewContext.templateComponent.emptyTextTemplate;
2251
- }
2252
- if (this.isCompatibleString()) {
2253
- return this.viewContext.templateComponent.compatibleStringTemplate;
2254
- }
2255
- return SlateDefaultString;
2256
- }
2257
- getType() {
2258
- if (this.isLineBreakEmptyString()) {
2259
- return 'lineBreakEmptyString';
2260
- }
2261
- return 'string';
2262
- }
2263
- getContext() {
2264
- const stringType = this.getType();
2265
- return {
2266
- text: this.context.leaf.text,
2267
- elementStringLength: Node.string(this.context.parent).length,
2268
- type: stringType
2269
- };
2270
- }
2271
- memoizedContext(prev, next) {
2272
- return false;
2273
- }
2274
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateString, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
2275
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2633
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateVoidText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2634
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateVoidText, isStandalone: true, selector: "span[slateVoidText]", host: { attributes: { "data-slate-spacer": "true", "data-slate-node": "text" }, classAttribute: "slate-spacer" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2276
2635
  }
2277
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateString, decorators: [{
2636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateVoidText, decorators: [{
2278
2637
  type: Component,
2279
2638
  args: [{
2280
- selector: 'span[slateString]',
2281
- template: '',
2639
+ selector: 'span[slateVoidText]',
2640
+ template: ``,
2282
2641
  changeDetection: ChangeDetectionStrategy.OnPush,
2283
- standalone: true
2642
+ host: {
2643
+ 'data-slate-spacer': 'true',
2644
+ class: 'slate-spacer',
2645
+ 'data-slate-node': 'text'
2646
+ },
2647
+ standalone: true,
2648
+ imports: [SlateLeaves]
2284
2649
  }]
2285
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }], propDecorators: { context: [{
2286
- type: Input
2287
- }] } });
2650
+ }] });
2288
2651
 
2289
- class SlateDefaultLeaf extends BaseLeafComponent {
2290
- onContextChange() {
2291
- super.onContextChange();
2292
- this.renderPlaceholder();
2293
- }
2294
- ngOnDestroy() {
2295
- // Because the placeholder span is not in the current component, it is destroyed along with the current component
2296
- this.destroyPlaceholder();
2297
- }
2298
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultLeaf, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2299
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultLeaf, isStandalone: true, selector: "span[slateDefaultLeaf]", host: { attributes: { "data-slate-leaf": "true" } }, usesInheritance: true, ngImport: i0, template: `<span slateString [context]="context" [viewContext]="viewContext"><span></span></span>`, isInline: true, dependencies: [{ kind: "component", type: SlateString, selector: "span[slateString]", inputs: ["context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2652
+ class SlateDefaultText extends BaseTextComponent {
2653
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2654
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultText, isStandalone: true, selector: "span[slateDefaultText]", host: { attributes: { "data-slate-node": "text" } }, usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2300
2655
  }
2301
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultLeaf, decorators: [{
2656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultText, decorators: [{
2302
2657
  type: Component,
2303
2658
  args: [{
2304
- selector: 'span[slateDefaultLeaf]',
2305
- template: `<span slateString [context]="context" [viewContext]="viewContext"><span></span></span>`,
2659
+ selector: 'span[slateDefaultText]',
2660
+ template: ``,
2306
2661
  changeDetection: ChangeDetectionStrategy.OnPush,
2307
2662
  host: {
2308
- 'data-slate-leaf': 'true'
2663
+ 'data-slate-node': 'text'
2309
2664
  },
2310
2665
  standalone: true,
2311
- imports: [SlateString]
2666
+ imports: [SlateLeaves]
2312
2667
  }]
2313
2668
  }] });
2314
2669
 
2315
- class SlateLeaf extends ViewContainerItem {
2316
- ngOnInit() {
2317
- this.createView();
2318
- }
2319
- getContext() {
2320
- return this.context;
2321
- }
2322
- getViewType() {
2323
- return (this.viewContext.renderLeaf && this.viewContext.renderLeaf(this.context.leaf)) || SlateDefaultLeaf;
2324
- }
2325
- memoizedContext(prev, next) {
2326
- return false;
2327
- }
2328
- ngOnChanges(simpleChanges) {
2329
- if (!this.initialized) {
2330
- return;
2331
- }
2332
- this.updateView();
2333
- }
2334
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaf, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2335
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateLeaf, isStandalone: true, selector: "slate-leaf", inputs: { context: "context" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2670
+ class SlateDefaultElement extends BaseElementComponent {
2671
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultElement, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2672
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultElement, isStandalone: true, selector: "div[slateDefaultElement]", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2336
2673
  }
2337
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaf, decorators: [{
2674
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultElement, decorators: [{
2338
2675
  type: Component,
2339
2676
  args: [{
2340
- selector: 'slate-leaf',
2341
- template: '',
2677
+ selector: 'div[slateDefaultElement]',
2678
+ template: ``,
2342
2679
  changeDetection: ChangeDetectionStrategy.OnPush,
2343
- standalone: true
2680
+ standalone: true,
2681
+ imports: [SlateChildren]
2344
2682
  }]
2345
- }], propDecorators: { context: [{
2346
- type: Input
2347
- }] } });
2683
+ }] });
2348
2684
 
2349
- class SlateLeaves extends ViewContainer {
2350
- constructor() {
2351
- super(...arguments);
2685
+ /**
2686
+ * Dynamically create/update components or templates
2687
+ * Provide rootNodes for the view container
2688
+ * If the dynamically created component uses onpush mode, then it must call markForCheck when setting the context
2689
+ */
2690
+ class ViewContainerItem {
2691
+ get rootNodes() {
2692
+ return this.getRootNodes();
2693
+ }
2694
+ getRootNodes() {
2695
+ if (this.embeddedViewRef) {
2696
+ return this.embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode));
2697
+ }
2698
+ if (this.componentRef) {
2699
+ return [this.componentRef.instance.nativeElement];
2700
+ }
2701
+ return [];
2702
+ }
2703
+ constructor(viewContainerRef) {
2704
+ this.viewContainerRef = viewContainerRef;
2352
2705
  this.initialized = false;
2353
2706
  }
2354
- ngOnInit() {
2355
- this.leaves = Text$1.decorations(this.context.text, this.context.decorations);
2356
- this.leafContexts = this.getLeafContexts();
2357
- this.initialized = true;
2707
+ destroyView() {
2708
+ if (this.embeddedViewRef) {
2709
+ this.embeddedViewRef.destroy();
2710
+ this.embeddedViewRef = null;
2711
+ }
2712
+ if (this.componentRef) {
2713
+ this.componentRef.destroy();
2714
+ this.componentRef = null;
2715
+ }
2358
2716
  }
2359
- getLeafContexts() {
2360
- return this.leaves.map((leaf, index) => {
2361
- return {
2362
- leaf,
2363
- text: this.context.text,
2364
- parent: this.context.parent,
2365
- index,
2366
- isLast: this.context.isLast && index === this.leaves.length - 1
2717
+ createView() {
2718
+ this.initialized = true;
2719
+ this.viewType = this.getViewType();
2720
+ const context = this.getContext();
2721
+ if (isTemplateRef(this.viewType)) {
2722
+ this.embeddedViewContext = {
2723
+ context,
2724
+ viewContext: this.viewContext
2367
2725
  };
2368
- });
2726
+ const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
2727
+ this.embeddedViewRef = embeddedViewRef;
2728
+ }
2729
+ if (isComponentType(this.viewType)) {
2730
+ const componentRef = this.viewContainerRef.createComponent(this.viewType);
2731
+ componentRef.instance.viewContext = this.viewContext;
2732
+ componentRef.instance.context = context;
2733
+ this.componentRef = componentRef;
2734
+ }
2369
2735
  }
2370
- ngOnChanges(simpleChanges) {
2371
- if (!this.initialized) {
2372
- return;
2736
+ updateView() {
2737
+ const viewType = this.getViewType();
2738
+ const context = this.getContext();
2739
+ if (this.viewType === viewType) {
2740
+ if (this.componentRef) {
2741
+ if (this.memoizedContext(this.componentRef.instance.context, context)) {
2742
+ return;
2743
+ }
2744
+ this.componentRef.instance.context = context;
2745
+ }
2746
+ if (this.embeddedViewRef) {
2747
+ if (this.memoizedContext(this.embeddedViewContext.context, context)) {
2748
+ return;
2749
+ }
2750
+ this.embeddedViewContext.context = context;
2751
+ }
2373
2752
  }
2374
- const context = simpleChanges['context'];
2375
- const previousValue = context.previousValue;
2376
- const currentValue = context.currentValue;
2377
- if (previousValue.text !== currentValue.text || !isDecoratorRangeListEqual(previousValue.decorations, currentValue.decorations)) {
2378
- this.leaves = Text$1.decorations(this.context.text, this.context.decorations);
2753
+ else {
2754
+ this.viewType = viewType;
2755
+ const firstRootNode = this.rootNodes[0];
2756
+ if (isTemplateRef(this.viewType)) {
2757
+ this.embeddedViewContext = {
2758
+ context,
2759
+ viewContext: this.viewContext
2760
+ };
2761
+ const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
2762
+ firstRootNode.replaceWith(...embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode)));
2763
+ this.destroyView();
2764
+ this.embeddedViewRef = embeddedViewRef;
2765
+ }
2766
+ if (isComponentType(this.viewType)) {
2767
+ const componentRef = this.viewContainerRef.createComponent(this.viewType);
2768
+ componentRef.instance.viewContext = this.viewContext;
2769
+ componentRef.instance.context = context;
2770
+ firstRootNode.replaceWith(componentRef.instance.nativeElement);
2771
+ this.destroyView();
2772
+ this.componentRef = componentRef;
2773
+ }
2379
2774
  }
2380
- this.leafContexts = this.getLeafContexts();
2381
2775
  }
2382
- trackBy(index, item) {
2383
- return index;
2776
+ appendBlockCardElement() {
2777
+ if (this.blockCardComponentRef) {
2778
+ this.blockCardComponentRef.instance.append();
2779
+ }
2384
2780
  }
2385
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaves, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2386
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateLeaves, isStandalone: true, selector: "slate-leaves", inputs: { context: "context" }, viewQueries: [{ propertyName: "childrenComponent", predicate: SlateLeaf, descendants: true, read: SlateLeaf }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `<slate-leaf
2387
- [context]="context"
2388
- [viewContext]="viewContext"
2389
- *ngFor="let context of leafContexts; trackBy: trackBy"
2390
- ></slate-leaf>`, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: SlateLeaf, selector: "slate-leaf", inputs: ["context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainerItem, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
2782
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: ViewContainerItem, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
2391
2783
  }
2392
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateLeaves, decorators: [{
2393
- type: Component,
2394
- args: [{
2395
- selector: 'slate-leaves',
2396
- template: `<slate-leaf
2397
- [context]="context"
2398
- [viewContext]="viewContext"
2399
- *ngFor="let context of leafContexts; trackBy: trackBy"
2400
- ></slate-leaf>`,
2401
- changeDetection: ChangeDetectionStrategy.OnPush,
2402
- standalone: true,
2403
- imports: [NgFor, SlateLeaf]
2404
- }]
2405
- }], propDecorators: { context: [{
2784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ViewContainerItem, decorators: [{
2785
+ type: Directive
2786
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { viewContext: [{
2406
2787
  type: Input
2407
- }], childrenComponent: [{
2408
- type: ViewChildren,
2409
- args: [SlateLeaf, { read: SlateLeaf }]
2410
2788
  }] } });
2411
2789
 
2412
- class SlateDefaultText extends BaseTextComponent {
2413
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2414
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultText, isStandalone: true, selector: "span[slateDefaultText]", host: { attributes: { "data-slate-node": "text" } }, usesInheritance: true, ngImport: i0, template: `<slate-leaves [context]="context" [viewContext]="viewContext" [viewContext]="viewContext"></slate-leaves>`, isInline: true, dependencies: [{ kind: "component", type: SlateLeaves, selector: "slate-leaves", inputs: ["context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2415
- }
2416
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultText, decorators: [{
2417
- type: Component,
2418
- args: [{
2419
- selector: 'span[slateDefaultText]',
2420
- template: `<slate-leaves [context]="context" [viewContext]="viewContext" [viewContext]="viewContext"></slate-leaves>`,
2421
- changeDetection: ChangeDetectionStrategy.OnPush,
2422
- host: {
2423
- 'data-slate-node': 'text'
2424
- },
2425
- standalone: true,
2426
- imports: [SlateLeaves]
2427
- }]
2428
- }] });
2429
-
2430
- class SlateVoidText extends BaseTextComponent {
2431
- ngOnInit() {
2432
- this.isLeafBlock = AngularEditor.isLeafBlock(this.viewContext.editor, this.context.parent);
2433
- super.ngOnInit();
2790
+ class SlateDefaultString extends BaseComponent {
2791
+ constructor(elementRef, cdr) {
2792
+ super(elementRef, cdr);
2793
+ this.elementRef = elementRef;
2794
+ this.cdr = cdr;
2795
+ }
2796
+ beforeContextChange(value) {
2797
+ if (this.context) {
2798
+ if (this.context.type === 'lineBreakEmptyString') {
2799
+ if (value.type === 'string') {
2800
+ this.removeLineBreakEmptyStringDOM();
2801
+ }
2802
+ else {
2803
+ this.textNode?.remove();
2804
+ this.brNode?.remove();
2805
+ }
2806
+ }
2807
+ if (this.context.type === 'string') {
2808
+ if (value.type === 'lineBreakEmptyString') {
2809
+ this.removeStringDOM();
2810
+ }
2811
+ }
2812
+ }
2813
+ }
2814
+ onContextChange() {
2815
+ if (this.context.type === 'string') {
2816
+ this.createStringDOM();
2817
+ }
2818
+ else if (this.context.type === 'lineBreakEmptyString') {
2819
+ this.createLineBreakEmptyStringDOM();
2820
+ }
2821
+ }
2822
+ createLineBreakEmptyStringDOM() {
2823
+ this.nativeElement.setAttribute('data-slate-zero-width', 'n');
2824
+ this.nativeElement.setAttribute('data-slate-length', `${this.context.elementStringLength}`);
2825
+ this.textNode = document.createTextNode(`\uFEFF`);
2826
+ this.brNode = document.createElement('br');
2827
+ this.nativeElement.append(this.textNode, this.brNode);
2828
+ }
2829
+ removeLineBreakEmptyStringDOM() {
2830
+ this.brNode?.remove();
2831
+ // remove zero width character
2832
+ const zeroWidthCharacterIndex = this.textNode?.textContent.indexOf(`\uFEFF`);
2833
+ this.textNode?.deleteData(zeroWidthCharacterIndex, 1);
2834
+ this.nativeElement.removeAttribute('data-slate-zero-width');
2835
+ this.nativeElement.removeAttribute('data-slate-length');
2836
+ }
2837
+ createStringDOM() {
2838
+ this.nativeElement.setAttribute('data-slate-string', 'true');
2839
+ this.updateStringDOM();
2434
2840
  }
2435
- ngOnChanges() {
2436
- if (!this.initialized) {
2437
- return;
2841
+ updateStringDOM() {
2842
+ // Avoid breaking some browser default behaviors, such as spellCheck, android composition input state
2843
+ if (this.nativeElement.textContent !== this.context.text) {
2844
+ this.nativeElement.textContent = this.context.text;
2438
2845
  }
2439
- this.isLeafBlock = AngularEditor.isLeafBlock(this.viewContext.editor, this.context.parent);
2440
2846
  }
2441
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateVoidText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2442
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateVoidText, isStandalone: true, selector: "span[slateVoidText]", host: { attributes: { "data-slate-spacer": "true", "data-slate-node": "text" }, properties: { "attr.contenteditable": "isLeafBlock" }, classAttribute: "slate-spacer" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `<slate-leaves [context]="context" [viewContext]="viewContext" [viewContext]="viewContext"></slate-leaves>`, isInline: true, dependencies: [{ kind: "component", type: SlateLeaves, selector: "slate-leaves", inputs: ["context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2847
+ removeStringDOM() {
2848
+ this.nativeElement.removeAttribute('data-slate-string');
2849
+ this.nativeElement.textContent = '';
2850
+ }
2851
+ ngOnInit() {
2852
+ this.nativeElement.setAttribute('editable-text', '');
2853
+ }
2854
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultString, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2855
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultString, isStandalone: true, selector: "span[slateDefaultString]", usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2443
2856
  }
2444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateVoidText, decorators: [{
2857
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultString, decorators: [{
2445
2858
  type: Component,
2446
2859
  args: [{
2447
- selector: 'span[slateVoidText]',
2448
- template: `<slate-leaves [context]="context" [viewContext]="viewContext" [viewContext]="viewContext"></slate-leaves>`,
2860
+ selector: 'span[slateDefaultString]',
2861
+ template: '',
2449
2862
  changeDetection: ChangeDetectionStrategy.OnPush,
2450
- host: {
2451
- '[attr.contenteditable]': 'isLeafBlock',
2452
- 'data-slate-spacer': 'true',
2453
- class: 'slate-spacer',
2454
- 'data-slate-node': 'text'
2455
- },
2456
- standalone: true,
2457
- imports: [SlateLeaves]
2863
+ standalone: true
2458
2864
  }]
2459
- }] });
2460
-
2461
- const SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN = new InjectionToken('slate-default-element-token');
2865
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }] });
2462
2866
 
2463
- class SlateDescendant extends ViewContainerItem {
2464
- get rootNodes() {
2465
- if (this.blockCardComponentRef) {
2466
- return [this.blockCardComponentRef.instance.nativeElement];
2467
- }
2468
- return super.getRootNodes();
2469
- }
2470
- get isBlockCard() {
2471
- return this.viewContext.editor.isBlockCard(this.descendant);
2472
- }
2473
- constructor(viewContainerRef, defaultElementComponentType) {
2867
+ class SlateString extends ViewContainerItem {
2868
+ constructor(elementRef, viewContainerRef) {
2474
2869
  super(viewContainerRef);
2870
+ this.elementRef = elementRef;
2475
2871
  this.viewContainerRef = viewContainerRef;
2476
- this.defaultElementComponentType = defaultElementComponentType;
2477
2872
  }
2478
2873
  ngOnInit() {
2479
- NODE_TO_INDEX.set(this.descendant, this.index);
2480
- NODE_TO_PARENT.set(this.descendant, this.context.parent);
2481
2874
  this.createView();
2482
- if (this.isBlockCard) {
2483
- this.createBlockCard();
2484
- }
2485
- }
2486
- destroyView() {
2487
- super.destroyView();
2488
- this.destroyBlockCard();
2489
2875
  }
2490
2876
  ngOnChanges() {
2491
2877
  if (!this.initialized) {
2492
2878
  return;
2493
2879
  }
2494
- NODE_TO_INDEX.set(this.descendant, this.index);
2495
- NODE_TO_PARENT.set(this.descendant, this.context.parent);
2496
2880
  this.updateView();
2497
- if (this.isBlockCard) {
2498
- this.updateBlockCard();
2499
- }
2500
2881
  }
2501
- destroyBlockCard() {
2502
- if (this.blockCardComponentRef) {
2503
- this.blockCardComponentRef.destroy();
2504
- this.blockCardComponentRef = null;
2505
- }
2882
+ ngAfterViewInit() {
2883
+ this.elementRef.nativeElement.remove();
2506
2884
  }
2507
- createBlockCard() {
2508
- const rootNodes = this.rootNodes;
2509
- this.blockCardComponentRef = this.viewContainerRef.createComponent(SlateBlockCard);
2510
- this.blockCardComponentRef.instance.initializeCenter(rootNodes);
2885
+ // COMPAT: If this is the last text node in an empty block, render a zero-
2886
+ // width space that will convert into a line break when copying and pasting
2887
+ // to support expected plain text.
2888
+ isLineBreakEmptyString() {
2889
+ return (this.context.leaf.text === '' &&
2890
+ this.context.parent.children[this.context.parent.children.length - 1] === this.context.text &&
2891
+ !this.viewContext.editor.isInline(this.context.parent) &&
2892
+ // [list-render] performance optimization: reduce the number of calls to the `Editor.string(editor, path)` method
2893
+ isEmpty(this.viewContext.editor, this.context.parent));
2511
2894
  }
2512
- updateBlockCard() {
2513
- if (this.blockCardComponentRef) {
2514
- return;
2515
- }
2516
- const rootNodes = this.rootNodes;
2517
- this.createBlockCard();
2518
- const firstRootNode = rootNodes[0];
2519
- firstRootNode.replaceWith(this.blockCardComponentRef.instance.nativeElement);
2895
+ // COMPAT: If the text is empty, it's because it's on the edge of an inline
2896
+ // node, so we render a zero-width space so that the selection can be
2897
+ // inserted next to it still.
2898
+ isEmptyText() {
2899
+ return this.context.leaf.text === '';
2520
2900
  }
2521
- getCommonContext() {
2522
- const path = AngularEditor.findPath(this.viewContext.editor, this.context.parent);
2523
- const p = path.concat(this.index);
2524
- try {
2525
- const range = Editor.range(this.viewContext.editor, p);
2526
- const sel = this.context.selection && Range.intersection(range, this.context.selection);
2527
- const ds = this.context.decorate([this.descendant, p]);
2528
- for (const dec of this.context.decorations) {
2529
- const d = Range.intersection(dec, range);
2530
- if (d) {
2531
- ds.push(d);
2532
- }
2533
- }
2534
- return { selection: sel, decorations: ds };
2535
- }
2536
- catch (error) {
2537
- this.viewContext.editor.onError({
2538
- code: SlateErrorCode.GetStartPointError,
2539
- nativeError: error
2540
- });
2541
- return { selection: null, decorations: [] };
2542
- }
2901
+ // COMPAT: Browsers will collapse trailing new lines at the end of blocks,
2902
+ // so we need to add an extra trailing new lines to prevent that.
2903
+ isCompatibleString() {
2904
+ return this.context.isLast && this.context.leaf.text.slice(-1) === '\n';
2543
2905
  }
2544
- getContext() {
2545
- if (Element.isElement(this.descendant)) {
2546
- const computedContext = this.getCommonContext();
2547
- const key = AngularEditor.findKey(this.viewContext.editor, this.descendant);
2548
- const isInline = this.viewContext.editor.isInline(this.descendant);
2549
- const isVoid = this.viewContext.editor.isVoid(this.descendant);
2550
- const elementContext = {
2551
- element: this.descendant,
2552
- ...computedContext,
2553
- attributes: {
2554
- 'data-slate-node': 'element',
2555
- 'data-slate-key': key.id
2556
- },
2557
- decorate: this.context.decorate,
2558
- readonly: this.context.readonly
2559
- };
2560
- if (isInline) {
2561
- elementContext.attributes['data-slate-inline'] = true;
2562
- }
2563
- if (isVoid) {
2564
- elementContext.attributes['data-slate-void'] = true;
2565
- elementContext.attributes.contenteditable = false;
2566
- }
2567
- return elementContext;
2568
- }
2569
- else {
2570
- const computedContext = this.getCommonContext();
2571
- const isLeafBlock = AngularEditor.isLeafBlock(this.viewContext.editor, this.context.parent);
2572
- const textContext = {
2573
- decorations: computedContext.decorations,
2574
- isLast: isLeafBlock && this.index === this.context.parent.children.length - 1,
2575
- parent: this.context.parent,
2576
- text: this.descendant
2577
- };
2578
- return textContext;
2579
- }
2906
+ // COMPAT: Render text inside void nodes with a zero-width space.
2907
+ // So the node can contain selection but the text is not visible.
2908
+ isVoid() {
2909
+ return this.viewContext.editor.isVoid(this.context.parent);
2580
2910
  }
2581
2911
  getViewType() {
2582
- if (Element.isElement(this.descendant)) {
2583
- return (this.viewContext.renderElement && this.viewContext.renderElement(this.descendant)) || this.defaultElementComponentType;
2912
+ if (this.isVoid()) {
2913
+ return this.viewContext.templateComponent.voidStringTemplate;
2584
2914
  }
2585
- else {
2586
- const isVoid = this.viewContext.editor.isVoid(this.context.parent);
2587
- return isVoid
2588
- ? SlateVoidText
2589
- : (this.viewContext.renderText && this.viewContext.renderText(this.descendant)) || SlateDefaultText;
2915
+ if (this.isLineBreakEmptyString()) {
2916
+ return SlateDefaultString;
2917
+ }
2918
+ if (this.isEmptyText()) {
2919
+ return this.viewContext.templateComponent.emptyTextTemplate;
2920
+ }
2921
+ if (this.isCompatibleString()) {
2922
+ return this.viewContext.templateComponent.compatibleStringTemplate;
2590
2923
  }
2924
+ return SlateDefaultString;
2591
2925
  }
2592
- memoizedElementContext(prev, next) {
2593
- return (prev.element === next.element &&
2594
- (!this.viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
2595
- prev.readonly === next.readonly &&
2596
- isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
2597
- (prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
2926
+ getType() {
2927
+ if (this.isLineBreakEmptyString()) {
2928
+ return 'lineBreakEmptyString';
2929
+ }
2930
+ return 'string';
2598
2931
  }
2599
- memoizedTextContext(prev, next) {
2600
- return (next.parent === prev.parent &&
2601
- next.isLast === prev.isLast &&
2602
- next.text === prev.text &&
2603
- isDecoratorRangeListEqual(next.decorations, prev.decorations));
2932
+ getContext() {
2933
+ const stringType = this.getType();
2934
+ return {
2935
+ text: this.context.leaf.text,
2936
+ elementStringLength: Node.string(this.context.parent).length,
2937
+ type: stringType
2938
+ };
2604
2939
  }
2605
2940
  memoizedContext(prev, next) {
2606
- if (Element.isElement(this.descendant)) {
2607
- return this.memoizedElementContext(prev, next);
2608
- }
2609
- else {
2610
- return this.memoizedTextContext(prev, next);
2611
- }
2941
+ return false;
2612
2942
  }
2613
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDescendant, deps: [{ token: i0.ViewContainerRef }, { token: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
2614
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDescendant, isStandalone: true, selector: "slate-descendant", inputs: { descendant: "descendant", context: "context", viewContext: "viewContext", index: "index" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2943
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateString, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component }); }
2944
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2615
2945
  }
2616
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDescendant, decorators: [{
2946
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateString, decorators: [{
2617
2947
  type: Component,
2618
2948
  args: [{
2619
- selector: 'slate-descendant',
2949
+ selector: 'span[slateString]',
2620
2950
  template: '',
2621
2951
  changeDetection: ChangeDetectionStrategy.OnPush,
2622
2952
  standalone: true
2623
2953
  }]
2624
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: undefined, decorators: [{
2625
- type: Inject,
2626
- args: [SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN]
2627
- }] }], propDecorators: { descendant: [{
2628
- type: Input
2629
- }], context: [{
2630
- type: Input
2631
- }], viewContext: [{
2632
- type: Input
2633
- }], index: [{
2954
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }], propDecorators: { context: [{
2634
2955
  type: Input
2635
2956
  }] } });
2957
+ /**
2958
+ * TODO: remove when bump slate
2959
+ * copy from slate
2960
+ * @param editor
2961
+ * @param element
2962
+ * @returns
2963
+ */
2964
+ const isEmpty = (editor, element) => {
2965
+ const { children } = element;
2966
+ const [first] = children;
2967
+ return children.length === 0 || (children.length === 1 && Text$1.isText(first) && first.text === '' && !editor.isVoid(element));
2968
+ };
2636
2969
 
2637
- class SlateChildren extends ViewContainer {
2638
- constructor() {
2639
- super(...arguments);
2640
- this.trackBy = (index, node) => {
2641
- return this.viewContext.trackBy(node) || AngularEditor.findKey(this.viewContext.editor, node);
2642
- };
2970
+ class SlateDefaultLeaf extends BaseLeafComponent {
2971
+ onContextChange() {
2972
+ super.onContextChange();
2973
+ this.renderPlaceholder();
2643
2974
  }
2644
- ngOnInit() { }
2645
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildren, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2646
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateChildren, isStandalone: true, selector: "slate-children", inputs: { children: "children", context: "context", viewContext: "viewContext" }, viewQueries: [{ propertyName: "childrenComponent", predicate: SlateDescendant, descendants: true, read: SlateDescendant }], usesInheritance: true, ngImport: i0, template: `<slate-descendant
2647
- [descendant]="descendant"
2648
- [context]="context"
2649
- [viewContext]="viewContext"
2650
- [viewContext]="viewContext"
2651
- [index]="index"
2652
- *ngFor="let descendant of children; let index = index; trackBy: trackBy"
2653
- ></slate-descendant>`, isInline: true, dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: SlateDescendant, selector: "slate-descendant", inputs: ["descendant", "context", "viewContext", "index"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2975
+ ngOnDestroy() {
2976
+ // Because the placeholder span is not in the current component, it is destroyed along with the current component
2977
+ this.destroyPlaceholder();
2978
+ }
2979
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultLeaf, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2980
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultLeaf, isStandalone: true, selector: "span[slateDefaultLeaf]", host: { attributes: { "data-slate-leaf": "true" } }, usesInheritance: true, ngImport: i0, template: `<span slateString [context]="context" [viewContext]="viewContext"><span></span></span>`, isInline: true, dependencies: [{ kind: "component", type: SlateString, selector: "span[slateString]", inputs: ["context"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2654
2981
  }
2655
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateChildren, decorators: [{
2982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultLeaf, decorators: [{
2656
2983
  type: Component,
2657
2984
  args: [{
2658
- selector: 'slate-children',
2659
- template: `<slate-descendant
2660
- [descendant]="descendant"
2661
- [context]="context"
2662
- [viewContext]="viewContext"
2663
- [viewContext]="viewContext"
2664
- [index]="index"
2665
- *ngFor="let descendant of children; let index = index; trackBy: trackBy"
2666
- ></slate-descendant>`,
2985
+ selector: 'span[slateDefaultLeaf]',
2986
+ template: `<span slateString [context]="context" [viewContext]="viewContext"><span></span></span>`,
2667
2987
  changeDetection: ChangeDetectionStrategy.OnPush,
2988
+ host: {
2989
+ 'data-slate-leaf': 'true'
2990
+ },
2668
2991
  standalone: true,
2669
- imports: [NgFor, SlateDescendant]
2992
+ imports: [SlateString]
2670
2993
  }]
2671
- }], propDecorators: { children: [{
2672
- type: Input
2673
- }], context: [{
2674
- type: Input
2675
- }], viewContext: [{
2676
- type: Input
2677
- }], childrenComponent: [{
2678
- type: ViewChildren,
2679
- args: [SlateDescendant, { read: SlateDescendant }]
2680
- }] } });
2994
+ }] });
2995
+
2996
+ const SLATE_DEFAULT_LEAF_COMPONENT_TOKEN = new InjectionToken('slate-default-leaf-token');
2997
+
2998
+ const TRIPLE_CLICK = 3;
2681
2999
 
2682
3000
  // not correctly clipboardData on beforeinput
2683
3001
  const forceOnDOMPaste = IS_SAFARI;
@@ -2685,12 +3003,16 @@ class SlateEditable {
2685
3003
  get hasBeforeInputSupport() {
2686
3004
  return HAS_BEFORE_INPUT_SUPPORT;
2687
3005
  }
2688
- constructor(elementRef, renderer2, cdr, ngZone, injector) {
3006
+ constructor(elementRef, renderer2, cdr, ngZone, injector, defaultElement, defaultText, defaultVoidText, defaultLeaf) {
2689
3007
  this.elementRef = elementRef;
2690
3008
  this.renderer2 = renderer2;
2691
3009
  this.cdr = cdr;
2692
3010
  this.ngZone = ngZone;
2693
3011
  this.injector = injector;
3012
+ this.defaultElement = defaultElement;
3013
+ this.defaultText = defaultText;
3014
+ this.defaultVoidText = defaultVoidText;
3015
+ this.defaultLeaf = defaultLeaf;
2694
3016
  this.destroy$ = new Subject();
2695
3017
  this.isComposing = false;
2696
3018
  this.isDraggingInternally = false;
@@ -2712,6 +3034,10 @@ class SlateEditable {
2712
3034
  this.dataSlateEditor = true;
2713
3035
  this.dataSlateNode = 'value';
2714
3036
  this.dataGramm = false;
3037
+ this.viewContainerRef = inject(ViewContainerRef);
3038
+ this.getOutletParent = () => {
3039
+ return this.elementRef.nativeElement;
3040
+ };
2715
3041
  }
2716
3042
  ngOnInit() {
2717
3043
  this.editor.injector = this.injector;
@@ -2737,6 +3063,7 @@ class SlateEditable {
2737
3063
  // add browser class
2738
3064
  let browserClass = IS_FIREFOX ? 'firefox' : IS_SAFARI ? 'safari' : '';
2739
3065
  browserClass && this.elementRef.nativeElement.classList.add(browserClass);
3066
+ this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, () => null);
2740
3067
  }
2741
3068
  ngOnChanges(simpleChanges) {
2742
3069
  if (!this.initialized) {
@@ -2744,16 +3071,16 @@ class SlateEditable {
2744
3071
  }
2745
3072
  const decorateChange = simpleChanges['decorate'];
2746
3073
  if (decorateChange) {
2747
- this.forceFlush();
3074
+ this.forceRender();
2748
3075
  }
2749
3076
  const placeholderChange = simpleChanges['placeholder'];
2750
3077
  if (placeholderChange) {
2751
- this.detectContext();
3078
+ this.render();
2752
3079
  }
2753
3080
  const readonlyChange = simpleChanges['readonly'];
2754
3081
  if (readonlyChange) {
2755
3082
  IS_READONLY.set(this.editor, this.readonly);
2756
- this.detectContext();
3083
+ this.render();
2757
3084
  this.toSlateSelection();
2758
3085
  }
2759
3086
  }
@@ -2777,6 +3104,12 @@ class SlateEditable {
2777
3104
  this.editor.children = normalize(value);
2778
3105
  }
2779
3106
  this.initializeContext();
3107
+ if (!this.listRender.initialized) {
3108
+ this.listRender.initialize(this.editor.children, this.editor, this.context);
3109
+ }
3110
+ else {
3111
+ this.listRender.update(this.editor.children, this.editor, this.context);
3112
+ }
2780
3113
  this.cdr.markForCheck();
2781
3114
  }
2782
3115
  }
@@ -2829,12 +3162,11 @@ class SlateEditable {
2829
3162
  hasDomSelectionInEditor = true;
2830
3163
  }
2831
3164
  // If the DOM selection is in the editor and the editor selection is already correct, we're done.
2832
- if (hasDomSelection &&
2833
- hasDomSelectionInEditor &&
2834
- selection &&
2835
- hasStringTarget(domSelection) &&
2836
- Range.equals(AngularEditor.toSlateRange(this.editor, domSelection), selection)) {
2837
- return;
3165
+ if (hasDomSelection && hasDomSelectionInEditor && selection && hasStringTarget(domSelection)) {
3166
+ const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: true });
3167
+ if (rangeFromDOMSelection && Range.equals(rangeFromDOMSelection, selection)) {
3168
+ return;
3169
+ }
2838
3170
  }
2839
3171
  // prevent updating native selection when active element is void element
2840
3172
  if (isTargetInsideVoid(this.editor, activeElement)) {
@@ -2845,7 +3177,7 @@ class SlateEditable {
2845
3177
  // but Slate's value is not being updated through any operation
2846
3178
  // and thus it doesn't transform selection on its own
2847
3179
  if (selection && !AngularEditor.hasRange(this.editor, selection)) {
2848
- this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection);
3180
+ this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: false });
2849
3181
  return;
2850
3182
  }
2851
3183
  // Otherwise the DOM selection is out of sync, so update it.
@@ -2886,14 +3218,14 @@ class SlateEditable {
2886
3218
  }
2887
3219
  }
2888
3220
  onChange() {
2889
- this.forceFlush();
3221
+ this.forceRender();
2890
3222
  this.onChangeCallback(this.editor.children);
2891
3223
  }
2892
3224
  ngAfterViewChecked() { }
2893
3225
  ngDoCheck() { }
2894
- forceFlush() {
2895
- this.detectContext();
2896
- this.cdr.detectChanges();
3226
+ forceRender() {
3227
+ this.updateContext();
3228
+ this.listRender.update(this.editor.children, this.editor, this.context);
2897
3229
  // repair collaborative editing when Chinese input is interrupted by other users' cursors
2898
3230
  // when the DOMElement where the selection is located is removed
2899
3231
  // the compositionupdate and compositionend events will no longer be fired
@@ -2929,6 +3261,29 @@ class SlateEditable {
2929
3261
  }
2930
3262
  this.toNativeSelection();
2931
3263
  }
3264
+ render() {
3265
+ const changed = this.updateContext();
3266
+ if (changed) {
3267
+ this.listRender.update(this.editor.children, this.editor, this.context);
3268
+ }
3269
+ }
3270
+ updateContext() {
3271
+ const decorations = this.generateDecorations();
3272
+ if (this.context.selection !== this.editor.selection ||
3273
+ this.context.decorate !== this.decorate ||
3274
+ this.context.readonly !== this.readonly ||
3275
+ !isDecoratorRangeListEqual(this.context.decorations, decorations)) {
3276
+ this.context = {
3277
+ parent: this.editor,
3278
+ selection: this.editor.selection,
3279
+ decorations: decorations,
3280
+ decorate: this.decorate,
3281
+ readonly: this.readonly
3282
+ };
3283
+ return true;
3284
+ }
3285
+ return false;
3286
+ }
2932
3287
  initializeContext() {
2933
3288
  this.context = {
2934
3289
  parent: this.editor,
@@ -2946,24 +3301,13 @@ class SlateEditable {
2946
3301
  renderText: this.renderText,
2947
3302
  trackBy: this.trackBy,
2948
3303
  isStrictDecorate: this.isStrictDecorate,
2949
- templateComponent: this.templateComponent
3304
+ templateComponent: this.templateComponent,
3305
+ defaultElement: this.defaultElement,
3306
+ defaultText: this.defaultText,
3307
+ defaultVoidText: this.defaultVoidText,
3308
+ defaultLeaf: this.defaultLeaf
2950
3309
  };
2951
3310
  }
2952
- detectContext() {
2953
- const decorations = this.generateDecorations();
2954
- if (this.context.selection !== this.editor.selection ||
2955
- this.context.decorate !== this.decorate ||
2956
- this.context.readonly !== this.readonly ||
2957
- !isDecoratorRangeListEqual(this.context.decorations, decorations)) {
2958
- this.context = {
2959
- parent: this.editor,
2960
- selection: this.editor.selection,
2961
- decorations: decorations,
2962
- decorate: this.decorate,
2963
- readonly: this.readonly
2964
- };
2965
- }
2966
- }
2967
3311
  composePlaceholderDecorate(editor) {
2968
3312
  if (this.placeholderDecorate) {
2969
3313
  return this.placeholderDecorate(editor) || [];
@@ -3255,7 +3599,23 @@ class SlateEditable {
3255
3599
  const end = Editor.end(this.editor, path);
3256
3600
  const startVoid = Editor.void(this.editor, { at: start });
3257
3601
  const endVoid = Editor.void(this.editor, { at: end });
3258
- if (startVoid && endVoid && Path.equals(startVoid[1], endVoid[1])) {
3602
+ if (event.detail === TRIPLE_CLICK && path.length >= 1) {
3603
+ let blockPath = path;
3604
+ if (!(Element.isElement(node) && Editor.isBlock(this.editor, node))) {
3605
+ const block = Editor.above(this.editor, {
3606
+ match: n => Element.isElement(n) && Editor.isBlock(this.editor, n),
3607
+ at: path
3608
+ });
3609
+ blockPath = block?.[1] ?? path.slice(0, 1);
3610
+ }
3611
+ const range = Editor.range(this.editor, blockPath);
3612
+ Transforms.select(this.editor, range);
3613
+ return;
3614
+ }
3615
+ if (startVoid &&
3616
+ endVoid &&
3617
+ Path.equals(startVoid[1], endVoid[1]) &&
3618
+ !(AngularEditor.isBlockCardLeftCursor(this.editor) || AngularEditor.isBlockCardRightCursor(this.editor))) {
3259
3619
  const range = Editor.range(this.editor, start);
3260
3620
  Transforms.select(this.editor, range);
3261
3621
  }
@@ -3267,14 +3627,13 @@ class SlateEditable {
3267
3627
  // solve the problem of cross node Chinese input
3268
3628
  if (Range.isExpanded(selection)) {
3269
3629
  Editor.deleteFragment(this.editor);
3270
- this.forceFlush();
3630
+ this.forceRender();
3271
3631
  }
3272
3632
  }
3273
3633
  if (hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionStart)) {
3274
3634
  this.isComposing = true;
3275
3635
  }
3276
- this.detectContext();
3277
- this.cdr.detectChanges();
3636
+ this.render();
3278
3637
  }
3279
3638
  onDOMCompositionUpdate(event) {
3280
3639
  this.isDOMEventHandled(event, this.compositionUpdate);
@@ -3296,8 +3655,7 @@ class SlateEditable {
3296
3655
  // so we need avoid repeat isnertText by isComposing === true,
3297
3656
  this.isComposing = false;
3298
3657
  }
3299
- this.detectContext();
3300
- this.cdr.detectChanges();
3658
+ this.render();
3301
3659
  }
3302
3660
  onDOMCopy(event) {
3303
3661
  const window = AngularEditor.getWindow(this.editor);
@@ -3323,7 +3681,7 @@ class SlateEditable {
3323
3681
  // that drops are allowed. Editable content is droppable by
3324
3682
  // default, and calling `preventDefault` hides the cursor.
3325
3683
  const node = AngularEditor.toSlateNode(this.editor, event.target);
3326
- if (Editor.isVoid(this.editor, node)) {
3684
+ if (Element.isElement(node) && Editor.isVoid(this.editor, node)) {
3327
3685
  event.preventDefault();
3328
3686
  }
3329
3687
  }
@@ -3332,7 +3690,7 @@ class SlateEditable {
3332
3690
  if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3333
3691
  const node = AngularEditor.toSlateNode(this.editor, event.target);
3334
3692
  const path = AngularEditor.findPath(this.editor, node);
3335
- const voidMatch = Editor.isVoid(this.editor, node) || Editor.void(this.editor, { at: path, voids: true });
3693
+ const voidMatch = Element.isElement(node) && (Editor.isVoid(this.editor, node) || Editor.void(this.editor, { at: path, voids: true }));
3336
3694
  // If starting a drag on a void node, make sure it is selected
3337
3695
  // so that it shows up in the selection's fragment.
3338
3696
  if (voidMatch) {
@@ -3594,7 +3952,7 @@ class SlateEditable {
3594
3952
  const currentNode = Node.parent(editor, selection.anchor.path);
3595
3953
  if (Element.isElement(currentNode) &&
3596
3954
  Editor.isVoid(editor, currentNode) &&
3597
- Editor.isInline(editor, currentNode)) {
3955
+ (Editor.isInline(editor, currentNode) || Editor.isBlock(editor, currentNode))) {
3598
3956
  event.preventDefault();
3599
3957
  Editor.deleteBackward(editor, {
3600
3958
  unit: 'block'
@@ -3670,14 +4028,30 @@ class SlateEditable {
3670
4028
  this.destroy$.complete();
3671
4029
  EDITOR_TO_ON_CHANGE.delete(this.editor);
3672
4030
  }
3673
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateEditable, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); }
4031
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateEditable, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }, { token: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN }, { token: SLATE_DEFAULT_TEXT_COMPONENT_TOKEN }, { token: SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN }, { token: SLATE_DEFAULT_LEAF_COMPONENT_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
3674
4032
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateEditable, isStandalone: true, selector: "slate-editable", inputs: { editor: "editor", renderElement: "renderElement", renderLeaf: "renderLeaf", renderText: "renderText", decorate: "decorate", placeholderDecorate: "placeholderDecorate", scrollSelectionIntoView: "scrollSelectionIntoView", isStrictDecorate: "isStrictDecorate", trackBy: "trackBy", readonly: "readonly", placeholder: "placeholder", beforeInput: "beforeInput", blur: "blur", click: "click", compositionEnd: "compositionEnd", compositionUpdate: "compositionUpdate", compositionStart: "compositionStart", copy: "copy", cut: "cut", dragOver: "dragOver", dragStart: "dragStart", dragEnd: "dragEnd", drop: "drop", focus: "focus", keydown: "keydown", paste: "paste", spellCheck: "spellCheck", autoCorrect: "autoCorrect", autoCapitalize: "autoCapitalize" }, host: { properties: { "attr.contenteditable": "readonly ? undefined : true", "attr.role": "readonly ? undefined : 'textbox'", "attr.spellCheck": "!hasBeforeInputSupport ? false : spellCheck", "attr.autoCorrect": "!hasBeforeInputSupport ? 'false' : autoCorrect", "attr.autoCapitalize": "!hasBeforeInputSupport ? 'false' : autoCapitalize", "attr.data-slate-editor": "this.dataSlateEditor", "attr.data-slate-node": "this.dataSlateNode", "attr.data-gramm": "this.dataGramm" }, classAttribute: "slate-editable-container" }, providers: [
3675
4033
  {
3676
4034
  provide: NG_VALUE_ACCESSOR,
3677
4035
  useExisting: forwardRef(() => SlateEditable),
3678
4036
  multi: true
4037
+ },
4038
+ {
4039
+ provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
4040
+ useValue: SlateDefaultElement
4041
+ },
4042
+ {
4043
+ provide: SLATE_DEFAULT_TEXT_COMPONENT_TOKEN,
4044
+ useValue: SlateDefaultText
4045
+ },
4046
+ {
4047
+ provide: SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN,
4048
+ useValue: SlateVoidText
4049
+ },
4050
+ {
4051
+ provide: SLATE_DEFAULT_LEAF_COMPONENT_TOKEN,
4052
+ useValue: SlateDefaultLeaf
3679
4053
  }
3680
- ], viewQueries: [{ propertyName: "templateComponent", first: true, predicate: ["templateComponent"], descendants: true, static: true }, { propertyName: "templateElementRef", first: true, predicate: ["templateComponent"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<slate-children [children]=\"editor.children\" [context]=\"context\" [viewContext]=\"viewContext\"></slate-children>\n<slate-string-template #templateComponent></slate-string-template>\n", dependencies: [{ kind: "component", type: SlateChildren, selector: "slate-children", inputs: ["children", "context", "viewContext"] }, { kind: "component", type: SlateStringTemplate, selector: "slate-string-template" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4054
+ ], viewQueries: [{ propertyName: "templateComponent", first: true, predicate: ["templateComponent"], descendants: true, static: true }, { propertyName: "templateElementRef", first: true, predicate: ["templateComponent"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<slate-string-template #templateComponent></slate-string-template>\n", dependencies: [{ kind: "component", type: SlateStringTemplate, selector: "slate-string-template" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3681
4055
  }
3682
4056
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateEditable, decorators: [{
3683
4057
  type: Component,
@@ -3693,9 +4067,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
3693
4067
  provide: NG_VALUE_ACCESSOR,
3694
4068
  useExisting: forwardRef(() => SlateEditable),
3695
4069
  multi: true
4070
+ },
4071
+ {
4072
+ provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
4073
+ useValue: SlateDefaultElement
4074
+ },
4075
+ {
4076
+ provide: SLATE_DEFAULT_TEXT_COMPONENT_TOKEN,
4077
+ useValue: SlateDefaultText
4078
+ },
4079
+ {
4080
+ provide: SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN,
4081
+ useValue: SlateVoidText
4082
+ },
4083
+ {
4084
+ provide: SLATE_DEFAULT_LEAF_COMPONENT_TOKEN,
4085
+ useValue: SlateDefaultLeaf
3696
4086
  }
3697
- ], standalone: true, imports: [SlateChildren, SlateStringTemplate], template: "<slate-children [children]=\"editor.children\" [context]=\"context\" [viewContext]=\"viewContext\"></slate-children>\n<slate-string-template #templateComponent></slate-string-template>\n" }]
3698
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }], propDecorators: { editor: [{
4087
+ ], standalone: true, imports: [SlateChildren, SlateStringTemplate], template: "<slate-string-template #templateComponent></slate-string-template>\n" }]
4088
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }, { type: undefined, decorators: [{
4089
+ type: Inject,
4090
+ args: [SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN]
4091
+ }] }, { type: undefined, decorators: [{
4092
+ type: Inject,
4093
+ args: [SLATE_DEFAULT_TEXT_COMPONENT_TOKEN]
4094
+ }] }, { type: undefined, decorators: [{
4095
+ type: Inject,
4096
+ args: [SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN]
4097
+ }] }, { type: undefined, decorators: [{
4098
+ type: Inject,
4099
+ args: [SLATE_DEFAULT_LEAF_COMPONENT_TOKEN]
4100
+ }] }], propDecorators: { editor: [{
3699
4101
  type: Input
3700
4102
  }], renderElement: [{
3701
4103
  type: Input
@@ -3810,8 +4212,8 @@ const hasTarget = (editor, target) => {
3810
4212
  * Check if the target is inside void and in the editor.
3811
4213
  */
3812
4214
  const isTargetInsideVoid = (editor, target) => {
3813
- const slateNode = hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target);
3814
- return Editor.isVoid(editor, slateNode);
4215
+ const slateNode = hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target, { suppressThrow: true });
4216
+ return slateNode && Element.isElement(slateNode) && Editor.isVoid(editor, slateNode);
3815
4217
  };
3816
4218
  const hasStringTarget = (domSelection) => {
3817
4219
  return ((domSelection.anchorNode.parentElement.hasAttribute('data-slate-string') ||
@@ -3840,28 +4242,13 @@ const preventInsertFromComposition = (event, editor) => {
3840
4242
 
3841
4243
  class SlateElement extends BaseElementComponent {
3842
4244
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateElement, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3843
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateElement, isStandalone: true, selector: "[slateElement]", usesInheritance: true, ngImport: i0, template: '<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children><ng-content></ng-content>', isInline: true, dependencies: [{ kind: "component", type: SlateChildren, selector: "slate-children", inputs: ["children", "context", "viewContext"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4245
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateElement, isStandalone: true, selector: "[slateElement]", usesInheritance: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3844
4246
  }
3845
4247
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateElement, decorators: [{
3846
4248
  type: Component,
3847
4249
  args: [{
3848
4250
  selector: '[slateElement]',
3849
- template: '<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children><ng-content></ng-content>',
3850
- changeDetection: ChangeDetectionStrategy.OnPush,
3851
- standalone: true,
3852
- imports: [SlateChildren]
3853
- }]
3854
- }] });
3855
-
3856
- class SlateDefaultElement extends BaseElementComponent {
3857
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultElement, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3858
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: SlateDefaultElement, isStandalone: true, selector: "div[slateDefaultElement]", usesInheritance: true, ngImport: i0, template: `<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>`, isInline: true, dependencies: [{ kind: "component", type: SlateChildren, selector: "slate-children", inputs: ["children", "context", "viewContext"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3859
- }
3860
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateDefaultElement, decorators: [{
3861
- type: Component,
3862
- args: [{
3863
- selector: 'div[slateDefaultElement]',
3864
- template: `<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>`,
4251
+ template: '<ng-content></ng-content>',
3865
4252
  changeDetection: ChangeDetectionStrategy.OnPush,
3866
4253
  standalone: true,
3867
4254
  imports: [SlateChildren]
@@ -3878,18 +4265,12 @@ class SlateModule {
3878
4265
  SlateDefaultText,
3879
4266
  SlateString,
3880
4267
  SlateStringTemplate,
3881
- SlateDescendant,
3882
4268
  SlateChildren,
3883
4269
  SlateBlockCard,
3884
- SlateLeaf,
3885
4270
  SlateLeaves,
3886
4271
  SlateDefaultLeaf,
3887
- SlateDefaultString], exports: [SlateEditable,
3888
- SlateChildren,
3889
- SlateElement,
3890
- SlateLeaves,
3891
- SlateString,
3892
- SlateDefaultString] }); }
4272
+ SlateDefaultString,
4273
+ SlateChildrenOutlet], exports: [SlateEditable, SlateChildren, SlateChildrenOutlet, SlateElement, SlateLeaves, SlateString, SlateDefaultString] }); }
3893
4274
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: SlateModule, providers: [
3894
4275
  {
3895
4276
  provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
@@ -3909,22 +4290,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
3909
4290
  SlateDefaultText,
3910
4291
  SlateString,
3911
4292
  SlateStringTemplate,
3912
- SlateDescendant,
3913
4293
  SlateChildren,
3914
4294
  SlateBlockCard,
3915
- SlateLeaf,
3916
4295
  SlateLeaves,
3917
4296
  SlateDefaultLeaf,
3918
- SlateDefaultString
3919
- ],
3920
- exports: [
3921
- SlateEditable,
3922
- SlateChildren,
3923
- SlateElement,
3924
- SlateLeaves,
3925
- SlateString,
3926
- SlateDefaultString
4297
+ SlateDefaultString,
4298
+ SlateChildrenOutlet
3927
4299
  ],
4300
+ exports: [SlateEditable, SlateChildren, SlateChildrenOutlet, SlateElement, SlateLeaves, SlateString, SlateDefaultString],
3928
4301
  providers: [
3929
4302
  {
3930
4303
  provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
@@ -3942,5 +4315,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
3942
4315
  * Generated bundle index. Do not edit.
3943
4316
  */
3944
4317
 
3945
- export { AngularEditor, BaseComponent, BaseElementComponent, BaseLeafComponent, BaseTextComponent, DOMComment, DOMElement, DOMNode, DOMRange, DOMSelection, DOMStaticRange, DOMText, EDITOR_TO_ELEMENT, EDITOR_TO_ON_CHANGE, EDITOR_TO_PLACEHOLDER, EDITOR_TO_WINDOW, ELEMENT_TO_COMPONENT, ELEMENT_TO_NODE, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_CLICKING, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_FOCUSED, IS_IOS, IS_QQBROWSER, IS_READONLY, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, KEY_TO_ELEMENT, Key, NODE_TO_ELEMENT, NODE_TO_INDEX, NODE_TO_KEY, NODE_TO_PARENT, PLACEHOLDER_SYMBOL, SlateChildren, SlateDefaultString, SlateEditable, SlateElement, SlateErrorCode, SlateLeaves, SlateModule, SlateString, check, defaultScrollSelectionIntoView, getCardTargetAttribute, getClipboardData, getDefaultView, getEditableChild, getEditableChildAndIndex, getPlainText, getSlateFragmentAttribute, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hasEditableTarget, hasShadowRoot, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isComponentType, isDOMComment, isDOMElement, isDOMNode, isDOMSelection, isDOMText, isDecoratorRangeListEqual, isPlainTextOnlyPaste, isTemplateRef, isValid, normalize, normalizeDOMPoint, shallowCompare, withAngular };
4318
+ export { AngularEditor, BaseComponent, BaseElementComponent, BaseLeafComponent, BaseTextComponent, DOMComment, DOMElement, DOMNode, DOMRange, DOMSelection, DOMStaticRange, DOMText, EDITOR_TO_ELEMENT, EDITOR_TO_ON_CHANGE, EDITOR_TO_PLACEHOLDER, EDITOR_TO_WINDOW, ELEMENT_TO_COMPONENT, ELEMENT_TO_NODE, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_CLICKING, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_FOCUSED, IS_IOS, IS_QQBROWSER, IS_READONLY, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, KEY_TO_ELEMENT, Key, NODE_TO_ELEMENT, NODE_TO_INDEX, NODE_TO_KEY, NODE_TO_PARENT, PLACEHOLDER_SYMBOL, SlateChildren, SlateChildrenOutlet, SlateDefaultString, SlateEditable, SlateElement, SlateErrorCode, SlateLeaves, SlateModule, SlateString, check, createThrottleRAF, defaultScrollSelectionIntoView, getCardTargetAttribute, getClipboardData, getDefaultView, getEditableChild, getEditableChildAndIndex, getPlainText, getSlateFragmentAttribute, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hasEditableTarget, hasShadowRoot, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isComponentType, isDOMComment, isDOMElement, isDOMNode, isDOMSelection, isDOMText, isDecoratorRangeListEqual, isEmpty, isPlainTextOnlyPaste, isTemplateRef, isValid, normalize, normalizeDOMPoint, shallowCompare, withAngular };
3946
4319
  //# sourceMappingURL=slate-angular.mjs.map