slate-angular 19.3.0 → 19.4.0-next.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 (38) hide show
  1. package/components/editable/editable.component.d.ts +2 -10
  2. package/components/element.flavour.d.ts +7 -0
  3. package/components/leaf/leaf.flavour.d.ts +8 -0
  4. package/components/string/string-render.d.ts +39 -0
  5. package/components/string/string.component.d.ts +4 -26
  6. package/components/text/default-text.flavour.d.ts +12 -0
  7. package/fesm2022/slate-angular.mjs +1110 -1172
  8. package/fesm2022/slate-angular.mjs.map +1 -1
  9. package/module.d.ts +4 -13
  10. package/package.json +1 -1
  11. package/public-api.d.ts +3 -5
  12. package/types/view.d.ts +2 -1
  13. package/utils/view.d.ts +1 -0
  14. package/utils/weak-maps.d.ts +2 -1
  15. package/view/base.d.ts +19 -17
  16. package/view/context.d.ts +1 -8
  17. package/view/flavour/base.d.ts +19 -0
  18. package/view/flavour/element.d.ts +27 -0
  19. package/view/flavour/index.d.ts +5 -0
  20. package/view/flavour/leaf.d.ts +17 -0
  21. package/view/flavour/ref.d.ts +5 -0
  22. package/view/flavour/text.d.ts +16 -0
  23. package/view/render/list-render.d.ts +2 -1
  24. package/view/render/utils.d.ts +5 -4
  25. package/components/children/children.component.d.ts +0 -11
  26. package/components/element/default-element.component.d.ts +0 -6
  27. package/components/element/default-element.component.token.d.ts +0 -4
  28. package/components/element/element.component.d.ts +0 -6
  29. package/components/leaf/default-leaf.component.d.ts +0 -9
  30. package/components/leaf/token.d.ts +0 -4
  31. package/components/leaves/leaves.component.d.ts +0 -12
  32. package/components/string/default-string.component.d.ts +0 -20
  33. package/components/string/template.component.d.ts +0 -9
  34. package/components/text/default-text.component.d.ts +0 -6
  35. package/components/text/token.d.ts +0 -5
  36. package/components/text/void-text.component.d.ts +0 -9
  37. package/view/container-item.d.ts +0 -32
  38. package/view/container.d.ts +0 -18
@@ -2,7 +2,7 @@ import { Editor, Range, Element, Transforms, Text as Text$1, Node, Path } from '
2
2
  import { EDITOR_TO_ELEMENT, NODE_TO_ELEMENT, DOMEditor, normalizeDOMPoint, isDOMSelection, IS_CHROME as IS_CHROME$1, hasShadowRoot, isDOMElement, NODE_TO_PARENT, NODE_TO_INDEX, IS_FOCUSED, isDOMNode, withDOM, NODE_TO_KEY, ELEMENT_TO_NODE, getDefaultView, EDITOR_TO_WINDOW, IS_READ_ONLY, EDITOR_TO_ON_CHANGE, TRIPLE_CLICK, isPlainTextOnlyPaste } from 'slate-dom';
3
3
  import { isKeyHotkey } from 'is-hotkey';
4
4
  import * as i0 from '@angular/core';
5
- import { TemplateRef, ViewChild, ChangeDetectionStrategy, Component, InjectionToken, ComponentRef, IterableDiffers, inject, ElementRef, ChangeDetectorRef, Input, Directive, HostBinding, ViewContainerRef, forwardRef, Inject, NgModule } from '@angular/core';
5
+ import { TemplateRef, ViewChild, Component, ComponentRef, IterableDiffers, inject, ViewContainerRef, forwardRef, HostBinding, Input, ChangeDetectionStrategy, NgModule, ElementRef, ChangeDetectorRef, Directive } from '@angular/core';
6
6
  import { direction } from 'direction';
7
7
  import scrollIntoView from 'scroll-into-view-if-needed';
8
8
  import { Subject } from 'rxjs';
@@ -572,6 +572,9 @@ function isTemplateRef(value) {
572
572
  function isComponentType(value) {
573
573
  return !isTemplateRef(value);
574
574
  }
575
+ function isFlavourType(value) {
576
+ return value && value.isFlavour === true;
577
+ }
575
578
 
576
579
  const shallowCompare = (obj1, obj2) => Object.keys(obj1).length === Object.keys(obj2).length &&
577
580
  Object.keys(obj1).every(key => obj2.hasOwnProperty(key) && obj1[key] === obj2[key]);
@@ -1477,24 +1480,6 @@ var SlateErrorCode;
1477
1480
  SlateErrorCode[SlateErrorCode["InvalidValueError"] = 4100] = "InvalidValueError";
1478
1481
  })(SlateErrorCode || (SlateErrorCode = {}));
1479
1482
 
