slate-angular 1.7.1 → 1.8.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.
@@ -550,6 +550,34 @@
550
550
  }
551
551
  return text;
552
552
  };
553
+ /**
554
+ * Get x-slate-fragment attribute from data-slate-fragment
555
+ */
556
+ var catchSlateFragment = /data-slate-fragment="(.+?)"/m;
557
+ var getSlateFragmentAttribute = function (dataTransfer) {
558
+ var htmlData = dataTransfer.getData('text/html');
559
+ var _a = __read(htmlData.match(catchSlateFragment) || [], 2), fragment = _a[1];
560
+ return fragment;
561
+ };
562
+ /**
563
+ * Get the x-slate-fragment attribute that exist in text/html data
564
+ * and append it to the DataTransfer object
565
+ */
566
+ var getClipboardData = function (dataTransfer, clipboardFormatKey) {
567
+ if (clipboardFormatKey === void 0) { clipboardFormatKey = 'x-slate-fragment'; }
568
+ if (!dataTransfer.getData("application/" + clipboardFormatKey)) {
569
+ var fragment = getSlateFragmentAttribute(dataTransfer);
570
+ if (fragment) {
571
+ var clipboardData_1 = new DataTransfer();
572
+ dataTransfer.types.forEach(function (type) {
573
+ clipboardData_1.setData(type, dataTransfer.getData(type));
574
+ });
575
+ clipboardData_1.setData("application/" + clipboardFormatKey, fragment);
576
+ return clipboardData_1;
577
+ }
578
+ }
579
+ return dataTransfer;
580
+ };
553
581
 
554
582
  /**
555
583
  * An auto-incrementing identifier for keys.
@@ -571,6 +599,7 @@
571
599
  /iPad|iPhone|iPod/.test(navigator.userAgent) &&
572
600
  !window.MSStream;
573
601
  var IS_APPLE = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent);
602
+ var IS_ANDROID = typeof navigator !== 'undefined' && /Android/.test(navigator.userAgent);
574
603
  var IS_FIREFOX = typeof navigator !== 'undefined' &&
575
604
  /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
576
605
  var IS_SAFARI = typeof navigator !== 'undefined' &&
@@ -582,6 +611,24 @@
582
611
  // Native beforeInput events don't work well with react on Chrome 75 and older, Chrome 76+ can use beforeInput
583
612
  var IS_CHROME_LEGACY = typeof navigator !== 'undefined' &&
584
613
  /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent);
614
+ // Firefox did not support `beforeInput` until `v87`.
615
+ var IS_FIREFOX_LEGACY = typeof navigator !== 'undefined' &&
616
+ /^(?!.*Seamonkey)(?=.*Firefox\/(?:[0-7][0-9]|[0-8][0-6])).*/i.test(navigator.userAgent);
617
+ // qq browser
618
+ var IS_QQBROWSER = typeof navigator !== 'undefined' && /.*QQBrowser/.test(navigator.userAgent);
619
+ // UC mobile browser
620
+ var IS_UC_MOBILE = typeof navigator !== 'undefined' && /.*UCBrowser/.test(navigator.userAgent);
621
+ // Wechat browser
622
+ var IS_WECHATBROWSER = typeof navigator !== 'undefined' && /.*Wechat/.test(navigator.userAgent);
623
+ // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
624
+ // Chrome Legacy doesn't support `beforeinput` correctly
625
+ var HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
626
+ !IS_EDGE_LEGACY &&
627
+ // globalThis is undefined in older browsers
628
+ typeof globalThis !== 'undefined' &&
629
+ globalThis.InputEvent &&
630
+ // @ts-ignore The `getTargetRanges` property isn't recognized.
631
+ typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
585
632
 
586
633
  var FAKE_LEFT_BLOCK_CARD_OFFSET = -1;
587
634
  var FAKE_RIGHT_BLOCK_CARD_OFFSET = -2;
@@ -664,27 +711,16 @@
664
711
  throw new Error("Unable to find the path for Slate node: " + JSON.stringify(node));
665
712
  },
