slate-react 0.130.0-20261008002243 → 0.130.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.
- package/dist/index.es.js +660 -702
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +138 -178
- package/dist/index.js.map +1 -1
- package/dist/slate-react.js +552 -615
- package/dist/slate-react.min.js +1 -1
- package/package.json +5 -5
package/dist/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import getDirection from 'direction';
|
|
2
2
|
import debounce from 'lodash/debounce';
|
|
3
3
|
import throttle from 'lodash/throttle';
|
|
4
|
-
import React, {
|
|
4
|
+
import React, { useContext, createContext, useRef, useEffect, useLayoutEffect, useState, memo, forwardRef, useCallback, useReducer, useMemo, Fragment, Component } from 'react';
|
|
5
5
|
import scrollIntoView from 'scroll-into-view-if-needed';
|
|
6
6
|
import { Node, Range, Editor, Path, Transforms, Location, Text as Text$1, Scrubber } from 'slate';
|
|
7
7
|
import { DOMEditor, isTrackedMutation, EDITOR_TO_FORCE_RENDER, IS_NODE_MAP_DIRTY, EDITOR_TO_PENDING_DIFFS, EDITOR_TO_PENDING_SELECTION, applyStringDiff, EDITOR_TO_PENDING_INSERTION_MARKS, isDOMSelection, IS_COMPOSING, EDITOR_TO_PENDING_ACTION, EDITOR_TO_USER_MARKS, targetRange, verifyDiffState, EDITOR_TO_PLACEHOLDER_ELEMENT, normalizeStringDiff, mergeStringDiffs, normalizeRange, normalizePoint, CAN_USE_DOM, IS_ANDROID, EDITOR_TO_SCHEDULE_FLUSH, MARK_PLACEHOLDER_SYMBOL, PLACEHOLDER_SYMBOL, IS_WEBKIT, isTextDecorationsEqual, isElementDecorationsEqual, EDITOR_TO_KEY_TO_ELEMENT, NODE_TO_ELEMENT, ELEMENT_TO_NODE, NODE_TO_INDEX, NODE_TO_PARENT, Key, splitDecorationsByChild, IS_READ_ONLY, getActiveElement, getSelection, IS_FOCUSED, getDefaultView, EDITOR_TO_WINDOW, EDITOR_TO_ELEMENT, IS_FIREFOX, containsShadowAware, EDITOR_TO_USER_SELECTION, HAS_BEFORE_INPUT_SUPPORT, isPlainTextOnlyPaste, Hotkeys, IS_CHROME, IS_FIREFOX_LEGACY, IS_IOS, IS_WECHATBROWSER, IS_UC_MOBILE, isDOMNode, TRIPLE_CLICK, isDOMElement, EDITOR_TO_ON_CHANGE, withDOM } from 'slate-dom';
|
|
@@ -9,33 +9,26 @@ export { NODE_TO_INDEX, NODE_TO_PARENT } from 'slate-dom';
|
|
|
9
9
|
import ReactDOM from 'react-dom';
|
|
10
10
|
import { ResizeObserver } from '@juggle/resize-observer';
|
|
11
11
|
|
|
12
|
-
function _objectWithoutPropertiesLoose(
|
|
13
|
-
if (
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
key = sourceKeys[i];
|
|
19
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
20
|
-
target[key] = source[key];
|
|
12
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
13
|
+
if (null == r) return {};
|
|
14
|
+
var t = {};
|
|
15
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
16
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
17
|
+
t[n] = r[n];
|
|
21
18
|
}
|
|
22
|
-
return
|
|
19
|
+
return t;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
function _objectWithoutProperties(
|
|
26
|
-
if (
|
|
27
|
-
var
|
|
28
|
-
|
|
22
|
+
function _objectWithoutProperties(e, t) {
|
|
23
|
+
if (null == e) return {};
|
|
24
|
+
var o,
|
|
25
|
+
r,
|
|
26
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
29
27
|
if (Object.getOwnPropertySymbols) {
|
|
30
|
-
var
|
|
31
|
-
for (
|
|
32
|
-
key = sourceSymbolKeys[i];
|
|
33
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
34
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
35
|
-
target[key] = source[key];
|
|
36
|
-
}
|
|
28
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
29
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
37
30
|
}
|
|
38
|
-
return
|
|
31
|
+
return i;
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
function _typeof(o) {
|
|
@@ -48,114 +41,107 @@ function _typeof(o) {
|
|
|
48
41
|
}, _typeof(o);
|
|
49
42
|
}
|
|
50
43
|
|
|
51
|
-
function
|
|
52
|
-
if (
|
|
53
|
-
var
|
|
54
|
-
if (
|
|
55
|
-
var
|
|
56
|
-
if (
|
|
44
|
+
function toPrimitive(t, r) {
|
|
45
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
46
|
+
var e = t[Symbol.toPrimitive];
|
|
47
|
+
if (void 0 !== e) {
|
|
48
|
+
var i = e.call(t, r);
|
|
49
|
+
if ("object" != _typeof(i)) return i;
|
|
57
50
|
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
58
51
|
}
|
|
59
|
-
return (
|
|
52
|
+
return ("string" === r ? String : Number)(t);
|
|
60
53
|
}
|
|
61
54
|
|
|
62
|
-
function
|
|
63
|
-
var
|
|
64
|
-
return _typeof(
|
|
55
|
+
function toPropertyKey(t) {
|
|
56
|
+
var i = toPrimitive(t, "string");
|
|
57
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
65
58
|
}
|
|
66
59
|
|
|
67
|
-
function _defineProperty(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
writable: true
|
|
75
|
-
});
|
|
76
|
-
} else {
|
|
77
|
-
obj[key] = value;
|
|
78
|
-
}
|
|
79
|
-
return obj;
|
|
60
|
+
function _defineProperty(e, r, t) {
|
|
61
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
62
|
+
value: t,
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true
|
|
66
|
+
}) : e[r] = t, e;
|
|
80
67
|
}
|
|
81
68
|
|
|
82
69
|
/**
|
|
83
70
|
* A React context for sharing the editor object.
|
|
84
71
|
*/
|
|
85
|
-
|
|
72
|
+
const EditorContext = /*#__PURE__*/createContext(null);
|
|
86
73
|
/**
|
|
87
74
|
* Get the current editor object from the React context.
|
|
88
75
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
76
|
+
const useSlateStatic = () => {
|
|
77
|
+
const editor = useContext(EditorContext);
|
|
91
78
|
if (!editor) {
|
|
92
|
-
throw new Error(
|
|
79
|
+
throw new Error(`The \`useSlateStatic\` hook must be used inside the <Slate> component's context.`);
|
|
93
80
|
}
|
|
94
81
|
return editor;
|
|
95
82
|
};
|
|
96
83
|
|
|
97
84
|
// eslint-disable-next-line no-redeclare
|
|
98
|
-
|
|
85
|
+
const ReactEditor = DOMEditor;
|
|
99
86
|
|
|
100
87
|
function ownKeys$8(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
101
88
|
function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$8(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
102
89
|
// https://github.com/facebook/draft-js/blob/main/src/component/handlers/composition/DraftEditorCompositionHandler.js#L41
|
|
103
90
|
// When using keyboard English association function, conpositionEnd triggered too fast, resulting in after `insertText` still maintain association state.
|
|
104
|
-
|
|
91
|
+
const RESOLVE_DELAY = 25;
|
|
105
92
|
// Time with no user interaction before the current user action is considered as done.
|
|
106
|
-
|
|
93
|
+
const FLUSH_DELAY = 200;
|
|
107
94
|
// Time with no composition input after which a composition that never ended is
|
|
108
95
|
// treated as stale. Long enough that pausing mid-word does not cut a live
|
|
109
96
|
// composition short.
|
|
110
|
-
|
|
97
|
+
const COMPOSITION_IDLE_TIMEOUT = 5000;
|
|
111
98
|
// How often a deferred flush re-checks whether the composition is still live.
|
|
112
99
|
// Only bounds how quickly the value catches up with a composition that ended
|
|
113
100
|
// without firing `compositionend`; one that ends normally flushes immediately.
|
|
114
|
-
|
|
101
|
+
const COMPOSITION_RECHECK_DELAY = 50;
|
|
115
102
|
// Replace with `const debug = console.log` to debug
|
|
116
|
-
|
|
103
|
+
const debug = (..._) => {};
|
|
117
104
|
// Type guard to check if a value is a DataTransfer
|
|
118
|
-
|
|
119
|
-
function createAndroidInputManager(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
var pendingSelection = EDITOR_TO_PENDING_SELECTION.get(editor);
|
|
105
|
+
const isDataTransfer = value => (value === null || value === void 0 ? void 0 : value.constructor.name) === 'DataTransfer';
|
|
106
|
+
function createAndroidInputManager({
|
|
107
|
+
editor,
|
|
108
|
+
scheduleOnDOMSelectionChange,
|
|
109
|
+
onDOMSelectionChange
|
|
110
|
+
}) {
|
|
111
|
+
let flushing = false;
|
|
112
|
+
let compositionEndTimeoutId = null;
|
|
113
|
+
let flushTimeoutId = null;
|
|
114
|
+
let actionTimeoutId = null;
|
|
115
|
+
let lastCompositionActivity = 0;
|
|
116
|
+
let compositionCleared = false;
|
|
117
|
+
let idCounter = 0;
|
|
118
|
+
let insertPositionHint = false;
|
|
119
|
+
const applyPendingSelection = () => {
|
|
120
|
+
const pendingSelection = EDITOR_TO_PENDING_SELECTION.get(editor);
|
|
135
121
|
EDITOR_TO_PENDING_SELECTION.delete(editor);
|
|
136
122
|
if (pendingSelection) {
|
|
137
|
-
|
|
123
|
+
const {
|
|
138
124
|
selection
|
|
139
125
|
} = editor;
|
|
140
|
-
|
|
126
|
+
const normalized = normalizeRange(editor, pendingSelection);
|
|
141
127
|
if (normalized && (!selection || !Range.equals(normalized, selection))) {
|
|
142
128
|
Transforms.select(editor, normalized);
|
|
143
129
|
}
|
|
144
130
|
}
|
|
145
131
|
};
|
|
146
|
-
|
|
147
|
-
|
|
132
|
+
const performAction = () => {
|
|
133
|
+
const action = EDITOR_TO_PENDING_ACTION.get(editor);
|
|
148
134
|
EDITOR_TO_PENDING_ACTION.delete(editor);
|
|
149
135
|
if (!action) {
|
|
150
136
|
return;
|
|
151
137
|
}
|
|
152
138
|
if (action.at) {
|
|
153
|
-
|
|
139
|
+
const target = Location.isPoint(action.at) ? normalizePoint(editor, action.at) : normalizeRange(editor, action.at);
|
|
154
140
|
if (!target) {
|
|
155
141
|
return;
|
|
156
142
|
}
|
|
157
|
-
|
|
158
|
-
if (!editor.selection || !Range.equals(editor.selection,
|
|
143
|
+
const targetRange = Editor.range(editor, target);
|
|
144
|
+
if (!editor.selection || !Range.equals(editor.selection, targetRange)) {
|
|
159
145
|
Transforms.select(editor, target);
|
|
160
146
|
}
|
|
161
147
|
}
|
|
@@ -165,13 +151,13 @@ function createAndroidInputManager(_ref) {
|
|
|
165
151
|
// already works around on keydown. Deferring flushes on a composition that
|
|
166
152
|
// never ends would strand the typed text outside the value, so a composition
|
|
167
153
|
// that has gone quiet, or that has lost focus, no longer holds flushes back.
|
|
168
|
-
|
|
154
|
+
const isCompositionLive = () => {
|
|
169
155
|
if (!IS_COMPOSING.get(editor) || compositionCleared) {
|
|
170
156
|
return false;
|
|
171
157
|
}
|
|
172
158
|
try {
|
|
173
|
-
|
|
174
|
-
|
|
159
|
+
const editable = ReactEditor.toDOMNode(editor, editor);
|
|
160
|
+
const {
|
|
175
161
|
activeElement
|
|
176
162
|
} = ReactEditor.getWindow(editor).document;
|
|
177
163
|
if (activeElement !== editable && !editable.contains(activeElement)) {
|
|
@@ -188,12 +174,11 @@ function createAndroidInputManager(_ref) {
|
|
|
188
174
|
// composition. Applying the pending diffs re-renders that leaf as a text
|
|
189
175
|
// leaf, which unmounts the zero-width span and takes the text node the IME is
|
|
190
176
|
// composing in with it, silently cancelling the composition.
|
|
191
|
-
|
|
177
|
+
const hasPendingDiffsInEmptyLeaf = () => {
|
|
192
178
|
var _EDITOR_TO_PENDING_DI;
|
|
193
|
-
return !!((_EDITOR_TO_PENDING_DI = EDITOR_TO_PENDING_DIFFS.get(editor)) !== null && _EDITOR_TO_PENDING_DI !== void 0 && _EDITOR_TO_PENDING_DI.some(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
} = _ref2;
|
|
179
|
+
return !!((_EDITOR_TO_PENDING_DI = EDITOR_TO_PENDING_DIFFS.get(editor)) !== null && _EDITOR_TO_PENDING_DI !== void 0 && _EDITOR_TO_PENDING_DI.some(({
|
|
180
|
+
path
|
|
181
|
+
}) => {
|
|
197
182
|
try {
|
|
198
183
|
return Node.leaf(editor, path).text.length === 0;
|
|
199
184
|
} catch (_unused2) {
|
|
@@ -202,7 +187,7 @@ function createAndroidInputManager(_ref) {
|
|
|
202
187
|
}
|
|
203
188
|
}));
|
|
204
189
|
};
|
|
205
|
-
|
|
190
|
+
const flush = () => {
|
|
206
191
|
if (flushTimeoutId) {
|
|
207
192
|
clearTimeout(flushTimeoutId);
|
|
208
193
|
flushTimeoutId = null;
|
|
@@ -231,16 +216,16 @@ function createAndroidInputManager(_ref) {
|
|
|
231
216
|
if (hasPendingAction()) {
|
|
232
217
|
flushing = 'action';
|
|
233
218
|
}
|
|
234
|
-
|
|
219
|
+
const selectionRef = editor.selection && Editor.rangeRef(editor, editor.selection, {
|
|
235
220
|
affinity: 'forward'
|
|
236
221
|
});
|
|
237
222
|
EDITOR_TO_USER_MARKS.set(editor, editor.marks);
|
|
238
223
|
debug('flush', EDITOR_TO_PENDING_ACTION.get(editor), EDITOR_TO_PENDING_DIFFS.get(editor));
|
|
239
|
-
|
|
240
|
-
|
|
224
|
+
let scheduleSelectionChange = hasPendingDiffs();
|
|
225
|
+
let diff;
|
|
241
226
|
while (diff = (_EDITOR_TO_PENDING_DI2 = EDITOR_TO_PENDING_DIFFS.get(editor)) === null || _EDITOR_TO_PENDING_DI2 === void 0 ? void 0 : _EDITOR_TO_PENDING_DI2[0]) {
|
|
242
227
|
var _EDITOR_TO_PENDING_DI2, _EDITOR_TO_PENDING_DI3;
|
|
243
|
-
|
|
228
|
+
const pendingMarks = EDITOR_TO_PENDING_INSERTION_MARKS.get(editor);
|
|
244
229
|
if (pendingMarks !== undefined) {
|
|
245
230
|
EDITOR_TO_PENDING_INSERTION_MARKS.delete(editor);
|
|
246
231
|
editor.marks = pendingMarks;
|
|
@@ -248,7 +233,7 @@ function createAndroidInputManager(_ref) {
|
|
|
248
233
|
if (pendingMarks && insertPositionHint === false) {
|
|
249
234
|
insertPositionHint = null;
|
|
250
235
|
}
|
|
251
|
-
|
|
236
|
+
const range = targetRange(diff);
|
|
252
237
|
if (!editor.selection || !Range.equals(editor.selection, range)) {
|
|
253
238
|
Transforms.select(editor, range);
|
|
254
239
|
}
|
|
@@ -259,12 +244,9 @@ function createAndroidInputManager(_ref) {
|
|
|
259
244
|
}
|
|
260
245
|
// Remove diff only after we have applied it to account for it when transforming
|
|
261
246
|
// pending ranges.
|
|
262
|
-
EDITOR_TO_PENDING_DIFFS.set(editor, (_EDITOR_TO_PENDING_DI3 = EDITOR_TO_PENDING_DIFFS.get(editor)) === null || _EDITOR_TO_PENDING_DI3 === void 0 ? void 0 : _EDITOR_TO_PENDING_DI3.filter(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
} = _ref3;
|
|
266
|
-
return id !== diff.id;
|
|
267
|
-
}));
|
|
247
|
+
EDITOR_TO_PENDING_DIFFS.set(editor, (_EDITOR_TO_PENDING_DI3 = EDITOR_TO_PENDING_DIFFS.get(editor)) === null || _EDITOR_TO_PENDING_DI3 === void 0 ? void 0 : _EDITOR_TO_PENDING_DI3.filter(({
|
|
248
|
+
id
|
|
249
|
+
}) => id !== diff.id));
|
|
268
250
|
if (!verifyDiffState(editor, diff)) {
|
|
269
251
|
scheduleSelectionChange = false;
|
|
270
252
|
EDITOR_TO_PENDING_ACTION.delete(editor);
|
|
@@ -278,7 +260,7 @@ function createAndroidInputManager(_ref) {
|
|
|
278
260
|
selectionRef === null || selectionRef === void 0 || selectionRef.unref();
|
|
279
261
|
}
|
|
280
262
|
}
|
|
281
|
-
|
|
263
|
+
const selection = selectionRef === null || selectionRef === void 0 ? void 0 : selectionRef.unref();
|
|
282
264
|
if (selection && !EDITOR_TO_PENDING_SELECTION.get(editor) && (!editor.selection || !Range.equals(selection, editor.selection))) {
|
|
283
265
|
Transforms.select(editor, selection);
|
|
284
266
|
}
|
|
@@ -295,14 +277,14 @@ function createAndroidInputManager(_ref) {
|
|
|
295
277
|
scheduleOnDOMSelectionChange.flush();
|
|
296
278
|
onDOMSelectionChange.flush();
|
|
297
279
|
applyPendingSelection();
|
|
298
|
-
|
|
280
|
+
const userMarks = EDITOR_TO_USER_MARKS.get(editor);
|
|
299
281
|
EDITOR_TO_USER_MARKS.delete(editor);
|
|
300
282
|
if (userMarks !== undefined) {
|
|
301
283
|
editor.marks = userMarks;
|
|
302
284
|
editor.onChange();
|
|
303
285
|
}
|
|
304
286
|
};
|
|
305
|
-
|
|
287
|
+
const handleCompositionEnd = _event => {
|
|
306
288
|
if (compositionEndTimeoutId) {
|
|
307
289
|
clearTimeout(compositionEndTimeoutId);
|
|
308
290
|
}
|
|
@@ -331,7 +313,7 @@ function createAndroidInputManager(_ref) {
|
|
|
331
313
|
updatePlaceholderVisibility();
|
|
332
314
|
}, RESOLVE_DELAY);
|
|
333
315
|
};
|
|
334
|
-
|
|
316
|
+
const handleCompositionStart = _event => {
|
|
335
317
|
IS_COMPOSING.set(editor, true);
|
|
336
318
|
lastCompositionActivity = Date.now();
|
|
337
319
|
compositionCleared = false;
|
|
@@ -340,9 +322,8 @@ function createAndroidInputManager(_ref) {
|
|
|
340
322
|
compositionEndTimeoutId = null;
|
|
341
323
|
}
|
|
342
324
|
};
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
var placeholderElement = EDITOR_TO_PLACEHOLDER_ELEMENT.get(editor);
|
|
325
|
+
const updatePlaceholderVisibility = (forceHide = false) => {
|
|
326
|
+
const placeholderElement = EDITOR_TO_PLACEHOLDER_ELEMENT.get(editor);
|
|
346
327
|
if (!placeholderElement) {
|
|
347
328
|
return;
|
|
348
329
|
}
|
|
@@ -352,14 +333,14 @@ function createAndroidInputManager(_ref) {
|
|
|
352
333
|
}
|
|
353
334
|
placeholderElement.style.removeProperty('display');
|
|
354
335
|
};
|
|
355
|
-
|
|
336
|
+
const storeDiff = (path, diff) => {
|
|
356
337
|
var _EDITOR_TO_PENDING_DI4;
|
|
357
|
-
|
|
338
|
+
const pendingDiffs = (_EDITOR_TO_PENDING_DI4 = EDITOR_TO_PENDING_DIFFS.get(editor)) !== null && _EDITOR_TO_PENDING_DI4 !== void 0 ? _EDITOR_TO_PENDING_DI4 : [];
|
|
358
339
|
EDITOR_TO_PENDING_DIFFS.set(editor, pendingDiffs);
|
|
359
|
-
|
|
360
|
-
|
|
340
|
+
const target = Node.leaf(editor, path);
|
|
341
|
+
const idx = pendingDiffs.findIndex(change => Path.equals(change.path, path));
|
|
361
342
|
if (idx < 0) {
|
|
362
|
-
|
|
343
|
+
const normalized = normalizeStringDiff(target.text, diff);
|
|
363
344
|
if (normalized) {
|
|
364
345
|
pendingDiffs.push({
|
|
365
346
|
path,
|
|
@@ -370,7 +351,7 @@ function createAndroidInputManager(_ref) {
|
|
|
370
351
|
updatePlaceholderVisibility();
|
|
371
352
|
return;
|
|
372
353
|
}
|
|
373
|
-
|
|
354
|
+
const merged = mergeStringDiffs(target.text, pendingDiffs[idx].diff, diff);
|
|
374
355
|
if (!merged) {
|
|
375
356
|
pendingDiffs.splice(idx, 1);
|
|
376
357
|
updatePlaceholderVisibility();
|
|
@@ -380,10 +361,9 @@ function createAndroidInputManager(_ref) {
|
|
|
380
361
|
diff: merged
|
|
381
362
|
});
|
|
382
363
|
};
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
364
|
+
const scheduleAction = (run, {
|
|
365
|
+
at
|
|
366
|
+
} = {}) => {
|
|
387
367
|
insertPositionHint = false;
|
|
388
368
|
EDITOR_TO_PENDING_SELECTION.delete(editor);
|
|
389
369
|
scheduleOnDOMSelectionChange.cancel();
|
|
@@ -400,14 +380,13 @@ function createAndroidInputManager(_ref) {
|
|
|
400
380
|
// in this case and thus never actually perform the action.
|
|
401
381
|
actionTimeoutId = setTimeout(flush);
|
|
402
382
|
};
|
|
403
|
-
|
|
404
|
-
var _targetRange2;
|
|
383
|
+
const handleDOMBeforeInput = event => {
|
|
405
384
|
if (flushTimeoutId) {
|
|
406
385
|
clearTimeout(flushTimeoutId);
|
|
407
386
|
flushTimeoutId = null;
|
|
408
387
|
}
|
|
409
|
-
|
|
410
|
-
|
|
388
|
+
const isNodeMapDirty = IS_NODE_MAP_DIRTY.get(editor);
|
|
389
|
+
const {
|
|
411
390
|
inputType: type
|
|
412
391
|
} = event;
|
|
413
392
|
if (type === 'insertCompositionText' || type === 'deleteCompositionText') {
|
|
@@ -421,12 +400,11 @@ function createAndroidInputManager(_ref) {
|
|
|
421
400
|
// would churn the DOM mid-composition and can make Android close the
|
|
422
401
|
// keyboard.
|
|
423
402
|
compositionCleared = true;
|
|
424
|
-
|
|
403
|
+
const deferredDiffs = EDITOR_TO_PENDING_DIFFS.get(editor);
|
|
425
404
|
if (deferredDiffs !== null && deferredDiffs !== void 0 && deferredDiffs.length) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
} = _ref4;
|
|
405
|
+
const allInEmptyLeaves = deferredDiffs.every(({
|
|
406
|
+
path
|
|
407
|
+
}) => {
|
|
430
408
|
try {
|
|
431
409
|
return Node.leaf(editor, path).text.length === 0;
|
|
432
410
|
} catch (_unused3) {
|
|
@@ -440,12 +418,12 @@ function createAndroidInputManager(_ref) {
|
|
|
440
418
|
}
|
|
441
419
|
}
|
|
442
420
|
}
|
|
443
|
-
|
|
444
|
-
|
|
421
|
+
let targetRange = null;
|
|
422
|
+
const data = event.dataTransfer || event.data || undefined;
|
|
445
423
|
if (insertPositionHint !== false && type !== 'insertText' && type !== 'insertCompositionText') {
|
|
446
424
|
insertPositionHint = false;
|
|
447
425
|
}
|
|
448
|
-
|
|
426
|
+
let [nativeTargetRange] = event.getTargetRanges();
|
|
449
427
|
if (nativeTargetRange && !isNodeMapDirty) {
|
|
450
428
|
targetRange = ReactEditor.toSlateRange(editor, nativeTargetRange, {
|
|
451
429
|
exactMatch: false,
|
|
@@ -454,8 +432,8 @@ function createAndroidInputManager(_ref) {
|
|
|
454
432
|
}
|
|
455
433
|
// COMPAT: SelectionChange event is fired after the action is performed, so we
|
|
456
434
|
// have to manually get the selection here to ensure it's up-to-date.
|
|
457
|
-
|
|
458
|
-
|
|
435
|
+
const window = ReactEditor.getWindow(editor);
|
|
436
|
+
const domSelection = window.getSelection();
|
|
459
437
|
if (!targetRange && domSelection && !isNodeMapDirty) {
|
|
460
438
|
nativeTargetRange = domSelection;
|
|
461
439
|
targetRange = ReactEditor.toSlateRange(editor, domSelection, {
|
|
@@ -463,7 +441,7 @@ function createAndroidInputManager(_ref) {
|
|
|
463
441
|
suppressThrow: true
|
|
464
442
|
});
|
|
465
443
|
}
|
|
466
|
-
targetRange =
|
|
444
|
+
targetRange = targetRange !== null && targetRange !== void 0 ? targetRange : editor.selection;
|
|
467
445
|
if (!targetRange) {
|
|
468
446
|
return;
|
|
469
447
|
}
|
|
@@ -472,14 +450,14 @@ function createAndroidInputManager(_ref) {
|
|
|
472
450
|
// for every input event as this can be expensive. However, there are some
|
|
473
451
|
// scenarios where we cannot safely store the text diff and must instead
|
|
474
452
|
// schedule an action to let Slate normalize the editor state.
|
|
475
|
-
|
|
453
|
+
let canStoreDiff = true;
|
|
476
454
|
if (type.startsWith('delete')) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
455
|
+
const direction = type.endsWith('Backward') ? 'backward' : 'forward';
|
|
456
|
+
let [start, end] = Range.edges(targetRange);
|
|
457
|
+
let [leaf, path] = Editor.leaf(editor, start.path);
|
|
480
458
|
if (Range.isExpanded(targetRange)) {
|
|
481
459
|
if (leaf.text.length === start.offset && end.offset === 0) {
|
|
482
|
-
|
|
460
|
+
const next = Editor.next(editor, {
|
|
483
461
|
at: start.path,
|
|
484
462
|
match: Node.isText
|
|
485
463
|
});
|
|
@@ -504,15 +482,15 @@ function createAndroidInputManager(_ref) {
|
|
|
504
482
|
}
|
|
505
483
|
}
|
|
506
484
|
}
|
|
507
|
-
|
|
485
|
+
const diff = {
|
|
508
486
|
text: '',
|
|
509
487
|
start: start.offset,
|
|
510
488
|
end: end.offset
|
|
511
489
|
};
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
490
|
+
const pendingDiffs = EDITOR_TO_PENDING_DIFFS.get(editor);
|
|
491
|
+
const relevantPendingDiffs = pendingDiffs === null || pendingDiffs === void 0 ? void 0 : pendingDiffs.find(change => Path.equals(change.path, path));
|
|
492
|
+
const diffs = relevantPendingDiffs ? [relevantPendingDiffs.diff, diff] : [diff];
|
|
493
|
+
const text = applyStringDiff(leaf.text, ...diffs);
|
|
516
494
|
if (text.length === 0) {
|
|
517
495
|
// Text leaf will be removed, so we need to schedule an
|
|
518
496
|
// action to remove it so that Slate can normalize instead
|
|
@@ -521,11 +499,11 @@ function createAndroidInputManager(_ref) {
|
|
|
521
499
|
}
|
|
522
500
|
if (Range.isExpanded(targetRange)) {
|
|
523
501
|
if (canStoreDiff && Path.equals(targetRange.anchor.path, targetRange.focus.path)) {
|
|
524
|
-
|
|
502
|
+
const point = {
|
|
525
503
|
path: targetRange.anchor.path,
|
|
526
504
|
offset: start.offset
|
|
527
505
|
};
|
|
528
|
-
|
|
506
|
+
const range = Editor.range(editor, point, point);
|
|
529
507
|
handleUserSelect(range);
|
|
530
508
|
return storeDiff(targetRange.anchor.path, {
|
|
531
509
|
text: '',
|
|
@@ -552,11 +530,11 @@ function createAndroidInputManager(_ref) {
|
|
|
552
530
|
case 'deleteContent':
|
|
553
531
|
case 'deleteContentForward':
|
|
554
532
|
{
|
|
555
|
-
|
|
533
|
+
const {
|
|
556
534
|
anchor
|
|
557
535
|
} = targetRange;
|
|
558
536
|
if (canStoreDiff && Range.isCollapsed(targetRange)) {
|
|
559
|
-
|
|
537
|
+
const targetNode = Node.leaf(editor, anchor.path);
|
|
560
538
|
if (anchor.offset < targetNode.text.length) {
|
|
561
539
|
return storeDiff(anchor.path, {
|
|
562
540
|
text: '',
|
|
@@ -572,18 +550,18 @@ function createAndroidInputManager(_ref) {
|
|
|
572
550
|
case 'deleteContentBackward':
|
|
573
551
|
{
|
|
574
552
|
var _nativeTargetRange;
|
|
575
|
-
|
|
576
|
-
anchor
|
|
553
|
+
const {
|
|
554
|
+
anchor
|
|
577
555
|
} = targetRange;
|
|
578
556
|
// If we have a mismatch between the native and slate selection being collapsed
|
|
579
557
|
// we are most likely deleting a zero-width placeholder and thus should perform it
|
|
580
558
|
// as an action to ensure correct behavior (mostly happens with mark placeholders)
|
|
581
|
-
|
|
582
|
-
if (canStoreDiff && nativeCollapsed && Range.isCollapsed(targetRange) &&
|
|
583
|
-
return storeDiff(
|
|
559
|
+
const nativeCollapsed = isDOMSelection(nativeTargetRange) ? nativeTargetRange.isCollapsed : !!((_nativeTargetRange = nativeTargetRange) !== null && _nativeTargetRange !== void 0 && _nativeTargetRange.collapsed);
|
|
560
|
+
if (canStoreDiff && nativeCollapsed && Range.isCollapsed(targetRange) && anchor.offset > 0) {
|
|
561
|
+
return storeDiff(anchor.path, {
|
|
584
562
|
text: '',
|
|
585
|
-
start:
|
|
586
|
-
end:
|
|
563
|
+
start: anchor.offset - 1,
|
|
564
|
+
end: anchor.offset
|
|
587
565
|
});
|
|
588
566
|
}
|
|
589
567
|
return scheduleAction(() => Editor.deleteBackward(editor), {
|
|
@@ -677,23 +655,23 @@ function createAndroidInputManager(_ref) {
|
|
|
677
655
|
at: targetRange
|
|
678
656
|
});
|
|
679
657
|
}
|
|
680
|
-
|
|
658
|
+
let text = data !== null && data !== void 0 ? data : '';
|
|
681
659
|
// COMPAT: If we are writing inside a placeholder, the ime inserts the text inside
|
|
682
660
|
// the placeholder itself and thus includes the zero-width space inside edit events.
|
|
683
661
|
if (EDITOR_TO_PENDING_INSERTION_MARKS.get(editor)) {
|
|
684
|
-
|
|
662
|
+
text = text.replace('\uFEFF', '');
|
|
685
663
|
}
|
|
686
664
|
// Pastes from the Android clipboard will generate `insertText` events.
|
|
687
665
|
// If the copied text contains any newlines, Android will append an
|
|
688
666
|
// extra newline to the end of the copied text.
|
|
689
|
-
if (type === 'insertText' && /.*\n.*\n$/.test(
|
|
690
|
-
|
|
667
|
+
if (type === 'insertText' && /.*\n.*\n$/.test(text)) {
|
|
668
|
+
text = text.slice(0, -1);
|
|
691
669
|
}
|
|
692
670
|
// If the text includes a newline, split it at newlines and paste each component
|
|
693
671
|
// string, with soft breaks in between each.
|
|
694
|
-
if (
|
|
672
|
+
if (text.includes('\n')) {
|
|
695
673
|
return scheduleAction(() => {
|
|
696
|
-
|
|
674
|
+
const parts = text.split('\n');
|
|
697
675
|
parts.forEach((line, i) => {
|
|
698
676
|
if (line) {
|
|
699
677
|
Editor.insertText(editor, line);
|
|
@@ -707,11 +685,11 @@ function createAndroidInputManager(_ref) {
|
|
|
707
685
|
});
|
|
708
686
|
}
|
|
709
687
|
if (Path.equals(targetRange.anchor.path, targetRange.focus.path)) {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
start:
|
|
713
|
-
end:
|
|
714
|
-
text
|
|
688
|
+
const [start, end] = Range.edges(targetRange);
|
|
689
|
+
const diff = {
|
|
690
|
+
start: start.offset,
|
|
691
|
+
end: end.offset,
|
|
692
|
+
text
|
|
715
693
|
};
|
|
716
694
|
// COMPAT: Swiftkey has a weird bug where the target range of the 2nd word
|
|
717
695
|
// inserted after a mark placeholder is inserted with an anchor offset off by 1.
|
|
@@ -719,11 +697,11 @@ function createAndroidInputManager(_ref) {
|
|
|
719
697
|
// text events are fired with the correct target ranges, only the final 'insertComposition'
|
|
720
698
|
// isn't, so we can adjust the target range start offset if we are confident this is the
|
|
721
699
|
// swiftkey insert causing the issue.
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (diffPosition === hintPosition + 1 &&
|
|
726
|
-
|
|
700
|
+
if (text && insertPositionHint && type === 'insertCompositionText') {
|
|
701
|
+
const hintPosition = insertPositionHint.start + insertPositionHint.text.search(/\S|$/);
|
|
702
|
+
const diffPosition = diff.start + diff.text.search(/\S|$/);
|
|
703
|
+
if (diffPosition === hintPosition + 1 && diff.end === insertPositionHint.start + insertPositionHint.text.length) {
|
|
704
|
+
diff.start -= 1;
|
|
727
705
|
insertPositionHint = null;
|
|
728
706
|
scheduleFlush();
|
|
729
707
|
} else {
|
|
@@ -731,10 +709,10 @@ function createAndroidInputManager(_ref) {
|
|
|
731
709
|
}
|
|
732
710
|
} else if (type === 'insertText') {
|
|
733
711
|
if (insertPositionHint === null) {
|
|
734
|
-
insertPositionHint =
|
|
735
|
-
} else if (insertPositionHint && Range.isCollapsed(targetRange) && insertPositionHint.end + insertPositionHint.text.length ===
|
|
712
|
+
insertPositionHint = diff;
|
|
713
|
+
} else if (insertPositionHint && Range.isCollapsed(targetRange) && insertPositionHint.end + insertPositionHint.text.length === start.offset) {
|
|
736
714
|
insertPositionHint = _objectSpread$8(_objectSpread$8({}, insertPositionHint), {}, {
|
|
737
|
-
text: insertPositionHint.text +
|
|
715
|
+
text: insertPositionHint.text + text
|
|
738
716
|
});
|
|
739
717
|
} else {
|
|
740
718
|
insertPositionHint = false;
|
|
@@ -743,12 +721,12 @@ function createAndroidInputManager(_ref) {
|
|
|
743
721
|
insertPositionHint = false;
|
|
744
722
|
}
|
|
745
723
|
if (canStoreDiff) {
|
|
746
|
-
|
|
747
|
-
storeDiff(
|
|
724
|
+
const currentSelection = editor.selection;
|
|
725
|
+
storeDiff(start.path, diff);
|
|
748
726
|
if (currentSelection) {
|
|
749
|
-
|
|
750
|
-
path:
|
|
751
|
-
offset:
|
|
727
|
+
const newPoint = {
|
|
728
|
+
path: start.path,
|
|
729
|
+
offset: start.offset + text.length
|
|
752
730
|
};
|
|
753
731
|
scheduleAction(() => {
|
|
754
732
|
Transforms.select(editor, {
|
|
@@ -762,39 +740,39 @@ function createAndroidInputManager(_ref) {
|
|
|
762
740
|
return;
|
|
763
741
|
}
|
|
764
742
|
}
|
|
765
|
-
return scheduleAction(() => Editor.insertText(editor,
|
|
743
|
+
return scheduleAction(() => Editor.insertText(editor, text), {
|
|
766
744
|
at: targetRange
|
|
767
745
|
});
|
|
768
746
|
}
|
|
769
747
|
}
|
|
770
748
|
};
|
|
771
|
-
|
|
749
|
+
const hasPendingAction = () => {
|
|
772
750
|
return !!EDITOR_TO_PENDING_ACTION.get(editor);
|
|
773
751
|
};
|
|
774
|
-
|
|
752
|
+
const hasPendingDiffs = () => {
|
|
775
753
|
var _EDITOR_TO_PENDING_DI5;
|
|
776
754
|
return !!((_EDITOR_TO_PENDING_DI5 = EDITOR_TO_PENDING_DIFFS.get(editor)) !== null && _EDITOR_TO_PENDING_DI5 !== void 0 && _EDITOR_TO_PENDING_DI5.length);
|
|
777
755
|
};
|
|
778
|
-
|
|
756
|
+
const hasPendingChanges = () => {
|
|
779
757
|
return hasPendingAction() || hasPendingDiffs();
|
|
780
758
|
};
|
|
781
|
-
|
|
759
|
+
const isFlushing = () => {
|
|
782
760
|
return flushing;
|
|
783
761
|
};
|
|
784
|
-
|
|
762
|
+
const handleUserSelect = range => {
|
|
785
763
|
EDITOR_TO_PENDING_SELECTION.set(editor, range);
|
|
786
764
|
if (flushTimeoutId) {
|
|
787
765
|
clearTimeout(flushTimeoutId);
|
|
788
766
|
flushTimeoutId = null;
|
|
789
767
|
}
|
|
790
|
-
|
|
768
|
+
const {
|
|
791
769
|
selection
|
|
792
770
|
} = editor;
|
|
793
771
|
if (!range) {
|
|
794
772
|
return;
|
|
795
773
|
}
|
|
796
|
-
|
|
797
|
-
|
|
774
|
+
const pathChanged = !selection || !Path.equals(selection.anchor.path, range.anchor.path);
|
|
775
|
+
const parentPathChanged = !selection || !Path.equals(selection.anchor.path.slice(0, -1), range.anchor.path.slice(0, -1));
|
|
798
776
|
if (pathChanged && insertPositionHint || parentPathChanged) {
|
|
799
777
|
insertPositionHint = false;
|
|
800
778
|
}
|
|
@@ -802,12 +780,12 @@ function createAndroidInputManager(_ref) {
|
|
|
802
780
|
flushTimeoutId = setTimeout(flush, FLUSH_DELAY);
|
|
803
781
|
}
|
|
804
782
|
};
|
|
805
|
-
|
|
783
|
+
const handleInput = () => {
|
|
806
784
|
if (hasPendingAction() || !hasPendingDiffs()) {
|
|
807
785
|
flush();
|
|
808
786
|
}
|
|
809
787
|
};
|
|
810
|
-
|
|
788
|
+
const handleKeyDown = _ => {
|
|
811
789
|
// COMPAT: Swiftkey closes the keyboard when typing inside a empty node
|
|
812
790
|
// directly next to a non-contenteditable element (= the placeholder).
|
|
813
791
|
// The only event fired soon enough for us to allow hiding the placeholder
|
|
@@ -818,12 +796,12 @@ function createAndroidInputManager(_ref) {
|
|
|
818
796
|
setTimeout(updatePlaceholderVisibility);
|
|
819
797
|
}
|
|
820
798
|
};
|
|
821
|
-
|
|
799
|
+
const scheduleFlush = () => {
|
|
822
800
|
if (!hasPendingAction()) {
|
|
823
801
|
actionTimeoutId = setTimeout(flush);
|
|
824
802
|
}
|
|
825
803
|
};
|
|
826
|
-
|
|
804
|
+
const handleDomMutations = mutations => {
|
|
827
805
|
if (hasPendingDiffs() || hasPendingAction()) {
|
|
828
806
|
return;
|
|
829
807
|
}
|
|
@@ -852,7 +830,7 @@ function createAndroidInputManager(_ref) {
|
|
|
852
830
|
}
|
|
853
831
|
|
|
854
832
|
function useIsMounted() {
|
|
855
|
-
|
|
833
|
+
const isMountedRef = useRef(false);
|
|
856
834
|
useEffect(() => {
|
|
857
835
|
isMountedRef.current = true;
|
|
858
836
|
return () => {
|
|
@@ -865,10 +843,10 @@ function useIsMounted() {
|
|
|
865
843
|
/**
|
|
866
844
|
* Prevent warning on SSR by falling back to useEffect when DOM isn't available
|
|
867
845
|
*/
|
|
868
|
-
|
|
846
|
+
const useIsomorphicLayoutEffect = CAN_USE_DOM ? useLayoutEffect : useEffect;
|
|
869
847
|
|
|
870
848
|
function useMutationObserver(node, callback, options) {
|
|
871
|
-
|
|
849
|
+
const [mutationObserver] = useState(() => new MutationObserver(callback));
|
|
872
850
|
useIsomorphicLayoutEffect(() => {
|
|
873
851
|
// Discard mutations caused during render phase. This works due to react calling
|
|
874
852
|
// useLayoutEffect synchronously after the render phase before the next tick.
|
|
@@ -883,25 +861,25 @@ function useMutationObserver(node, callback, options) {
|
|
|
883
861
|
}, [mutationObserver, node, options]);
|
|
884
862
|
}
|
|
885
863
|
|
|
886
|
-
|
|
864
|
+
const _excluded$2 = ["node"];
|
|
887
865
|
function ownKeys$7(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
888
866
|
function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$7(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
889
|
-
|
|
867
|
+
const MUTATION_OBSERVER_CONFIG$1 = {
|
|
890
868
|
subtree: true,
|
|
891
869
|
childList: true,
|
|
892
870
|
characterData: true
|
|
893
871
|
};
|
|
894
|
-
|
|
895
|
-
|
|
872
|
+
const useAndroidInputManager = !IS_ANDROID ? () => null : _ref => {
|
|
873
|
+
let {
|
|
896
874
|
node
|
|
897
875
|
} = _ref,
|
|
898
876
|
options = _objectWithoutProperties(_ref, _excluded$2);
|
|
899
877
|
if (!IS_ANDROID) {
|
|
900
878
|
return null;
|
|
901
879
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
880
|
+
const editor = useSlateStatic();
|
|
881
|
+
const isMounted = useIsMounted();
|
|
882
|
+
const [inputManager] = useState(() => createAndroidInputManager(_objectSpread$7({
|
|
905
883
|
editor
|
|
906
884
|
}, options)));
|
|
907
885
|
useMutationObserver(node, inputManager.handleDomMutations, MUTATION_OBSERVER_CONFIG$1);
|
|
@@ -917,17 +895,17 @@ function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t
|
|
|
917
895
|
/**
|
|
918
896
|
* Leaf content strings.
|
|
919
897
|
*/
|
|
920
|
-
|
|
921
|
-
|
|
898
|
+
const String$1 = props => {
|
|
899
|
+
const {
|
|
922
900
|
isLast,
|
|
923
901
|
leaf,
|
|
924
902
|
parent,
|
|
925
903
|
text
|
|
926
904
|
} = props;
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
905
|
+
const editor = useSlateStatic();
|
|
906
|
+
const path = ReactEditor.findPath(editor, text);
|
|
907
|
+
const parentPath = Path.parent(path);
|
|
908
|
+
const isMarkPlaceholder = Boolean(leaf[MARK_PLACEHOLDER_SYMBOL]);
|
|
931
909
|
// COMPAT: Render text inside void nodes with a zero-width space.
|
|
932
910
|
// So the node can contain selection but the text is not visible.
|
|
933
911
|
if (editor.isVoid(parent)) {
|
|
@@ -967,17 +945,17 @@ var String$1 = props => {
|
|
|
967
945
|
/**
|
|
968
946
|
* Leaf strings with text in them.
|
|
969
947
|
*/
|
|
970
|
-
|
|
971
|
-
|
|
948
|
+
const TextString = props => {
|
|
949
|
+
const {
|
|
972
950
|
text,
|
|
973
951
|
isTrailing = false
|
|
974
952
|
} = props;
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
return
|
|
953
|
+
const editor = useSlateStatic();
|
|
954
|
+
const ref = useRef(null);
|
|
955
|
+
const getTextContent = () => {
|
|
956
|
+
return `${text !== null && text !== void 0 ? text : ''}${isTrailing ? '\n' : ''}`;
|
|
979
957
|
};
|
|
980
|
-
|
|
958
|
+
const [initialText] = useState(getTextContent);
|
|
981
959
|
// This is the actual text rendering boundary where we interface with the DOM
|
|
982
960
|
// The text is not rendered as part of the virtual DOM, as since we handle basic character insertions natively,
|
|
983
961
|
// updating the DOM is not a one way dataflow anymore. What we need here is not reconciliation and diffing
|
|
@@ -988,7 +966,7 @@ var TextString = props => {
|
|
|
988
966
|
// useLayoutEffect: updating our span before browser paint
|
|
989
967
|
useIsomorphicLayoutEffect(() => {
|
|
990
968
|
// null coalescing text to make sure we're not outputing "null" as a string in the extreme case it is nullish at runtime
|
|
991
|
-
|
|
969
|
+
const textWithTrailing = getTextContent();
|
|
992
970
|
if (ref.current && ref.current.textContent !== textWithTrailing) {
|
|
993
971
|
// On Android the DOM intentionally runs ahead of the value while the IME
|
|
994
972
|
// composes, since input is buffered as pending diffs. Writing
|
|
@@ -997,7 +975,7 @@ var TextString = props => {
|
|
|
997
975
|
// composition ends.
|
|
998
976
|
if (IS_ANDROID && IS_COMPOSING.get(editor)) {
|
|
999
977
|
var _ReactEditor$getWindo;
|
|
1000
|
-
|
|
978
|
+
const composingNode = (_ReactEditor$getWindo = ReactEditor.getWindow(editor).getSelection()) === null || _ReactEditor$getWindo === void 0 ? void 0 : _ReactEditor$getWindo.anchorNode;
|
|
1001
979
|
if (composingNode && ref.current.contains(composingNode)) {
|
|
1002
980
|
return;
|
|
1003
981
|
}
|
|
@@ -1013,7 +991,7 @@ var TextString = props => {
|
|
|
1013
991
|
ref: ref
|
|
1014
992
|
}, initialText);
|
|
1015
993
|
};
|
|
1016
|
-
|
|
994
|
+
const MemoizedText$1 = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((props, ref) => {
|
|
1017
995
|
return /*#__PURE__*/React.createElement("span", {
|
|
1018
996
|
"data-slate-string": true,
|
|
1019
997
|
ref: ref
|
|
@@ -1022,13 +1000,13 @@ var MemoizedText$1 = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((props, ref) => {
|
|
|
1022
1000
|
/**
|
|
1023
1001
|
* Leaf strings without text, render as zero-width strings.
|
|
1024
1002
|
*/
|
|
1025
|
-
|
|
1026
|
-
|
|
1003
|
+
const ZeroWidthString = props => {
|
|
1004
|
+
const {
|
|
1027
1005
|
length = 0,
|
|
1028
1006
|
isLineBreak = false,
|
|
1029
1007
|
isMarkPlaceholder = false
|
|
1030
1008
|
} = props;
|
|
1031
|
-
|
|
1009
|
+
const attributes = {
|
|
1032
1010
|
'data-slate-zero-width': isLineBreak ? 'n' : 'z',
|
|
1033
1011
|
'data-slate-length': length
|
|
1034
1012
|
};
|
|
@@ -1056,7 +1034,7 @@ function ownKeys$5(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymb
|
|
|
1056
1034
|
function _objectSpread$5(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$5(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$5(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1057
1035
|
// Delay the placeholder on Android to prevent the keyboard from closing.
|
|
1058
1036
|
// (https://github.com/ianstormtaylor/slate/pull/5368)
|
|
1059
|
-
|
|
1037
|
+
const PLACEHOLDER_DELAY = IS_ANDROID ? 300 : 0;
|
|
1060
1038
|
function disconnectPlaceholderResizeObserver(placeholderResizeObserver, releaseObserver) {
|
|
1061
1039
|
if (placeholderResizeObserver.current) {
|
|
1062
1040
|
placeholderResizeObserver.current.disconnect();
|
|
@@ -1071,12 +1049,12 @@ function clearTimeoutRef(timeoutRef) {
|
|
|
1071
1049
|
timeoutRef.current = null;
|
|
1072
1050
|
}
|
|
1073
1051
|
}
|
|
1074
|
-
|
|
1052
|
+
const defaultRenderLeaf = props => /*#__PURE__*/React.createElement(DefaultLeaf, _objectSpread$5({}, props));
|
|
1075
1053
|
/**
|
|
1076
1054
|
* Individual leaves in a text node with unique formatting.
|
|
1077
1055
|
*/
|
|
1078
|
-
|
|
1079
|
-
|
|
1056
|
+
const Leaf = props => {
|
|
1057
|
+
const {
|
|
1080
1058
|
leaf,
|
|
1081
1059
|
isLast,
|
|
1082
1060
|
text,
|
|
@@ -1085,12 +1063,12 @@ var Leaf = props => {
|
|
|
1085
1063
|
renderLeaf = defaultRenderLeaf,
|
|
1086
1064
|
leafPosition
|
|
1087
1065
|
} = props;
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1066
|
+
const editor = useSlateStatic();
|
|
1067
|
+
const placeholderResizeObserver = useRef(null);
|
|
1068
|
+
const placeholderRef = useRef(null);
|
|
1069
|
+
const [showPlaceholder, setShowPlaceholder] = useState(false);
|
|
1070
|
+
const showPlaceholderTimeoutRef = useRef(null);
|
|
1071
|
+
const callbackPlaceholderRef = useCallback(placeholderEl => {
|
|
1094
1072
|
disconnectPlaceholderResizeObserver(placeholderResizeObserver, placeholderEl == null);
|
|
1095
1073
|
if (placeholderEl == null) {
|
|
1096
1074
|
var _leaf$onPlaceholderRe;
|
|
@@ -1100,7 +1078,7 @@ var Leaf = props => {
|
|
|
1100
1078
|
EDITOR_TO_PLACEHOLDER_ELEMENT.set(editor, placeholderEl);
|
|
1101
1079
|
if (!placeholderResizeObserver.current) {
|
|
1102
1080
|
// Create a new observer and observe the placeholder element.
|
|
1103
|
-
|
|
1081
|
+
const ResizeObserver$1 = window.ResizeObserver || ResizeObserver;
|
|
1104
1082
|
placeholderResizeObserver.current = new ResizeObserver$1(() => {
|
|
1105
1083
|
var _leaf$onPlaceholderRe2;
|
|
1106
1084
|
(_leaf$onPlaceholderRe2 = leaf.onPlaceholderResize) === null || _leaf$onPlaceholderRe2 === void 0 || _leaf$onPlaceholderRe2.call(leaf, placeholderEl);
|
|
@@ -1110,13 +1088,13 @@ var Leaf = props => {
|
|
|
1110
1088
|
placeholderRef.current = placeholderEl;
|
|
1111
1089
|
}
|
|
1112
1090
|
}, [placeholderRef, leaf, editor]);
|
|
1113
|
-
|
|
1091
|
+
let children = /*#__PURE__*/React.createElement(String$1, {
|
|
1114
1092
|
isLast: isLast,
|
|
1115
1093
|
leaf: leaf,
|
|
1116
1094
|
parent: parent,
|
|
1117
1095
|
text: text
|
|
1118
1096
|
});
|
|
1119
|
-
|
|
1097
|
+
const leafIsPlaceholder = Boolean(leaf[PLACEHOLDER_SYMBOL]);
|
|
1120
1098
|
useEffect(() => {
|
|
1121
1099
|
if (leafIsPlaceholder) {
|
|
1122
1100
|
if (!showPlaceholderTimeoutRef.current) {
|
|
@@ -1133,7 +1111,7 @@ var Leaf = props => {
|
|
|
1133
1111
|
return () => clearTimeoutRef(showPlaceholderTimeoutRef);
|
|
1134
1112
|
}, [leafIsPlaceholder, setShowPlaceholder]);
|
|
1135
1113
|
if (leafIsPlaceholder && showPlaceholder) {
|
|
1136
|
-
|
|
1114
|
+
const placeholderProps = {
|
|
1137
1115
|
children: leaf.placeholder,
|
|
1138
1116
|
attributes: {
|
|
1139
1117
|
'data-slate-placeholder': true,
|
|
@@ -1159,7 +1137,7 @@ var Leaf = props => {
|
|
|
1159
1137
|
// COMPAT: Having the `data-` attributes on these leaf elements ensures that
|
|
1160
1138
|
// in certain misbehaving browsers they aren't weirdly cloned/destroyed by
|
|
1161
1139
|
// contenteditable behaviors. (2019/05/08)
|
|
1162
|
-
|
|
1140
|
+
const attributes = {
|
|
1163
1141
|
'data-slate-leaf': true
|
|
1164
1142
|
};
|
|
1165
1143
|
return renderLeaf({
|
|
@@ -1170,11 +1148,11 @@ var Leaf = props => {
|
|
|
1170
1148
|
leafPosition
|
|
1171
1149
|
});
|
|
1172
1150
|
};
|
|
1173
|
-
|
|
1151
|
+
const MemoizedLeaf = /*#__PURE__*/React.memo(Leaf, (prev, next) => {
|
|
1174
1152
|
return next.parent === prev.parent && next.isLast === prev.isLast && next.renderLeaf === prev.renderLeaf && next.renderPlaceholder === prev.renderPlaceholder && next.text === prev.text && Text$1.equals(next.leaf, prev.leaf) && next.leaf[PLACEHOLDER_SYMBOL] === prev.leaf[PLACEHOLDER_SYMBOL];
|
|
1175
1153
|
});
|
|
1176
|
-
|
|
1177
|
-
|
|
1154
|
+
const DefaultLeaf = props => {
|
|
1155
|
+
const {
|
|
1178
1156
|
attributes,
|
|
1179
1157
|
children
|
|
1180
1158
|
} = props;
|
|
@@ -1200,14 +1178,14 @@ var DefaultLeaf = props => {
|
|
|
1200
1178
|
* return state
|
|
1201
1179
|
*/
|
|
1202
1180
|
function useGenericSelector(selector, equalityFn) {
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1181
|
+
const [, forceRender] = useReducer(s => s + 1, 0);
|
|
1182
|
+
const latestSubscriptionCallbackError = useRef();
|
|
1183
|
+
const latestSelector = useRef(() => null);
|
|
1184
|
+
const latestSelectedState = useRef(null);
|
|
1185
|
+
let selectedState;
|
|
1208
1186
|
try {
|
|
1209
1187
|
if (selector !== latestSelector.current || latestSubscriptionCallbackError.current) {
|
|
1210
|
-
|
|
1188
|
+
const selectorResult = selector();
|
|
1211
1189
|
if (equalityFn(latestSelectedState.current, selectorResult)) {
|
|
1212
1190
|
selectedState = latestSelectedState.current;
|
|
1213
1191
|
} else {
|
|
@@ -1218,16 +1196,16 @@ function useGenericSelector(selector, equalityFn) {
|
|
|
1218
1196
|
}
|
|
1219
1197
|
} catch (err) {
|
|
1220
1198
|
if (latestSubscriptionCallbackError.current && isError(err)) {
|
|
1221
|
-
err.message +=
|
|
1199
|
+
err.message += `\nThe error may be correlated with this previous error:\n${latestSubscriptionCallbackError.current.stack}\n\n`;
|
|
1222
1200
|
}
|
|
1223
1201
|
throw err;
|
|
1224
1202
|
}
|
|
1225
1203
|
latestSelector.current = selector;
|
|
1226
1204
|
latestSelectedState.current = selectedState;
|
|
1227
1205
|
latestSubscriptionCallbackError.current = undefined;
|
|
1228
|
-
|
|
1206
|
+
const update = useCallback(() => {
|
|
1229
1207
|
try {
|
|
1230
|
-
|
|
1208
|
+
const newSelectedState = latestSelector.current();
|
|
1231
1209
|
if (equalityFn(latestSelectedState.current, newSelectedState)) {
|
|
1232
1210
|
return;
|
|
1233
1211
|
}
|
|
@@ -1257,32 +1235,32 @@ function isError(error) {
|
|
|
1257
1235
|
* A React context for sharing the `decorate` prop of the editable and
|
|
1258
1236
|
* subscribing to changes on this prop.
|
|
1259
1237
|
*/
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1238
|
+
const DecorateContext = /*#__PURE__*/createContext({});
|
|
1239
|
+
const useDecorations = (node, parentDecorations) => {
|
|
1240
|
+
const editor = useSlateStatic();
|
|
1241
|
+
const {
|
|
1264
1242
|
decorate,
|
|
1265
1243
|
addEventListener
|
|
1266
1244
|
} = useContext(DecorateContext);
|
|
1267
1245
|
// Not memoized since we want nodes to be decorated on each render
|
|
1268
|
-
|
|
1269
|
-
|
|
1246
|
+
const selector = () => {
|
|
1247
|
+
const path = ReactEditor.findPath(editor, node);
|
|
1270
1248
|
return decorate([node, path]);
|
|
1271
1249
|
};
|
|
1272
|
-
|
|
1273
|
-
|
|
1250
|
+
const equalityFn = Node.isText(node) ? isTextDecorationsEqual : isElementDecorationsEqual;
|
|
1251
|
+
const [decorations, update] = useGenericSelector(selector, equalityFn);
|
|
1274
1252
|
useIsomorphicLayoutEffect(() => {
|
|
1275
|
-
|
|
1253
|
+
const unsubscribe = addEventListener(update);
|
|
1276
1254
|
update();
|
|
1277
1255
|
return unsubscribe;
|
|
1278
1256
|
}, [addEventListener, update]);
|
|
1279
1257
|
return useMemo(() => [...decorations, ...parentDecorations], [decorations, parentDecorations]);
|
|
1280
1258
|
};
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1259
|
+
const useDecorateContext = decorateProp => {
|
|
1260
|
+
const [, forceUpdate] = useReducer(s => s + 1, 0);
|
|
1261
|
+
const eventListeners = useRef(new Set());
|
|
1262
|
+
const hasMounted = useRef(false);
|
|
1263
|
+
const latestDecorate = useRef(decorateProp);
|
|
1286
1264
|
useIsomorphicLayoutEffect(() => {
|
|
1287
1265
|
latestDecorate.current = decorateProp;
|
|
1288
1266
|
eventListeners.current.forEach(listener => listener());
|
|
@@ -1301,8 +1279,8 @@ var useDecorateContext = decorateProp => {
|
|
|
1301
1279
|
}
|
|
1302
1280
|
forceUpdate();
|
|
1303
1281
|
}, [decorateProp]);
|
|
1304
|
-
|
|
1305
|
-
|
|
1282
|
+
const decorate = useCallback(entry => latestDecorate.current(entry), []);
|
|
1283
|
+
const addEventListener = useCallback(callback => {
|
|
1306
1284
|
eventListeners.current.add(callback);
|
|
1307
1285
|
return () => {
|
|
1308
1286
|
eventListeners.current.delete(callback);
|
|
@@ -1316,12 +1294,12 @@ var useDecorateContext = decorateProp => {
|
|
|
1316
1294
|
|
|
1317
1295
|
function ownKeys$4(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1318
1296
|
function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$4(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$4(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1319
|
-
|
|
1297
|
+
const defaultRenderText = props => /*#__PURE__*/React.createElement(DefaultText, _objectSpread$4({}, props));
|
|
1320
1298
|
/**
|
|
1321
1299
|
* Text.
|
|
1322
1300
|
*/
|
|
1323
|
-
|
|
1324
|
-
|
|
1301
|
+
const Text = props => {
|
|
1302
|
+
const {
|
|
1325
1303
|
decorations: parentDecorations,
|
|
1326
1304
|
isLast,
|
|
1327
1305
|
parent,
|
|
@@ -1330,20 +1308,20 @@ var Text = props => {
|
|
|
1330
1308
|
renderText = defaultRenderText,
|
|
1331
1309
|
text
|
|
1332
1310
|
} = props;
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
for (
|
|
1340
|
-
|
|
1311
|
+
const editor = useSlateStatic();
|
|
1312
|
+
const ref = useRef(null);
|
|
1313
|
+
const decorations = useDecorations(text, parentDecorations);
|
|
1314
|
+
const decoratedLeaves = Text$1.decorations(text, decorations);
|
|
1315
|
+
const key = ReactEditor.findKey(editor, text);
|
|
1316
|
+
const children = [];
|
|
1317
|
+
for (let i = 0; i < decoratedLeaves.length; i++) {
|
|
1318
|
+
const {
|
|
1341
1319
|
leaf,
|
|
1342
1320
|
position
|
|
1343
1321
|
} = decoratedLeaves[i];
|
|
1344
1322
|
children.push(/*#__PURE__*/React.createElement(MemoizedLeaf, {
|
|
1345
1323
|
isLast: isLast && i === decoratedLeaves.length - 1,
|
|
1346
|
-
key:
|
|
1324
|
+
key: `${key.id}-${i}`,
|
|
1347
1325
|
renderPlaceholder: renderPlaceholder,
|
|
1348
1326
|
leaf: leaf,
|
|
1349
1327
|
leafPosition: position,
|
|
@@ -1353,8 +1331,8 @@ var Text = props => {
|
|
|
1353
1331
|
}));
|
|
1354
1332
|
}
|
|
1355
1333
|
// Update element-related weak maps with the DOM element ref.
|
|
1356
|
-
|
|
1357
|
-
|
|
1334
|
+
const callbackRef = useCallback(span => {
|
|
1335
|
+
const KEY_TO_ELEMENT = EDITOR_TO_KEY_TO_ELEMENT.get(editor);
|
|
1358
1336
|
if (span) {
|
|
1359
1337
|
KEY_TO_ELEMENT === null || KEY_TO_ELEMENT === void 0 || KEY_TO_ELEMENT.set(key, span);
|
|
1360
1338
|
NODE_TO_ELEMENT.set(text, span);
|
|
@@ -1368,7 +1346,7 @@ var Text = props => {
|
|
|
1368
1346
|
}
|
|
1369
1347
|
ref.current = span;
|
|
1370
1348
|
}, [ref, editor, key, text]);
|
|
1371
|
-
|
|
1349
|
+
const attributes = {
|
|
1372
1350
|
'data-slate-node': 'text',
|
|
1373
1351
|
ref: callbackRef
|
|
1374
1352
|
};
|
|
@@ -1378,11 +1356,11 @@ var Text = props => {
|
|
|
1378
1356
|
attributes
|
|
1379
1357
|
});
|
|
1380
1358
|
};
|
|
1381
|
-
|
|
1359
|
+
const MemoizedText = /*#__PURE__*/React.memo(Text, (prev, next) => {
|
|
1382
1360
|
return next.parent === prev.parent && next.isLast === prev.isLast && next.renderText === prev.renderText && next.renderLeaf === prev.renderLeaf && next.renderPlaceholder === prev.renderPlaceholder && next.text === prev.text && isTextDecorationsEqual(next.decorations, prev.decorations);
|
|
1383
1361
|
});
|
|
1384
|
-
|
|
1385
|
-
|
|
1362
|
+
const DefaultText = props => {
|
|
1363
|
+
const {
|
|
1386
1364
|
attributes,
|
|
1387
1365
|
children
|
|
1388
1366
|
} = props;
|
|
@@ -1391,12 +1369,12 @@ var DefaultText = props => {
|
|
|
1391
1369
|
|
|
1392
1370
|
function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1393
1371
|
function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1394
|
-
|
|
1372
|
+
const defaultRenderElement = props => (/*#__PURE__*/React.createElement(DefaultElement, _objectSpread$3({}, props)));
|
|
1395
1373
|
/**
|
|
1396
1374
|
* Element.
|
|
1397
1375
|
*/
|
|
1398
|
-
|
|
1399
|
-
|
|
1376
|
+
const Element = props => {
|
|
1377
|
+
const {
|
|
1400
1378
|
decorations: parentDecorations,
|
|
1401
1379
|
element,
|
|
1402
1380
|
renderElement = defaultRenderElement,
|
|
@@ -1405,14 +1383,14 @@ var Element = props => {
|
|
|
1405
1383
|
renderLeaf,
|
|
1406
1384
|
renderText
|
|
1407
1385
|
} = props;
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1386
|
+
const editor = useSlateStatic();
|
|
1387
|
+
const readOnly = useReadOnly();
|
|
1388
|
+
const isInline = editor.isInline(element);
|
|
1389
|
+
const decorations = useDecorations(element, parentDecorations);
|
|
1390
|
+
const key = ReactEditor.findKey(editor, element);
|
|
1391
|
+
const ref = useCallback(ref => {
|
|
1414
1392
|
// Update element-related weak maps with the DOM element ref.
|
|
1415
|
-
|
|
1393
|
+
const KEY_TO_ELEMENT = EDITOR_TO_KEY_TO_ELEMENT.get(editor);
|
|
1416
1394
|
if (ref) {
|
|
1417
1395
|
KEY_TO_ELEMENT === null || KEY_TO_ELEMENT === void 0 || KEY_TO_ELEMENT.set(key, ref);
|
|
1418
1396
|
NODE_TO_ELEMENT.set(element, ref);
|
|
@@ -1422,7 +1400,7 @@ var Element = props => {
|
|
|
1422
1400
|
NODE_TO_ELEMENT.delete(element);
|
|
1423
1401
|
}
|
|
1424
1402
|
}, [editor, key, element]);
|
|
1425
|
-
|
|
1403
|
+
let children = useChildren({
|
|
1426
1404
|
decorations,
|
|
1427
1405
|
node: element,
|
|
1428
1406
|
renderElement,
|
|
@@ -1433,7 +1411,7 @@ var Element = props => {
|
|
|
1433
1411
|
});
|
|
1434
1412
|
// Attributes that the developer must mix into the element in their
|
|
1435
1413
|
// custom node renderer component.
|
|
1436
|
-
|
|
1414
|
+
const attributes = {
|
|
1437
1415
|
'data-slate-node': 'element',
|
|
1438
1416
|
ref
|
|
1439
1417
|
};
|
|
@@ -1443,8 +1421,8 @@ var Element = props => {
|
|
|
1443
1421
|
// If it's a block node with inline children, add the proper `dir` attribute
|
|
1444
1422
|
// for text direction.
|
|
1445
1423
|
if (!isInline && Editor.hasInlines(editor, element)) {
|
|
1446
|
-
|
|
1447
|
-
|
|
1424
|
+
const text = Node.string(element);
|
|
1425
|
+
const dir = getDirection(text);
|
|
1448
1426
|
if (dir === 'rtl') {
|
|
1449
1427
|
attributes.dir = dir;
|
|
1450
1428
|
}
|
|
@@ -1455,8 +1433,8 @@ var Element = props => {
|
|
|
1455
1433
|
if (!readOnly && isInline) {
|
|
1456
1434
|
attributes.contentEditable = false;
|
|
1457
1435
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1436
|
+
const Tag = isInline ? 'span' : 'div';
|
|
1437
|
+
const [[text]] = Node.texts(element);
|
|
1460
1438
|
children = /*#__PURE__*/React.createElement(Tag, {
|
|
1461
1439
|
"data-slate-spacer": true,
|
|
1462
1440
|
style: {
|
|
@@ -1470,10 +1448,10 @@ var Element = props => {
|
|
|
1470
1448
|
decorations: [],
|
|
1471
1449
|
isLast: false,
|
|
1472
1450
|
parent: element,
|
|
1473
|
-
text:
|
|
1451
|
+
text: text
|
|
1474
1452
|
}));
|
|
1475
|
-
NODE_TO_INDEX.set(
|
|
1476
|
-
NODE_TO_PARENT.set(
|
|
1453
|
+
NODE_TO_INDEX.set(text, 0);
|
|
1454
|
+
NODE_TO_PARENT.set(text, element);
|
|
1477
1455
|
}
|
|
1478
1456
|
return renderElement({
|
|
1479
1457
|
attributes,
|
|
@@ -1481,20 +1459,20 @@ var Element = props => {
|
|
|
1481
1459
|
element
|
|
1482
1460
|
});
|
|
1483
1461
|
};
|
|
1484
|
-
|
|
1462
|
+
const MemoizedElement = /*#__PURE__*/React.memo(Element, (prev, next) => {
|
|
1485
1463
|
return prev.element === next.element && prev.renderElement === next.renderElement && prev.renderChunk === next.renderChunk && prev.renderText === next.renderText && prev.renderLeaf === next.renderLeaf && prev.renderPlaceholder === next.renderPlaceholder && isElementDecorationsEqual(prev.decorations, next.decorations);
|
|
1486
1464
|
});
|
|
1487
1465
|
/**
|
|
1488
1466
|
* The default element renderer.
|
|
1489
1467
|
*/
|
|
1490
|
-
|
|
1491
|
-
|
|
1468
|
+
const DefaultElement = props => {
|
|
1469
|
+
const {
|
|
1492
1470
|
attributes,
|
|
1493
1471
|
children,
|
|
1494
1472
|
element
|
|
1495
1473
|
} = props;
|
|
1496
|
-
|
|
1497
|
-
|
|
1474
|
+
const editor = useSlateStatic();
|
|
1475
|
+
const Tag = editor.isInline(element) ? 'span' : 'div';
|
|
1498
1476
|
return /*#__PURE__*/React.createElement(Tag, _objectSpread$3(_objectSpread$3({}, attributes), {}, {
|
|
1499
1477
|
style: {
|
|
1500
1478
|
position: 'relative'
|
|
@@ -1506,11 +1484,10 @@ var DefaultElement = props => {
|
|
|
1506
1484
|
* Traverse and modify a chunk tree
|
|
1507
1485
|
*/
|
|
1508
1486
|
class ChunkTreeHelper {
|
|
1509
|
-
constructor(chunkTree,
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
} = _ref;
|
|
1487
|
+
constructor(chunkTree, {
|
|
1488
|
+
chunkSize,
|
|
1489
|
+
debug
|
|
1490
|
+
}) {
|
|
1514
1491
|
/**
|
|
1515
1492
|
* The root of the chunk tree
|
|
1516
1493
|
*/
|
|
@@ -1644,15 +1621,15 @@ class ChunkTreeHelper {
|
|
|
1644
1621
|
insertAfter(leaves) {
|
|
1645
1622
|
// istanbul ignore next
|
|
1646
1623
|
if (leaves.length === 0) return;
|
|
1647
|
-
|
|
1648
|
-
|
|
1624
|
+
let beforeDepth = 0;
|
|
1625
|
+
let afterDepth = 0;
|
|
1649
1626
|
// While at the end of a chunk, insert any leaves that will fit, and then
|
|
1650
1627
|
// exit the chunk
|
|
1651
1628
|
while (this.pointerChunk.type === 'chunk' && this.pointerIndex === this.pointerSiblings.length - 1) {
|
|
1652
|
-
|
|
1653
|
-
|
|
1629
|
+
const remainingCapacity = this.chunkSize - this.pointerSiblings.length;
|
|
1630
|
+
const toInsertCount = Math.min(remainingCapacity, leaves.length);
|
|
1654
1631
|
if (toInsertCount > 0) {
|
|
1655
|
-
|
|
1632
|
+
const leavesToInsert = leaves.splice(0, toInsertCount);
|
|
1656
1633
|
this.rawInsertAfter(leavesToInsert, beforeDepth);
|
|
1657
1634
|
}
|
|
1658
1635
|
this.exitChunk();
|
|
@@ -1661,23 +1638,23 @@ class ChunkTreeHelper {
|
|
|
1661
1638
|
if (leaves.length === 0) return;
|
|
1662
1639
|
// Save the pointer so that we can come back here after inserting leaves
|
|
1663
1640
|
// into the starts of subsequent blocks
|
|
1664
|
-
|
|
1641
|
+
const rawInsertPointer = this.savePointer();
|
|
1665
1642
|
// If leaves are inserted into the start of a subsequent block, then we
|
|
1666
1643
|
// eventually need to restore the pointer to the last such inserted leaf
|
|
1667
|
-
|
|
1644
|
+
let finalPointer = null;
|
|
1668
1645
|
// Move the pointer into the chunk containing the next leaf, if it exists
|
|
1669
1646
|
if (this.readLeaf()) {
|
|
1670
1647
|
// While at the start of a chunk, insert any leaves that will fit, and
|
|
1671
1648
|
// then exit the chunk
|
|
1672
1649
|
while (this.pointerChunk.type === 'chunk' && this.pointerIndex === 0) {
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
if (
|
|
1676
|
-
|
|
1650
|
+
const remainingCapacity = this.chunkSize - this.pointerSiblings.length;
|
|
1651
|
+
const toInsertCount = Math.min(remainingCapacity, leaves.length);
|
|
1652
|
+
if (toInsertCount > 0) {
|
|
1653
|
+
const leavesToInsert = leaves.splice(-toInsertCount, toInsertCount);
|
|
1677
1654
|
// Insert the leaves at the start of the chunk
|
|
1678
1655
|
this.pointerIndex = -1;
|
|
1679
1656
|
this.cachedPointerNode = undefined;
|
|
1680
|
-
this.rawInsertAfter(
|
|
1657
|
+
this.rawInsertAfter(leavesToInsert, afterDepth);
|
|
1681
1658
|
// If this is the first batch of insertions at the start of a
|
|
1682
1659
|
// subsequent chunk, set the final pointer to the last inserted leaf
|
|
1683
1660
|
if (!finalPointer) {
|
|
@@ -1692,7 +1669,7 @@ class ChunkTreeHelper {
|
|
|
1692
1669
|
// If there are leaves left to insert, insert them between the end of the
|
|
1693
1670
|
// previous chunk and the start of the first subsequent chunk, or wherever
|
|
1694
1671
|
// the pointer ended up after the first batch of insertions
|
|
1695
|
-
|
|
1672
|
+
const minDepth = Math.max(beforeDepth, afterDepth);
|
|
1696
1673
|
this.rawInsertAfter(leaves, minDepth);
|
|
1697
1674
|
if (finalPointer) {
|
|
1698
1675
|
this.restorePointer(finalPointer);
|
|
@@ -1719,7 +1696,7 @@ class ChunkTreeHelper {
|
|
|
1719
1696
|
* chunks
|
|
1720
1697
|
*/
|
|
1721
1698
|
invalidateChunk() {
|
|
1722
|
-
for (
|
|
1699
|
+
for (let c = this.pointerChunk; c.type === 'chunk'; c = c.parent) {
|
|
1723
1700
|
this.root.modifiedChunks.add(c);
|
|
1724
1701
|
}
|
|
1725
1702
|
}
|
|
@@ -1754,7 +1731,7 @@ class ChunkTreeHelper {
|
|
|
1754
1731
|
*/
|
|
1755
1732
|
get pointerNode() {
|
|
1756
1733
|
if (this.cachedPointerNode !== undefined) return this.cachedPointerNode;
|
|
1757
|
-
|
|
1734
|
+
const pointerNode = this.getPointerNode();
|
|
1758
1735
|
this.cachedPointerNode = pointerNode;
|
|
1759
1736
|
return pointerNode;
|
|
1760
1737
|
}
|
|
@@ -1763,9 +1740,9 @@ class ChunkTreeHelper {
|
|
|
1763
1740
|
* is not connected to the root
|
|
1764
1741
|
*/
|
|
1765
1742
|
getChunkPath(chunk) {
|
|
1766
|
-
|
|
1767
|
-
for (
|
|
1768
|
-
|
|
1743
|
+
const path = [];
|
|
1744
|
+
for (let c = chunk; c.type === 'chunk'; c = c.parent) {
|
|
1745
|
+
const index = c.parent.children.indexOf(c);
|
|
1769
1746
|
// istanbul ignore next
|
|
1770
1747
|
if (index === -1) {
|
|
1771
1748
|
return null;
|
|
@@ -1804,16 +1781,16 @@ class ChunkTreeHelper {
|
|
|
1804
1781
|
// pointer since it was saved, the index and index stack must be
|
|
1805
1782
|
// recomputed. This is slow, but this is fine since restoring a pointer is
|
|
1806
1783
|
// not a frequent operation.
|
|
1807
|
-
|
|
1784
|
+
const {
|
|
1808
1785
|
chunk,
|
|
1809
1786
|
node
|
|
1810
1787
|
} = savedPointer;
|
|
1811
|
-
|
|
1788
|
+
const index = chunk.children.indexOf(node);
|
|
1812
1789
|
// istanbul ignore next
|
|
1813
1790
|
if (index === -1) {
|
|
1814
1791
|
throw new Error('Cannot restore point because saved node is no longer in saved chunk');
|
|
1815
1792
|
}
|
|
1816
|
-
|
|
1793
|
+
const indexStack = this.getChunkPath(chunk);
|
|
1817
1794
|
// istanbul ignore next
|
|
1818
1795
|
if (!indexStack) {
|
|
1819
1796
|
throw new Error('Cannot restore point because saved chunk is no longer connected to root');
|
|
@@ -1868,7 +1845,7 @@ class ChunkTreeHelper {
|
|
|
1868
1845
|
if (this.pointerChunk.type === 'root') {
|
|
1869
1846
|
throw new Error('Cannot exit root');
|
|
1870
1847
|
}
|
|
1871
|
-
|
|
1848
|
+
const previousPointerChunk = this.pointerChunk;
|
|
1872
1849
|
this.pointerChunk = previousPointerChunk.parent;
|
|
1873
1850
|
this.pointerIndex = this.pointerIndexStack.pop();
|
|
1874
1851
|
this.cachedPointerNode = undefined;
|
|
@@ -1883,13 +1860,13 @@ class ChunkTreeHelper {
|
|
|
1883
1860
|
*/
|
|
1884
1861
|
rawInsertAfter(leaves, minDepth) {
|
|
1885
1862
|
if (leaves.length === 0) return;
|
|
1886
|
-
|
|
1863
|
+
const groupIntoChunks = (leaves, parent, perChunk) => {
|
|
1887
1864
|
if (perChunk === 1) return leaves;
|
|
1888
|
-
|
|
1889
|
-
for (
|
|
1890
|
-
|
|
1865
|
+
const chunks = [];
|
|
1866
|
+
for (let i = 0; i < this.chunkSize; i++) {
|
|
1867
|
+
const chunkNodes = leaves.slice(i * perChunk, (i + 1) * perChunk);
|
|
1891
1868
|
if (chunkNodes.length === 0) break;
|
|
1892
|
-
|
|
1869
|
+
const chunk = {
|
|
1893
1870
|
type: 'chunk',
|
|
1894
1871
|
key: new Key(),
|
|
1895
1872
|
parent,
|
|
@@ -1902,15 +1879,15 @@ class ChunkTreeHelper {
|
|
|
1902
1879
|
};
|
|
1903
1880
|
// Determine the chunking depth based on the number of existing nodes in
|
|
1904
1881
|
// the chunk and the number of nodes being inserted
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
for (
|
|
1882
|
+
const newTotal = this.pointerSiblings.length + leaves.length;
|
|
1883
|
+
let depthForTotal = 0;
|
|
1884
|
+
for (let i = this.chunkSize; i < newTotal; i *= this.chunkSize) {
|
|
1908
1885
|
depthForTotal++;
|
|
1909
1886
|
}
|
|
1910
1887
|
// A depth of 0 means no chunking
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1888
|
+
const depth = Math.max(depthForTotal, minDepth);
|
|
1889
|
+
const perTopLevelChunk = Math.pow(this.chunkSize, depth);
|
|
1890
|
+
const chunks = groupIntoChunks(leaves, this.pointerChunk, perTopLevelChunk);
|
|
1914
1891
|
this.pointerSiblings.splice(this.pointerIndex + 1, 0, ...chunks);
|
|
1915
1892
|
this.pointerIndex += chunks.length;
|
|
1916
1893
|
this.cachedPointerNode = undefined;
|
|
@@ -1923,14 +1900,14 @@ class ChunkTreeHelper {
|
|
|
1923
1900
|
// istanbul ignore next
|
|
1924
1901
|
validateState() {
|
|
1925
1902
|
if (!this.debug) return;
|
|
1926
|
-
|
|
1903
|
+
const validateDescendant = node => {
|
|
1927
1904
|
if (node.type === 'chunk') {
|
|
1928
|
-
|
|
1905
|
+
const {
|
|
1929
1906
|
parent,
|
|
1930
1907
|
children
|
|
1931
1908
|
} = node;
|
|
1932
1909
|
if (!parent.children.includes(node)) {
|
|
1933
|
-
throw new Error(
|
|
1910
|
+
throw new Error(`Debug: Chunk ${node.key.id} has an incorrect parent property`);
|
|
1934
1911
|
}
|
|
1935
1912
|
children.forEach(validateDescendant);
|
|
1936
1913
|
}
|
|
@@ -1939,12 +1916,12 @@ class ChunkTreeHelper {
|
|
|
1939
1916
|
if (this.cachedPointerNode !== undefined && this.cachedPointerNode !== this.getPointerNode()) {
|
|
1940
1917
|
throw new Error('Debug: The cached pointer is incorrect and has not been invalidated');
|
|
1941
1918
|
}
|
|
1942
|
-
|
|
1919
|
+
const actualIndexStack = this.getChunkPath(this.pointerChunk);
|
|
1943
1920
|
if (!actualIndexStack) {
|
|
1944
1921
|
throw new Error('Debug: The pointer chunk is not connected to the root');
|
|
1945
1922
|
}
|
|
1946
1923
|
if (!Path.equals(this.pointerIndexStack, actualIndexStack)) {
|
|
1947
|
-
throw new Error(
|
|
1924
|
+
throw new Error(`Debug: The cached index stack [${this.pointerIndexStack.join(', ')}] does not match the path of the pointer chunk [${actualIndexStack.join(', ')}]`);
|
|
1948
1925
|
}
|
|
1949
1926
|
}
|
|
1950
1927
|
}
|
|
@@ -1982,7 +1959,7 @@ class ChildrenHelper {
|
|
|
1982
1959
|
if (n === 1) {
|
|
1983
1960
|
return [this.children[this.pointerIndex++]];
|
|
1984
1961
|
}
|
|
1985
|
-
|
|
1962
|
+
const slicedChildren = this.remaining(n);
|
|
1986
1963
|
this.pointerIndex += n;
|
|
1987
1964
|
return slicedChildren;
|
|
1988
1965
|
}
|
|
@@ -2017,11 +1994,11 @@ class ChildrenHelper {
|
|
|
2017
1994
|
* by one and compare it to the known key.
|
|
2018
1995
|
*/
|
|
2019
1996
|
lookAhead(node, key) {
|
|
2020
|
-
|
|
1997
|
+
const elementResult = this.children.indexOf(node, this.pointerIndex);
|
|
2021
1998
|
if (elementResult > -1) return elementResult - this.pointerIndex;
|
|
2022
|
-
for (
|
|
2023
|
-
|
|
2024
|
-
|
|
1999
|
+
for (let i = this.pointerIndex; i < this.children.length; i++) {
|
|
2000
|
+
const candidateNode = this.children[i];
|
|
2001
|
+
const candidateKey = this.findKey(candidateNode, i);
|
|
2025
2002
|
if (candidateKey === key) return i - this.pointerIndex;
|
|
2026
2003
|
}
|
|
2027
2004
|
return -1;
|
|
@@ -2042,9 +2019,9 @@ class ChildrenHelper {
|
|
|
2042
2019
|
* Get the key for a Slate node, cached using the node's index
|
|
2043
2020
|
*/
|
|
2044
2021
|
findKey(node, index) {
|
|
2045
|
-
|
|
2022
|
+
const cachedKey = this.cachedKeys[index];
|
|
2046
2023
|
if (cachedKey) return cachedKey;
|
|
2047
|
-
|
|
2024
|
+
const key = ReactEditor.findKey(this.editor, node);
|
|
2048
2025
|
this.cachedKeys[index] = key;
|
|
2049
2026
|
return key;
|
|
2050
2027
|
}
|
|
@@ -2054,55 +2031,54 @@ class ChildrenHelper {
|
|
|
2054
2031
|
* Update the chunk tree to match the children array, inserting, removing and
|
|
2055
2032
|
* updating differing nodes
|
|
2056
2033
|
*/
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
var chunkTreeHelper = new ChunkTreeHelper(chunkTree, {
|
|
2034
|
+
const reconcileChildren = (editor, {
|
|
2035
|
+
chunkTree,
|
|
2036
|
+
children,
|
|
2037
|
+
chunkSize,
|
|
2038
|
+
rerenderChildren: _rerenderChildren = [],
|
|
2039
|
+
onInsert,
|
|
2040
|
+
onUpdate,
|
|
2041
|
+
onIndexChange,
|
|
2042
|
+
debug
|
|
2043
|
+
}) => {
|
|
2044
|
+
const chunkTreeHelper = new ChunkTreeHelper(chunkTree, {
|
|
2069
2045
|
chunkSize,
|
|
2070
2046
|
debug
|
|
2071
2047
|
});
|
|
2072
|
-
|
|
2073
|
-
|
|
2048
|
+
const childrenHelper = new ChildrenHelper(editor, children);
|
|
2049
|
+
let treeLeaf;
|
|
2074
2050
|
// Read leaves from the tree one by one, each one representing a single Slate
|
|
2075
2051
|
// node. Each leaf from the tree is compared to the current node in the
|
|
2076
2052
|
// children array to determine whether nodes have been inserted, removed or
|
|
2077
2053
|
// updated.
|
|
2078
|
-
|
|
2054
|
+
while (treeLeaf = chunkTreeHelper.readLeaf()) {
|
|
2079
2055
|
// Check where the tree node appears in the children array. In the most
|
|
2080
2056
|
// common case (where no insertions or removals have occurred), this will be
|
|
2081
2057
|
// 0. If the node has been removed, this will be -1. If new nodes have been
|
|
2082
2058
|
// inserted before the node, or if the node has been moved to a later
|
|
2083
2059
|
// position in the same children array, this will be a positive number.
|
|
2084
|
-
|
|
2060
|
+
const lookAhead = childrenHelper.lookAhead(treeLeaf.node, treeLeaf.key);
|
|
2085
2061
|
// If the node was moved, we want to remove it and insert it later, rather
|
|
2086
2062
|
// then re-inserting all intermediate nodes before it.
|
|
2087
|
-
|
|
2063
|
+
const wasMoved = lookAhead > 0 && chunkTree.movedNodeKeys.has(treeLeaf.key);
|
|
2088
2064
|
// If the tree leaf was moved or removed, remove it
|
|
2089
2065
|
if (lookAhead === -1 || wasMoved) {
|
|
2090
2066
|
chunkTreeHelper.remove();
|
|
2091
|
-
|
|
2067
|
+
continue;
|
|
2092
2068
|
}
|
|
2093
2069
|
// Get the matching Slate node and any nodes that may have been inserted
|
|
2094
2070
|
// prior to it. Insert these into the chunk tree.
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2071
|
+
const insertedChildrenStartIndex = childrenHelper.pointerIndex;
|
|
2072
|
+
const insertedChildren = childrenHelper.read(lookAhead + 1);
|
|
2073
|
+
const matchingChild = insertedChildren.pop();
|
|
2098
2074
|
if (insertedChildren.length) {
|
|
2099
|
-
|
|
2100
|
-
chunkTreeHelper.insertBefore(
|
|
2075
|
+
const leavesToInsert = childrenHelper.toChunkLeaves(insertedChildren, insertedChildrenStartIndex);
|
|
2076
|
+
chunkTreeHelper.insertBefore(leavesToInsert);
|
|
2101
2077
|
insertedChildren.forEach((node, relativeIndex) => {
|
|
2102
2078
|
onInsert === null || onInsert === void 0 || onInsert(node, insertedChildrenStartIndex + relativeIndex);
|
|
2103
2079
|
});
|
|
2104
2080
|
}
|
|
2105
|
-
|
|
2081
|
+
const matchingChildIndex = childrenHelper.pointerIndex - 1;
|
|
2106
2082
|
// Make sure the chunk tree contains the most recent version of the Slate
|
|
2107
2083
|
// node
|
|
2108
2084
|
if (treeLeaf.node !== matchingChild) {
|
|
@@ -2117,18 +2093,15 @@ var reconcileChildren = (editor, _ref) => {
|
|
|
2117
2093
|
}
|
|
2118
2094
|
// Manually invalidate chunks containing specific children that we want to
|
|
2119
2095
|
// re-render
|
|
2120
|
-
if (
|
|
2096
|
+
if (_rerenderChildren.includes(matchingChildIndex)) {
|
|
2121
2097
|
chunkTreeHelper.invalidateChunk();
|
|
2122
2098
|
}
|
|
2123
|
-
};
|
|
2124
|
-
while (treeLeaf = chunkTreeHelper.readLeaf()) {
|
|
2125
|
-
if (_loop()) continue;
|
|
2126
2099
|
}
|
|
2127
2100
|
// If there are still Slate nodes remaining from the children array that were
|
|
2128
2101
|
// not matched to nodes in the tree, insert them at the end of the tree
|
|
2129
2102
|
if (!childrenHelper.reachedEnd) {
|
|
2130
|
-
|
|
2131
|
-
|
|
2103
|
+
const remainingChildren = childrenHelper.remaining();
|
|
2104
|
+
const leavesToInsert = childrenHelper.toChunkLeaves(remainingChildren, childrenHelper.pointerIndex);
|
|
2132
2105
|
// Move the pointer back to the final leaf in the tree, or the start of the
|
|
2133
2106
|
// tree if the tree is currently empty
|
|
2134
2107
|
chunkTreeHelper.returnToPreviousLeaf();
|
|
@@ -2142,7 +2115,7 @@ var reconcileChildren = (editor, _ref) => {
|
|
|
2142
2115
|
|
|
2143
2116
|
function ownKeys$2(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2144
2117
|
function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$2(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2145
|
-
|
|
2118
|
+
const KEY_TO_CHUNK_TREE = new WeakMap();
|
|
2146
2119
|
/**
|
|
2147
2120
|
* Get or create the chunk tree for a Slate node
|
|
2148
2121
|
*
|
|
@@ -2150,10 +2123,11 @@ var KEY_TO_CHUNK_TREE = new WeakMap();
|
|
|
2150
2123
|
* match the current children of the node. The children are chunked
|
|
2151
2124
|
* automatically using the given chunk size.
|
|
2152
2125
|
*/
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2126
|
+
const getChunkTreeForNode = (editor, node,
|
|
2127
|
+
// istanbul ignore next
|
|
2128
|
+
options = {}) => {
|
|
2129
|
+
const key = ReactEditor.findKey(editor, node);
|
|
2130
|
+
let chunkTree = KEY_TO_CHUNK_TREE.get(key);
|
|
2157
2131
|
if (!chunkTree) {
|
|
2158
2132
|
chunkTree = {
|
|
2159
2133
|
type: 'root',
|
|
@@ -2174,14 +2148,11 @@ var getChunkTreeForNode = function getChunkTreeForNode(editor, node) {
|
|
|
2174
2148
|
|
|
2175
2149
|
function ownKeys$1(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2176
2150
|
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
};
|
|
2183
|
-
var ChunkAncestor = props => {
|
|
2184
|
-
var {
|
|
2151
|
+
const defaultRenderChunk = ({
|
|
2152
|
+
children
|
|
2153
|
+
}) => children;
|
|
2154
|
+
const ChunkAncestor = props => {
|
|
2155
|
+
const {
|
|
2185
2156
|
root,
|
|
2186
2157
|
ancestor,
|
|
2187
2158
|
renderElement,
|
|
@@ -2189,8 +2160,8 @@ var ChunkAncestor = props => {
|
|
|
2189
2160
|
} = props;
|
|
2190
2161
|
return ancestor.children.map(chunkNode => {
|
|
2191
2162
|
if (chunkNode.type === 'chunk') {
|
|
2192
|
-
|
|
2193
|
-
|
|
2163
|
+
const key = chunkNode.key.id;
|
|
2164
|
+
const renderedChunk = renderChunk({
|
|
2194
2165
|
highest: ancestor === root,
|
|
2195
2166
|
lowest: chunkNode.children.some(c => c.type === 'leaf'),
|
|
2196
2167
|
attributes: {
|
|
@@ -2208,11 +2179,11 @@ var ChunkAncestor = props => {
|
|
|
2208
2179
|
}, renderedChunk);
|
|
2209
2180
|
}
|
|
2210
2181
|
// Only blocks containing no inlines are chunked
|
|
2211
|
-
|
|
2182
|
+
const element = chunkNode.node;
|
|
2212
2183
|
return renderElement(element, chunkNode.index, chunkNode.key);
|
|
2213
2184
|
});
|
|
2214
2185
|
};
|
|
2215
|
-
|
|
2186
|
+
const ChunkTree = props => {
|
|
2216
2187
|
// Clear the set of modified chunks only when React finishes rendering. The
|
|
2217
2188
|
// timing of this is important in strict mode because if the chunks are
|
|
2218
2189
|
// cleared during rendering (such as in reconcileChildren), strict mode's
|
|
@@ -2222,14 +2193,14 @@ var ChunkTree = props => {
|
|
|
2222
2193
|
});
|
|
2223
2194
|
return /*#__PURE__*/React.createElement(ChunkAncestor, _objectSpread$1({}, props));
|
|
2224
2195
|
};
|
|
2225
|
-
|
|
2196
|
+
const MemoizedChunk = /*#__PURE__*/React.memo(ChunkAncestor, (prev, next) => prev.root === next.root && prev.renderElement === next.renderElement && prev.renderChunk === next.renderChunk && !next.root.modifiedChunks.has(next.ancestor));
|
|
2226
2197
|
|
|
2227
|
-
|
|
2198
|
+
const ElementContext = /*#__PURE__*/createContext(null);
|
|
2228
2199
|
/**
|
|
2229
2200
|
* Get the current element.
|
|
2230
2201
|
*/
|
|
2231
|
-
|
|
2232
|
-
|
|
2202
|
+
const useElement = () => {
|
|
2203
|
+
const context = useContext(ElementContext);
|
|
2233
2204
|
if (!context) {
|
|
2234
2205
|
throw new Error('The `useElement` hook must be used inside `renderElement`.');
|
|
2235
2206
|
}
|
|
@@ -2238,13 +2209,13 @@ var useElement = () => {
|
|
|
2238
2209
|
/**
|
|
2239
2210
|
* Get the current element, or return null if not inside `renderElement`.
|
|
2240
2211
|
*/
|
|
2241
|
-
|
|
2212
|
+
const useElementIf = () => useContext(ElementContext);
|
|
2242
2213
|
|
|
2243
2214
|
/**
|
|
2244
2215
|
* Children.
|
|
2245
2216
|
*/
|
|
2246
|
-
|
|
2247
|
-
|
|
2217
|
+
const useChildren = props => {
|
|
2218
|
+
const {
|
|
2248
2219
|
decorations,
|
|
2249
2220
|
node,
|
|
2250
2221
|
renderElement,
|
|
@@ -2253,13 +2224,13 @@ var useChildren = props => {
|
|
|
2253
2224
|
renderText,
|
|
2254
2225
|
renderLeaf
|
|
2255
2226
|
} = props;
|
|
2256
|
-
|
|
2227
|
+
const editor = useSlateStatic();
|
|
2257
2228
|
IS_NODE_MAP_DIRTY.set(editor, false);
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2229
|
+
const isBlock = Node.isElement(node) && !editor.isInline(node);
|
|
2230
|
+
const isLeafBlock = isBlock && Editor.hasInlines(editor, node);
|
|
2231
|
+
const chunkSize = isLeafBlock ? null : editor.getChunkSize(node);
|
|
2232
|
+
const chunking = !!chunkSize;
|
|
2233
|
+
const {
|
|
2263
2234
|
decorationsByChild,
|
|
2264
2235
|
childrenToRedecorate
|
|
2265
2236
|
} = useDecorationsByChild(editor, node, decorations);
|
|
@@ -2272,10 +2243,10 @@ var useChildren = props => {
|
|
|
2272
2243
|
NODE_TO_PARENT.set(n, node);
|
|
2273
2244
|
});
|
|
2274
2245
|
}
|
|
2275
|
-
|
|
2276
|
-
|
|
2246
|
+
const renderElementComponent = useCallback((n, i, cachedKey) => {
|
|
2247
|
+
const key = cachedKey !== null && cachedKey !== void 0 ? cachedKey : ReactEditor.findKey(editor, n);
|
|
2277
2248
|
return /*#__PURE__*/React.createElement(ElementContext.Provider, {
|
|
2278
|
-
key:
|
|
2249
|
+
key: `provider-${key.id}`,
|
|
2279
2250
|
value: n
|
|
2280
2251
|
}, /*#__PURE__*/React.createElement(MemoizedElement, {
|
|
2281
2252
|
decorations: decorationsByChild[i],
|
|
@@ -2288,8 +2259,8 @@ var useChildren = props => {
|
|
|
2288
2259
|
renderText: renderText
|
|
2289
2260
|
}));
|
|
2290
2261
|
}, [editor, decorationsByChild, renderElement, renderChunk, renderPlaceholder, renderLeaf, renderText]);
|
|
2291
|
-
|
|
2292
|
-
|
|
2262
|
+
const renderTextComponent = (n, i) => {
|
|
2263
|
+
const key = ReactEditor.findKey(editor, n);
|
|
2293
2264
|
return /*#__PURE__*/React.createElement(MemoizedText, {
|
|
2294
2265
|
decorations: decorationsByChild[i],
|
|
2295
2266
|
key: key.id,
|
|
@@ -2304,7 +2275,7 @@ var useChildren = props => {
|
|
|
2304
2275
|
if (!chunking) {
|
|
2305
2276
|
return node.children.map((n, i) => Node.isText(n) ? renderTextComponent(n, i) : renderElementComponent(n, i));
|
|
2306
2277
|
}
|
|
2307
|
-
|
|
2278
|
+
const chunkTree = getChunkTreeForNode(editor, node, {
|
|
2308
2279
|
reconcile: {
|
|
2309
2280
|
chunkSize,
|
|
2310
2281
|
rerenderChildren: childrenToRedecorate,
|
|
@@ -2328,23 +2299,23 @@ var useChildren = props => {
|
|
|
2328
2299
|
renderChunk: renderChunk
|
|
2329
2300
|
});
|
|
2330
2301
|
};
|
|
2331
|
-
|
|
2332
|
-
|
|
2302
|
+
const useDecorationsByChild = (editor, node, decorations) => {
|
|
2303
|
+
const decorationsByChild = splitDecorationsByChild(editor, node, decorations);
|
|
2333
2304
|
// The value we return is a mutable array of `DecoratedRange[]` arrays. This
|
|
2334
2305
|
// lets us avoid passing an immutable array of decorations for each child into
|
|
2335
2306
|
// `ChunkTree` using props. Each `DecoratedRange[]` is only updated if the
|
|
2336
2307
|
// decorations at that index have changed, which speeds up the equality check
|
|
2337
2308
|
// for the `decorations` prop in the memoized `Element` and `Text` components.
|
|
2338
|
-
|
|
2309
|
+
const mutableDecorationsByChild = useRef(decorationsByChild).current;
|
|
2339
2310
|
// Track the list of child indices whose decorations have changed, so that we
|
|
2340
2311
|
// can tell the chunk tree to re-render these children.
|
|
2341
|
-
|
|
2312
|
+
const childrenToRedecorate = [];
|
|
2342
2313
|
// Resize the mutable array to match the latest result
|
|
2343
2314
|
mutableDecorationsByChild.length = decorationsByChild.length;
|
|
2344
|
-
for (
|
|
2315
|
+
for (let i = 0; i < decorationsByChild.length; i++) {
|
|
2345
2316
|
var _mutableDecorationsBy;
|
|
2346
|
-
|
|
2347
|
-
|
|
2317
|
+
const _decorations = decorationsByChild[i];
|
|
2318
|
+
const previousDecorations = (_mutableDecorationsBy = mutableDecorationsByChild[i]) !== null && _mutableDecorationsBy !== void 0 ? _mutableDecorationsBy : null;
|
|
2348
2319
|
if (!isElementDecorationsEqual(previousDecorations, _decorations)) {
|
|
2349
2320
|
mutableDecorationsByChild[i] = _decorations;
|
|
2350
2321
|
childrenToRedecorate.push(i);
|
|
@@ -2359,11 +2330,11 @@ var useDecorationsByChild = (editor, node, decorations) => {
|
|
|
2359
2330
|
/**
|
|
2360
2331
|
* A React context for sharing the `readOnly` state of the editor.
|
|
2361
2332
|
*/
|
|
2362
|
-
|
|
2333
|
+
const ReadOnlyContext = /*#__PURE__*/createContext(false);
|
|
2363
2334
|
/**
|
|
2364
2335
|
* Get the current `readOnly` state of the editor.
|
|
2365
2336
|
*/
|
|
2366
|
-
|
|
2337
|
+
const useReadOnly = () => {
|
|
2367
2338
|
return useContext(ReadOnlyContext);
|
|
2368
2339
|
};
|
|
2369
2340
|
|
|
@@ -2371,8 +2342,8 @@ var useReadOnly = () => {
|
|
|
2371
2342
|
* A React context for sharing the editor selector context in a way to control
|
|
2372
2343
|
* re-renders.
|
|
2373
2344
|
*/
|
|
2374
|
-
|
|
2375
|
-
|
|
2345
|
+
const SlateSelectorContext = /*#__PURE__*/createContext({});
|
|
2346
|
+
const refEquality = (a, b) => a === b;
|
|
2376
2347
|
/**
|
|
2377
2348
|
* Use redux style selectors to prevent re-rendering on every keystroke.
|
|
2378
2349
|
*
|
|
@@ -2387,23 +2358,21 @@ var refEquality = (a, b) => a === b;
|
|
|
2387
2358
|
* @example
|
|
2388
2359
|
* const isSelectionActive = useSlateSelector(editor => Boolean(editor.selection))
|
|
2389
2360
|
*/
|
|
2390
|
-
function useSlateSelector(selector
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
} = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
2395
|
-
var context = useContext(SlateSelectorContext);
|
|
2361
|
+
function useSlateSelector(selector, equalityFn = refEquality, {
|
|
2362
|
+
deferred
|
|
2363
|
+
} = {}) {
|
|
2364
|
+
const context = useContext(SlateSelectorContext);
|
|
2396
2365
|
if (!context) {
|
|
2397
|
-
throw new Error(
|
|
2366
|
+
throw new Error(`The \`useSlateSelector\` hook must be used inside the <Slate> component's context.`);
|
|
2398
2367
|
}
|
|
2399
|
-
|
|
2368
|
+
const {
|
|
2400
2369
|
addEventListener
|
|
2401
2370
|
} = context;
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2371
|
+
const editor = useSlateStatic();
|
|
2372
|
+
const genericSelector = useCallback(() => selector(editor), [editor, selector]);
|
|
2373
|
+
const [selectedState, update] = useGenericSelector(genericSelector, equalityFn);
|
|
2405
2374
|
useIsomorphicLayoutEffect(() => {
|
|
2406
|
-
|
|
2375
|
+
const unsubscribe = addEventListener(update, {
|
|
2407
2376
|
deferred
|
|
2408
2377
|
});
|
|
2409
2378
|
update();
|
|
@@ -2415,26 +2384,25 @@ function useSlateSelector(selector) {
|
|
|
2415
2384
|
* Create selector context with editor updating on every editor change
|
|
2416
2385
|
*/
|
|
2417
2386
|
function useSelectorContext() {
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2387
|
+
const eventListeners = useRef(new Set());
|
|
2388
|
+
const deferredEventListeners = useRef(new Set());
|
|
2389
|
+
const onChange = useCallback(() => {
|
|
2421
2390
|
eventListeners.current.forEach(listener => listener());
|
|
2422
2391
|
}, []);
|
|
2423
|
-
|
|
2392
|
+
const flushDeferred = useCallback(() => {
|
|
2424
2393
|
deferredEventListeners.current.forEach(listener => listener());
|
|
2425
2394
|
deferredEventListeners.current.clear();
|
|
2426
2395
|
}, []);
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
var callback = deferred ? () => deferredEventListeners.current.add(callbackProp) : callbackProp;
|
|
2396
|
+
const addEventListener = useCallback((callbackProp, {
|
|
2397
|
+
deferred: _deferred = false
|
|
2398
|
+
} = {}) => {
|
|
2399
|
+
const callback = _deferred ? () => deferredEventListeners.current.add(callbackProp) : callbackProp;
|
|
2432
2400
|
eventListeners.current.add(callback);
|
|
2433
2401
|
return () => {
|
|
2434
2402
|
eventListeners.current.delete(callback);
|
|
2435
2403
|
};
|
|
2436
2404
|
}, []);
|
|
2437
|
-
|
|
2405
|
+
const selectorContext = useMemo(() => ({
|
|
2438
2406
|
addEventListener,
|
|
2439
2407
|
flushDeferred
|
|
2440
2408
|
}), [addEventListener, flushDeferred]);
|
|
@@ -2444,7 +2412,7 @@ function useSelectorContext() {
|
|
|
2444
2412
|
};
|
|
2445
2413
|
}
|
|
2446
2414
|
function useFlushDeferredSelectorsOnRender() {
|
|
2447
|
-
|
|
2415
|
+
const {
|
|
2448
2416
|
flushDeferred
|
|
2449
2417
|
} = useContext(SlateSelectorContext);
|
|
2450
2418
|
useIsomorphicLayoutEffect(flushDeferred);
|
|
@@ -2453,20 +2421,20 @@ function useFlushDeferredSelectorsOnRender() {
|
|
|
2453
2421
|
/**
|
|
2454
2422
|
* Get the current editor object and re-render whenever it changes.
|
|
2455
2423
|
*/
|
|
2456
|
-
|
|
2457
|
-
|
|
2424
|
+
const useSlate = () => {
|
|
2425
|
+
const {
|
|
2458
2426
|
addEventListener
|
|
2459
2427
|
} = useContext(SlateSelectorContext);
|
|
2460
|
-
|
|
2428
|
+
const [, forceRender] = useReducer(s => s + 1, 0);
|
|
2461
2429
|
if (!addEventListener) {
|
|
2462
|
-
throw new Error(
|
|
2430
|
+
throw new Error(`The \`useSlate\` hook must be used inside the <Slate> component's context.`);
|
|
2463
2431
|
}
|
|
2464
2432
|
useIsomorphicLayoutEffect(() => addEventListener(forceRender), [addEventListener]);
|
|
2465
2433
|
return useSlateStatic();
|
|
2466
2434
|
};
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2435
|
+
const EDITOR_TO_V = new WeakMap();
|
|
2436
|
+
const getEditorVersionRef = editor => {
|
|
2437
|
+
let v = EDITOR_TO_V.get(editor);
|
|
2470
2438
|
if (v) {
|
|
2471
2439
|
return v;
|
|
2472
2440
|
}
|
|
@@ -2475,7 +2443,7 @@ var getEditorVersionRef = editor => {
|
|
|
2475
2443
|
};
|
|
2476
2444
|
EDITOR_TO_V.set(editor, v);
|
|
2477
2445
|
// Register the `onChange` handler exactly once per editor
|
|
2478
|
-
|
|
2446
|
+
const {
|
|
2479
2447
|
onChange
|
|
2480
2448
|
} = editor;
|
|
2481
2449
|
editor.onChange = options => {
|
|
@@ -2491,9 +2459,9 @@ var getEditorVersionRef = editor => {
|
|
|
2491
2459
|
* @deprecated The `v` counter is no longer used except for this hook, and may
|
|
2492
2460
|
* be removed in a future version.
|
|
2493
2461
|
*/
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2462
|
+
const useSlateWithV = () => {
|
|
2463
|
+
const editor = useSlate();
|
|
2464
|
+
const vRef = useMemo(() => getEditorVersionRef(editor), [editor]);
|
|
2497
2465
|
return {
|
|
2498
2466
|
editor,
|
|
2499
2467
|
v: vRef.current
|
|
@@ -2501,15 +2469,15 @@ var useSlateWithV = () => {
|
|
|
2501
2469
|
};
|
|
2502
2470
|
|
|
2503
2471
|
function useTrackUserInput() {
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2472
|
+
const editor = useSlateStatic();
|
|
2473
|
+
const receivedUserInput = useRef(false);
|
|
2474
|
+
const animationFrameIdRef = useRef(0);
|
|
2475
|
+
const onUserInput = useCallback(() => {
|
|
2508
2476
|
if (receivedUserInput.current) {
|
|
2509
2477
|
return;
|
|
2510
2478
|
}
|
|
2511
2479
|
receivedUserInput.current = true;
|
|
2512
|
-
|
|
2480
|
+
const window = ReactEditor.getWindow(editor);
|
|
2513
2481
|
window.cancelAnimationFrame(animationFrameIdRef.current);
|
|
2514
2482
|
animationFrameIdRef.current = window.requestAnimationFrame(() => {
|
|
2515
2483
|
receivedUserInput.current = false;
|
|
@@ -2522,16 +2490,16 @@ function useTrackUserInput() {
|
|
|
2522
2490
|
};
|
|
2523
2491
|
}
|
|
2524
2492
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2493
|
+
const createRestoreDomManager = (editor, receivedUserInput) => {
|
|
2494
|
+
let bufferedMutations = [];
|
|
2495
|
+
const clear = () => {
|
|
2528
2496
|
bufferedMutations = [];
|
|
2529
2497
|
};
|
|
2530
|
-
|
|
2498
|
+
const registerMutations = mutations => {
|
|
2531
2499
|
if (!receivedUserInput.current) {
|
|
2532
2500
|
return;
|
|
2533
2501
|
}
|
|
2534
|
-
|
|
2502
|
+
const trackedMutations = mutations.filter(mutation => isTrackedMutation(editor, mutation, mutations));
|
|
2535
2503
|
bufferedMutations.push(...trackedMutations);
|
|
2536
2504
|
};
|
|
2537
2505
|
function restoreDOM() {
|
|
@@ -2560,7 +2528,7 @@ var createRestoreDomManager = (editor, receivedUserInput) => {
|
|
|
2560
2528
|
};
|
|
2561
2529
|
};
|
|
2562
2530
|
|
|
2563
|
-
|
|
2531
|
+
const MUTATION_OBSERVER_CONFIG = {
|
|
2564
2532
|
subtree: true,
|
|
2565
2533
|
childList: true,
|
|
2566
2534
|
characterData: true,
|
|
@@ -2569,15 +2537,15 @@ var MUTATION_OBSERVER_CONFIG = {
|
|
|
2569
2537
|
// We have to use a class component here since we rely on `getSnapshotBeforeUpdate` which has no FC equivalent
|
|
2570
2538
|
// to run code synchronously immediately before react commits the component update to the DOM.
|
|
2571
2539
|
class RestoreDOMComponent extends Component {
|
|
2572
|
-
constructor() {
|
|
2573
|
-
super(...
|
|
2540
|
+
constructor(...args) {
|
|
2541
|
+
super(...args);
|
|
2574
2542
|
_defineProperty(this, "context", null);
|
|
2575
2543
|
_defineProperty(this, "manager", null);
|
|
2576
2544
|
_defineProperty(this, "mutationObserver", null);
|
|
2577
2545
|
}
|
|
2578
2546
|
observe() {
|
|
2579
2547
|
var _this$mutationObserve;
|
|
2580
|
-
|
|
2548
|
+
const {
|
|
2581
2549
|
node
|
|
2582
2550
|
} = this.props;
|
|
2583
2551
|
if (!node.current) {
|
|
@@ -2586,17 +2554,17 @@ class RestoreDOMComponent extends Component {
|
|
|
2586
2554
|
(_this$mutationObserve = this.mutationObserver) === null || _this$mutationObserve === void 0 || _this$mutationObserve.observe(node.current, MUTATION_OBSERVER_CONFIG);
|
|
2587
2555
|
}
|
|
2588
2556
|
componentDidMount() {
|
|
2589
|
-
|
|
2557
|
+
const {
|
|
2590
2558
|
receivedUserInput
|
|
2591
2559
|
} = this.props;
|
|
2592
|
-
|
|
2560
|
+
const editor = this.context;
|
|
2593
2561
|
this.manager = createRestoreDomManager(editor, receivedUserInput);
|
|
2594
2562
|
this.mutationObserver = new MutationObserver(this.manager.registerMutations);
|
|
2595
2563
|
this.observe();
|
|
2596
2564
|
}
|
|
2597
2565
|
getSnapshotBeforeUpdate() {
|
|
2598
2566
|
var _this$mutationObserve2, _this$mutationObserve3, _this$manager2;
|
|
2599
|
-
|
|
2567
|
+
const pendingMutations = (_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 ? void 0 : _this$mutationObserve2.takeRecords();
|
|
2600
2568
|
if (pendingMutations !== null && pendingMutations !== void 0 && pendingMutations.length) {
|
|
2601
2569
|
var _this$manager;
|
|
2602
2570
|
(_this$manager = this.manager) === null || _this$manager === void 0 || _this$manager.registerMutations(pendingMutations);
|
|
@@ -2619,46 +2587,43 @@ class RestoreDOMComponent extends Component {
|
|
|
2619
2587
|
}
|
|
2620
2588
|
}
|
|
2621
2589
|
_defineProperty(RestoreDOMComponent, "contextType", EditorContext);
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
} = _ref;
|
|
2626
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
2627
|
-
};
|
|
2590
|
+
const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({
|
|
2591
|
+
children
|
|
2592
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
2628
2593
|
|
|
2629
2594
|
/**
|
|
2630
2595
|
* A React context for sharing the `composing` state of the editor.
|
|
2631
2596
|
*/
|
|
2632
|
-
|
|
2597
|
+
const ComposingContext = /*#__PURE__*/createContext(false);
|
|
2633
2598
|
/**
|
|
2634
2599
|
* Get the current `composing` state of the editor.
|
|
2635
2600
|
*/
|
|
2636
|
-
|
|
2601
|
+
const useComposing = () => {
|
|
2637
2602
|
return useContext(ComposingContext);
|
|
2638
2603
|
};
|
|
2639
2604
|
|
|
2640
|
-
|
|
2605
|
+
const _excluded$1 = ["autoFocus", "decorate", "onDOMBeforeInput", "placeholder", "readOnly", "renderElement", "renderChunk", "renderLeaf", "renderText", "renderPlaceholder", "scrollSelectionIntoView", "style", "as", "disableDefaultStyles"],
|
|
2641
2606
|
_excluded2 = ["text"];
|
|
2642
2607
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2643
2608
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
2644
|
-
|
|
2609
|
+
const isSameCaretPosition = (editor, a, b) => {
|
|
2645
2610
|
if (!Range.isCollapsed(a) || !Range.isCollapsed(b)) {
|
|
2646
2611
|
return false;
|
|
2647
2612
|
}
|
|
2648
|
-
|
|
2613
|
+
const [first, second] = Path.isBefore(a.anchor.path, b.anchor.path) ? [a.anchor, b.anchor] : [b.anchor, a.anchor];
|
|
2649
2614
|
if (second.offset !== 0 || !Path.equals(Path.next(first.path), second.path)) {
|
|
2650
2615
|
return false;
|
|
2651
2616
|
}
|
|
2652
|
-
|
|
2617
|
+
const node = Node.get(editor, first.path);
|
|
2653
2618
|
return Node.isText(node) && first.offset === node.text.length;
|
|
2654
2619
|
};
|
|
2655
|
-
|
|
2620
|
+
const Children = props => (/*#__PURE__*/React.createElement(React.Fragment, null, useChildren(props)));
|
|
2656
2621
|
/**
|
|
2657
2622
|
* Editable.
|
|
2658
2623
|
*/
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2624
|
+
const Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
2625
|
+
const defaultRenderPlaceholder = useCallback(props => /*#__PURE__*/React.createElement(DefaultPlaceholder, _objectSpread({}, props)), []);
|
|
2626
|
+
const {
|
|
2662
2627
|
autoFocus,
|
|
2663
2628
|
decorate = defaultDecorate,
|
|
2664
2629
|
onDOMBeforeInput: propsOnDOMBeforeInput,
|
|
@@ -2675,23 +2640,23 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2675
2640
|
disableDefaultStyles = false
|
|
2676
2641
|
} = props,
|
|
2677
2642
|
attributes = _objectWithoutProperties(props, _excluded$1);
|
|
2678
|
-
|
|
2643
|
+
const editor = useSlate();
|
|
2679
2644
|
// Rerender editor when composition status changed
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2645
|
+
const [isComposing, setIsComposing] = useState(false);
|
|
2646
|
+
const ref = useRef(null);
|
|
2647
|
+
const deferredOperations = useRef([]);
|
|
2648
|
+
const [placeholderHeight, setPlaceholderHeight] = useState();
|
|
2649
|
+
const processing = useRef(false);
|
|
2650
|
+
const {
|
|
2686
2651
|
onUserInput,
|
|
2687
2652
|
receivedUserInput
|
|
2688
2653
|
} = useTrackUserInput();
|
|
2689
|
-
|
|
2654
|
+
const [, forceRender] = useReducer(s => s + 1, 0);
|
|
2690
2655
|
EDITOR_TO_FORCE_RENDER.set(editor, forceRender);
|
|
2691
2656
|
// Update internal state on each render.
|
|
2692
2657
|
IS_READ_ONLY.set(editor, readOnly);
|
|
2693
2658
|
// Keep track of some state for the event handler logic.
|
|
2694
|
-
|
|
2659
|
+
const state = useMemo(() => ({
|
|
2695
2660
|
isDraggingInternally: false,
|
|
2696
2661
|
isUpdatingSelection: false,
|
|
2697
2662
|
latestElement: null,
|
|
@@ -2715,22 +2680,22 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2715
2680
|
* It is defined as a reference to simplify hook dependencies and clarify that
|
|
2716
2681
|
* it needs to be initialized.
|
|
2717
2682
|
*/
|
|
2718
|
-
|
|
2683
|
+
const androidInputManagerRef = useRef();
|
|
2719
2684
|
// Listen on the native `selectionchange` event to be able to update any time
|
|
2720
2685
|
// the selection changes. This is required because React's `onSelect` is leaky
|
|
2721
2686
|
// and non-standard so it doesn't fire until after a selection has been
|
|
2722
2687
|
// released. This causes issues in situations where another change happens
|
|
2723
2688
|
// while a selection is being dragged.
|
|
2724
|
-
|
|
2689
|
+
const onDOMSelectionChange = useMemo(() => throttle(() => {
|
|
2725
2690
|
if (IS_NODE_MAP_DIRTY.get(editor)) {
|
|
2726
2691
|
onDOMSelectionChange();
|
|
2727
2692
|
return;
|
|
2728
2693
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2694
|
+
const el = ReactEditor.toDOMNode(editor, editor);
|
|
2695
|
+
const root = el.getRootNode();
|
|
2731
2696
|
if (!processing.current && IS_WEBKIT && root instanceof ShadowRoot) {
|
|
2732
2697
|
processing.current = true;
|
|
2733
|
-
|
|
2698
|
+
const active = getActiveElement();
|
|
2734
2699
|
if (active) {
|
|
2735
2700
|
document.execCommand('indent');
|
|
2736
2701
|
} else {
|
|
@@ -2739,14 +2704,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2739
2704
|
processing.current = false;
|
|
2740
2705
|
return;
|
|
2741
2706
|
}
|
|
2742
|
-
|
|
2707
|
+
const androidInputManager = androidInputManagerRef.current;
|
|
2743
2708
|
if ((IS_ANDROID || !ReactEditor.isComposing(editor)) && (!state.isUpdatingSelection || androidInputManager !== null && androidInputManager !== void 0 && androidInputManager.isFlushing()) && !state.isDraggingInternally) {
|
|
2744
|
-
|
|
2745
|
-
|
|
2709
|
+
const _root = ReactEditor.findDocumentOrShadowRoot(editor);
|
|
2710
|
+
const {
|
|
2746
2711
|
activeElement
|
|
2747
2712
|
} = _root;
|
|
2748
|
-
|
|
2749
|
-
|
|
2713
|
+
const _el = ReactEditor.toDOMNode(editor, editor);
|
|
2714
|
+
const domSelection = getSelection(_root);
|
|
2750
2715
|
if (activeElement === _el) {
|
|
2751
2716
|
state.latestElement = activeElement;
|
|
2752
2717
|
IS_FOCUSED.set(editor, true);
|
|
@@ -2756,14 +2721,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2756
2721
|
if (!domSelection) {
|
|
2757
2722
|
return Transforms.deselect(editor);
|
|
2758
2723
|
}
|
|
2759
|
-
|
|
2724
|
+
const {
|
|
2760
2725
|
anchorNode,
|
|
2761
2726
|
focusNode
|
|
2762
2727
|
} = domSelection;
|
|
2763
|
-
|
|
2764
|
-
|
|
2728
|
+
const anchorNodeSelectable = ReactEditor.hasEditableTarget(editor, anchorNode) || ReactEditor.isTargetInsideNonReadonlyVoid(editor, anchorNode);
|
|
2729
|
+
const focusNodeInEditor = ReactEditor.hasTarget(editor, focusNode);
|
|
2765
2730
|
if (anchorNodeSelectable && focusNodeInEditor) {
|
|
2766
|
-
|
|
2731
|
+
const range = ReactEditor.toSlateRange(editor, domSelection, {
|
|
2767
2732
|
exactMatch: false,
|
|
2768
2733
|
suppressThrow: true
|
|
2769
2734
|
});
|
|
@@ -2781,7 +2746,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2781
2746
|
}
|
|
2782
2747
|
}
|
|
2783
2748
|
}, 100), [editor, readOnly, state]);
|
|
2784
|
-
|
|
2749
|
+
const scheduleOnDOMSelectionChange = useMemo(() => debounce(onDOMSelectionChange, 0), [onDOMSelectionChange]);
|
|
2785
2750
|
androidInputManagerRef.current = useAndroidInputManager({
|
|
2786
2751
|
node: ref,
|
|
2787
2752
|
onDOMSelectionChange,
|
|
@@ -2790,7 +2755,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2790
2755
|
useIsomorphicLayoutEffect(() => {
|
|
2791
2756
|
var _androidInputManagerR, _androidInputManagerR2;
|
|
2792
2757
|
// Update element-related weak maps with the DOM element ref.
|
|
2793
|
-
|
|
2758
|
+
let window;
|
|
2794
2759
|
if (ref.current && (window = getDefaultView(ref.current))) {
|
|
2795
2760
|
EDITOR_TO_WINDOW.set(editor, window);
|
|
2796
2761
|
EDITOR_TO_ELEMENT.set(editor, ref.current);
|
|
@@ -2800,28 +2765,28 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2800
2765
|
NODE_TO_ELEMENT.delete(editor);
|
|
2801
2766
|
}
|
|
2802
2767
|
// Make sure the DOM selection state is in sync.
|
|
2803
|
-
|
|
2768
|
+
const {
|
|
2804
2769
|
selection
|
|
2805
2770
|
} = editor;
|
|
2806
|
-
|
|
2807
|
-
|
|
2771
|
+
const root = ReactEditor.findDocumentOrShadowRoot(editor);
|
|
2772
|
+
const domSelection = getSelection(root);
|
|
2808
2773
|
if (!domSelection || !ReactEditor.isFocused(editor) || (_androidInputManagerR = androidInputManagerRef.current) !== null && _androidInputManagerR !== void 0 && _androidInputManagerR.hasPendingAction()) {
|
|
2809
2774
|
return;
|
|
2810
2775
|
}
|
|
2811
|
-
|
|
2812
|
-
|
|
2776
|
+
const setDomSelection = forceChange => {
|
|
2777
|
+
const hasDomSelection = domSelection.type !== 'None';
|
|
2813
2778
|
// If the DOM selection is properly unset, we're done.
|
|
2814
2779
|
if (!selection && !hasDomSelection) {
|
|
2815
2780
|
return;
|
|
2816
2781
|
}
|
|
2817
2782
|
// Get anchorNode and focusNode
|
|
2818
|
-
|
|
2819
|
-
|
|
2783
|
+
const focusNode = domSelection.focusNode;
|
|
2784
|
+
let anchorNode;
|
|
2820
2785
|
// COMPAT: In firefox the normal selection way does not work
|
|
2821
2786
|
// (https://github.com/ianstormtaylor/slate/pull/5486#issue-1820720223)
|
|
2822
2787
|
if (IS_FIREFOX && domSelection.rangeCount > 1) {
|
|
2823
|
-
|
|
2824
|
-
|
|
2788
|
+
const firstRange = domSelection.getRangeAt(0);
|
|
2789
|
+
const lastRange = domSelection.getRangeAt(domSelection.rangeCount - 1);
|
|
2825
2790
|
// Right to left
|
|
2826
2791
|
if (firstRange.startContainer === focusNode) {
|
|
2827
2792
|
anchorNode = lastRange.endContainer;
|
|
@@ -2833,14 +2798,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2833
2798
|
anchorNode = domSelection.anchorNode;
|
|
2834
2799
|
}
|
|
2835
2800
|
// verify that the dom selection is in the editor
|
|
2836
|
-
|
|
2837
|
-
|
|
2801
|
+
const editorElement = EDITOR_TO_ELEMENT.get(editor);
|
|
2802
|
+
let hasDomSelectionInEditor = false;
|
|
2838
2803
|
if (containsShadowAware(editorElement, anchorNode) && containsShadowAware(editorElement, focusNode)) {
|
|
2839
2804
|
hasDomSelectionInEditor = true;
|
|
2840
2805
|
}
|
|
2841
2806
|
// If the DOM selection is in the editor and the editor selection is already correct, we're done.
|
|
2842
2807
|
if (hasDomSelection && hasDomSelectionInEditor && selection && !forceChange) {
|
|
2843
|
-
|
|
2808
|
+
const slateRange = ReactEditor.toSlateRange(editor, domSelection, {
|
|
2844
2809
|
exactMatch: true,
|
|
2845
2810
|
// domSelection is not necessarily a valid Slate range
|
|
2846
2811
|
// (e.g. when clicking on contentEditable:false element)
|
|
@@ -2870,7 +2835,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2870
2835
|
}
|
|
2871
2836
|
// Otherwise the DOM selection is out of sync, so update it.
|
|
2872
2837
|
state.isUpdatingSelection = true;
|
|
2873
|
-
|
|
2838
|
+
let newDomRange = null;
|
|
2874
2839
|
try {
|
|
2875
2840
|
newDomRange = selection && ReactEditor.toDOMRange(editor, selection);
|
|
2876
2841
|
} catch (e) {
|
|
@@ -2896,19 +2861,19 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2896
2861
|
if (domSelection.rangeCount <= 1) {
|
|
2897
2862
|
setDomSelection();
|
|
2898
2863
|
}
|
|
2899
|
-
|
|
2864
|
+
const ensureSelection = ((_androidInputManagerR2 = androidInputManagerRef.current) === null || _androidInputManagerR2 === void 0 ? void 0 : _androidInputManagerR2.isFlushing()) === 'action';
|
|
2900
2865
|
if (!IS_ANDROID || !ensureSelection) {
|
|
2901
2866
|
setTimeout(() => {
|
|
2902
2867
|
state.isUpdatingSelection = false;
|
|
2903
2868
|
});
|
|
2904
2869
|
return;
|
|
2905
2870
|
}
|
|
2906
|
-
|
|
2907
|
-
|
|
2871
|
+
let timeoutId = null;
|
|
2872
|
+
const animationFrameId = requestAnimationFrame(() => {
|
|
2908
2873
|
if (ensureSelection) {
|
|
2909
|
-
|
|
2874
|
+
const ensureDomSelection = forceChange => {
|
|
2910
2875
|
try {
|
|
2911
|
-
|
|
2876
|
+
const el = ReactEditor.toDOMNode(editor, editor);
|
|
2912
2877
|
el.focus();
|
|
2913
2878
|
setDomSelection(forceChange);
|
|
2914
2879
|
} catch (e) {
|
|
@@ -2940,21 +2905,21 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2940
2905
|
// is required because React's `beforeinput` is fake and never really attaches
|
|
2941
2906
|
// to the real event sadly. (2019/11/01)
|
|
2942
2907
|
// https://github.com/facebook/react/issues/11211
|
|
2943
|
-
|
|
2908
|
+
const onDOMBeforeInput = useCallback(event => {
|
|
2944
2909
|
if (!event.isTrusted) {
|
|
2945
2910
|
return;
|
|
2946
2911
|
}
|
|
2947
2912
|
handleNativeHistoryEvents(editor, event);
|
|
2948
|
-
|
|
2949
|
-
|
|
2913
|
+
const el = ReactEditor.toDOMNode(editor, editor);
|
|
2914
|
+
const root = el.getRootNode();
|
|
2950
2915
|
if (processing !== null && processing !== void 0 && processing.current && IS_WEBKIT && root instanceof ShadowRoot) {
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2916
|
+
const ranges = event.getTargetRanges();
|
|
2917
|
+
const range = ranges[0];
|
|
2918
|
+
const newRange = new window.Range();
|
|
2954
2919
|
newRange.setStart(range.startContainer, range.startOffset);
|
|
2955
2920
|
newRange.setEnd(range.endContainer, range.endOffset);
|
|
2956
2921
|
// Unresolvable ranges would throw out of the handler (#3556); suppress and skip the move.
|
|
2957
|
-
|
|
2922
|
+
const slateRange = ReactEditor.toSlateRange(editor, newRange, {
|
|
2958
2923
|
exactMatch: false,
|
|
2959
2924
|
suppressThrow: true
|
|
2960
2925
|
});
|
|
@@ -2977,20 +2942,20 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2977
2942
|
// set selection.
|
|
2978
2943
|
scheduleOnDOMSelectionChange.flush();
|
|
2979
2944
|
onDOMSelectionChange.flush();
|
|
2980
|
-
|
|
2945
|
+
const {
|
|
2981
2946
|
selection
|
|
2982
2947
|
} = editor;
|
|
2983
|
-
|
|
2948
|
+
const {
|
|
2984
2949
|
inputType: type
|
|
2985
2950
|
} = event;
|
|
2986
|
-
|
|
2987
|
-
|
|
2951
|
+
const data = event.dataTransfer || event.data || undefined;
|
|
2952
|
+
const isCompositionChange = type === 'insertCompositionText' || type === 'deleteCompositionText';
|
|
2988
2953
|
// COMPAT: use composition change events as a hint to where we should insert
|
|
2989
2954
|
// composition text if we aren't composing to work around https://github.com/ianstormtaylor/slate/issues/5038
|
|
2990
2955
|
if (isCompositionChange && ReactEditor.isComposing(editor)) {
|
|
2991
2956
|
return;
|
|
2992
2957
|
}
|
|
2993
|
-
|
|
2958
|
+
let native = false;
|
|
2994
2959
|
if (type === 'insertText' && selection && Range.isCollapsed(selection) &&
|
|
2995
2960
|
// Only use native character insertion for single characters a-z or space for now.
|
|
2996
2961
|
// Long-press events (hold a + press 4 = ä) to choose a special character otherwise
|
|
@@ -3011,24 +2976,24 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3011
2976
|
var _node$parentElement, _window$getComputedSt;
|
|
3012
2977
|
// Chrome also has issues correctly editing the end of anchor elements: https://bugs.chromium.org/p/chromium/issues/detail?id=1259100
|
|
3013
2978
|
// Therefore we don't allow native events to insert text at the end of anchor nodes.
|
|
3014
|
-
|
|
2979
|
+
const {
|
|
3015
2980
|
anchor
|
|
3016
2981
|
} = selection;
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
2982
|
+
const [node, offset] = ReactEditor.toDOMPoint(editor, anchor);
|
|
2983
|
+
const anchorNode = (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.closest('a');
|
|
2984
|
+
const window = ReactEditor.getWindow(editor);
|
|
3020
2985
|
if (native && anchorNode && ReactEditor.hasDOMNode(editor, anchorNode)) {
|
|
3021
2986
|
var _lastText$textContent;
|
|
3022
2987
|
// Find the last text node inside the anchor.
|
|
3023
|
-
|
|
2988
|
+
const lastText = window === null || window === void 0 ? void 0 : window.document.createTreeWalker(anchorNode, NodeFilter.SHOW_TEXT).lastChild();
|
|
3024
2989
|
if (lastText === node && ((_lastText$textContent = lastText.textContent) === null || _lastText$textContent === void 0 ? void 0 : _lastText$textContent.length) === offset) {
|
|
3025
2990
|
native = false;
|
|
3026
2991
|
}
|
|
3027
2992
|
}
|
|
3028
2993
|
// Chrome has issues with the presence of tab characters inside elements with whiteSpace = 'pre'
|
|
3029
2994
|
// causing abnormal insert behavior: https://bugs.chromium.org/p/chromium/issues/detail?id=1219139
|
|
3030
|
-
if (native && node.parentElement && (
|
|
3031
|
-
|
|
2995
|
+
if (native && node.parentElement && (window === null || window === void 0 || (_window$getComputedSt = window.getComputedStyle(node.parentElement)) === null || _window$getComputedSt === void 0 ? void 0 : _window$getComputedSt.whiteSpace) === 'pre') {
|
|
2996
|
+
const block = Editor.above(editor, {
|
|
3032
2997
|
at: anchor.path,
|
|
3033
2998
|
match: n => Node.isElement(n) && Editor.isBlock(editor, n)
|
|
3034
2999
|
});
|
|
@@ -3043,19 +3008,19 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3043
3008
|
// and those commands determine that for themselves.
|
|
3044
3009
|
// If the NODE_MAP is dirty, we can't trust the selection anchor (eg ReactEditor.toDOMPoint via ReactEditor.toSlateRange)
|
|
3045
3010
|
if ((!type.startsWith('delete') || type.startsWith('deleteBy')) && !IS_NODE_MAP_DIRTY.get(editor)) {
|
|
3046
|
-
|
|
3011
|
+
const [targetRange] = event.getTargetRanges();
|
|
3047
3012
|
if (targetRange) {
|
|
3048
3013
|
// Unresolvable ranges would throw out of the handler (#3556); suppress and fall back to synthetic handling.
|
|
3049
|
-
|
|
3014
|
+
const range = ReactEditor.toSlateRange(editor, targetRange, {
|
|
3050
3015
|
exactMatch: false,
|
|
3051
3016
|
suppressThrow: true
|
|
3052
3017
|
});
|
|
3053
|
-
if (!
|
|
3018
|
+
if (!range) {
|
|
3054
3019
|
native = false;
|
|
3055
|
-
} else if (!selection || !Range.equals(selection,
|
|
3020
|
+
} else if (!selection || !Range.equals(selection, range)) {
|
|
3056
3021
|
native = false;
|
|
3057
|
-
|
|
3058
|
-
Transforms.select(editor,
|
|
3022
|
+
const selectionRef = !isCompositionChange && editor.selection && !isSameCaretPosition(editor, editor.selection, range) && Editor.rangeRef(editor, editor.selection);
|
|
3023
|
+
Transforms.select(editor, range);
|
|
3059
3024
|
if (selectionRef) {
|
|
3060
3025
|
EDITOR_TO_USER_SELECTION.set(editor, selectionRef);
|
|
3061
3026
|
}
|
|
@@ -3073,7 +3038,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3073
3038
|
// COMPAT: If the selection is expanded, even if the command seems like
|
|
3074
3039
|
// a delete forward/backward command it should delete the selection.
|
|
3075
3040
|
if (selection && Range.isExpanded(selection) && type.startsWith('delete')) {
|
|
3076
|
-
|
|
3041
|
+
const direction = type.endsWith('Backward') ? 'backward' : 'forward';
|
|
3077
3042
|
Editor.deleteFragment(editor, {
|
|
3078
3043
|
direction
|
|
3079
3044
|
});
|
|
@@ -3194,14 +3159,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3194
3159
|
}
|
|
3195
3160
|
}
|
|
3196
3161
|
// Restore the actual user section if nothing manually set it.
|
|
3197
|
-
|
|
3162
|
+
const toRestore = (_EDITOR_TO_USER_SELEC = EDITOR_TO_USER_SELECTION.get(editor)) === null || _EDITOR_TO_USER_SELEC === void 0 ? void 0 : _EDITOR_TO_USER_SELEC.unref();
|
|
3198
3163
|
EDITOR_TO_USER_SELECTION.delete(editor);
|
|
3199
3164
|
if (toRestore && (!editor.selection || !Range.equals(editor.selection, toRestore))) {
|
|
3200
3165
|
Transforms.select(editor, toRestore);
|
|
3201
3166
|
}
|
|
3202
3167
|
}
|
|
3203
3168
|
}, [editor, onDOMSelectionChange, onUserInput, propsOnDOMBeforeInput, readOnly, scheduleOnDOMSelectionChange]);
|
|
3204
|
-
|
|
3169
|
+
const callbackRef = useCallback(node => {
|
|
3205
3170
|
if (node == null) {
|
|
3206
3171
|
onDOMSelectionChange.cancel();
|
|
3207
3172
|
scheduleOnDOMSelectionChange.cancel();
|
|
@@ -3229,17 +3194,16 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3229
3194
|
}
|
|
3230
3195
|
}, [onDOMSelectionChange, scheduleOnDOMSelectionChange, editor, onDOMBeforeInput, forwardedRef]);
|
|
3231
3196
|
useIsomorphicLayoutEffect(() => {
|
|
3232
|
-
|
|
3197
|
+
const window = ReactEditor.getWindow(editor);
|
|
3233
3198
|
// COMPAT: In Chrome, `selectionchange` events can fire when <input> and
|
|
3234
3199
|
// <textarea> elements are appended to the DOM, causing
|
|
3235
3200
|
// `editor.selection` to be overwritten in some circumstances.
|
|
3236
3201
|
// (2025/01/16) https://issues.chromium.org/issues/389368412
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
var targetTagName = targetElement === null || targetElement === void 0 ? void 0 : targetElement.tagName;
|
|
3202
|
+
const onSelectionChange = ({
|
|
3203
|
+
target
|
|
3204
|
+
}) => {
|
|
3205
|
+
const targetElement = target instanceof HTMLElement ? target : null;
|
|
3206
|
+
const targetTagName = targetElement === null || targetElement === void 0 ? void 0 : targetElement.tagName;
|
|
3243
3207
|
if (targetTagName === 'INPUT' || targetTagName === 'TEXTAREA') {
|
|
3244
3208
|
return;
|
|
3245
3209
|
}
|
|
@@ -3254,7 +3218,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3254
3218
|
// Listen for dragend and drop globally. In Firefox, if a drop handler
|
|
3255
3219
|
// initiates an operation that causes the originally dragged element to
|
|
3256
3220
|
// unmount, that element will not emit a dragend event. (2024/06/21)
|
|
3257
|
-
|
|
3221
|
+
const stoppedDragging = () => {
|
|
3258
3222
|
state.isDraggingInternally = false;
|
|
3259
3223
|
};
|
|
3260
3224
|
window.document.addEventListener('dragend', stoppedDragging);
|
|
@@ -3265,10 +3229,10 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3265
3229
|
window.document.removeEventListener('drop', stoppedDragging);
|
|
3266
3230
|
};
|
|
3267
3231
|
}, [scheduleOnDOMSelectionChange, state]);
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3232
|
+
const decorations = decorate([editor, []]);
|
|
3233
|
+
const decorateContext = useDecorateContext(decorate);
|
|
3234
|
+
const showPlaceholder = placeholder && editor.children.length === 1 && Array.from(Node.texts(editor)).length === 1 && Node.string(editor) === '' && !isComposing;
|
|
3235
|
+
const placeHolderResizeHandler = useCallback(placeholderEl => {
|
|
3272
3236
|
if (placeholderEl && showPlaceholder) {
|
|
3273
3237
|
var _placeholderEl$getBou;
|
|
3274
3238
|
setPlaceholderHeight((_placeholderEl$getBou = placeholderEl.getBoundingClientRect()) === null || _placeholderEl$getBou === void 0 ? void 0 : _placeholderEl$getBou.height);
|
|
@@ -3277,7 +3241,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3277
3241
|
}
|
|
3278
3242
|
}, [showPlaceholder]);
|
|
3279
3243
|
if (showPlaceholder) {
|
|
3280
|
-
|
|
3244
|
+
const start = Editor.start(editor, []);
|
|
3281
3245
|
decorations.push({
|
|
3282
3246
|
[PLACEHOLDER_SYMBOL]: true,
|
|
3283
3247
|
placeholder,
|
|
@@ -3286,16 +3250,16 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3286
3250
|
focus: start
|
|
3287
3251
|
});
|
|
3288
3252
|
}
|
|
3289
|
-
|
|
3253
|
+
const {
|
|
3290
3254
|
marks
|
|
3291
3255
|
} = editor;
|
|
3292
3256
|
state.hasMarkPlaceholder = false;
|
|
3293
3257
|
if (editor.selection && Range.isCollapsed(editor.selection) && marks) {
|
|
3294
|
-
|
|
3258
|
+
const {
|
|
3295
3259
|
anchor
|
|
3296
3260
|
} = editor.selection;
|
|
3297
|
-
|
|
3298
|
-
|
|
3261
|
+
const leaf = Node.leaf(editor, anchor.path);
|
|
3262
|
+
const {
|
|
3299
3263
|
text
|
|
3300
3264
|
} = leaf,
|
|
3301
3265
|
rest = _objectWithoutProperties(leaf, _excluded2);
|
|
@@ -3305,7 +3269,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3305
3269
|
loose: true
|
|
3306
3270
|
})) {
|
|
3307
3271
|
state.hasMarkPlaceholder = true;
|
|
3308
|
-
|
|
3272
|
+
const unset = Object.fromEntries(Object.keys(rest).map(mark => [mark, null]));
|
|
3309
3273
|
decorations.push(_objectSpread(_objectSpread(_objectSpread({
|
|
3310
3274
|
[MARK_PLACEHOLDER_SYMBOL]: true
|
|
3311
3275
|
}, unset), marks), {}, {
|
|
@@ -3318,17 +3282,17 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3318
3282
|
// before we receive the composition end event.
|
|
3319
3283
|
useEffect(() => {
|
|
3320
3284
|
setTimeout(() => {
|
|
3321
|
-
|
|
3285
|
+
const {
|
|
3322
3286
|
selection
|
|
3323
3287
|
} = editor;
|
|
3324
3288
|
if (selection) {
|
|
3325
|
-
|
|
3326
|
-
anchor
|
|
3289
|
+
const {
|
|
3290
|
+
anchor
|
|
3327
3291
|
} = selection;
|
|
3328
|
-
|
|
3292
|
+
const text = Node.leaf(editor, anchor.path);
|
|
3329
3293
|
// While marks isn't a 'complete' text, we can still use loose Text.equals
|
|
3330
3294
|
// here which only compares marks anyway.
|
|
3331
|
-
if (marks && !Text$1.equals(
|
|
3295
|
+
if (marks && !Text$1.equals(text, marks, {
|
|
3332
3296
|
loose: true
|
|
3333
3297
|
})) {
|
|
3334
3298
|
EDITOR_TO_PENDING_INSERTION_MARKS.set(editor, marks);
|
|
@@ -3388,8 +3352,8 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3388
3352
|
if (!HAS_BEFORE_INPUT_SUPPORT && !readOnly && !isEventHandled(event, attributes.onBeforeInput) && ReactEditor.hasSelectableTarget(editor, event.target)) {
|
|
3389
3353
|
event.preventDefault();
|
|
3390
3354
|
if (!ReactEditor.isComposing(editor)) {
|
|
3391
|
-
|
|
3392
|
-
Editor.insertText(editor,
|
|
3355
|
+
const text = event.data;
|
|
3356
|
+
Editor.insertText(editor, text);
|
|
3393
3357
|
}
|
|
3394
3358
|
}
|
|
3395
3359
|
}, [attributes.onBeforeInput, editor, readOnly]),
|
|
@@ -3405,7 +3369,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3405
3369
|
// and we can correctly compare DOM text values in components
|
|
3406
3370
|
// to stop rendering, so that browser functions like autocorrect
|
|
3407
3371
|
// and spellcheck work as expected.
|
|
3408
|
-
for (
|
|
3372
|
+
for (const op of deferredOperations.current) {
|
|
3409
3373
|
op();
|
|
3410
3374
|
}
|
|
3411
3375
|
deferredOperations.current = [];
|
|
@@ -3425,14 +3389,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3425
3389
|
// one, this is due to the window being blurred when the tab
|
|
3426
3390
|
// itself becomes unfocused, so we want to abort early to allow to
|
|
3427
3391
|
// editor to stay focused when the tab becomes focused again.
|
|
3428
|
-
|
|
3392
|
+
const root = ReactEditor.findDocumentOrShadowRoot(editor);
|
|
3429
3393
|
if (state.latestElement === root.activeElement) {
|
|
3430
3394
|
return;
|
|
3431
3395
|
}
|
|
3432
|
-
|
|
3396
|
+
const {
|
|
3433
3397
|
relatedTarget
|
|
3434
3398
|
} = event;
|
|
3435
|
-
|
|
3399
|
+
const el = ReactEditor.toDOMNode(editor, editor);
|
|
3436
3400
|
// COMPAT: The event should be ignored if the focus is returning
|
|
3437
3401
|
// to the editor from an embedded editable element (eg. an <input>
|
|
3438
3402
|
// element inside a void node).
|
|
@@ -3448,7 +3412,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3448
3412
|
// non- editable section of an element that isn't a void node (eg.
|
|
3449
3413
|
// a list item of the check list example).
|
|
3450
3414
|
if (relatedTarget != null && isDOMNode(relatedTarget) && ReactEditor.hasDOMNode(editor, relatedTarget)) {
|
|
3451
|
-
|
|
3415
|
+
const node = ReactEditor.toSlateNode(editor, relatedTarget);
|
|
3452
3416
|
if (Node.isElement(node) && !editor.isVoid(node)) {
|
|
3453
3417
|
return;
|
|
3454
3418
|
}
|
|
@@ -3457,15 +3421,15 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3457
3421
|
// editable element no longer has focus. Refer to:
|
|
3458
3422
|
// https://stackoverflow.com/questions/12353247/force-contenteditable-div-to-stop-accepting-input-after-it-loses-focus-under-web
|
|
3459
3423
|
if (IS_WEBKIT) {
|
|
3460
|
-
|
|
3424
|
+
const domSelection = getSelection(root);
|
|
3461
3425
|
domSelection === null || domSelection === void 0 || domSelection.removeAllRanges();
|
|
3462
3426
|
}
|
|
3463
3427
|
IS_FOCUSED.delete(editor);
|
|
3464
3428
|
}, [readOnly, state.isUpdatingSelection, state.latestElement, editor, attributes.onBlur]),
|
|
3465
3429
|
onClick: useCallback(event => {
|
|
3466
3430
|
if (ReactEditor.hasTarget(editor, event.target) && !isEventHandled(event, attributes.onClick) && isDOMNode(event.target)) {
|
|
3467
|
-
|
|
3468
|
-
|
|
3431
|
+
const node = ReactEditor.toSlateNode(editor, event.target);
|
|
3432
|
+
const path = ReactEditor.findPath(editor, node);
|
|
3469
3433
|
// At this time, the Slate document may be arbitrarily different,
|
|
3470
3434
|
// because onClick handlers can change the document before we get here.
|
|
3471
3435
|
// Therefore we must check that this path actually exists,
|
|
@@ -3474,33 +3438,33 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3474
3438
|
return;
|
|
3475
3439
|
}
|
|
3476
3440
|
if (event.detail === TRIPLE_CLICK && path.length >= 1) {
|
|
3477
|
-
|
|
3441
|
+
let blockPath = path;
|
|
3478
3442
|
if (!(Node.isElement(node) && Editor.isBlock(editor, node))) {
|
|
3479
3443
|
var _block$;
|
|
3480
|
-
|
|
3444
|
+
const block = Editor.above(editor, {
|
|
3481
3445
|
match: n => Node.isElement(n) && Editor.isBlock(editor, n),
|
|
3482
3446
|
at: path
|
|
3483
3447
|
});
|
|
3484
3448
|
blockPath = (_block$ = block === null || block === void 0 ? void 0 : block[1]) !== null && _block$ !== void 0 ? _block$ : path.slice(0, 1);
|
|
3485
3449
|
}
|
|
3486
|
-
|
|
3450
|
+
const range = Editor.range(editor, blockPath);
|
|
3487
3451
|
Transforms.select(editor, range);
|
|
3488
3452
|
return;
|
|
3489
3453
|
}
|
|
3490
3454
|
if (readOnly) {
|
|
3491
3455
|
return;
|
|
3492
3456
|
}
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
at:
|
|
3457
|
+
const start = Editor.start(editor, path);
|
|
3458
|
+
const end = Editor.end(editor, path);
|
|
3459
|
+
const startVoid = Editor.void(editor, {
|
|
3460
|
+
at: start
|
|
3497
3461
|
});
|
|
3498
|
-
|
|
3462
|
+
const endVoid = Editor.void(editor, {
|
|
3499
3463
|
at: end
|
|
3500
3464
|
});
|
|
3501
3465
|
if (startVoid && endVoid && Path.equals(startVoid[1], endVoid[1])) {
|
|
3502
|
-
|
|
3503
|
-
Transforms.select(editor,
|
|
3466
|
+
const range = Editor.range(editor, start);
|
|
3467
|
+
Transforms.select(editor, range);
|
|
3504
3468
|
}
|
|
3505
3469
|
}
|
|
3506
3470
|
}, [editor, attributes.onClick, readOnly]),
|
|
@@ -3525,7 +3489,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3525
3489
|
// type that we need. So instead, insert whenever a composition
|
|
3526
3490
|
// ends since it will already have been committed to the DOM.
|
|
3527
3491
|
if (!IS_WEBKIT && !IS_FIREFOX_LEGACY && !IS_IOS && !IS_WECHATBROWSER && !IS_UC_MOBILE && event.data) {
|
|
3528
|
-
|
|
3492
|
+
const placeholderMarks = EDITOR_TO_PENDING_INSERTION_MARKS.get(editor);
|
|
3529
3493
|
EDITOR_TO_PENDING_INSERTION_MARKS.delete(editor);
|
|
3530
3494
|
// Ensure we insert text with the marks the user was actually seeing
|
|
3531
3495
|
if (placeholderMarks !== undefined) {
|
|
@@ -3533,7 +3497,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3533
3497
|
editor.marks = placeholderMarks;
|
|
3534
3498
|
}
|
|
3535
3499
|
Editor.insertText(editor, event.data);
|
|
3536
|
-
|
|
3500
|
+
const userMarks = EDITOR_TO_USER_MARKS.get(editor);
|
|
3537
3501
|
EDITOR_TO_USER_MARKS.delete(editor);
|
|
3538
3502
|
if (userMarks !== undefined) {
|
|
3539
3503
|
editor.marks = userMarks;
|
|
@@ -3560,7 +3524,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3560
3524
|
return;
|
|
3561
3525
|
}
|
|
3562
3526
|
setIsComposing(true);
|
|
3563
|
-
|
|
3527
|
+
const {
|
|
3564
3528
|
selection
|
|
3565
3529
|
} = editor;
|
|
3566
3530
|
if (selection && Range.isExpanded(selection)) {
|
|
@@ -3579,14 +3543,14 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3579
3543
|
if (!readOnly && ReactEditor.hasSelectableTarget(editor, event.target) && !isEventHandled(event, attributes.onCut) && !isDOMEventTargetInput(event)) {
|
|
3580
3544
|
event.preventDefault();
|
|
3581
3545
|
ReactEditor.setFragmentData(editor, event.clipboardData, 'cut');
|
|
3582
|
-
|
|
3546
|
+
const {
|
|
3583
3547
|
selection
|
|
3584
3548
|
} = editor;
|
|
3585
3549
|
if (selection) {
|
|
3586
3550
|
if (Range.isExpanded(selection)) {
|
|
3587
3551
|
Editor.deleteFragment(editor);
|
|
3588
3552
|
} else {
|
|
3589
|
-
|
|
3553
|
+
const node = Node.parent(editor, selection.anchor.path);
|
|
3590
3554
|
if (Editor.isVoid(editor, node)) {
|
|
3591
3555
|
Transforms.delete(editor);
|
|
3592
3556
|
}
|
|
@@ -3599,7 +3563,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3599
3563
|
// Only when the target is void, call `preventDefault` to signal
|
|
3600
3564
|
// that drops are allowed. Editable content is droppable by
|
|
3601
3565
|
// default, and calling `preventDefault` hides the cursor.
|
|
3602
|
-
|
|
3566
|
+
const node = ReactEditor.toSlateNode(editor, event.target);
|
|
3603
3567
|
if (Node.isElement(node) && Editor.isVoid(editor, node)) {
|
|
3604
3568
|
event.preventDefault();
|
|
3605
3569
|
}
|
|
@@ -3607,16 +3571,16 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3607
3571
|
}, [attributes.onDragOver, editor]),
|
|
3608
3572
|
onDragStart: useCallback(event => {
|
|
3609
3573
|
if (!readOnly && ReactEditor.hasTarget(editor, event.target) && !isEventHandled(event, attributes.onDragStart)) {
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3574
|
+
const node = ReactEditor.toSlateNode(editor, event.target);
|
|
3575
|
+
const path = ReactEditor.findPath(editor, node);
|
|
3576
|
+
const voidMatch = Node.isElement(node) && Editor.isVoid(editor, node) || Editor.void(editor, {
|
|
3613
3577
|
at: path,
|
|
3614
3578
|
voids: true
|
|
3615
3579
|
});
|
|
3616
3580
|
// If starting a drag on a void node, make sure it is selected
|
|
3617
3581
|
// so that it shows up in the selection's fragment.
|
|
3618
3582
|
if (voidMatch) {
|
|
3619
|
-
|
|
3583
|
+
const range = Editor.range(editor, path);
|
|
3620
3584
|
Transforms.select(editor, range);
|
|
3621
3585
|
}
|
|
3622
3586
|
state.isDraggingInternally = true;
|
|
@@ -3627,10 +3591,10 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3627
3591
|
if (!readOnly && event.isTrusted && ReactEditor.hasTarget(editor, event.target) && !isEventHandled(event, attributes.onDrop)) {
|
|
3628
3592
|
event.preventDefault();
|
|
3629
3593
|
// Keep a reference to the dragged range before updating selection
|
|
3630
|
-
|
|
3594
|
+
const draggedRange = editor.selection;
|
|
3631
3595
|
// Find the range where the drop happened
|
|
3632
|
-
|
|
3633
|
-
|
|
3596
|
+
const range = ReactEditor.findEventRange(editor, event);
|
|
3597
|
+
const data = event.dataTransfer;
|
|
3634
3598
|
Transforms.select(editor, range);
|
|
3635
3599
|
if (state.isDraggingInternally) {
|
|
3636
3600
|
if (draggedRange && !Range.equals(draggedRange, range) && !Editor.void(editor, {
|
|
@@ -3657,8 +3621,8 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3657
3621
|
}, [readOnly, state, attributes, editor]),
|
|
3658
3622
|
onFocus: useCallback(event => {
|
|
3659
3623
|
if (!readOnly && !state.isUpdatingSelection && ReactEditor.hasEditableTarget(editor, event.target) && !isEventHandled(event, attributes.onFocus)) {
|
|
3660
|
-
|
|
3661
|
-
|
|
3624
|
+
const el = ReactEditor.toDOMNode(editor, editor);
|
|
3625
|
+
const root = ReactEditor.findDocumentOrShadowRoot(editor);
|
|
3662
3626
|
state.latestElement = root.activeElement;
|
|
3663
3627
|
// COMPAT: If the editor has nested editable elements, the focus
|
|
3664
3628
|
// can go to them. In Firefox, this must be prevented because it
|
|
@@ -3674,7 +3638,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3674
3638
|
if (!readOnly && ReactEditor.hasEditableTarget(editor, event.target)) {
|
|
3675
3639
|
var _androidInputManagerR5;
|
|
3676
3640
|
(_androidInputManagerR5 = androidInputManagerRef.current) === null || _androidInputManagerR5 === void 0 || _androidInputManagerR5.handleKeyDown(event);
|
|
3677
|
-
|
|
3641
|
+
const {
|
|
3678
3642
|
nativeEvent
|
|
3679
3643
|
} = event;
|
|
3680
3644
|
// COMPAT: The composition end event isn't fired reliably in all browsers,
|
|
@@ -3687,18 +3651,18 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3687
3651
|
if (isEventHandled(event, attributes.onKeyDown) || ReactEditor.isComposing(editor)) {
|
|
3688
3652
|
return;
|
|
3689
3653
|
}
|
|
3690
|
-
|
|
3654
|
+
const {
|
|
3691
3655
|
selection
|
|
3692
3656
|
} = editor;
|
|
3693
|
-
|
|
3694
|
-
|
|
3657
|
+
const element = editor.children[selection !== null ? selection.focus.path[0] : 0];
|
|
3658
|
+
const isRTL = getDirection(Node.string(element)) === 'rtl';
|
|
3695
3659
|
// COMPAT: Since we prevent the default behavior on
|
|
3696
3660
|
// `beforeinput` events, the browser doesn't think there's ever
|
|
3697
3661
|
// any history stack to undo or redo, so we have to manage these
|
|
3698
3662
|
// hotkeys ourselves. (2019/11/06)
|
|
3699
3663
|
if (Hotkeys.isRedo(nativeEvent)) {
|
|
3700
3664
|
event.preventDefault();
|
|
3701
|
-
|
|
3665
|
+
const maybeHistoryEditor = editor;
|
|
3702
3666
|
if (typeof maybeHistoryEditor.redo === 'function') {
|
|
3703
3667
|
maybeHistoryEditor.redo();
|
|
3704
3668
|
}
|
|
@@ -3706,9 +3670,9 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3706
3670
|
}
|
|
3707
3671
|
if (Hotkeys.isUndo(nativeEvent)) {
|
|
3708
3672
|
event.preventDefault();
|
|
3709
|
-
|
|
3710
|
-
if (typeof
|
|
3711
|
-
|
|
3673
|
+
const maybeHistoryEditor = editor;
|
|
3674
|
+
if (typeof maybeHistoryEditor.undo === 'function') {
|
|
3675
|
+
maybeHistoryEditor.undo();
|
|
3712
3676
|
}
|
|
3713
3677
|
return;
|
|
3714
3678
|
}
|
|
@@ -3904,7 +3868,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3904
3868
|
// COMPAT: Chrome and Safari support `beforeinput` event but do not fire
|
|
3905
3869
|
// an event when deleting backwards in a selected void inline node
|
|
3906
3870
|
if (selection && (Hotkeys.isDeleteBackward(nativeEvent) || Hotkeys.isDeleteForward(nativeEvent)) && Range.isCollapsed(selection)) {
|
|
3907
|
-
|
|
3871
|
+
const currentNode = Node.parent(editor, selection.anchor.path);
|
|
3908
3872
|
if (Node.isElement(currentNode) && Editor.isVoid(editor, currentNode) && (Editor.isInline(editor, currentNode) || Editor.isBlock(editor, currentNode))) {
|
|
3909
3873
|
event.preventDefault();
|
|
3910
3874
|
if (Hotkeys.isDeleteForward(nativeEvent)) {
|
|
@@ -3951,39 +3915,35 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
3951
3915
|
/**
|
|
3952
3916
|
* The default placeholder element
|
|
3953
3917
|
*/
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
// to prevent Android IMEs to pick up its content in autocorrect and to auto-capitalize the first letter
|
|
3963
|
-
React.createElement("span", _objectSpread({}, attributes), children, IS_ANDROID && /*#__PURE__*/React.createElement("br", null))
|
|
3964
|
-
);
|
|
3965
|
-
};
|
|
3918
|
+
const DefaultPlaceholder = ({
|
|
3919
|
+
attributes,
|
|
3920
|
+
children
|
|
3921
|
+
}) => (
|
|
3922
|
+
/*#__PURE__*/
|
|
3923
|
+
// COMPAT: Artificially add a line-break to the end on the placeholder element
|
|
3924
|
+
// to prevent Android IMEs to pick up its content in autocorrect and to auto-capitalize the first letter
|
|
3925
|
+
React.createElement("span", _objectSpread({}, attributes), children, IS_ANDROID && /*#__PURE__*/React.createElement("br", null)));
|
|
3966
3926
|
/**
|
|
3967
3927
|
* A default memoized decorate function.
|
|
3968
3928
|
*/
|
|
3969
|
-
|
|
3929
|
+
const defaultDecorate = () => [];
|
|
3970
3930
|
/**
|
|
3971
3931
|
* A default implement to scroll dom range into view.
|
|
3972
3932
|
*/
|
|
3973
|
-
|
|
3933
|
+
const defaultScrollSelectionIntoView = (editor, domRange) => {
|
|
3974
3934
|
// Scroll to the focus point of the selection, in case the selection is expanded
|
|
3975
|
-
|
|
3976
|
-
|
|
3935
|
+
const isBackward = !!editor.selection && Range.isBackward(editor.selection);
|
|
3936
|
+
const domFocusPoint = domRange.cloneRange();
|
|
3977
3937
|
domFocusPoint.collapse(isBackward);
|
|
3978
3938
|
if (domFocusPoint.getBoundingClientRect) {
|
|
3979
|
-
|
|
3939
|
+
const leafEl = domFocusPoint.startContainer.parentElement;
|
|
3980
3940
|
// COMPAT: In Chrome, domFocusPoint.getBoundingClientRect() can return zero dimensions for valid ranges (e.g. line breaks).
|
|
3981
3941
|
// When this happens, do not scroll like most editors do.
|
|
3982
|
-
|
|
3983
|
-
|
|
3942
|
+
const domRect = domFocusPoint.getBoundingClientRect();
|
|
3943
|
+
const isZeroDimensionRect = domRect.width === 0 && domRect.height === 0 && domRect.x === 0 && domRect.y === 0;
|
|
3984
3944
|
if (isZeroDimensionRect) {
|
|
3985
|
-
|
|
3986
|
-
|
|
3945
|
+
const leafRect = leafEl.getBoundingClientRect();
|
|
3946
|
+
const leafHasDimensions = leafRect.width > 0 || leafRect.height > 0;
|
|
3987
3947
|
if (leafHasDimensions) {
|
|
3988
3948
|
return;
|
|
3989
3949
|
}
|
|
@@ -4000,13 +3960,13 @@ var defaultScrollSelectionIntoView = (editor, domRange) => {
|
|
|
4000
3960
|
/**
|
|
4001
3961
|
* Check if an event is overrided by a handler.
|
|
4002
3962
|
*/
|
|
4003
|
-
|
|
3963
|
+
const isEventHandled = (event, handler) => {
|
|
4004
3964
|
if (!handler) {
|
|
4005
3965
|
return false;
|
|
4006
3966
|
}
|
|
4007
3967
|
// The custom event handler may return a boolean to specify whether the event
|
|
4008
3968
|
// shall be treated as being handled or not.
|
|
4009
|
-
|
|
3969
|
+
const shouldTreatEventAsHandled = handler(event);
|
|
4010
3970
|
if (shouldTreatEventAsHandled != null) {
|
|
4011
3971
|
return shouldTreatEventAsHandled;
|
|
4012
3972
|
}
|
|
@@ -4015,26 +3975,26 @@ var isEventHandled = (event, handler) => {
|
|
|
4015
3975
|
/**
|
|
4016
3976
|
* Check if the event's target is an input element
|
|
4017
3977
|
*/
|
|
4018
|
-
|
|
3978
|
+
const isDOMEventTargetInput = event => {
|
|
4019
3979
|
return isDOMNode(event.target) && (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement);
|
|
4020
3980
|
};
|
|
4021
3981
|
/**
|
|
4022
3982
|
* Check if a DOM event is overrided by a handler.
|
|
4023
3983
|
*/
|
|
4024
|
-
|
|
3984
|
+
const isDOMEventHandled = (event, handler) => {
|
|
4025
3985
|
if (!handler) {
|
|
4026
3986
|
return false;
|
|
4027
3987
|
}
|
|
4028
3988
|
// The custom event handler may return a boolean to specify whether the event
|
|
4029
3989
|
// shall be treated as being handled or not.
|
|
4030
|
-
|
|
3990
|
+
const shouldTreatEventAsHandled = handler(event);
|
|
4031
3991
|
if (shouldTreatEventAsHandled != null) {
|
|
4032
3992
|
return shouldTreatEventAsHandled;
|
|
4033
3993
|
}
|
|
4034
3994
|
return event.defaultPrevented;
|
|
4035
3995
|
};
|
|
4036
|
-
|
|
4037
|
-
|
|
3996
|
+
const handleNativeHistoryEvents = (editor, event) => {
|
|
3997
|
+
const maybeHistoryEditor = editor;
|
|
4038
3998
|
if (event.inputType === 'historyUndo' && typeof maybeHistoryEditor.undo === 'function') {
|
|
4039
3999
|
maybeHistoryEditor.undo();
|
|
4040
4000
|
return;
|
|
@@ -4048,23 +4008,23 @@ var handleNativeHistoryEvents = (editor, event) => {
|
|
|
4048
4008
|
/**
|
|
4049
4009
|
* A React context for sharing the `focused` state of the editor.
|
|
4050
4010
|
*/
|
|
4051
|
-
|
|
4011
|
+
const FocusedContext = /*#__PURE__*/createContext(false);
|
|
4052
4012
|
/**
|
|
4053
4013
|
* Get the current `focused` state of the editor.
|
|
4054
4014
|
*/
|
|
4055
|
-
|
|
4015
|
+
const useFocused = () => {
|
|
4056
4016
|
return useContext(FocusedContext);
|
|
4057
4017
|
};
|
|
4058
4018
|
|
|
4059
|
-
|
|
4019
|
+
const REACT_MAJOR_VERSION = parseInt(React.version.split('.')[0], 10);
|
|
4060
4020
|
|
|
4061
|
-
|
|
4021
|
+
const _excluded = ["editor", "children", "onChange", "onSelectionChange", "onValueChange", "initialValue"];
|
|
4062
4022
|
/**
|
|
4063
4023
|
* A wrapper around the provider to handle `onChange` events, because the editor
|
|
4064
4024
|
* is a mutable singleton so it won't ever register as "changed" otherwise.
|
|
4065
4025
|
*/
|
|
4066
|
-
|
|
4067
|
-
|
|
4026
|
+
const Slate = props => {
|
|
4027
|
+
const {
|
|
4068
4028
|
editor,
|
|
4069
4029
|
children,
|
|
4070
4030
|
onChange,
|
|
@@ -4073,23 +4033,23 @@ var Slate = props => {
|
|
|
4073
4033
|
initialValue
|
|
4074
4034
|
} = props,
|
|
4075
4035
|
rest = _objectWithoutProperties(props, _excluded);
|
|
4076
|
-
|
|
4036
|
+
const initializedEditor = useRef(null);
|
|
4077
4037
|
if (initializedEditor.current !== editor) {
|
|
4078
4038
|
if (!Node.isNodeList(initialValue)) {
|
|
4079
|
-
throw new Error(
|
|
4039
|
+
throw new Error(`[Slate] initialValue is invalid! Expected a list of elements but got: ${Scrubber.stringify(initialValue)}`);
|
|
4080
4040
|
}
|
|
4081
4041
|
if (!Editor.isEditor(editor)) {
|
|
4082
|
-
throw new Error(
|
|
4042
|
+
throw new Error(`[Slate] editor is invalid! You passed: ${Scrubber.stringify(editor)}`);
|
|
4083
4043
|
}
|
|
4084
4044
|
editor.children = initialValue;
|
|
4085
4045
|
Object.assign(editor, rest);
|
|
4086
4046
|
initializedEditor.current = editor;
|
|
4087
4047
|
}
|
|
4088
|
-
|
|
4048
|
+
const {
|
|
4089
4049
|
selectorContext,
|
|
4090
4050
|
onChange: handleSelectorChange
|
|
4091
4051
|
} = useSelectorContext();
|
|
4092
|
-
|
|
4052
|
+
const onContextChange = useCallback(() => {
|
|
4093
4053
|
if (onChange) {
|
|
4094
4054
|
onChange(editor.children);
|
|
4095
4055
|
}
|
|
@@ -4107,12 +4067,12 @@ var Slate = props => {
|
|
|
4107
4067
|
EDITOR_TO_ON_CHANGE.set(editor, () => {});
|
|
4108
4068
|
};
|
|
4109
4069
|
}, [editor, onContextChange]);
|
|
4110
|
-
|
|
4070
|
+
const [isFocused, setIsFocused] = useState(ReactEditor.isFocused(editor));
|
|
4111
4071
|
useEffect(() => {
|
|
4112
4072
|
setIsFocused(ReactEditor.isFocused(editor));
|
|
4113
4073
|
}, [editor]);
|
|
4114
4074
|
useIsomorphicLayoutEffect(() => {
|
|
4115
|
-
|
|
4075
|
+
const fn = () => setIsFocused(ReactEditor.isFocused(editor));
|
|
4116
4076
|
if (REACT_MAJOR_VERSION >= 17) {
|
|
4117
4077
|
// In React >= 17 onFocus and onBlur listen to the focusin and focusout events during the bubbling phase.
|
|
4118
4078
|
// Therefore in order for <Editable />'s handlers to run first, which is necessary for ReactEditor.isFocused(editor)
|
|
@@ -4145,10 +4105,10 @@ var Slate = props => {
|
|
|
4145
4105
|
* Get the current editor object from the React context.
|
|
4146
4106
|
* @deprecated Use useSlateStatic instead.
|
|
4147
4107
|
*/
|
|
4148
|
-
|
|
4149
|
-
|
|
4108
|
+
const useEditor = () => {
|
|
4109
|
+
const editor = useContext(EditorContext);
|
|
4150
4110
|
if (!editor) {
|
|
4151
|
-
throw new Error(
|
|
4111
|
+
throw new Error(`The \`useEditor\` hook must be used inside the <Slate> component's context.`);
|
|
4152
4112
|
}
|
|
4153
4113
|
return editor;
|
|
4154
4114
|
};
|
|
@@ -4159,30 +4119,29 @@ var useEditor = () => {
|
|
|
4159
4119
|
* Set `suppressThrow` to return `false` instead of throwing when the element
|
|
4160
4120
|
* can no longer be found in the editor.
|
|
4161
4121
|
*/
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
var element = useElementIf();
|
|
4122
|
+
const useSelected = ({
|
|
4123
|
+
suppressThrow: _suppressThrow = false
|
|
4124
|
+
} = {}) => {
|
|
4125
|
+
const element = useElementIf();
|
|
4167
4126
|
// Breaking the rules of hooks is fine here since `!element` will remain true
|
|
4168
4127
|
// or false for the entire lifetime of the component this hook is called from.
|
|
4169
4128
|
// TODO: Decide if we want to throw an error instead when calling
|
|
4170
4129
|
// `useSelected` outside of an element (potentially a breaking change).
|
|
4171
4130
|
if (!element) return false;
|
|
4172
4131
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
4173
|
-
|
|
4132
|
+
const selector = useCallback(editor => {
|
|
4174
4133
|
if (!editor.selection) return false;
|
|
4175
4134
|
try {
|
|
4176
|
-
|
|
4177
|
-
|
|
4135
|
+
const path = ReactEditor.findPath(editor, element);
|
|
4136
|
+
const range = Editor.range(editor, path);
|
|
4178
4137
|
return !!Range.intersection(range, editor.selection);
|
|
4179
4138
|
} catch (e) {
|
|
4180
|
-
if (
|
|
4139
|
+
if (_suppressThrow) {
|
|
4181
4140
|
return false;
|
|
4182
4141
|
}
|
|
4183
4142
|
throw e;
|
|
4184
4143
|
}
|
|
4185
|
-
}, [element,
|
|
4144
|
+
}, [element, _suppressThrow]);
|
|
4186
4145
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
4187
4146
|
return useSlateSelector(selector, undefined, {
|
|
4188
4147
|
// Defer the selector until after `Editable` has rendered so that the path
|
|
@@ -4195,10 +4154,10 @@ var useSelected = function useSelected() {
|
|
|
4195
4154
|
* Get the current slate selection.
|
|
4196
4155
|
* Only triggers a rerender when the selection actually changes
|
|
4197
4156
|
*/
|
|
4198
|
-
|
|
4157
|
+
const useSlateSelection = () => {
|
|
4199
4158
|
return useSlateSelector(editor => editor.selection, isSelectionEqual);
|
|
4200
4159
|
};
|
|
4201
|
-
|
|
4160
|
+
const isSelectionEqual = (a, b) => {
|
|
4202
4161
|
if (!a && !b) return true;
|
|
4203
4162
|
if (!a || !b) return false;
|
|
4204
4163
|
return Range.equals(a, b);
|
|
@@ -4212,11 +4171,10 @@ var isSelectionEqual = (a, b) => {
|
|
|
4212
4171
|
*
|
|
4213
4172
|
* See https://docs.slatejs.org/concepts/11-typescript to learn how.
|
|
4214
4173
|
*/
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
var e = editor;
|
|
4174
|
+
const withReact = (editor, clipboardFormatKey = 'x-slate-fragment') => {
|
|
4175
|
+
let e = editor;
|
|
4218
4176
|
e = withDOM(e, clipboardFormatKey);
|
|
4219
|
-
|
|
4177
|
+
const {
|
|
4220
4178
|
onChange,
|
|
4221
4179
|
apply,
|
|
4222
4180
|
insertText
|
|
@@ -4240,7 +4198,7 @@ var withReact = function withReact(editor) {
|
|
|
4240
4198
|
// pass. So we have to use this unstable API to ensure it batches them.
|
|
4241
4199
|
// (2019/12/03)
|
|
4242
4200
|
// https://github.com/facebook/react/issues/14259#issuecomment-439702367
|
|
4243
|
-
|
|
4201
|
+
const maybeBatchUpdates = REACT_MAJOR_VERSION < 18 ? ReactDOM.unstable_batchedUpdates : callback => callback();
|
|
4244
4202
|
maybeBatchUpdates(() => {
|
|
4245
4203
|
onChange(options);
|
|
4246
4204
|
});
|
|
@@ -4250,12 +4208,12 @@ var withReact = function withReact(editor) {
|
|
|
4250
4208
|
// parent's chunk tree.
|
|
4251
4209
|
e.apply = operation => {
|
|
4252
4210
|
if (operation.type === 'move_node') {
|
|
4253
|
-
|
|
4254
|
-
|
|
4211
|
+
const parent = Node.parent(e, operation.path);
|
|
4212
|
+
const chunking = !!e.getChunkSize(parent);
|
|
4255
4213
|
if (chunking) {
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4214
|
+
const node = Node.get(e, operation.path);
|
|
4215
|
+
const chunkTree = getChunkTreeForNode(e, parent);
|
|
4216
|
+
const key = ReactEditor.findKey(e, node);
|
|
4259
4217
|
chunkTree.movedNodeKeys.add(key);
|
|
4260
4218
|
}
|
|
4261
4219
|
}
|