@atlaskit/editor-plugin-block-controls 2.21.1 → 2.21.2

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.
@@ -1,8 +1,9 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  /**
2
3
  * @jsxRuntime classic
3
4
  * @jsx jsx
4
5
  */
5
- import { useEffect, useMemo, useRef, useState } from 'react';
6
+ import { Fragment, useEffect, useMemo, useRef, useState } from 'react';
6
7
 
7
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
8
9
  import { css, jsx } from '@emotion/react';
@@ -11,21 +12,27 @@ import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indi
11
12
  import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
12
13
  import { layers } from '@atlaskit/theme/constants';
13
14
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
15
+ import { getNodeAnchor } from '../pm-plugins/decorations-common';
16
+ import { useActiveAnchorTracker } from '../pm-plugins/utils/active-anchor-tracker';
17
+ import { isAnchorSupported } from '../pm-plugins/utils/anchor-utils';
14
18
  import { isBlocksDragTargetDebug } from '../pm-plugins/utils/drag-target-debug';
15
- import { dropTargetMarginMap, getNestedNodeLeftPaddingMargin, nodeMargins, spaceLookupMap } from './consts';
19
+ import { shouldAllowInlineDropTarget } from '../pm-plugins/utils/inline-drop-target';
20
+ import { getNestedNodeLeftPaddingMargin } from './consts';
21
+ import { InlineDropTarget } from './inline-drop-target';
16
22
  const DEFAULT_DROP_INDICATOR_WIDTH = 760;
17
23
  const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH = '--editor-block-controls-drop-indicator-width';
18
24
  const EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN = '--editor-block-controls-drop-target-leftMargin';
19
25
  const EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX = '--editor-block-controls-drop-target-zindex';
26
+ export const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET = '--editor-block-controls-drop-indicator-offset';
27
+ export const EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP = '--editor-block-controls-drop-indicator-gap';
20
28
  const styleDropTarget = css({
21
- height: "var(--ds-space-100, 8px)",
22
- marginTop: "var(--ds-space-negative-100, -8px)",
23
29
  marginLeft: `calc(-1 * var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN}, 0))`,
24
30
  paddingLeft: `var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN}, 0)`,
25
31
  position: 'absolute',
26
32
  left: '0',
27
33
  display: 'block',
28
- zIndex: `var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX}, 110)`
34
+ zIndex: `var(${EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX}, 110)`,
35
+ transform: `translateY(var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET}, 0))`
29
36
  });
