slate-angular 19.0.0-next.0 → 19.1.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
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';
3
+ export { NODE_TO_INDEX, NODE_TO_PARENT } from 'slate-dom';
2
4
  import { isKeyHotkey } from 'is-hotkey';
3
5
  import * as i0 from '@angular/core';
4
6
  import { TemplateRef, ViewChild, ChangeDetectionStrategy, Component, InjectionToken, ComponentRef, IterableDiffers, inject, ElementRef, ChangeDetectorRef, Input, Directive, HostBinding, ViewContainerRef, forwardRef, Inject, NgModule } from '@angular/core';
@@ -9,258 +11,6 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
9
11
  import { HistoryEditor } from 'slate-history';
10
12
  import { CommonModule } from '@angular/common';
11
13
 
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
14
  const FAKE_LEFT_BLOCK_CARD_OFFSET = -1;
265
15
  const FAKE_RIGHT_BLOCK_CARD_OFFSET = -2;
266
16
  function hasBlockCardWithNode(node) {
@@ -286,61 +36,251 @@ function isCardCenterByTargetAttr(targetAttr) {
286
36
  return targetAttr && targetAttr.nodeValue === 'card-center';
287
37
  }
288
38
 
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');
39
+ const customToDOMNode = (editor, node) => {
40
+ const domNode = Editor.isEditor(node) ? EDITOR_TO_ELEMENT.get(editor) : NODE_TO_ELEMENT.get(node);
41
+ if (!domNode) {
42
+ throw new Error(`Cannot resolve a DOM node from Slate node: ${JSON.stringify(node)}`);
43
+ }
44
+ return domNode;
45
+ };
46
+ DOMEditor.toDOMNode = customToDOMNode;
47
+ const toDOMPointForBlockCard = (editor, point) => {
48
+ const [node] = Editor.node(editor, point.path);
49
+ const [parentNode] = Editor.parent(editor, point.path);
50
+ if (editor.isBlockCard(parentNode) || editor.isBlockCard(node)) {
51
+ if (point.offset < 0) {
52
+ if (point.offset === FAKE_LEFT_BLOCK_CARD_OFFSET) {
53
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, node, { direction: 'left' });
54
+ return [cursorNode, 1];
55
+ }
56
+ else {
57
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, node, { direction: 'right' });
58
+ return [cursorNode, 1];
59
+ }
297
60
  }
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);
61
+ if (editor.selection && Range.isExpanded(editor.selection)) {
62
+ const [start, end] = Range.edges(editor.selection);
63
+ if (start === point) {
64
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, parentNode, { direction: 'left' });
65
+ return [cursorNode, 1];
66
+ }
67
+ else {
68
+ const cursorNode = CustomDOMEditor.getCardCursorNode(editor, parentNode, { direction: 'right' });
69
+ return [cursorNode, 1];
70
+ }
308
71
  }
