slate-react 0.115.0 → 0.116.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/chunking/children-helper.d.ts +61 -0
- package/dist/chunking/children-helper.d.ts.map +1 -0
- package/dist/chunking/chunk-tree-helper.d.ts +160 -0
- package/dist/chunking/chunk-tree-helper.d.ts.map +1 -0
- package/dist/chunking/get-chunk-tree-for-node.d.ts +16 -0
- package/dist/chunking/get-chunk-tree-for-node.d.ts.map +1 -0
- package/dist/chunking/index.d.ts +3 -0
- package/dist/chunking/index.d.ts.map +1 -0
- package/dist/chunking/reconcile-children.d.ts +19 -0
- package/dist/chunking/reconcile-children.d.ts.map +1 -0
- package/dist/chunking/types.d.ts +44 -0
- package/dist/chunking/types.d.ts.map +1 -0
- package/dist/components/chunk-tree.d.ts +13 -0
- package/dist/components/chunk-tree.d.ts.map +1 -0
- package/dist/components/editable.d.ts +13 -0
- package/dist/components/editable.d.ts.map +1 -1
- package/dist/components/element.d.ts +4 -4
- package/dist/components/element.d.ts.map +1 -1
- package/dist/components/leaf.d.ts.map +1 -1
- package/dist/components/slate.d.ts.map +1 -1
- package/dist/components/text.d.ts +1 -1
- package/dist/components/text.d.ts.map +1 -1
- package/dist/hooks/use-children.d.ts +4 -4
- package/dist/hooks/use-children.d.ts.map +1 -1
- package/dist/hooks/use-decorations.d.ts +18 -0
- package/dist/hooks/use-decorations.d.ts.map +1 -0
- package/dist/hooks/use-element.d.ts +12 -0
- package/dist/hooks/use-element.d.ts.map +1 -0
- package/dist/hooks/use-generic-selector.d.ts +20 -0
- package/dist/hooks/use-generic-selector.d.ts.map +1 -0
- package/dist/hooks/use-selected.d.ts +0 -5
- package/dist/hooks/use-selected.d.ts.map +1 -1
- package/dist/hooks/use-slate-selector.d.ts +30 -15
- package/dist/hooks/use-slate-selector.d.ts.map +1 -1
- package/dist/hooks/use-slate.d.ts +7 -14
- package/dist/hooks/use-slate.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +1154 -232
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1328 -343
- package/dist/index.js.map +1 -1
- package/dist/plugin/react-editor.d.ts +7 -0
- package/dist/plugin/react-editor.d.ts.map +1 -1
- package/dist/plugin/with-react.d.ts.map +1 -1
- package/dist/slate-react.js +1385 -346
- package/dist/slate-react.min.js +1 -1
- package/package.json +5 -4
- package/dist/hooks/use-decorate.d.ts +0 -11
- package/dist/hooks/use-decorate.d.ts.map +0 -1
package/dist/index.es.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import getDirection from 'direction';
|
|
2
2
|
import debounce from 'lodash/debounce';
|
|
3
3
|
import throttle from 'lodash/throttle';
|
|
4
|
-
import React, { createContext, useContext, useRef, useEffect, useLayoutEffect, useState, memo, forwardRef, useCallback,
|
|
4
|
+
import React, { createContext, useContext, 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 { Editor, Range, Transforms, Node, Text as Text$1, Path, Point, Element as Element$1, Scrubber } from 'slate';
|
|
7
|
-
import { DOMEditor, EDITOR_TO_USER_MARKS, EDITOR_TO_PENDING_DIFFS, EDITOR_TO_PENDING_ACTION, EDITOR_TO_PENDING_INSERTION_MARKS, targetRange, verifyDiffState, EDITOR_TO_PENDING_SELECTION, IS_COMPOSING, IS_NODE_MAP_DIRTY, applyStringDiff, isDOMSelection, isTrackedMutation, EDITOR_TO_FORCE_RENDER, normalizeRange, normalizePoint, EDITOR_TO_PLACEHOLDER_ELEMENT, normalizeStringDiff, mergeStringDiffs, CAN_USE_DOM, IS_ANDROID, EDITOR_TO_SCHEDULE_FLUSH, MARK_PLACEHOLDER_SYMBOL, PLACEHOLDER_SYMBOL, IS_WEBKIT, isTextDecorationsEqual, EDITOR_TO_KEY_TO_ELEMENT, NODE_TO_ELEMENT, ELEMENT_TO_NODE,
|
|
7
|
+
import { DOMEditor, EDITOR_TO_USER_MARKS, EDITOR_TO_PENDING_DIFFS, EDITOR_TO_PENDING_ACTION, EDITOR_TO_PENDING_INSERTION_MARKS, targetRange, verifyDiffState, EDITOR_TO_PENDING_SELECTION, IS_COMPOSING, IS_NODE_MAP_DIRTY, applyStringDiff, isDOMSelection, isTrackedMutation, EDITOR_TO_FORCE_RENDER, normalizeRange, normalizePoint, EDITOR_TO_PLACEHOLDER_ELEMENT, normalizeStringDiff, mergeStringDiffs, 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, EDITOR_TO_USER_SELECTION, HAS_BEFORE_INPUT_SUPPORT, isDOMElement, isDOMNode, TRIPLE_CLICK, IS_FIREFOX_LEGACY, IS_IOS, IS_WECHATBROWSER, IS_UC_MOBILE, Hotkeys, IS_CHROME, isPlainTextOnlyPaste, EDITOR_TO_ON_CHANGE, withDOM } from 'slate-dom';
|
|
8
8
|
export { NODE_TO_INDEX, NODE_TO_PARENT } from 'slate-dom';
|
|
9
9
|
import { ResizeObserver } from '@juggle/resize-observer';
|
|
10
10
|
import ReactDOM from 'react-dom';
|
|
@@ -97,8 +97,8 @@ var useSlateStatic = () => {
|
|
|
97
97
|
// eslint-disable-next-line no-redeclare
|
|
98
98
|
var ReactEditor = DOMEditor;
|
|
99
99
|
|
|
100
|
-
function ownKeys$
|
|
101
|
-
function _objectSpread$
|
|
100
|
+
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; }
|
|
101
|
+
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), !0).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; }
|
|
102
102
|
// https://github.com/facebook/draft-js/blob/main/src/component/handlers/composition/DraftEditorCompositionHandler.js#L41
|
|
103
103
|
// When using keyboard English association function, conpositionEnd triggered too fast, resulting in after `insertText` still maintain association state.
|
|
104
104
|
var RESOLVE_DELAY = 25;
|
|
@@ -294,7 +294,7 @@ function createAndroidInputManager(_ref) {
|
|
|
294
294
|
updatePlaceholderVisibility();
|
|
295
295
|
return;
|
|
296
296
|
}
|
|
297
|
-
pendingDiffs[idx] = _objectSpread$
|
|
297
|
+
pendingDiffs[idx] = _objectSpread$7(_objectSpread$7({}, pendingDiffs[idx]), {}, {
|
|
298
298
|
diff: merged
|
|
299
299
|
});
|
|
300
300
|
};
|
|
@@ -612,7 +612,7 @@ function createAndroidInputManager(_ref) {
|
|
|
612
612
|
if (insertPositionHint === null) {
|
|
613
613
|
insertPositionHint = _diff;
|
|
614
614
|
} else if (insertPositionHint && Range.isCollapsed(targetRange) && insertPositionHint.end + insertPositionHint.text.length === _start2.offset) {
|
|
615
|
-
insertPositionHint = _objectSpread$
|
|
615
|
+
insertPositionHint = _objectSpread$7(_objectSpread$7({}, insertPositionHint), {}, {
|
|
616
616
|
text: insertPositionHint.text + _text
|
|
617
617
|
});
|
|
618
618
|
} else {
|
|
@@ -748,8 +748,8 @@ function useMutationObserver(node, callback, options) {
|
|
|
748
748
|
}
|
|
749
749
|
|
|
750
750
|
var _excluded$2 = ["node"];
|
|
751
|
-
function ownKeys$
|
|
752
|
-
function _objectSpread$
|
|
751
|
+
function ownKeys$6(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; }
|
|
752
|
+
function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$6(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
753
753
|
var MUTATION_OBSERVER_CONFIG$1 = {
|
|
754
754
|
subtree: true,
|
|
755
755
|
childList: true,
|
|
@@ -765,7 +765,7 @@ var useAndroidInputManager = !IS_ANDROID ? () => null : _ref => {
|
|
|
765
765
|
}
|
|
766
766
|
var editor = useSlateStatic();
|
|
767
767
|
var isMounted = useIsMounted();
|
|
768
|
-
var [inputManager] = useState(() => createAndroidInputManager(_objectSpread$
|
|
768
|
+
var [inputManager] = useState(() => createAndroidInputManager(_objectSpread$6({
|
|
769
769
|
editor
|
|
770
770
|
}, options)));
|
|
771
771
|
useMutationObserver(node, inputManager.handleDomMutations, MUTATION_OBSERVER_CONFIG$1);
|
|
@@ -776,8 +776,8 @@ var useAndroidInputManager = !IS_ANDROID ? () => null : _ref => {
|
|
|
776
776
|
return inputManager;
|
|
777
777
|
};
|
|
778
778
|
|
|
779
|
-
function ownKeys$
|
|
780
|
-
function _objectSpread$
|
|
779
|
+
function ownKeys$5(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; }
|
|
780
|
+
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), !0).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; }
|
|
781
781
|
/**
|
|
782
782
|
* Leaf content strings.
|
|
783
783
|
*/
|
|
@@ -894,11 +894,11 @@ var ZeroWidthString = props => {
|
|
|
894
894
|
// be because accepting an IME suggestion when at the start of a block (no
|
|
895
895
|
// preceding \uFEFF) removes one or more DOM elements that `toSlateRange`
|
|
896
896
|
// depends on. (https://github.com/ianstormtaylor/slate/issues/5703)
|
|
897
|
-
return /*#__PURE__*/React.createElement("span", _objectSpread$
|
|
897
|
+
return /*#__PURE__*/React.createElement("span", _objectSpread$5({}, attributes), !IS_ANDROID || !isLineBreak ? '\uFEFF' : null, isLineBreak ? /*#__PURE__*/React.createElement("br", null) : null);
|
|
898
898
|
};
|
|
899
899
|
|
|
900
|
-
function ownKeys$
|
|
901
|
-
function _objectSpread$
|
|
900
|
+
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; }
|
|
901
|
+
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), !0).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; }
|
|
902
902
|
// Delay the placeholder on Android to prevent the keyboard from closing.
|
|
903
903
|
// (https://github.com/ianstormtaylor/slate/pull/5368)
|
|
904
904
|
var PLACEHOLDER_DELAY = IS_ANDROID ? 300 : 0;
|
|
@@ -916,6 +916,7 @@ function clearTimeoutRef(timeoutRef) {
|
|
|
916
916
|
timeoutRef.current = null;
|
|
917
917
|
}
|
|
918
918
|
}
|
|
919
|
+
var defaultRenderLeaf = props => /*#__PURE__*/React.createElement(DefaultLeaf, _objectSpread$4({}, props));
|
|
919
920
|
/**
|
|
920
921
|
* Individual leaves in a text node with unique formatting.
|
|
921
922
|
*/
|
|
@@ -926,7 +927,7 @@ var Leaf = props => {
|
|
|
926
927
|
text,
|
|
927
928
|
parent,
|
|
928
929
|
renderPlaceholder,
|
|
929
|
-
renderLeaf =
|
|
930
|
+
renderLeaf = defaultRenderLeaf,
|
|
930
931
|
leafPosition
|
|
931
932
|
} = props;
|
|
932
933
|
var editor = useSlateStatic();
|
|
@@ -1022,26 +1023,145 @@ var DefaultLeaf = props => {
|
|
|
1022
1023
|
attributes,
|
|
1023
1024
|
children
|
|
1024
1025
|
} = props;
|
|
1025
|
-
return /*#__PURE__*/React.createElement("span", _objectSpread$
|
|
1026
|
+
return /*#__PURE__*/React.createElement("span", _objectSpread$4({}, attributes), children);
|
|
1026
1027
|
};
|
|
1027
1028
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1029
|
+
/**
|
|
1030
|
+
* Create a selector that updates when an `update` function is called, and
|
|
1031
|
+
* which only causes the component to render when the result of `selector`
|
|
1032
|
+
* differs from the previous result according to `equalityFn`.
|
|
1033
|
+
*
|
|
1034
|
+
* If `selector` is memoized using `useCallback`, then it will only be called
|
|
1035
|
+
* when it changes or when `update` is called. Otherwise, `selector` will be
|
|
1036
|
+
* called every time the component renders.
|
|
1037
|
+
*
|
|
1038
|
+
* @example
|
|
1039
|
+
* const [state, update] = useGenericSelector(selector, equalityFn)
|
|
1040
|
+
*
|
|
1041
|
+
* useIsomorphicLayoutEffect(() => {
|
|
1042
|
+
* return addEventListener(update)
|
|
1043
|
+
* }, [addEventListener, update])
|
|
1044
|
+
*
|
|
1045
|
+
* return state
|
|
1046
|
+
*/
|
|
1047
|
+
function useGenericSelector(selector, equalityFn) {
|
|
1048
|
+
var [, forceRender] = useReducer(s => s + 1, 0);
|
|
1049
|
+
var latestSubscriptionCallbackError = useRef();
|
|
1050
|
+
var latestSelector = useRef(() => null);
|
|
1051
|
+
var latestSelectedState = useRef(null);
|
|
1052
|
+
var selectedState;
|
|
1053
|
+
try {
|
|
1054
|
+
if (selector !== latestSelector.current || latestSubscriptionCallbackError.current) {
|
|
1055
|
+
var selectorResult = selector();
|
|
1056
|
+
if (equalityFn(latestSelectedState.current, selectorResult)) {
|
|
1057
|
+
selectedState = latestSelectedState.current;
|
|
1058
|
+
} else {
|
|
1059
|
+
selectedState = selectorResult;
|
|
1060
|
+
}
|
|
1061
|
+
} else {
|
|
1062
|
+
selectedState = latestSelectedState.current;
|
|
1063
|
+
}
|
|
1064
|
+
} catch (err) {
|
|
1065
|
+
if (latestSubscriptionCallbackError.current && isError(err)) {
|
|
1066
|
+
err.message += "\nThe error may be correlated with this previous error:\n".concat(latestSubscriptionCallbackError.current.stack, "\n\n");
|
|
1067
|
+
}
|
|
1068
|
+
throw err;
|
|
1069
|
+
}
|
|
1070
|
+
latestSelector.current = selector;
|
|
1071
|
+
latestSelectedState.current = selectedState;
|
|
1072
|
+
latestSubscriptionCallbackError.current = undefined;
|
|
1073
|
+
var update = useCallback(() => {
|
|
1074
|
+
try {
|
|
1075
|
+
var newSelectedState = latestSelector.current();
|
|
1076
|
+
if (equalityFn(latestSelectedState.current, newSelectedState)) {
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
latestSelectedState.current = newSelectedState;
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
// we ignore all errors here, since when the component
|
|
1082
|
+
// is re-rendered, the selectors are called again, and
|
|
1083
|
+
// will throw again, if neither props nor store state
|
|
1084
|
+
// changed
|
|
1085
|
+
if (err instanceof Error) {
|
|
1086
|
+
latestSubscriptionCallbackError.current = err;
|
|
1087
|
+
} else {
|
|
1088
|
+
latestSubscriptionCallbackError.current = new Error(String(err));
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
forceRender();
|
|
1092
|
+
// don't rerender on equalityFn change since we want to be able to define it inline
|
|
1093
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1094
|
+
}, []);
|
|
1095
|
+
return [selectedState, update];
|
|
1096
|
+
}
|
|
1097
|
+
function isError(error) {
|
|
1098
|
+
return error instanceof Error;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* A React context for sharing the `decorate` prop of the editable and
|
|
1103
|
+
* subscribing to changes on this prop.
|
|
1104
|
+
*/
|
|
1105
|
+
var DecorateContext = /*#__PURE__*/createContext({});
|
|
1106
|
+
var useDecorations = (node, parentDecorations) => {
|
|
1107
|
+
var editor = useSlateStatic();
|
|
1108
|
+
var {
|
|
1109
|
+
decorate,
|
|
1110
|
+
addEventListener
|
|
1111
|
+
} = useContext(DecorateContext);
|
|
1112
|
+
// Not memoized since we want nodes to be decorated on each render
|
|
1113
|
+
var selector = () => {
|
|
1114
|
+
var path = ReactEditor.findPath(editor, node);
|
|
1115
|
+
return decorate([node, path]);
|
|
1116
|
+
};
|
|
1117
|
+
var equalityFn = Text$1.isText(node) ? isTextDecorationsEqual : isElementDecorationsEqual;
|
|
1118
|
+
var [decorations, update] = useGenericSelector(selector, equalityFn);
|
|
1119
|
+
useIsomorphicLayoutEffect(() => {
|
|
1120
|
+
var unsubscribe = addEventListener(update);
|
|
1121
|
+
update();
|
|
1122
|
+
return unsubscribe;
|
|
1123
|
+
}, [addEventListener, update]);
|
|
1124
|
+
return useMemo(() => [...decorations, ...parentDecorations], [decorations, parentDecorations]);
|
|
1125
|
+
};
|
|
1126
|
+
var useDecorateContext = decorateProp => {
|
|
1127
|
+
var eventListeners = useRef(new Set());
|
|
1128
|
+
var latestDecorate = useRef(decorateProp);
|
|
1129
|
+
useIsomorphicLayoutEffect(() => {
|
|
1130
|
+
latestDecorate.current = decorateProp;
|
|
1131
|
+
eventListeners.current.forEach(listener => listener());
|
|
1132
|
+
}, [decorateProp]);
|
|
1133
|
+
var decorate = useCallback(entry => latestDecorate.current(entry), []);
|
|
1134
|
+
var addEventListener = useCallback(callback => {
|
|
1135
|
+
eventListeners.current.add(callback);
|
|
1136
|
+
return () => {
|
|
1137
|
+
eventListeners.current.delete(callback);
|
|
1138
|
+
};
|
|
1139
|
+
}, []);
|
|
1140
|
+
return useMemo(() => ({
|
|
1141
|
+
decorate,
|
|
1142
|
+
addEventListener
|
|
1143
|
+
}), [decorate, addEventListener]);
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
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; }
|
|
1147
|
+
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), !0).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; }
|
|
1148
|
+
var defaultRenderText = props => /*#__PURE__*/React.createElement(DefaultText, _objectSpread$3({}, props));
|
|
1030
1149
|
/**
|
|
1031
1150
|
* Text.
|
|
1032
1151
|
*/
|
|
1033
1152
|
var Text = props => {
|
|
1034
1153
|
var {
|
|
1035
|
-
decorations,
|
|
1154
|
+
decorations: parentDecorations,
|
|
1036
1155
|
isLast,
|
|
1037
1156
|
parent,
|
|
1038
1157
|
renderPlaceholder,
|
|
1039
1158
|
renderLeaf,
|
|
1040
|
-
renderText =
|
|
1159
|
+
renderText = defaultRenderText,
|
|
1041
1160
|
text
|
|
1042
1161
|
} = props;
|
|
1043
1162
|
var editor = useSlateStatic();
|
|
1044
1163
|
var ref = useRef(null);
|
|
1164
|
+
var decorations = useDecorations(text, parentDecorations);
|
|
1045
1165
|
var decoratedLeaves = Text$1.decorations(text, decorations);
|
|
1046
1166
|
var key = ReactEditor.findKey(editor, text);
|
|
1047
1167
|
var children = [];
|
|
@@ -1095,27 +1215,29 @@ var DefaultText = props => {
|
|
|
1095
1215
|
attributes,
|
|
1096
1216
|
children
|
|
1097
1217
|
} = props;
|
|
1098
|
-
return /*#__PURE__*/React.createElement("span", _objectSpread$
|
|
1218
|
+
return /*#__PURE__*/React.createElement("span", _objectSpread$3({}, attributes), children);
|
|
1099
1219
|
};
|
|
1100
1220
|
|
|
1101
|
-
function ownKeys$
|
|
1102
|
-
function _objectSpread$
|
|
1221
|
+
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; }
|
|
1222
|
+
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), !0).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; }
|
|
1223
|
+
var defaultRenderElement = props => /*#__PURE__*/React.createElement(DefaultElement, _objectSpread$2({}, props));
|
|
1103
1224
|
/**
|
|
1104
1225
|
* Element.
|
|
1105
1226
|
*/
|
|
1106
1227
|
var Element = props => {
|
|
1107
1228
|
var {
|
|
1108
|
-
decorations,
|
|
1229
|
+
decorations: parentDecorations,
|
|
1109
1230
|
element,
|
|
1110
|
-
renderElement =
|
|
1231
|
+
renderElement = defaultRenderElement,
|
|
1232
|
+
renderChunk,
|
|
1111
1233
|
renderPlaceholder,
|
|
1112
1234
|
renderLeaf,
|
|
1113
|
-
renderText
|
|
1114
|
-
selection
|
|
1235
|
+
renderText
|
|
1115
1236
|
} = props;
|
|
1116
1237
|
var editor = useSlateStatic();
|
|
1117
1238
|
var readOnly = useReadOnly();
|
|
1118
1239
|
var isInline = editor.isInline(element);
|
|
1240
|
+
var decorations = useDecorations(element, parentDecorations);
|
|
1119
1241
|
var key = ReactEditor.findKey(editor, element);
|
|
1120
1242
|
var ref = useCallback(ref => {
|
|
1121
1243
|
// Update element-related weak maps with the DOM element ref.
|
|
@@ -1133,10 +1255,10 @@ var Element = props => {
|
|
|
1133
1255
|
decorations,
|
|
1134
1256
|
node: element,
|
|
1135
1257
|
renderElement,
|
|
1258
|
+
renderChunk,
|
|
1136
1259
|
renderPlaceholder,
|
|
1137
1260
|
renderLeaf,
|
|
1138
|
-
renderText
|
|
1139
|
-
selection
|
|
1261
|
+
renderText
|
|
1140
1262
|
});
|
|
1141
1263
|
// Attributes that the developer must mix into the element in their
|
|
1142
1264
|
// custom node renderer component.
|
|
@@ -1189,7 +1311,7 @@ var Element = props => {
|
|
|
1189
1311
|
});
|
|
1190
1312
|
};
|
|
1191
1313
|
var MemoizedElement = /*#__PURE__*/React.memo(Element, (prev, next) => {
|
|
1192
|
-
return prev.element === next.element && prev.renderElement === next.renderElement && prev.
|
|
1314
|
+
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);
|
|
1193
1315
|
});
|
|
1194
1316
|
/**
|
|
1195
1317
|
* The default element renderer.
|
|
@@ -1202,7 +1324,7 @@ var DefaultElement = props => {
|
|
|
1202
1324
|
} = props;
|
|
1203
1325
|
var editor = useSlateStatic();
|
|
1204
1326
|
var Tag = editor.isInline(element) ? 'span' : 'div';
|
|
1205
|
-
return /*#__PURE__*/React.createElement(Tag, _objectSpread$
|
|
1327
|
+
return /*#__PURE__*/React.createElement(Tag, _objectSpread$2(_objectSpread$2({}, attributes), {}, {
|
|
1206
1328
|
style: {
|
|
1207
1329
|
position: 'relative'
|
|
1208
1330
|
}
|
|
@@ -1210,26 +1332,732 @@ var DefaultElement = props => {
|
|
|
1210
1332
|
};
|
|
1211
1333
|
|
|
1212
1334
|
/**
|
|
1213
|
-
*
|
|
1335
|
+
* Traverse and modify a chunk tree
|
|
1336
|
+
*/
|
|
1337
|
+
class ChunkTreeHelper {
|
|
1338
|
+
constructor(chunkTree, _ref) {
|
|
1339
|
+
var {
|
|
1340
|
+
chunkSize,
|
|
1341
|
+
debug
|
|
1342
|
+
} = _ref;
|
|
1343
|
+
/**
|
|
1344
|
+
* The root of the chunk tree
|
|
1345
|
+
*/
|
|
1346
|
+
_defineProperty(this, "root", void 0);
|
|
1347
|
+
/**
|
|
1348
|
+
* The ideal size of a chunk
|
|
1349
|
+
*/
|
|
1350
|
+
_defineProperty(this, "chunkSize", void 0);
|
|
1351
|
+
/**
|
|
1352
|
+
* Whether debug mode is enabled
|
|
1353
|
+
*
|
|
1354
|
+
* If enabled, the pointer state will be checked for internal consistency
|
|
1355
|
+
* after each mutating operation.
|
|
1356
|
+
*/
|
|
1357
|
+
_defineProperty(this, "debug", void 0);
|
|
1358
|
+
/**
|
|
1359
|
+
* Whether the traversal has reached the end of the chunk tree
|
|
1360
|
+
*
|
|
1361
|
+
* When this is true, the pointerChunk and pointerIndex point to the last
|
|
1362
|
+
* top-level node in the chunk tree, although pointerNode returns null.
|
|
1363
|
+
*/
|
|
1364
|
+
_defineProperty(this, "reachedEnd", void 0);
|
|
1365
|
+
/**
|
|
1366
|
+
* The chunk containing the current node
|
|
1367
|
+
*/
|
|
1368
|
+
_defineProperty(this, "pointerChunk", void 0);
|
|
1369
|
+
/**
|
|
1370
|
+
* The index of the current node within pointerChunk
|
|
1371
|
+
*
|
|
1372
|
+
* Can be -1 to indicate that the pointer is before the start of the tree.
|
|
1373
|
+
*/
|
|
1374
|
+
_defineProperty(this, "pointerIndex", void 0);
|
|
1375
|
+
/**
|
|
1376
|
+
* Similar to a Slate path; tracks the path of pointerChunk relative to the
|
|
1377
|
+
* root.
|
|
1378
|
+
*
|
|
1379
|
+
* Used to move the pointer from the current chunk to the parent chunk more
|
|
1380
|
+
* efficiently.
|
|
1381
|
+
*/
|
|
1382
|
+
_defineProperty(this, "pointerIndexStack", void 0);
|
|
1383
|
+
/**
|
|
1384
|
+
* Indexing the current chunk's children has a slight time cost, which adds up
|
|
1385
|
+
* when traversing very large trees, so the current node is cached.
|
|
1386
|
+
*
|
|
1387
|
+
* A value of undefined means that the current node is not cached. This
|
|
1388
|
+
* property must be set to undefined whenever the pointer is moved, unless
|
|
1389
|
+
* the pointer is guaranteed to point to the same node that it did previously.
|
|
1390
|
+
*/
|
|
1391
|
+
_defineProperty(this, "cachedPointerNode", void 0);
|
|
1392
|
+
this.root = chunkTree;
|
|
1393
|
+
this.chunkSize = chunkSize;
|
|
1394
|
+
// istanbul ignore next
|
|
1395
|
+
this.debug = debug !== null && debug !== void 0 ? debug : false;
|
|
1396
|
+
this.pointerChunk = chunkTree;
|
|
1397
|
+
this.pointerIndex = -1;
|
|
1398
|
+
this.pointerIndexStack = [];
|
|
1399
|
+
this.reachedEnd = false;
|
|
1400
|
+
this.validateState();
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Move the pointer to the next leaf in the chunk tree
|
|
1404
|
+
*/
|
|
1405
|
+
readLeaf() {
|
|
1406
|
+
// istanbul ignore next
|
|
1407
|
+
if (this.reachedEnd) return null;
|
|
1408
|
+
// Get the next sibling or aunt node
|
|
1409
|
+
while (true) {
|
|
1410
|
+
if (this.pointerIndex + 1 < this.pointerSiblings.length) {
|
|
1411
|
+
this.pointerIndex++;
|
|
1412
|
+
this.cachedPointerNode = undefined;
|
|
1413
|
+
break;
|
|
1414
|
+
} else if (this.pointerChunk.type === 'root') {
|
|
1415
|
+
this.reachedEnd = true;
|
|
1416
|
+
return null;
|
|
1417
|
+
} else {
|
|
1418
|
+
this.exitChunk();
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
this.validateState();
|
|
1422
|
+
// If the next sibling or aunt is a chunk, descend into it
|
|
1423
|
+
this.enterChunkUntilLeaf(false);
|
|
1424
|
+
return this.pointerNode;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Move the pointer to the previous leaf in the chunk tree
|
|
1428
|
+
*/
|
|
1429
|
+
returnToPreviousLeaf() {
|
|
1430
|
+
// If we were at the end of the tree, descend into the end of the last
|
|
1431
|
+
// chunk in the tree
|
|
1432
|
+
if (this.reachedEnd) {
|
|
1433
|
+
this.reachedEnd = false;
|
|
1434
|
+
this.enterChunkUntilLeaf(true);
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
// Get the previous sibling or aunt node
|
|
1438
|
+
while (true) {
|
|
1439
|
+
if (this.pointerIndex >= 1) {
|
|
1440
|
+
this.pointerIndex--;
|
|
1441
|
+
this.cachedPointerNode = undefined;
|
|
1442
|
+
break;
|
|
1443
|
+
} else if (this.pointerChunk.type === 'root') {
|
|
1444
|
+
this.pointerIndex = -1;
|
|
1445
|
+
return;
|
|
1446
|
+
} else {
|
|
1447
|
+
this.exitChunk();
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
this.validateState();
|
|
1451
|
+
// If the previous sibling or aunt is a chunk, descend into it
|
|
1452
|
+
this.enterChunkUntilLeaf(true);
|
|
1453
|
+
}
|
|
1454
|
+
/**
|
|
1455
|
+
* Insert leaves before the current leaf, leaving the pointer unchanged
|
|
1456
|
+
*/
|
|
1457
|
+
insertBefore(leaves) {
|
|
1458
|
+
this.returnToPreviousLeaf();
|
|
1459
|
+
this.insertAfter(leaves);
|
|
1460
|
+
this.readLeaf();
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Insert leaves after the current leaf, leaving the pointer on the last
|
|
1464
|
+
* inserted leaf
|
|
1465
|
+
*
|
|
1466
|
+
* The insertion algorithm first checks for any chunk we're currently at the
|
|
1467
|
+
* end of that can receive additional leaves. Next, it tries to insert leaves
|
|
1468
|
+
* at the starts of any subsequent chunks.
|
|
1469
|
+
*
|
|
1470
|
+
* Any remaining leaves are passed to rawInsertAfter to be chunked and
|
|
1471
|
+
* inserted at the highest possible level.
|
|
1472
|
+
*/
|
|
1473
|
+
insertAfter(leaves) {
|
|
1474
|
+
// istanbul ignore next
|
|
1475
|
+
if (leaves.length === 0) return;
|
|
1476
|
+
var beforeDepth = 0;
|
|
1477
|
+
var afterDepth = 0;
|
|
1478
|
+
// While at the end of a chunk, insert any leaves that will fit, and then
|
|
1479
|
+
// exit the chunk
|
|
1480
|
+
while (this.pointerChunk.type === 'chunk' && this.pointerIndex === this.pointerSiblings.length - 1) {
|
|
1481
|
+
var remainingCapacity = this.chunkSize - this.pointerSiblings.length;
|
|
1482
|
+
var toInsertCount = Math.min(remainingCapacity, leaves.length);
|
|
1483
|
+
if (toInsertCount > 0) {
|
|
1484
|
+
var leavesToInsert = leaves.splice(0, toInsertCount);
|
|
1485
|
+
this.rawInsertAfter(leavesToInsert, beforeDepth);
|
|
1486
|
+
}
|
|
1487
|
+
this.exitChunk();
|
|
1488
|
+
beforeDepth++;
|
|
1489
|
+
}
|
|
1490
|
+
if (leaves.length === 0) return;
|
|
1491
|
+
// Save the pointer so that we can come back here after inserting leaves
|
|
1492
|
+
// into the starts of subsequent blocks
|
|
1493
|
+
var rawInsertPointer = this.savePointer();
|
|
1494
|
+
// If leaves are inserted into the start of a subsequent block, then we
|
|
1495
|
+
// eventually need to restore the pointer to the last such inserted leaf
|
|
1496
|
+
var finalPointer = null;
|
|
1497
|
+
// Move the pointer into the chunk containing the next leaf, if it exists
|
|
1498
|
+
if (this.readLeaf()) {
|
|
1499
|
+
// While at the start of a chunk, insert any leaves that will fit, and
|
|
1500
|
+
// then exit the chunk
|
|
1501
|
+
while (this.pointerChunk.type === 'chunk' && this.pointerIndex === 0) {
|
|
1502
|
+
var _remainingCapacity = this.chunkSize - this.pointerSiblings.length;
|
|
1503
|
+
var _toInsertCount = Math.min(_remainingCapacity, leaves.length);
|
|
1504
|
+
if (_toInsertCount > 0) {
|
|
1505
|
+
var _leavesToInsert = leaves.splice(-_toInsertCount, _toInsertCount);
|
|
1506
|
+
// Insert the leaves at the start of the chunk
|
|
1507
|
+
this.pointerIndex = -1;
|
|
1508
|
+
this.cachedPointerNode = undefined;
|
|
1509
|
+
this.rawInsertAfter(_leavesToInsert, afterDepth);
|
|
1510
|
+
// If this is the first batch of insertions at the start of a
|
|
1511
|
+
// subsequent chunk, set the final pointer to the last inserted leaf
|
|
1512
|
+
if (!finalPointer) {
|
|
1513
|
+
finalPointer = this.savePointer();
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
this.exitChunk();
|
|
1517
|
+
afterDepth++;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
this.restorePointer(rawInsertPointer);
|
|
1521
|
+
// If there are leaves left to insert, insert them between the end of the
|
|
1522
|
+
// previous chunk and the start of the first subsequent chunk, or wherever
|
|
1523
|
+
// the pointer ended up after the first batch of insertions
|
|
1524
|
+
var minDepth = Math.max(beforeDepth, afterDepth);
|
|
1525
|
+
this.rawInsertAfter(leaves, minDepth);
|
|
1526
|
+
if (finalPointer) {
|
|
1527
|
+
this.restorePointer(finalPointer);
|
|
1528
|
+
}
|
|
1529
|
+
this.validateState();
|
|
1530
|
+
}
|
|
1531
|
+
/**
|
|
1532
|
+
* Remove the current node and decrement the pointer, deleting any ancestor
|
|
1533
|
+
* chunk that becomes empty as a result
|
|
1534
|
+
*/
|
|
1535
|
+
remove() {
|
|
1536
|
+
this.pointerSiblings.splice(this.pointerIndex--, 1);
|
|
1537
|
+
this.cachedPointerNode = undefined;
|
|
1538
|
+
if (this.pointerSiblings.length === 0 && this.pointerChunk.type === 'chunk') {
|
|
1539
|
+
this.exitChunk();
|
|
1540
|
+
this.remove();
|
|
1541
|
+
} else {
|
|
1542
|
+
this.invalidateChunk();
|
|
1543
|
+
}
|
|
1544
|
+
this.validateState();
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Add the current chunk and all ancestor chunks to the list of modified
|
|
1548
|
+
* chunks
|
|
1549
|
+
*/
|
|
1550
|
+
invalidateChunk() {
|
|
1551
|
+
for (var c = this.pointerChunk; c.type === 'chunk'; c = c.parent) {
|
|
1552
|
+
this.root.modifiedChunks.add(c);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Whether the pointer is at the start of the tree
|
|
1557
|
+
*/
|
|
1558
|
+
get atStart() {
|
|
1559
|
+
return this.pointerChunk.type === 'root' && this.pointerIndex === -1;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* The siblings of the current node
|
|
1563
|
+
*/
|
|
1564
|
+
get pointerSiblings() {
|
|
1565
|
+
return this.pointerChunk.children;
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Get the current node (uncached)
|
|
1569
|
+
*
|
|
1570
|
+
* If the pointer is at the start or end of the document, returns null.
|
|
1571
|
+
*
|
|
1572
|
+
* Usually, the current node is a chunk leaf, although it can be a chunk
|
|
1573
|
+
* while insertions are in progress.
|
|
1574
|
+
*/
|
|
1575
|
+
getPointerNode() {
|
|
1576
|
+
if (this.reachedEnd || this.pointerIndex === -1) {
|
|
1577
|
+
return null;
|
|
1578
|
+
}
|
|
1579
|
+
return this.pointerSiblings[this.pointerIndex];
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Cached getter for the current node
|
|
1583
|
+
*/
|
|
1584
|
+
get pointerNode() {
|
|
1585
|
+
if (this.cachedPointerNode !== undefined) return this.cachedPointerNode;
|
|
1586
|
+
var pointerNode = this.getPointerNode();
|
|
1587
|
+
this.cachedPointerNode = pointerNode;
|
|
1588
|
+
return pointerNode;
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Get the path of a chunk relative to the root, returning null if the chunk
|
|
1592
|
+
* is not connected to the root
|
|
1593
|
+
*/
|
|
1594
|
+
getChunkPath(chunk) {
|
|
1595
|
+
var path = [];
|
|
1596
|
+
for (var c = chunk; c.type === 'chunk'; c = c.parent) {
|
|
1597
|
+
var index = c.parent.children.indexOf(c);
|
|
1598
|
+
// istanbul ignore next
|
|
1599
|
+
if (index === -1) {
|
|
1600
|
+
return null;
|
|
1601
|
+
}
|
|
1602
|
+
path.unshift(index);
|
|
1603
|
+
}
|
|
1604
|
+
return path;
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Save the current pointer to be restored later
|
|
1608
|
+
*/
|
|
1609
|
+
savePointer() {
|
|
1610
|
+
if (this.atStart) return 'start';
|
|
1611
|
+
// istanbul ignore next
|
|
1612
|
+
if (!this.pointerNode) {
|
|
1613
|
+
throw new Error('Cannot save pointer when pointerNode is null');
|
|
1614
|
+
}
|
|
1615
|
+
return {
|
|
1616
|
+
chunk: this.pointerChunk,
|
|
1617
|
+
node: this.pointerNode
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Restore the pointer to a previous state
|
|
1622
|
+
*/
|
|
1623
|
+
restorePointer(savedPointer) {
|
|
1624
|
+
if (savedPointer === 'start') {
|
|
1625
|
+
this.pointerChunk = this.root;
|
|
1626
|
+
this.pointerIndex = -1;
|
|
1627
|
+
this.pointerIndexStack = [];
|
|
1628
|
+
this.reachedEnd = false;
|
|
1629
|
+
this.cachedPointerNode = undefined;
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
// Since nodes may have been inserted or removed prior to the saved
|
|
1633
|
+
// pointer since it was saved, the index and index stack must be
|
|
1634
|
+
// recomputed. This is slow, but this is fine since restoring a pointer is
|
|
1635
|
+
// not a frequent operation.
|
|
1636
|
+
var {
|
|
1637
|
+
chunk,
|
|
1638
|
+
node
|
|
1639
|
+
} = savedPointer;
|
|
1640
|
+
var index = chunk.children.indexOf(node);
|
|
1641
|
+
// istanbul ignore next
|
|
1642
|
+
if (index === -1) {
|
|
1643
|
+
throw new Error('Cannot restore point because saved node is no longer in saved chunk');
|
|
1644
|
+
}
|
|
1645
|
+
var indexStack = this.getChunkPath(chunk);
|
|
1646
|
+
// istanbul ignore next
|
|
1647
|
+
if (!indexStack) {
|
|
1648
|
+
throw new Error('Cannot restore point because saved chunk is no longer connected to root');
|
|
1649
|
+
}
|
|
1650
|
+
this.pointerChunk = chunk;
|
|
1651
|
+
this.pointerIndex = index;
|
|
1652
|
+
this.pointerIndexStack = indexStack;
|
|
1653
|
+
this.reachedEnd = false;
|
|
1654
|
+
this.cachedPointerNode = node;
|
|
1655
|
+
this.validateState();
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* Assuming the current node is a chunk, move the pointer into that chunk
|
|
1659
|
+
*
|
|
1660
|
+
* @param end If true, place the pointer on the last node of the chunk.
|
|
1661
|
+
* Otherwise, place the pointer on the first node.
|
|
1662
|
+
*/
|
|
1663
|
+
enterChunk(end) {
|
|
1664
|
+
var _this$pointerNode;
|
|
1665
|
+
// istanbul ignore next
|
|
1666
|
+
if (((_this$pointerNode = this.pointerNode) === null || _this$pointerNode === void 0 ? void 0 : _this$pointerNode.type) !== 'chunk') {
|
|
1667
|
+
throw new Error('Cannot enter non-chunk');
|
|
1668
|
+
}
|
|
1669
|
+
this.pointerIndexStack.push(this.pointerIndex);
|
|
1670
|
+
this.pointerChunk = this.pointerNode;
|
|
1671
|
+
this.pointerIndex = end ? this.pointerSiblings.length - 1 : 0;
|
|
1672
|
+
this.cachedPointerNode = undefined;
|
|
1673
|
+
this.validateState();
|
|
1674
|
+
// istanbul ignore next
|
|
1675
|
+
if (this.pointerChunk.children.length === 0) {
|
|
1676
|
+
throw new Error('Cannot enter empty chunk');
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Assuming the current node is a chunk, move the pointer into that chunk
|
|
1681
|
+
* repeatedly until the current node is a leaf
|
|
1682
|
+
*
|
|
1683
|
+
* @param end If true, place the pointer on the last node of the chunk.
|
|
1684
|
+
* Otherwise, place the pointer on the first node.
|
|
1685
|
+
*/
|
|
1686
|
+
enterChunkUntilLeaf(end) {
|
|
1687
|
+
while (((_this$pointerNode2 = this.pointerNode) === null || _this$pointerNode2 === void 0 ? void 0 : _this$pointerNode2.type) === 'chunk') {
|
|
1688
|
+
var _this$pointerNode2;
|
|
1689
|
+
this.enterChunk(end);
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Move the pointer to the parent chunk
|
|
1694
|
+
*/
|
|
1695
|
+
exitChunk() {
|
|
1696
|
+
// istanbul ignore next
|
|
1697
|
+
if (this.pointerChunk.type === 'root') {
|
|
1698
|
+
throw new Error('Cannot exit root');
|
|
1699
|
+
}
|
|
1700
|
+
var previousPointerChunk = this.pointerChunk;
|
|
1701
|
+
this.pointerChunk = previousPointerChunk.parent;
|
|
1702
|
+
this.pointerIndex = this.pointerIndexStack.pop();
|
|
1703
|
+
this.cachedPointerNode = undefined;
|
|
1704
|
+
this.validateState();
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Insert leaves immediately after the current node, leaving the pointer on
|
|
1708
|
+
* the last inserted leaf
|
|
1709
|
+
*
|
|
1710
|
+
* Leaves are chunked according to the number of nodes already in the parent
|
|
1711
|
+
* plus the number of nodes being inserted, or the minimum depth if larger
|
|
1712
|
+
*/
|
|
1713
|
+
rawInsertAfter(leaves, minDepth) {
|
|
1714
|
+
if (leaves.length === 0) return;
|
|
1715
|
+
var groupIntoChunks = (leaves, parent, perChunk) => {
|
|
1716
|
+
if (perChunk === 1) return leaves;
|
|
1717
|
+
var chunks = [];
|
|
1718
|
+
for (var i = 0; i < this.chunkSize; i++) {
|
|
1719
|
+
var chunkNodes = leaves.slice(i * perChunk, (i + 1) * perChunk);
|
|
1720
|
+
if (chunkNodes.length === 0) break;
|
|
1721
|
+
var chunk = {
|
|
1722
|
+
type: 'chunk',
|
|
1723
|
+
key: new Key(),
|
|
1724
|
+
parent,
|
|
1725
|
+
children: []
|
|
1726
|
+
};
|
|
1727
|
+
chunk.children = groupIntoChunks(chunkNodes, chunk, perChunk / this.chunkSize);
|
|
1728
|
+
chunks.push(chunk);
|
|
1729
|
+
}
|
|
1730
|
+
return chunks;
|
|
1731
|
+
};
|
|
1732
|
+
// Determine the chunking depth based on the number of existing nodes in
|
|
1733
|
+
// the chunk and the number of nodes being inserted
|
|
1734
|
+
var newTotal = this.pointerSiblings.length + leaves.length;
|
|
1735
|
+
var depthForTotal = 0;
|
|
1736
|
+
for (var i = this.chunkSize; i < newTotal; i *= this.chunkSize) {
|
|
1737
|
+
depthForTotal++;
|
|
1738
|
+
}
|
|
1739
|
+
// A depth of 0 means no chunking
|
|
1740
|
+
var depth = Math.max(depthForTotal, minDepth);
|
|
1741
|
+
var perTopLevelChunk = Math.pow(this.chunkSize, depth);
|
|
1742
|
+
var chunks = groupIntoChunks(leaves, this.pointerChunk, perTopLevelChunk);
|
|
1743
|
+
this.pointerSiblings.splice(this.pointerIndex + 1, 0, ...chunks);
|
|
1744
|
+
this.pointerIndex += chunks.length;
|
|
1745
|
+
this.cachedPointerNode = undefined;
|
|
1746
|
+
this.invalidateChunk();
|
|
1747
|
+
this.validateState();
|
|
1748
|
+
}
|
|
1749
|
+
/**
|
|
1750
|
+
* If debug mode is enabled, ensure that the state is internally consistent
|
|
1751
|
+
*/
|
|
1752
|
+
// istanbul ignore next
|
|
1753
|
+
validateState() {
|
|
1754
|
+
if (!this.debug) return;
|
|
1755
|
+
var validateDescendant = node => {
|
|
1756
|
+
if (node.type === 'chunk') {
|
|
1757
|
+
var {
|
|
1758
|
+
parent,
|
|
1759
|
+
children
|
|
1760
|
+
} = node;
|
|
1761
|
+
if (!parent.children.includes(node)) {
|
|
1762
|
+
throw new Error("Debug: Chunk ".concat(node.key.id, " has an incorrect parent property"));
|
|
1763
|
+
}
|
|
1764
|
+
children.forEach(validateDescendant);
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
this.root.children.forEach(validateDescendant);
|
|
1768
|
+
if (this.cachedPointerNode !== undefined && this.cachedPointerNode !== this.getPointerNode()) {
|
|
1769
|
+
throw new Error('Debug: The cached pointer is incorrect and has not been invalidated');
|
|
1770
|
+
}
|
|
1771
|
+
var actualIndexStack = this.getChunkPath(this.pointerChunk);
|
|
1772
|
+
if (!actualIndexStack) {
|
|
1773
|
+
throw new Error('Debug: The pointer chunk is not connected to the root');
|
|
1774
|
+
}
|
|
1775
|
+
if (!Path.equals(this.pointerIndexStack, actualIndexStack)) {
|
|
1776
|
+
throw new Error("Debug: The cached index stack [".concat(this.pointerIndexStack.join(', '), "] does not match the path of the pointer chunk [").concat(actualIndexStack.join(', '), "]"));
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
/**
|
|
1782
|
+
* Traverse an array of children, providing helpers useful for reconciling the
|
|
1783
|
+
* children array with a chunk tree
|
|
1214
1784
|
*/
|
|
1215
|
-
|
|
1785
|
+
class ChildrenHelper {
|
|
1786
|
+
constructor(editor, children) {
|
|
1787
|
+
_defineProperty(this, "editor", void 0);
|
|
1788
|
+
_defineProperty(this, "children", void 0);
|
|
1789
|
+
/**
|
|
1790
|
+
* Sparse array of Slate node keys, each index corresponding to an index in
|
|
1791
|
+
* the children array
|
|
1792
|
+
*
|
|
1793
|
+
* Fetching the key for a Slate node is expensive, so we cache them here.
|
|
1794
|
+
*/
|
|
1795
|
+
_defineProperty(this, "cachedKeys", void 0);
|
|
1796
|
+
/**
|
|
1797
|
+
* The index of the next node to be read in the children array
|
|
1798
|
+
*/
|
|
1799
|
+
_defineProperty(this, "pointerIndex", void 0);
|
|
1800
|
+
this.editor = editor;
|
|
1801
|
+
this.children = children;
|
|
1802
|
+
this.cachedKeys = new Array(children.length);
|
|
1803
|
+
this.pointerIndex = 0;
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Read a given number of nodes, advancing the pointer by that amount
|
|
1807
|
+
*/
|
|
1808
|
+
read(n) {
|
|
1809
|
+
// PERF: If only one child was requested (the most common case), use array
|
|
1810
|
+
// indexing instead of slice
|
|
1811
|
+
if (n === 1) {
|
|
1812
|
+
return [this.children[this.pointerIndex++]];
|
|
1813
|
+
}
|
|
1814
|
+
var slicedChildren = this.remaining(n);
|
|
1815
|
+
this.pointerIndex += n;
|
|
1816
|
+
return slicedChildren;
|
|
1817
|
+
}
|
|
1818
|
+
/**
|
|
1819
|
+
* Get the remaining children without advancing the pointer
|
|
1820
|
+
*
|
|
1821
|
+
* @param [maxChildren] Limit the number of children returned.
|
|
1822
|
+
*/
|
|
1823
|
+
remaining(maxChildren) {
|
|
1824
|
+
if (maxChildren === undefined) {
|
|
1825
|
+
return this.children.slice(this.pointerIndex);
|
|
1826
|
+
}
|
|
1827
|
+
return this.children.slice(this.pointerIndex, this.pointerIndex + maxChildren);
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Whether all children have been read
|
|
1831
|
+
*/
|
|
1832
|
+
get reachedEnd() {
|
|
1833
|
+
return this.pointerIndex >= this.children.length;
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Determine whether a node with a given key appears in the unread part of the
|
|
1837
|
+
* children array, and return its index relative to the current pointer if so
|
|
1838
|
+
*
|
|
1839
|
+
* Searching for the node object itself using indexOf is most efficient, but
|
|
1840
|
+
* will fail to locate nodes that have been modified. In this case, nodes
|
|
1841
|
+
* should be identified by their keys instead.
|
|
1842
|
+
*
|
|
1843
|
+
* Searching an array of keys using indexOf is very inefficient since fetching
|
|
1844
|
+
* the keys for all children in advance is very slow. Insead, if the node
|
|
1845
|
+
* search fails to return a value, fetch the keys of each remaining child one
|
|
1846
|
+
* by one and compare it to the known key.
|
|
1847
|
+
*/
|
|
1848
|
+
lookAhead(node, key) {
|
|
1849
|
+
var elementResult = this.children.indexOf(node, this.pointerIndex);
|
|
1850
|
+
if (elementResult > -1) return elementResult - this.pointerIndex;
|
|
1851
|
+
for (var i = this.pointerIndex; i < this.children.length; i++) {
|
|
1852
|
+
var candidateNode = this.children[i];
|
|
1853
|
+
var candidateKey = this.findKey(candidateNode, i);
|
|
1854
|
+
if (candidateKey === key) return i - this.pointerIndex;
|
|
1855
|
+
}
|
|
1856
|
+
return -1;
|
|
1857
|
+
}
|
|
1858
|
+
/**
|
|
1859
|
+
* Convert an array of Slate nodes to an array of chunk leaves, each
|
|
1860
|
+
* containing the node and its key
|
|
1861
|
+
*/
|
|
1862
|
+
toChunkLeaves(nodes, startIndex) {
|
|
1863
|
+
return nodes.map((node, i) => ({
|
|
1864
|
+
type: 'leaf',
|
|
1865
|
+
node,
|
|
1866
|
+
key: this.findKey(node, startIndex + i),
|
|
1867
|
+
index: startIndex + i
|
|
1868
|
+
}));
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Get the key for a Slate node, cached using the node's index
|
|
1872
|
+
*/
|
|
1873
|
+
findKey(node, index) {
|
|
1874
|
+
var cachedKey = this.cachedKeys[index];
|
|
1875
|
+
if (cachedKey) return cachedKey;
|
|
1876
|
+
var key = ReactEditor.findKey(this.editor, node);
|
|
1877
|
+
this.cachedKeys[index] = key;
|
|
1878
|
+
return key;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1216
1882
|
/**
|
|
1217
|
-
*
|
|
1883
|
+
* Update the chunk tree to match the children array, inserting, removing and
|
|
1884
|
+
* updating differing nodes
|
|
1218
1885
|
*/
|
|
1219
|
-
var
|
|
1220
|
-
|
|
1886
|
+
var reconcileChildren = (editor, _ref) => {
|
|
1887
|
+
var {
|
|
1888
|
+
chunkTree,
|
|
1889
|
+
children,
|
|
1890
|
+
chunkSize,
|
|
1891
|
+
rerenderChildren = [],
|
|
1892
|
+
onInsert,
|
|
1893
|
+
onUpdate,
|
|
1894
|
+
onIndexChange,
|
|
1895
|
+
debug
|
|
1896
|
+
} = _ref;
|
|
1897
|
+
chunkTree.modifiedChunks.clear();
|
|
1898
|
+
var chunkTreeHelper = new ChunkTreeHelper(chunkTree, {
|
|
1899
|
+
chunkSize,
|
|
1900
|
+
debug
|
|
1901
|
+
});
|
|
1902
|
+
var childrenHelper = new ChildrenHelper(editor, children);
|
|
1903
|
+
var treeLeaf;
|
|
1904
|
+
// Read leaves from the tree one by one, each one representing a single Slate
|
|
1905
|
+
// node. Each leaf from the tree is compared to the current node in the
|
|
1906
|
+
// children array to determine whether nodes have been inserted, removed or
|
|
1907
|
+
// updated.
|
|
1908
|
+
var _loop = function _loop() {
|
|
1909
|
+
// Check where the tree node appears in the children array. In the most
|
|
1910
|
+
// common case (where no insertions or removals have occurred), this will be
|
|
1911
|
+
// 0. If the node has been removed, this will be -1. If new nodes have been
|
|
1912
|
+
// inserted before the node, or if the node has been moved to a later
|
|
1913
|
+
// position in the same children array, this will be a positive number.
|
|
1914
|
+
var lookAhead = childrenHelper.lookAhead(treeLeaf.node, treeLeaf.key);
|
|
1915
|
+
// If the node was moved, we want to remove it and insert it later, rather
|
|
1916
|
+
// then re-inserting all intermediate nodes before it.
|
|
1917
|
+
var wasMoved = lookAhead > 0 && chunkTree.movedNodeKeys.has(treeLeaf.key);
|
|
1918
|
+
// If the tree leaf was moved or removed, remove it
|
|
1919
|
+
if (lookAhead === -1 || wasMoved) {
|
|
1920
|
+
chunkTreeHelper.remove();
|
|
1921
|
+
return 1; // continue
|
|
1922
|
+
}
|
|
1923
|
+
// Get the matching Slate node and any nodes that may have been inserted
|
|
1924
|
+
// prior to it. Insert these into the chunk tree.
|
|
1925
|
+
var insertedChildrenStartIndex = childrenHelper.pointerIndex;
|
|
1926
|
+
var insertedChildren = childrenHelper.read(lookAhead + 1);
|
|
1927
|
+
var matchingChild = insertedChildren.pop();
|
|
1928
|
+
if (insertedChildren.length) {
|
|
1929
|
+
var _leavesToInsert = childrenHelper.toChunkLeaves(insertedChildren, insertedChildrenStartIndex);
|
|
1930
|
+
chunkTreeHelper.insertBefore(_leavesToInsert);
|
|
1931
|
+
insertedChildren.forEach((node, relativeIndex) => {
|
|
1932
|
+
onInsert === null || onInsert === void 0 || onInsert(node, insertedChildrenStartIndex + relativeIndex);
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1935
|
+
var matchingChildIndex = childrenHelper.pointerIndex - 1;
|
|
1936
|
+
// Make sure the chunk tree contains the most recent version of the Slate
|
|
1937
|
+
// node
|
|
1938
|
+
if (treeLeaf.node !== matchingChild) {
|
|
1939
|
+
treeLeaf.node = matchingChild;
|
|
1940
|
+
chunkTreeHelper.invalidateChunk();
|
|
1941
|
+
onUpdate === null || onUpdate === void 0 || onUpdate(matchingChild, matchingChildIndex);
|
|
1942
|
+
}
|
|
1943
|
+
// Update the index if it has changed
|
|
1944
|
+
if (treeLeaf.index !== matchingChildIndex) {
|
|
1945
|
+
treeLeaf.index = matchingChildIndex;
|
|
1946
|
+
onIndexChange === null || onIndexChange === void 0 || onIndexChange(matchingChild, matchingChildIndex);
|
|
1947
|
+
}
|
|
1948
|
+
// Manually invalidate chunks containing specific children that we want to
|
|
1949
|
+
// re-render
|
|
1950
|
+
if (rerenderChildren.includes(matchingChildIndex)) {
|
|
1951
|
+
chunkTreeHelper.invalidateChunk();
|
|
1952
|
+
}
|
|
1953
|
+
};
|
|
1954
|
+
while (treeLeaf = chunkTreeHelper.readLeaf()) {
|
|
1955
|
+
if (_loop()) continue;
|
|
1956
|
+
}
|
|
1957
|
+
// If there are still Slate nodes remaining from the children array that were
|
|
1958
|
+
// not matched to nodes in the tree, insert them at the end of the tree
|
|
1959
|
+
if (!childrenHelper.reachedEnd) {
|
|
1960
|
+
var remainingChildren = childrenHelper.remaining();
|
|
1961
|
+
var leavesToInsert = childrenHelper.toChunkLeaves(remainingChildren, childrenHelper.pointerIndex);
|
|
1962
|
+
// Move the pointer back to the final leaf in the tree, or the start of the
|
|
1963
|
+
// tree if the tree is currently empty
|
|
1964
|
+
chunkTreeHelper.returnToPreviousLeaf();
|
|
1965
|
+
chunkTreeHelper.insertAfter(leavesToInsert);
|
|
1966
|
+
remainingChildren.forEach((node, relativeIndex) => {
|
|
1967
|
+
onInsert === null || onInsert === void 0 || onInsert(node, childrenHelper.pointerIndex + relativeIndex);
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
chunkTree.movedNodeKeys.clear();
|
|
1221
1971
|
};
|
|
1222
1972
|
|
|
1973
|
+
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; }
|
|
1974
|
+
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), !0).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; }
|
|
1975
|
+
var KEY_TO_CHUNK_TREE = new WeakMap();
|
|
1223
1976
|
/**
|
|
1224
|
-
*
|
|
1977
|
+
* Get or create the chunk tree for a Slate node
|
|
1978
|
+
*
|
|
1979
|
+
* If the reconcile option is provided, the chunk tree will be updated to
|
|
1980
|
+
* match the current children of the node. The children are chunked
|
|
1981
|
+
* automatically using the given chunk size.
|
|
1225
1982
|
*/
|
|
1226
|
-
var
|
|
1983
|
+
var getChunkTreeForNode = function getChunkTreeForNode(editor, node) {
|
|
1984
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
1985
|
+
var key = ReactEditor.findKey(editor, node);
|
|
1986
|
+
var chunkTree = KEY_TO_CHUNK_TREE.get(key);
|
|
1987
|
+
if (!chunkTree) {
|
|
1988
|
+
chunkTree = {
|
|
1989
|
+
type: 'root',
|
|
1990
|
+
movedNodeKeys: new Set(),
|
|
1991
|
+
modifiedChunks: new Set(),
|
|
1992
|
+
children: []
|
|
1993
|
+
};
|
|
1994
|
+
KEY_TO_CHUNK_TREE.set(key, chunkTree);
|
|
1995
|
+
}
|
|
1996
|
+
if (options.reconcile) {
|
|
1997
|
+
reconcileChildren(editor, _objectSpread$1({
|
|
1998
|
+
chunkTree,
|
|
1999
|
+
children: node.children
|
|
2000
|
+
}, options.reconcile));
|
|
2001
|
+
}
|
|
2002
|
+
return chunkTree;
|
|
2003
|
+
};
|
|
2004
|
+
|
|
2005
|
+
var defaultRenderChunk = _ref => {
|
|
2006
|
+
var {
|
|
2007
|
+
children
|
|
2008
|
+
} = _ref;
|
|
2009
|
+
return children;
|
|
2010
|
+
};
|
|
2011
|
+
var ChunkAncestor = props => {
|
|
2012
|
+
var {
|
|
2013
|
+
root,
|
|
2014
|
+
ancestor,
|
|
2015
|
+
renderElement,
|
|
2016
|
+
renderChunk = defaultRenderChunk
|
|
2017
|
+
} = props;
|
|
2018
|
+
return ancestor.children.map(chunkNode => {
|
|
2019
|
+
if (chunkNode.type === 'chunk') {
|
|
2020
|
+
var key = chunkNode.key.id;
|
|
2021
|
+
var renderedChunk = renderChunk({
|
|
2022
|
+
highest: ancestor === root,
|
|
2023
|
+
lowest: chunkNode.children.some(c => c.type === 'leaf'),
|
|
2024
|
+
attributes: {
|
|
2025
|
+
'data-slate-chunk': true
|
|
2026
|
+
},
|
|
2027
|
+
children: /*#__PURE__*/React.createElement(MemoizedChunk, {
|
|
2028
|
+
root: root,
|
|
2029
|
+
ancestor: chunkNode,
|
|
2030
|
+
renderElement: renderElement,
|
|
2031
|
+
renderChunk: renderChunk
|
|
2032
|
+
})
|
|
2033
|
+
});
|
|
2034
|
+
return /*#__PURE__*/React.createElement(Fragment, {
|
|
2035
|
+
key: key
|
|
2036
|
+
}, renderedChunk);
|
|
2037
|
+
}
|
|
2038
|
+
// Only blocks containing no inlines are chunked
|
|
2039
|
+
var element = chunkNode.node;
|
|
2040
|
+
return renderElement(element, chunkNode.index, chunkNode.key);
|
|
2041
|
+
});
|
|
2042
|
+
};
|
|
2043
|
+
var ChunkTree = ChunkAncestor;
|
|
2044
|
+
var 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));
|
|
2045
|
+
|
|
2046
|
+
var ElementContext = /*#__PURE__*/createContext(null);
|
|
1227
2047
|
/**
|
|
1228
|
-
* Get the current
|
|
2048
|
+
* Get the current element.
|
|
1229
2049
|
*/
|
|
1230
|
-
var
|
|
1231
|
-
|
|
2050
|
+
var useElement = () => {
|
|
2051
|
+
var context = useContext(ElementContext);
|
|
2052
|
+
if (!context) {
|
|
2053
|
+
throw new Error('The `useElement` hook must be used inside `renderElement`.');
|
|
2054
|
+
}
|
|
2055
|
+
return context;
|
|
1232
2056
|
};
|
|
2057
|
+
/**
|
|
2058
|
+
* Get the current element, or return null if not inside `renderElement`.
|
|
2059
|
+
*/
|
|
2060
|
+
var useElementIf = () => useContext(ElementContext);
|
|
1233
2061
|
|
|
1234
2062
|
/**
|
|
1235
2063
|
* Children.
|
|
@@ -1239,60 +2067,113 @@ var useChildren = props => {
|
|
|
1239
2067
|
decorations,
|
|
1240
2068
|
node,
|
|
1241
2069
|
renderElement,
|
|
2070
|
+
renderChunk,
|
|
1242
2071
|
renderPlaceholder,
|
|
1243
2072
|
renderText,
|
|
1244
|
-
renderLeaf
|
|
1245
|
-
selection
|
|
2073
|
+
renderLeaf
|
|
1246
2074
|
} = props;
|
|
1247
|
-
var decorate = useDecorate();
|
|
1248
2075
|
var editor = useSlateStatic();
|
|
1249
2076
|
IS_NODE_MAP_DIRTY.set(editor, false);
|
|
1250
|
-
var
|
|
1251
|
-
var
|
|
1252
|
-
var isLeafBlock =
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
2077
|
+
var isEditor = Editor.isEditor(node);
|
|
2078
|
+
var isBlock = !isEditor && Element$1.isElement(node) && !editor.isInline(node);
|
|
2079
|
+
var isLeafBlock = isBlock && Editor.hasInlines(editor, node);
|
|
2080
|
+
var chunkSize = isLeafBlock ? null : editor.getChunkSize(node);
|
|
2081
|
+
var chunking = !!chunkSize;
|
|
2082
|
+
var {
|
|
2083
|
+
decorationsByChild,
|
|
2084
|
+
childrenToRedecorate
|
|
2085
|
+
} = useDecorationsByChild(editor, node, decorations);
|
|
2086
|
+
// Update the index and parent of each child.
|
|
2087
|
+
// PERF: If chunking is enabled, this is done while traversing the chunk tree
|
|
2088
|
+
// instead to eliminate unnecessary weak map operations.
|
|
2089
|
+
if (!chunking) {
|
|
2090
|
+
node.children.forEach((n, i) => {
|
|
2091
|
+
NODE_TO_INDEX.set(n, i);
|
|
2092
|
+
NODE_TO_PARENT.set(n, node);
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
var renderElementComponent = useCallback((n, i, cachedKey) => {
|
|
2096
|
+
var key = cachedKey !== null && cachedKey !== void 0 ? cachedKey : ReactEditor.findKey(editor, n);
|
|
2097
|
+
return /*#__PURE__*/React.createElement(ElementContext.Provider, {
|
|
2098
|
+
key: "provider-".concat(key.id),
|
|
2099
|
+
value: n
|
|
2100
|
+
}, /*#__PURE__*/React.createElement(MemoizedElement, {
|
|
2101
|
+
decorations: decorationsByChild[i],
|
|
2102
|
+
element: n,
|
|
2103
|
+
key: key.id,
|
|
2104
|
+
renderElement: renderElement,
|
|
2105
|
+
renderChunk: renderChunk,
|
|
2106
|
+
renderPlaceholder: renderPlaceholder,
|
|
2107
|
+
renderLeaf: renderLeaf,
|
|
2108
|
+
renderText: renderText
|
|
2109
|
+
}));
|
|
2110
|
+
}, [editor, decorationsByChild, renderElement, renderChunk, renderPlaceholder, renderLeaf, renderText]);
|
|
2111
|
+
var renderTextComponent = (n, i) => {
|
|
1256
2112
|
var key = ReactEditor.findKey(editor, n);
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
2113
|
+
return /*#__PURE__*/React.createElement(MemoizedText, {
|
|
2114
|
+
decorations: decorationsByChild[i],
|
|
2115
|
+
key: key.id,
|
|
2116
|
+
isLast: i === node.children.length - 1,
|
|
2117
|
+
parent: node,
|
|
2118
|
+
renderPlaceholder: renderPlaceholder,
|
|
2119
|
+
renderLeaf: renderLeaf,
|
|
2120
|
+
renderText: renderText,
|
|
2121
|
+
text: n
|
|
2122
|
+
});
|
|
2123
|
+
};
|
|
2124
|
+
if (!chunking) {
|
|
2125
|
+
return node.children.map((n, i) => Text$1.isText(n) ? renderTextComponent(n, i) : renderElementComponent(n, i));
|
|
2126
|
+
}
|
|
2127
|
+
var chunkTree = getChunkTreeForNode(editor, node, {
|
|
2128
|
+
reconcile: {
|
|
2129
|
+
chunkSize,
|
|
2130
|
+
rerenderChildren: childrenToRedecorate,
|
|
2131
|
+
onInsert: (n, i) => {
|
|
2132
|
+
NODE_TO_INDEX.set(n, i);
|
|
2133
|
+
NODE_TO_PARENT.set(n, node);
|
|
2134
|
+
},
|
|
2135
|
+
onUpdate: (n, i) => {
|
|
2136
|
+
NODE_TO_INDEX.set(n, i);
|
|
2137
|
+
NODE_TO_PARENT.set(n, node);
|
|
2138
|
+
},
|
|
2139
|
+
onIndexChange: (n, i) => {
|
|
2140
|
+
NODE_TO_INDEX.set(n, i);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
return /*#__PURE__*/React.createElement(ChunkTree, {
|
|
2145
|
+
root: chunkTree,
|
|
2146
|
+
ancestor: chunkTree,
|
|
2147
|
+
renderElement: renderElementComponent,
|
|
2148
|
+
renderChunk: renderChunk
|
|
2149
|
+
});
|
|
2150
|
+
};
|
|
2151
|
+
var useDecorationsByChild = (editor, node, decorations) => {
|
|
2152
|
+
var decorationsByChild = splitDecorationsByChild(editor, node, decorations);
|
|
2153
|
+
// The value we return is a mutable array of `DecoratedRange[]` arrays. This
|
|
2154
|
+
// lets us avoid passing an immutable array of decorations for each child into
|
|
2155
|
+
// `ChunkTree` using props. Each `DecoratedRange[]` is only updated if the
|
|
2156
|
+
// decorations at that index have changed, which speeds up the equality check
|
|
2157
|
+
// for the `decorations` prop in the memoized `Element` and `Text` components.
|
|
2158
|
+
var mutableDecorationsByChild = useRef(decorationsByChild).current;
|
|
2159
|
+
// Track the list of child indices whose decorations have changed, so that we
|
|
2160
|
+
// can tell the chunk tree to re-render these children.
|
|
2161
|
+
var childrenToRedecorate = [];
|
|
2162
|
+
// Resize the mutable array to match the latest result
|
|
2163
|
+
mutableDecorationsByChild.length = decorationsByChild.length;
|
|
2164
|
+
for (var i = 0; i < decorationsByChild.length; i++) {
|
|
2165
|
+
var _mutableDecorationsBy;
|
|
2166
|
+
var _decorations = decorationsByChild[i];
|
|
2167
|
+
var previousDecorations = (_mutableDecorationsBy = mutableDecorationsByChild[i]) !== null && _mutableDecorationsBy !== void 0 ? _mutableDecorationsBy : null;
|
|
2168
|
+
if (!isElementDecorationsEqual(previousDecorations, _decorations)) {
|
|
2169
|
+
mutableDecorationsByChild[i] = _decorations;
|
|
2170
|
+
childrenToRedecorate.push(i);
|
|
1291
2171
|
}
|
|
1292
|
-
NODE_TO_INDEX.set(n, i);
|
|
1293
|
-
NODE_TO_PARENT.set(n, node);
|
|
1294
2172
|
}
|
|
1295
|
-
return
|
|
2173
|
+
return {
|
|
2174
|
+
decorationsByChild: mutableDecorationsByChild,
|
|
2175
|
+
childrenToRedecorate
|
|
2176
|
+
};
|
|
1296
2177
|
};
|
|
1297
2178
|
|
|
1298
2179
|
/**
|
|
@@ -1306,26 +2187,137 @@ var useReadOnly = () => {
|
|
|
1306
2187
|
return useContext(ReadOnlyContext);
|
|
1307
2188
|
};
|
|
1308
2189
|
|
|
1309
|
-
var SlateContext = /*#__PURE__*/createContext(null);
|
|
1310
2190
|
/**
|
|
1311
|
-
*
|
|
2191
|
+
* A React context for sharing the editor selector context in a way to control
|
|
2192
|
+
* re-renders.
|
|
1312
2193
|
*/
|
|
1313
|
-
var
|
|
1314
|
-
|
|
2194
|
+
var SlateSelectorContext = /*#__PURE__*/createContext({});
|
|
2195
|
+
var refEquality = (a, b) => a === b;
|
|
2196
|
+
/**
|
|
2197
|
+
* Use redux style selectors to prevent re-rendering on every keystroke.
|
|
2198
|
+
*
|
|
2199
|
+
* Bear in mind re-rendering can only prevented if the returned value is a value
|
|
2200
|
+
* type or for reference types (e.g. objects and arrays) add a custom equality
|
|
2201
|
+
* function.
|
|
2202
|
+
*
|
|
2203
|
+
* If `selector` is memoized using `useCallback`, then it will only be called
|
|
2204
|
+
* when it or the editor state changes. Otherwise, `selector` will be called
|
|
2205
|
+
* every time the component renders.
|
|
2206
|
+
*
|
|
2207
|
+
* @example
|
|
2208
|
+
* const isSelectionActive = useSlateSelector(editor => Boolean(editor.selection))
|
|
2209
|
+
*/
|
|
2210
|
+
function useSlateSelector(selector) {
|
|
2211
|
+
var equalityFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : refEquality;
|
|
2212
|
+
var {
|
|
2213
|
+
deferred
|
|
2214
|
+
} = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
2215
|
+
var context = useContext(SlateSelectorContext);
|
|
1315
2216
|
if (!context) {
|
|
1316
|
-
throw new Error("The `
|
|
2217
|
+
throw new Error("The `useSlateSelector` hook must be used inside the <Slate> component's context.");
|
|
1317
2218
|
}
|
|
1318
2219
|
var {
|
|
1319
|
-
|
|
2220
|
+
addEventListener
|
|
1320
2221
|
} = context;
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
var
|
|
1324
|
-
|
|
1325
|
-
|
|
2222
|
+
var editor = useSlateStatic();
|
|
2223
|
+
var genericSelector = useCallback(() => selector(editor), [editor, selector]);
|
|
2224
|
+
var [selectedState, update] = useGenericSelector(genericSelector, equalityFn);
|
|
2225
|
+
useIsomorphicLayoutEffect(() => {
|
|
2226
|
+
var unsubscribe = addEventListener(update, {
|
|
2227
|
+
deferred
|
|
2228
|
+
});
|
|
2229
|
+
update();
|
|
2230
|
+
return unsubscribe;
|
|
2231
|
+
}, [addEventListener, update, deferred]);
|
|
2232
|
+
return selectedState;
|
|
2233
|
+
}
|
|
2234
|
+
/**
|
|
2235
|
+
* Create selector context with editor updating on every editor change
|
|
2236
|
+
*/
|
|
2237
|
+
function useSelectorContext() {
|
|
2238
|
+
var eventListeners = useRef(new Set());
|
|
2239
|
+
var deferredEventListeners = useRef(new Set());
|
|
2240
|
+
var onChange = useCallback(() => {
|
|
2241
|
+
eventListeners.current.forEach(listener => listener());
|
|
2242
|
+
}, []);
|
|
2243
|
+
var flushDeferred = useCallback(() => {
|
|
2244
|
+
deferredEventListeners.current.forEach(listener => listener());
|
|
2245
|
+
deferredEventListeners.current.clear();
|
|
2246
|
+
}, []);
|
|
2247
|
+
var addEventListener = useCallback(function (callbackProp) {
|
|
2248
|
+
var {
|
|
2249
|
+
deferred = false
|
|
2250
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
2251
|
+
var callback = deferred ? () => deferredEventListeners.current.add(callbackProp) : callbackProp;
|
|
2252
|
+
eventListeners.current.add(callback);
|
|
2253
|
+
return () => {
|
|
2254
|
+
eventListeners.current.delete(callback);
|
|
2255
|
+
};
|
|
2256
|
+
}, []);
|
|
2257
|
+
var selectorContext = useMemo(() => ({
|
|
2258
|
+
addEventListener,
|
|
2259
|
+
flushDeferred
|
|
2260
|
+
}), [addEventListener, flushDeferred]);
|
|
2261
|
+
return {
|
|
2262
|
+
selectorContext,
|
|
2263
|
+
onChange
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
function useFlushDeferredSelectorsOnRender() {
|
|
2267
|
+
var {
|
|
2268
|
+
flushDeferred
|
|
2269
|
+
} = useContext(SlateSelectorContext);
|
|
2270
|
+
useIsomorphicLayoutEffect(flushDeferred);
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
/**
|
|
2274
|
+
* Get the current editor object and re-render whenever it changes.
|
|
2275
|
+
*/
|
|
2276
|
+
var useSlate = () => {
|
|
2277
|
+
var {
|
|
2278
|
+
addEventListener
|
|
2279
|
+
} = useContext(SlateSelectorContext);
|
|
2280
|
+
var [, forceRender] = useReducer(s => s + 1, 0);
|
|
2281
|
+
if (!addEventListener) {
|
|
1326
2282
|
throw new Error("The `useSlate` hook must be used inside the <Slate> component's context.");
|
|
1327
2283
|
}
|
|
1328
|
-
|
|
2284
|
+
useIsomorphicLayoutEffect(() => addEventListener(forceRender), [addEventListener]);
|
|
2285
|
+
return useSlateStatic();
|
|
2286
|
+
};
|
|
2287
|
+
var EDITOR_TO_V = new WeakMap();
|
|
2288
|
+
var getEditorVersionRef = editor => {
|
|
2289
|
+
var v = EDITOR_TO_V.get(editor);
|
|
2290
|
+
if (v) {
|
|
2291
|
+
return v;
|
|
2292
|
+
}
|
|
2293
|
+
v = {
|
|
2294
|
+
current: 0
|
|
2295
|
+
};
|
|
2296
|
+
EDITOR_TO_V.set(editor, v);
|
|
2297
|
+
// Register the `onChange` handler exactly once per editor
|
|
2298
|
+
var {
|
|
2299
|
+
onChange
|
|
2300
|
+
} = editor;
|
|
2301
|
+
editor.onChange = options => {
|
|
2302
|
+
v.current++;
|
|
2303
|
+
onChange(options);
|
|
2304
|
+
};
|
|
2305
|
+
return v;
|
|
2306
|
+
};
|
|
2307
|
+
/**
|
|
2308
|
+
* Get the current editor object and its version, which increments on every
|
|
2309
|
+
* change.
|
|
2310
|
+
*
|
|
2311
|
+
* @deprecated The `v` counter is no longer used except for this hook, and may
|
|
2312
|
+
* be removed in a future version.
|
|
2313
|
+
*/
|
|
2314
|
+
var useSlateWithV = () => {
|
|
2315
|
+
var editor = useSlate();
|
|
2316
|
+
var vRef = useMemo(() => getEditorVersionRef(editor), [editor]);
|
|
2317
|
+
return {
|
|
2318
|
+
editor,
|
|
2319
|
+
v: vRef.current
|
|
2320
|
+
};
|
|
1329
2321
|
};
|
|
1330
2322
|
|
|
1331
2323
|
function useTrackUserInput() {
|
|
@@ -1465,7 +2457,7 @@ var useComposing = () => {
|
|
|
1465
2457
|
return useContext(ComposingContext);
|
|
1466
2458
|
};
|
|
1467
2459
|
|
|
1468
|
-
var _excluded$1 = ["autoFocus", "decorate", "onDOMBeforeInput", "placeholder", "readOnly", "renderElement", "renderLeaf", "renderText", "renderPlaceholder", "scrollSelectionIntoView", "style", "as", "disableDefaultStyles"],
|
|
2460
|
+
var _excluded$1 = ["autoFocus", "decorate", "onDOMBeforeInput", "placeholder", "readOnly", "renderElement", "renderChunk", "renderLeaf", "renderText", "renderPlaceholder", "scrollSelectionIntoView", "style", "as", "disableDefaultStyles"],
|
|
1469
2461
|
_excluded2 = ["text"];
|
|
1470
2462
|
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; }
|
|
1471
2463
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).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; }
|
|
@@ -1482,6 +2474,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
1482
2474
|
placeholder,
|
|
1483
2475
|
readOnly = false,
|
|
1484
2476
|
renderElement,
|
|
2477
|
+
renderChunk,
|
|
1485
2478
|
renderLeaf,
|
|
1486
2479
|
renderText,
|
|
1487
2480
|
renderPlaceholder = defaultRenderPlaceholder,
|
|
@@ -1515,6 +2508,11 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
1515
2508
|
}), []);
|
|
1516
2509
|
// The autoFocus TextareaHTMLAttribute doesn't do anything on a div, so it
|
|
1517
2510
|
// needs to be manually focused.
|
|
2511
|
+
//
|
|
2512
|
+
// If this stops working in Firefox, make sure nothing is causing this
|
|
2513
|
+
// component to re-render during the initial mount. If the DOM selection is
|
|
2514
|
+
// set by `useIsomorphicLayoutEffect` before `onDOMSelectionChange` updates
|
|
2515
|
+
// `editor.selection`, the DOM selection can be removed accidentally.
|
|
1518
2516
|
useEffect(() => {
|
|
1519
2517
|
if (ref.current && autoFocus) {
|
|
1520
2518
|
ref.current.focus();
|
|
@@ -2067,6 +3065,7 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2067
3065
|
};
|
|
2068
3066
|
}, [scheduleOnDOMSelectionChange, state]);
|
|
2069
3067
|
var decorations = decorate([editor, []]);
|
|
3068
|
+
var decorateContext = useDecorateContext(decorate);
|
|
2070
3069
|
var showPlaceholder = placeholder && editor.children.length === 1 && Array.from(Node.texts(editor)).length === 1 && Node.string(editor) === '' && !isComposing;
|
|
2071
3070
|
var placeHolderResizeHandler = useCallback(placeholderEl => {
|
|
2072
3071
|
if (placeholderEl && showPlaceholder) {
|
|
@@ -2135,12 +3134,13 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2135
3134
|
EDITOR_TO_PENDING_INSERTION_MARKS.delete(editor);
|
|
2136
3135
|
});
|
|
2137
3136
|
});
|
|
3137
|
+
useFlushDeferredSelectorsOnRender();
|
|
2138
3138
|
return /*#__PURE__*/React.createElement(ReadOnlyContext.Provider, {
|
|
2139
3139
|
value: readOnly
|
|
2140
3140
|
}, /*#__PURE__*/React.createElement(ComposingContext.Provider, {
|
|
2141
3141
|
value: isComposing
|
|
2142
3142
|
}, /*#__PURE__*/React.createElement(DecorateContext.Provider, {
|
|
2143
|
-
value:
|
|
3143
|
+
value: decorateContext
|
|
2144
3144
|
}, /*#__PURE__*/React.createElement(RestoreDOM, {
|
|
2145
3145
|
node: ref,
|
|
2146
3146
|
receivedUserInput: receivedUserInput
|
|
@@ -2725,10 +3725,10 @@ var Editable = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
2725
3725
|
decorations: decorations,
|
|
2726
3726
|
node: editor,
|
|
2727
3727
|
renderElement: renderElement,
|
|
3728
|
+
renderChunk: renderChunk,
|
|
2728
3729
|
renderPlaceholder: renderPlaceholder,
|
|
2729
3730
|
renderLeaf: renderLeaf,
|
|
2730
|
-
renderText: renderText
|
|
2731
|
-
selection: editor.selection
|
|
3731
|
+
renderText: renderText
|
|
2732
3732
|
}))))));
|
|
2733
3733
|
});
|
|
2734
3734
|
/**
|
|
@@ -2825,118 +3825,6 @@ var useFocused = () => {
|
|
|
2825
3825
|
return useContext(FocusedContext);
|
|
2826
3826
|
};
|
|
2827
3827
|
|
|
2828
|
-
function isError(error) {
|
|
2829
|
-
return error instanceof Error;
|
|
2830
|
-
}
|
|
2831
|
-
/**
|
|
2832
|
-
* A React context for sharing the editor selector context in a way to control rerenders
|
|
2833
|
-
*/
|
|
2834
|
-
var SlateSelectorContext = /*#__PURE__*/createContext({});
|
|
2835
|
-
var refEquality = (a, b) => a === b;
|
|
2836
|
-
/**
|
|
2837
|
-
* use redux style selectors to prevent rerendering on every keystroke.
|
|
2838
|
-
* Bear in mind rerendering can only prevented if the returned value is a value type or for reference types (e.g. objects and arrays) add a custom equality function.
|
|
2839
|
-
*
|
|
2840
|
-
* Example:
|
|
2841
|
-
* ```
|
|
2842
|
-
* const isSelectionActive = useSlateSelector(editor => Boolean(editor.selection));
|
|
2843
|
-
* ```
|
|
2844
|
-
*/
|
|
2845
|
-
function useSlateSelector(selector) {
|
|
2846
|
-
var equalityFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : refEquality;
|
|
2847
|
-
var [, forceRender] = useReducer(s => s + 1, 0);
|
|
2848
|
-
var context = useContext(SlateSelectorContext);
|
|
2849
|
-
if (!context) {
|
|
2850
|
-
throw new Error("The `useSlateSelector` hook must be used inside the <Slate> component's context.");
|
|
2851
|
-
}
|
|
2852
|
-
var {
|
|
2853
|
-
getSlate,
|
|
2854
|
-
addEventListener
|
|
2855
|
-
} = context;
|
|
2856
|
-
var latestSubscriptionCallbackError = useRef();
|
|
2857
|
-
var latestSelector = useRef(() => null);
|
|
2858
|
-
var latestSelectedState = useRef(null);
|
|
2859
|
-
var selectedState;
|
|
2860
|
-
try {
|
|
2861
|
-
if (selector !== latestSelector.current || latestSubscriptionCallbackError.current) {
|
|
2862
|
-
var selectorResult = selector(getSlate());
|
|
2863
|
-
if (equalityFn(latestSelectedState.current, selectorResult)) {
|
|
2864
|
-
selectedState = latestSelectedState.current;
|
|
2865
|
-
} else {
|
|
2866
|
-
selectedState = selectorResult;
|
|
2867
|
-
}
|
|
2868
|
-
} else {
|
|
2869
|
-
selectedState = latestSelectedState.current;
|
|
2870
|
-
}
|
|
2871
|
-
} catch (err) {
|
|
2872
|
-
if (latestSubscriptionCallbackError.current && isError(err)) {
|
|
2873
|
-
err.message += "\nThe error may be correlated with this previous error:\n".concat(latestSubscriptionCallbackError.current.stack, "\n\n");
|
|
2874
|
-
}
|
|
2875
|
-
throw err;
|
|
2876
|
-
}
|
|
2877
|
-
useIsomorphicLayoutEffect(() => {
|
|
2878
|
-
latestSelector.current = selector;
|
|
2879
|
-
latestSelectedState.current = selectedState;
|
|
2880
|
-
latestSubscriptionCallbackError.current = undefined;
|
|
2881
|
-
});
|
|
2882
|
-
useIsomorphicLayoutEffect(() => {
|
|
2883
|
-
function checkForUpdates() {
|
|
2884
|
-
try {
|
|
2885
|
-
var newSelectedState = latestSelector.current(getSlate());
|
|
2886
|
-
if (equalityFn(newSelectedState, latestSelectedState.current)) {
|
|
2887
|
-
return;
|
|
2888
|
-
}
|
|
2889
|
-
latestSelectedState.current = newSelectedState;
|
|
2890
|
-
} catch (err) {
|
|
2891
|
-
// we ignore all errors here, since when the component
|
|
2892
|
-
// is re-rendered, the selectors are called again, and
|
|
2893
|
-
// will throw again, if neither props nor store state
|
|
2894
|
-
// changed
|
|
2895
|
-
if (err instanceof Error) {
|
|
2896
|
-
latestSubscriptionCallbackError.current = err;
|
|
2897
|
-
} else {
|
|
2898
|
-
latestSubscriptionCallbackError.current = new Error(String(err));
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
forceRender();
|
|
2902
|
-
}
|
|
2903
|
-
var unsubscribe = addEventListener(checkForUpdates);
|
|
2904
|
-
checkForUpdates();
|
|
2905
|
-
return () => unsubscribe();
|
|
2906
|
-
},
|
|
2907
|
-
// don't rerender on equalityFn change since we want to be able to define it inline
|
|
2908
|
-
[addEventListener, getSlate]);
|
|
2909
|
-
return selectedState;
|
|
2910
|
-
}
|
|
2911
|
-
/**
|
|
2912
|
-
* Create selector context with editor updating on every editor change
|
|
2913
|
-
*/
|
|
2914
|
-
function useSelectorContext(editor) {
|
|
2915
|
-
var eventListeners = useRef([]).current;
|
|
2916
|
-
var slateRef = useRef({
|
|
2917
|
-
editor
|
|
2918
|
-
}).current;
|
|
2919
|
-
var onChange = useCallback(editor => {
|
|
2920
|
-
slateRef.editor = editor;
|
|
2921
|
-
eventListeners.forEach(listener => listener(editor));
|
|
2922
|
-
}, [eventListeners, slateRef]);
|
|
2923
|
-
var selectorContext = useMemo(() => {
|
|
2924
|
-
return {
|
|
2925
|
-
getSlate: () => slateRef.editor,
|
|
2926
|
-
addEventListener: callback => {
|
|
2927
|
-
eventListeners.push(callback);
|
|
2928
|
-
return () => {
|
|
2929
|
-
eventListeners.splice(eventListeners.indexOf(callback), 1);
|
|
2930
|
-
};
|
|
2931
|
-
}
|
|
2932
|
-
};
|
|
2933
|
-
}, [eventListeners, slateRef]);
|
|
2934
|
-
return {
|
|
2935
|
-
selectorContext,
|
|
2936
|
-
onChange
|
|
2937
|
-
};
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
3828
|
var REACT_MAJOR_VERSION = parseInt(React.version.split('.')[0], 10);
|
|
2941
3829
|
|
|
2942
3830
|
var _excluded = ["editor", "children", "onChange", "onSelectionChange", "onValueChange", "initialValue"];
|
|
@@ -2954,7 +3842,8 @@ var Slate = props => {
|
|
|
2954
3842
|
initialValue
|
|
2955
3843
|
} = props,
|
|
2956
3844
|
rest = _objectWithoutProperties(props, _excluded);
|
|
2957
|
-
|
|
3845
|
+
// Run once on first mount, but before `useEffect` or render
|
|
3846
|
+
React.useState(() => {
|
|
2958
3847
|
if (!Node.isNodeList(initialValue)) {
|
|
2959
3848
|
throw new Error("[Slate] initialValue is invalid! Expected a list of elements but got: ".concat(Scrubber.stringify(initialValue)));
|
|
2960
3849
|
}
|
|
@@ -2963,15 +3852,11 @@ var Slate = props => {
|
|
|
2963
3852
|
}
|
|
2964
3853
|
editor.children = initialValue;
|
|
2965
3854
|
Object.assign(editor, rest);
|
|
2966
|
-
return {
|
|
2967
|
-
v: 0,
|
|
2968
|
-
editor
|
|
2969
|
-
};
|
|
2970
3855
|
});
|
|
2971
3856
|
var {
|
|
2972
3857
|
selectorContext,
|
|
2973
3858
|
onChange: handleSelectorChange
|
|
2974
|
-
} = useSelectorContext(
|
|
3859
|
+
} = useSelectorContext();
|
|
2975
3860
|
var onContextChange = useCallback(options => {
|
|
2976
3861
|
var _options$operation;
|
|
2977
3862
|
if (onChange) {
|
|
@@ -2984,11 +3869,7 @@ var Slate = props => {
|
|
|
2984
3869
|
default:
|
|
2985
3870
|
onValueChange === null || onValueChange === void 0 || onValueChange(editor.children);
|
|
2986
3871
|
}
|
|
2987
|
-
|
|
2988
|
-
v: prevContext.v + 1,
|
|
2989
|
-
editor
|
|
2990
|
-
}));
|
|
2991
|
-
handleSelectorChange(editor);
|
|
3872
|
+
handleSelectorChange();
|
|
2992
3873
|
}, [editor, handleSelectorChange, onChange, onSelectionChange, onValueChange]);
|
|
2993
3874
|
useEffect(() => {
|
|
2994
3875
|
EDITOR_TO_ON_CHANGE.set(editor, onContextChange);
|
|
@@ -3023,13 +3904,11 @@ var Slate = props => {
|
|
|
3023
3904
|
}, []);
|
|
3024
3905
|
return /*#__PURE__*/React.createElement(SlateSelectorContext.Provider, {
|
|
3025
3906
|
value: selectorContext
|
|
3026
|
-
}, /*#__PURE__*/React.createElement(SlateContext.Provider, {
|
|
3027
|
-
value: context
|
|
3028
3907
|
}, /*#__PURE__*/React.createElement(EditorContext.Provider, {
|
|
3029
|
-
value:
|
|
3908
|
+
value: editor
|
|
3030
3909
|
}, /*#__PURE__*/React.createElement(FocusedContext.Provider, {
|
|
3031
3910
|
value: isFocused
|
|
3032
|
-
}, children)))
|
|
3911
|
+
}, children)));
|
|
3033
3912
|
};
|
|
3034
3913
|
|
|
3035
3914
|
/**
|
|
@@ -3044,6 +3923,31 @@ var useEditor = () => {
|
|
|
3044
3923
|
return editor;
|
|
3045
3924
|
};
|
|
3046
3925
|
|
|
3926
|
+
/**
|
|
3927
|
+
* Get the current `selected` state of an element.
|
|
3928
|
+
*/
|
|
3929
|
+
var useSelected = () => {
|
|
3930
|
+
var element = useElementIf();
|
|
3931
|
+
// Breaking the rules of hooks is fine here since `!element` will remain true
|
|
3932
|
+
// or false for the entire lifetime of the component this hook is called from.
|
|
3933
|
+
// TODO: Decide if we want to throw an error instead when calling
|
|
3934
|
+
// `useSelected` outside of an element (potentially a breaking change).
|
|
3935
|
+
if (!element) return false;
|
|
3936
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
3937
|
+
var selector = useCallback(editor => {
|
|
3938
|
+
if (!editor.selection) return false;
|
|
3939
|
+
var path = ReactEditor.findPath(editor, element);
|
|
3940
|
+
var range = Editor.range(editor, path);
|
|
3941
|
+
return !!Range.intersection(range, editor.selection);
|
|
3942
|
+
}, [element]);
|
|
3943
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
3944
|
+
return useSlateSelector(selector, undefined, {
|
|
3945
|
+
// Defer the selector until after `Editable` has rendered so that the path
|
|
3946
|
+
// will be accurate.
|
|
3947
|
+
deferred: true
|
|
3948
|
+
});
|
|
3949
|
+
};
|
|
3950
|
+
|
|
3047
3951
|
/**
|
|
3048
3952
|
* Get the current slate selection.
|
|
3049
3953
|
* Only triggers a rerender when the selection actually changes
|
|
@@ -3070,8 +3974,10 @@ var withReact = function withReact(editor) {
|
|
|
3070
3974
|
var e = editor;
|
|
3071
3975
|
e = withDOM(e, clipboardFormatKey);
|
|
3072
3976
|
var {
|
|
3073
|
-
onChange
|
|
3977
|
+
onChange,
|
|
3978
|
+
apply
|
|
3074
3979
|
} = e;
|
|
3980
|
+
e.getChunkSize = () => null;
|
|
3075
3981
|
e.onChange = options => {
|
|
3076
3982
|
// COMPAT: React < 18 doesn't batch `setState` hook calls, which means
|
|
3077
3983
|
// that the children and selection can get out of sync for one render
|
|
@@ -3083,8 +3989,24 @@ var withReact = function withReact(editor) {
|
|
|
3083
3989
|
onChange(options);
|
|
3084
3990
|
});
|
|
3085
3991
|
};
|
|
3992
|
+
// On move_node, if the chunking optimization is enabled for the parent of the
|
|
3993
|
+
// node being moved, add the moved node to the movedNodeKeys set of the
|
|
3994
|
+
// parent's chunk tree.
|
|
3995
|
+
e.apply = operation => {
|
|
3996
|
+
if (operation.type === 'move_node') {
|
|
3997
|
+
var parent = Node.parent(e, operation.path);
|
|
3998
|
+
var chunking = !!e.getChunkSize(parent);
|
|
3999
|
+
if (chunking) {
|
|
4000
|
+
var node = Node.get(e, operation.path);
|
|
4001
|
+
var chunkTree = getChunkTreeForNode(e, parent);
|
|
4002
|
+
var key = ReactEditor.findKey(e, node);
|
|
4003
|
+
chunkTree.movedNodeKeys.add(key);
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
apply(operation);
|
|
4007
|
+
};
|
|
3086
4008
|
return e;
|
|
3087
4009
|
};
|
|
3088
4010
|
|
|
3089
|
-
export { DefaultElement, DefaultLeaf, DefaultPlaceholder, DefaultText, Editable, ReactEditor, Slate, useComposing, useEditor, useFocused, useReadOnly, useSelected, useSlate, useSlateSelection, useSlateSelector, useSlateStatic, useSlateWithV, withReact };
|
|
4011
|
+
export { DefaultElement, DefaultLeaf, DefaultPlaceholder, DefaultText, Editable, ReactEditor, Slate, useComposing, useEditor, useElement, useElementIf, useFocused, useReadOnly, useSelected, useSlate, useSlateSelection, useSlateSelector, useSlateStatic, useSlateWithV, withReact };
|
|
3090
4012
|
//# sourceMappingURL=index.es.js.map
|