666
713
  /**
667
- * Find the DOM node that implements DocumentOrShadowRoot for the editor.
668
- */
714
+ * Find the DOM node that implements DocumentOrShadowRoot for the editor.
715
+ */
669
716
  findDocumentOrShadowRoot: function (editor) {
670
717
  var el = AngularEditor.toDOMNode(editor, editor);
671
718
  var root = el.getRootNode();
672
- // The below exception will always be thrown for iframes because the document inside an iframe
673
- // does not inherit it's prototype from the parent document, therefore we return early
674
- if (el.ownerDocument !== document) {
675
- return el.ownerDocument;
676
- }
677
- if (!(root instanceof Document || root instanceof ShadowRoot)) {
678
- throw new Error("Unable to find DocumentOrShadowRoot for editor element: " + el);
679
- }
680
- // COMPAT: Only Chrome implements the DocumentOrShadowRoot mixin for
681
- // ShadowRoot; other browsers still implement it on the Document
682
- // interface. (2020/08/08)
683
- // https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot#Properties
684
- if (root.getSelection === undefined && el.ownerDocument !== null) {
685
- return el.ownerDocument;
686
- }
687
- return root;
719
+ if ((root instanceof Document || root instanceof ShadowRoot) &&
720
+ root.getSelection != null) {
721
+ return root;
722
+ }
723
+ return el.ownerDocument;
688
724
  },
689
725
  /**
690
726
  * Check if the editor is focused.
@@ -782,6 +818,18 @@
782
818
  insertData: function (editor, data) {
783
819
  editor.insertData(data);
784
820
  },
821
+ /**
822
+ * Insert fragment data from a `DataTransfer` into the editor.
823
+ */
824
+ insertFragmentData: function (editor, data) {
825
+ return editor.insertFragmentData(data);
826
+ },
827
+ /**
828
+ * Insert text data from a `DataTransfer` into the editor.
829
+ */
830
+ insertTextData: function (editor, data) {
831
+ return editor.insertTextData(data);
832
+ },
785
833
  /**
786
834
  * onKeydown hook.
787
835
  */
@@ -797,8 +845,8 @@
797
845
  /**
798
846
  * Sets data from the currently selected fragment on a `DataTransfer`.
799
847
  */
800
- setFragmentData: function (editor, data) {
801
- editor.setFragmentData(data);
848
+ setFragmentData: function (editor, data, originEvent) {
849
+ editor.setFragmentData(data, originEvent);
802
850
  },
803
851
  deleteCutData: function (editor) {
804
852
  editor.deleteCutData();
@@ -1063,7 +1111,9 @@
1063
1111
  // composition the ASCII characters will be prepended to the zero-width
1064
1112
  // space, so subtract 1 from the offset to account for the zero-width
1065
1113
  // space character.
1066
- if (domNode_1 && offset === domNode_1.textContent.length && parentNode && parentNode.hasAttribute('data-slate-zero-width')) {
1114
+ if (domNode_1 &&
1115
+ offset === domNode_1.textContent.length &&
1116
+ (parentNode && parentNode.hasAttribute('data-slate-zero-width'))) {
1067
1117
  offset--;
1068
1118
  }
1069
1119
  }
@@ -1519,7 +1569,7 @@
1519
1569
  // in the HTML, and can be used for intra-Slate pasting. If it's a text
1520
1570
  // node, wrap it in a `<span>` so we have something to set an attribute on.
1521
1571
  if (isDOMText(attach)) {
1522
- var span = document.createElement('span');
1572
+ var span = attach.ownerDocument.createElement('span');
1523
1573
  // COMPAT: In Chrome and Safari, if we don't add the `white-space` style
1524
1574
  // then leading and trailing spaces will be ignored. (2017/09/21)
1525
1575
  span.style.whiteSpace = 'pre';
@@ -1533,13 +1583,14 @@
1533
1583
  attach.setAttribute('data-slate-fragment', encoded);
1534
1584
  data.setData("application/" + clipboardFormatKey, encoded);
1535
1585
  // Add the content to a <div> so that we can get its inner HTML.
1536
- var div = document.createElement('div');
1586
+ var div = contents.ownerDocument.createElement('div');
1537
1587
  div.appendChild(contents);
1538
1588
  div.setAttribute('hidden', 'true');
1539
- document.body.appendChild(div);
1589
+ contents.ownerDocument.body.appendChild(div);
1540
1590
  data.setData('text/html', div.innerHTML);
1541
1591
  data.setData('text/plain', getPlainText(div));
1542
- document.body.removeChild(div);
1592
+ contents.ownerDocument.body.removeChild(div);
1593
+ return data;
1543
1594
  };
1544
1595
  e.deleteCutData = function () {
1545
1596
  var selection = editor.selection;
@@ -1556,14 +1607,26 @@
1556
1607
  }
1557
1608
  };
1558
1609
  e.insertData = function (data) {
1559
- var e_5, _a;
1560
- var fragment = data.getData("application/" + clipboardFormatKey);
1610
+ if (!e.insertFragmentData(data)) {
1611
+ e.insertTextData(data);
1612
+ }
1613
+ };
1614
+ e.insertFragmentData = function (data) {
1615
+ /**
1616
+ * Checking copied fragment from application/x-slate-fragment or data-slate-fragment
1617
+ */
1618
+ var fragment = data.getData("application/" + clipboardFormatKey) ||
1619
+ getSlateFragmentAttribute(data);
1561
1620
  if (fragment) {
1562
1621
  var decoded = decodeURIComponent(window.atob(fragment));
1563
1622
  var parsed = JSON.parse(decoded);
1564
1623
  e.insertFragment(parsed);
1565
- return;
1624
+ return true;
1566
1625
  }
1626
+ return false;
1627
+ };
1628
+ e.insertTextData = function (data) {
1629
+ var e_5, _a;
1567
1630
  var text = data.getData('text/plain');
1568
1631
  if (text) {
1569
1632
  var lines = text.split(/\r\n|\r|\n/);
@@ -1585,7 +1648,9 @@
1585
1648
  }
1586
1649
  finally { if (e_5) throw e_5.error; }
1587
1650
  }
1651
+ return true;
1588
1652
  }