30
37
  const styleDropIndicator = css({
31
38
  height: '100%',
@@ -36,168 +43,210 @@ const styleDropIndicator = css({
36
43
  const nestedDropIndicatorStyle = css({
37
44
  position: 'relative'
38
45
  });
39
- const marginLookupMap = Object.fromEntries(Object.entries(spaceLookupMap).map(([key, value], i) => [key,
40
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
41
- css({
42
- transform: `translateY(${value})`
43
- })]));
44
- const getNodeMargins = node => {
45
- if (!node) {
46
- return nodeMargins['default'];
47
- }
48
- const nodeTypeName = node.type.name;
49
- if (nodeTypeName === 'heading') {
50
- return nodeMargins[`heading${node.attrs.level}`] || nodeMargins['default'];
51
- }
52
- return nodeMargins[nodeTypeName] || nodeMargins['default'];
53
- };
54
- const getNestedDropTargetMarginTop = (prevNode, nextNode, isNestedDropTarget) => {
55
- if (!prevNode || !nextNode) {
56
- return css({
57
- marginTop: "var(--ds-space-negative-100, -8px)"
58
- });
59
- }
60
- const top = getNodeMargins(nextNode).top;
61
- const bottom = getNodeMargins(prevNode).bottom;
62
- if (['rule', 'media', 'mediaSingle'].includes(prevNode.type.name) && isNestedDropTarget && top > 0 && bottom > 0) {
63
- const collapsedMarginOffset = top === bottom ? top : Math.abs(top - bottom);
64
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
65
- const marginTop = dropTargetMarginMap[-collapsedMarginOffset - 8] || `-${collapsedMarginOffset + 8}px`;
66
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values
46
+ const dropZoneStyles = css({
47
+ margin: 0,
48
+ position: 'absolute',
49
+ width: '100%',
50
+ zIndex: 110,
51
+ minHeight: '4px'
52
+ });
53
+ const nestedDropZoneStyle = css({
54
+ left: '4px',
55
+ right: '4px',
56
+ width: 'unset'
57
+ });
58
+ const enableDropZone = ['paragraph', 'mediaSingle', 'heading', 'codeBlock', 'decisionList', 'bulletList', 'orderedList', 'taskList', 'extension', 'blockCard'];
59
+
60
+ // This z index is used in container like layout
61
+ const fullHeightStyleAdjustZIndexStyle = css({
62
+ zIndex: 0
63
+ });
64
+ const HoverZone = ({
65
+ onDragEnter,
66
+ onDragLeave,
67
+ onDrop,
68
+ node,
69
+ parent,
70
+ editorWidth,
71
+ anchorRectCache,
72
+ position,
73
+ isNestedDropTarget,
74
+ dropTargetStyle
75
+ }) => {
76
+ const ref = useRef(null);
77
+ const isRemainingheight = dropTargetStyle === 'remainingHeight';
78
+ const anchorName = useMemo(() => {
79
+ return node ? getNodeAnchor(node) : '';
80
+ }, [node]);
81
+ const [_isActive, setActiveAnchor] = useActiveAnchorTracker(anchorName);
82
+ useEffect(() => {
83
+ if (ref.current) {
84
+ return dropTargetForElements({
85
+ element: ref.current,
86
+ onDragEnter: () => {
87
+ if (!isNestedDropTarget && editorExperiment('advanced_layouts', true)) {
88
+ setActiveAnchor();
89
+ }
90
+ onDragEnter();
91
+ },
92
+ onDragLeave,
93
+ onDrop
94
+ });
95
+ }
96
+ }, [isNestedDropTarget, onDragEnter, onDragLeave, onDrop, setActiveAnchor]);
97
+ const hoverZoneUpperStyle = useMemo(() => {
98
+ const heightStyleOffset = `var(--editor-block-controls-drop-indicator-gap, 0)/2`;
99
+ const transformOffset = `var(${EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET}, 0)`;
100
+ const heightStyle = anchorName && enableDropZone.includes((node === null || node === void 0 ? void 0 : node.type.name) || '') ? isAnchorSupported() ? `calc(anchor-size(${anchorName} height)/2 + ${heightStyleOffset})` : `calc(${((anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.getHeight(anchorName)) || 0) / 2}px + ${heightStyleOffset})` : '4px';
101
+ const transform = position === 'upper' ? `translateY(calc(-100% + ${transformOffset}))` : `translateY(${transformOffset})`;
67
102
  return css({
68
- marginTop
103
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
104
+ height: heightStyle,
105
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
106
+ transform: transform,
107
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
108
+ maxWidth: `${editorWidth || 0}px`
69
109
  });
70
- }
71
- };
72
- const getDropTargetOffsetStyle = (prevNode, nextNode) => {
73
- if (!prevNode || !nextNode) {
74
- return null;
75
- }
76
- const top = getNodeMargins(nextNode).top;
77
- const bottom = getNodeMargins(prevNode).bottom;
78
- const marginDiff = Math.round((top - bottom) / 2);
79
- if (marginDiff === 0) {
110
+ }, [anchorName, anchorRectCache, editorWidth, node === null || node === void 0 ? void 0 : node.type.name, position]);
111
+
112
+ /**
113
+ * 1. Above the last empty line
114
+ * 2. Below the last element
115
+ *
116
+ * Both cases will take the remaining height of the the container
117
+ */
118
+ const heightStyle = useMemo(() => {
119
+ // only apply upper drop zone
120
+ if (isRemainingheight && position === 'upper') {
121
+ // previous node
122
+ const anchorName = node ? getNodeAnchor(node) : '';
123
+ let top = 'unset';
124
+ if (anchorName) {
125
+ const enabledDropZone = enableDropZone.includes((node === null || node === void 0 ? void 0 : node.type.name) || '');
126
+ if (isAnchorSupported()) {
127
+ top = enabledDropZone ? `calc(anchor(${anchorName} 50%))` : `calc(anchor(${anchorName} bottom) - 4px)`;
128
+ } else if (anchorRectCache) {
129
+ const preNodeTopPos = anchorRectCache.getTop(anchorName) || 0;
130
+ const prevNodeHeight = anchorRectCache.getHeight(anchorName) || 0;
131
+ top = enabledDropZone ? `calc(${preNodeTopPos}px + ${prevNodeHeight / 2}px)` : `calc(${preNodeTopPos}px + ${prevNodeHeight}px - 4px)`;
132
+ } else {
133
+ // Should not happen
134
+ return null;
135
+ }
136
+ } else {
137
+ // first empty paragraph
138
+ top = '4px';
139
+ }
140
+ return css({
141
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values
142
+ top: top,
143
+ bottom: '4px',
144
+ height: 'unset',
145
+ zIndex: 10,
146
+ transform: 'none'
147
+ });
148
+ }
80
149
  return null;
81
- }
82
- const offset = Math.max(Math.min(marginDiff, 24), -24);
83
- return marginLookupMap[offset];
150
+ }, [anchorRectCache, isRemainingheight, node, position]);
151
+ const isFullHeightInLayout = isRemainingheight && (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'layoutColumn';
152
+ return jsx("div", {
153
+ ref: ref
154
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
155
+ ,
156
+ className: `drop-target-hover-zone-${position}`,
157
+ "data-testid": `drop-target-zone-${position}`
158
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
159
+ ,
160
+ css: [dropZoneStyles, isNestedDropTarget && nestedDropZoneStyle,
161
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
162
+ hoverZoneUpperStyle,
163
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
164
+ heightStyle, isFullHeightInLayout && fullHeightStyleAdjustZIndexStyle]
165
+ });
84
166
  };
85
- export const DropTarget = ({
86
- api,
87
- getPos,
88
- prevNode,
89
- nextNode,
90
- parentNode,
91
- formatMessage
92
- }) => {
93
- const ref = useRef(null);
167
+ export const DropTarget = props => {
168
+ var _api$blockControls;
169
+ const {
170
+ api,
171
+ getPos,
172
+ prevNode,
173
+ nextNode,
174
+ parentNode,
175
+ formatMessage,
176
+ anchorRectCache,
177
+ dropTargetStyle = 'default',
178
+ isSameLayout
179
+ } = props;
94
180
  const [isDraggedOver, setIsDraggedOver] = useState(false);
95
181
  const {
96
182
  widthState
97
183
  } = useSharedPluginState(api, ['width']);
98
184
  const isNestedDropTarget = (parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) !== 'doc';
99
- useEffect(() => {
100
- const element = ref.current;
101
- if (!element) {
185
+ const {
186
+ activeNode
187
+ } = (api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
188
+ const onDrop = () => {
189
+ if (!activeNode) {
102
190
  return;
103
191
  }
104
-
105
- // This should be moved to platform/packages/editor/editor-plugin-block-controls/src/pm-plugins/utils/validation.ts
106
- // Since we are moved to drop-target-v2
107
- // Place experiments here instead of just inside move-node.ts as it stops the drag marker from appearing.
108
- if (editorExperiment('nest-media-and-codeblock-in-quote', false)) {
109
- var _api$blockControls;
192
+ const pos = getPos();
193
+ if (activeNode && pos !== undefined) {
194
+ var _api$core, _api$blockControls2, _api$blockControls2$c;
110
195
  const {
111
- activeNode
112
- } = (api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
113
- const parentNodeType = parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name;
114
- const activeNodeType = activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType;
115
- if (parentNodeType === 'blockquote' && (activeNodeType === 'mediaGroup' || activeNodeType === 'mediaSingle' || activeNodeType === 'codeBlock')) {
116
- return;
117
- }
196
+ pos: start
197
+ } = activeNode;
198
+ api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.moveNode(start, pos, undefined, formatMessage));
118
199
  }
119
- if (editorExperiment('nested-expand-in-expand', false)) {
120
- var _api$blockControls2;
121
- const {
122
- activeNode
123
- } = (api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.sharedState.currentState()) || {};
124
- const parentNodeType = parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name;
125
- const activeNodeType = activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeType;
126
- if (parentNodeType === 'expand' && (activeNodeType === 'expand' || activeNodeType === 'nestedExpand')) {
127
- return;
128
- }
129
- }
130
- return dropTargetForElements({
131
- element,
132
- getIsSticky: () => true,
133
- onDragEnter: () => {
134
- setIsDraggedOver(true);
135
- },
136
- onDragLeave: () => {
137
- setIsDraggedOver(false);
138
- },
139
- onDrop: () => {
140
- var _api$blockControls3;
141
- const {
142
- activeNode
143
- } = (api === null || api === void 0 ? void 0 : (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.sharedState.currentState()) || {};
144
- if (!activeNode) {
145
- return;
146
- }
147
- const pos = getPos();
148
- if (activeNode && pos !== undefined) {
149
- var _api$core, _api$blockControls4, _api$blockControls4$c;
150
- const {
151
- pos: start
152
- } = activeNode;
153
- api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : (_api$blockControls4$c = _api$blockControls4.commands) === null || _api$blockControls4$c === void 0 ? void 0 : _api$blockControls4$c.moveNode(start, pos, undefined, formatMessage));
154
- }
155
- }
156
- });
157
- }, [api, formatMessage, getPos, parentNode]);
158
- const dropTargetOffsetStyle = useMemo(() => {
159
- /**
160
- * First child of a nested node.
161
- * Disable the position adjustment temporarily
162
- */
163
- if (parentNode === prevNode) {
164
- return null;
165
- }
166
- return getDropTargetOffsetStyle(prevNode, nextNode);
167
- }, [prevNode, nextNode, parentNode]);
168
- const dropTargetMarginTopStyles = useMemo(() => {
169
- if (parentNode === prevNode) {
170
- return null;
171
- }
172
- return getNestedDropTargetMarginTop(prevNode, nextNode, isNestedDropTarget);
173
- }, [prevNode, nextNode, parentNode, isNestedDropTarget]);
200
+ };
174
201
  const dynamicStyle = {
175
202
  width: isNestedDropTarget ? 'unset' : '100%',
176
203
  [EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_WIDTH]: isNestedDropTarget ? '100%' : `${(widthState === null || widthState === void 0 ? void 0 : widthState.lineLength) || DEFAULT_DROP_INDICATOR_WIDTH}px`,
177
204
  [EDITOR_BLOCK_CONTROLS_DROP_TARGET_LEFT_MARGIN]: isNestedDropTarget ? getNestedNodeLeftPaddingMargin(parentNode === null || parentNode === void 0 ? void 0 : parentNode.type.name) : '0',
178
205
  [EDITOR_BLOCK_CONTROLS_DROP_TARGET_ZINDEX]: editorExperiment('nested-dnd', true) ? layers.navigation() : layers.card()
179
206
  };
180
- return (
181
- // Note: Firefox has trouble with using a button element as the handle for drag and drop
182
- jsx("div", {
183
- css: [styleDropTarget,
184
- // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
185
- dropTargetOffsetStyle, isNestedDropTarget && nestedDropIndicatorStyle,
186
- // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
187
- dropTargetMarginTopStyles]
188
- // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
189
- ,
190
- style: dynamicStyle,
191
- ref: ref,
192
- "data-testid": "block-ctrl-drop-target"
193
- },
194
- // 4px gap to clear expand node border
195
- (isDraggedOver || isBlocksDragTargetDebug()) && jsx("div", {
196
- css: styleDropIndicator,
197
- "data-testid": "block-ctrl-drop-indicator"
198
- }, jsx(DropIndicator, {
199
- edge: "bottom",
200
- gap: "4px"
201
- })))
202
- );
207
+ return jsx(Fragment, null, jsx(HoverZone, {
208
+ onDragEnter: () => setIsDraggedOver(true),
209
+ onDragLeave: () => setIsDraggedOver(false),
210
+ onDrop: onDrop,
211
+ node: prevNode,
212
+ editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
213
+ anchorRectCache: anchorRectCache,
214
+ position: "upper",
215
+ isNestedDropTarget: isNestedDropTarget,
216
+ dropTargetStyle: dropTargetStyle
217
+ }), jsx("div", {
218
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
219
+ css: [styleDropTarget, isNestedDropTarget && nestedDropIndicatorStyle]
220
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
221
+ ,
222
+ style: dynamicStyle,
223
+ "data-testid": "block-ctrl-drop-target"
224
+ },
225
+ // 4px gap to clear expand node border
226
+ (isDraggedOver || isBlocksDragTargetDebug()) && jsx("div", {
227
+ css: styleDropIndicator,
228
+ "data-testid": "block-ctrl-drop-indicator"
229
+ }, jsx(DropIndicator, {
230
+ edge: "bottom"
231
+ }))), dropTargetStyle !== 'remainingHeight' && jsx(HoverZone, {
232
+ onDragEnter: () => setIsDraggedOver(true),
233
+ onDragLeave: () => setIsDraggedOver(false),
234
+ onDrop: onDrop,
235
+ node: nextNode,
236
+ parent: parentNode,
237
+ editorWidth: widthState === null || widthState === void 0 ? void 0 : widthState.lineLength,
238
+ anchorRectCache: anchorRectCache,
239
+ position: "lower",
240
+ isNestedDropTarget: isNestedDropTarget
241
+ }), shouldAllowInlineDropTarget(isNestedDropTarget, nextNode, isSameLayout, activeNode) && jsx(Fragment, null, jsx(InlineDropTarget
242
+ // Ignored via go/ees005
243
+ // eslint-disable-next-line react/jsx-props-no-spreading
244
+ , _extends({}, props, {
245
+ position: "left"
246
+ })), jsx(InlineDropTarget
247
+ // Ignored via go/ees005
248
+ // eslint-disable-next-line react/jsx-props-no-spreading
249
+ , _extends({}, props, {
250
+ position: "right"
251
+ }))));
203
252
  };
@@ -9,8 +9,8 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
11
11
  import { nodeMargins } from '../ui/consts';
12
+ import { DropTarget, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target';
12
13
  import { DropTargetLayout } from '../ui/drop-target-layout';
13
- import { DropTargetV2, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_GAP, EDITOR_BLOCK_CONTROLS_DROP_INDICATOR_OFFSET } from '../ui/drop-target-v2';
14
14
  import { getNestedDepth, TYPE_DROP_TARGET_DEC, unmountDecorations } from './decorations-common';
15
15
  import { maxLayoutColumnSupported } from './utils/consts';
16
16
  import { isBlocksDragTargetDebug } from './utils/drag-target-debug';
@@ -102,14 +102,14 @@ export var createDropTargetDecoration = function createDropTargetDecoration(pos,
102
102
  element.style.setProperty('display', 'block');
103
103
  if (fg('platform_editor_react18_plugin_portalprovider')) {
104
104
  nodeViewPortalProviderAPI.render(function () {
105
- return /*#__PURE__*/createElement(DropTargetV2, _objectSpread(_objectSpread({}, props), {}, {
105
+ return /*#__PURE__*/createElement(DropTarget, _objectSpread(_objectSpread({}, props), {}, {
106
106
  getPos: getPos,
107
107
  anchorRectCache: anchorRectCache,
108
108
  isSameLayout: isSameLayout
109
109
  }));
110
110
  }, element, key);
111
111
  } else {
112
- ReactDOM.render( /*#__PURE__*/createElement(DropTargetV2, _objectSpread(_objectSpread({}, props), {}, {
112
+ ReactDOM.render( /*#__PURE__*/createElement(DropTarget, _objectSpread(_objectSpread({}, props), {}, {
113
113
  getPos: getPos,
114
114
  anchorRectCache: anchorRectCache,
115
115
  isSameLayout: isSameLayout