slate-react 0.71.0 → 0.71.1-20211141648

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.
@@ -973,7 +973,7 @@
973
973
  */
974
974
 
975
975
  var EDITOR_TO_ON_CHANGE = new WeakMap();
976
- var EDITOR_TO_RESTORE_DOM = new WeakMap();
976
+ var NODE_TO_RESTORE_DOM = new WeakMap();
977
977
  /**
978
978
  * Symbols.
979
979
  */
@@ -1130,6 +1130,42 @@
1130
1130
  return true;
1131
1131
  };
1132
1132
 
1133
+ function useContentKey(node) {
1134
+ var contentKeyRef = React.useRef(0);
1135
+ var updateAnimationFrameRef = React.useRef(null);
1136
+
1137
+ var _useState = React.useState(0),
1138
+ _useState2 = _slicedToArray(_useState, 2),
1139
+ setForceRerenderCounter = _useState2[1];
1140
+
1141
+ React.useEffect(function () {
1142
+ NODE_TO_RESTORE_DOM.set(node, function () {
1143
+ // Update is already queued and node hasn't re-render yet
1144
+ if (updateAnimationFrameRef.current) {
1145
+ return;
1146
+ }
1147
+
1148
+ updateAnimationFrameRef.current = requestAnimationFrame(function () {
1149
+ setForceRerenderCounter(function (state) {
1150
+ return state + 1;
1151
+ });
1152
+ updateAnimationFrameRef.current = null;
1153
+ });
1154
+ contentKeyRef.current++;
1155
+ });
1156
+ return function () {
1157
+ NODE_TO_RESTORE_DOM["delete"](node);
1158
+ };
1159
+ }, [node]); // Node was restored => clear scheduled update
1160
+
1161
+ if (updateAnimationFrameRef.current) {
1162
+ cancelAnimationFrame(updateAnimationFrameRef.current);
1163
+ updateAnimationFrameRef.current = null;
1164
+ }
1165
+
1166
+ return contentKeyRef.current;
1167
+ }
1168
+
1133
1169
  /**
1134
1170
  * Text.
1135
1171
  */
@@ -1173,9 +1209,11 @@
1173
1209
  NODE_TO_ELEMENT["delete"](text);
1174
1210
  }
1175
1211
  });
1212
+ var contentKey = IS_ANDROID ? useContentKey(text) : undefined;
1176
1213
  return /*#__PURE__*/React__default['default'].createElement("span", {
1177
1214
  "data-slate-node": "text",
1178
- ref: ref
1215
+ ref: ref,
1216
+ key: contentKey
1179
1217
  }, children);
1180
1218
  };
1181
1219
 
@@ -1279,11 +1317,20 @@
1279
1317
  NODE_TO_ELEMENT["delete"](element);
1280
1318
  }
1281
1319
  });
