slate-react 0.70.2 → 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) {
@@ -2489,9 +2536,12 @@
2489
2536
  }, attributes, {
2490
2537
  // COMPAT: Certain browsers don't support the `beforeinput` event, so we'd
2491
2538
  // have to use hacks to make these replacement-based features work.
2492
- spellCheck: !HAS_BEFORE_INPUT_SUPPORT ? false : attributes.spellCheck,
2493
- autoCorrect: !HAS_BEFORE_INPUT_SUPPORT ? 'false' : attributes.autoCorrect,
2494
- autoCapitalize: !HAS_BEFORE_INPUT_SUPPORT ? 'false' : attributes.autoCapitalize,
2539
+ // For SSR situations HAS_BEFORE_INPUT_SUPPORT is false and results in prop
2540
+ // mismatch warning app moves to browser. Pass-through consumer props when
2541
+ // not CAN_USE_DOM (SSR) and default to falsy value
2542
+ spellCheck: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.spellCheck : false,
2543
+ autoCorrect: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.autoCorrect : 'false',
2544
+ autoCapitalize: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.autoCapitalize : 'false',
2495
2545
  "data-slate-editor": true,
2496
2546
  "data-slate-node": "value",
2497
2547
  // explicitly set this
@@ -4175,19 +4225,6 @@
4175
4225
  return removedNodes.length > 0 && addedNodes.length === 0 && characterDataMutations.length > 0;
4176
4226
  };
4177
4227
 
4178
- function restoreDOM(editor) {
4179
- try {
4180
- var onRestoreDOM = EDITOR_TO_RESTORE_DOM.get(editor);
4181
-
4182
- if (onRestoreDOM) {
4183
- onRestoreDOM();
4184
- }
4185
- } catch (err) {
4186
- // eslint-disable-next-line no-console
4187
- console.error(err);
4188
- }
4189
- }
4190
-
4191
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; } } }; }
4192
4229
 
4193
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); }
@@ -4218,15 +4255,17 @@
4218
4255
  * - Line breaks
4219
4256
  *
4220
4257
  * @param editor
4258
+ * @param restoreDOM
4221
4259
  */
4222
4260
 
4223
4261
 
