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.
package/dist/index.js CHANGED
@@ -319,7 +319,7 @@ var IS_FOCUSED = new WeakMap();
319
319
  */
320
320
 
321
321
  var EDITOR_TO_ON_CHANGE = new WeakMap();
322
- var EDITOR_TO_RESTORE_DOM = new WeakMap();
322
+ var NODE_TO_RESTORE_DOM = new WeakMap();
323
323
  /**
324
324
  * Symbols.
325
325
  */
@@ -476,6 +476,42 @@ var isDecoratorRangeListEqual = function isDecoratorRangeListEqual(list, another
476
476
  return true;
477
477
  };
478
478
 
479
+ function useContentKey(node) {
480
+ var contentKeyRef = React.useRef(0);
481
+ var updateAnimationFrameRef = React.useRef(null);
482
+
483
+ var _useState = React.useState(0),
484
+ _useState2 = _slicedToArray(_useState, 2),
485
+ setForceRerenderCounter = _useState2[1];
486
+
487
+ React.useEffect(function () {
488
+ NODE_TO_RESTORE_DOM.set(node, function () {
489
+ // Update is already queued and node hasn't re-render yet
490
+ if (updateAnimationFrameRef.current) {
491
+ return;
492
+ }
493
+
494
+ updateAnimationFrameRef.current = requestAnimationFrame(function () {
495
+ setForceRerenderCounter(function (state) {
496
+ return state + 1;
497
+ });
498
+ updateAnimationFrameRef.current = null;
499
+ });
500
+ contentKeyRef.current++;
501
+ });
502
+ return function () {
503
+ NODE_TO_RESTORE_DOM["delete"](node);
504
+ };
505
+ }, [node]); // Node was restored => clear scheduled update
506
+
507
+ if (updateAnimationFrameRef.current) {
508
+ cancelAnimationFrame(updateAnimationFrameRef.current);
509
+ updateAnimationFrameRef.current = null;
510
+ }
511
+
512
+ return contentKeyRef.current;
513
+ }
514
+
479
515
  /**
480
516
  * Text.
481
517
  */
@@ -519,9 +555,11 @@ var Text = function Text(props) {
519
555
  NODE_TO_ELEMENT["delete"](text);
520
556
  }
521
557
  });
558
+ var contentKey = IS_ANDROID ? useContentKey(text) : undefined;
522
559
  return /*#__PURE__*/React__default['default'].createElement("span", {
523
560
  "data-slate-node": "text",
524
- ref: ref
561
+ ref: ref,
562
+ key: contentKey
525
563
  }, children);
526
564
  };
527
565
 
@@ -625,11 +663,20 @@ var Element = function Element(props) {
625
663
  NODE_TO_ELEMENT["delete"](element);
626
664
  }
627
665
  });
628
- return renderElement({
666
+ var content = renderElement({
629
667
  attributes: attributes,
630
668
  children: children,
631
669
  element: element
632
670
  });
671
+
672
+ if (IS_ANDROID) {
673
+ var contentKey = useContentKey(element);
674
+ return /*#__PURE__*/React__default['default'].createElement(React.Fragment, {
675
+ key: contentKey
676
+ }, content);
677
+ }
678
+
679
+ return content;
633
680
  };
634
681
 
635
682
  var MemoizedElement = /*#__PURE__*/React__default['default'].memo(Element, function (prev, next) {
@@ -1579,9 +1626,12 @@ var Editable$1 = function Editable(props) {
1579
1626
  }, attributes, {
1580
1627
  // COMPAT: Certain browsers don't support the `beforeinput` event, so we'd
1581
1628
  // have to use hacks to make these replacement-based features work.
1582
- spellCheck: !HAS_BEFORE_INPUT_SUPPORT ? false : attributes.spellCheck,
1583
- autoCorrect: !HAS_BEFORE_INPUT_SUPPORT ? 'false' : attributes.autoCorrect,
1584
- autoCapitalize: !HAS_BEFORE_INPUT_SUPPORT ? 'false' : attributes.autoCapitalize,
1629
+ // For SSR situations HAS_BEFORE_INPUT_SUPPORT is false and results in prop
1630
+ // mismatch warning app moves to browser. Pass-through consumer props when
1631
+ // not CAN_USE_DOM (SSR) and default to falsy value
1632
+ spellCheck: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.spellCheck : false,
1633
+ autoCorrect: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.autoCorrect : 'false',
1634
+ autoCapitalize: HAS_BEFORE_INPUT_SUPPORT || !CAN_USE_DOM ? attributes.autoCapitalize : 'false',
1585
1635
  "data-slate-editor": true,
1586
1636
  "data-slate-node": "value",
1587
1637
  // explicitly set this
@@ -3265,19 +3315,6 @@ var isRemoveLeafNodes = function isRemoveLeafNodes(_, _ref7) {
3265
3315
  return removedNodes.length > 0 && addedNodes.length === 0 && characterDataMutations.length > 0;
3266
3316
  };
3267
3317
 
3268
- function restoreDOM(editor) {
3269
- try {
3270
- var onRestoreDOM = EDITOR_TO_RESTORE_DOM.get(editor);
3271
-
3272
- if (onRestoreDOM) {
3273
- onRestoreDOM();
3274
- }
3275
- } catch (err) {
3276
- // eslint-disable-next-line no-console
3277
- console.error(err);
3278
- }
3279
- }
3280
-
3281
3318
  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; } } }; }