1282
- return renderElement({
1320
+ var content = renderElement({
1283
1321
  attributes: attributes,
1284
1322
  children: children,
1285
1323
  element: element
1286
1324
  });
1325
+
1326
+ if (IS_ANDROID) {
1327
+ var contentKey = useContentKey(element);
1328
+ return /*#__PURE__*/React__default['default'].createElement(React.Fragment, {
1329
+ key: contentKey
1330
+ }, content);
1331
+ }
1332
+
1333
+ return content;
1287
1334
  };
1288
1335
 
1289
1336
  var MemoizedElement = /*#__PURE__*/React__default['default'].memo(Element, function (prev, next) {
@@ -4178,19 +4225,6 @@
4178
4225
  return removedNodes.length > 0 && addedNodes.length === 0 && characterDataMutations.length > 0;
4179
4226
  };
4180
4227
 
4181
- function restoreDOM(editor) {
4182
- try {
4183
- var onRestoreDOM = EDITOR_TO_RESTORE_DOM.get(editor);
4184
-
4185
- if (onRestoreDOM) {
4186
- onRestoreDOM();
4187
- }
4188
- } catch (err) {
4189
- // eslint-disable-next-line no-console
4190
- console.error(err);
4191
- }
4192
- }
4193
-
4194
4228
  function _createForOfIteratorHelper$1(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
4195
4229
 
4196
4230
  function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); }
@@ -4221,15 +4255,17 @@
4221
4255
  * - Line breaks
4222
4256
  *
4223
4257
  * @param editor
4258
+ * @param restoreDOM
4224
4259
  */
4225
4260
 
4226
4261
 
4227
- var AndroidInputManager = function AndroidInputManager(editor) {
4262
+ var AndroidInputManager = function AndroidInputManager(editor, restoreDOM) {
4228
4263
  var _this = this;
4229
4264
 
4230
4265
  _classCallCheck(this, AndroidInputManager);
4231
4266
 
4232
4267
  this.editor = editor;
4268
+ this.restoreDOM = restoreDOM;
4233
4269
  /**
4234
4270
  * Handle MutationObserver flush
4235
4271
  *
@@ -4244,7 +4280,7 @@
4244
4280
  // eslint-disable-next-line no-console
4245
4281
  console.error(err); // Failed to reconcile mutations, restore DOM to its previous state
4246
4282
 
4247
- restoreDOM(_this.editor);
4283
+ _this.restoreDOM();
4248
4284
  }
4249
4285
  };
4250
4286
  /**
@@ -4312,10 +4348,9 @@
4312
4348
 
4313
4349
  this.insertBreak = function () {
4314
4350
  var selection = _this.editor.selection;
4315
- slate.Editor.insertBreak(_this.editor); // To-do: Need a more granular solution to restoring only a specific portion
4316
- // of the document. Restoring the entire document is expensive.
4351
+ slate.Editor.insertBreak(_this.editor);
4317
4352
 
4318
- restoreDOM(_this.editor);
4353
+ _this.restoreDOM();
4319
4354
 
4320
4355
  if (selection) {
4321
4356
  // Compat: Move selection to the newly inserted block if it has not moved
@@ -4340,7 +4375,7 @@
4340
4375
  slate.Editor.insertText(_this.editor, text);
4341
4376
  }
4342
4377
 
4343
- restoreDOM(_this.editor);
4378
+ _this.restoreDOM();
4344
4379
  };
4345
4380
  /**
4346
4381
  * Handle `backspace` that merges blocks
@@ -4350,7 +4385,8 @@
4350
4385
  this.deleteBackward = function () {
4351
4386
  slate.Editor.deleteBackward(_this.editor);
4352
4387
  ReactEditor.focus(_this.editor);
4353
- restoreDOM(_this.editor);
4388
+
4389
+ _this.restoreDOM();
4354
4390
  };
4355
4391
  /**
4356
4392
  * Handle mutations that remove specific leaves
@@ -4371,7 +4407,8 @@
4371
4407
  slate.Transforms["delete"](_this.editor, {
4372
4408
  at: path
4373
4409
  });
4374
- restoreDOM(_this.editor);
4410
+
4411
+ _this.restoreDOM();
4375
4412
  }
4376
4413
  }
4377
4414
  } catch (err) {
@@ -4382,6 +4419,7 @@
4382
4419
  };
4383
4420
 
4384
4421
  this.editor = editor;
4422
+ this.restoreDOM = restoreDOM;
4385
4423
  };
4386
4424
 
4387
4425
  function useMutationObserver(node, callback, options) {
@@ -4407,6 +4445,72 @@
4407
4445
  });
4408
4446
  }
4409
4447
 
4448
+ var MUTATION_OBSERVER_CONFIG$1 = {
4449
+ childList: true,
4450
+ characterData: true,
4451
+ subtree: true
4452
+ };
4453
+
4454
+ function findClosestKnowSlateNode(domNode) {
4455
+ var _domEl;
4456
+
4457
+ var domEl = isDOMElement(domNode) ? domNode : domNode.parentElement;
4458
+
4459
+ if (domEl && !domEl.hasAttribute('data-slate-node')) {
4460
+ domEl = domEl.closest("[data-slate-node]");
4461
+ }
4462
+
4463
+ var slateNode = domEl && ELEMENT_TO_NODE.get(domEl);
4464
+
4465
+ if (slateNode) {
4466
+ return slateNode;
4467
+ } // Unknown dom element with a slate-slate-node attribute => the IME
4468
+ // most likely duplicated the node so we have to restore the parent
4469
+
4470
+
4471
+ return (_domEl = domEl) !== null && _domEl !== void 0 && _domEl.parentElement ? findClosestKnowSlateNode(domEl.parentElement) : null;
4472
+ }
4473
+
4474
+ function useRestoreDom(node, receivedUserInput) {
4475
+ var editor = useSlateStatic();
4476
+ var mutatedNodes = React.useRef(new Set());
4477
+ var handleDOMMutation = React.useCallback(function (mutations) {
4478
+ if (!receivedUserInput.current) {
4479
+ return;
4480
+ }
4481
+
4482
+ mutations.forEach(function (_ref) {
4483
+ var target = _ref.target;
4484
+ var slateNode = findClosestKnowSlateNode(target);
4485
+
4486
+ if (!slateNode) {
4487
+ return;
4488
+ }
4489
+
4490
+ return mutatedNodes.current.add(slateNode);
4491
+ });
4492
+ }, []);
4493
+ useMutationObserver(node, handleDOMMutation, MUTATION_OBSERVER_CONFIG$1); // Clear mutated nodes on every render
4494
+
4495
+ mutatedNodes.current.clear();
4496
+ var restore = React.useCallback(function () {
4497
+ var mutated = Array.from(mutatedNodes.current.values()); // Filter out child nodes of nodes that will be restored anyway
4498
+
4499
+ var nodesToRestore = mutated.filter(function (n) {
4500
+ return !mutated.some(function (m) {
4501
+ return slate.Path.isParent(ReactEditor.findPath(editor, m), ReactEditor.findPath(editor, n));
4502
+ });
4503
+ });
4504
+ nodesToRestore.forEach(function (n) {
4505
+ var _NODE_TO_RESTORE_DOM$;
4506
+
4507
+ (_NODE_TO_RESTORE_DOM$ = NODE_TO_RESTORE_DOM.get(n)) === null || _NODE_TO_RESTORE_DOM$ === void 0 ? void 0 : _NODE_TO_RESTORE_DOM$();
4508
+ });
4509
+ mutatedNodes.current.clear();
4510
+ }, []);
4511
+ return restore;
4512
+ }
4513
+
4410
4514
  function useTrackUserInput() {
4411
4515
  var editor = useSlateStatic();
4412
4516
  var receivedUserInput = React.useRef(false);
@@ -4447,16 +4551,14 @@
4447
4551
  function useAndroidInputManager(node) {
4448
4552
  var editor = useSlateStatic();
4449
4553
 
4450
- var _useState = React.useState(function () {
4451
- return new AndroidInputManager(editor);
4452
- }),
4453
- _useState2 = _slicedToArray(_useState, 1),
4454
- inputManager = _useState2[0];
4455
-
4456
4554
  var _useTrackUserInput = useTrackUserInput(),
4457
4555
  receivedUserInput = _useTrackUserInput.receivedUserInput,
4458
4556
  onUserInput = _useTrackUserInput.onUserInput;
4459
4557
 
4558
+ var restoreDom = useRestoreDom(node, receivedUserInput);
4559
+ var inputManager = React.useMemo(function () {
4560
+ return new AndroidInputManager(editor, restoreDom);
4561
+ }, [restoreDom, editor]);
4460
4562
  var timeoutId = React.useRef(null);
4461
4563
  var isReconciling = React.useRef(false);
4462
4564
  var flush = React.useCallback(function (mutations) {
@@ -4524,17 +4626,7 @@
4524
4626
  latestElement: null
4525
4627
  };
4526
4628
  }, []);
4527
-
4528
- var _useState = React.useState(0),
4529
- _useState2 = _slicedToArray(_useState, 2),
4530
- contentKey = _useState2[0],
4531
- setContentKey = _useState2[1];
4532
-
4533
- var onRestoreDOM = React.useCallback(function () {
4534
- setContentKey(function (prev) {
4535
- return prev + 1;
4536
- });
4537
- }, [contentKey]); // Whenever the editor updates...
4629
+ var contentKey = useContentKey(editor); // Whenever the editor updates...
4538
4630
 
4539
4631
  useIsomorphicLayoutEffect(function () {
4540
4632
  // Update element-related weak maps with the DOM element ref.
@@ -4545,10 +4637,8 @@
4545
4637
  EDITOR_TO_ELEMENT.set(editor, ref.current);
4546
4638
  NODE_TO_ELEMENT.set(editor, ref.current);
4547
4639
  ELEMENT_TO_NODE.set(ref.current, editor);
4548
- EDITOR_TO_RESTORE_DOM.set(editor, onRestoreDOM);
4549
4640
  } else {
4550
4641
  NODE_TO_ELEMENT["delete"](editor);
4551
- EDITOR_TO_RESTORE_DOM["delete"](editor);
4552
4642
  }
4553
4643
 
4554
4644
  try {