1653
+ return false;
1589
1654
  };
1590
1655
  e.onKeydown = function () { };
1591
1656
  e.onClick = function () { };
@@ -2177,6 +2242,31 @@
2177
2242
  }
2178
2243
  this.cdr.markForCheck();
2179
2244
  };
2245
+ BaseLeafComponent.prototype.renderPlaceholder = function () {
2246
+ // issue-1: IME input was interrupted
2247
+ // issue-2: IME input focus jumping
2248
+ // Issue occurs when the span node of the placeholder is before the slateString span node
2249
+ if (this.context.leaf['placeholder']) {
2250
+ if (!this.placeholderElement) {
2251
+ this.placeholderElement = document.createElement('span');
2252
+ this.placeholderElement.innerText = this.context.leaf['placeholder'];
2253
+ this.placeholderElement.contentEditable = 'false';
2254
+ this.placeholderElement.setAttribute('data-slate-placeholder', 'true');
2255
+ this.nativeElement.classList.add('leaf-with-placeholder');
2256
+ this.nativeElement.appendChild(this.placeholderElement);
2257
+ }
2258
+ }
2259
+ else {
2260
+ this.destroyPlaceholder();
2261
+ }
2262
+ };
2263
+ BaseLeafComponent.prototype.destroyPlaceholder = function () {
2264
+ if (this.placeholderElement) {
2265
+ this.placeholderElement.remove();
2266
+ this.placeholderElement = null;
2267
+ this.nativeElement.classList.remove('leaf-with-placeholder');
2268
+ }
2269
+ };
2180
2270
  return BaseLeafComponent;
2181
2271
  }(BaseComponent));
2182
2272
  BaseLeafComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.7", ngImport: i0__namespace, type: BaseLeafComponent, deps: null, target: i0__namespace.ɵɵFactoryTarget.Directive });
@@ -2503,15 +2593,23 @@
2503
2593
  function SlateDefaultLeafComponent() {
2504
2594
  return _super !== null && _super.apply(this, arguments) || this;
2505
2595
  }
2596
+ SlateDefaultLeafComponent.prototype.onContextChange = function () {
2597
+ _super.prototype.onContextChange.call(this);
2598
+ this.renderPlaceholder();
2599
+ };
2600
+ SlateDefaultLeafComponent.prototype.ngOnDestroy = function () {
2601
+ // Because the placeholder span is not in the current component, it is destroyed along with the current component
2602
+ this.destroyPlaceholder();
2603
+ };
2506
2604
  return SlateDefaultLeafComponent;
2507
2605
  }(BaseLeafComponent));
2508
2606
  SlateDefaultLeafComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.7", ngImport: i0__namespace, type: SlateDefaultLeafComponent, deps: null, target: i0__namespace.ɵɵFactoryTarget.Component });
