@portabletext/editor 7.10.16 → 7.10.17
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/lib/{_chunks-dts/behavior.types.action.d.ts → behavior.types.action-CYtiRDck.d.ts} +260 -59
- package/lib/behavior.types.action-CYtiRDck.d.ts.map +1 -0
- package/lib/behavior.types.behavior-B_77VtQR.js +159 -0
- package/lib/behavior.types.behavior-B_77VtQR.js.map +1 -0
- package/lib/behaviors/index.d.ts +1 -1
- package/lib/behaviors/index.js +2 -35
- package/lib/get-container-BeXYKpoi.js +222 -0
- package/lib/get-container-BeXYKpoi.js.map +1 -0
- package/lib/get-parent-51Kzgaf9.js +237 -0
- package/lib/get-parent-51Kzgaf9.js.map +1 -0
- package/lib/get-path-sub-schema--2I4NJbG.js +513 -0
- package/lib/get-path-sub-schema--2I4NJbG.js.map +1 -0
- package/lib/index.d.ts +2 -67
- package/lib/index.js +16743 -18963
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.ts +1 -2
- package/lib/plugins/index.d.ts.map +1 -1
- package/lib/plugins/index.js +103 -41
- package/lib/plugins/index.js.map +1 -1
- package/lib/selector.is-at-the-start-of-block-gJIMWRpU.js +822 -0
- package/lib/selector.is-at-the-start-of-block-gJIMWRpU.js.map +1 -0
- package/lib/selectors/index.d.ts +1 -3
- package/lib/selectors/index.d.ts.map +1 -1
- package/lib/selectors/index.js +256 -215
- package/lib/selectors/index.js.map +1 -1
- package/lib/traversal/index.d.ts +1 -1
- package/lib/traversal/index.d.ts.map +1 -1
- package/lib/traversal/index.js +33 -52
- package/lib/traversal/index.js.map +1 -1
- package/lib/use-editor-CwNeVwVC.js +47 -0
- package/lib/use-editor-CwNeVwVC.js.map +1 -0
- package/lib/util.is-equal-selections-BF4WJtz5.js +25 -0
- package/lib/util.is-equal-selections-BF4WJtz5.js.map +1 -0
- package/lib/util.slice-blocks-DQnr9X2s.js +633 -0
- package/lib/util.slice-blocks-DQnr9X2s.js.map +1 -0
- package/lib/utils/index.d.ts +11 -39
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/index.js +87 -123
- package/lib/utils/index.js.map +1 -1
- package/package.json +18 -15
- package/lib/_chunks-dts/behavior.types.action.d.ts.map +0 -1
- package/lib/_chunks-dts/block-offset.d.ts +0 -10
- package/lib/_chunks-dts/block-offset.d.ts.map +0 -1
- package/lib/_chunks-dts/editor-selector.d.ts +0 -33
- package/lib/_chunks-dts/editor-selector.d.ts.map +0 -1
- package/lib/_chunks-dts/editor.d.ts +0 -99
- package/lib/_chunks-dts/editor.d.ts.map +0 -1
- package/lib/_chunks-es/get-container.js +0 -187
- package/lib/_chunks-es/get-container.js.map +0 -1
- package/lib/_chunks-es/get-parent.js +0 -195
- package/lib/_chunks-es/get-parent.js.map +0 -1
- package/lib/_chunks-es/get-path-sub-schema.js +0 -399
- package/lib/_chunks-es/get-path-sub-schema.js.map +0 -1
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +0 -947
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +0 -1
- package/lib/_chunks-es/use-editor.js +0 -20
- package/lib/_chunks-es/use-editor.js.map +0 -1
- package/lib/_chunks-es/util.is-equal-selections.js +0 -20
- package/lib/_chunks-es/util.is-equal-selections.js.map +0 -1
- package/lib/_chunks-es/util.slice-blocks.js +0 -720
- package/lib/_chunks-es/util.slice-blocks.js.map +0 -1
- package/lib/behaviors/index.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
import { a as getNodeChildren, i as getChildren, n as parentPath, r as getNode, t as getParent, u as isKeyedSegment } from "./get-parent-51Kzgaf9.js";
|
|
2
|
+
import { S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, i as getEnclosingBlock, l as getSibling, m as rangeEdges, o as getBlock, p as isTextBlockNode, t as getPathSubSchema, u as getNodes, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema--2I4NJbG.js";
|
|
3
|
+
import { d as getSelectionEndPoint$1, f as isSelectionCollapsed$1, g as isEqualSelectionPoints, m as getBlockEndPoint, n as isListBlock, p as getBlockStartPoint, t as sliceBlocks, u as getSelectionStartPoint$1, v as blockOffsetToSpanSelectionPoint, y as spanSelectionPointToBlockOffset } from "./util.slice-blocks-DQnr9X2s.js";
|
|
4
|
+
import { isSpan, isTextBlock } from "@portabletext/schema";
|
|
5
|
+
/**
|
|
6
|
+
* Returns true if the two ranges share at least one point.
|
|
7
|
+
*
|
|
8
|
+
* Two ranges overlap iff each one's start is at or before the other's end.
|
|
9
|
+
* Adjacent ranges that touch at a single point are considered overlapping.
|
|
10
|
+
*/
|
|
11
|
+
function rangesOverlap(rangeA, rangeB, root) {
|
|
12
|
+
let [startA, endA] = rangeEdges(rangeA, root), [startB, endB] = rangeEdges(rangeB, root);
|
|
13
|
+
return comparePoints(startA, endB, root) <= 0 && comparePoints(startB, endA, root) <= 0;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get the node at the given path if it is inline (a span or inline object).
|
|
17
|
+
*
|
|
18
|
+
* A node is inline if its parent is a text block. Returns the node narrowed
|
|
19
|
+
* to `PortableTextSpan | PortableTextObject`, or `undefined` if the node
|
|
20
|
+
* doesn't exist or is not inline.
|
|
21
|
+
*/
|
|
22
|
+
function getInline(snapshot, path) {
|
|
23
|
+
let entry = getNode(snapshot, path);
|
|
24
|
+
if (!(!entry || !isInline(snapshot, entry.path)) && !(!isSpanNode({ schema: snapshot.context.schema }, entry.node) && !isObject(snapshot, entry.node))) return {
|
|
25
|
+
node: entry.node,
|
|
26
|
+
path: entry.path
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the child (span or inline object) containing the focus selection,
|
|
31
|
+
* resolved at any depth.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
const getFocusChild = (snapshot) => {
|
|
36
|
+
let selection = snapshot.context.selection;
|
|
37
|
+
if (selection) return getInline(snapshot, selection.focus.path);
|
|
38
|
+
}, getFocusInlineObject = (snapshot) => {
|
|
39
|
+
let focusChild = getFocusChild(snapshot);
|
|
40
|
+
return focusChild && !isSpanNode(snapshot.context, focusChild.node) ? {
|
|
41
|
+
node: focusChild.node,
|
|
42
|
+
path: focusChild.path
|
|
43
|
+
} : void 0;
|
|
44
|
+
}, getFocusSpan = (snapshot) => {
|
|
45
|
+
let focusChild = getFocusChild(snapshot);
|
|
46
|
+
return focusChild && isSpan(snapshot.context, focusChild.node) ? {
|
|
47
|
+
node: focusChild.node,
|
|
48
|
+
path: focusChild.path
|
|
49
|
+
} : void 0;
|
|
50
|
+
}, getFocusBlock = (snapshot) => {
|
|
51
|
+
let selection = snapshot.context.selection;
|
|
52
|
+
if (selection) return getEnclosingBlock(snapshot, selection.focus.path);
|
|
53
|
+
}, getFocusTextBlock = (snapshot) => {
|
|
54
|
+
let focusBlock = getFocusBlock(snapshot);
|
|
55
|
+
return focusBlock && isTextBlock(snapshot.context, focusBlock.node) ? {
|
|
56
|
+
node: focusBlock.node,
|
|
57
|
+
path: focusBlock.path
|
|
58
|
+
} : void 0;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Set of types that are valid at the root of the editor's value: the
|
|
62
|
+
* configured text-block type plus every registered block-object type.
|
|
63
|
+
*
|
|
64
|
+
* The editor accepts these at the top level of `value` and uses them
|
|
65
|
+
* to validate input and as the implicit accept-list for any payload
|
|
66
|
+
* that escapes registered containers.
|
|
67
|
+
*/
|
|
68
|
+
function getRootAcceptedTypes(schema) {
|
|
69
|
+
return /* @__PURE__ */ new Set([schema.block.name, ...schema.blockObjects.map((blockObject) => blockObject.name)]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns the portion of the document's value covered by the selection,
|
|
73
|
+
* resolved at any depth.
|
|
74
|
+
*
|
|
75
|
+
* Containers fully inside the selection are preserved verbatim. Containers
|
|
76
|
+
* on the selection boundary are recursed into so only the selected portion
|
|
77
|
+
* of their content is kept. Text blocks on the boundary are span-sliced.
|
|
78
|
+
*
|
|
79
|
+
* The result preserves the full ancestor envelope around the selection. For
|
|
80
|
+
* the clipboard-shaped view that unwraps the envelope toward the selection's
|
|
81
|
+
* lowest common ancestor, see {@link getFragment}.
|
|
82
|
+
*
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
85
|
+
const getSelectedValue = (snapshot) => {
|
|
86
|
+
let selection = snapshot.context.selection;
|
|
87
|
+
if (!selection) return [];
|
|
88
|
+
let startPoint = getSelectionStartPoint$1(selection), endPoint = getSelectionEndPoint$1(selection);
|
|
89
|
+
return !startPoint || !endPoint ? [] : sliceArray({
|
|
90
|
+
context: snapshot.context,
|
|
91
|
+
blocks: snapshot.context.value,
|
|
92
|
+
pathPrefix: [],
|
|
93
|
+
fieldNameInPrefix: void 0,
|
|
94
|
+
startEdge: startPoint,
|
|
95
|
+
endEdge: endPoint
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
function sliceArray({ context, blocks, pathPrefix, fieldNameInPrefix, startEdge, endEdge, parent }) {
|
|
99
|
+
if (blocks.length === 0) return [];
|
|
100
|
+
let startIdx = resolveIndex(blocks, pathPrefix, startEdge), endIdx = resolveIndex(blocks, pathPrefix, endEdge);
|
|
101
|
+
if (startIdx === -1 || endIdx === -1) return [];
|
|
102
|
+
let [lo, hi, loEdge, hiEdge] = startIdx <= endIdx ? [
|
|
103
|
+
startIdx,
|
|
104
|
+
endIdx,
|
|
105
|
+
startEdge,
|
|
106
|
+
endEdge
|
|
107
|
+
] : [
|
|
108
|
+
endIdx,
|
|
109
|
+
startIdx,
|
|
110
|
+
endEdge,
|
|
111
|
+
startEdge
|
|
112
|
+
], result = [];
|
|
113
|
+
for (let i = lo; i <= hi; i++) {
|
|
114
|
+
let block = blocks[i], blockPath = [
|
|
115
|
+
...pathPrefix,
|
|
116
|
+
...fieldNameInPrefix ? [fieldNameInPrefix] : [],
|
|
117
|
+
{ _key: block._key }
|
|
118
|
+
], startPointForBlock = i === lo ? loEdge : "array-start", endPointForBlock = i === hi ? hiEdge : "array-end", startInside = edgeIsInside(startPointForBlock, blockPath), endInside = edgeIsInside(endPointForBlock, blockPath);
|
|
119
|
+
if (!startInside && !endInside) {
|
|
120
|
+
result.push(block);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (isTextBlock({ schema: context.schema }, block)) {
|
|
124
|
+
let sliced = sliceBoundaryTextBlock({
|
|
125
|
+
context,
|
|
126
|
+
block,
|
|
127
|
+
blockPath,
|
|
128
|
+
startEdge: startPointForBlock,
|
|
129
|
+
endEdge: endPointForBlock
|
|
130
|
+
});
|
|
131
|
+
sliced && result.push(sliced);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
let childInfo = getNodeChildren(context, block, parent);
|
|
135
|
+
if (!childInfo) {
|
|
136
|
+
result.push(block);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
let innerSliced = sliceArray({
|
|
140
|
+
context,
|
|
141
|
+
blocks: childInfo.children,
|
|
142
|
+
pathPrefix: blockPath,
|
|
143
|
+
fieldNameInPrefix: childInfo.fieldName,
|
|
144
|
+
startEdge: startPointForBlock,
|
|
145
|
+
endEdge: endPointForBlock,
|
|
146
|
+
parent: childInfo.parent
|
|
147
|
+
}), updatedBlock = { ...block };
|
|
148
|
+
updatedBlock[childInfo.fieldName] = innerSliced, result.push(updatedBlock);
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
function resolveIndex(blocks, pathPrefix, edge) {
|
|
153
|
+
return edge === "array-start" ? 0 : edge === "array-end" ? blocks.length - 1 : findBlockIndexForPoint(blocks, pathPrefix, edge);
|
|
154
|
+
}
|
|
155
|
+
function findBlockIndexForPoint(blocks, pathPrefix, point) {
|
|
156
|
+
let nodeSegmentIndex = pathPrefix.length;
|
|
157
|
+
nodeSegmentIndex < point.path.length && typeof point.path[nodeSegmentIndex] == "string" && nodeSegmentIndex++;
|
|
158
|
+
let segment = point.path[nodeSegmentIndex];
|
|
159
|
+
return segment === void 0 ? -1 : isKeyedSegment(segment) ? blocks.findIndex((block) => block._key === segment._key) : typeof segment == "number" && segment >= 0 && segment < blocks.length ? segment : -1;
|
|
160
|
+
}
|
|
161
|
+
function edgeIsInside(edge, blockPath) {
|
|
162
|
+
return edge === "array-start" || edge === "array-end" ? !1 : edge.path.length > blockPath.length;
|
|
163
|
+
}
|
|
164
|
+
function sliceBoundaryTextBlock({ context, block, blockPath, startEdge, endEdge }) {
|
|
165
|
+
if (!isTextBlock({ schema: context.schema }, block)) return block;
|
|
166
|
+
let firstChild = block.children[0], lastChild = block.children[block.children.length - 1], blockRelativeStart = stripPrefix(startEdge, blockPath, block, {
|
|
167
|
+
fallback: "block-start",
|
|
168
|
+
firstChild
|
|
169
|
+
}), blockRelativeEnd = stripPrefix(endEdge, blockPath, block, {
|
|
170
|
+
fallback: "block-end",
|
|
171
|
+
lastChild,
|
|
172
|
+
context
|
|
173
|
+
});
|
|
174
|
+
return sliceBlocks({
|
|
175
|
+
context: {
|
|
176
|
+
...context,
|
|
177
|
+
selection: {
|
|
178
|
+
anchor: blockRelativeStart,
|
|
179
|
+
focus: blockRelativeEnd
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
blocks: [block]
|
|
183
|
+
})[0];
|
|
184
|
+
}
|
|
185
|
+
function stripPrefix(edge, blockPath, block, opts) {
|
|
186
|
+
return edge !== "array-start" && edge !== "array-end" && edge.path.length > blockPath.length ? {
|
|
187
|
+
path: edge.path.slice(blockPath.length - 1),
|
|
188
|
+
offset: edge.offset
|
|
189
|
+
} : opts.fallback === "block-start" ? {
|
|
190
|
+
path: [
|
|
191
|
+
{ _key: block._key },
|
|
192
|
+
"children",
|
|
193
|
+
{ _key: opts.firstChild?._key ?? "" }
|
|
194
|
+
],
|
|
195
|
+
offset: 0
|
|
196
|
+
} : {
|
|
197
|
+
path: [
|
|
198
|
+
{ _key: block._key },
|
|
199
|
+
"children",
|
|
200
|
+
{ _key: opts.lastChild?._key ?? "" }
|
|
201
|
+
],
|
|
202
|
+
offset: opts.lastChild && opts.context && isSpan({ schema: opts.context.schema }, opts.lastChild) ? opts.lastChild.text.length : 0
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Returns the smallest top-level-valid fragment of the editor's value
|
|
207
|
+
* that covers the current selection.
|
|
208
|
+
*
|
|
209
|
+
* Starts from {@link getSelectedValue}'s envelope and unwraps it toward
|
|
210
|
+
* the selection's lowest common ancestor, stopping at the deepest level
|
|
211
|
+
* whose siblings are all root-accepted types. Intermediate single-child
|
|
212
|
+
* containers (a single row inside a table, a single cell inside a row)
|
|
213
|
+
* are walked through to look for a deeper unwrap target; an intermediate
|
|
214
|
+
* level with multiple siblings (the lowest common ancestor across two
|
|
215
|
+
* cells in one row) ends the walk and the last root-valid wrapping is
|
|
216
|
+
* returned.
|
|
217
|
+
*
|
|
218
|
+
* A selection whose endpoints terminate at the root level (collapsed at
|
|
219
|
+
* a root-level node, or expanded across root siblings without descending
|
|
220
|
+
* into them) is treated as the user pointing AT the named node(s) rather
|
|
221
|
+
* than INTO them; the envelope is returned as-is and the unwrap walk is
|
|
222
|
+
* skipped. This is how a chrome drag carries the container itself rather
|
|
223
|
+
* than its unwrapped content.
|
|
224
|
+
*
|
|
225
|
+
* Backs every registered clipboard converter, `editor.getFragment()`
|
|
226
|
+
* (which projects to blocks only), and the drag preview pipeline (which
|
|
227
|
+
* uses the paths to find DOM nodes). Exposed for custom converters and
|
|
228
|
+
* any consumer that needs the clipboard-shaped view of the current
|
|
229
|
+
* selection without redundant ancestor envelopes.
|
|
230
|
+
*
|
|
231
|
+
* @public
|
|
232
|
+
*/
|
|
233
|
+
const getFragment = (snapshot) => {
|
|
234
|
+
let envelope = getSelectedValue(snapshot);
|
|
235
|
+
if (envelope.length === 0) return [];
|
|
236
|
+
let selection = snapshot.context.selection;
|
|
237
|
+
if (selection && selection.anchor.path.length <= 1 && selection.focus.path.length <= 1) return envelope.map((block) => ({
|
|
238
|
+
node: block,
|
|
239
|
+
path: [{ _key: block._key }]
|
|
240
|
+
}));
|
|
241
|
+
let { schema, containers, value } = snapshot.context, rootAcceptedTypes = getRootAcceptedTypes(schema), textBlockName = schema.block.name, lastRootValid = envelope, lastRootValidPrefix = [], current = envelope, pathPrefix = [];
|
|
242
|
+
for (; current.length === 1;) {
|
|
243
|
+
let single = current[0], singlePath = [...pathPrefix, { _key: single._key }], container = resolveContainerAt(containers, value, singlePath);
|
|
244
|
+
if (!container || !("field" in container)) break;
|
|
245
|
+
let children = single[container.field.name];
|
|
246
|
+
if (!Array.isArray(children) || children.length === 0) break;
|
|
247
|
+
let childBlocks = children;
|
|
248
|
+
if (pathPrefix.push({ _key: single._key }, container.field.name), current = childBlocks, childBlocks.every((block) => block._type === textBlockName || rootAcceptedTypes.has(block._type))) {
|
|
249
|
+
lastRootValid = childBlocks, lastRootValidPrefix = [...pathPrefix];
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (childBlocks.length !== 1) break;
|
|
253
|
+
}
|
|
254
|
+
return lastRootValid.map((block) => ({
|
|
255
|
+
node: block,
|
|
256
|
+
path: [...lastRootValidPrefix, { _key: block._key }]
|
|
257
|
+
}));
|
|
258
|
+
}, getSelectionEndBlock = (snapshot) => {
|
|
259
|
+
let endPoint = getSelectionEndPoint$1(snapshot.context.selection);
|
|
260
|
+
if (endPoint) return getFocusBlock({
|
|
261
|
+
...snapshot,
|
|
262
|
+
context: {
|
|
263
|
+
...snapshot.context,
|
|
264
|
+
selection: {
|
|
265
|
+
anchor: endPoint,
|
|
266
|
+
focus: endPoint
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}, getSelectionStartBlock = (snapshot) => {
|
|
271
|
+
let startPoint = getSelectionStartPoint$1(snapshot.context.selection);
|
|
272
|
+
if (startPoint) return getFocusBlock({
|
|
273
|
+
...snapshot,
|
|
274
|
+
context: {
|
|
275
|
+
...snapshot.context,
|
|
276
|
+
selection: {
|
|
277
|
+
anchor: startPoint,
|
|
278
|
+
focus: startPoint
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Returns true if the supplied selection shares at least one point with the
|
|
285
|
+
* editor's current selection. Resolves at any container depth.
|
|
286
|
+
*
|
|
287
|
+
* Two selections that touch at a single endpoint share that point and are
|
|
288
|
+
* considered overlapping.
|
|
289
|
+
*
|
|
290
|
+
* @public
|
|
291
|
+
*/
|
|
292
|
+
function isOverlappingSelection(selection) {
|
|
293
|
+
return (snapshot) => {
|
|
294
|
+
let editorSelection = snapshot.context.selection;
|
|
295
|
+
return !selection || !editorSelection || !hasNode(snapshot, selection.anchor.path) || !hasNode(snapshot, selection.focus.path) || !hasNode(snapshot, editorSelection.anchor.path) || !hasNode(snapshot, editorSelection.focus.path) ? !1 : rangesOverlap(selection, editorSelection, { value: snapshot.context.value });
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* @public
|
|
300
|
+
*/
|
|
301
|
+
const isSelectionCollapsed = (snapshot) => isSelectionCollapsed$1(snapshot.context.selection), isSelectionExpanded$1 = (snapshot) => snapshot.context.selection !== null && !isSelectionCollapsed(snapshot), getSelectedBlocks = (snapshot) => {
|
|
302
|
+
let selection = snapshot.context.selection;
|
|
303
|
+
if (!selection) return [];
|
|
304
|
+
let startPoint = getSelectionStartPoint$1(selection), endPoint = getSelectionEndPoint$1(selection);
|
|
305
|
+
if (!startPoint || !endPoint) return [];
|
|
306
|
+
let startRootKey = startPoint.path.find(isKeyedSegment)?._key, endRootKey = endPoint.path.find(isKeyedSegment)?._key;
|
|
307
|
+
if (startRootKey && startRootKey === endRootKey) {
|
|
308
|
+
let block = getBlock(snapshot, [{ _key: startRootKey }]);
|
|
309
|
+
if (block) return [{
|
|
310
|
+
node: block.node,
|
|
311
|
+
path: block.path
|
|
312
|
+
}];
|
|
313
|
+
}
|
|
314
|
+
let result = [];
|
|
315
|
+
for (let entry of getNodes(snapshot, {
|
|
316
|
+
from: startPoint.path,
|
|
317
|
+
to: endPoint.path,
|
|
318
|
+
match: (_, path) => path.length === 1
|
|
319
|
+
})) {
|
|
320
|
+
let block = getBlock(snapshot, entry.path);
|
|
321
|
+
block && result.push({
|
|
322
|
+
node: block.node,
|
|
323
|
+
path: block.path
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return result;
|
|
327
|
+
}, isSelectingEntireBlocks = (snapshot) => {
|
|
328
|
+
if (!snapshot.context.selection) return !1;
|
|
329
|
+
let startPoint = snapshot.context.selection.backward ? snapshot.context.selection.focus : snapshot.context.selection.anchor, endPoint = snapshot.context.selection.backward ? snapshot.context.selection.anchor : snapshot.context.selection.focus, startBlock = getSelectionStartBlock(snapshot), endBlock = getSelectionEndBlock(snapshot);
|
|
330
|
+
if (!startBlock || !endBlock) return !1;
|
|
331
|
+
let startBlockStartPoint = getBlockStartPoint({
|
|
332
|
+
context: snapshot.context,
|
|
333
|
+
block: startBlock
|
|
334
|
+
}), endBlockEndPoint = getBlockEndPoint({
|
|
335
|
+
context: snapshot.context,
|
|
336
|
+
block: endBlock
|
|
337
|
+
});
|
|
338
|
+
return isEqualSelectionPoints(startBlockStartPoint, startPoint) && isEqualSelectionPoints(endBlockEndPoint, endPoint);
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* @public
|
|
342
|
+
*/
|
|
343
|
+
function isSelectionExpanded(selection) {
|
|
344
|
+
return selection ? !isSelectionCollapsed$1(selection) : !1;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* @public
|
|
348
|
+
*/
|
|
349
|
+
const getSelectionEndPoint = (snapshot) => {
|
|
350
|
+
if (snapshot.context.selection) return snapshot.context.selection.backward ? snapshot.context.selection.anchor : snapshot.context.selection.focus;
|
|
351
|
+
}, getNextSpan = (snapshot) => {
|
|
352
|
+
let point = getSelectionEndPoint(snapshot);
|
|
353
|
+
if (point) return getSibling(snapshot, point.path, {
|
|
354
|
+
direction: "next",
|
|
355
|
+
match: (node) => isSpan(snapshot.context, node)
|
|
356
|
+
});
|
|
357
|
+
}, getSelectionStartPoint = (snapshot) => {
|
|
358
|
+
if (snapshot.context.selection) return snapshot.context.selection.backward ? snapshot.context.selection.focus : snapshot.context.selection.anchor;
|
|
359
|
+
}, getPreviousSpan = (snapshot) => {
|
|
360
|
+
let point = getSelectionStartPoint(snapshot);
|
|
361
|
+
if (point) return getSibling(snapshot, point.path, {
|
|
362
|
+
direction: "previous",
|
|
363
|
+
match: (node) => isSpan(snapshot.context, node)
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
/**
|
|
367
|
+
* Returns the inline children (spans and inline objects) touched by the
|
|
368
|
+
* selection, resolved at any depth.
|
|
369
|
+
*
|
|
370
|
+
* @public
|
|
371
|
+
*/
|
|
372
|
+
function getSelectedChildren(options) {
|
|
373
|
+
let filter = options?.filter;
|
|
374
|
+
return (snapshot) => {
|
|
375
|
+
let startPoint = getSelectionStartPoint$1(snapshot.context.selection), endPoint = getSelectionEndPoint$1(snapshot.context.selection);
|
|
376
|
+
if (!startPoint || !endPoint) return [];
|
|
377
|
+
let startChildKey = startPoint.path.findLast(isKeyedSegment)?._key, endChildKey = endPoint.path.findLast(isKeyedSegment)?._key, result = [];
|
|
378
|
+
if (startChildKey && startChildKey === endChildKey && isInline(snapshot, startPoint.path)) {
|
|
379
|
+
let node = getNode(snapshot, startPoint.path);
|
|
380
|
+
if (node) {
|
|
381
|
+
let child = node.node, skip = !1;
|
|
382
|
+
child._key === startChildKey && isSpan(snapshot.context, child) && (startPoint.offset >= child.text.length && (skip = !0), endPoint.offset <= 0 && (skip = !0)), !skip && (!filter || filter(child)) && result.push({
|
|
383
|
+
node: child,
|
|
384
|
+
path: node.path
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
for (let entry of getNodes(snapshot, {
|
|
390
|
+
from: startPoint.path,
|
|
391
|
+
to: endPoint.path,
|
|
392
|
+
match: (_, path) => isInline(snapshot, path)
|
|
393
|
+
})) {
|
|
394
|
+
let child = entry.node;
|
|
395
|
+
child._key === startChildKey && isSpan(snapshot.context, child) && startPoint.offset >= child.text.length || child._key === endChildKey && isSpan(snapshot.context, child) && endPoint.offset <= 0 || filter && !filter(child) || result.push({
|
|
396
|
+
node: child,
|
|
397
|
+
path: entry.path
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return result;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Returns the spans touched by the selection, resolved at any depth.
|
|
405
|
+
*
|
|
406
|
+
* @public
|
|
407
|
+
*/
|
|
408
|
+
const getSelectedSpans = (snapshot) => snapshot.context.selection ? getSelectedChildren({ filter: (child) => isSpan(snapshot.context, child) })(snapshot) : [], getMarkState = (snapshot) => {
|
|
409
|
+
if (!snapshot.context.selection) return;
|
|
410
|
+
let selection = snapshot.context.selection;
|
|
411
|
+
if (getBlock(snapshot, selection.anchor.path)) {
|
|
412
|
+
let spanSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
413
|
+
snapshot,
|
|
414
|
+
blockOffset: {
|
|
415
|
+
path: selection.anchor.path,
|
|
416
|
+
offset: selection.anchor.offset
|
|
417
|
+
},
|
|
418
|
+
direction: selection.backward ? "backward" : "forward"
|
|
419
|
+
});
|
|
420
|
+
selection = spanSelectionPoint ? {
|
|
421
|
+
...selection,
|
|
422
|
+
anchor: spanSelectionPoint
|
|
423
|
+
} : selection;
|
|
424
|
+
}
|
|
425
|
+
if (getBlock(snapshot, selection.focus.path)) {
|
|
426
|
+
let spanSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
427
|
+
snapshot,
|
|
428
|
+
blockOffset: {
|
|
429
|
+
path: selection.focus.path,
|
|
430
|
+
offset: selection.focus.offset
|
|
431
|
+
},
|
|
432
|
+
direction: selection.backward ? "backward" : "forward"
|
|
433
|
+
});
|
|
434
|
+
selection = spanSelectionPoint ? {
|
|
435
|
+
...selection,
|
|
436
|
+
focus: spanSelectionPoint
|
|
437
|
+
} : selection;
|
|
438
|
+
}
|
|
439
|
+
let focusSpan = getFocusSpan({
|
|
440
|
+
...snapshot,
|
|
441
|
+
context: {
|
|
442
|
+
...snapshot.context,
|
|
443
|
+
selection
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
if (!focusSpan) return;
|
|
447
|
+
if (isSelectionExpanded(selection)) {
|
|
448
|
+
let spanInfo = getSelectedSpans({
|
|
449
|
+
...snapshot,
|
|
450
|
+
context: {
|
|
451
|
+
...snapshot.context,
|
|
452
|
+
selection
|
|
453
|
+
}
|
|
454
|
+
}).map((span) => {
|
|
455
|
+
let block = getParent(snapshot, span.path, { match: (node) => isTextBlock({ schema: snapshot.context.schema }, node) });
|
|
456
|
+
return {
|
|
457
|
+
marks: span.node.marks ?? [],
|
|
458
|
+
decoratorNames: getPathSubSchema(snapshot, span.path).decorators.map((decorator) => decorator.name),
|
|
459
|
+
markDefKeys: (block?.node.markDefs ?? []).map((markDef) => markDef._key)
|
|
460
|
+
};
|
|
461
|
+
}), candidateMarks = /* @__PURE__ */ new Set();
|
|
462
|
+
for (let { marks: spanMarks } of spanInfo) for (let mark of spanMarks) candidateMarks.add(mark);
|
|
463
|
+
let marks = [];
|
|
464
|
+
for (let candidate of candidateMarks) {
|
|
465
|
+
let isDecoratorSomewhere = spanInfo.some(({ decoratorNames }) => decoratorNames.includes(candidate)), active = !0;
|
|
466
|
+
for (let { marks: spanMarks, decoratorNames, markDefKeys } of spanInfo) if ((isDecoratorSomewhere ? decoratorNames.includes(candidate) : markDefKeys.includes(candidate)) && !spanMarks.includes(candidate)) {
|
|
467
|
+
active = !1;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
active && marks.push(candidate);
|
|
471
|
+
}
|
|
472
|
+
return {
|
|
473
|
+
state: "unchanged",
|
|
474
|
+
marks
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
let decorators = getPathSubSchema(snapshot, focusSpan.path).decorators.map((decorator) => decorator.name), marks = focusSpan.node.marks ?? [], marksWithoutAnnotations = marks.filter((mark) => decorators.includes(mark)), spanHasAnnotations = marks.length > marksWithoutAnnotations.length, spanIsEmpty = focusSpan.node.text.length === 0, atTheBeginningOfSpan = snapshot.context.selection.anchor.offset === 0, atTheEndOfSpan = snapshot.context.selection.anchor.offset === focusSpan.node.text.length, previousSpan = getPreviousSpan({
|
|
478
|
+
...snapshot,
|
|
479
|
+
context: {
|
|
480
|
+
...snapshot.context,
|
|
481
|
+
selection
|
|
482
|
+
}
|
|
483
|
+
}), nextSpan = getNextSpan({
|
|
484
|
+
...snapshot,
|
|
485
|
+
context: {
|
|
486
|
+
...snapshot.context,
|
|
487
|
+
selection
|
|
488
|
+
}
|
|
489
|
+
}), nextSpanAnnotations = nextSpan?.node?.marks?.filter((mark) => !decorators.includes(mark)) ?? [], spanAnnotations = marks.filter((mark) => !decorators.includes(mark)), previousSpanHasAnnotations = previousSpan ? previousSpan.node.marks?.some((mark) => !decorators.includes(mark)) : !1, previousSpanHasSameAnnotations = previousSpan ? previousSpan.node.marks?.filter((mark) => !decorators.includes(mark)).every((mark) => marks.includes(mark)) : !1, previousSpanHasSameAnnotation = previousSpan ? previousSpan.node.marks?.some((mark) => !decorators.includes(mark) && marks.includes(mark)) : !1, previousSpanHasSameMarks = previousSpan ? previousSpan.node.marks?.every((mark) => marks.includes(mark)) : !1, nextSpanSharesSomeAnnotations = spanAnnotations.some((mark) => nextSpanAnnotations?.includes(mark));
|
|
490
|
+
if (spanHasAnnotations && !spanIsEmpty) {
|
|
491
|
+
if (atTheBeginningOfSpan) {
|
|
492
|
+
if (previousSpanHasSameMarks || previousSpanHasSameAnnotations) return {
|
|
493
|
+
state: "changed",
|
|
494
|
+
previousMarks: marks,
|
|
495
|
+
marks: previousSpan?.node.marks ?? []
|
|
496
|
+
};
|
|
497
|
+
if (previousSpanHasSameAnnotation) return {
|
|
498
|
+
state: "unchanged",
|
|
499
|
+
marks: focusSpan.node.marks ?? []
|
|
500
|
+
};
|
|
501
|
+
if (!previousSpan) return {
|
|
502
|
+
state: "changed",
|
|
503
|
+
previousMarks: marks,
|
|
504
|
+
marks: []
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
if (atTheEndOfSpan) {
|
|
508
|
+
if (!nextSpan || nextSpanAnnotations.length > 0 && !nextSpanSharesSomeAnnotations) return {
|
|
509
|
+
state: "changed",
|
|
510
|
+
previousMarks: marks,
|
|
511
|
+
marks: []
|
|
512
|
+
};
|
|
513
|
+
if (nextSpanSharesSomeAnnotations && nextSpanAnnotations.length < spanAnnotations.length || !nextSpanSharesSomeAnnotations) return {
|
|
514
|
+
state: "changed",
|
|
515
|
+
previousMarks: marks,
|
|
516
|
+
marks: nextSpan?.node.marks ?? []
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return atTheBeginningOfSpan && !spanIsEmpty && previousSpan ? previousSpanHasAnnotations ? {
|
|
521
|
+
state: "changed",
|
|
522
|
+
marks,
|
|
523
|
+
previousMarks: previousSpan?.node.marks ?? []
|
|
524
|
+
} : {
|
|
525
|
+
state: "changed",
|
|
526
|
+
previousMarks: marks,
|
|
527
|
+
marks: (previousSpan?.node.marks ?? []).filter((mark) => decorators.includes(mark))
|
|
528
|
+
} : {
|
|
529
|
+
state: "unchanged",
|
|
530
|
+
marks
|
|
531
|
+
};
|
|
532
|
+
};
|
|
533
|
+
function getActiveAnnotationsMarks(snapshot) {
|
|
534
|
+
let schema = snapshot.context.schema;
|
|
535
|
+
return (getMarkState(snapshot)?.marks ?? []).filter((mark) => !schema.decorators.map((decorator) => decorator.name).includes(mark));
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Returns the text blocks touched by the selection, resolved at any depth.
|
|
539
|
+
*
|
|
540
|
+
* Walks the tree between the selection endpoints and returns every text
|
|
541
|
+
* block found, regardless of container nesting. For toolbar state and
|
|
542
|
+
* anywhere that needs "text blocks with text in the selection".
|
|
543
|
+
*
|
|
544
|
+
* @public
|
|
545
|
+
*/
|
|
546
|
+
const getSelectedTextBlocks = (snapshot) => {
|
|
547
|
+
let selection = snapshot.context.selection;
|
|
548
|
+
if (!selection) return [];
|
|
549
|
+
let startPoint = getSelectionStartPoint$1(selection), endPoint = getSelectionEndPoint$1(selection);
|
|
550
|
+
if (!startPoint || !endPoint) return [];
|
|
551
|
+
let startBlock = getEnclosingBlock(snapshot, startPoint.path), endBlock = getEnclosingBlock(snapshot, endPoint.path);
|
|
552
|
+
if (startBlock && endBlock && startBlock.node._key === endBlock.node._key && isTextBlock(snapshot.context, startBlock.node)) return [{
|
|
553
|
+
node: startBlock.node,
|
|
554
|
+
path: startBlock.path
|
|
555
|
+
}];
|
|
556
|
+
let result = [];
|
|
557
|
+
for (let entry of getNodes(snapshot, {
|
|
558
|
+
from: startPoint.path,
|
|
559
|
+
to: endPoint.path,
|
|
560
|
+
match: (node) => isTextBlock(snapshot.context, node)
|
|
561
|
+
})) isTextBlock(snapshot.context, entry.node) && result.push({
|
|
562
|
+
node: entry.node,
|
|
563
|
+
path: entry.path
|
|
564
|
+
});
|
|
565
|
+
return result;
|
|
566
|
+
};
|
|
567
|
+
function getActiveDecorators(snapshot) {
|
|
568
|
+
let decoratorState = snapshot.decoratorState, markState = getMarkState(snapshot), selectedBlocks = getSelectedTextBlocks(snapshot), decorators = /* @__PURE__ */ new Set();
|
|
569
|
+
for (let block of selectedBlocks) for (let decorator of getPathSubSchema(snapshot, block.path).decorators) decorators.add(decorator.name);
|
|
570
|
+
if (decorators.size === 0) for (let decorator of snapshot.context.schema.decorators) decorators.add(decorator.name);
|
|
571
|
+
let activeDecorators = (markState?.marks ?? []).filter((mark) => decorators.has(mark));
|
|
572
|
+
for (let decorator in decoratorState) decoratorState[decorator] === !1 ? activeDecorators = activeDecorators.filter((activeDecorator) => activeDecorator !== decorator) : decoratorState[decorator] === !0 && (activeDecorators.includes(decorator) || activeDecorators.push(decorator));
|
|
573
|
+
return activeDecorators;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Check whether an annotation is active in the given `snapshot`.
|
|
577
|
+
*
|
|
578
|
+
* @public
|
|
579
|
+
*/
|
|
580
|
+
function isActiveAnnotation(annotation, options) {
|
|
581
|
+
return (snapshot) => {
|
|
582
|
+
if ((options?.mode ?? "full") === "partial" && isSelectionExpanded$1(snapshot)) return getSelectedValue(snapshot).some((block) => {
|
|
583
|
+
if (!isTextBlock(snapshot.context, block)) return !1;
|
|
584
|
+
let annotationKeys = new Set((block.markDefs ?? []).filter((markDef) => markDef._type === annotation).map((markDef) => markDef._key));
|
|
585
|
+
return annotationKeys.size !== 0 && block.children.some((child) => isSpan(snapshot.context, child) && child.text.length > 0 && child.marks?.some((mark) => annotationKeys.has(mark)));
|
|
586
|
+
});
|
|
587
|
+
let selectionMarkDefs = getSelectedTextBlocks(snapshot).flatMap((block) => block.node.markDefs ?? []), activeAnnotations = getActiveAnnotationsMarks(snapshot);
|
|
588
|
+
return selectionMarkDefs.filter((markDef) => markDef._type === annotation && activeAnnotations.includes(markDef._key)).length > 0;
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* @public
|
|
593
|
+
*/
|
|
594
|
+
const getActiveAnnotations = (snapshot) => {
|
|
595
|
+
if (!snapshot.context.selection) return [];
|
|
596
|
+
let selectedBlocks = getSelectedTextBlocks(snapshot), markState = getMarkState(snapshot), decoratorNames = /* @__PURE__ */ new Set();
|
|
597
|
+
for (let block of selectedBlocks) for (let decorator of getPathSubSchema(snapshot, block.path).decorators) decoratorNames.add(decorator.name);
|
|
598
|
+
if (decoratorNames.size === 0) for (let decorator of snapshot.context.schema.decorators) decoratorNames.add(decorator.name);
|
|
599
|
+
let activeAnnotations = (markState?.marks ?? []).filter((mark) => !decoratorNames.has(mark));
|
|
600
|
+
return selectedBlocks.flatMap((block) => block.node.markDefs ?? []).filter((markDef) => activeAnnotations.includes(markDef._key));
|
|
601
|
+
}, getActiveListItem = (snapshot) => {
|
|
602
|
+
if (!snapshot.context.selection) return;
|
|
603
|
+
let selectedTextBlocks = getSelectedTextBlocks(snapshot), firstTextBlock = selectedTextBlocks.at(0);
|
|
604
|
+
if (!firstTextBlock) return;
|
|
605
|
+
let firstListItem = firstTextBlock.node.listItem;
|
|
606
|
+
if (firstListItem && selectedTextBlocks.filter((block) => getPathSubSchema(snapshot, block.path).lists.some((l) => l.name === firstListItem)).every((block) => block.node.listItem === firstListItem)) return firstListItem;
|
|
607
|
+
}, getActiveStyle = (snapshot) => {
|
|
608
|
+
if (!snapshot.context.selection) return;
|
|
609
|
+
let selectedTextBlocks = getSelectedTextBlocks(snapshot), firstTextBlock = selectedTextBlocks.at(0);
|
|
610
|
+
if (!firstTextBlock) return;
|
|
611
|
+
let firstStyle = firstTextBlock.node.style ?? getPathSubSchema(snapshot, firstTextBlock.path).styles.at(0)?.name;
|
|
612
|
+
if (firstStyle && selectedTextBlocks.filter((block) => getPathSubSchema(snapshot, block.path).styles.some((s) => s.name === firstStyle)).every((block) => (block.node.style ?? getPathSubSchema(snapshot, block.path).styles.at(0)?.name) === firstStyle)) return firstStyle;
|
|
613
|
+
}, getNextInlineObject = (snapshot) => {
|
|
614
|
+
let point = getSelectionEndPoint(snapshot);
|
|
615
|
+
if (point) return getSibling(snapshot, point.path, {
|
|
616
|
+
direction: "next",
|
|
617
|
+
match: (node) => isObject(snapshot, node)
|
|
618
|
+
});
|
|
619
|
+
}, getPreviousInlineObject = (snapshot) => {
|
|
620
|
+
let point = getSelectionStartPoint(snapshot);
|
|
621
|
+
if (point) return getSibling(snapshot, point.path, {
|
|
622
|
+
direction: "previous",
|
|
623
|
+
match: (node) => isObject(snapshot, node)
|
|
624
|
+
});
|
|
625
|
+
}, getSelectionText = (snapshot) => {
|
|
626
|
+
let selectedValue = getSelectedValue(snapshot);
|
|
627
|
+
return collectText(snapshot.context, selectedValue);
|
|
628
|
+
};
|
|
629
|
+
function collectText(context, blocks, parent) {
|
|
630
|
+
let text = "";
|
|
631
|
+
for (let block of blocks) {
|
|
632
|
+
if (isTextBlock(context, block)) {
|
|
633
|
+
for (let child of block.children) isSpan(context, child) && (text += child.text);
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
let childInfo = getNodeChildren(context, block, parent);
|
|
637
|
+
childInfo && (text += collectText(context, childInfo.children, childInfo.parent));
|
|
638
|
+
}
|
|
639
|
+
return text;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* @public
|
|
643
|
+
* Returns the selection of the of the word the caret is placed in.
|
|
644
|
+
* Note: Only returns a word selection if the current selection is collapsed
|
|
645
|
+
*/
|
|
646
|
+
const getCaretWordSelection = (snapshot) => {
|
|
647
|
+
if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return null;
|
|
648
|
+
let focusTextBlock = getFocusTextBlock(snapshot), selectionStartPoint = getSelectionStartPoint(snapshot), selectionStartOffset = selectionStartPoint ? spanSelectionPointToBlockOffset({
|
|
649
|
+
snapshot,
|
|
650
|
+
selectionPoint: selectionStartPoint
|
|
651
|
+
}) : void 0;
|
|
652
|
+
if (!focusTextBlock || !selectionStartPoint || !selectionStartOffset) return null;
|
|
653
|
+
let previousInlineObject = getPreviousInlineObject(snapshot), blockStartPoint = getBlockStartPoint({
|
|
654
|
+
context: snapshot.context,
|
|
655
|
+
block: focusTextBlock
|
|
656
|
+
}), textDirectlyBefore = getSelectionText({
|
|
657
|
+
...snapshot,
|
|
658
|
+
context: {
|
|
659
|
+
...snapshot.context,
|
|
660
|
+
selection: {
|
|
661
|
+
anchor: previousInlineObject ? {
|
|
662
|
+
path: previousInlineObject.path,
|
|
663
|
+
offset: 0
|
|
664
|
+
} : blockStartPoint,
|
|
665
|
+
focus: selectionStartPoint
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}).split(/\s+/).at(-1), nextInlineObject = getNextInlineObject(snapshot), blockEndPoint = getBlockEndPoint({
|
|
669
|
+
context: snapshot.context,
|
|
670
|
+
block: focusTextBlock
|
|
671
|
+
}), textDirectlyAfter = getSelectionText({
|
|
672
|
+
...snapshot,
|
|
673
|
+
context: {
|
|
674
|
+
...snapshot.context,
|
|
675
|
+
selection: {
|
|
676
|
+
anchor: selectionStartPoint,
|
|
677
|
+
focus: nextInlineObject ? {
|
|
678
|
+
path: nextInlineObject.path,
|
|
679
|
+
offset: 0
|
|
680
|
+
} : blockEndPoint
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}).split(/\s+/).at(0);
|
|
684
|
+
if ((textDirectlyBefore === void 0 || textDirectlyBefore === "") && (textDirectlyAfter === void 0 || textDirectlyAfter === "")) return null;
|
|
685
|
+
let caretWordStartOffset = textDirectlyBefore ? {
|
|
686
|
+
...selectionStartOffset,
|
|
687
|
+
offset: selectionStartOffset.offset - textDirectlyBefore.length
|
|
688
|
+
} : selectionStartOffset, caretWordEndOffset = textDirectlyAfter ? {
|
|
689
|
+
...selectionStartOffset,
|
|
690
|
+
offset: selectionStartOffset.offset + textDirectlyAfter.length
|
|
691
|
+
} : selectionStartOffset, caretWordStartSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
692
|
+
snapshot,
|
|
693
|
+
blockOffset: caretWordStartOffset,
|
|
694
|
+
direction: "backward"
|
|
695
|
+
}), caretWordEndSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
696
|
+
snapshot,
|
|
697
|
+
blockOffset: caretWordEndOffset,
|
|
698
|
+
direction: "forward"
|
|
699
|
+
});
|
|
700
|
+
if (!caretWordStartSelectionPoint || !caretWordEndSelectionPoint) return null;
|
|
701
|
+
let caretWordSelection = {
|
|
702
|
+
anchor: caretWordStartSelectionPoint,
|
|
703
|
+
focus: caretWordEndSelectionPoint
|
|
704
|
+
};
|
|
705
|
+
return isSelectionExpanded$1({
|
|
706
|
+
...snapshot,
|
|
707
|
+
context: {
|
|
708
|
+
...snapshot.context,
|
|
709
|
+
selection: caretWordSelection
|
|
710
|
+
}
|
|
711
|
+
}) ? caretWordSelection : null;
|
|
712
|
+
}, getFocusBlockObject = (snapshot) => {
|
|
713
|
+
let focusBlock = getFocusBlock(snapshot);
|
|
714
|
+
if (focusBlock && !isTextBlockNode(snapshot.context, focusBlock.node) && !isEditableContainer(snapshot, focusBlock.node, focusBlock.path)) return {
|
|
715
|
+
node: focusBlock.node,
|
|
716
|
+
path: focusBlock.path
|
|
717
|
+
};
|
|
718
|
+
}, getFocusListBlock = (snapshot) => {
|
|
719
|
+
let focusTextBlock = getFocusTextBlock(snapshot);
|
|
720
|
+
return focusTextBlock && isListBlock(snapshot.context, focusTextBlock.node) ? {
|
|
721
|
+
node: focusTextBlock.node,
|
|
722
|
+
path: focusTextBlock.path
|
|
723
|
+
} : void 0;
|
|
724
|
+
}, getLastBlock = (snapshot) => {
|
|
725
|
+
let focusBlock = getFocusBlock(snapshot);
|
|
726
|
+
if (focusBlock) {
|
|
727
|
+
let last = getChildren(snapshot, parentPath(focusBlock.path)).at(-1);
|
|
728
|
+
if (last) return getBlock(snapshot, last.path);
|
|
729
|
+
}
|
|
730
|
+
let node = snapshot.context.value.at(-1);
|
|
731
|
+
return node ? {
|
|
732
|
+
node,
|
|
733
|
+
path: [{ _key: node._key }]
|
|
734
|
+
} : void 0;
|
|
735
|
+
}, getNextBlock = (snapshot) => {
|
|
736
|
+
let selectionEndBlock = getSelectionEndBlock(snapshot);
|
|
737
|
+
if (!selectionEndBlock) return;
|
|
738
|
+
let next = getSibling(snapshot, selectionEndBlock.path, { direction: "next" });
|
|
739
|
+
if (next) return getBlock(snapshot, next.path);
|
|
740
|
+
}, getPreviousBlock = (snapshot) => {
|
|
741
|
+
let selectionStartBlock = getSelectionStartBlock(snapshot);
|
|
742
|
+
if (!selectionStartBlock) return;
|
|
743
|
+
let previous = getSibling(snapshot, selectionStartBlock.path, { direction: "previous" });
|
|
744
|
+
if (previous) return getBlock(snapshot, previous.path);
|
|
745
|
+
}, getSelectionEndChild = (snapshot) => {
|
|
746
|
+
let endPoint = getSelectionEndPoint$1(snapshot.context.selection);
|
|
747
|
+
if (endPoint) return getFocusChild({
|
|
748
|
+
...snapshot,
|
|
749
|
+
context: {
|
|
750
|
+
...snapshot.context,
|
|
751
|
+
selection: {
|
|
752
|
+
anchor: endPoint,
|
|
753
|
+
focus: endPoint
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
}, getSelectionStartChild = (snapshot) => {
|
|
758
|
+
let startPoint = getSelectionStartPoint$1(snapshot.context.selection);
|
|
759
|
+
if (startPoint) return getFocusChild({
|
|
760
|
+
...snapshot,
|
|
761
|
+
context: {
|
|
762
|
+
...snapshot.context,
|
|
763
|
+
selection: {
|
|
764
|
+
anchor: startPoint,
|
|
765
|
+
focus: startPoint
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
};
|
|
770
|
+
/**
|
|
771
|
+
* @public
|
|
772
|
+
*/
|
|
773
|
+
function isActiveDecorator(decorator) {
|
|
774
|
+
return (snapshot) => {
|
|
775
|
+
if (isSelectionExpanded$1(snapshot)) {
|
|
776
|
+
let inScopeSpans = getSelectedSpans(snapshot).filter((span) => getPathSubSchema(snapshot, span.path).decorators.some((d) => d.name === decorator));
|
|
777
|
+
return inScopeSpans.length > 0 && inScopeSpans.every((span) => span.node.marks?.includes(decorator));
|
|
778
|
+
}
|
|
779
|
+
return getActiveDecorators(snapshot).includes(decorator);
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* @public
|
|
784
|
+
*/
|
|
785
|
+
function isActiveListItem(listItem) {
|
|
786
|
+
return (snapshot) => getActiveListItem(snapshot) === listItem;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* @public
|
|
790
|
+
*/
|
|
791
|
+
function isActiveStyle(style) {
|
|
792
|
+
return (snapshot) => getActiveStyle(snapshot) === style;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* @public
|
|
796
|
+
*/
|
|
797
|
+
function isAtTheEndOfBlock(block) {
|
|
798
|
+
return (snapshot) => {
|
|
799
|
+
if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return !1;
|
|
800
|
+
let blockEndPoint = getBlockEndPoint({
|
|
801
|
+
context: snapshot.context,
|
|
802
|
+
block
|
|
803
|
+
});
|
|
804
|
+
return isEqualSelectionPoints(snapshot.context.selection.focus, blockEndPoint);
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* @public
|
|
809
|
+
*/
|
|
810
|
+
function isAtTheStartOfBlock(block) {
|
|
811
|
+
return (snapshot) => {
|
|
812
|
+
if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return !1;
|
|
813
|
+
let blockStartPoint = getBlockStartPoint({
|
|
814
|
+
context: snapshot.context,
|
|
815
|
+
block
|
|
816
|
+
});
|
|
817
|
+
return isEqualSelectionPoints(snapshot.context.selection.focus, blockStartPoint);
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
export { isSelectingEntireBlocks as A, getFocusTextBlock as B, getActiveAnnotationsMarks as C, getSelectionStartPoint as D, getPreviousSpan as E, getSelectionStartBlock as F, getInline as G, getFocusSpan as H, getSelectionEndBlock as I, rangesOverlap as K, getFragment as L, isSelectionExpanded$1 as M, isSelectionCollapsed as N, getNextSpan as O, isOverlappingSelection as P, getSelectedValue as R, getSelectedTextBlocks as S, getSelectedSpans as T, getFocusInlineObject as U, getFocusBlock as V, getFocusChild as W, getActiveStyle as _, isActiveDecorator as a, isActiveAnnotation as b, getPreviousBlock as c, getFocusListBlock as d, getFocusBlockObject as f, getNextInlineObject as g, getPreviousInlineObject as h, isActiveListItem as i, getSelectedBlocks as j, getSelectionEndPoint as k, getNextBlock as l, getSelectionText as m, isAtTheEndOfBlock as n, getSelectionStartChild as o, getCaretWordSelection as p, isActiveStyle as r, getSelectionEndChild as s, isAtTheStartOfBlock as t, getLastBlock as u, getActiveListItem as v, getMarkState as w, getActiveDecorators as x, getActiveAnnotations as y, getRootAcceptedTypes as z };
|
|
821
|
+
|
|
822
|
+
//# sourceMappingURL=selector.is-at-the-start-of-block-gJIMWRpU.js.map
|