4224
- var AndroidInputManager = function AndroidInputManager(editor) {
4262
+ var AndroidInputManager = function AndroidInputManager(editor, restoreDOM) {
4225
4263
  var _this = this;
4226
4264
 
4227
4265
  _classCallCheck(this, AndroidInputManager);
4228
4266
 
4229
4267
  this.editor = editor;
4268
+ this.restoreDOM = restoreDOM;
4230
4269
  /**
4231
4270
  * Handle MutationObserver flush
4232
4271
  *
@@ -4241,7 +4280,7 @@
4241
4280
  // eslint-disable-next-line no-console
4242
4281
  console.error(err); // Failed to reconcile mutations, restore DOM to its previous state
4243
4282
 
4244
- restoreDOM(_this.editor);
4283
+ _this.restoreDOM();
4245
4284
  }
4246
4285
  };
4247
4286
  /**
@@ -4309,10 +4348,9 @@
4309
4348
 
4310
4349
  this.insertBreak = function () {
4311
4350
  var selection = _this.editor.selection;
4312
- slate.Editor.insertBreak(_this.editor); // To-do: Need a more granular solution to restoring only a specific portion
4313
- // of the document. Restoring the entire document is expensive.
4351
+ slate.Editor.insertBreak(_this.editor);
4314
4352
 
4315
- restoreDOM(_this.editor);
4353
+ _this.restoreDOM();
4316
4354
 
4317
4355
  if (selection) {
4318
4356
  // Compat: Move selection to the newly inserted block if it has not moved
@@ -4337,7 +4375,7 @@
4337
4375
  slate.Editor.insertText(_this.editor, text);
4338
4376
  }
4339
4377
 
4340
- restoreDOM(_this.editor);
4378
+ _this.restoreDOM();
4341
4379
  };
4342
4380
  /**
4343
4381
  * Handle `backspace` that merges blocks
@@ -4347,7 +4385,8 @@
4347
4385
  this.deleteBackward = function () {
4348
4386
  slate.Editor.deleteBackward(_this.editor);
4349
4387
  ReactEditor.focus(_this.editor);
4350
- restoreDOM(_this.editor);
4388
+
4389
+ _this.restoreDOM();
4351
4390
  };
4352
4391
  /**
4353
4392
  * Handle mutations that remove specific leaves
@@ -4368,7 +4407,8 @@
4368
4407
  slate.Transforms["delete"](_this.editor, {
4369
4408
  at: path
4370
4409
  });
4371
- restoreDOM(_this.editor);
4410
+
4411
+ _this.restoreDOM();
4372
4412
  }
4373
4413
  }
4374
4414
  } catch (err) {
@@ -4379,6 +4419,7 @@
4379
4419
  };
4380
4420
 
4381
4421
  this.editor = editor;
4422
+ this.restoreDOM = restoreDOM;
4382
4423
  };
4383
4424
 
4384
4425
  function useMutationObserver(node, callback, options) {
@@ -4404,6 +4445,72 @@
4404
4445
  });
4405
4446
  }
4406
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
+
4407
4514
  function useTrackUserInput() {
4408
4515
  var editor = useSlateStatic();
4409
4516
  var receivedUserInput = React.useRef(false);
@@ -4444,16 +4551,14 @@
4444
4551
  function useAndroidInputManager(node) {
4445
4552
  var editor = useSlateStatic();
4446
4553
 
4447
- var _useState = React.useState(function () {
4448
- return new AndroidInputManager(editor);
4449
- }),
4450
- _useState2 = _slicedToArray(_useState, 1),
4451
- inputManager = _useState2[0];
4452
-
4453
4554
  var _useTrackUserInput = useTrackUserInput(),
4454
4555
  receivedUserInput = _useTrackUserInput.receivedUserInput,
4455
4556
  onUserInput = _useTrackUserInput.onUserInput;
4456
4557
 
4558
+ var restoreDom = useRestoreDom(node, receivedUserInput);
4559
+ var inputManager = React.useMemo(function () {
4560
+ return new AndroidInputManager(editor, restoreDom);
4561
+ }, [restoreDom, editor]);
4457
4562
  var timeoutId = React.useRef(null);
4458
4563
  var isReconciling = React.useRef(false);
4459
4564
  var flush = React.useCallback(function (mutations) {
@@ -4521,17 +4626,7 @@
4521
4626
  latestElement: null
4522
4627
  };
4523
4628
  }, []);
4524
-
4525
- var _useState = React.useState(0),
4526
- _useState2 = _slicedToArray(_useState, 2),
4527
- contentKey = _useState2[0],
4528
- setContentKey = _useState2[1];
4529
-
4530
- var onRestoreDOM = React.useCallback(function () {
4531
- setContentKey(function (prev) {
4532
- return prev + 1;
4533
- });
4534
- }, [contentKey]); // Whenever the editor updates...
4629
+ var contentKey = useContentKey(editor); // Whenever the editor updates...
4535
4630
 
4536
4631
  useIsomorphicLayoutEffect(function () {
4537
4632
  // Update element-related weak maps with the DOM element ref.
@@ -4542,10 +4637,8 @@
4542
4637
  EDITOR_TO_ELEMENT.set(editor, ref.current);
4543
4638
  NODE_TO_ELEMENT.set(editor, ref.current);
4544
4639
  ELEMENT_TO_NODE.set(ref.current, editor);
4545
- EDITOR_TO_RESTORE_DOM.set(editor, onRestoreDOM);
4546
4640
  } else {
4547
4641
  NODE_TO_ELEMENT["delete"](editor);
4548
- EDITOR_TO_RESTORE_DOM["delete"](editor);
4549
4642
  }
4550
4643
 
4551
4644
  try {