2509
- SlateDefaultLeafComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.7", type: SlateDefaultLeafComponent, selector: "span[slateDefaultLeaf]", host: { attributes: { "data-slate-leaf": "true" } }, usesInheritance: true, ngImport: i0__namespace, template: "\n <ng-container *ngIf=\"context.leaf['placeholder']\">\n <span contenteditable=\"false\" data-slate-placeholder=\"true\" slate-placeholder=\"true\">{{context.leaf['placeholder']}}</span>\n </ng-container>\n <span slateString [context]=\"context\" [viewContext]=\"viewContext\"><span>", isInline: true, components: [{ type: SlateStringComponent, selector: "span[slateString]", inputs: ["context"] }], directives: [{ type: i2__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0__namespace.ChangeDetectionStrategy.OnPush });
2607
+ SlateDefaultLeafComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.7", type: SlateDefaultLeafComponent, selector: "span[slateDefaultLeaf]", host: { attributes: { "data-slate-leaf": "true" } }, usesInheritance: true, ngImport: i0__namespace, template: "<span slateString [context]=\"context\" [viewContext]=\"viewContext\"><span>", isInline: true, components: [{ type: SlateStringComponent, selector: "span[slateString]", inputs: ["context"] }], changeDetection: i0__namespace.ChangeDetectionStrategy.OnPush });
2510
2608
  i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.7", ngImport: i0__namespace, type: SlateDefaultLeafComponent, decorators: [{
2511
2609
  type: i0.Component,
2512
2610
  args: [{
2513
2611
  selector: 'span[slateDefaultLeaf]',
2514
- template: "\n <ng-container *ngIf=\"context.leaf['placeholder']\">\n <span contenteditable=\"false\" data-slate-placeholder=\"true\" slate-placeholder=\"true\">{{context.leaf['placeholder']}}</span>\n </ng-container>\n <span slateString [context]=\"context\" [viewContext]=\"viewContext\"><span>",
2612
+ template: "<span slateString [context]=\"context\" [viewContext]=\"viewContext\"><span>",
2515
2613
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
2516
2614
  host: {
2517
2615
  'data-slate-leaf': 'true'
@@ -2927,13 +3025,6 @@
2927
3025
  }] } });
2928
3026
 
2929
3027
  var timeDebug = Debug__default["default"]('slate-angular-time');
2930
- // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
2931
- // Chrome Legacy doesn't support `beforeinput` correctly
2932
- var HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
2933
- !IS_EDGE_LEGACY &&
2934
- globalThis.InputEvent &&
2935
- // @ts-ignore The `getTargetRanges` property isn't recognized.
2936
- typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
2937
3028
  // not correctly clipboardData on beforeinput
2938
3029
  var forceOnDOMPaste = IS_SAFARI;
