slate-angular 19.0.0 → 19.1.0-next.1

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.
@@ -1,4 +1,5 @@
1
- import { Editor, Transforms, Element, Range, Text as Text$1, Path, Node } from 'slate';
1
+ import { Editor, Range, Element, Transforms, Text as Text$1, Node, Path } from 'slate';
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, isDOMNode, withDOM, NODE_TO_KEY, ELEMENT_TO_NODE, getDefaultView, EDITOR_TO_WINDOW, IS_READ_ONLY, EDITOR_TO_ON_CHANGE, IS_FOCUSED, TRIPLE_CLICK, isPlainTextOnlyPaste } from 'slate-dom';
2
3
  import { isKeyHotkey } from 'is-hotkey';
3
4
  import * as i0 from '@angular/core';
4
5
  import { TemplateRef, ViewChild, ChangeDetectionStrategy, Component, InjectionToken, ComponentRef, IterableDiffers, inject, ElementRef, ChangeDetectorRef, Input, Directive, HostBinding, ViewContainerRef, forwardRef, Inject, NgModule } from '@angular/core';
@@ -9,258 +10,6 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
9
10
  import { HistoryEditor } from 'slate-history';
10
11
  import { CommonModule } from '@angular/common';
11
12
 
12
- /**
13
- * Two weak maps that allow us rebuild a path given a node. They are populated
14
- * at render time such that after a render occurs we can always backtrack.
15
- */
16
- const EDITOR_TO_WINDOW = new WeakMap();
17
- const NODE_TO_INDEX = new WeakMap();
18
- const NODE_TO_PARENT = new WeakMap();
19
- /**
20
- * Weak maps that allow us to go between Slate nodes and DOM nodes. These
21
- * are used to resolve DOM event-related logic into Slate actions.
22
- */
23
- const EDITOR_TO_ELEMENT = new WeakMap();
24
- const EDITOR_TO_PLACEHOLDER = new WeakMap();
25
- const ELEMENT_TO_NODE = new WeakMap();
26
- // Deprecated
27
- const KEY_TO_ELEMENT = new WeakMap();
28
- const NODE_TO_ELEMENT = new WeakMap();
29
- const NODE_TO_KEY = new WeakMap();
30
- /**
31
- * Weak maps for storing editor-related state.
32
- */
33
- const IS_READONLY = new WeakMap();
34
- const IS_FOCUSED = new WeakMap();
35
- const IS_DRAGGING = new WeakMap();
36
- const IS_CLICKING = new WeakMap();
37
- /**
38
- * Weak map for associating the context `onChange` context with the plugin.
39
- */
40
- const EDITOR_TO_ON_CHANGE = new WeakMap();
41
- // export const NODE_TO_VIEWNODE = new WeakMap<Node, ViewNode>();
42
- /**
43
- * Symbols.
44
- */
45
- const PLACEHOLDER_SYMBOL = Symbol('placeholder');
46
- /**
47
- * Weak map for associating the html element with the component.
48
- */
49
- const ELEMENT_TO_COMPONENT = new WeakMap();
50
- const EDITOR_TO_AFTER_VIEW_INIT_QUEUE = new WeakMap();
51
-
52
- /**
53
- * Types.
54
- */
55
- // COMPAT: This is required to prevent TypeScript aliases from doing some very
56
- // weird things for Slate's types with the same name as globals. (2019/11/27)
57
- // https://github.com/microsoft/TypeScript/issues/35002
58
- var DOMNode = globalThis.Node;
59
- var DOMComment = globalThis.Comment;
60
- var DOMElement = globalThis.Element;
61
- var DOMText = globalThis.Text;
62
- var DOMRange = globalThis.Range;
63
- var DOMSelection = globalThis.Selection;
64
- var DOMStaticRange = globalThis.StaticRange;
65
- /**
66
- * Returns the host window of a DOM node
67
- */
68
- const getDefaultView = (value) => {
69
- return (value && value.ownerDocument && value.ownerDocument.defaultView) || null;
70
- };
71
- /**
72
- * Check if a DOM node is a comment node.
73
- */
74
- const isDOMComment = (value) => {
75
- return isDOMNode(value) && value.nodeType === 8;
76
- };
77
- /**
78
- * Check if a DOM node is an element node.
79
- */
80
- const isDOMElement = (value) => {
81
- return isDOMNode(value) && value.nodeType === 1;
82
- };
83
- /**
84
- * Check if a value is a DOM node.
85
- */
86
- const isDOMNode = (value) => {
87
- const window = getDefaultView(value);
88
- return !!window && value instanceof window.Node;
89
- };
90
- /**
91
- * Check if a value is a DOM selection.
92
- */
93
- const isDOMSelection = (value) => {
94
- const window = value && value.anchorNode && getDefaultView(value.anchorNode);
95
- return !!window && value instanceof window.Selection;
96
- };
97
- /**
98
- * Check if a DOM node is an element node.
99
- */
100
- const isDOMText = (value) => {
101
- return isDOMNode(value) && value.nodeType === 3;
102
- };
103
- /**
104
- * Checks whether a paste event is a plaintext-only event.
105
- */
106
- const isPlainTextOnlyPaste = (event) => {
107
- return event.clipboardData && event.clipboardData.getData('text/plain') !== '' && event.clipboardData.types.length === 1;
108
- };
109
- /**
110
- * Normalize a DOM point so that it always refers to a text node.
111
- */
112
- const normalizeDOMPoint = (domPoint) => {
113
- let [node, offset] = domPoint;
114
- // If it's an element node, its offset refers to the index of its children
115
- // including comment nodes, so try to find the right text child node.
116
- if (isDOMElement(node) && node.childNodes.length) {
117
- let isLast = offset === node.childNodes.length;
118
- let index = isLast ? offset - 1 : offset;
119
- [node, index] = getEditableChildAndIndex(node, index, isLast ? 'backward' : 'forward');
120
- // If the editable child found is in front of input offset, we instead seek to its end
121
- isLast = index < offset;
122
- // If the node has children, traverse until we have a leaf node. Leaf nodes
123
- // can be either text nodes, or other void DOM nodes.
124
- while (isDOMElement(node) && node.childNodes.length) {
125
- const i = isLast ? node.childNodes.length - 1 : 0;
126
- node = getEditableChild(node, i, isLast ? 'backward' : 'forward');
127
- }
128
- // Determine the new offset inside the text node.
129
- offset = isLast && node.textContent != null ? node.textContent.length : 0;
130
- }
131
- // Return the node and offset.
132
- return [node, offset];
133
- };
134
- /**
135
- * Determines wether the active element is nested within a shadowRoot
136
- */
137
- const hasShadowRoot = () => {
138
- return !!(window.document.activeElement && window.document.activeElement.shadowRoot);
139
- };
140
- /**
141
- * Get the nearest editable child and index at `index` in a `parent`, preferring
142
- * `direction`.
143
- */
144
- const getEditableChildAndIndex = (parent, index, direction) => {
145
- const { childNodes } = parent;
146
- let child = childNodes[index];
147
- let i = index;
148
- let triedForward = false;
149
- let triedBackward = false;
150
- // While the child is a comment node, or an element node with no children,
151
- // keep iterating to find a sibling non-void, non-comment node.
152
- while (isDOMComment(child) ||
153
- (isDOMElement(child) && child.childNodes.length === 0) ||
154
- (isDOMElement(child) && child.getAttribute('contenteditable') === 'false')) {
155
- if (triedForward && triedBackward) {
156
- break;
157
- }
158
- if (i >= childNodes.length) {
159
- triedForward = true;
160
- i = index - 1;
161
- direction = 'backward';
162
- continue;
163
- }
164
- if (i < 0) {
165
- triedBackward = true;
166
- i = index + 1;
167
- direction = 'forward';
168
- continue;
169
- }
170
- child = childNodes[i];
171
- index = i;
172
- i += direction === 'forward' ? 1 : -1;
173
- }
174
- return [child, index];
175
- };
176
- /**
177
- * Get the nearest editable child at `index` in a `parent`, preferring
178
- * `direction`.
179
- */
180
- const getEditableChild = (parent, index, direction) => {
181
- const [child] = getEditableChildAndIndex(parent, index, direction);
182
- return child;
183
- };
184
- /**
185
- * Get a plaintext representation of the content of a node, accounting for block
186
- * elements which get a newline appended.
187
- *
188
- * The domNode must be attached to the DOM.
189
- */
190
- const getPlainText = (domNode) => {
191
- let text = '';
192
- if (isDOMText(domNode) && domNode.nodeValue) {
193
- return domNode.nodeValue;
194
- }
195
- if (isDOMElement(domNode)) {
196
- for (const childNode of Array.from(domNode.childNodes)) {
197
- text += getPlainText(childNode);
198
- }
199
- const display = getComputedStyle(domNode).getPropertyValue('display');
200
- if (display === 'block' || display === 'list' || domNode.tagName === 'BR') {
201
- text += '\n';
202
- }
203
- }
204
- return text;
205
- };
206
- const SlateFragmentAttributeKey = 'data-slate-angular-fragment';
207
- /**
208
- * Get x-slate-fragment attribute from data-slate-angular-fragment
209
- */
210
- const catchSlateFragment = /data-slate-angular-fragment="(.+?)"/m;
211
- const getSlateFragmentAttribute = (htmlData) => {
212
- const [, fragment] = htmlData.match(catchSlateFragment) || [];
213
- return fragment;
214
- };
215
-
216
- /**
217
- * An auto-incrementing identifier for keys.
218
- */
219
- let n = 0;
220
- /**
221
- * A class that keeps track of a key string. We use a full class here because we
222
- * want to be able to use them as keys in `WeakMap` objects.
223
- */
224
- class Key {
225
- constructor() {
226
- this.id = `${n++}`;
227
- }
228
- }
229
-
230
- const IS_IOS = typeof navigator !== 'undefined' &&
231
- typeof window !== 'undefined' &&
232
- /iPad|iPhone|iPod/.test(navigator.userAgent) &&
233
- !window.MSStream;
234
- const IS_APPLE = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent);
235
- const IS_ANDROID = typeof navigator !== 'undefined' && /Android/.test(navigator.userAgent);
236
- const IS_FIREFOX = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
237
- const IS_SAFARI = typeof navigator !== 'undefined' && /Version\/[\d\.]+.*Safari/.test(navigator.userAgent);
238
- // "modern" Edge was released at 79.x
239
- const IS_EDGE_LEGACY = typeof navigator !== 'undefined' && /Edge?\/(?:[0-6][0-9]|[0-7][0-8])(?:\.)/i.test(navigator.userAgent);
240
- const IS_CHROME = typeof navigator !== 'undefined' && /Chrome/i.test(navigator.userAgent);
241
- // Native beforeInput events don't work well with react on Chrome 75 and older, Chrome 76+ can use beforeInput
242
- const IS_CHROME_LEGACY = typeof navigator !== 'undefined' &&
243
- /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent) &&
244
- // Exclude Chrome version greater than 3 bits,Chrome releases v100 on 2022.03.29
245
- !/Chrome?\/(?:\d{3,})/i.test(navigator.userAgent);
246
- // Firefox did not support `beforeInput` until `v87`.
247
- const IS_FIREFOX_LEGACY = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox\/(?:[0-7][0-9]|[0-8][0-6])(?:\.)).*/i.test(navigator.userAgent);
248
- // qq browser
249
- const IS_QQBROWSER = typeof navigator !== 'undefined' && /.*QQBrowser/.test(navigator.userAgent);
250
- // UC mobile browser
251
- const IS_UC_MOBILE = typeof navigator !== 'undefined' && /.*UCBrowser/.test(navigator.userAgent);
252
- // Wechat browser
253
- const IS_WECHATBROWSER = typeof navigator !== 'undefined' && /.*Wechat/.test(navigator.userAgent);
254
- // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
255
- // Chrome Legacy doesn't support `beforeinput` correctly
256
- const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
257
- !IS_EDGE_LEGACY &&
258
- // globalThis is undefined in older browsers
259
- typeof globalThis !== 'undefined' &&
260
- globalThis.InputEvent &&
261
- // @ts-ignore The `getTargetRanges` property isn't recognized.
262
- typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
263
-
264
13
  const FAKE_LEFT_BLOCK_CARD_OFFSET = -1;