1480
- class SlateStringTemplate {
1481
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateStringTemplate, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1482
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateStringTemplate, isStandalone: true, selector: "slate-string-template", viewQueries: [{ propertyName: "compatibleStringTemplate", first: true, predicate: ["compatibleStringTemplate"], descendants: true, read: TemplateRef, static: true }, { propertyName: "voidStringTemplate", first: true, predicate: ["voidStringTemplate"], descendants: true, read: TemplateRef, static: true }, { propertyName: "emptyTextTemplate", first: true, predicate: ["emptyTextTemplate"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<ng-template #compatibleStringTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <!-- Compatible with Chinese input in Chrome with \\n -->\n <span editable-text data-slate-string=\"true\"\n >{{ context.text }}<span data-slate-zero-width>{{ '\\uFEFF' }}</span></span\n >\n</ng-template>\n<ng-template #voidStringTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <span editable-text data-slate-zero-width=\"z\" attr.data-slate-length=\"{{ context.elementStringLength }}\">{{ '\\uFEFF' }}</span>\n</ng-template>\n<ng-template #emptyTextTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <span editable-text data-slate-zero-width=\"z\" data-slate-length=\"0\">{{ '\\uFEFF' }}</span>\n</ng-template>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1483
- }
1484
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateStringTemplate, decorators: [{
1485
- type: Component,
1486
- args: [{ selector: 'slate-string-template', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<ng-template #compatibleStringTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <!-- Compatible with Chinese input in Chrome with \\n -->\n <span editable-text data-slate-string=\"true\"\n >{{ context.text }}<span data-slate-zero-width>{{ '\\uFEFF' }}</span></span\n >\n</ng-template>\n<ng-template #voidStringTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <span editable-text data-slate-zero-width=\"z\" attr.data-slate-length=\"{{ context.elementStringLength }}\">{{ '\\uFEFF' }}</span>\n</ng-template>\n<ng-template #emptyTextTemplate let-context=\"context\" let-viewContext=\"viewContext\">\n <span editable-text data-slate-zero-width=\"z\" data-slate-length=\"0\">{{ '\\uFEFF' }}</span>\n</ng-template>\n" }]
1487
- }], propDecorators: { compatibleStringTemplate: [{
1488
- type: ViewChild,
1489
- args: ['compatibleStringTemplate', { read: TemplateRef, static: true }]
1490
- }], voidStringTemplate: [{
1491
- type: ViewChild,
1492
- args: ['voidStringTemplate', { read: TemplateRef, static: true }]
1493
- }], emptyTextTemplate: [{
1494
- type: ViewChild,
1495
- args: ['emptyTextTemplate', { read: TemplateRef, static: true }]
1496
- }] } });
1497
-
1498
1483
  function restoreDom(editor, execute) {
1499
1484
  const editable = EDITOR_TO_ELEMENT.get(editor);
1500
1485
  let observer = new MutationObserver(mutations => {
@@ -1527,45 +1512,53 @@ function restoreDom(editor, execute) {
1527
1512
  }, 0);
1528
1513
  }
1529
1514
 
1530
- const SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN = new InjectionToken('slate-default-element-token');
1531
-
1532
- const SLATE_DEFAULT_TEXT_COMPONENT_TOKEN = new InjectionToken('slate-default-text-token');
1533
- const SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN = new InjectionToken('slate-default-void-text-token');
1534
-
1535
- class SlateChildrenOutlet {
1515
+ class SlateBlockCard {
1516
+ get nativeElement() {
1517
+ return this.elementRef.nativeElement;
1518
+ }
1519
+ get centerContainerElement() {
1520
+ return this.centerContianer.nativeElement;
1521
+ }
1536
1522
  constructor(elementRef) {
1537
1523
  this.elementRef = elementRef;
1538
1524
  }
1539
- getNativeElement() {
1540
- return this.elementRef.nativeElement;
1525
+ ngOnInit() {
1526
+ this.nativeElement.classList.add(`slate-block-card`);
1541
1527
  }
1542
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildrenOutlet, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1543
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateChildrenOutlet, isStandalone: true, selector: "slate-children-outlet", ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1528
+ append() {
1529
+ this.centerRootNodes.forEach(rootNode => !this.centerContainerElement.contains(rootNode) && this.centerContainerElement.appendChild(rootNode));
1530
+ }
1531
+ initializeCenter(rootNodes) {
1532
+ this.centerRootNodes = rootNodes;
1533
+ this.append();
1534
+ }
1535
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateBlockCard, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1536
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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" }); }
1544
1537
  }
1545
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildrenOutlet, decorators: [{
1538
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateBlockCard, decorators: [{
1546
1539
  type: Component,
1547
- args: [{
1548
- selector: 'slate-children-outlet',
1549
- template: ``,
1550
- changeDetection: ChangeDetectionStrategy.OnPush,
1551
- standalone: true
1552
- }]
1553
- }], ctorParameters: () => [{ type: i0.ElementRef }] });
1540
+ args: [{ selector: 'slate-block-card, [slateBlockCard]', standalone: true, 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" }]
1541
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { centerContianer: [{
1542
+ type: ViewChild,
1543
+ args: ['centerContianer', { static: true }]
1544
+ }] } });
1554
1545
 
1555
- function hasBeforeContextChange(value) {
1556
- if (value.beforeContextChange) {
1557
- return true;
1558
- }
1559
- return false;
1560
- }
1561
- function hasAfterContextChange(value) {
1562
- if (value.afterContextChange) {
1563
- return true;
1546
+ class FlavourRef {
1547
+ destroy() {
1548
+ this.instance.onDestroy();
1564
1549
  }
1565
- return false;
1566
1550
  }
1567
1551
 
1568
- function createEmbeddedViewOrComponent(viewType, context, viewContext, viewContainerRef) {
1552
+ function createEmbeddedViewOrComponentOrFlavour(viewType, context, viewContext, viewContainerRef) {
1553
+ if (isFlavourType(viewType)) {
1554
+ const flavourRef = new FlavourRef();
1555
+ flavourRef.instance = new viewType();
1556
+ flavourRef.instance.context = context;
1557
+ flavourRef.instance.viewContext = viewContext;
1558
+ flavourRef.instance.viewContainerRef = viewContainerRef;
1559
+ flavourRef.instance.onInit();
1560
+ return flavourRef;
1561
+ }
1569
1562
  if (isTemplateRef(viewType)) {
1570
1563
  const embeddedViewContext = {
1571
1564
  context,
@@ -1586,6 +1579,10 @@ function createEmbeddedViewOrComponent(viewType, context, viewContext, viewConta
1586
1579
  }
1587
1580
  }
1588
1581
  function updateContext(view, newContext, viewContext) {
1582
+ if (view instanceof FlavourRef) {
1583
+ view.instance.context = newContext;
1584
+ return;
1585
+ }
1589
1586
  if (view instanceof ComponentRef) {
1590
1587
  view.instance.context = newContext;
1591
1588
  }
@@ -1615,6 +1612,9 @@ function getRootNodes(ref, blockCard) {
1615
1612
  if (blockCard) {
1616
1613
  return [blockCard.instance.nativeElement];
1617
1614
  }
1615
+ if (ref instanceof FlavourRef) {
1616
+ return [ref.instance.nativeElement];
1617
+ }
1618
1618
  if (ref instanceof ComponentRef) {
1619
1619
  ref.hostView.rootNodes.forEach(ele => {
1620
1620
  if (!(ele instanceof HTMLElement)) {
@@ -1670,498 +1670,166 @@ function mountOnItemChange(index, item, views, blockCards, outletParent, firstRo
1670
1670
  }
1671
1671
  }
1672
1672
 
1673
- class LeavesRender {
1674
- constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
1675
- this.viewContext = viewContext;
1676
- this.viewContainerRef = viewContainerRef;
1677
- this.getOutletParent = getOutletParent;
1678
- this.getOutletElement = getOutletElement;
1679
- this.views = [];
1680
- this.contexts = [];
1681
- this.viewTypes = [];
1673
+ function hasBeforeContextChange(value) {
1674
+ if (value.beforeContextChange) {
1675
+ return true;
1682
1676
  }
1683
- initialize(context) {
1684
- const { decoratedLeaves, contexts } = this.getLeaves(context);
1685
- this.decoratedLeaves = decoratedLeaves;
1686
- this.contexts = contexts;
1687
- this.decoratedLeaves.forEach((leaf, index) => {
1688
- const context = getContext$1(index, this.contexts);
1689
- const viewType = getViewType$1(context, this.viewContext);
1690
- const view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1691
- this.views.push(view);
1692
- this.contexts.push(context);
1693
- this.viewTypes.push(viewType);
1694
- });
1695
- mount(this.views, null, this.getOutletParent(), this.getOutletElement());
1696
- const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
1697
- this.differ = newDiffers.find(this.decoratedLeaves).create(trackBy$1(this.viewContext));
1698
- this.differ.diff(this.decoratedLeaves);
1677
+ return false;
1678
+ }
1679
+ function hasAfterContextChange(value) {
1680
+ if (value.afterContextChange) {
1681
+ return true;
1699
1682
  }
1700
- update(context) {
1701
- const { decoratedLeaves, contexts } = this.getLeaves(context);
1702
- const outletParent = this.getOutletParent();
1703
- const diffResult = this.differ.diff(decoratedLeaves);
1704
- if (diffResult) {
1705
- let firstRootNode = getRootNodes(this.views[0])[0];
1706
- const newContexts = [];
1707
- const newViewTypes = [];
1708
- const newViews = [];
1709
- diffResult.forEachItem(record => {
1710
- let context = getContext$1(record.currentIndex, contexts);
1711
- const viewType = getViewType$1(context, this.viewContext);
1712
- newViewTypes.push(viewType);
1713
- let view;
1714
- if (record.previousIndex === null) {
1715
- view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1716
- newContexts.push(context);
1717
- newViews.push(view);
1718
- mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
1719
- }
1720
- else {
1721
- const previousView = this.views[record.previousIndex];
1722
- const previousViewType = this.viewTypes[record.previousIndex];
1723
- if (previousViewType !== viewType) {
1724
- view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1725
- const firstRootNode = getRootNodes(previousView, null)[0];
1726
- const newRootNodes = getRootNodes(view, null);
1727
- firstRootNode.replaceWith(...newRootNodes);
1728
- previousView.destroy();
1729
- }
1730
- else {
1731
- view = previousView;
1732
- updateContext(previousView, context, this.viewContext);
1733
- }
1734
- newContexts.push(context);
1735
- newViews.push(view);
1736
- }
1737
- });
1738
- diffResult.forEachRemovedItem(record => {
1739
- const view = this.views[record.previousIndex];
1740
- view.destroy();
1741
- });
1742
- diffResult.forEachMovedItem(record => {
1743
- mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
1744
- });
1745
- this.viewTypes = newViewTypes;
1746
- this.views = newViews;
1747
- this.contexts = newContexts;
1748
- this.decoratedLeaves = decoratedLeaves;
1683
+ return false;
1684
+ }
1685
+
1686
+ class BaseFlavour {
1687
+ constructor() {
1688
+ this.initialized = false;
1689
+ }
1690
+ static { this.isFlavour = true; }
1691
+ set context(value) {
1692
+ if (hasBeforeContextChange(this)) {
1693
+ this.beforeContextChange(value);
1694
+ }
1695
+ this._context = value;
1696
+ this.onContextChange();
1697
+ if (hasAfterContextChange(this)) {
1698
+ this.afterContextChange();
1749
1699
  }
1750
1700
  }
1751
- getLeaves(context) {
1752
- const decoratedLeaves = Text$1.decorations(context.text, context.decorations);
1753
- const contexts = decoratedLeaves.map((decoratedLeaf, index) => {
1754
- return {
1755
- leaf: decoratedLeaf.leaf,
1756
- leafPosition: decoratedLeaf.position,
1757
- text: context.text,
1758
- parent: context.parent,
1759
- index,
1760
- isLast: context.isLast && index === decoratedLeaves.length - 1
1761
- };
1762
- });
1763
- return { decoratedLeaves, contexts };
1701
+ get context() {
1702
+ return this._context;
1703
+ }
1704
+ get editor() {
1705
+ return this.viewContext && this.viewContext.editor;
1764
1706
  }
1765
- }
1766
- function getContext$1(index, leafContexts) {
1767
- return leafContexts[index];
1768
- }
1769
- function getViewType$1(leafContext, viewContext) {
1770
- return (viewContext.renderLeaf && viewContext.renderLeaf(leafContext.leaf)) || viewContext.defaultLeaf;
1771
- }
1772
- function trackBy$1(viewContext) {
1773
- return (index, node) => {
1774
- return index;
1775
- };
1776
1707
  }
1777
1708
 
1778
- class SlateBlockCard {
1779
- get nativeElement() {
1780
- return this.elementRef.nativeElement;
1709
+ class BaseElementFlavour extends BaseFlavour {
1710
+ constructor() {
1711
+ super(...arguments);
1712
+ this.getOutletParent = () => {
1713
+ return this.nativeElement;
1714
+ };
1715
+ this.getOutletElement = () => {
1716
+ return this.nativeElement.querySelector('.children-outlet');
1717
+ };
1781
1718
  }
1782
- get centerContainerElement() {
1783
- return this.centerContianer.nativeElement;
1719
+ get element() {
1720
+ return this._context && this._context.element;
1784
1721
  }
1785
- constructor(elementRef) {
1786
- this.elementRef = elementRef;
1722
+ get selection() {
1723
+ return this._context && this._context.selection;
1787
1724
  }
1788
- ngOnInit() {
1789
- this.nativeElement.classList.add(`slate-block-card`);
1725
+ get decorations() {
1726
+ return this._context && this._context.decorations;
1790
1727
  }
1791
- append() {
1792
- this.centerRootNodes.forEach(rootNode => !this.centerContainerElement.contains(rootNode) && this.centerContainerElement.appendChild(rootNode));
1728
+ get children() {
1729
+ return this._context && this._context.element.children;
1793
1730
  }
1794
- initializeCenter(rootNodes) {
1795
- this.centerRootNodes = rootNodes;
1796
- this.append();
1731
+ get isCollapsed() {
1732
+ return this.selection && Range.isCollapsed(this.selection);
1797
1733
  }
1798
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateBlockCard, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1799
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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" }); }
1800
- }
1801
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateBlockCard, decorators: [{
1802
- type: Component,
1803
- args: [{ selector: 'slate-block-card, [slateBlockCard]', standalone: true, 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" }]
1804
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { centerContianer: [{
1805
- type: ViewChild,
1806
- args: ['centerContianer', { static: true }]
1807
- }] } });
1808
-
1809
- class ListRender {
1810
- constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
1811
- this.viewContext = viewContext;
1812
- this.viewContainerRef = viewContainerRef;
1813
- this.getOutletParent = getOutletParent;
1814
- this.getOutletElement = getOutletElement;
1815
- this.views = [];
1816
- // private addedViews: (EmbeddedViewRef<any> | ComponentRef<any>)[] = [];
1817
- this.blockCards = [];
1818
- this.contexts = [];
1819
- this.viewTypes = [];
1820
- this.differ = null;
1821
- this.initialized = false;
1734
+ get isCollapsedAndNonReadonly() {
1735
+ return this.selection && Range.isCollapsed(this.selection) && !this.readonly;
1822
1736
  }
1823
- initialize(children, parent, childrenContext) {
1737
+ get readonly() {
1738
+ return this._context && this._context.readonly;
1739
+ }
1740
+ onInit() {
1824
1741
  this.initialized = true;
1825
- this.children = children;
1826
- const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
1827
- children.forEach((descendant, index) => {
1828
- NODE_TO_INDEX.set(descendant, index);
1829
- NODE_TO_PARENT.set(descendant, parent);
1830
- const context = getContext(index, descendant, parentPath, childrenContext, this.viewContext);
1831
- const viewType = getViewType(descendant, parent, this.viewContext);
1832
- const view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1833
- const blockCard = createBlockCard(descendant, view, this.viewContainerRef, this.viewContext);
1834
- this.views.push(view);
1835
- this.contexts.push(context);
1836
- this.viewTypes.push(viewType);
1837
- this.blockCards.push(blockCard);
1838
- });
1839
- mount(this.views, this.blockCards, this.getOutletParent(), this.getOutletElement());
1840
- const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
1841
- this.differ = newDiffers.find(children).create(trackBy(this.viewContext));
1842
- this.differ.diff(children);
1843
- if (parent === this.viewContext.editor) {
1844
- executeAfterViewInit(this.viewContext.editor);
1845
- }
1846
- }
1847
- update(children, parent, childrenContext) {
1848
- if (!this.initialized || this.children.length === 0) {
1849
- this.initialize(children, parent, childrenContext);
1850
- return;
1851
- }
1852
- if (!this.differ) {
1853
- throw new Error('Exception: Can not find differ ');
1854
- }
1855
- const outletParent = this.getOutletParent();
1856
- const diffResult = this.differ.diff(children);
1857
- const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
1858
- if (diffResult) {
1859
- let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
1860
- const newContexts = [];
1861
- const newViewTypes = [];
1862
- const newViews = [];
1863
- const newBlockCards = [];
1864
- diffResult.forEachItem(record => {
1865
- NODE_TO_INDEX.set(record.item, record.currentIndex);
1866
- NODE_TO_PARENT.set(record.item, parent);
1867
- let context = getContext(record.currentIndex, record.item, parentPath, childrenContext, this.viewContext);
1868
- const viewType = getViewType(record.item, parent, this.viewContext);
1869
- newViewTypes.push(viewType);
1870
- let view;
1871
- let blockCard;
1872
- if (record.previousIndex === null) {
1873
- view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1874
- blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
1875
- newContexts.push(context);
1876
- newViews.push(view);
1877
- newBlockCards.push(blockCard);
1878
- mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
1879
- }
1880
- else {
1881
- const previousView = this.views[record.previousIndex];
1882
- const previousViewType = this.viewTypes[record.previousIndex];
1883
- const previousContext = this.contexts[record.previousIndex];
1884
- const previousBlockCard = this.blockCards[record.previousIndex];
1885
- if (previousViewType !== viewType) {
1886
- view = createEmbeddedViewOrComponent(viewType, context, this.viewContext, this.viewContainerRef);
1887
- blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
1888
- const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
1889
- const newRootNodes = getRootNodes(view, blockCard);
1890
- firstRootNode.replaceWith(...newRootNodes);
1891
- previousView.destroy();
1892
- previousBlockCard?.destroy();
1893
- }
1894
- else {
1895
- view = previousView;
1896
- blockCard = previousBlockCard;
1897
- if (memoizedContext(this.viewContext, record.item, previousContext, context)) {
1898
- context = previousContext;
1899
- }
1900
- else {
1901
- updateContext(previousView, context, this.viewContext);
1902
- }
1903
- }
1904
- newContexts.push(context);
1905
- newViews.push(view);
1906
- newBlockCards.push(blockCard);
1907
- }
1908
- });
1909
- diffResult.forEachOperation(record => {
1910
- // removed
1911
- if (record.currentIndex === null) {
1912
- const view = this.views[record.previousIndex];
1913
- const blockCard = this.blockCards[record.previousIndex];
1914
- view.destroy();
1915
- blockCard?.destroy();
1916
- }
1917
- // moved
1918
- if (record.previousIndex !== null && record.currentIndex !== null) {
1919
- mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
1920
- // Solve the block-card DOMElement loss when moving nodes
1921
- newBlockCards[record.currentIndex]?.instance.append();
1922
- }
1923
- });
1924
- this.viewTypes = newViewTypes;
1925
- this.views = newViews;
1926
- this.contexts = newContexts;
1927
- this.children = children;
1928
- this.blockCards = newBlockCards;
1929
- if (parent === this.viewContext.editor) {
1930
- executeAfterViewInit(this.viewContext.editor);
1931
- }
1742
+ this.render();
1743
+ for (const key in this._context.attributes) {
1744
+ this.nativeElement.setAttribute(key, this._context.attributes[key]);
1932
1745
  }
1933
- else {
1934
- const newContexts = [];
1935
- this.children.forEach((child, index) => {
1936
- NODE_TO_INDEX.set(child, index);
1937
- NODE_TO_PARENT.set(child, parent);
1938
- let context = getContext(index, child, parentPath, childrenContext, this.viewContext);
1939
- const previousContext = this.contexts[index];
1940
- if (memoizedContext(this.viewContext, child, previousContext, context)) {
1941
- context = previousContext;
1942
- }
1943
- else {
1944
- updateContext(this.views[index], context, this.viewContext);
1945
- }
1946
- newContexts.push(context);
1947
- });
1948
- this.contexts = newContexts;
1746
+ this.updateWeakMap();
1747
+ this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
1748
+ if (this.editor.isExpanded(this.element)) {
1749
+ this.listRender.initialize(this.children, this.element, this.childrenContext);
1949
1750
  }
1950
- }
1951
- destroy() {
1952
- this.children.forEach((element, index) => {
1953
- if (this.views[index]) {
1954
- this.views[index].destroy();
1955
- }
1956
- if (this.blockCards[index]) {
1957
- this.blockCards[index].destroy();
1958
- }
1751
+ addAfterViewInitQueue(this.editor, () => {
1752
+ this.afterViewInit();
1959
1753
  });
1960
- this.views = [];
1961
- this.blockCards = [];
1962
- this.contexts = [];
1963
- this.viewTypes = [];
1964
- this.initialized = false;
1965
- this.differ = null;
1966
1754
  }
1967
- }
1968
- function getContext(index, item, parentPath, childrenContext, viewContext) {
1969
- if (Element.isElement(item)) {
1970
- const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
1971
- const key = AngularEditor.findKey(viewContext.editor, item);
1972
- const isInline = viewContext.editor.isInline(item);
1973
- const isVoid = viewContext.editor.isVoid(item);
1974
- const elementContext = {
1975
- element: item,
1976
- ...computedContext,
1977
- attributes: {
1978
- 'data-slate-node': 'element',
1979
- 'data-slate-key': key.id
1980
- },
1981
- decorate: childrenContext.decorate,
1982
- readonly: childrenContext.readonly
1983
- };
1984
- if (isInline) {
1985
- elementContext.attributes['data-slate-inline'] = true;
1755
+ afterViewInit() {
1756
+ if (this._context.contentEditable !== undefined) {
1757
+ this.nativeElement.setAttribute('contenteditable', this._context.contentEditable + '');
1986
1758
  }
1987
- if (isVoid) {
1988
- elementContext.attributes['data-slate-void'] = true;
1759
+ }
1760
+ updateWeakMap() {
1761
+ NODE_TO_ELEMENT.set(this.element, this.nativeElement);
1762
+ ELEMENT_TO_NODE.set(this.nativeElement, this.element);
1763
+ ELEMENT_TO_COMPONENT.set(this.element, this);
1764
+ }
1765
+ onDestroy() {
1766
+ if (NODE_TO_ELEMENT.get(this.element) === this.nativeElement) {
1767
+ NODE_TO_ELEMENT.delete(this.element);
1989
1768
  }
1990
- // add contentEditable for block element only to avoid chinese input be broken
1991
- if (isVoid && !isInline) {
1992
- elementContext.contentEditable = false;
1769
+ ELEMENT_TO_NODE.delete(this.nativeElement);
1770
+ if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
1771
+ ELEMENT_TO_COMPONENT.delete(this.element);
1993
1772
  }
1994
- return elementContext;
1773
+ this.nativeElement?.remove();
1995
1774
  }
1996
- else {
1997
- const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
1998
- const isLeafBlock = AngularEditor.isLeafBlock(viewContext.editor, childrenContext.parent);
1999
- const textContext = {
2000
- decorations: computedContext.decorations,
2001
- isLast: isLeafBlock && index === childrenContext.parent.children.length - 1,
2002
- parent: childrenContext.parent,
2003
- text: item
2004
- };
2005
- return textContext;
1775
+ onContextChange() {
1776
+ this.childrenContext = this.getChildrenContext();
1777
+ if (!this.initialized) {
1778
+ return;
1779
+ }
1780
+ this.rerender();
1781
+ this.updateWeakMap();
1782
+ this.updateChildrenView();
2006
1783
  }
2007
- }
2008
- function getCommonContext(index, item, parentPath, viewContext, childrenContext) {
2009
- const p = parentPath.concat(index);
2010
- try {
2011
- const ds = childrenContext.decorate([item, p]);
2012
- // [list-render] performance optimization: reduce the number of calls to the `Editor.range(viewContext.editor, p)` method
2013
- if (childrenContext.selection || childrenContext.decorations.length > 0) {
2014
- const range = Editor.range(viewContext.editor, p);
2015
- const sel = childrenContext.selection && Range.intersection(range, childrenContext.selection);
2016
- for (const dec of childrenContext.decorations) {
2017
- const d = Range.intersection(dec, range);
2018
- if (d) {
2019
- ds.push(d);
2020
- }
2021
- }
2022
- return { selection: sel, decorations: ds };
1784
+ updateChildrenView() {
1785
+ if (this.editor.isExpanded(this.element)) {
1786
+ this.listRender.update(this.children, this.element, this.childrenContext);
2023
1787
  }
2024
1788
  else {
2025
- return { selection: null, decorations: ds };
1789
+ if (this.listRender.initialized) {
1790
+ this.listRender.destroy();
1791
+ }
2026
1792
  }
2027
1793
  }
2028
- catch (error) {
2029
- viewContext.editor.onError({
2030
- code: SlateErrorCode.GetStartPointError,
2031
- nativeError: error
2032
- });
2033
- return { selection: null, decorations: [] };
1794
+ getChildrenContext() {
1795
+ return {
1796
+ parent: this._context.element,
1797
+ selection: this._context.selection,
1798
+ decorations: this._context.decorations,
1799
+ decorate: this._context.decorate,
1800
+ readonly: this._context.readonly
1801
+ };
2034
1802
  }
2035
1803
  }
2036
- function getViewType(item, parent, viewContext) {
2037
- if (Element.isElement(item)) {
2038
- return (viewContext.renderElement && viewContext.renderElement(item)) || viewContext.defaultElement;
1804
+
1805
+ class DefaultElementFlavour extends BaseElementFlavour {
1806
+ render() {
1807
+ const nativeElement = document.createElement('div');
1808
+ this.nativeElement = nativeElement;
2039
1809
  }
2040
- else {
2041
- const isVoid = viewContext.editor.isVoid(parent);
2042
- return isVoid ? viewContext.defaultVoidText : (viewContext.renderText && viewContext.renderText(item)) || viewContext.defaultText;
1810
+ rerender() {
1811
+ // No-op
2043
1812
  }
2044
1813
  }
2045
- function createBlockCard(item, view, viewContainerRef, viewContext) {
2046
- const isBlockCard = viewContext.editor.isBlockCard(item);
2047
- if (isBlockCard) {
2048
- const rootNodes = getRootNodes(view);
2049
- const blockCardComponentRef = viewContainerRef.createComponent(SlateBlockCard, {
2050
- injector: viewContainerRef.injector
2051
- });
2052
- blockCardComponentRef.instance.initializeCenter(rootNodes);
2053
- blockCardComponentRef.changeDetectorRef.detectChanges();
2054
- return blockCardComponentRef;
2055
- }
2056
- else {
2057
- return null;
1814
+
1815
+ class BaseLeafFlavour extends BaseFlavour {
1816
+ get text() {
1817
+ return this.context && this.context.text;
2058
1818
  }
2059
- }
2060
- function trackBy(viewContext) {
2061
- return (index, node) => {
2062
- return viewContext.trackBy(node) || AngularEditor.findKey(viewContext.editor, node);
2063
- };
2064
- }
2065
- function memoizedContext(viewContext, descendant, prev, next) {
2066
- if (Element.isElement(descendant)) {
2067
- return memoizedElementContext(viewContext, prev, next);
1819
+ get leaf() {
1820
+ return this.context && this.context.leaf;
2068
1821
  }
2069
- else {
2070
- return memoizedTextContext(prev, next);
2071
- }
2072
- }
2073
- function memoizedElementContext(viewContext, prev, next) {
2074
- return (prev.element === next.element &&
2075
- (!viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
2076
- prev.readonly === next.readonly &&
2077
- isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
2078
- (prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
2079
- }
2080
- function memoizedTextContext(prev, next) {
2081
- return (next.parent === prev.parent &&
2082
- next.isLast === prev.isLast &&
2083
- next.text === prev.text &&
2084
- isDecoratorRangeListEqual(next.decorations, prev.decorations));
2085
- }
2086
- function addAfterViewInitQueue(editor, afterViewInitCallback) {
2087
- const queue = getAfterViewInitQueue(editor);
2088
- queue.push(afterViewInitCallback);
2089
- EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, queue);
2090
- }
2091
- function getAfterViewInitQueue(editor) {
2092
- return EDITOR_TO_AFTER_VIEW_INIT_QUEUE.get(editor) || [];
2093
- }
2094
- function clearAfterViewInitQueue(editor) {
2095
- EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, []);
2096
- }
2097
- function executeAfterViewInit(editor) {
2098
- const queue = getAfterViewInitQueue(editor);
2099
- queue.forEach(callback => callback());
2100
- clearAfterViewInitQueue(editor);
2101
- }
2102
-
2103
- /**
2104
- * base class for custom element component or text component
2105
- */
2106
- class BaseComponent {
2107
- constructor() {
2108
- this.initialized = false;
2109
- this.elementRef = inject(ElementRef);
2110
- this.cdr = inject(ChangeDetectorRef);
2111
- }
2112
- set context(value) {
2113
- if (hasBeforeContextChange(this)) {
2114
- this.beforeContextChange(value);
2115
- }
2116
- this._context = value;
2117
- this.onContextChange();
2118
- if (this.initialized) {
2119
- this.cdr.detectChanges();
2120
- }
2121
- if (hasAfterContextChange(this)) {
2122
- this.afterContextChange();
2123
- }
2124
- }
2125
- get context() {
2126
- return this._context;
2127
- }
2128
- get editor() {
2129
- return this.viewContext && this.viewContext.editor;
2130
- }
2131
- get nativeElement() {
2132
- return this.elementRef.nativeElement;
2133
- }
2134
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2135
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseComponent, isStandalone: true, inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0 }); }
2136
- }
2137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseComponent, decorators: [{
2138
- type: Directive
2139
- }], propDecorators: { context: [{
2140
- type: Input
2141
- }], viewContext: [{
2142
- type: Input
2143
- }] } });
2144
- /**
2145
- * base class for custom leaf component
2146
- */
2147
- class BaseLeafComponent extends BaseComponent {
2148
- constructor() {
2149
- super(...arguments);
2150
- this.isSlateLeaf = true;
2151
- }
2152
- get text() {
2153
- return this.context && this.context.text;
2154
- }
2155
- get leaf() {
2156
- return this.context && this.context.leaf;
2157
- }
2158
- ngOnInit() {
1822
+ onInit() {
1823
+ this.render();
1824
+ this.renderPlaceholder();
2159
1825
  this.initialized = true;
2160
1826
  }
2161
1827
  onContextChange() {
2162
1828
  if (!this.initialized) {
2163
1829
  return;
2164
1830
  }
1831
+ this.rerender();
1832
+ this.renderPlaceholder();
2165
1833
  }
2166
1834
  renderPlaceholder() {
2167
1835
  // issue-1: IME input was interrupted
@@ -2188,10 +1856,12 @@ class BaseLeafComponent extends BaseComponent {
2188
1856
  setTimeout(() => {
2189
1857
  const editorElement = this.nativeElement.closest('.the-editor-typo');
2190
1858
  const editorContentHeight = getContentHeight(editorElement);
2191
- // Not supported webkitLineClamp exceeds height hiding
2192
- placeholderElement.style.maxHeight = `${editorContentHeight}px`;
2193
- const lineClamp = Math.floor(editorContentHeight / this.nativeElement.offsetHeight);
2194
- placeholderElement.style.webkitLineClamp = `${lineClamp}`;
1859
+ if (editorContentHeight > 0) {
1860
+ // Not supported webkitLineClamp exceeds height hiding
1861
+ placeholderElement.style.maxHeight = `${editorContentHeight}px`;
1862
+ }
1863
+ const lineClamp = Math.floor(editorContentHeight / this.nativeElement.offsetHeight) || 0;
1864
+ placeholderElement.style.webkitLineClamp = `${Math.max(lineClamp, 1)}`;
2195
1865
  });
2196
1866
  }
2197
1867
  updatePlaceholder() {
@@ -2206,142 +1876,309 @@ class BaseLeafComponent extends BaseComponent {
2206
1876
  this.nativeElement.classList.remove('leaf-with-placeholder');
2207
1877
  }
2208
1878
  }
2209
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseLeafComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
2210
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseLeafComponent, isStandalone: true, host: { properties: { "attr.data-slate-leaf": "this.isSlateLeaf" } }, usesInheritance: true, ngImport: i0 }); }
1879
+ onDestroy() {
1880
+ this.nativeElement?.remove();
1881
+ }
2211
1882
  }
2212
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseLeafComponent, decorators: [{
2213
- type: Directive
2214
- }], propDecorators: { isSlateLeaf: [{
2215
- type: HostBinding,
2216
- args: ['attr.data-slate-leaf']
2217
- }] } });
2218
- /**
2219
- * base class for custom element component
2220
- */
2221
- class BaseElementComponent extends BaseComponent {
2222
- constructor() {
2223
- super(...arguments);
2224
- this.viewContainerRef = inject(ViewContainerRef);
2225
- this.getOutletParent = () => {
2226
- return this.elementRef.nativeElement;
2227
- };
2228
- this.getOutletElement = () => {
2229
- if (this.childrenOutletInstance) {
2230
- return this.childrenOutletInstance.getNativeElement();
2231
- }
2232
- return null;
2233
- };
1883
+
1884
+ var StringType;
1885
+ (function (StringType) {
1886
+ StringType["normalString"] = "normalString";
1887
+ StringType["lineBreakEmptyString"] = "lineBreakEmptyString";
1888
+ StringType["normalEmptyText"] = "normalEmptyText";
1889
+ StringType["compatibleString"] = "compatibleString";
1890
+ StringType["voidString"] = "voidString";
1891
+ })(StringType || (StringType = {}));
1892
+ class SlateStringRender {
1893
+ constructor(context, viewContext) {
1894
+ this.context = context;
1895
+ this.viewContext = viewContext;
2234
1896
  }
2235
- get element() {
2236
- return this._context && this._context.element;
1897
+ // COMPAT: If the text is empty, it's because it's on the edge of an inline
1898
+ // node, so we render a zero-width space so that the selection can be
1899
+ // inserted next to it still.
1900
+ isEmptyText() {
1901
+ return this.context.leaf.text === '';
2237
1902
  }
2238
- get selection() {
2239
- return this._context && this._context.selection;
1903
+ // COMPAT: Browsers will collapse trailing new lines at the end of blocks,
1904
+ // so we need to add an extra trailing new lines to prevent that.
1905
+ isCompatibleString() {
1906
+ return this.context.isLast && this.context.leaf.text.slice(-1) === '\n';
2240
1907
  }
2241
- get decorations() {
2242
- return this._context && this._context.decorations;
1908
+ // COMPAT: Render text inside void nodes with a zero-width space.
1909
+ // So the node can contain selection but the text is not visible.
1910
+ isVoid() {
1911
+ return this.viewContext.editor.isVoid(this.context.parent);
2243
1912
  }
2244
- get children() {
2245
- return this._context && this._context.element.children;
1913
+ get leaf() {
1914
+ return this.context && this.context.leaf;
2246
1915
  }
2247
- get isCollapsed() {
2248
- return this.selection && Range.isCollapsed(this.selection);
1916
+ // COMPAT: If this is the last text node in an empty block, render a zero-
1917
+ // width space that will convert into a line break when copying and pasting
1918
+ // to support expected plain text.
1919
+ isLineBreakEmptyString() {
1920
+ return (this.context.leaf.text === '' &&
1921
+ this.context.parent.children[this.context.parent.children.length - 1] === this.context.text &&
1922
+ !this.viewContext.editor.isInline(this.context.parent) &&
1923
+ // [list-render] performance optimization: reduce the number of calls to the `Editor.string(editor, path)` method
1924
+ isEmpty(this.viewContext.editor, this.context.parent));
2249
1925
  }
2250
- get isCollapsedAndNonReadonly() {
2251
- return this.selection && Range.isCollapsed(this.selection) && !this.readonly;
1926
+ createStringNode(type) {
1927
+ let newNativeElement;
1928
+ switch (type) {
1929
+ case StringType.lineBreakEmptyString:
1930
+ newNativeElement = createLineBreakEmptyStringDOM(this.getElementStringLength());
1931
+ break;
1932
+ case StringType.voidString:
1933
+ case StringType.normalEmptyText:
1934
+ newNativeElement = createEmptyOrVoidStringNode();
1935
+ break;
1936
+ case StringType.compatibleString:
1937
+ newNativeElement = createCompatibleStringNode(this.leaf.text);
1938
+ break;
1939
+ case StringType.normalString:
1940
+ newNativeElement = createDefaultStringNode(this.leaf.text);
1941
+ break;
1942
+ default:
1943
+ newNativeElement = createDefaultStringNode(this.leaf.text);
1944
+ }
1945
+ return newNativeElement;
2252
1946
  }
2253
- get readonly() {
2254
- return this._context && this._context.readonly;
1947
+ render() {
1948
+ this.type = this.getType();
1949
+ this.nativeElement = this.createStringNode(this.type);
1950
+ return this.nativeElement;
2255
1951
  }
2256
- ngOnInit() {
2257
- for (const key in this._context.attributes) {
2258
- this.nativeElement.setAttribute(key, this._context.attributes[key]);
2259
- }
2260
- this.initialized = true;
2261
- this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
2262
- if (this.editor.isExpanded(this.element)) {
2263
- this.listRender.initialize(this.children, this.element, this.childrenContext);
1952
+ getType() {
1953
+ if (this.isLineBreakEmptyString()) {
1954
+ return StringType.lineBreakEmptyString;
2264
1955
  }
2265
- addAfterViewInitQueue(this.editor, () => {
2266
- this.afterViewInit();
2267
- });
2268
- }
2269
- afterViewInit() {
2270
- if (this._context.contentEditable !== undefined) {
2271
- this.nativeElement.setAttribute('contenteditable', this._context.contentEditable + '');
1956
+ if (this.isVoid()) {
1957
+ return StringType.voidString;
2272
1958
  }
2273
- }
2274
- updateWeakMap() {
2275
- NODE_TO_ELEMENT.set(this.element, this.nativeElement);
2276
- ELEMENT_TO_NODE.set(this.nativeElement, this.element);
2277
- ELEMENT_TO_COMPONENT.set(this.element, this);
2278
- }
2279
- ngOnDestroy() {
2280
- if (NODE_TO_ELEMENT.get(this.element) === this.nativeElement) {
2281
- NODE_TO_ELEMENT.delete(this.element);
1959
+ if (this.isEmptyText()) {
1960
+ return StringType.normalEmptyText;
2282
1961
  }
2283
- ELEMENT_TO_NODE.delete(this.nativeElement);
2284
- if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
2285
- ELEMENT_TO_COMPONENT.delete(this.element);
1962
+ if (this.isCompatibleString()) {
1963
+ return StringType.compatibleString;
2286
1964
  }
1965
+ return StringType.normalString;
2287
1966
  }
2288
- onContextChange() {
2289
- this.childrenContext = this.getChildrenContext();
2290
- this.updateWeakMap();
2291
- if (!this.initialized) {
1967
+ update(context, viewContext) {
1968
+ this.context = context;
1969
+ this.viewContext = viewContext;
1970
+ const type = this.getType();
1971
+ if (type !== this.type) {
1972
+ const newNativeElement = this.createStringNode(type);
1973
+ this.nativeElement.replaceWith(newNativeElement);
1974
+ this.nativeElement = newNativeElement;
1975
+ this.type = type;
2292
1976
  return;
2293
1977
  }
2294
- this.updateChildrenView();
2295
- }
2296
- updateChildrenView() {
2297
- if (this.editor.isExpanded(this.element)) {
2298
- this.listRender.update(this.children, this.element, this.childrenContext);
2299
- }
2300
- else {
2301
- if (this.listRender.initialized) {
2302
- this.listRender.destroy();
2303
- }
1978
+ if (this.type === StringType.normalString) {
1979
+ this.nativeElement.textContent = this.leaf.text;
2304
1980
  }
2305
1981
  }
2306
- getChildrenContext() {
2307
- return {
2308
- parent: this._context.element,
2309
- selection: this._context.selection,
2310
- decorations: this._context.decorations,
2311
- decorate: this._context.decorate,
2312
- readonly: this._context.readonly
2313
- };
1982
+ getElementStringLength() {
1983
+ return Node.string(this.context.parent).length;
2314
1984
  }
2315
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseElementComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
2316
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseElementComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
2317
1985
  }
2318
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseElementComponent, decorators: [{
2319
- type: Directive
2320
- }], propDecorators: { childrenOutletInstance: [{
2321
- type: ViewChild,
2322
- args: [SlateChildrenOutlet, { static: true }]
2323
- }] } });
1986
+ const createDefaultStringNode = (text) => {
1987
+ const stringNode = document.createElement('span');
1988
+ stringNode.textContent = text;
1989
+ stringNode.setAttribute('data-slate-string', 'true');
1990
+ stringNode.setAttribute('editable-text', '');
1991
+ return stringNode;
1992
+ };
1993
+ const createEmptyOrVoidStringNode = () => {
1994
+ const stringNode = document.createElement('span');
1995
+ stringNode.setAttribute('data-slate-string', 'true');
1996
+ stringNode.setAttribute('data-slate-zero-width', 'z');
1997
+ stringNode.setAttribute('data-slate-length', '0');
1998
+ const zeroWidthSpace = document.createTextNode('\uFEFF');
1999
+ stringNode.appendChild(zeroWidthSpace);
2000
+ stringNode.setAttribute('editable-text', '');
2001
+ return stringNode;
2002
+ };
2003
+ const createCompatibleStringNode = (text) => {
2004
+ const stringNode = document.createElement('span');
2005
+ stringNode.setAttribute('data-slate-string', 'true');
2006
+ stringNode.textContent = text;
2007
+ stringNode.setAttribute('editable-text', '');
2008
+ const zeroWidthSpan = document.createElement('span');
2009
+ const zeroWidthSpace = document.createTextNode('\uFEFF');
2010
+ zeroWidthSpan.setAttribute('data-slate-zero-width', '');
2011
+ zeroWidthSpan.appendChild(zeroWidthSpace);
2012
+ stringNode.appendChild(zeroWidthSpan);
2013
+ return stringNode;
2014
+ };
2015
+ const createLineBreakEmptyStringDOM = (elementStringLength) => {
2016
+ const stringNode = document.createElement('span');
2017
+ stringNode.setAttribute('data-slate-zero-width', 'n');
2018
+ stringNode.setAttribute('data-slate-length', `${elementStringLength}`);
2019
+ const zeroWidthSpace = document.createTextNode(`\uFEFF`);
2020
+ stringNode.appendChild(zeroWidthSpace);
2021
+ const brNode = document.createElement('br');
2022
+ stringNode.appendChild(brNode);
2023
+ stringNode.setAttribute('editable-text', '');
2024
+ return stringNode;
2025
+ };
2324
2026
  /**
2325
- * base class for custom text component
2027
+ * TODO: remove when bump slate
2028
+ * copy from slate
2029
+ * @param editor
2030
+ * @param element
2031
+ * @returns
2326
2032
  */
2327
- class BaseTextComponent extends BaseComponent {
2033
+ const isEmpty = (editor, element) => {
2034
+ const { children } = element;
2035
+ const [first] = children;
2036
+ return children.length === 0 || (children.length === 1 && Text$1.isText(first) && first.text === '' && !editor.isVoid(element));
2037
+ };
2038
+
2039
+ class DefaultLeafFlavour extends BaseLeafFlavour {
2328
2040
  constructor() {
2329
2041
  super(...arguments);
2330
- this.viewContainerRef = inject(ViewContainerRef);
2331
- this.getOutletParent = () => {
2332
- return this.elementRef.nativeElement;
2333
- };
2334
- this.getOutletElement = () => {
2335
- if (this.childrenOutletInstance) {
2336
- return this.childrenOutletInstance.getNativeElement();
2337
- }
2338
- return null;
2339
- };
2042
+ this.stringRender = null;
2340
2043
  }
2341
- get text() {
2044
+ render() {
2045
+ const leafNode = createDefaultLeafNode();
2046
+ this.stringRender = new SlateStringRender(this.context, this.viewContext);
2047
+ const stringNode = this.stringRender.render();
2048
+ leafNode.appendChild(stringNode);
2049
+ this.nativeElement = leafNode;
2050
+ }
2051
+ rerender() {
2052
+ this.stringRender?.update(this.context, this.viewContext);
2053
+ }
2054
+ }
2055
+ const createDefaultLeafNode = () => {
2056
+ const span = document.createElement('span');
2057
+ span.setAttribute('data-slate-leaf', 'true');
2058
+ return span;
2059
+ };
2060
+
2061
+ class LeavesRender {
2062
+ constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
2063
+ this.viewContext = viewContext;
2064
+ this.viewContainerRef = viewContainerRef;
2065
+ this.getOutletParent = getOutletParent;
2066
+ this.getOutletElement = getOutletElement;
2067
+ this.views = [];
2068
+ this.contexts = [];
2069
+ this.viewTypes = [];
2070
+ }
2071
+ initialize(context) {
2072
+ const { decoratedLeaves, contexts } = this.getLeaves(context);
2073
+ this.decoratedLeaves = decoratedLeaves;
2074
+ this.contexts = contexts;
2075
+ this.decoratedLeaves.forEach((leaf, index) => {
2076
+ const context = getContext$1(index, this.contexts);
2077
+ const viewType = getViewType$1(context, this.viewContext);
2078
+ const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2079
+ this.views.push(view);
2080
+ this.contexts.push(context);
2081
+ this.viewTypes.push(viewType);
2082
+ });
2083
+ mount(this.views, null, this.getOutletParent(), this.getOutletElement());
2084
+ const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
2085
+ this.differ = newDiffers.find(this.decoratedLeaves).create(trackBy$1(this.viewContext));
2086
+ this.differ.diff(this.decoratedLeaves);
2087
+ }
2088
+ update(context) {
2089
+ const { decoratedLeaves, contexts } = this.getLeaves(context);
2090
+ const outletParent = this.getOutletParent();
2091
+ const diffResult = this.differ.diff(decoratedLeaves);
2092
+ if (diffResult) {
2093
+ let firstRootNode = getRootNodes(this.views[0])[0];
2094
+ const newContexts = [];
2095
+ const newViewTypes = [];
2096
+ const newViews = [];
2097
+ diffResult.forEachItem(record => {
2098
+ let context = getContext$1(record.currentIndex, contexts);
2099
+ const viewType = getViewType$1(context, this.viewContext);
2100
+ newViewTypes.push(viewType);
2101
+ let view;
2102
+ if (record.previousIndex === null) {
2103
+ view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2104
+ newContexts.push(context);
2105
+ newViews.push(view);
2106
+ mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
2107
+ }
2108
+ else {
2109
+ const previousView = this.views[record.previousIndex];
2110
+ const previousViewType = this.viewTypes[record.previousIndex];
2111
+ if (previousViewType !== viewType) {
2112
+ view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2113
+ const firstRootNode = getRootNodes(previousView, null)[0];
2114
+ const newRootNodes = getRootNodes(view, null);
2115
+ firstRootNode.replaceWith(...newRootNodes);
2116
+ previousView.destroy();
2117
+ }
2118
+ else {
2119
+ view = previousView;
2120
+ updateContext(previousView, context, this.viewContext);
2121
+ }
2122
+ newContexts.push(context);
2123
+ newViews.push(view);
2124
+ }
2125
+ });
2126
+ diffResult.forEachRemovedItem(record => {
2127
+ const view = this.views[record.previousIndex];
2128
+ view.destroy();
2129
+ });
2130
+ diffResult.forEachMovedItem(record => {
2131
+ mountOnItemChange(record.currentIndex, record.item, newViews, null, outletParent, firstRootNode, this.viewContext);
2132
+ });
2133
+ this.viewTypes = newViewTypes;
2134
+ this.views = newViews;
2135
+ this.contexts = newContexts;
2136
+ this.decoratedLeaves = decoratedLeaves;
2137
+ }
2138
+ }
2139
+ getLeaves(context) {
2140
+ const decoratedLeaves = Text$1.decorations(context.text, context.decorations);
2141
+ const contexts = decoratedLeaves.map((decoratedLeaf, index) => {
2142
+ return {
2143
+ leaf: decoratedLeaf.leaf,
2144
+ leafPosition: decoratedLeaf.position,
2145
+ text: context.text,
2146
+ parent: context.parent,
2147
+ index,
2148
+ isLast: context.isLast && index === decoratedLeaves.length - 1
2149
+ };
2150
+ });
2151
+ return { decoratedLeaves, contexts };
2152
+ }
2153
+ }
2154
+ function getContext$1(index, leafContexts) {
2155
+ return leafContexts[index];
2156
+ }
2157
+ function getViewType$1(leafContext, viewContext) {
2158
+ return (viewContext.renderLeaf && viewContext.renderLeaf(leafContext.leaf)) || DefaultLeafFlavour;
2159
+ }
2160
+ function trackBy$1(viewContext) {
2161
+ return (index, node) => {
2162
+ return index;
2163
+ };
2164
+ }
2165
+
2166
+ class BaseTextFlavour extends BaseFlavour {
2167
+ constructor() {
2168
+ super(...arguments);
2169
+ this.getOutletParent = () => {
2170
+ return this.nativeElement;
2171
+ };
2172
+ this.getOutletElement = () => {
2173
+ return this.nativeElement.querySelector('.children-outlet');
2174
+ };
2175
+ }
2176
+ get text() {
2342
2177
  return this._context && this._context.text;
2343
2178
  }
2344
- ngOnInit() {
2179
+ onInit() {
2180
+ this.render();
2181
+ this.updateWeakMap();
2345
2182
  this.initialized = true;
2346
2183
  this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
2347
2184
  this.leavesRender.initialize(this.context);
@@ -2350,390 +2187,337 @@ class BaseTextComponent extends BaseComponent {
2350
2187
  ELEMENT_TO_NODE.set(this.nativeElement, this.text);
2351
2188
  NODE_TO_ELEMENT.set(this.text, this.nativeElement);
2352
2189
  }
2353
- ngOnDestroy() {
2190
+ onDestroy() {
2354
2191
  if (NODE_TO_ELEMENT.get(this.text) === this.nativeElement) {
2355
2192
  NODE_TO_ELEMENT.delete(this.text);
2356
2193
  }
2357
2194
  ELEMENT_TO_NODE.delete(this.nativeElement);
2195
+ this.nativeElement?.remove();
2358
2196
  }
2359
2197
  onContextChange() {
2360
- this.updateWeakMap();
2361
2198
  if (!this.initialized) {
2362
2199
  return;
2363
2200
  }
2201
+ this.rerender();
2202
+ this.updateWeakMap();
2364
2203
  this.leavesRender.update(this.context);
2365
2204
  }
2366
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseTextComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
2367
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseTextComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
2368
2205
  }
2369
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseTextComponent, decorators: [{
2370
- type: Directive
2371
- }], propDecorators: { childrenOutletInstance: [{
2372
- type: ViewChild,
2373
- args: [SlateChildrenOutlet, { static: true }]
2374
- }] } });
2375
2206
 
2376
- class SlateVoidText extends BaseTextComponent {
2377
- ngOnInit() {
2378
- super.ngOnInit();
2379
- }
2380
- ngOnChanges() {
2381
- if (!this.initialized) {
2382
- return;
2383
- }
2207
+ class DefaultTextFlavour extends BaseTextFlavour {
2208
+ render() {
2209
+ const { nativeElement } = createText(this.text.text);
2210
+ this.nativeElement = nativeElement;
2384
2211
  }
2385
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateVoidText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2386
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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 }); }
2387
- }
2388
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateVoidText, decorators: [{
2389
- type: Component,
2390
- args: [{
2391
- selector: 'span[slateVoidText]',
2392
- template: ``,
2393
- changeDetection: ChangeDetectionStrategy.OnPush,
2394
- host: {
2395
- 'data-slate-spacer': 'true',
2396
- class: 'slate-spacer',
2397
- 'data-slate-node': 'text'
2398
- }
2399
- }]
2400
- }] });
2401
-
2402
- class SlateDefaultText extends BaseTextComponent {
2403
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultText, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2404
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateDefaultText, isStandalone: true, selector: "span[slateDefaultText]", host: { attributes: { "data-slate-node": "text" } }, usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2212
+ rerender() { }
2405
2213
  }
2406
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultText, decorators: [{
2407
- type: Component,
2408
- args: [{
2409
- selector: 'span[slateDefaultText]',
2410
- template: ``,
2411
- changeDetection: ChangeDetectionStrategy.OnPush,
2412
- host: {
2413
- 'data-slate-node': 'text'
2414
- }
2415
- }]
2416
- }] });
2417
-
2418
- class SlateDefaultElement extends BaseElementComponent {
2419
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultElement, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2420
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateDefaultElement, isStandalone: true, selector: "div[slateDefaultElement]", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2214
+ class VoidTextFlavour extends BaseTextFlavour {
2215
+ render() {
2216
+ const { nativeElement } = createText(this.text.text);
2217
+ this.nativeElement = nativeElement;
2218
+ this.nativeElement.setAttribute('data-slate-spacer', 'true');
2219
+ this.nativeElement.classList.add('slate-spacer');
2220
+ }
2221
+ rerender() { }
2421
2222
  }
2422
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultElement, decorators: [{
2423
- type: Component,
2424
- args: [{
2425
- selector: 'div[slateDefaultElement]',
2426
- template: ``,
2427
- changeDetection: ChangeDetectionStrategy.OnPush
2428
- }]
2429
- }] });
2223
+ const createText = (text) => {
2224
+ const nativeElement = document.createElement('span');
2225
+ nativeElement.setAttribute('data-slate-node', 'text');
2226
+ return { nativeElement };
2227
+ };
2430
2228
 
2431
- /**
2432
- * Dynamically create/update components or templates
2433
- * Provide rootNodes for the view container
2434
- * If the dynamically created component uses onpush mode, then it must call markForCheck when setting the context
2435
- */
2436
- class ViewContainerItem {
2437
- constructor() {
2229
+ class ListRender {
2230
+ constructor(viewContext, viewContainerRef, getOutletParent, getOutletElement) {
2231
+ this.viewContext = viewContext;
2232
+ this.viewContainerRef = viewContainerRef;
2233
+ this.getOutletParent = getOutletParent;
2234
+ this.getOutletElement = getOutletElement;
2235
+ this.views = [];
2236
+ this.blockCards = [];
2237
+ this.contexts = [];
2238
+ this.viewTypes = [];
2239
+ this.differ = null;
2438
2240
  this.initialized = false;
2439
- this.viewContainerRef = inject(ViewContainerRef);
2440
- }
2441
- get rootNodes() {
2442
- return this.getRootNodes();
2443
- }
2444
- getRootNodes() {
2445
- if (this.embeddedViewRef) {
2446
- return this.embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode));
2447
- }
2448
- if (this.componentRef) {
2449
- return [this.componentRef.instance.nativeElement];
2450
- }
2451
- return [];
2452
- }
2453
- destroyView() {
2454
- if (this.embeddedViewRef) {
2455
- this.embeddedViewRef.destroy();
2456
- this.embeddedViewRef = null;
2457
- }
2458
- if (this.componentRef) {
2459
- this.componentRef.destroy();
2460
- this.componentRef = null;
2461
- }
2462
2241
  }
2463
- createView() {
2242
+ initialize(children, parent, childrenContext) {
2464
2243
  this.initialized = true;
2465
- this.viewType = this.getViewType();
2466
- const context = this.getContext();
2467
- if (isTemplateRef(this.viewType)) {
2468
- this.embeddedViewContext = {
2469
- context,
2470
- viewContext: this.viewContext
2471
- };
2472
- const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
2473
- this.embeddedViewRef = embeddedViewRef;
2474
- }
2475
- if (isComponentType(this.viewType)) {
2476
- const componentRef = this.viewContainerRef.createComponent(this.viewType);
2477
- componentRef.instance.viewContext = this.viewContext;
2478
- componentRef.instance.context = context;
2479
- this.componentRef = componentRef;
2480
- }
2481
- }
2482
- updateView() {
2483
- const viewType = this.getViewType();
2484
- const context = this.getContext();
2485
- if (this.viewType === viewType) {
2486
- if (this.componentRef) {
2487
- if (this.memoizedContext(this.componentRef.instance.context, context)) {
2488
- return;
2489
- }
2490
- this.componentRef.instance.context = context;
2491
- }
2492
- if (this.embeddedViewRef) {
2493
- if (this.memoizedContext(this.embeddedViewContext.context, context)) {
2494
- return;
2495
- }
2496
- this.embeddedViewContext.context = context;
2497
- }
2498
- }
2499
- else {
2500
- this.viewType = viewType;
2501
- const firstRootNode = this.rootNodes[0];
2502
- if (isTemplateRef(this.viewType)) {
2503
- this.embeddedViewContext = {
2504
- context,
2505
- viewContext: this.viewContext
2506
- };
2507
- const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.viewType, this.embeddedViewContext);
2508
- firstRootNode.replaceWith(...embeddedViewRef.rootNodes.filter(rootNode => isDOMElement(rootNode)));
2509
- this.destroyView();
2510
- this.embeddedViewRef = embeddedViewRef;
2511
- }
2512
- if (isComponentType(this.viewType)) {
2513
- const componentRef = this.viewContainerRef.createComponent(this.viewType);
2514
- componentRef.instance.viewContext = this.viewContext;
2515
- componentRef.instance.context = context;
2516
- firstRootNode.replaceWith(componentRef.instance.nativeElement);
2517
- this.destroyView();
2518
- this.componentRef = componentRef;
2519
- }
2244
+ this.children = children;
2245
+ const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
2246
+ children.forEach((descendant, index) => {
2247
+ NODE_TO_INDEX.set(descendant, index);
2248
+ NODE_TO_PARENT.set(descendant, parent);
2249
+ const context = getContext(index, descendant, parentPath, childrenContext, this.viewContext);
2250
+ const viewType = getViewType(descendant, parent, this.viewContext);
2251
+ const view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2252
+ const blockCard = createBlockCard(descendant, view, this.viewContainerRef, this.viewContext);
2253
+ this.views.push(view);
2254
+ this.contexts.push(context);
2255
+ this.viewTypes.push(viewType);
2256
+ this.blockCards.push(blockCard);
2257
+ });
2258
+ mount(this.views, this.blockCards, this.getOutletParent(), this.getOutletElement());
2259
+ const newDiffers = this.viewContext.editor.injector.get(IterableDiffers);
2260
+ this.differ = newDiffers.find(children).create(trackBy(this.viewContext));
2261
+ this.differ.diff(children);
2262
+ if (parent === this.viewContext.editor) {
2263
+ executeAfterViewInit(this.viewContext.editor);
2520
2264
  }
2521
2265
  }
2522
- appendBlockCardElement() {
2523
- if (this.blockCardComponentRef) {
2524
- this.blockCardComponentRef.instance.append();
2266
+ update(children, parent, childrenContext) {
2267
+ if (!this.initialized || this.children.length === 0) {
2268
+ this.initialize(children, parent, childrenContext);
2269
+ return;
2525
2270
  }
2526
- }
2527
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ViewContainerItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2528
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: ViewContainerItem, isStandalone: true, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
2529
- }
2530
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ViewContainerItem, decorators: [{
2531
- type: Directive
2532
- }], propDecorators: { viewContext: [{
2533
- type: Input
2534
- }] } });
2535
-
2536
- class SlateDefaultString extends BaseComponent {
2537
- beforeContextChange(value) {
2538
- if (this.context) {
2539
- if (this.context.type === 'lineBreakEmptyString') {
2540
- if (value.type === 'string') {
2541
- this.removeLineBreakEmptyStringDOM();
2271
+ if (!this.differ) {
2272
+ throw new Error('Exception: Can not find differ ');
2273
+ }
2274
+ const outletParent = this.getOutletParent();
2275
+ const diffResult = this.differ.diff(children);
2276
+ const parentPath = AngularEditor.findPath(this.viewContext.editor, parent);
2277
+ if (diffResult) {
2278
+ let firstRootNode = getRootNodes(this.views[0], this.blockCards[0])[0];
2279
+ const newContexts = [];
2280
+ const newViewTypes = [];
2281
+ const newViews = [];
2282
+ const newBlockCards = [];
2283
+ diffResult.forEachItem(record => {
2284
+ NODE_TO_INDEX.set(record.item, record.currentIndex);
2285
+ NODE_TO_PARENT.set(record.item, parent);
2286
+ let context = getContext(record.currentIndex, record.item, parentPath, childrenContext, this.viewContext);
2287
+ const viewType = getViewType(record.item, parent, this.viewContext);
2288
+ newViewTypes.push(viewType);
2289
+ let view;
2290
+ let blockCard;
2291
+ if (record.previousIndex === null) {
2292
+ view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2293
+ blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
2294
+ newContexts.push(context);
2295
+ newViews.push(view);
2296
+ newBlockCards.push(blockCard);
2297
+ mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
2542
2298
  }
2543
2299
  else {
2544
- this.textNode?.remove();
2545
- this.brNode?.remove();
2546
- }
2547
- }
2548
- if (this.context.type === 'string') {
2549
- if (value.type === 'lineBreakEmptyString') {
2550
- this.removeStringDOM();
2551
- }
2552
- }
2553
- }
2554
- }
2555
- onContextChange() {
2556
- if (this.context.type === 'string') {
2557
- this.createStringDOM();
2558
- }
2559
- else if (this.context.type === 'lineBreakEmptyString') {
2560
- this.createLineBreakEmptyStringDOM();
2300
+ const previousView = this.views[record.previousIndex];
2301
+ const previousViewType = this.viewTypes[record.previousIndex];
2302
+ const previousContext = this.contexts[record.previousIndex];
2303
+ const previousBlockCard = this.blockCards[record.previousIndex];
2304
+ if (previousViewType !== viewType) {
2305
+ view = createEmbeddedViewOrComponentOrFlavour(viewType, context, this.viewContext, this.viewContainerRef);
2306
+ blockCard = createBlockCard(record.item, view, this.viewContainerRef, this.viewContext);
2307
+ const firstRootNode = getRootNodes(previousView, previousBlockCard)[0];
2308
+ const newRootNodes = getRootNodes(view, blockCard);
2309
+ firstRootNode.replaceWith(...newRootNodes);
2310
+ previousView.destroy();
2311
+ previousBlockCard?.destroy();
2312
+ }
2313
+ else {
2314
+ view = previousView;
2315
+ blockCard = previousBlockCard;
2316
+ if (memoizedContext(this.viewContext, record.item, previousContext, context)) {
2317
+ context = previousContext;
2318
+ }
2319
+ else {
2320
+ updateContext(previousView, context, this.viewContext);
2321
+ }
2322
+ }
2323
+ newContexts.push(context);
2324
+ newViews.push(view);
2325
+ newBlockCards.push(blockCard);
2326
+ }
2327
+ });
2328
+ diffResult.forEachOperation(record => {
2329
+ // removed
2330
+ if (record.currentIndex === null) {
2331
+ const view = this.views[record.previousIndex];
2332
+ const blockCard = this.blockCards[record.previousIndex];
2333
+ view.destroy();
2334
+ blockCard?.destroy();
2335
+ }
2336
+ // moved
2337
+ if (record.previousIndex !== null && record.currentIndex !== null) {
2338
+ mountOnItemChange(record.currentIndex, record.item, newViews, newBlockCards, outletParent, firstRootNode, this.viewContext);
2339
+ // Solve the block-card DOMElement loss when moving nodes
2340
+ newBlockCards[record.currentIndex]?.instance.append();
2341
+ }
2342
+ });
2343
+ this.viewTypes = newViewTypes;
2344
+ this.views = newViews;
2345
+ this.contexts = newContexts;
2346
+ this.children = children;
2347
+ this.blockCards = newBlockCards;
2348
+ if (parent === this.viewContext.editor) {
2349
+ executeAfterViewInit(this.viewContext.editor);
2350
+ }
2561
2351
  }
2562
- }
2563
- createLineBreakEmptyStringDOM() {
2564
- this.nativeElement.setAttribute('data-slate-zero-width', 'n');
2565
- this.nativeElement.setAttribute('data-slate-length', `${this.context.elementStringLength}`);
2566
- this.textNode = document.createTextNode(`\uFEFF`);
2567
- this.brNode = document.createElement('br');
2568
- this.nativeElement.append(this.textNode, this.brNode);
2569
- }
2570
- removeLineBreakEmptyStringDOM() {
2571
- this.brNode?.remove();
2572
- // remove zero width character
2573
- const zeroWidthCharacterIndex = this.textNode?.textContent.indexOf(`\uFEFF`);
2574
- this.textNode?.deleteData(zeroWidthCharacterIndex, 1);
2575
- this.nativeElement.removeAttribute('data-slate-zero-width');
2576
- this.nativeElement.removeAttribute('data-slate-length');
2577
- }
2578
- createStringDOM() {
2579
- this.nativeElement.setAttribute('data-slate-string', 'true');
2580
- this.updateStringDOM();
2581
- }
2582
- updateStringDOM() {
2583
- // Avoid breaking some browser default behaviors, such as spellCheck, android composition input state
2584
- if (this.nativeElement.textContent !== this.context.text) {
2585
- this.nativeElement.textContent = this.context.text;
2352
+ else {
2353
+ const newContexts = [];
2354
+ this.children.forEach((child, index) => {
2355
+ NODE_TO_INDEX.set(child, index);
2356
+ NODE_TO_PARENT.set(child, parent);
2357
+ let context = getContext(index, child, parentPath, childrenContext, this.viewContext);
2358
+ const previousContext = this.contexts[index];
2359
+ if (memoizedContext(this.viewContext, child, previousContext, context)) {
2360
+ context = previousContext;
2361
+ }
2362
+ else {
2363
+ updateContext(this.views[index], context, this.viewContext);
2364
+ }
2365
+ newContexts.push(context);
2366
+ });
2367
+ this.contexts = newContexts;
2586
2368
  }
2587
2369
  }
2588
- removeStringDOM() {
2589
- this.nativeElement.removeAttribute('data-slate-string');
2590
- this.nativeElement.textContent = '';
2591
- }
2592
- ngOnInit() {
2593
- this.nativeElement.setAttribute('editable-text', '');
2370
+ destroy() {
2371
+ this.children.forEach((element, index) => {
2372
+ if (this.views[index]) {
2373
+ this.views[index].destroy();
2374
+ }
2375
+ if (this.blockCards[index]) {
2376
+ this.blockCards[index].destroy();
2377
+ }
2378
+ });
2379
+ this.views = [];
2380
+ this.blockCards = [];
2381
+ this.contexts = [];
2382
+ this.viewTypes = [];
2383
+ this.initialized = false;
2384
+ this.differ = null;
2594
2385
  }
2595
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultString, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2596
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateDefaultString, isStandalone: true, selector: "span[slateDefaultString]", usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2597
2386
  }
2598
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultString, decorators: [{
2599
- type: Component,
2600
- args: [{
2601
- selector: 'span[slateDefaultString]',
2602
- template: '',
2603
- changeDetection: ChangeDetectionStrategy.OnPush,
2604
- standalone: true
2605
- }]
2606
- }] });
2607
-
2608
- class SlateString extends ViewContainerItem {
2609
- constructor() {
2610
- super(...arguments);
2611
- this.elementRef = inject(ElementRef);
2612
- this.viewContainerRef = inject(ViewContainerRef);
2613
- }
2614
- ngOnInit() {
2615
- this.createView();
2616
- }
2617
- ngOnChanges() {
2618
- if (!this.initialized) {
2619
- return;
2387
+ function getContext(index, item, parentPath, childrenContext, viewContext) {
2388
+ if (Element.isElement(item)) {
2389
+ const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
2390
+ const key = AngularEditor.findKey(viewContext.editor, item);
2391
+ const isInline = viewContext.editor.isInline(item);
2392
+ const isVoid = viewContext.editor.isVoid(item);
2393
+ const elementContext = {
2394
+ element: item,
2395
+ ...computedContext,
2396
+ attributes: {
2397
+ 'data-slate-node': 'element',
2398
+ 'data-slate-key': key.id
2399
+ },
2400
+ decorate: childrenContext.decorate,
2401
+ readonly: childrenContext.readonly
2402
+ };
2403
+ if (isInline) {
2404
+ elementContext.attributes['data-slate-inline'] = true;
2620
2405
  }
2621
- this.updateView();
2622
- }
2623
- ngAfterViewInit() {
2624
- this.elementRef.nativeElement.remove();
2625
- }
2626
- // COMPAT: If this is the last text node in an empty block, render a zero-
2627
- // width space that will convert into a line break when copying and pasting
2628
- // to support expected plain text.
2629
- isLineBreakEmptyString() {
2630
- return (this.context.leaf.text === '' &&
2631
- this.context.parent.children[this.context.parent.children.length - 1] === this.context.text &&
2632
- !this.viewContext.editor.isInline(this.context.parent) &&
2633
- // [list-render] performance optimization: reduce the number of calls to the `Editor.string(editor, path)` method
2634
- isEmpty(this.viewContext.editor, this.context.parent));
2635
- }
2636
- // COMPAT: If the text is empty, it's because it's on the edge of an inline
2637
- // node, so we render a zero-width space so that the selection can be
2638
- // inserted next to it still.
2639
- isEmptyText() {
2640
- return this.context.leaf.text === '';
2641
- }
2642
- // COMPAT: Browsers will collapse trailing new lines at the end of blocks,
2643
- // so we need to add an extra trailing new lines to prevent that.
2644
- isCompatibleString() {
2645
- return this.context.isLast && this.context.leaf.text.slice(-1) === '\n';
2646
- }
2647
- // COMPAT: Render text inside void nodes with a zero-width space.
2648
- // So the node can contain selection but the text is not visible.
2649
- isVoid() {
2650
- return this.viewContext.editor.isVoid(this.context.parent);
2651
- }
2652
- getViewType() {
2653
- if (this.isVoid()) {
2654
- return this.viewContext.templateComponent.voidStringTemplate;
2406
+ if (isVoid) {
2407
+ elementContext.attributes['data-slate-void'] = true;
2655
2408
  }
2656
- if (this.isLineBreakEmptyString()) {
2657
- return SlateDefaultString;
2409
+ // add contentEditable for block element only to avoid chinese input be broken
2410
+ if (isVoid && !isInline) {
2411
+ elementContext.contentEditable = false;
2658
2412
  }
2659
- if (this.isEmptyText()) {
2660
- return this.viewContext.templateComponent.emptyTextTemplate;
2413
+ return elementContext;
2414
+ }
2415
+ else {
2416
+ const computedContext = getCommonContext(index, item, parentPath, viewContext, childrenContext);
2417
+ const isLeafBlock = AngularEditor.isLeafBlock(viewContext.editor, childrenContext.parent);
2418
+ const textContext = {
2419
+ decorations: computedContext.decorations,
2420
+ isLast: isLeafBlock && index === childrenContext.parent.children.length - 1,
2421
+ parent: childrenContext.parent,
2422
+ text: item
2423
+ };
2424
+ return textContext;
2425
+ }
2426
+ }
2427
+ function getCommonContext(index, item, parentPath, viewContext, childrenContext) {
2428
+ const p = parentPath.concat(index);
2429
+ try {
2430
+ const ds = childrenContext.decorate([item, p]);
2431
+ // [list-render] performance optimization: reduce the number of calls to the `Editor.range(viewContext.editor, p)` method
2432
+ if (childrenContext.selection || childrenContext.decorations.length > 0) {
2433
+ const range = Editor.range(viewContext.editor, p);
2434
+ const sel = childrenContext.selection && Range.intersection(range, childrenContext.selection);
2435
+ for (const dec of childrenContext.decorations) {
2436
+ const d = Range.intersection(dec, range);
2437
+ if (d) {
2438
+ ds.push(d);
2439
+ }
2440
+ }
2441
+ return { selection: sel, decorations: ds };
2661
2442
  }
2662
- if (this.isCompatibleString()) {
2663
- return this.viewContext.templateComponent.compatibleStringTemplate;
2443
+ else {
2444
+ return { selection: null, decorations: ds };
2664
2445
  }
2665
- return SlateDefaultString;
2666
2446
  }
2667
- getType() {
2668
- if (this.isLineBreakEmptyString()) {
2669
- return 'lineBreakEmptyString';
2670
- }
2671
- return 'string';
2447
+ catch (error) {
2448
+ viewContext.editor.onError({
2449
+ code: SlateErrorCode.GetStartPointError,
2450
+ nativeError: error
2451
+ });
2452
+ return { selection: null, decorations: [] };
2672
2453
  }
2673
- getContext() {
2674
- const stringType = this.getType();
2675
- return {
2676
- text: this.context.leaf.text,
2677
- elementStringLength: Node.string(this.context.parent).length,
2678
- type: stringType
2679
- };
2454
+ }
2455
+ function getViewType(item, parent, viewContext) {
2456
+ if (Element.isElement(item)) {
2457
+ return (viewContext.renderElement && viewContext.renderElement(item)) || DefaultElementFlavour;
2680
2458
  }
2681
- memoizedContext(prev, next) {
2682
- return false;
2459
+ else {
2460
+ const isVoid = viewContext.editor.isVoid(parent);
2461
+ return isVoid ? VoidTextFlavour : (viewContext.renderText && viewContext.renderText(item)) || DefaultTextFlavour;
2683
2462
  }
2684
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateString, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2685
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2686
2463
  }
2687
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateString, decorators: [{
2688
- type: Component,
2689
- args: [{
2690
- selector: 'span[slateString]',
2691
- template: '',
2692
- changeDetection: ChangeDetectionStrategy.OnPush,
2693
- standalone: true
2694
- }]
2695
- }], propDecorators: { context: [{
2696
- type: Input
2697
- }] } });
2698
- /**
2699
- * TODO: remove when bump slate
2700
- * copy from slate
2701
- * @param editor
2702
- * @param element
2703
- * @returns
2704
- */
2705
- const isEmpty = (editor, element) => {
2706
- const { children } = element;
2707
- const [first] = children;
2708
- return children.length === 0 || (children.length === 1 && Text$1.isText(first) && first.text === '' && !editor.isVoid(element));
2709
- };
2710
-
2711
- class SlateDefaultLeaf extends BaseLeafComponent {
2712
- onContextChange() {
2713
- super.onContextChange();
2714
- this.renderPlaceholder();
2464
+ function createBlockCard(item, view, viewContainerRef, viewContext) {
2465
+ const isBlockCard = viewContext.editor.isBlockCard(item);
2466
+ if (isBlockCard) {
2467
+ const rootNodes = getRootNodes(view);
2468
+ const blockCardComponentRef = viewContainerRef.createComponent(SlateBlockCard, {
2469
+ injector: viewContainerRef.injector
2470
+ });
2471
+ blockCardComponentRef.instance.initializeCenter(rootNodes);
2472
+ blockCardComponentRef.changeDetectorRef.detectChanges();
2473
+ return blockCardComponentRef;
2715
2474
  }
2716
- ngOnDestroy() {
2717
- // Because the placeholder span is not in the current component, it is destroyed along with the current component
2718
- this.destroyPlaceholder();
2475
+ else {
2476
+ return null;
2719
2477
  }
2720
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultLeaf, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2721
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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 }); }
2722
2478
  }
2723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateDefaultLeaf, decorators: [{
2724
- type: Component,
2725
- args: [{
2726
- selector: 'span[slateDefaultLeaf]',
2727
- template: `<span slateString [context]="context" [viewContext]="viewContext"><span></span></span>`,
2728
- changeDetection: ChangeDetectionStrategy.OnPush,
2729
- host: {
2730
- 'data-slate-leaf': 'true'
2731
- },
2732
- imports: [SlateString]
2733
- }]
2734
- }] });
2735
-
2736
- const SLATE_DEFAULT_LEAF_COMPONENT_TOKEN = new InjectionToken('slate-default-leaf-token');
2479
+ function trackBy(viewContext) {
2480
+ return (index, node) => {
2481
+ return viewContext.trackBy(node) || AngularEditor.findKey(viewContext.editor, node);
2482
+ };
2483
+ }
2484
+ function memoizedContext(viewContext, descendant, prev, next) {
2485
+ if (Element.isElement(descendant)) {
2486
+ return memoizedElementContext(viewContext, prev, next);
2487
+ }
2488
+ else {
2489
+ return memoizedTextContext(prev, next);
2490
+ }
2491
+ }
2492
+ function memoizedElementContext(viewContext, prev, next) {
2493
+ return (prev.element === next.element &&
2494
+ (!viewContext.isStrictDecorate || prev.decorate === next.decorate) &&
2495
+ prev.readonly === next.readonly &&
2496
+ isDecoratorRangeListEqual(prev.decorations, next.decorations) &&
2497
+ (prev.selection === next.selection || (!!prev.selection && !!next.selection && Range.equals(prev.selection, next.selection))));
2498
+ }
2499
+ function memoizedTextContext(prev, next) {
2500
+ return (next.parent === prev.parent &&
2501
+ next.isLast === prev.isLast &&
2502
+ next.text === prev.text &&
2503
+ isDecoratorRangeListEqual(next.decorations, prev.decorations));
2504
+ }
2505
+ function addAfterViewInitQueue(editor, afterViewInitCallback) {
2506
+ const queue = getAfterViewInitQueue(editor);
2507
+ queue.push(afterViewInitCallback);
2508
+ EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, queue);
2509
+ }
2510
+ function getAfterViewInitQueue(editor) {
2511
+ return EDITOR_TO_AFTER_VIEW_INIT_QUEUE.get(editor) || [];
2512
+ }
2513
+ function clearAfterViewInitQueue(editor) {
2514
+ EDITOR_TO_AFTER_VIEW_INIT_QUEUE.set(editor, []);
2515
+ }
2516
+ function executeAfterViewInit(editor) {
2517
+ const queue = getAfterViewInitQueue(editor);
2518
+ queue.forEach(callback => callback());
2519
+ clearAfterViewInitQueue(editor);
2520
+ }
2737
2521
 
2738
2522
  // not correctly clipboardData on beforeinput
2739
2523
  const forceOnDOMPaste = IS_SAFARI;
@@ -2741,16 +2525,12 @@ class SlateEditable {
2741
2525
  get hasBeforeInputSupport() {
2742
2526
  return HAS_BEFORE_INPUT_SUPPORT;
2743
2527
  }
2744
- constructor(elementRef, renderer2, cdr, ngZone, injector, defaultElement, defaultText, defaultVoidText, defaultLeaf) {
2528
+ constructor(elementRef, renderer2, cdr, ngZone, injector) {
2745
2529
  this.elementRef = elementRef;
2746
2530
  this.renderer2 = renderer2;
2747
2531
  this.cdr = cdr;
2748
2532
  this.ngZone = ngZone;
2749
2533
  this.injector = injector;
2750
- this.defaultElement = defaultElement;
2751
- this.defaultText = defaultText;
2752
- this.defaultVoidText = defaultVoidText;
2753
- this.defaultLeaf = defaultLeaf;
2754
2534
  this.destroy$ = new Subject();
2755
2535
  this.isComposing = false;
2756
2536
  this.isDraggingInternally = false;
@@ -2772,6 +2552,7 @@ class SlateEditable {
2772
2552
  this.dataSlateEditor = true;
2773
2553
  this.dataSlateNode = 'value';
2774
2554
  this.dataGramm = false;
2555
+ //#endregion
2775
2556
  this.viewContainerRef = inject(ViewContainerRef);
2776
2557
  this.getOutletParent = () => {
2777
2558
  return this.elementRef.nativeElement;
@@ -2796,8 +2577,6 @@ class SlateEditable {
2796
2577
  });
2797
2578
  this.initializeViewContext();
2798
2579
  this.initializeContext();
2799
- // remove unused DOM, just keep templateComponent instance
2800
- this.templateElementRef.nativeElement.remove();
2801
2580
  // add browser class
2802
2581
  let browserClass = IS_FIREFOX ? 'firefox' : IS_SAFARI ? 'safari' : '';
2803
2582
  browserClass && this.elementRef.nativeElement.classList.add(browserClass);
@@ -2833,7 +2612,9 @@ class SlateEditable {
2833
2612
  this.editor.children = value;
2834
2613
  this.initializeContext();
2835
2614
  if (!this.listRender.initialized) {
2615
+ console.time('initialize list render');
2836
2616
  this.listRender.initialize(this.editor.children, this.editor, this.context);
2617
+ console.timeEnd('initialize list render');
2837
2618
  }
2838
2619
  else {
2839
2620
  this.listRender.update(this.editor.children, this.editor, this.context);
@@ -2968,7 +2749,7 @@ class SlateEditable {
2968
2749
  if (this.isComposing) {
2969
2750
  // Composition input text be not rendered when user composition input with selection is expanded
2970
2751
  // At this time, the following matching conditions are met, assign isComposing to false, and the status is wrong
2971
- // this time condition is true and isComposiing is assigned false
2752
+ // this time condition is true and isComposing is assigned false
2972
2753
  // Therefore, need to wait for the composition input text to be rendered before performing condition matching
2973
2754
  setTimeout(() => {
2974
2755
  const textNode = Node.get(this.editor, this.editor.selection.anchor.path);
@@ -3033,12 +2814,7 @@ class SlateEditable {
3033
2814
  renderLeaf: this.renderLeaf,
3034
2815
  renderText: this.renderText,
3035
2816
  trackBy: this.trackBy,
3036
- isStrictDecorate: this.isStrictDecorate,
3037
- templateComponent: this.templateComponent,
3038
- defaultElement: this.defaultElement,
3039
- defaultText: this.defaultText,
3040
- defaultVoidText: this.defaultVoidText,
3041
- defaultLeaf: this.defaultLeaf
2817
+ isStrictDecorate: this.isStrictDecorate
3042
2818
  };
3043
2819
  }
3044
2820
  composePlaceholderDecorate(editor) {
@@ -3763,30 +3539,14 @@ class SlateEditable {
3763
3539
  this.destroy$.complete();
3764
3540
  EDITOR_TO_ON_CHANGE.delete(this.editor);
3765
3541
  }
3766
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", 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 }); }
3542
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateEditable, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); }
3767
3543
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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: [
3768
3544
  {
3769
3545
  provide: NG_VALUE_ACCESSOR,
3770
3546
  useExisting: forwardRef(() => SlateEditable),
3771
3547
  multi: true
3772
- },
3773
- {
3774
- provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
3775
- useValue: SlateDefaultElement
3776
- },
3777
- {
3778
- provide: SLATE_DEFAULT_TEXT_COMPONENT_TOKEN,
3779
- useValue: SlateDefaultText
3780
- },
3781
- {
3782
- provide: SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN,
3783
- useValue: SlateVoidText
3784
- },
3785
- {
3786
- provide: SLATE_DEFAULT_LEAF_COMPONENT_TOKEN,
3787
- useValue: SlateDefaultLeaf
3788
3548
  }
3789
- ], 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 }); }
3549
+ ], usesOnChanges: true, ngImport: i0, template: "", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3790
3550
  }
3791
3551
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateEditable, decorators: [{
3792
3552
  type: Component,
@@ -3802,37 +3562,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
3802
3562
  provide: NG_VALUE_ACCESSOR,
3803
3563
  useExisting: forwardRef(() => SlateEditable),
3804
3564
  multi: true
3805
- },
3806
- {
3807
- provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
3808
- useValue: SlateDefaultElement
3809
- },
3810
- {
3811
- provide: SLATE_DEFAULT_TEXT_COMPONENT_TOKEN,
3812
- useValue: SlateDefaultText
3813
- },
3814
- {
3815
- provide: SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN,
3816
- useValue: SlateVoidText
3817
- },
3818
- {
3819
- provide: SLATE_DEFAULT_LEAF_COMPONENT_TOKEN,
3820
- useValue: SlateDefaultLeaf
3821
3565
  }
3822
- ], imports: [SlateStringTemplate], template: "<slate-string-template #templateComponent></slate-string-template>\n" }]
3823
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }, { type: undefined, decorators: [{
3824
- type: Inject,
3825
- args: [SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN]
3826
- }] }, { type: undefined, decorators: [{
3827
- type: Inject,
3828
- args: [SLATE_DEFAULT_TEXT_COMPONENT_TOKEN]
3829
- }] }, { type: undefined, decorators: [{
3830
- type: Inject,
3831
- args: [SLATE_DEFAULT_VOID_TEXT_COMPONENT_TOKEN]
3832
- }] }, { type: undefined, decorators: [{
3833
- type: Inject,
3834
- args: [SLATE_DEFAULT_LEAF_COMPONENT_TOKEN]
3835
- }] }], propDecorators: { editor: [{
3566
+ ], imports: [], template: "" }]
3567
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.Injector }], propDecorators: { editor: [{
3836
3568
  type: Input
3837
3569
  }], renderElement: [{
3838
3570
  type: Input
@@ -3899,12 +3631,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
3899
3631
  }], dataGramm: [{
3900
3632
  type: HostBinding,
3901
3633
  args: ['attr.data-gramm']
3902
- }], templateComponent: [{
3903
- type: ViewChild,
3904
- args: ['templateComponent', { static: true }]
3905
- }], templateElementRef: [{
3906
- type: ViewChild,
3907
- args: ['templateComponent', { static: true, read: ElementRef }]
3908
3634
  }] } });
3909
3635
  const defaultScrollSelectionIntoView = (editor, domRange) => {
3910
3636
  // This was affecting the selection of multiple blocks and dragging behavior,
@@ -3922,173 +3648,385 @@ const defaultScrollSelectionIntoView = (editor, domRange) => {
3922
3648
  return;
3923
3649
  }
3924
3650
  }
3925
- leafEl.getBoundingClientRect = domRange.getBoundingClientRect.bind(domRange);
3926
- scrollIntoView(leafEl, {
3927
- scrollMode: 'if-needed'
3651
+ leafEl.getBoundingClientRect = domRange.getBoundingClientRect.bind(domRange);
3652
+ scrollIntoView(leafEl, {
3653
+ scrollMode: 'if-needed'
3654
+ });
3655
+ delete leafEl.getBoundingClientRect;
3656
+ }
3657
+ };
3658
+ /**
3659
+ * Check if the target is inside void and in the editor.
3660
+ */
3661
+ const isTargetInsideVoid = (editor, target) => {
3662
+ let slateNode = null;
3663
+ try {
3664
+ slateNode = AngularEditor.hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target);
3665
+ }
3666
+ catch (error) { }
3667
+ return slateNode && Element.isElement(slateNode) && Editor.isVoid(editor, slateNode);
3668
+ };
3669
+ const hasStringTarget = (domSelection) => {
3670
+ return ((domSelection.anchorNode.parentElement.hasAttribute('data-slate-string') ||
3671
+ domSelection.anchorNode.parentElement.hasAttribute('data-slate-zero-width')) &&
3672
+ (domSelection.focusNode.parentElement.hasAttribute('data-slate-string') ||
3673
+ domSelection.focusNode.parentElement.hasAttribute('data-slate-zero-width')));
3674
+ };
3675
+ /**
3676
+ * remove default insert from composition
3677
+ * @param text
3678
+ */
3679
+ const preventInsertFromComposition = (event, editor) => {
3680
+ const types = ['compositionend', 'insertFromComposition'];
3681
+ if (!types.includes(event.type)) {
3682
+ return;
3683
+ }
3684
+ const insertText = event.data;
3685
+ const window = AngularEditor.getWindow(editor);
3686
+ const domSelection = window.getSelection();
3687
+ // ensure text node insert composition input text
3688
+ if (insertText && domSelection.anchorNode instanceof Text && domSelection.anchorNode.textContent.endsWith(insertText)) {
3689
+ const textNode = domSelection.anchorNode;
3690
+ textNode.splitText(textNode.length - insertText.length).remove();
3691
+ }
3692
+ };
3693
+
3694
+ class SlateChildrenOutlet {
3695
+ constructor(elementRef) {
3696
+ this.elementRef = elementRef;
3697
+ }
3698
+ getNativeElement() {
3699
+ return this.elementRef.nativeElement;
3700
+ }
3701
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildrenOutlet, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
3702
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateChildrenOutlet, isStandalone: true, selector: "slate-children-outlet", ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3703
+ }
3704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildrenOutlet, decorators: [{
3705
+ type: Component,
3706
+ args: [{
3707
+ selector: 'slate-children-outlet',
3708
+ template: ``,
3709
+ changeDetection: ChangeDetectionStrategy.OnPush,
3710
+ standalone: true
3711
+ }]
3712
+ }], ctorParameters: () => [{ type: i0.ElementRef }] });
3713
+
3714
+ class SlateString {
3715
+ ngOnInit() { }
3716
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateString, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3717
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateString, isStandalone: true, selector: "span[slateString]", inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3718
+ }
3719
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateString, decorators: [{
3720
+ type: Component,
3721
+ args: [{
3722
+ selector: 'span[slateString]',
3723
+ template: '',
3724
+ changeDetection: ChangeDetectionStrategy.OnPush,
3725
+ standalone: true
3726
+ }]
3727
+ }], propDecorators: { context: [{
3728
+ type: Input
3729
+ }], viewContext: [{
3730
+ type: Input
3731
+ }] } });
3732
+
3733
+ class SlateModule {
3734
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3735
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, imports: [CommonModule, SlateEditable, SlateBlockCard, SlateChildrenOutlet, SlateString], exports: [SlateEditable, SlateChildrenOutlet, SlateString] }); }
3736
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, imports: [CommonModule] }); }
3737
+ }
3738
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, decorators: [{
3739
+ type: NgModule,
3740
+ args: [{
3741
+ imports: [CommonModule, SlateEditable, SlateBlockCard, SlateChildrenOutlet, SlateString],
3742
+ exports: [SlateEditable, SlateChildrenOutlet, SlateString],
3743
+ providers: []
3744
+ }]
3745
+ }] });
3746
+
3747
+ /**
3748
+ * base class for custom element component or text component
3749
+ */
3750
+ class BaseComponent {
3751
+ constructor() {
3752
+ this.initialized = false;
3753
+ this.elementRef = inject(ElementRef);
3754
+ this.cdr = inject(ChangeDetectorRef);
3755
+ }
3756
+ set context(value) {
3757
+ if (hasBeforeContextChange(this)) {
3758
+ this.beforeContextChange(value);
3759
+ }
3760
+ this._context = value;
3761
+ this.onContextChange();
3762
+ if (this.initialized) {
3763
+ this.cdr.detectChanges();
3764
+ }
3765
+ if (hasAfterContextChange(this)) {
3766
+ this.afterContextChange();
3767
+ }
3768
+ }
3769
+ get context() {
3770
+ return this._context;
3771
+ }
3772
+ get editor() {
3773
+ return this.viewContext && this.viewContext.editor;
3774
+ }
3775
+ get nativeElement() {
3776
+ return this.elementRef.nativeElement;
3777
+ }
3778
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3779
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseComponent, isStandalone: true, inputs: { context: "context", viewContext: "viewContext" }, ngImport: i0 }); }
3780
+ }
3781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseComponent, decorators: [{
3782
+ type: Directive
3783
+ }], propDecorators: { context: [{
3784
+ type: Input
3785
+ }], viewContext: [{
3786
+ type: Input
3787
+ }] } });
3788
+ /**
3789
+ * base class for custom element component
3790
+ */
3791
+ class BaseElementComponent extends BaseComponent {
3792
+ constructor() {
3793
+ super(...arguments);
3794
+ this.viewContainerRef = inject(ViewContainerRef);
3795
+ this.getOutletParent = () => {
3796
+ return this.elementRef.nativeElement;
3797
+ };
3798
+ this.getOutletElement = () => {
3799
+ if (this.childrenOutletInstance) {
3800
+ return this.childrenOutletInstance.getNativeElement();
3801
+ }
3802
+ return null;
3803
+ };
3804
+ }
3805
+ get element() {
3806
+ return this._context && this._context.element;
3807
+ }
3808
+ get selection() {
3809
+ return this._context && this._context.selection;
3810
+ }
3811
+ get decorations() {
3812
+ return this._context && this._context.decorations;
3813
+ }
3814
+ get children() {
3815
+ return this._context && this._context.element.children;
3816
+ }
3817
+ get isCollapsed() {
3818
+ return this.selection && Range.isCollapsed(this.selection);
3819
+ }
3820
+ get isCollapsedAndNonReadonly() {
3821
+ return this.selection && Range.isCollapsed(this.selection) && !this.readonly;
3822
+ }
3823
+ get readonly() {
3824
+ return this._context && this._context.readonly;
3825
+ }
3826
+ ngOnInit() {
3827
+ for (const key in this._context.attributes) {
3828
+ this.nativeElement.setAttribute(key, this._context.attributes[key]);
3829
+ }
3830
+ this.initialized = true;
3831
+ this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
3832
+ if (this.editor.isExpanded(this.element)) {
3833
+ this.listRender.initialize(this.children, this.element, this.childrenContext);
3834
+ }
3835
+ addAfterViewInitQueue(this.editor, () => {
3836
+ this.afterViewInit();
3928
3837
  });
3929
- delete leafEl.getBoundingClientRect;
3930
3838
  }
3931
- };
3932
- /**
3933
- * Check if the target is inside void and in the editor.
3934
- */
3935
- const isTargetInsideVoid = (editor, target) => {
3936
- let slateNode = null;
3937
- try {
3938
- slateNode = AngularEditor.hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target);
3839
+ afterViewInit() {
3840
+ if (this._context.contentEditable !== undefined) {
3841
+ this.nativeElement.setAttribute('contenteditable', this._context.contentEditable + '');
3842
+ }
3939
3843
  }
3940
- catch (error) { }
3941
- return slateNode && Element.isElement(slateNode) && Editor.isVoid(editor, slateNode);
3942
- };
3943
- const hasStringTarget = (domSelection) => {
3944
- return ((domSelection.anchorNode.parentElement.hasAttribute('data-slate-string') ||
3945
- domSelection.anchorNode.parentElement.hasAttribute('data-slate-zero-width')) &&
3946
- (domSelection.focusNode.parentElement.hasAttribute('data-slate-string') ||
3947
- domSelection.focusNode.parentElement.hasAttribute('data-slate-zero-width')));
3948
- };
3949
- /**
3950
- * remove default insert from composition
3951
- * @param text
3952
- */
3953
- const preventInsertFromComposition = (event, editor) => {
3954
- const types = ['compositionend', 'insertFromComposition'];
3955
- if (!types.includes(event.type)) {
3956
- return;
3844
+ updateWeakMap() {
3845
+ NODE_TO_ELEMENT.set(this.element, this.nativeElement);
3846
+ ELEMENT_TO_NODE.set(this.nativeElement, this.element);
3847
+ ELEMENT_TO_COMPONENT.set(this.element, this);
3957
3848
  }
3958
- const insertText = event.data;
3959
- const window = AngularEditor.getWindow(editor);
3960
- const domSelection = window.getSelection();
3961
- // ensure text node insert composition input text
3962
- if (insertText && domSelection.anchorNode instanceof Text && domSelection.anchorNode.textContent.endsWith(insertText)) {
3963
- const textNode = domSelection.anchorNode;
3964
- textNode.splitText(textNode.length - insertText.length).remove();
3849
+ ngOnDestroy() {
3850
+ if (NODE_TO_ELEMENT.get(this.element) === this.nativeElement) {
3851
+ NODE_TO_ELEMENT.delete(this.element);
3852
+ }
3853
+ ELEMENT_TO_NODE.delete(this.nativeElement);
3854
+ if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
3855
+ ELEMENT_TO_COMPONENT.delete(this.element);
3856
+ }
3965
3857
  }
3966
- };
3967
-
3968
- class SlateElement extends BaseElementComponent {
3969
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateElement, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3970
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateElement, isStandalone: true, selector: "[slateElement]", usesInheritance: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3858
+ onContextChange() {
3859
+ this.childrenContext = this.getChildrenContext();
3860
+ this.updateWeakMap();
3861
+ if (!this.initialized) {
3862
+ return;
3863
+ }
3864
+ this.updateChildrenView();
3865
+ }
3866
+ updateChildrenView() {
3867
+ if (this.editor.isExpanded(this.element)) {
3868
+ this.listRender.update(this.children, this.element, this.childrenContext);
3869
+ }
3870
+ else {
3871
+ if (this.listRender.initialized) {
3872
+ this.listRender.destroy();
3873
+ }
3874
+ }
3875
+ }
3876
+ getChildrenContext() {
3877
+ return {
3878
+ parent: this._context.element,
3879
+ selection: this._context.selection,
3880
+ decorations: this._context.decorations,
3881
+ decorate: this._context.decorate,
3882
+ readonly: this._context.readonly
3883
+ };
3884
+ }
3885
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseElementComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
3886
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseElementComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
3971
3887
  }
3972
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateElement, decorators: [{
3973
- type: Component,
3974
- args: [{
3975
- selector: '[slateElement]',
3976
- template: '<ng-content></ng-content>',
3977
- changeDetection: ChangeDetectionStrategy.OnPush
3978
- }]
3979
- }] });
3980
-
3888
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseElementComponent, decorators: [{
3889
+ type: Directive
3890
+ }], propDecorators: { childrenOutletInstance: [{
3891
+ type: ViewChild,
3892
+ args: [SlateChildrenOutlet, { static: true }]
3893
+ }] } });
3981
3894
  /**
3982
- * @deprecated
3983
- * the special container for angular template
3984
- * Add the rootNodes of each child component to the parentElement
3985
- * Remove useless DOM elements, eg: comment...
3895
+ * base class for custom text component
3986
3896
  */
3987
- class ViewContainer {
3988
- constructor(elementRef, differs) {
3989
- this.elementRef = elementRef;
3990
- this.differs = differs;
3897
+ class BaseTextComponent extends BaseComponent {
3898
+ constructor() {
3899
+ super(...arguments);
3900
+ this.viewContainerRef = inject(ViewContainerRef);
3901
+ this.getOutletParent = () => {
3902
+ return this.elementRef.nativeElement;
3903
+ };
3904
+ this.getOutletElement = () => {
3905
+ if (this.childrenOutletInstance) {
3906
+ return this.childrenOutletInstance.getNativeElement();
3907
+ }
3908
+ return null;
3909
+ };
3910
+ }
3911
+ get text() {
3912
+ return this._context && this._context.text;
3913
+ }
3914
+ ngOnInit() {
3915
+ this.initialized = true;
3916
+ this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
3917
+ this.leavesRender.initialize(this.context);
3918
+ }
3919
+ updateWeakMap() {
3920
+ ELEMENT_TO_NODE.set(this.nativeElement, this.text);
3921
+ NODE_TO_ELEMENT.set(this.text, this.nativeElement);
3922
+ }
3923
+ ngOnDestroy() {
3924
+ if (NODE_TO_ELEMENT.get(this.text) === this.nativeElement) {
3925
+ NODE_TO_ELEMENT.delete(this.text);
3926
+ }
3927
+ ELEMENT_TO_NODE.delete(this.nativeElement);
3928
+ }
3929
+ onContextChange() {
3930
+ this.updateWeakMap();
3931
+ if (!this.initialized) {
3932
+ return;
3933
+ }
3934
+ this.leavesRender.update(this.context);
3991
3935
  }
3992
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ViewContainer, deps: [{ token: i0.ElementRef }, { token: i0.IterableDiffers }], target: i0.ɵɵFactoryTarget.Directive }); }
3993
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: ViewContainer, isStandalone: true, inputs: { viewContext: "viewContext" }, ngImport: i0 }); }
3936
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseTextComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
3937
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseTextComponent, isStandalone: true, viewQueries: [{ propertyName: "childrenOutletInstance", first: true, predicate: SlateChildrenOutlet, descendants: true, static: true }], usesInheritance: true, ngImport: i0 }); }
3994
3938
  }
3995
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ViewContainer, decorators: [{
3939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseTextComponent, decorators: [{
3996
3940
  type: Directive
3997
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.IterableDiffers }], propDecorators: { viewContext: [{
3998
- type: Input
3999
- }] } });
4000
-
4001
- class SlateChildren extends ViewContainer {
4002
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildren, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4003
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", 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 }); }
4004
- }
4005
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateChildren, decorators: [{
4006
- type: Component,
4007
- args: [{
4008
- selector: 'slate-children',
4009
- template: ``,
4010
- changeDetection: ChangeDetectionStrategy.OnPush,
4011
- standalone: true
4012
- }]
4013
- }], propDecorators: { children: [{
4014
- type: Input
4015
- }], context: [{
4016
- type: Input
4017
- }], viewContext: [{
4018
- type: Input
3941
+ }], propDecorators: { childrenOutletInstance: [{
3942
+ type: ViewChild,
3943
+ args: [SlateChildrenOutlet, { static: true }]
4019
3944
  }] } });
4020
-
4021
- class SlateLeaves extends ViewContainer {
3945
+ /**
3946
+ * base class for custom leaf component
3947
+ */
3948
+ class BaseLeafComponent extends BaseComponent {
4022
3949
  constructor() {
4023
3950
  super(...arguments);
4024
- this.initialized = false;
3951
+ this.stringRender = null;
3952
+ this.isSlateLeaf = true;
4025
3953
  }
4026
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateLeaves, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4027
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: SlateLeaves, isStandalone: true, selector: "slate-leaves", inputs: { context: "context" }, usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4028
- }
4029
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateLeaves, decorators: [{
4030
- type: Component,
4031
- args: [{
4032
- selector: 'slate-leaves',
4033
- template: ``,
4034
- changeDetection: ChangeDetectionStrategy.OnPush,
4035
- imports: []
4036
- }]
4037
- }], propDecorators: { context: [{
4038
- type: Input
4039
- }] } });
4040
-
4041
- class SlateModule {
4042
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4043
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, imports: [CommonModule,
4044
- SlateEditable,
4045
- SlateDefaultElement,
4046
- SlateElement,
4047
- SlateVoidText,
4048
- SlateDefaultText,
4049
- SlateString,
4050
- SlateStringTemplate,
4051
- SlateChildren,
4052
- SlateBlockCard,
4053
- SlateLeaves,
4054
- SlateDefaultLeaf,
4055
- SlateDefaultString,
4056
- SlateChildrenOutlet], exports: [SlateEditable, SlateChildren, SlateChildrenOutlet, SlateElement, SlateLeaves, SlateString, SlateDefaultString] }); }
4057
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, providers: [
4058
- {
4059
- provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
4060
- useValue: SlateDefaultElement
3954
+ get text() {
3955
+ return this.context && this.context.text;
3956
+ }
3957
+ get leaf() {
3958
+ return this.context && this.context.leaf;
3959
+ }
3960
+ ngOnInit() {
3961
+ this.initialized = true;
3962
+ }
3963
+ onContextChange() {
3964
+ if (!this.initialized) {
3965
+ this.stringRender = new SlateStringRender(this.context, this.viewContext);
3966
+ const stringNode = this.stringRender.render();
3967
+ this.nativeElement.appendChild(stringNode);
3968
+ }
3969
+ else {
3970
+ this.stringRender?.update(this.context, this.viewContext);
3971
+ }
3972
+ if (!this.initialized) {
3973
+ return;
3974
+ }
3975
+ }
3976
+ renderPlaceholder() {
3977
+ // issue-1: IME input was interrupted
3978
+ // issue-2: IME input focus jumping
3979
+ // Issue occurs when the span node of the placeholder is before the slateString span node
3980
+ if (this.context.leaf['placeholder']) {
3981
+ if (!this.placeholderElement) {
3982
+ this.createPlaceholder();
3983
+ }
3984
+ this.updatePlaceholder();
3985
+ }
3986
+ else {
3987
+ this.destroyPlaceholder();
3988
+ }
3989
+ }
3990
+ createPlaceholder() {
3991
+ const placeholderElement = document.createElement('span');
3992
+ placeholderElement.innerText = this.context.leaf['placeholder'];
3993
+ placeholderElement.contentEditable = 'false';
3994
+ placeholderElement.setAttribute('data-slate-placeholder', 'true');
3995
+ this.placeholderElement = placeholderElement;
3996
+ this.nativeElement.classList.add('leaf-with-placeholder');
3997
+ this.nativeElement.appendChild(placeholderElement);
3998
+ setTimeout(() => {
3999
+ const editorElement = this.nativeElement.closest('.the-editor-typo');
4000
+ const editorContentHeight = getContentHeight(editorElement);
4001
+ if (editorContentHeight > 0) {
4002
+ // Not supported webkitLineClamp exceeds height hiding
4003
+ placeholderElement.style.maxHeight = `${editorContentHeight}px`;
4061
4004
  }
4062
- ], imports: [CommonModule] }); }
4005
+ const lineClamp = Math.floor(editorContentHeight / this.nativeElement.offsetHeight) || 0;
4006
+ placeholderElement.style.webkitLineClamp = `${Math.max(lineClamp, 1)}`;
4007
+ });
4008
+ }
4009
+ updatePlaceholder() {
4010
+ if (this.placeholderElement.innerText !== this.context.leaf['placeholder']) {
4011
+ this.placeholderElement.innerText = this.context.leaf['placeholder'];
4012
+ }
4013
+ }
4014
+ destroyPlaceholder() {
4015
+ if (this.placeholderElement) {
4016
+ this.placeholderElement.remove();
4017
+ this.placeholderElement = null;
4018
+ this.nativeElement.classList.remove('leaf-with-placeholder');
4019
+ }
4020
+ }
4021
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseLeafComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
4022
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseLeafComponent, isStandalone: true, host: { properties: { "attr.data-slate-leaf": "this.isSlateLeaf" } }, usesInheritance: true, ngImport: i0 }); }
4063
4023
  }
4064
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: SlateModule, decorators: [{
4065
- type: NgModule,
4066
- args: [{
4067
- imports: [
4068
- CommonModule,
4069
- SlateEditable,
4070
- SlateDefaultElement,
4071
- SlateElement,
4072
- SlateVoidText,
4073
- SlateDefaultText,
4074
- SlateString,
4075
- SlateStringTemplate,
4076
- SlateChildren,
4077
- SlateBlockCard,
4078
- SlateLeaves,
4079
- SlateDefaultLeaf,
4080
- SlateDefaultString,
4081
- SlateChildrenOutlet
4082
- ],
4083
- exports: [SlateEditable, SlateChildren, SlateChildrenOutlet, SlateElement, SlateLeaves, SlateString, SlateDefaultString],
4084
- providers: [
4085
- {
4086
- provide: SLATE_DEFAULT_ELEMENT_COMPONENT_TOKEN,
4087
- useValue: SlateDefaultElement
4088
- }
4089
- ]
4090
- }]
4091
- }] });
4024
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseLeafComponent, decorators: [{
4025
+ type: Directive
4026
+ }], propDecorators: { isSlateLeaf: [{
4027
+ type: HostBinding,
4028
+ args: ['attr.data-slate-leaf']
4029
+ }] } });
4092
4030
 
4093
4031
  /*
4094
4032
  * Public API Surface of slate-angular
@@ -4098,5 +4036,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
4098
4036
  * Generated bundle index. Do not edit.
4099
4037
  */
4100
4038
 
4101
- export { AngularEditor, BaseComponent, BaseElementComponent, BaseLeafComponent, BaseTextComponent, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, PLACEHOLDER_SYMBOL, SlateChildren, SlateChildrenOutlet, SlateDefaultString, SlateEditable, SlateElement, SlateErrorCode, SlateFragmentAttributeKey, SlateLeaves, SlateModule, SlateString, blobAsString, buildHTMLText, check, completeTable, createClipboardData, createThrottleRAF, defaultScrollSelectionIntoView, fallbackCopyText, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getContentHeight, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, getPlainText, getSelection, getSlateFragmentAttribute, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDOMText, isDecoratorRangeListEqual, isEmpty, isInvalidTable, isTemplateRef, isValid, normalize, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
4039
+ export { AngularEditor, BaseComponent, BaseElementComponent, BaseElementFlavour, BaseFlavour, BaseLeafComponent, BaseLeafFlavour, BaseTextComponent, BaseTextFlavour, DefaultTextFlavour, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, ELEMENT_TO_COMPONENT, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, FlavourRef, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_IOS, IS_QQBROWSER, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, PLACEHOLDER_SYMBOL, SlateChildrenOutlet, SlateEditable, SlateErrorCode, SlateFragmentAttributeKey, SlateModule, SlateString, VoidTextFlavour, blobAsString, buildHTMLText, check, completeTable, createClipboardData, createText, createThrottleRAF, defaultScrollSelectionIntoView, fallbackCopyText, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getContentHeight, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, getPlainText, getSelection, getSlateFragmentAttribute, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDOMText, isDecoratorRangeListEqual, isFlavourType, isInvalidTable, isTemplateRef, isValid, normalize, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
4102
4040
  //# sourceMappingURL=slate-angular.mjs.map