309
- return key;
310
- },
311
- /**
312
- * handle editor error.
313
- */
314
- onError(errorData) {
315
- if (errorData.nativeError) {
316
- throw errorData.nativeError;
72
+ }
73
+ };
74
+ const customToDOMPoint = (editor, point) => {
75
+ const [node] = Editor.node(editor, point.path);
76
+ const el = customToDOMNode(editor, node);
77
+ let domPoint;
78
+ const domPointForBlackCard = toDOMPointForBlockCard(editor, point);
79
+ if (domPointForBlackCard) {
80
+ return domPointForBlackCard;
81
+ }
82
+ // If we're inside a void node, force the offset to 0, otherwise the zero
83
+ // width spacing character will result in an incorrect offset of 1
84
+ if (Editor.void(editor, { at: point })) {
85
+ point = { path: point.path, offset: 0 };
86
+ }
87
+ // For each leaf, we need to isolate its content, which means filtering
88
+ // to its direct text and zero-width spans. (We have to filter out any
89
+ // other siblings that may have been rendered alongside them.)
90
+ const selector = `[data-slate-string], [data-slate-zero-width]`;
91
+ const texts = Array.from(el.querySelectorAll(selector));
92
+ let start = 0;
93
+ for (const text of texts) {
94
+ const domNode = text.childNodes[0];
95
+ if (domNode == null || domNode.textContent == null) {
96
+ continue;
317
97
  }
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
- }
98
+ const { length } = domNode.textContent;
99
+ const attr = text.getAttribute('data-slate-length');
100
+ const trueLength = attr == null ? length : parseInt(attr, 10);
101
+ const end = start + trueLength;
102
+ if (point.offset <= end) {
103
+ const offset = Math.min(length, Math.max(0, point.offset - start));
104
+ domPoint = [domNode, offset];
105
+ // fixed cursor position after zero width char
106
+ if (offset === 0 && length === 1 && domNode.textContent === '\uFEFF') {
107
+ domPoint = [domNode, offset + 1];
334
108
  }
335
- const i = NODE_TO_INDEX.get(child);
336
- if (i == null) {
337
- break;
109
+ break;
110
+ }
111
+ start = end;
112
+ }
113
+ if (!domPoint) {
114
+ throw new Error(`Cannot resolve a DOM point from Slate point: ${JSON.stringify(point)}`);
115
+ }
116
+ return domPoint;
117
+ };
118
+ DOMEditor.toDOMPoint = customToDOMPoint;
119
+ const toSlatePointForBlockCard = (editor, domPoint, nearestNode) => {
120
+ const [domNode] = domPoint;
121
+ const cardTargetAttr = getCardTargetAttribute(domNode);
122
+ if (cardTargetAttr) {
123
+ const domSelection = window.getSelection();
124
+ const blockCardEntry = CustomDOMEditor.toSlateCardEntry(editor, domNode) || CustomDOMEditor.toSlateCardEntry(editor, nearestNode);
125
+ const [, blockPath] = blockCardEntry;
126
+ if (domSelection.isCollapsed) {
127
+ if (isCardLeftByTargetAttr(cardTargetAttr)) {
128
+ return { path: blockPath, offset: -1 };
129
+ }
130
+ else {
131
+ return { path: blockPath, offset: -2 };
338
132
  }
339
- path.unshift(i);
340
- child = parent;
341
133
  }
342
- throw new Error(`Unable to find the path for Slate node: ${JSON.stringify(node)}`);
343
- },
134
+ if (isCardLeftByTargetAttr(cardTargetAttr)) {
135
+ return Editor.start(editor, blockPath);
136
+ }
137
+ else {
138
+ return Editor.end(editor, blockPath);
139
+ }
140
+ }
141
+ };
142
+ const customToSlatePoint = (editor, domPoint, options) => {
143
+ const { exactMatch, suppressThrow } = options;
144
+ const [nearestNode, nearestOffset] = normalizeDOMPoint(domPoint);
145
+ let parentNode = nearestNode.parentNode;
146
+ let textNode = null;
147
+ let offset = 0;
148
+ const slatePointForBlockCard = toSlatePointForBlockCard(editor, domPoint, nearestNode);
149
+ if (slatePointForBlockCard) {
150
+ return slatePointForBlockCard;
151
+ }
152
+ if (parentNode) {
153
+ const voidNode = parentNode.closest('[data-slate-void="true"]');
154
+ let leafNode = parentNode.closest('[data-slate-leaf]');
155
+ let domNode = null;
156
+ // Calculate how far into the text node the `nearestNode` is, so that we
157
+ // can determine what the offset relative to the text node is.
158
+ if (leafNode && CustomDOMEditor.isLeafInEditor(editor, leafNode)) {
159
+ textNode = leafNode.closest('[data-slate-node="text"]');
160
+ const window = DOMEditor.getWindow(editor);
161
+ const range = window.document.createRange();
162
+ range.setStart(textNode, 0);
163
+ range.setEnd(nearestNode, nearestOffset);
164
+ const contents = range.cloneContents();
165
+ const removals = [
166
+ ...Array.prototype.slice.call(contents.querySelectorAll('[data-slate-zero-width]')),
167
+ ...Array.prototype.slice.call(contents.querySelectorAll('[contenteditable=false]'))
168
+ ];
169
+ removals.forEach(el => {
170
+ el.parentNode.removeChild(el);
171
+ });
172
+ // COMPAT: Edge has a bug where Range.prototype.toString() will
173
+ // convert \n into \r\n. The bug causes a loop when slate-react
174
+ // attempts to reposition its cursor to match the native position. Use
175
+ // textContent.length instead.
176
+ // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10291116/
177
+ offset = contents.textContent.length;
178
+ domNode = textNode;
179
+ }
180
+ else if (voidNode) {
181
+ // For void nodes, the element with the offset key will be a cousin, not an
182
+ // ancestor, so find it by going down from the nearest void parent.
183
+ const spacer = voidNode.querySelector('[data-slate-spacer="true"]');
184
+ leafNode = spacer.firstElementChild;
185
+ parentNode = leafNode.firstElementChild;
186
+ textNode = spacer;
187
+ domNode = leafNode;
188
+ offset = domNode.textContent.length;
189
+ }
190
+ // COMPAT: If the parent node is a Slate zero-width space, editor is
191
+ // because the text node should have no characters. However, during IME
192
+ // composition the ASCII characters will be prepended to the zero-width
193
+ // space, so subtract 1 from the offset to account for the zero-width
194
+ // space character.
195
+ if (domNode && offset === domNode.textContent.length && parentNode && parentNode.hasAttribute('data-slate-zero-width')) {
196
+ offset--;
197
+ }
198
+ }
199
+ if (!textNode) {
200
+ if (suppressThrow) {
201
+ return null;
202
+ }
203
+ throw new Error(`Cannot resolve a Slate point from DOM point: ${domPoint}`);
204
+ }
205
+ // COMPAT: If someone is clicking from one Slate editor into another,
206
+ // the select event fires twice, once for the old editor's `element`
207
+ // first, and then afterwards for the correct `element`. (2017/03/03)
208
+ let slateNode = null;
209
+ try {
210
+ slateNode = CustomDOMEditor.toSlateNode(editor, textNode);
211
+ }
212
+ catch (error) {
213
+ if (!suppressThrow) {
214
+ throw error;
215
+ }
216
+ }
217
+ if (!slateNode && suppressThrow) {
218
+ return null;
219
+ }
220
+ const path = CustomDOMEditor.findPath(editor, slateNode);
221
+ return { path, offset };
222
+ };
223
+ DOMEditor.toSlatePoint = customToSlatePoint;
224
+ const customToSlateRange = (editor, domRange, options) => {
225
+ const { exactMatch, suppressThrow } = options || {};
226
+ const el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer;
227
+ let anchorNode;
228
+ let anchorOffset;
229
+ let focusNode;
230
+ let focusOffset;
231
+ let isCollapsed;
232
+ if (el) {
233
+ if (isDOMSelection(domRange)) {
234
+ anchorNode = domRange.anchorNode;
235
+ anchorOffset = domRange.anchorOffset;
236
+ focusNode = domRange.focusNode;
237
+ focusOffset = domRange.focusOffset;
238
+ // COMPAT: There's a bug in chrome that always returns `true` for
239
+ // `isCollapsed` for a Selection that comes from a ShadowRoot.
240
+ // (2020/08/08)
241
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=447523
242
+ if (IS_CHROME$1 && hasShadowRoot(anchorNode)) {
243
+ isCollapsed = domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset;
244
+ }
245
+ else {
246
+ isCollapsed = domRange.isCollapsed;
247
+ }
248
+ }
249
+ else {
250
+ anchorNode = domRange.startContainer;
251
+ anchorOffset = domRange.startOffset;
252
+ focusNode = domRange.endContainer;
253
+ focusOffset = domRange.endOffset;
254
+ isCollapsed = domRange.collapsed;
255
+ }
256
+ }
257
+ if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
258
+ throw new Error(`Cannot resolve a Slate range from DOM range: ${domRange}`);
259
+ }
260
+ const anchor = DOMEditor.toSlatePoint(editor, [anchorNode, anchorOffset], { suppressThrow, exactMatch });
261
+ if (!anchor) {
262
+ return null;
263
+ }
264
+ const focus = isCollapsed ? anchor : DOMEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
265
+ if (!focus) {
266
+ return null;
267
+ }
268
+ let range = { anchor: anchor, focus: focus };
269
+ // if the selection is a hanging range that ends in a void
270
+ // and the DOM focus is an Element
271
+ // (meaning that the selection ends before the element)
272
+ // unhang the range to avoid mistakenly including the void
273
+ if (Range.isExpanded(range) &&
274
+ Range.isForward(range) &&
275
+ isDOMElement(focusNode) &&
276
+ Editor.void(editor, { at: range.focus, mode: 'highest' })) {
277
+ range = Editor.unhangRange(editor, range, { voids: true });
278
+ }
279
+ return range;
280
+ };
281
+ DOMEditor.toSlateRange = customToSlateRange;
282
+ const CustomDOMEditor = {
283
+ ...DOMEditor,
344
284
  isNodeInEditor(editor, node) {
345
285
  let child = node;
346
286
  while (true) {
@@ -361,321 +301,14 @@ const AngularEditor = {
361
301
  }
362
302
  return false;
363
303
  },
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
304
+ isLeafInEditor(editor, leafNode) {
305
+ const textNode = leafNode.closest('[data-slate-node="text"]');
306
+ let node = null;
452
307
  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}`);
308
+ node = CustomDOMEditor.toSlateNode(editor, textNode);
621
309
  }
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)) {
310
+ catch (error) { }
311
+ if (node && CustomDOMEditor.isNodeInEditor(editor, node)) {
679
312
  return true;
680
313
  }
681
314
  else {
@@ -683,162 +316,22 @@ const AngularEditor = {
683
316
  }
684
317
  },
685
318
  /**
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.
319
+ * Check if the editor is hanging right.
782
320
  */
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;
321
+ isBlockHangingRight(editor) {
322
+ const { selection } = editor;
323
+ if (!selection) {
324
+ return false;
822
325
  }
823
- const focus = isCollapsed ? anchor : AngularEditor.toSlatePoint(editor, [focusNode, focusOffset], { suppressThrow, exactMatch });
824
- if (!focus) {
825
- return null;
326
+ if (Range.isCollapsed(selection)) {
327
+ return false;
826
328
  }
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);
329
+ const [start, end] = Range.edges(selection);
330
+ const endBlock = Editor.above(editor, {
331
+ at: end,
332
+ match: node => Element.isElement(node) && Editor.isBlock(editor, node)
333
+ });
334
+ return Editor.isStart(editor, end, endBlock[1]);
842
335
  },
843
336
  isBlockCardLeftCursor(editor) {
844
337
  return (editor.selection?.anchor?.offset === FAKE_LEFT_BLOCK_CARD_OFFSET &&
@@ -849,15 +342,45 @@ const AngularEditor = {
849
342
  editor.selection?.focus?.offset === FAKE_RIGHT_BLOCK_CARD_OFFSET);
850
343
  },
851
344
  getCardCursorNode(editor, blockCardNode, options) {
852
- const blockCardElement = AngularEditor.toDOMNode(editor, blockCardNode);
345
+ const blockCardElement = DOMEditor.toDOMNode(editor, blockCardNode);
853
346
  const cardCenter = blockCardElement.parentElement;
854
347
  return options.direction === 'left' ? cardCenter.previousElementSibling.firstChild : cardCenter.nextElementSibling.firstChild;
855
348
  },
856
349
  toSlateCardEntry(editor, node) {
857
350
  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);
351
+ const slateNode = DOMEditor.toSlateNode(editor, element);
352
+ const path = DOMEditor.findPath(editor, slateNode);
860
353
  return [slateNode, path];
354
+ }
355
+ };
356
+
357
+ const AngularEditor = {
358
+ ...CustomDOMEditor,
359
+ /**
360
+ * handle editor error.
361
+ */
362
+ onError(errorData) {
363
+ if (errorData.nativeError) {
364
+ throw errorData.nativeError;
365
+ }
366
+ },
367
+ /**
368
+ * onKeydown hook.
369
+ */
370
+ onKeydown(editor, data) {
371
+ editor.onKeydown(data);
372
+ },
373
+ /**
374
+ * onClick hook.
375
+ */
376
+ onClick(editor, data) {
377
+ editor.onClick(data);
378
+ },
379
+ deleteCutData(editor) {
380
+ editor.deleteCutData();
381
+ },
382
+ isLeafBlock(editor, node) {
383
+ return Element.isElement(node) && !editor.isInline(node) && Editor.hasInlines(editor, node);
861
384
  },
862
385
  /**
863
386
  * move native selection to card-left or card-right
@@ -883,13 +406,53 @@ const AngularEditor = {
883
406
  offset: options.direction === 'left' ? FAKE_LEFT_BLOCK_CARD_OFFSET : FAKE_RIGHT_BLOCK_CARD_OFFSET
884
407
  };
885
408
  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
409
  }
891
410
  };
892
411
 
412
+ /**
413
+ * Symbols.
414
+ */
415
+ const PLACEHOLDER_SYMBOL = Symbol('placeholder');
416
+ /**
417
+ * Weak map for associating the html element with the component.
418
+ */
419
+ const ELEMENT_TO_COMPONENT = new WeakMap();
420
+ const EDITOR_TO_AFTER_VIEW_INIT_QUEUE = new WeakMap();
421
+
422
+ const IS_IOS = typeof navigator !== 'undefined' &&
423
+ typeof window !== 'undefined' &&
424
+ /iPad|iPhone|iPod/.test(navigator.userAgent) &&
425
+ !window.MSStream;
426
+ const IS_APPLE = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent);
427
+ const IS_ANDROID = typeof navigator !== 'undefined' && /Android/.test(navigator.userAgent);
428
+ const IS_FIREFOX = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
429
+ const IS_SAFARI = typeof navigator !== 'undefined' && /Version\/[\d\.]+.*Safari/.test(navigator.userAgent);
430
+ // "modern" Edge was released at 79.x
431
+ const IS_EDGE_LEGACY = typeof navigator !== 'undefined' && /Edge?\/(?:[0-6][0-9]|[0-7][0-8])(?:\.)/i.test(navigator.userAgent);
432
+ const IS_CHROME = typeof navigator !== 'undefined' && /Chrome/i.test(navigator.userAgent);
433
+ // Native beforeInput events don't work well with react on Chrome 75 and older, Chrome 76+ can use beforeInput
434
+ const IS_CHROME_LEGACY = typeof navigator !== 'undefined' &&
435
+ /Chrome?\/(?:[0-7][0-5]|[0-6][0-9])/i.test(navigator.userAgent) &&
436
+ // Exclude Chrome version greater than 3 bits,Chrome releases v100 on 2022.03.29
437
+ !/Chrome?\/(?:\d{3,})/i.test(navigator.userAgent);
438
+ // Firefox did not support `beforeInput` until `v87`.
439
+ const IS_FIREFOX_LEGACY = typeof navigator !== 'undefined' && /^(?!.*Seamonkey)(?=.*Firefox\/(?:[0-7][0-9]|[0-8][0-6])(?:\.)).*/i.test(navigator.userAgent);
440
+ // qq browser
441
+ const IS_QQBROWSER = typeof navigator !== 'undefined' && /.*QQBrowser/.test(navigator.userAgent);
442
+ // UC mobile browser
443
+ const IS_UC_MOBILE = typeof navigator !== 'undefined' && /.*UCBrowser/.test(navigator.userAgent);
444
+ // Wechat browser
445
+ const IS_WECHATBROWSER = typeof navigator !== 'undefined' && /.*Wechat/.test(navigator.userAgent);
446
+ // COMPAT: Firefox/Edge Legacy don't support the `beforeinput` event
447
+ // Chrome Legacy doesn't support `beforeinput` correctly
448
+ const HAS_BEFORE_INPUT_SUPPORT = !IS_CHROME_LEGACY &&
449
+ !IS_EDGE_LEGACY &&
450
+ // globalThis is undefined in older browsers
451
+ typeof globalThis !== 'undefined' &&
452
+ globalThis.InputEvent &&
453
+ // @ts-ignore The `getTargetRanges` property isn't recognized.
454
+ typeof globalThis.InputEvent.prototype.getTargetRanges === 'function';
455
+
893
456
  /**
894
457
  * Hotkey mappings for each platform.
895
458
  */
@@ -1188,6 +751,44 @@ const getNavigatorClipboard = async () => {
1188
751
  return clipboardData;
1189
752
  };
1190
753
 
754
+ const SlateFragmentAttributeKey = 'data-slate-angular-fragment';
755
+ /**
756
+ * Get x-slate-fragment attribute from data-slate-angular-fragment
757
+ */
758
+ const catchSlateFragment = /data-slate-angular-fragment="(.+?)"/m;
759
+ const getSlateFragmentAttribute = (htmlData) => {
760
+ const [, fragment] = htmlData.match(catchSlateFragment) || [];
761
+ return fragment;
762
+ };
763
+ /**
764
+ * Check if a DOM node is an element node.
765
+ */
766
+ const isDOMText = (value) => {
767
+ return isDOMNode(value) && value.nodeType === 3;
768
+ };
769
+ /**
770
+ * Get a plaintext representation of the content of a node, accounting for block
771
+ * elements which get a newline appended.
772
+ *
773
+ * The domNode must be attached to the DOM.
774
+ */
775
+ const getPlainText = (domNode) => {
776
+ let text = '';
777
+ if (isDOMText(domNode) && domNode.nodeValue) {
778
+ return domNode.nodeValue;
779
+ }
780
+ if (isDOMElement(domNode)) {
781
+ for (const childNode of Array.from(domNode.childNodes)) {
782
+ text += getPlainText(childNode);
783
+ }
784
+ const display = getComputedStyle(domNode).getPropertyValue('display');
785
+ if (display === 'block' || display === 'list' || domNode.tagName === 'BR') {
786
+ text += '\n';
787
+ }
788
+ }
789
+ return text;
790
+ };
791
+
1191
792
  const buildHTMLText = (wrapper, attach, data) => {
1192
793
  const stringObj = JSON.stringify(data);
1193
794
  const encoded = window.btoa(encodeURIComponent(stringObj));
@@ -1262,128 +863,10 @@ const setClipboardData = async (clipboardData, wrapper, attach, dataTransfer) =>
1262
863
  }
1263
864
  };
1264
865
 
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
866
  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
- };
867
+ let e = editor;
868
+ let { apply } = e;
869
+ e = withDOM(e, clipboardFormatKey);
1387
870
  e.setFragmentData = (dataTransfer, originEvent) => {
1388
871
  const { selection } = e;
1389
872
  if (!selection) {
@@ -1472,11 +955,11 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1472
955
  }
1473
956
  };
1474
957
  e.insertData = async (data) => {
1475
- if (!(await e.insertFragmentData(data))) {
958
+ if (!(await e.customInsertFragmentData(data))) {
1476
959
  e.insertTextData(data);
1477
960
  }
1478
961
  };
1479
- e.insertFragmentData = async (data) => {
962
+ e.customInsertFragmentData = async (data) => {
1480
963
  /**
1481
964
  * Checking copied fragment from application/x-slate-fragment or data-slate-fragment
1482
965
  */
@@ -1487,7 +970,7 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1487
970
  }
1488
971
  return false;
1489
972
  };
1490
- e.insertTextData = async (data) => {
973
+ e.customInsertTextData = async (data) => {
1491
974
  const clipboardData = await getClipboardData(data);
1492
975
  if (clipboardData && clipboardData.text) {
1493
976
  const lines = clipboardData.text.split(/\r\n|\r|\n/);
@@ -1515,6 +998,56 @@ const withAngular = (editor, clipboardFormatKey = 'x-slate-fragment') => {
1515
998
  console.error(errorData);
1516
999
  }
1517
1000
  };
1001
+ // exist issue for move operation in withDOM
1002
+ e.apply = (op) => {
1003
+ const matches = [];
1004
+ switch (op.type) {
1005
+ case 'insert_text':
1006
+ case 'remove_text':
1007
+ case 'set_node': {
1008
+ for (const [node, path] of Editor.levels(e, { at: op.path })) {
1009
+ const key = AngularEditor.findKey(e, node);
1010
+ matches.push([path, key]);
1011
+ }
1012
+ break;
1013
+ }
1014
+ case 'insert_node':
1015
+ case 'remove_node':
1016
+ case 'merge_node':
1017
+ case 'split_node': {
1018
+ for (const [node, path] of Editor.levels(e, {
1019
+ at: Path.parent(op.path)
1020
+ })) {
1021
+ const key = AngularEditor.findKey(e, node);
1022
+ matches.push([path, key]);
1023
+ }
1024
+ break;
1025
+ }
1026
+ case 'move_node': {
1027
+ const commonPath = Path.common(Path.parent(op.path), Path.parent(op.newPath));
1028
+ for (const [node, path] of Editor.levels(e, {
1029
+ at: Path.parent(op.path)
1030
+ })) {
1031
+ const key = AngularEditor.findKey(e, node);
1032
+ matches.push([Editor.pathRef(editor, path), key]);
1033
+ }
1034
+ for (const [node, path] of Editor.levels(e, {
1035
+ at: Path.parent(op.newPath)
1036
+ })) {
1037
+ if (path.length > commonPath.length) {
1038
+ const key = AngularEditor.findKey(e, node);
1039
+ matches.push([Editor.pathRef(editor, path), key]);
1040
+ }
1041
+ }
1042
+ break;
1043
+ }
1044
+ }
1045
+ apply(op);
1046
+ for (const [source, key] of matches) {
1047
+ const [node] = Editor.node(e, Path.isPath(source) ? source : source.current);
1048
+ NODE_TO_KEY.set(node, key);
1049
+ }
1050
+ };
1518
1051
  return e;
1519
1052
  };
1520
1053
 
@@ -3118,8 +2651,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImpor
3118
2651
 
3119
2652
  const SLATE_DEFAULT_LEAF_COMPONENT_TOKEN = new InjectionToken('slate-default-leaf-token');
3120
2653
 
3121
- const TRIPLE_CLICK = 3;
3122
-
3123
2654
  // not correctly clipboardData on beforeinput
3124
2655
  const forceOnDOMPaste = IS_SAFARI;
3125
2656
  class SlateEditable {
@@ -3170,7 +2701,7 @@ class SlateEditable {
3170
2701
  EDITOR_TO_ELEMENT.set(this.editor, this.elementRef.nativeElement);
3171
2702
  NODE_TO_ELEMENT.set(this.editor, this.elementRef.nativeElement);
3172
2703
  ELEMENT_TO_NODE.set(this.elementRef.nativeElement, this.editor);
3173
- IS_READONLY.set(this.editor, this.readonly);
2704
+ IS_READ_ONLY.set(this.editor, this.readonly);
3174
2705
  EDITOR_TO_ON_CHANGE.set(this.editor, () => {
3175
2706
  this.ngZone.run(() => {
3176
2707
  this.onChange();
@@ -3202,7 +2733,7 @@ class SlateEditable {
3202
2733
  }
3203
2734
  const readonlyChange = simpleChanges['readonly'];
3204
2735
  if (readonlyChange) {
3205
- IS_READONLY.set(this.editor, this.readonly);
2736
+ IS_READ_ONLY.set(this.editor, this.readonly);
3206
2737
  this.render();
3207
2738
  this.toSlateSelection();
3208
2739
  }
@@ -3276,7 +2807,10 @@ class SlateEditable {
3276
2807
  }
3277
2808
  // If the DOM selection is in the editor and the editor selection is already correct, we're done.
3278
2809
  if (hasDomSelection && hasDomSelectionInEditor && selection && hasStringTarget(domSelection)) {
3279
- const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: true });
2810
+ const rangeFromDOMSelection = AngularEditor.toSlateRange(this.editor, domSelection, {
2811
+ exactMatch: false,
2812
+ suppressThrow: true
2813
+ });
3280
2814
  if (rangeFromDOMSelection && Range.equals(rangeFromDOMSelection, selection)) {
3281
2815
  return;
3282
2816
  }
@@ -3290,7 +2824,7 @@ class SlateEditable {
3290
2824
  // but Slate's value is not being updated through any operation
3291
2825
  // and thus it doesn't transform selection on its own
3292
2826
  if (selection && !AngularEditor.hasRange(this.editor, selection)) {
3293
- this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { suppressThrow: false });
2827
+ this.editor.selection = AngularEditor.toSlateRange(this.editor, domSelection, { exactMatch: false, suppressThrow: false });
3294
2828
  return;
3295
2829
  }
3296
2830
  // Otherwise the DOM selection is out of sync, so update it.
@@ -3514,14 +3048,14 @@ class SlateEditable {
3514
3048
  let targetRange = null;
3515
3049
  let [nativeTargetRange] = event.getTargetRanges();
3516
3050
  if (nativeTargetRange) {
3517
- targetRange = AngularEditor.toSlateRange(editor, nativeTargetRange);
3051
+ targetRange = AngularEditor.toSlateRange(editor, nativeTargetRange, { exactMatch: false, suppressThrow: false });
3518
3052
  }
3519
3053
  // COMPAT: SelectionChange event is fired after the action is performed, so we
3520
3054
  // have to manually get the selection here to ensure it's up-to-date.
3521
3055
  const window = AngularEditor.getWindow(editor);
3522
3056
  const domSelection = window.getSelection();
3523
3057
  if (!targetRange && domSelection) {
3524
- targetRange = AngularEditor.toSlateRange(editor, domSelection);
3058
+ targetRange = AngularEditor.toSlateRange(editor, domSelection, { exactMatch: false, suppressThrow: false });
3525
3059
  }
3526
3060
  targetRange = targetRange ?? editor.selection;
3527
3061
  if (type === 'insertCompositionText') {
@@ -3567,7 +3101,7 @@ class SlateEditable {
3567
3101
  }
3568
3102
  }
3569
3103
  if (!this.readonly &&
3570
- hasEditableTarget(editor, event.target) &&
3104
+ AngularEditor.hasEditableTarget(editor, event.target) &&
3571
3105
  !isTargetInsideVoid(editor, activeElement) &&
3572
3106
  !this.isDOMEventHandled(event, this.beforeInput)) {
3573
3107
  try {
@@ -3668,7 +3202,7 @@ class SlateEditable {
3668
3202
  onDOMBlur(event) {
3669
3203
  if (this.readonly ||
3670
3204
  this.isUpdatingSelection ||
3671
- !hasEditableTarget(this.editor, event.target) ||
3205
+ !AngularEditor.hasEditableTarget(this.editor, event.target) ||
3672
3206
  this.isDOMEventHandled(event, this.blur)) {
3673
3207
  return;
3674
3208
  }
@@ -3707,7 +3241,7 @@ class SlateEditable {
3707
3241
  }
3708
3242
  onDOMClick(event) {
3709
3243
  if (!this.readonly &&
3710
- hasTarget(this.editor, event.target) &&
3244
+ AngularEditor.hasTarget(this.editor, event.target) &&
3711
3245
  !this.isDOMEventHandled(event, this.click) &&
3712
3246
  isDOMNode(event.target)) {
3713
3247
  const node = AngularEditor.toSlateNode(this.editor, event.target);
@@ -3747,7 +3281,7 @@ class SlateEditable {
3747
3281
  this.forceRender();
3748
3282
  }
3749
3283
  }
3750
- if (hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionStart)) {
3284
+ if (AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionStart)) {
3751
3285
  this.isComposing = true;
3752
3286
  }
3753
3287
  this.render();
@@ -3759,7 +3293,7 @@ class SlateEditable {
3759
3293
  if (!event.data && !Range.isCollapsed(this.editor.selection)) {
3760
3294
  Transforms.delete(this.editor);
3761
3295
  }
3762
- if (hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionEnd)) {
3296
+ if (AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.compositionEnd)) {
3763
3297
  // COMPAT: In Chrome/Firefox, `beforeinput` events for compositions
3764
3298
  // aren't correct and never fire the "insertFromComposition"
3765
3299
  // type that we need. So instead, insert whenever a composition
@@ -3777,13 +3311,13 @@ class SlateEditable {
3777
3311
  onDOMCopy(event) {
3778
3312
  const window = AngularEditor.getWindow(this.editor);
3779
3313
  const isOutsideSlate = !hasStringTarget(window.getSelection()) && isTargetInsideVoid(this.editor, event.target);
3780
- if (!isOutsideSlate && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.copy)) {
3314
+ if (!isOutsideSlate && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.copy)) {
3781
3315
  event.preventDefault();
3782
3316
  AngularEditor.setFragmentData(this.editor, event.clipboardData, 'copy');
3783
3317
  }
3784
3318
  }
3785
3319
  onDOMCut(event) {
3786
- if (!this.readonly && hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.cut)) {
3320
+ if (!this.readonly && AngularEditor.hasEditableTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.cut)) {
3787
3321
  event.preventDefault();
3788
3322
  AngularEditor.setFragmentData(this.editor, event.clipboardData, 'cut');
3789
3323
  const { selection } = this.editor;
@@ -3793,7 +3327,7 @@ class SlateEditable {
3793
3327
  }
3794
3328
  }
3795
3329
  onDOMDragOver(event) {
3796
- if (hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragOver)) {
3330
+ if (AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragOver)) {
3797
3331
  // Only when the target is void, call `preventDefault` to signal
3798
3332
  // that drops are allowed. Editable content is droppable by
3799
3333
  // default, and calling `preventDefault` hides the cursor.
@@ -3804,7 +3338,7 @@ class SlateEditable {
3804
3338
  }
3805
3339
  }
3806
3340
  onDOMDragStart(event) {
3807
- if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3341
+ if (!this.readonly && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.dragStart)) {
3808
3342
  const node = AngularEditor.toSlateNode(this.editor, event.target);
3809
3343
  const path = AngularEditor.findPath(this.editor, node);
3810
3344
  const voidMatch = Element.isElement(node) && (Editor.isVoid(this.editor, node) || Editor.void(this.editor, { at: path, voids: true }));
@@ -3820,7 +3354,7 @@ class SlateEditable {
3820
3354
  }
3821
3355
  onDOMDrop(event) {
3822
3356
  const editor = this.editor;
3823
- if (!this.readonly && hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.drop)) {
3357
+ if (!this.readonly && AngularEditor.hasTarget(this.editor, event.target) && !this.isDOMEventHandled(event, this.drop)) {
3824
3358
  event.preventDefault();
3825
3359
  // Keep a reference to the dragged range before updating selection
3826
3360
  const draggedRange = editor.selection;
@@ -3847,7 +3381,7 @@ class SlateEditable {
3847
3381
  onDOMDragEnd(event) {
3848
3382
  if (!this.readonly &&
3849
3383
  this.isDraggingInternally &&
3850
- hasTarget(this.editor, event.target) &&
3384
+ AngularEditor.hasTarget(this.editor, event.target) &&
3851
3385
  !this.isDOMEventHandled(event, this.dragEnd)) {
3852
3386
  this.isDraggingInternally = false;
3853
3387
  }
@@ -3855,7 +3389,7 @@ class SlateEditable {
3855
3389
  onDOMFocus(event) {
3856
3390
  if (!this.readonly &&
3857
3391
  !this.isUpdatingSelection &&
3858
- hasEditableTarget(this.editor, event.target) &&
3392
+ AngularEditor.hasEditableTarget(this.editor, event.target) &&
3859
3393
  !this.isDOMEventHandled(event, this.focus)) {
3860
3394
  const el = AngularEditor.toDOMNode(this.editor, this.editor);
3861
3395
  const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
@@ -3875,7 +3409,7 @@ class SlateEditable {
3875
3409
  const root = AngularEditor.findDocumentOrShadowRoot(this.editor);
3876
3410
  const { activeElement } = root;
3877
3411
  if (!this.readonly &&
3878
- hasEditableTarget(editor, event.target) &&
3412
+ AngularEditor.hasEditableTarget(editor, event.target) &&
3879
3413
  !isTargetInsideVoid(editor, activeElement) && // stop fire keydown handle when focus void node
3880
3414
  !this.isComposing &&
3881
3415
  !this.isDOMEventHandled(event, this.keydown)) {
@@ -4097,7 +3631,7 @@ class SlateEditable {
4097
3631
  if (!this.isDOMEventHandled(event, this.paste) &&
4098
3632
  (!HAS_BEFORE_INPUT_SUPPORT || isPlainTextOnlyPaste(event) || forceOnDOMPaste) &&
4099
3633
  !this.readonly &&
4100
- hasEditableTarget(this.editor, event.target)) {
3634
+ AngularEditor.hasEditableTarget(this.editor, event.target)) {
4101
3635
  event.preventDefault();
4102
3636
  AngularEditor.insertData(this.editor, event.clipboardData);
4103
3637
  }
@@ -4109,7 +3643,7 @@ class SlateEditable {
4109
3643
  if (!HAS_BEFORE_INPUT_SUPPORT &&
4110
3644
  !this.readonly &&
4111
3645
  !this.isDOMEventHandled(event.nativeEvent, this.beforeInput) &&
4112
- hasEditableTarget(this.editor, event.nativeEvent.target)) {
3646
+ AngularEditor.hasEditableTarget(this.editor, event.nativeEvent.target)) {
4113
3647
  event.nativeEvent.preventDefault();
4114
3648
  try {
4115
3649
  const text = event.data;
@@ -4300,36 +3834,15 @@ const defaultScrollSelectionIntoView = (editor, domRange) => {
4300
3834
  delete leafEl.getBoundingClientRect;
4301
3835
  }
4302
3836
  };
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
3837
  /**
4329
3838
  * Check if the target is inside void and in the editor.
4330
3839
  */
4331
3840
  const isTargetInsideVoid = (editor, target) => {
4332
- const slateNode = hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target, { suppressThrow: true });
3841
+ let slateNode = null;
3842
+ try {
3843
+ slateNode = AngularEditor.hasTarget(editor, target) && AngularEditor.toSlateNode(editor, target);
3844
+ }
3845
+ catch (error) { }
4333
3846
  return slateNode && Element.isElement(slateNode) && Editor.isVoid(editor, slateNode);
4334
3847
  };
4335
3848
  const hasStringTarget = (domSelection) => {
@@ -4490,5 +4003,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImpor
4490
4003
  * Generated bundle index. Do not edit.
4491
4004
  */
4492
4005
 
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 };
4006
+ 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, SlateLeaves, SlateModule, SlateString, blobAsString, buildHTMLText, check, completeTable, createClipboardData, createThrottleRAF, defaultScrollSelectionIntoView, getCardTargetAttribute, getClipboardData, getClipboardFromHTMLText, getDataTransferClipboard, getDataTransferClipboardText, getNavigatorClipboard, hasAfterContextChange, hasBeforeContextChange, hasBlockCard, hasBlockCardWithNode, hotkeys, isCardCenterByTargetAttr, isCardLeft, isCardLeftByTargetAttr, isCardRightByTargetAttr, isClipboardFile, isClipboardReadSupported, isClipboardWriteSupported, isClipboardWriteTextSupported, isComponentType, isDecoratorRangeListEqual, isEmpty, isInvalidTable, isTemplateRef, isValid, normalize, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setNavigatorClipboard, shallowCompare, stripHtml, withAngular };
4494
4007
  //# sourceMappingURL=slate-angular.mjs.map