3282
3319
 
3283
3320
  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); }
@@ -3308,15 +3345,17 @@ function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) {
3308
3345
  * - Line breaks
3309
3346
  *
3310
3347
  * @param editor
3348
+ * @param restoreDOM
3311
3349
  */
3312
3350
 
3313
3351
 
3314
- var AndroidInputManager = function AndroidInputManager(editor) {
3352
+ var AndroidInputManager = function AndroidInputManager(editor, restoreDOM) {
3315
3353
  var _this = this;
3316
3354
 
3317
3355
  _classCallCheck(this, AndroidInputManager);
3318
3356
 
3319
3357
  this.editor = editor;
3358
+ this.restoreDOM = restoreDOM;
3320
3359
  /**
3321
3360
  * Handle MutationObserver flush
3322
3361
  *
@@ -3331,7 +3370,7 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3331
3370
  // eslint-disable-next-line no-console
3332
3371
  console.error(err); // Failed to reconcile mutations, restore DOM to its previous state
3333
3372
 
3334
- restoreDOM(_this.editor);
3373
+ _this.restoreDOM();
3335
3374
  }
3336
3375
  };
3337
3376
  /**
@@ -3399,10 +3438,9 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3399
3438
 
3400
3439
  this.insertBreak = function () {
3401
3440
  var selection = _this.editor.selection;
3402
- slate.Editor.insertBreak(_this.editor); // To-do: Need a more granular solution to restoring only a specific portion
3403
- // of the document. Restoring the entire document is expensive.
3441
+ slate.Editor.insertBreak(_this.editor);
3404
3442
 
3405
- restoreDOM(_this.editor);
3443
+ _this.restoreDOM();
3406
3444
 
3407
3445
  if (selection) {
3408
3446
  // Compat: Move selection to the newly inserted block if it has not moved
@@ -3427,7 +3465,7 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3427
3465
  slate.Editor.insertText(_this.editor, text);
3428
3466
  }
3429
3467
 
3430
- restoreDOM(_this.editor);
3468
+ _this.restoreDOM();
3431
3469
  };
3432
3470
  /**
3433
3471
  * Handle `backspace` that merges blocks
@@ -3437,7 +3475,8 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3437
3475
  this.deleteBackward = function () {
3438
3476
  slate.Editor.deleteBackward(_this.editor);
3439
3477
  ReactEditor.focus(_this.editor);
3440
- restoreDOM(_this.editor);
3478
+
3479
+ _this.restoreDOM();
3441
3480
  };
3442
3481
  /**
3443
3482
  * Handle mutations that remove specific leaves
@@ -3458,7 +3497,8 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3458
3497
  slate.Transforms["delete"](_this.editor, {
3459
3498
  at: path
3460
3499
  });
3461
- restoreDOM(_this.editor);
3500
+
3501
+ _this.restoreDOM();
3462
3502
  }
3463
3503
  }
3464
3504
  } catch (err) {
@@ -3469,6 +3509,7 @@ var AndroidInputManager = function AndroidInputManager(editor) {
3469
3509
  };
3470
3510
 
3471
3511
  this.editor = editor;
3512
+ this.restoreDOM = restoreDOM;
3472
3513
  };
3473
3514
 
3474
3515
  function useMutationObserver(node, callback, options) {
@@ -3494,6 +3535,72 @@ function useMutationObserver(node, callback, options) {
3494
3535
  });
3495
3536
  }
3496
3537
 
3538
+ var MUTATION_OBSERVER_CONFIG$1 = {
3539
+ childList: true,
3540
+ characterData: true,
3541
+ subtree: true
3542
+ };
3543
+
3544
+ function findClosestKnowSlateNode(domNode) {
3545
+ var _domEl;
3546
+
3547
+ var domEl = isDOMElement(domNode) ? domNode : domNode.parentElement;
3548
+
3549
+ if (domEl && !domEl.hasAttribute('data-slate-node')) {
3550
+ domEl = domEl.closest("[data-slate-node]");
3551
+ }
3552
+
3553
+ var slateNode = domEl && ELEMENT_TO_NODE.get(domEl);
3554
+
3555
+ if (slateNode) {
3556
+ return slateNode;
3557
+ } // Unknown dom element with a slate-slate-node attribute => the IME
3558
+ // most likely duplicated the node so we have to restore the parent
3559
+
3560
+
3561
+ return (_domEl = domEl) !== null && _domEl !== void 0 && _domEl.parentElement ? findClosestKnowSlateNode(domEl.parentElement) : null;
3562
+ }
3563
+
3564
+ function useRestoreDom(node, receivedUserInput) {
3565
+ var editor = useSlateStatic();
3566
+ var mutatedNodes = React.useRef(new Set());
3567
+ var handleDOMMutation = React.useCallback(function (mutations) {
3568
+ if (!receivedUserInput.current) {
3569
+ return;
3570
+ }
3571
+
3572
+ mutations.forEach(function (_ref) {
3573
+ var target = _ref.target;
3574
+ var slateNode = findClosestKnowSlateNode(target);
3575
+
3576
+ if (!slateNode) {
3577
+ return;
3578
+ }
3579
+
3580
+ return mutatedNodes.current.add(slateNode);
3581
+ });
3582
+ }, []);
3583
+ useMutationObserver(node, handleDOMMutation, MUTATION_OBSERVER_CONFIG$1); // Clear mutated nodes on every render
3584
+
3585
+ mutatedNodes.current.clear();
3586
+ var restore = React.useCallback(function () {
3587
+ var mutated = Array.from(mutatedNodes.current.values()); // Filter out child nodes of nodes that will be restored anyway
3588
+
3589
+ var nodesToRestore = mutated.filter(function (n) {
3590
+ return !mutated.some(function (m) {
3591
+ return slate.Path.isParent(ReactEditor.findPath(editor, m), ReactEditor.findPath(editor, n));
3592
+ });
3593
+ });
3594
+ nodesToRestore.forEach(function (n) {
3595
+ var _NODE_TO_RESTORE_DOM$;
3596
+
3597
+ (_NODE_TO_RESTORE_DOM$ = NODE_TO_RESTORE_DOM.get(n)) === null || _NODE_TO_RESTORE_DOM$ === void 0 ? void 0 : _NODE_TO_RESTORE_DOM$();
3598
+ });
3599
+ mutatedNodes.current.clear();
3600
+ }, []);
3601
+ return restore;
3602
+ }
3603
+
3497
3604
  function useTrackUserInput() {
3498
3605
  var editor = useSlateStatic();
3499
3606
  var receivedUserInput = React.useRef(false);
@@ -3534,16 +3641,14 @@ var MUTATION_OBSERVER_CONFIG = {
3534
3641
  function useAndroidInputManager(node) {
3535
3642
  var editor = useSlateStatic();
3536
3643
 
3537
- var _useState = React.useState(function () {
3538
- return new AndroidInputManager(editor);
3539
- }),
3540
- _useState2 = _slicedToArray(_useState, 1),
3541
- inputManager = _useState2[0];
3542
-
3543
3644
  var _useTrackUserInput = useTrackUserInput(),
3544
3645
  receivedUserInput = _useTrackUserInput.receivedUserInput,
3545
3646
  onUserInput = _useTrackUserInput.onUserInput;
3546
3647
 
3648
+ var restoreDom = useRestoreDom(node, receivedUserInput);
3649
+ var inputManager = React.useMemo(function () {
3650
+ return new AndroidInputManager(editor, restoreDom);
3651
+ }, [restoreDom, editor]);
3547
3652
  var timeoutId = React.useRef(null);
3548
3653
  var isReconciling = React.useRef(false);
3549
3654
  var flush = React.useCallback(function (mutations) {
@@ -3611,17 +3716,7 @@ var AndroidEditable = function AndroidEditable(props) {
3611
3716
  latestElement: null
3612
3717
  };
3613
3718
  }, []);
3614
-
3615
- var _useState = React.useState(0),
3616
- _useState2 = _slicedToArray(_useState, 2),
3617
- contentKey = _useState2[0],
3618
- setContentKey = _useState2[1];
3619
-
3620
- var onRestoreDOM = React.useCallback(function () {
3621
- setContentKey(function (prev) {
3622
- return prev + 1;
3623
- });
3624
- }, [contentKey]); // Whenever the editor updates...
3719
+ var contentKey = useContentKey(editor); // Whenever the editor updates...
3625
3720
 
3626
3721
  useIsomorphicLayoutEffect(function () {
3627
3722
  // Update element-related weak maps with the DOM element ref.
@@ -3632,10 +3727,8 @@ var AndroidEditable = function AndroidEditable(props) {
3632
3727
  EDITOR_TO_ELEMENT.set(editor, ref.current);
3633
3728
  NODE_TO_ELEMENT.set(editor, ref.current);
3634
3729
  ELEMENT_TO_NODE.set(ref.current, editor);
3635
- EDITOR_TO_RESTORE_DOM.set(editor, onRestoreDOM);
3636
3730
  } else {
3637
3731
  NODE_TO_ELEMENT["delete"](editor);
3638
- EDITOR_TO_RESTORE_DOM["delete"](editor);
3639
3732
  }
3640
3733
 
3641
3734
  try {