265
14
  const FAKE_RIGHT_BLOCK_CARD_OFFSET = -2;
266
15
  function hasBlockCardWithNode(node) {
@@ -286,61 +35,251 @@ function isCardCenterByTargetAttr(targetAttr) {
286
35
  return targetAttr && targetAttr.nodeValue === 'card-center';
287
36
  }
288
37
 
289
- const AngularEditor = {
290
- /**
291
- * Return the host window of the current editor.
292
- */
293
- getWindow(editor) {
294
- const window = EDITOR_TO_WINDOW.get(editor);
295
- if (!window) {
296
- throw new Error('Unable to find a host window element for this editor');
38
+ const customToDOMNode = (editor, node) => {
39
+ const domNode = Editor.isEditor(node) ? EDITOR_TO_ELEMENT.get(editor) : NODE_TO_ELEMENT.get(node);
40
+ if (!domNode) {
41
+ throw new Error(`Cannot resolve a DOM node from Slate node: ${JSON.stringify(node)}`);
42
+ }
43
+ return domNode;
44
+ };
45
+ DOMEditor.toDOMNode = customToDOMNode;
46
+ const toDOMPointForBlockCard = (editor, point) => {
47
+ const [node] = Editor.node(editor, point.path);
48
+ const [parentNode] = Editor.parent(editor, point.path);
49
+ if (editor.isBlockCard(parentNode) || editor.isBlockCard(node)) {
50
+ if (point.offset < 0) {
51
+ if (point.offset === FAKE_LEFT_BLOCK_CARD_OFFSET) {
52
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, node, { direction: 'left' });
53
+ return [cursorNode, 1];
54
+ }
55
+ else {
56
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, node, { direction: 'right' });
57
+ return [cursorNode, 1];
58
+ }
297
59
  }
298
- return window;
299
- },
300
- /**
301
- * Find a key for a Slate node.
302
- */
303
- findKey(editor, node) {
304
- let key = NODE_TO_KEY.get(node);
305
- if (!key) {
306
- key = new Key();
307
- NODE_TO_KEY.set(node, key);
60
+ if (editor.selection && Range.isExpanded(editor.selection)) {
61
+ const [start, end] = Range.edges(editor.selection);
62
+ if (start === point) {
63
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, parentNode, { direction: 'left' });
64
+ return [cursorNode, 1];
65
+ }
66
+ else {
67
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, parentNode, { direction: 'right' });
68
+ return [cursorNode, 1];
69
+ }
308
70
  }
309
- return key;
310
- },
311
- /**
312
- * handle editor error.
313
- */
314
- onError(errorData) {
315
- if (errorData.nativeError) {
316
- throw errorData.nativeError;
71
+ }
72
+ };
73
+ const customToDOMPoint = (editor, point) => {
74
+ const [node] = Editor.node(editor, point.path);
75
+ const el = customToDOMNode(editor, node);
76
+ let domPoint;
77
+ const domPointForBlackCard = toDOMPointForBlockCard(editor, point);
78
+ if (domPointForBlackCard) {
79
+ return domPointForBlackCard;
80
+ }
81
+ // If we're inside a void node, force the offset to 0, otherwise the zero
82
+ // width spacing character will result in an incorrect offset of 1
83
+ if (Editor.void(editor, { at: point })) {
84
+ point = { path: point.path, offset: 0 };
85
+ }
86
+ // For each leaf, we need to isolate its content, which means filtering
87
+ // to its direct text and zero-width spans. (We have to filter out any
88
+ // other siblings that may have been rendered alongside them.)
89
+ const selector = `[data-slate-string], [data-slate-zero-width]`;
90
+ const texts = Array.from(el.querySelectorAll(selector));
91
+ let start = 0;
92
+ for (const text of texts) {
93
+ const domNode = text.childNodes[0];
94
+ if (domNode == null || domNode.textContent == null) {
95
+ continue;
317
96
  }
318
- },
319
- /**
320
- * Find the path of Slate node.
321
- */
322
- findPath(editor, node) {
323
- const path = [];
324
- let child = node;
325
- while (true) {
326
- const parent = NODE_TO_PARENT.get(child);
327
- if (parent == null) {
328
- if (Editor.isEditor(child) && child === editor) {
329
- return path;
330
- }
331
- else {
332
- break;
333
- }
97
+ const { length } = domNode.textContent;
98
+ const attr = text.getAttribute('data-slate-length');
99
+ const trueLength = attr == null ? length : parseInt(attr, 10);
100
+ const end = start + trueLength;
101
+ if (point.offset <= end) {
102
+ const offset = Math.min(length, Math.max(0, point.offset - start));
103
+ domPoint = [domNode, offset];
104
+ // fixed cursor position after zero width char
105
+ if (offset === 0 && length === 1 && domNode.textContent === '\uFEFF') {
106
+ domPoint = [domNode, offset + 1];
334
107
  }
335
- const i = NODE_TO_INDEX.get(child);
336
- if (i == null) {
337
- break;
108
+ break;
109
+ }
110
+ start = end;
111
+ }
112
+ if (!domPoint) {
113
+ throw new Error(`Cannot resolve a DOM point from Slate point: ${JSON.stringify(point)}`);
114
+ }
115
+ return domPoint;
116
+ };
117
+ DOMEditor.toDOMPoint = customToDOMPoint;
118
+ const toSlatePointForBlockCard = (editor, domPoint, nearestNode) => {
119
+ const [domNode] = domPoint;
120
+ const cardTargetAttr = getCardTargetAttribute(domNode);
121
+ if (cardTargetAttr) {
122
+ const domSelection = window.getSelection();
123
+ const blockCardEntry = CustomDOMEditor.toSlateCardEntry(editor, domNode) || CustomDOMEditor.toSlateCardEntry(editor, nearestNode);
124
+ const [, blockPath] = blockCardEntry;
125
+ if (domSelection.isCollapsed) {
126
+ if (isCardLeftByTargetAttr(cardTargetAttr)) {
127
+ return { path: blockPath, offset: -1 };
128
+ }
129
+ else {
130
+ return { path: blockPath, offset: -2 };
338
131
  }
339
- path.unshift(i);
340
- child = parent;
341
132
  }
342
- throw new Error(`Unable to find the path for Slate node: ${JSON.stringify(node)}`);
343
- },
133
+ if (isCardLeftByTargetAttr(cardTargetAttr)) {
134
+ return Editor.start(editor, blockPath);
135
+ }
136
+ else {
137
+ return Editor.end(editor, blockPath);
138
+ }
139
+ }
140
+ };
141
+ const customToSlatePoint = (editor, domPoint, options) => {
142
+ const { exactMatch, suppressThrow } = options;
143
+ const [nearestNode, nearestOffset] = normalizeDOMPoint(domPoint);
144
+ let parentNode = nearestNode.parentNode;
145
+ let textNode = null;
146
+ let offset = 0;
147
+ const slatePointForBlockCard = toSlatePointForBlockCard(editor, domPoint, nearestNode);
148
+ if (slatePointForBlockCard) {
149
+ return slatePointForBlockCard;
150
+ }
151
+ if (parentNode) {
152
+ const voidNode = parentNode.closest('[data-slate-void="true"]');
153
+ let leafNode = parentNode.closest('[data-slate-leaf]');
154
+ let domNode = null;
155
+ // Calculate how far into the text node the `nearestNode` is, so that we
156
+ // can determine what the offset relative to the text node is.
157
+ if (leafNode && CustomDOMEditor.isLeafInEditor(editor, leafNode)) {
158
+ textNode = leafNode.closest('[data-slate-node="text"]');
159
+ const window = DOMEditor.getWindow(editor);
160
+ const range = window.document.createRange();
161
+ range.setStart(textNode, 0);
162
+ range.setEnd(nearestNode, nearestOffset);
163
+ const contents = range.cloneContents();
164
+ const removals = [
165
+ ...Array.prototype.slice.call(contents.querySelectorAll('[data-slate-zero-width]')),
166
+ ...Array.prototype.slice.call(contents.querySelectorAll('[contenteditable=false]'))
167
+ ];
168
+ removals.forEach(el => {
169
+ el.parentNode.removeChild(el);
170
+ });
171
+ // COMPAT: Edge has a bug where Range.prototype.toString() will
172
+ // convert \n into \r\n. The bug causes a loop when slate-react
173
+ // attempts to reposition its cursor to match the native position. Use
174
+ // textContent.length instead.
175
+ // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10291116/
176
+ offset = contents.textContent.length;
177
+ domNode = textNode;
178
+ }
179
+ else if (voidNode) {
180
+ // For void nodes, the element with the offset key will be a cousin, not an
181
+ // ancestor, so find it by going down from the nearest void parent.
182
+ const spacer = voidNode.querySelector('[data-slate-spacer="true"]');
183
+ leafNode = spacer.firstElementChild;
184
+ parentNode = leafNode.firstElementChild;
185
+ textNode = spacer;
186
+ domNode = leafNode;
187
+ offset = domNode.textContent.length;
188
+ }
189
+ // COMPAT: If the parent node is a Slate zero-width space, editor is
190
+ // because the text node should have no characters. However, during IME
191
+ // composition the ASCII characters will be prepended to the zero-width
192
+ // space, so subtract 1 from the offset to account for the zero-width
193
+ // space character.
194
+ if (domNode && offset === domNode.textContent.length && parentNode && parentNode.hasAttribute('data-slate-zero-width')) {
195
+ offset--;
196
+ }
197
+ }
198
+ if (!textNode) {
199
+ if (suppressThrow) {
200
+ return null;
201
+ }
202
+ throw new Error(`Cannot resolve a Slate point from DOM point: ${domPoint}`);
203
+ }
204
+ // COMPAT: If someone is clicking from one Slate editor into another,
205
+ // the select event fires twice, once for the old editor's `element`
206
+ // first, and then afterwards for the correct `element`. (2017/03/03)
207
+ let slateNode = null;
208
+ try {
209
+ slateNode = CustomDOMEditor.toSlateNode(editor, textNode);
210
+ }
211
+ catch (error) {
212
+ if (!suppressThrow) {
213
+ throw error;
214
+ }
215
+ }
216
+ if (!slateNode && suppressThrow) {
217
+ return null;
218
+ }
219
+ const path = CustomDOMEditor.findPath(editor, slateNode);
220
+ return { path, offset };
221
+ };
222
+ DOMEditor.toSlatePoint = customToSlatePoint;
223
+ const customToSlateRange = (editor, domRange, options) => {
224
+ const { exactMatch, suppressThrow } = options || {};
225
+ const el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer;
226
+ let anchorNode;
227
+ let anchorOffset;
228
+ let focusNode;
229
+ let focusOffset;
230
+ let isCollapsed;
231
+ if (el) {
232
+ if (isDOMSelection(domRange)) {
233
+ anchorNode = domRange.anchorNode;
234
+ anchorOffset = domRange.anchorOffset;
235
+ focusNode = domRange.focusNode;
236
+ focusOffset = domRange.focusOffset;
237
+ // COMPAT: There's a bug in chrome that always returns `true` for
238
+ // `isCollapsed` for a Selection that comes from a ShadowRoot.
239
+ // (2020/08/08)
240
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=447523
241
+ if (IS_CHROME$1 && hasShadowRoot(anchorNode)) {
242
+ isCollapsed = domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset;
243
+ }
244
+ else {
245
+ isCollapsed = domRange.isCollapsed;
246
+ }
247
+ }
248
+ else {
249
+ anchorNode = domRange.startContainer;
250
+ anchorOffset = domRange.startOffset;
251
+ focusNode = domRange.endContainer;
252
+ focusOffset = domRange.endOffset;
253
+ isCollapsed = domRange.collapsed;
254
+ }
255
+ }
256
+ if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
257
+ throw new Error(`Cannot resolve a Slate range from DOM range: ${domRange}`);
258
+ }
259
+ const anchor = DOMEditor.toSlatePoint(editor, [anchorNode, anchorOffset], { suppressThrow, exactMatch });
260
+ if (!anchor) {
261
+ return null;
262
+ }
263
+ const focus = isCollapsed ? anchor : DOMEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
264
+ if (!focus) {
265
+ return null;
266
+ }
267
+ let range = { anchor: anchor, focus: focus };
268
+ // if the selection is a hanging range that ends in a void
269
+ // and the DOM focus is an Element
270
+ // (meaning that the selection ends before the element)
271
+ // unhang the range to avoid mistakenly including the void
272
+ if (Range.isExpanded(range) &&
273
+ Range.isForward(range) &&
274
+ isDOMElement(focusNode) &&
275
+ Editor.void(editor, { at: range.focus, mode: 'highest' })) {
276
+ range = Editor.unhangRange(editor, range, { voids: true });
277
+ }
278
+ return range;
279
+ };
280
+ DOMEditor.toSlateRange = customToSlateRange;
281
+ const CustomDOMEditor = {
282
+ ...DOMEditor,
344
283
  isNodeInEditor(editor, node) {
345
284
  let child = node;
346
285
  while (true) {
@@ -361,321 +300,14 @@ const AngularEditor = {
361
300
  }
362
301
  return false;
363
302
  },
364
- /**
365
- * Find the DOM node that implements DocumentOrShadowRoot for the editor.
366
- */
367
- findDocumentOrShadowRoot(editor) {
368
- const el = AngularEditor.toDOMNode(editor, editor);
369
- const root = el.getRootNode();
370
- if ((root instanceof Document || root instanceof ShadowRoot) && root.getSelection != null) {
371
- return root;
372
- }
373
- return el.ownerDocument;
374
- },
375
- /**
376
- * Check if the editor is focused.
377
- */
378
- isFocused(editor) {
379
- return !!IS_FOCUSED.get(editor);
380
- },
381
- /**
382
- * Check if the editor is in read-only mode.
383
- */
384
- isReadonly(editor) {
385
- return !!IS_READONLY.get(editor);
386
- },
387
- /**
388
- * Check if the editor is hanging right.
389
- */
390
- isBlockHangingRight(editor) {
391
- const { selection } = editor;
392
- if (!selection) {
393
- return false;
394
- }
395
- if (Range.isCollapsed(selection)) {
396
- return false;
397
- }
398
- const [start, end] = Range.edges(selection);
399
- const endBlock = Editor.above(editor, {
400
- at: end,
401
- match: node => Element.isElement(node) && Editor.isBlock(editor, node)
402
- });
403
- return Editor.isStart(editor, end, endBlock[1]);
404
- },
405
- /**
406
- * Blur the editor.
407
- */
408
- blur(editor) {
409
- const el = AngularEditor.toDOMNode(editor, editor);
410
- const root = AngularEditor.findDocumentOrShadowRoot(editor);
411
- IS_FOCUSED.set(editor, false);
412
- if (root.activeElement === el) {
413
- el.blur();
414
- }
415
- },
416
- /**
417
- * Focus the editor.
418
- */
419
- focus(editor) {
420
- const el = AngularEditor.toDOMNode(editor, editor);
421
- IS_FOCUSED.set(editor, true);
422
- const window = AngularEditor.getWindow(editor);
423
- if (window.document.activeElement !== el) {
424
- el.focus({ preventScroll: true });
425
- }
426
- },
427
- /**
428
- * Deselect the editor.
429
- */
430
- deselect(editor) {
431
- const { selection } = editor;
432
- const root = AngularEditor.findDocumentOrShadowRoot(editor);
433
- const domSelection = root.getSelection();
434
- if (domSelection && domSelection.rangeCount > 0) {
435
- domSelection.removeAllRanges();
436
- }
437
- if (selection) {
438
- Transforms.deselect(editor);
439
- }
440
- },
441
- /**
442
- * Check if a DOM node is within the editor.
443
- */
444
- hasDOMNode(editor, target, options = {}) {
445
- const { editable = false } = options;
446
- const editorEl = AngularEditor.toDOMNode(editor, editor);
447
- let targetEl;
448
- // COMPAT: In Firefox, reading `target.nodeType` will throw an error if
449
- // target is originating from an internal "restricted" element (e.g. a
450
- // stepper arrow on a number input). (2018/05/04)
451
- // https://github.com/ianstormtaylor/slate/issues/1819
303
+ isLeafInEditor(editor, leafNode) {
304
+ const textNode = leafNode.closest('[data-slate-node="text"]');
305
+ let node = null;
452
306
  try {
453
- targetEl = (isDOMElement(target) ? target : target.parentElement);
454
- }
455
- catch (err) {
456
- if (!err.message.includes('Permission denied to access property "nodeType"')) {
457
- throw err;
458
- }
459
- }
460
- if (!targetEl) {
461
- return false;
462
- }
463
- return (targetEl.closest(`[data-slate-editor]`) === editorEl &&
464
- (!editable || targetEl.isContentEditable || !!targetEl.getAttribute('data-slate-zero-width')));
465
- },
466
- /**
467
- * Insert data from a `DataTransfer` into the editor.
468
- */
469
- insertData(editor, data) {
470
- editor.insertData(data);
471
- },
472
- /**
473
- * Insert fragment data from a `DataTransfer` into the editor.
474
- */
475
- insertFragmentData(editor, data) {
476
- return editor.insertFragmentData(data);
477
- },
478
- /**
479
- * Insert text data from a `DataTransfer` into the editor.
480
- */
481
- insertTextData(editor, data) {
482
- return editor.insertTextData(data);
483
- },
484
- /**
485
- * onKeydown hook.
486
- */
487
- onKeydown(editor, data) {
488
- editor.onKeydown(data);
489
- },
490
- /**
491
- * onClick hook.
492
- */
493
- onClick(editor, data) {
494
- editor.onClick(data);
495
- },
496
- /**
497
- * Sets data from the currently selected fragment on a `DataTransfer`.
498
- */
499
- setFragmentData(editor, data, originEvent) {
500
- editor.setFragmentData(data, originEvent);
501
- },
502
- deleteCutData(editor) {
503
- editor.deleteCutData();
504
- },
505
- /**
506
- * Find the native DOM element from a Slate node.
507
- */
508
- toDOMNode(editor, node) {
509
- const domNode = Editor.isEditor(node) ? EDITOR_TO_ELEMENT.get(editor) : NODE_TO_ELEMENT.get(node);
510
- if (!domNode) {
511
- throw new Error(`Cannot resolve a DOM node from Slate node: ${JSON.stringify(node)}`);
512
- }
513
- return domNode;
514
- },
515
- /**
516
- * Find a native DOM selection point from a Slate point.
517
- */
518
- toDOMPoint(editor, point, options) {
519
- const [node] = Editor.node(editor, point.path);
520
- const el = AngularEditor.toDOMNode(editor, node);
521
- let domPoint;
522
- // block card
523
- const [parentNode] = Editor.parent(editor, point.path);
524
- if (editor.isBlockCard(parentNode) || editor.isBlockCard(node)) {
525
- if (point.offset < 0) {
526
- if (point.offset === FAKE_LEFT_BLOCK_CARD_OFFSET) {
527
- const cursorNode = AngularEditor.getCardCursorNode(editor, node, { direction: 'left' });
528
- return [cursorNode, 1];
529
- }
530
- else {
531
- const cursorNode = AngularEditor.getCardCursorNode(editor, node, { direction: 'right' });
532
- return [cursorNode, 1];
533
- }
534
- }
535
- if (Range.isExpanded(options.range)) {
536
- const [start, end] = Range.edges(options.range);
537
- if (start === point) {
538
- const cursorNode = AngularEditor.getCardCursorNode(editor, parentNode, { direction: 'left' });
539
- return [cursorNode, 1];
540
- }
541
- else {
542
- const cursorNode = AngularEditor.getCardCursorNode(editor, parentNode, { direction: 'right' });
543
- return [cursorNode, 1];
544
- }
545
- }
546
- }
547
- // If we're inside a void node, force the offset to 0, otherwise the zero
548
- // width spacing character will result in an incorrect offset of 1
549
- if (Editor.void(editor, { at: point })) {
550
- point = { path: point.path, offset: 0 };
551
- }
552
- // For each leaf, we need to isolate its content, which means filtering
553
- // to its direct text and zero-width spans. (We have to filter out any
554
- // other siblings that may have been rendered alongside them.)
555
- const selector = `[data-slate-string], [data-slate-zero-width]`;
556
- const texts = Array.from(el.querySelectorAll(selector));
557
- let start = 0;
558
- for (const text of texts) {
559
- const domNode = text.childNodes[0];
560
- if (domNode == null || domNode.textContent == null) {
561
- continue;
562
- }
563
- const { length } = domNode.textContent;
564
- const attr = text.getAttribute('data-slate-length');
565
- const trueLength = attr == null ? length : parseInt(attr, 10);
566
- const end = start + trueLength;
567
- if (point.offset <= end) {
568
- const offset = Math.min(length, Math.max(0, point.offset - start));
569
- domPoint = [domNode, offset];
570
- // fixed cursor position after zero width char
571
- if (offset === 0 && length === 1 && domNode.textContent === '\uFEFF') {
572
- domPoint = [domNode, offset + 1];
573
- }
574
- break;
575
- }
576
- start = end;
577
- }
578
- if (!domPoint) {
579
- throw new Error(`Cannot resolve a DOM point from Slate point: ${JSON.stringify(point)}`);
580
- }
581
- return domPoint;
582
- },
583
- /**
584
- * Find a native DOM range from a Slate `range`.
585
- */
586
- toDOMRange(editor, range) {
587
- const { anchor, focus } = range;
588
- const isBackward = Range.isBackward(range);
589
- const domAnchor = AngularEditor.toDOMPoint(editor, anchor, { range });
590
- const domFocus = Range.isCollapsed(range) ? domAnchor : AngularEditor.toDOMPoint(editor, focus, { range });
591
- const window = AngularEditor.getWindow(editor);
592
- const domRange = window.document.createRange();
593
- const [startNode, startOffset] = isBackward ? domFocus : domAnchor;
594
- const [endNode, endOffset] = isBackward ? domAnchor : domFocus;
595
- // A slate Point at zero-width Leaf always has an offset of 0 but a native DOM selection at
596
- // zero-width node has an offset of 1 so we have to check if we are in a zero-width node and
597
- // adjust the offset accordingly.
598
- const startEl = (isDOMElement(startNode) ? startNode : startNode.parentElement);
599
- const isStartAtZeroWidth = !!startEl.getAttribute('data-slate-zero-width');
600
- const endEl = (isDOMElement(endNode) ? endNode : endNode.parentElement);
601
- const isEndAtZeroWidth = !!endEl.getAttribute('data-slate-zero-width');
602
- domRange.setStart(startNode, isStartAtZeroWidth ? 1 : startOffset);
603
- domRange.setEnd(endNode, isEndAtZeroWidth ? 1 : endOffset);
604
- return domRange;
605
- },
606
- /**
607
- * Find a Slate node from a native DOM `element`.
608
- */
609
- toSlateNode(editor, domNode, options) {
610
- const { suppressThrow } = options || { suppressThrow: false };
611
- let domEl = isDOMElement(domNode) ? domNode : domNode.parentElement;
612
- if (domEl && !domEl.hasAttribute('data-slate-node')) {
613
- domEl = domEl.closest(`[data-slate-node]`);
614
- }
615
- const node = domEl ? ELEMENT_TO_NODE.get(domEl) : null;
616
- if (!node) {
617
- if (suppressThrow) {
618
- return null;
619
- }
620
- throw new Error(`Cannot resolve a Slate node from DOM node: ${domEl}`);
307
+ node = CustomDOMEditor.toSlateNode(editor, textNode);
621
308
  }
622
- return node;
623
- },
624
- /**
625
- * Get the target range from a DOM `event`.
626
- */
627
- findEventRange(editor, event) {
628
- if ('nativeEvent' in event) {
629
- event = event.nativeEvent;
630
- }
631
- const { clientX: x, clientY: y, target } = event;
632
- if (x == null || y == null) {
633
- throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
634
- }
635
- const node = AngularEditor.toSlateNode(editor, event.target, { suppressThrow: false });
636
- const path = AngularEditor.findPath(editor, node);
637
- // If the drop target is inside a void node, move it into either the
638
- // next or previous node, depending on which side the `x` and `y`
639
- // coordinates are closest to.
640
- if (Element.isElement(node) && Editor.isVoid(editor, node)) {
641
- const rect = target.getBoundingClientRect();
642
- const isPrev = editor.isInline(node) ? x - rect.left < rect.left + rect.width - x : y - rect.top < rect.top + rect.height - y;
643
- const edge = Editor.point(editor, path, {
644
- edge: isPrev ? 'start' : 'end'
645
- });
646
- const point = isPrev ? Editor.before(editor, edge) : Editor.after(editor, edge);
647
- if (point) {
648
- return Editor.range(editor, point);
649
- }
650
- }
651
- // Else resolve a range from the caret position where the drop occured.
652
- let domRange;
653
- const window = AngularEditor.getWindow(editor);
654
- const { document } = window;
655
- // COMPAT: In Firefox, `caretRangeFromPoint` doesn't exist. (2016/07/25)
656
- if (document.caretRangeFromPoint) {
657
- domRange = document.caretRangeFromPoint(x, y);
658
- }
659
- else {
660
- const position = document.caretPositionFromPoint(x, y);
661
- if (position) {
662
- domRange = document.createRange();
663
- domRange.setStart(position.offsetNode, position.offset);
664
- domRange.setEnd(position.offsetNode, position.offset);
665
- }
666
- }
667
- if (!domRange) {
668
- throw new Error(`Cannot resolve a Slate range from a DOM event: ${event}`);
669
- }
670
- // Resolve a Slate range from the DOM range.
671
- const range = AngularEditor.toSlateRange(editor, domRange, { suppressThrow: false });
672
- return range;
673
- },
674
- isLeafInEditor(editor, leafNode, options) {
675
- const { suppressThrow } = options;
676
- const textNode = leafNode.closest('[data-slate-node="text"]');
677
- const node = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
678
- if (node && AngularEditor.isNodeInEditor(editor, node)) {
309
+ catch (error) { }
310
+ if (node && CustomDOMEditor.isNodeInEditor(editor, node)) {
679
311
  return true;
680
312
  }
681
313
  else {
@@ -683,162 +315,22 @@ const AngularEditor = {
683
315
  }
684
316
  },
685
317
  /**
686
- * Find a Slate point from a DOM selection's `domNode` and `domOffset`.
687
- */
688
- toSlatePoint(editor, domPoint, options) {
689
- const { exactMatch, suppressThrow } = options;
690
- const [domNode] = domPoint;
691
- const [nearestNode, nearestOffset] = normalizeDOMPoint(domPoint);
692
- let parentNode = nearestNode.parentNode;
693
- let textNode = null;
694
- let offset = 0;
695
- // block card
696
- const cardTargetAttr = getCardTargetAttribute(domNode);
697
- if (cardTargetAttr) {
698
- const domSelection = window.getSelection();
699
- const isBackward = editor.selection && Range.isBackward(editor.selection);
700
- const blockCardEntry = AngularEditor.toSlateCardEntry(editor, domNode) || AngularEditor.toSlateCardEntry(editor, nearestNode);
701
- const [, blockPath] = blockCardEntry;
702
- if (domSelection.isCollapsed) {
703
- if (isCardLeftByTargetAttr(cardTargetAttr)) {
704
- return { path: blockPath, offset: -1 };
705
- }
706
- else {
707
- return { path: blockPath, offset: -2 };
708
- }
709
- }
710
- if (isCardLeftByTargetAttr(cardTargetAttr)) {
711
- return Editor.start(editor, blockPath);
712
- }
713
- else {
714
- return Editor.end(editor, blockPath);
715
- }
716
- }
717
- if (parentNode) {
718
- const voidNode = parentNode.closest('[data-slate-void="true"]');
719
- let leafNode = parentNode.closest('[data-slate-leaf]');
720
- let domNode = null;
721
- // Calculate how far into the text node the `nearestNode` is, so that we
722
- // can determine what the offset relative to the text node is.
723
- if (leafNode && AngularEditor.isLeafInEditor(editor, leafNode, { suppressThrow: true })) {
724
- textNode = leafNode.closest('[data-slate-node="text"]');
725
- const window = AngularEditor.getWindow(editor);
726
- const range = window.document.createRange();
727
- range.setStart(textNode, 0);
728
- range.setEnd(nearestNode, nearestOffset);
729
- const contents = range.cloneContents();
730
- const removals = [
731
- ...Array.prototype.slice.call(contents.querySelectorAll('[data-slate-zero-width]')),
732
- ...Array.prototype.slice.call(contents.querySelectorAll('[contenteditable=false]'))
733
- ];
734
- removals.forEach(el => {
735
- el.parentNode.removeChild(el);
736
- });
737
- // COMPAT: Edge has a bug where Range.prototype.toString() will
738
- // convert \n into \r\n. The bug causes a loop when slate-react
739
- // attempts to reposition its cursor to match the native position. Use
740
- // textContent.length instead.
741
- // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10291116/
742
- offset = contents.textContent.length;
743
- domNode = textNode;
744
- }
745
- else if (voidNode) {
746
- // For void nodes, the element with the offset key will be a cousin, not an
747
- // ancestor, so find it by going down from the nearest void parent.
748
- const spacer = voidNode.querySelector('[data-slate-spacer="true"]');
749
- leafNode = spacer.firstElementChild;
750
- parentNode = leafNode.firstElementChild;
751
- textNode = spacer;
752
- domNode = leafNode;
753
- offset = domNode.textContent.length;
754
- }
755
- // COMPAT: If the parent node is a Slate zero-width space, editor is
756
- // because the text node should have no characters. However, during IME
757
- // composition the ASCII characters will be prepended to the zero-width
758
- // space, so subtract 1 from the offset to account for the zero-width
759
- // space character.
760
- if (domNode && offset === domNode.textContent.length && parentNode && parentNode.hasAttribute('data-slate-zero-width')) {
761
- offset--;
762
- }
763
- }
764
- if (!textNode) {
765
- if (suppressThrow) {
766
- return null;
767
- }
768
- throw new Error(`Cannot resolve a Slate point from DOM point: ${domPoint}`);
769
- }
770
- // COMPAT: If someone is clicking from one Slate editor into another,
771
- // the select event fires twice, once for the old editor's `element`
772
- // first, and then afterwards for the correct `element`. (2017/03/03)
773
- const slateNode = AngularEditor.toSlateNode(editor, textNode, { suppressThrow });
774
- if (!slateNode && suppressThrow) {
775
- return null;
776
- }
777
- const path = AngularEditor.findPath(editor, slateNode);
778
- return { path, offset };
779
- },
780
- /**
781
- * Find a Slate range from a DOM range or selection.
318
+ * Check if the editor is hanging right.
782
319
  */
783
- toSlateRange(editor, domRange, options) {
784
- const { exactMatch, suppressThrow } = options || {};
785
- const el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer;
786
- let anchorNode;
787
- let anchorOffset;
788
- let focusNode;
789
- let focusOffset;
790
- let isCollapsed;
791
- if (el) {
792
- if (isDOMSelection(domRange)) {
793
- anchorNode = domRange.anchorNode;
794
- anchorOffset = domRange.anchorOffset;
795
- focusNode = domRange.focusNode;
796
- focusOffset = domRange.focusOffset;
797
- // COMPAT: There's a bug in chrome that always returns `true` for
798
- // `isCollapsed` for a Selection that comes from a ShadowRoot.
799
- // (2020/08/08)
800
- // https://bugs.chromium.org/p/chromium/issues/detail?id=447523
801
- if (IS_CHROME && hasShadowRoot()) {
802
- isCollapsed = domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset;
803
- }
804
- else {
805
- isCollapsed = domRange.isCollapsed;
806
- }
807
- }
808
- else {
809
- anchorNode = domRange.startContainer;
810
- anchorOffset = domRange.startOffset;
811
- focusNode = domRange.endContainer;
812
- focusOffset = domRange.endOffset;
813
- isCollapsed = domRange.collapsed;
814
- }
815
- }
816
- if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
817
- throw new Error(`Cannot resolve a Slate range from DOM range: ${domRange}`);
818
- }
819
- const anchor = AngularEditor.toSlatePoint(editor, [anchorNode, anchorOffset], { suppressThrow, exactMatch });
820
- if (!anchor) {
821
- return null;
320
+ isBlockHangingRight(editor) {
321
+ const { selection } = editor;
322
+ if (!selection) {
323
+ return false;
822
324
  }
823
- const focus = isCollapsed ? anchor : AngularEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
824
- if (!focus) {
825
- return null;
325
+ if (Range.isCollapsed(selection)) {
326
+ return false;
826
327
  }
827
- let range = { anchor: anchor, focus: focus };
828
- // if the selection is a hanging range that ends in a void
829
- // and the DOM focus is an Element
830
- // (meaning that the selection ends before the element)
831
- // unhang the range to avoid mistakenly including the void
832
- if (Range.isExpanded(range) &&
833
- Range.isForward(range) &&
834
- isDOMElement(focusNode) &&
835
- Editor.void(editor, { at: range.focus, mode: 'highest' })) {
836
- range = Editor.unhangRange(editor, range, { voids: true });
837
- }
838
- return range;
839
- },
840
- isLeafBlock(editor, node) {
841
- return Element.isElement(node) && !editor.isInline(node) && Editor.hasInlines(editor, node);
328
+ const [start, end] = Range.edges(selection);
329
+ const endBlock = Editor.above(editor, {
330
+ at: end,
331
+ match: node => Element.isElement(node) && Editor.isBlock(editor, node)
332
+ });
333
+ return Editor.isStart(editor, end, endBlock[1]);
842
334
  },
843
335
  isBlockCardLeftCursor(editor) {
844
336
  return (editor.selection?.anchor?.offset === FAKE_LEFT_BLOCK_CARD_OFFSET &&
@@ -849,15 +341,45 @@ const AngularEditor = {
849
341
  editor.selection?.focus?.offset === FAKE_RIGHT_BLOCK_CARD_OFFSET);
850
342
  },
851
343
  getCardCursorNode(editor, blockCardNode, options) {
852
- const blockCardElement = AngularEditor.toDOMNode(editor, blockCardNode);
344
+ const blockCardElement = DOMEditor.toDOMNode(editor, blockCardNode);
853
345
  const cardCenter = blockCardElement.parentElement;
854
346
  return options.direction === 'left' ? cardCenter.previousElementSibling.firstChild : cardCenter.nextElementSibling.firstChild;
855
347
  },
856
348
  toSlateCardEntry(editor, node) {
857
349
  const element = node.parentElement.closest('.slate-block-card')?.querySelector('[card-target="card-center"]').firstElementChild;
858
- const slateNode = AngularEditor.toSlateNode(editor, element, { suppressThrow: false });
859
- const path = AngularEditor.findPath(editor, slateNode);
350
+ const slateNode = DOMEditor.toSlateNode(editor, element);
351
+ const path = DOMEditor.findPath(editor, slateNode);
860
352
  return [slateNode, path];
353
+ }
354
+ };
355
+
356
+ const AngularEditor = {
357
+ ...CustomDOMEditor,
358
+ /**
359
+ * handle editor error.
360
+ */
361
+ onError(errorData) {
362
+ if (errorData.nativeError) {
363
+ throw errorData.nativeError;
364
+ }
365
+ },
366
+ /**
367
+ * onKeydown hook.
368
+ */
369
+ onKeydown(editor, data) {
370
+ editor.onKeydown(data);
371
+ },
372
+ /**
373
+ * onClick hook.
374
+ */
375
+ onClick(editor, data) {
376
+ editor.onClick(data);
377
+ },
378
+ deleteCutData(editor) {
379
+ editor.deleteCutData();
380
+ },
381
+ isLeafBlock(editor, node) {
382
+ return Element.isElement(node) && !editor.isInline(node) && Editor.hasInlines(editor, node);
861
383
  },
862
384
  /**
863
385
  * move native selection to card-left or card-right
@@ -883,13 +405,53 @@ const AngularEditor = {
883
405
  offset: options.direction === 'left' ? FAKE_LEFT_BLOCK_CARD_OFFSET : FAKE_RIGHT_BLOCK_CARD_OFFSET
884
406
  };
885
407
  Transforms.select(editor, { anchor: cursor, focus: cursor });
886
- },
887
- hasRange(editor, range) {
888
- const { anchor, focus } = range;
889
- return Editor.hasPath(editor, anchor.path) && Editor.hasPath(editor, focus.path);
890
408
  }
891
409
  };
892
410
 
411
+ /**
412
+ * Symbols.
413
+ */
414
+ const PLACEHOLDER_SYMBOL = Symbol('placeholder');
415
+ /**
416
+ * Weak map for associating the html element with the component.
417
+ */
418
+ const ELEMENT_TO_COMPONENT = new WeakMap();
419
+ const EDITOR_TO_AFTER_VIEW_INIT_QUEUE = new WeakMap();
420
+
421
+ const IS_IOS = typeof navigator !== 'undefined' &&
422
+ typeof window !== 'undefined' &&
423
+ /iPad|iPhone|iPod/.test(navigator.userAgent) &&
424
+ !window.MSStream;
425
+ const IS_APPLE = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent);
426
+ const IS_ANDROID = typeof navigator !== 'undefined' && /Android/.test(navigator.userAgent);
427
+ const IS_FIREFOX = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
428
+ const IS_SAFARI = typeof navigator !== 'undefined' && /Version\/[\d\.]+.*Safari/.test(navigator.userAgent);
429
+ // "modern" Edge was released at 79.x
430
+ const IS_EDGE_LEGACY = typeof navigator !== 'undefined' && /Edge?\/(?:[0-6][0-9]|[0-7][0-8])(?:\.)/i.test(navigator.userAgent);
431
+ const IS_CHROME = typeof navigator !== 'undefined' && /Chrome/i.test(navigator.userAgent);
432
+ // Native beforeInput events don't work well with react on Chrome 75 and older, Chrome 76+ can use beforeInput
433
+ const IS_CHROME_LEGACY = typeof navigator !== 'undefined' &&
434
+ /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent) &&
435
+ // Exclude Chrome version greater than 3 bits,Chrome releases v100 on 2022.03.29
436
+ !/Chrome?\/(?:\d{3,})/i.test(navigator.userAgent);
437
+ // Firefox did not support `beforeInput` until `v87`.
438
+ const IS_FIREFOX_LEGACY = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox\/(?:[0-7][0-9]|[0-8][0-6])(?:\.)).*/i.test(navigator.userAgent);
439
+ // qq browser
440
+ const IS_QQBROWSER = typeof navigator !== 'undefined' && /.*QQBrowser/.test(navigator.userAgent);
441
+ // UC mobile browser
442
+ const IS_UC_MOBILE = typeof navigator !== 'undefined' && /.*UCBrowser/.test(navigator.userAgent);
443
+ // Wechat browser
444
+ const IS_WECHATBROWSER = typeof navigator !== 'undefined' && /.*Wechat/.test(navigator.userAgent);
445
+ // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
446
+ // Chrome Legacy doesn't support `beforeinput` correctly
447
+ const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
448
+ !IS_EDGE_LEGACY &&
449
+ // globalThis is undefined in older browsers
450
+ typeof globalThis !== 'undefined' &&
451
+ globalThis.InputEvent &&
452
+ // @ts-ignore The `getTargetRanges` property isn't recognized.
453
+ typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
454
+
893
455
  /**
894
456
  * Hotkey mappings for each platform.
895
457
  */
@@ -1188,6 +750,44 @@ const getNavigatorClipboard = async () => {
1188
750
  return clipboardData;
1189
751
  };
1190
752
 
753
+ const SlateFragmentAttributeKey = 'data-slate-angular-fragment';
754
+ /**
755
+ * Get x-slate-fragment attribute from data-slate-angular-fragment
756
+ */
757
+ const catchSlateFragment = /data-slate-angular-fragment="(.+?)"/m;
758
+ const getSlateFragmentAttribute = (htmlData) => {
759
+ const [, fragment] = htmlData.match(catchSlateFragment) || [];
760
+ return fragment;
761
+ };
762
+ /**
763
+ * Check if a DOM node is an element node.
764
+ */
765
+ const isDOMText = (value) => {
766
+ return isDOMNode(value) && value.nodeType === 3;
767
+ };
768
+ /**
769
+ * Get a plaintext representation of the content of a node, accounting for block
770
+ * elements which get a newline appended.
771
+ *
772
+ * The domNode must be attached to the DOM.
773
+ */
774
+ const getPlainText = (domNode) => {
775
+ let text = '';
776
+ if (isDOMText(domNode) && domNode.nodeValue) {
777
+ return domNode.nodeValue;
778
+ }
779
+ if (isDOMElement(domNode)) {
780
+ for (const childNode of Array.from(domNode.childNodes)) {
781
+ text += getPlainText(childNode);
782
+ }
783
+ const display = getComputedStyle(domNode).getPropertyValue('display');
784
+ if (display === 'block' || display === 'list' || domNode.tagName === 'BR') {
785
+ text += '\n';
786
+ }
787
+ }
788
+ return text;
789
+ };
790
+
1191
791
  const buildHTMLText = (wrapper, attach, data) => {
1192
792
  const stringObj = JSON.stringify(data);
1193
793
  const encoded = window.btoa(encodeURIComponent(stringObj));
@@ -1262,128 +862,10 @@ const setClipboardData = async (clipboardData, wrapper, attach, dataTransfer) =>
1262
862
  }
1263
863
  };
1264
864
 
1265
- /**
1266
- * Utilities for single-line deletion
1267
- */
1268
- const doRectsIntersect = (rect, compareRect) => {
1269
- const middle = (compareRect.top + compareRect.bottom) / 2;
1270
- return rect.top <= middle && rect.bottom >= middle;
1271
- };
1272
- const areRangesSameLine = (editor, range1, range2) => {
1273
- const rect1 = AngularEditor.toDOMRange(editor, range1).getBoundingClientRect();
1274
- const rect2 = AngularEditor.toDOMRange(editor, range2).getBoundingClientRect();
1275
- return doRectsIntersect(rect1, rect2) && doRectsIntersect(rect2, rect1);
1276
- };
1277
- /**
1278
- * A helper utility that returns the end portion of a `Range`
1279
- * which is located on a single line.
1280
- *
1281
- * @param {Editor} editor The editor object to compare against
1282
- * @param {Range} parentRange The parent range to compare against
1283
- * @returns {Range} A valid portion of the parentRange which is one a single line
1284
- */
1285
- const findCurrentLineRange = (editor, parentRange) => {
1286
- const parentRangeBoundary = Editor.range(editor, Range.end(parentRange));
1287
- const positions = Array.from(Editor.positions(editor, { at: parentRange }));
1288
- let left = 0;
1289
- let right = positions.length;
1290
- let middle = Math.floor(right / 2);
1291
- if (areRangesSameLine(editor, Editor.range(editor, positions[left]), parentRangeBoundary)) {
1292
- return Editor.range(editor, positions[left], parentRangeBoundary);
1293
- }
1294
- if (positions.length < 2) {
1295
- return Editor.range(editor, positions[positions.length - 1], parentRangeBoundary);
1296
- }
1297
- while (middle !== positions.length && middle !== left) {
1298
- if (areRangesSameLine(editor, Editor.range(editor, positions[middle]), parentRangeBoundary)) {
1299
- right = middle;
1300
- }
1301
- else {
1302
- left = middle;
1303
- }
1304
- middle = Math.floor((left + right) / 2);
1305
- }
1306
- return Editor.range(editor, positions[right], parentRangeBoundary);
1307
- };
1308
-
1309
865
  const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1310
- const e = editor;
1311
- const { apply, onChange, deleteBackward } = e;
1312
- e.deleteBackward = unit => {
1313
- if (unit !== 'line') {
1314
- return deleteBackward(unit);
1315
- }
1316
- if (editor.selection && Range.isCollapsed(editor.selection)) {
1317
- const parentBlockEntry = Editor.above(editor, {
1318
- match: n => Element.isElement(n) && Editor.isBlock(editor, n),
1319
- at: editor.selection
1320
- });
1321
- if (parentBlockEntry) {
1322
- const [, parentBlockPath] = parentBlockEntry;
1323
- const parentElementRange = Editor.range(editor, parentBlockPath, editor.selection.anchor);
1324
- const currentLineRange = findCurrentLineRange(e, parentElementRange);
1325
- if (!Range.isCollapsed(currentLineRange)) {
1326
- Transforms.delete(editor, { at: currentLineRange });
1327
- }
1328
- }
1329
- }
1330
- };
1331
- e.apply = (op) => {
1332
- const matches = [];
1333
- switch (op.type) {
1334
- case 'insert_text':
1335
- case 'remove_text':
1336
- case 'set_node': {
1337
- for (const [node, path] of Editor.levels(e, { at: op.path })) {
1338
- const key = AngularEditor.findKey(e, node);
1339
- matches.push([path, key]);
1340
- }
1341
- break;
1342
- }
1343
- case 'insert_node':
1344
- case 'remove_node':
1345
- case 'merge_node':
1346
- case 'split_node': {
1347
- for (const [node, path] of Editor.levels(e, {
1348
- at: Path.parent(op.path)
1349
- })) {
1350
- const key = AngularEditor.findKey(e, node);
1351
- matches.push([path, key]);
1352
- }
1353
- break;
1354
- }
1355
- case 'move_node': {
1356
- const commonPath = Path.common(Path.parent(op.path), Path.parent(op.newPath));
1357
- for (const [node, path] of Editor.levels(e, {
1358
- at: Path.parent(op.path)
1359
- })) {
1360
- const key = AngularEditor.findKey(e, node);
1361
- matches.push([Editor.pathRef(editor, path), key]);
1362
- }
1363
- for (const [node, path] of Editor.levels(e, {
1364
- at: Path.parent(op.newPath)
1365
- })) {
1366
- if (path.length > commonPath.length) {
1367
- const key = AngularEditor.findKey(e, node);
1368
- matches.push([Editor.pathRef(editor, path), key]);
1369
- }
1370
- }
1371
- break;
1372
- }
1373
- }
1374
- apply(op);
1375
- for (const [source, key] of matches) {
1376
- const [node] = Editor.node(e, Path.isPath(source) ? source : source.current);
1377
- NODE_TO_KEY.set(node, key);
1378
- }
1379
- };
1380
- e.onChange = () => {
1381
- const onContextChange = EDITOR_TO_ON_CHANGE.get(e);
1382
- if (onContextChange) {
1383
- onContextChange();
1384
- }
1385
- onChange();
1386
- };
866
+ let e = editor;
867
+ let { apply } = e;
868
+ e = withDOM(e, clipboardFormatKey);
1387
869
  e.setFragmentData = (dataTransfer, originEvent) => {
1388
870
  const { selection } = e;
1389
871
  if (!selection) {
@@ -1472,11 +954,11 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1472
954
  }
1473
955
  };
1474
956
  e.insertData = async (data) => {
1475
- if (!(await e.insertFragmentData(data))) {
957
+ if (!(await e.customInsertFragmentData(data))) {
1476
958
  e.insertTextData(data);
1477
959
  }
1478
960
  };
1479
- e.insertFragmentData = async (data) => {
961
+ e.customInsertFragmentData = async (data) => {
1480
962
  /**
1481
963
  * Checking copied fragment from application/x-slate-fragment or data-slate-fragment
1482
964
  */
@@ -1487,7 +969,7 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1487
969
  }
1488
970
  return false;
1489
971
  };
1490
- e.insertTextData = async (data) => {
972
+ e.customInsertTextData = async (data) => {
1491
973
  const clipboardData = await getClipboardData(data);
1492
974
  if (clipboardData && clipboardData.text) {
1493
975
  const lines = clipboardData.text.split(/\r\n|\r|\n/);
@@ -1515,6 +997,56 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1515
997
  console.error(errorData);
1516
998
  }
1517
999
  };
1000
+ // exist issue for move operation in withDOM
1001
+ e.apply = (op) => {
1002
+ const matches = [];
1003
+ switch (op.type) {
1004
+ case 'insert_text':
1005
+ case 'remove_text':
1006
+ case 'set_node': {
1007
+ for (const [node, path] of Editor.levels(e, { at: op.path })) {
1008
+ const key = AngularEditor.findKey(e, node);
1009
+ matches.push([path, key]);
1010
+ }
1011
+ break;
1012
+ }
1013
+ case 'insert_node':
1014
+ case 'remove_node':
1015
+ case 'merge_node':
1016
+ case 'split_node': {
1017
+ for (const [node, path] of Editor.levels(e, {
1018
+ at: Path.parent(op.path)
1019
+ })) {
1020
+ const key = AngularEditor.findKey(e, node);
1021
+ matches.push([path, key]);
1022
+ }
1023
+ break;
1024
+ }
1025
+ case 'move_node': {
1026
+ const commonPath = Path.common(Path.parent(op.path), Path.parent(op.newPath));
1027
+ for (const [node, path] of Editor.levels(e, {
1028
+ at: Path.parent(op.path)
1029
+ })) {
1030
+ const key = AngularEditor.findKey(e, node);
1031
+ matches.push([Editor.pathRef(editor, path), key]);
1032
+ }
1033
+ for (const [node, path] of Editor.levels(e, {
1034
+ at: Path.parent(op.newPath)
1035
+ })) {
1036
+ if (path.length > commonPath.length) {
1037
+ const key = AngularEditor.findKey(e, node);
1038
+ matches.push([Editor.pathRef(editor, path), key]);
1039
+ }
1040
+ }
1041
+ break;
1042
+ }
1043
+ }
1044
+ apply(op);
1045
+ for (const [source, key] of matches) {
1046
+ const [node] = Editor.node(e, Path.isPath(source) ? source : source.current);
1047
+ NODE_TO_KEY.set(node, key);
1048
+ }
1049
+ };
1518
1050
  return e;
1519
1051
  };
1520
1052
 
@@ -3118,8 +2650,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImpor
3118
2650
 
3119
2651
  const SLATE_DEFAULT_LEAF_COMPONENT_TOKEN = new InjectionToken('slate-default-leaf-token');
3120
2652
 
3121
- const TRIPLE_CLICK = 3;
3122
-
3123
2653
  // not correctly clipboardData on beforeinput
3124
2654
  const forceOnDOMPaste = IS_SAFARI;
3125
2655
  class SlateEditable {
@@ -3170,7 +2700,7 @@ class SlateEditable {
3170
2700
  EDITOR_TO_ELEMENT.set(this.editor, this.elementRef.nativeElement);
3171
2701
  NODE_TO_ELEMENT.set(this.editor, this.elementRef.nativeElement);
3172
2702
  ELEMENT_TO_NODE.set(this.elementRef.nativeElement, this.editor);
3173
- IS_READONLY.set(this.editor, this.readonly);
2703
+ IS_READ_ONLY.set(this.editor, this.readonly);
3174
2704
  EDITOR_TO_ON_CHANGE.set(this.editor, () => {
3175
2705
  this.ngZone.run(() => {
3176
2706
  this.onChange();
@@ -3202,7 +2732,7 @@ class SlateEditable {
3202
2732
  }
3203
2733
  const readonlyChange = simpleChanges['readonly'];
3204
2734
  if (readonlyChange) {
3205
- IS_READONLY.set(this.editor, this.readonly);
2735
+ IS_READ_ONLY.set(this.editor, this.readonly);
3206
2736
  this.render();
3207
2737
  this.toSlateSelection();
3208
2738
  }
@@ -3276,7 +2806,10 @@ class SlateEditable {
3276
2806
  }
3277
2807
  // If the DOM selection is in the editor and the editor selection is already correct, we're done.
3278
2808
  if (hasDomSelection && hasDomSelectionInEditor && selection && hasStringTarget(domSelection)) {
3279
- const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: true });
2809
+ const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, {
2810
+ exactMatch: false,
2811
+ suppressThrow: true
2812
+ });
3280
2813
  if (rangeFromDOMSelection && Range.equals(rangeFromDOMSelection, selection)) {
3281
2814
  return;
3282
2815
  }
@@ -3290,7 +2823,7 @@ class SlateEditable {
3290
2823
  // but Slate's value is not being updated through any operation
3291
2824
  // and thus it doesn't transform selection on its own
3292
2825
  if (selection && !AngularEditor.hasRange(this.editor, selection)) {
3293
- this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: false });
2826
+ this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { exactMatch: false, suppressThrow: false });
3294
2827
  return;
3295
2828
  }
3296
2829
  // Otherwise the DOM selection is out of sync, so update it.
@@ -3514,14 +3047,14 @@ class SlateEditable {
3514
3047
  let targetRange = null;
3515
3048
  let [nativeTargetRange] = event.getTargetRanges();
3516
3049
  if (nativeTargetRange) {
3517
- targetRange = AngularEditor.toSlateRange(editor, nativeTargetRange);
3050
+ targetRange = AngularEditor.toSlateRange(editor, nativeTargetRange, { exactMatch: false, suppressThrow: false });
3518
3051
  }
3519
3052
  // COMPAT: SelectionChange event is fired after the action is performed, so we
3520
3053
  // have to manually get the selection here to ensure it's up-to-date.
3521
3054
  const window = AngularEditor.getWindow(editor);
3522
3055
  const domSelection = window.getSelection();
3523
3056
  if (!targetRange && domSelection) {
3524
- targetRange = AngularEditor.toSlateRange(editor, domSelection);
3057
+ targetRange = AngularEditor.toSlateRange(editor, domSelection, { exactMatch: false, suppressThrow: false });
3525
3058
  }
3526
3059
  targetRange = targetRange ?? editor.selection;
3527
3060
  if (type === 'insertCompositionText') {
@@ -3567,7 +3100,7 @@ class SlateEditable {
3567
3100
  }
3568
3101
  }
3569
3102
  if (!this.readonly &&
3570
- hasEditableTarget(editor, event.target) &&
3103
+ AngularEditor.hasEditableTarget(editor, event.target) &&
3571
3104
  !isTargetInsideVoid(editor, activeElement) &&
3572
3105
  !this.isDOMEventHandled(event, this.beforeInput)) {
3573
3106
  try {
@@ -3668,7 +3201,7 @@ class SlateEditable {
3668
3201
  onDOMBlur(event) {
3669
3202
  if (this.readonly ||
3670
3203
  this.isUpdatingSelection ||
3671
- !hasEditableTarget(this.editor, event.target) ||
3204
+ !AngularEditor.hasEditableTarget(this.editor, event.target) ||
3672
3205
  this.isDOMEventHandled(event, this.blur)) {
3673
3206
  return;
3674
3207
  }
@@ -3707,7 +3240,7 @@ class SlateEditable {
3707
3240
  }
3708
3241
  onDOMClick(event) {
3709
3242
  if (!this.readonly &&
3710
- hasTarget(this.editor, event.target) &&
3243
+ AngularEditor.hasTarget(this.editor, event.target) &&
3711
3244
  !this.isDOMEventHandled(event, this.click) &&
3712
3245
  isDOMNode(event.target)) {
3713
3246
  const node = AngularEditor.toSlateNode(this.editor, event.target);
@@ -3747,7 +3280,7 @@ class SlateEditable {
3747
3280
  this.forceRender();
3748
3281
  }
3749
3282
  }
3750
- if (hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionStart)) {
3283
+ if (AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionStart)) {
3751
3284
  this.isComposing = true;
3752
3285
  }
3753
3286
  this.render();
@@ -3759,7 +3292,7 @@ class SlateEditable {
3759
3292
  if (!event.data && !Range.isCollapsed(this.editor.selection)) {
3760
3293
  Transforms.delete(this.editor);
3761
3294
  }
3762
- if (hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionEnd)) {
3295
+ if (AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionEnd)) {
3763
3296
  // COMPAT: In Chrome/Firefox, `beforeinput` events for compositions
3764
3297
  // aren't correct and never fire the "insertFromComposition"
3765
3298
  // type that we need. So instead, insert whenever a composition
@@ -3777,13 +3310,13 @@ class SlateEditable {
3777
3310
  onDOMCopy(event) {
3778
3311
  const window = AngularEditor.getWindow(this.editor);
3779
3312
  const isOutsideSlate = !hasStringTarget(window.getSelection()) && isTargetInsideVoid(this.editor, event.target);
3780
- if (!isOutsideSlate && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.copy)) {
3313
+ if (!isOutsideSlate && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.copy)) {
3781
3314
  event.preventDefault();
3782
3315
  AngularEditor.setFragmentData(this.editor, event.clipboardData, 'copy');
3783
3316
  }
3784
3317
  }
3785
3318
  onDOMCut(event) {
3786
- if (!this.readonly && hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.cut)) {
3319
+ if (!this.readonly && AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.cut)) {
3787
3320
  event.preventDefault();
3788
3321
  AngularEditor.setFragmentData(this.editor, event.clipboardData, 'cut');
3789
3322
  const { selection } = this.editor;
@@ -3793,7 +3326,7 @@ class SlateEditable {
3793
3326
  }
3794
3327
  }
3795
3328
  onDOMDragOver(event) {
3796
- if (hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragOver)) {
3329
+ if (AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragOver)) {
3797
3330
  // Only when the target is void, call `preventDefault` to signal
3798
3331
  // that drops are allowed. Editable content is droppable by
3799
3332
  // default, and calling `preventDefault` hides the cursor.
@@ -3804,7 +3337,7 @@ class SlateEditable {
3804
3337
  }
3805
3338
  }
3806
3339
  onDOMDragStart(event) {
3807
- if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3340
+ if (!this.readonly && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3808
3341
  const node = AngularEditor.toSlateNode(this.editor, event.target);
3809
3342
  const path = AngularEditor.findPath(this.editor, node);
3810
3343
  const voidMatch = Element.isElement(node) && (Editor.isVoid(this.editor, node) || Editor.void(this.editor, { at: path, voids: true }));
@@ -3820,7 +3353,7 @@ class SlateEditable {
3820
3353
  }
3821
3354
  onDOMDrop(event) {
3822
3355
  const editor = this.editor;
3823
- if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.drop)) {
3356
+ if (!this.readonly && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.drop)) {
3824
3357
  event.preventDefault();
3825
3358
  // Keep a reference to the dragged range before updating selection
3826
3359
  const draggedRange = editor.selection;
@@ -3847,7 +3380,7 @@ class SlateEditable {
3847
3380
  onDOMDragEnd(event) {
3848
3381
  if (!this.readonly &&
3849
3382
  this.isDraggingInternally &&
3850
- hasTarget(this.editor, event.target) &&
3383
+ AngularEditor.hasTarget(this.editor, event.target) &&
3851
3384
  !this.isDOMEventHandled(event, this.dragEnd)) {
3852
3385
  this.isDraggingInternally = false;
3853
3386
  }
@@ -3855,7 +3388,7 @@ class SlateEditable {
3855
3388
  onDOMFocus(event) {
3856
3389
  if (!this.readonly &&
3857
3390
  !this.isUpdatingSelection &&
3858
- hasEditableTarget(this.editor, event.target) &&
3391
+ AngularEditor.hasEditableTarget(this.editor, event.target) &&
3859
3392
  !this.isDOMEventHandled(event, this.focus)) {
3860
3393
  const el = AngularEditor.toDOMNode(this.editor, this.editor);
3861
3394
  const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
@@ -3875,7 +3408,7 @@ class SlateEditable {
3875
3408
  const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
3876
3409
  const { activeElement } = root;
3877
3410
  if (!this.readonly &&
3878
- hasEditableTarget(editor, event.target) &&
3411
+ AngularEditor.hasEditableTarget(editor, event.target) &&
3879
3412
  !isTargetInsideVoid(editor, activeElement) && // stop fire keydown handle when focus void node
3880
3413
  !this.isComposing &&
3881
3414
  !this.isDOMEventHandled(event, this.keydown)) {
@@ -4097,7 +3630,7 @@ class SlateEditable {
4097
3630
  if (!this.isDOMEventHandled(event, this.paste) &&
4098
3631
  (!HAS_BEFORE_INPUT_SUPPORT || isPlainTextOnlyPaste(event) || forceOnDOMPaste) &&
4099
3632
  !this.readonly &&
4100
- hasEditableTarget(this.editor, event.target)) {
3633
+ AngularEditor.hasEditableTarget(this.editor, event.target)) {
4101
3634
  event.preventDefault();
4102
3635
  AngularEditor.insertData(this.editor, event.clipboardData);
4103
3636
  }
@@ -4109,7 +3642,7 @@ class SlateEditable {
4109
3642
  if (!HAS_BEFORE_INPUT_SUPPORT &&
4110
3643
  !this.readonly &&
4111
3644
  !this.isDOMEventHandled(event.nativeEvent, this.beforeInput) &&
4112
- hasEditableTarget(this.editor, event.nativeEvent.target)) {
3645
+ AngularEditor.hasEditableTarget(this.editor, event.nativeEvent.target)) {
4113
3646
  event.nativeEvent.preventDefault();
4114
3647
  try {
4115
3648
  const text = event.data;
@@ -4300,36 +3833,15 @@ const defaultScrollSelectionIntoView = (editor, domRange) => {
4300
3833
  delete leafEl.getBoundingClientRect;
4301
3834
  }
4302
3835
  };
4303
- /**
4304
- * Check if the target is editable and in the editor.
4305
- */
4306
- const hasEditableTarget = (editor, target) => {
4307
- return isDOMNode(target) && AngularEditor.hasDOMNode(editor, target, { editable: true });
4308
- };
4309
- /**
4310
- * Check if two DOM range objects are equal.
4311
- */
4312
- const isRangeEqual = (a, b) => {
4313
- return ((a.startContainer === b.startContainer &&
4314
- a.startOffset === b.startOffset &&
4315
- a.endContainer === b.endContainer &&
4316
- a.endOffset === b.endOffset) ||
4317
- (a.startContainer === b.endContainer &&
4318
- a.startOffset === b.endOffset &&
4319
- a.endContainer === b.startContainer &&
4320
- a.endOffset === b.startOffset));
4321
- };
4322
- /**
4323
- * Check if the target is in the editor.
4324
- */
4325
- const hasTarget = (editor, target) => {
4326
- return isDOMNode(target) && AngularEditor.hasDOMNode(editor, target);
4327
- };
4328
3836
  /**
4329
3837
  * Check if the target is inside void and in the editor.
4330
3838
  */
4331
3839
  const isTargetInsideVoid = (editor, target) => {
4332
- const slateNode = hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target, { suppressThrow: true });
3840
+ let slateNode = null;
3841
+ try {
3842
+ slateNode = AngularEditor.hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target);
3843
+ }
3844
+ catch (error) { }
4333
3845
  return slateNode && Element.isElement(slateNode) && Editor.isVoid(editor, slateNode);
4334
3846
  };
4335
3847
  const hasStringTarget = (domSelection) => {
@@ -4490,5 +4002,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImpor
4490
4002
  * Generated bundle index. Do not edit.
4491
4003
  */
4492
4004
 
4493
- export { AngularEditor, BaseComponent, BaseElementComponent, BaseLeafComponent, BaseTextComponent, DOMComment, DOMElement, DOMNode, DOMRange, DOMSelection, DOMStaticRange, DOMText, EDITOR_TO_AFTER_VIEW_INIT_QUEUE, EDITOR_TO_ELEMENT, EDITOR_TO_ON_CHANGE, EDITOR_TO_PLACEHOLDER, EDITOR_TO_WINDOW, ELEMENT_TO_COMPONENT, ELEMENT_TO_NODE, FAKE_LEFT_BLOCK_CARD_OFFSET, FAKE_RIGHT_BLOCK_CARD_OFFSET, HAS_BEFORE_INPUT_SUPPORT, IS_ANDROID, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_CLICKING, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_FIREFOX_LEGACY, IS_FOCUSED, IS_IOS, IS_QQBROWSER, IS_READONLY, IS_SAFARI, IS_UC_MOBILE, IS_WECHATBROWSER, KEY_TO_ELEMENT, Key, NODE_TO_ELEMENT, NODE_TO_INDEX, NODE_TO_KEY, NODE_TO_PARENT, PLACEHOLDER_SYMBOL, SlateChildren, SlateChildrenOutlet, SlateDefaultString, SlateEditable, SlateElement, SlateErrorCode, SlateFragmentAttributeKey, SlateLeaves, SlateModule, SlateString, blobAsString, buildHTMLText, check, completeTable, createClipboardData, createThrottleRAF, defaultScrollSelectionIntoView, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getDataTransferClipboard, getDataTransferClipboardText, getDefaultView, getEditableChild, getEditableChildAndIndex, getNavigatorClipboard, getPlainText, getSlateFragmentAttribute, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hasEditableTarget, hasShadowRoot, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDOMComment, isDOMElement, isDOMNode, isDOMSelection, isDOMText, isDecoratorRangeListEqual, isEmpty, isInvalidTable, isPlainTextOnlyPaste, isTemplateRef, isValid, normalize, normalizeDOMPoint, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
4005
+ 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, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, getPlainText, 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 };
4494
4006
  //# sourceMappingURL=slate-angular.mjs.map