2939
3030
  var SlateEditableComponent = /** @class */ (function () {
@@ -2993,6 +3084,9 @@
2993
3084
  this.initializeContext();
2994
3085
  // remove unused DOM, just keep templateComponent instance
2995
3086
  this.templateElementRef.nativeElement.remove();
3087
+ // add browser class
3088
+ var browserClass = IS_FIREFOX ? 'firefox' : (IS_SAFARI ? 'safari' : '');
3089
+ browserClass && this.elementRef.nativeElement.classList.add(browserClass);
2996
3090
  };
2997
3091
  SlateEditableComponent.prototype.ngOnChanges = function (simpleChanges) {
2998
3092
  if (!this.initialized) {
@@ -3371,7 +3465,10 @@
3371
3465
  case 'insertFromYank':
3372
3466
  case 'insertReplacementText':
3373
3467
  case 'insertText': {
3374
- if (data instanceof DataTransfer) {
3468
+ // use a weak comparison instead of 'instanceof' to allow
3469
+ // programmatic access of paste events coming from external windows
3470
+ // like cypress where cy.window does not work realibly
3471
+ if ((data === null || data === void 0 ? void 0 : data.constructor.name) === 'DataTransfer') {
3375
3472
  AngularEditor.insertData(editor, data);
3376
3473
  }
3377
3474
  else if (typeof data === 'string') {
@@ -3483,13 +3580,13 @@
3483
3580
  var isOutsideSlate = !hasStringTarget(window.getSelection()) && isTargetInsideVoid(this.editor, event.target);
3484
3581
  if (!isOutsideSlate && hasTarget(this.editor, event.target) && !this.readonly && !this.isDOMEventHandled(event, this.copy)) {
3485
3582
  event.preventDefault();
3486
- AngularEditor.setFragmentData(this.editor, event.clipboardData);
3583
+ AngularEditor.setFragmentData(this.editor, event.clipboardData, 'copy');
3487
3584
  }
3488
3585
  };
3489
3586
  SlateEditableComponent.prototype.onDOMCut = function (event) {
3490
3587
  if (!this.readonly && hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.cut)) {
3491
3588
  event.preventDefault();
3492
- AngularEditor.setFragmentData(this.editor, event.clipboardData);
3589
+ AngularEditor.setFragmentData(this.editor, event.clipboardData, 'cut');
3493
3590
  var selection = this.editor.selection;
3494
3591
  if (selection) {
3495
3592
  AngularEditor.deleteCutData(this.editor);
@@ -3508,7 +3605,7 @@
3508
3605
  }
3509
3606
  };
3510
3607
  SlateEditableComponent.prototype.onDOMDragStart = function (event) {
3511
- if (hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3608
+ if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3512
3609
  var node = AngularEditor.toSlateNode(this.editor, event.target);
3513
3610
  var path = AngularEditor.findPath(this.editor, node);
3514
3611
  var voidMatch = slate.Editor.isVoid(this.editor, node) ||
@@ -3520,7 +3617,7 @@
3520
3617
  slate.Transforms.select(this.editor, range);
3521
3618
  }
3522
3619
  this.isDraggingInternally = true;
3523
- AngularEditor.setFragmentData(this.editor, event.dataTransfer);
3620
+ AngularEditor.setFragmentData(this.editor, event.dataTransfer, 'drag');
3524
3621
  }
3525
3622
  };
3526
3623
  SlateEditableComponent.prototype.onDOMDrop = function (event) {
@@ -4097,6 +4194,8 @@
4097
4194
  exports.ELEMENT_TO_NODE = ELEMENT_TO_NODE;
4098
4195
  exports.FAKE_LEFT_BLOCK_CARD_OFFSET = FAKE_LEFT_BLOCK_CARD_OFFSET;
4099
4196
  exports.FAKE_RIGHT_BLOCK_CARD_OFFSET = FAKE_RIGHT_BLOCK_CARD_OFFSET;
4197
+ exports.HAS_BEFORE_INPUT_SUPPORT = HAS_BEFORE_INPUT_SUPPORT;
4198
+ exports.IS_ANDROID = IS_ANDROID;
4100
4199
  exports.IS_APPLE = IS_APPLE;
4101
4200
  exports.IS_CHROME = IS_CHROME;
4102
4201
  exports.IS_CHROME_LEGACY = IS_CHROME_LEGACY;
@@ -4104,10 +4203,14 @@
4104
4203
  exports.IS_DRAGGING = IS_DRAGGING;
4105
4204
  exports.IS_EDGE_LEGACY = IS_EDGE_LEGACY;
4106
4205
  exports.IS_FIREFOX = IS_FIREFOX;
4206
+ exports.IS_FIREFOX_LEGACY = IS_FIREFOX_LEGACY;
4107
4207
  exports.IS_FOCUSED = IS_FOCUSED;
4108
4208
  exports.IS_IOS = IS_IOS;
4209
+ exports.IS_QQBROWSER = IS_QQBROWSER;
4109
4210
  exports.IS_READONLY = IS_READONLY;
4110
4211
  exports.IS_SAFARI = IS_SAFARI;
4212
+ exports.IS_UC_MOBILE = IS_UC_MOBILE;
4213
+ exports.IS_WECHATBROWSER = IS_WECHATBROWSER;
4111
4214
  exports.KEY_TO_ELEMENT = KEY_TO_ELEMENT;
4112
4215
  exports.Key = Key;
4113
4216
  exports.NODE_TO_ELEMENT = NODE_TO_ELEMENT;
@@ -4123,10 +4226,12 @@
4123
4226
  exports.SlateStringComponent = SlateStringComponent;
4124
4227
  exports.check = check;
4125
4228
  exports.getCardTargetAttribute = getCardTargetAttribute;
4229
+ exports.getClipboardData = getClipboardData;
4126
4230
  exports.getDefaultView = getDefaultView;
4127
4231
  exports.getEditableChild = getEditableChild;
4128
4232
  exports.getEditableChildAndIndex = getEditableChildAndIndex;
4129
4233
  exports.getPlainText = getPlainText;
4234
+ exports.getSlateFragmentAttribute = getSlateFragmentAttribute;
4130
4235
  exports.hasBeforeContextChange = hasBeforeContextChange;
4131
4236
  exports.hasBlockCard = hasBlockCard;
4132
4237
  exports.hasBlockCardWithNode = hasBlockCardWithNode;