UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

542 lines (541 loc) 24.2 kB
"use strict"; var selectionPoint = require("./selection-point.cjs"), selector_isSelectionExpanded = require("./selector.is-selection-expanded.cjs"), util_isEqualSelectionPoints = require("./util.is-equal-selection-points.cjs"), types = require("@sanity/types"); const getSelectionEndPoint = (snapshot) => { if (snapshot.context.selection) return snapshot.context.selection.backward ? snapshot.context.selection.anchor : snapshot.context.selection.focus; }, getSelectedSpans = (snapshot) => { if (!snapshot.context.selection) return []; const selectedSpans = [], startPoint = selector_isSelectionExpanded.getSelectionStartPoint(snapshot), endPoint = getSelectionEndPoint(snapshot); if (!startPoint || !endPoint) return selectedSpans; const startBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(startPoint), endBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(endPoint); if (!startBlockKey || !endBlockKey) return selectedSpans; const startSpanKey = selectionPoint.getChildKeyFromSelectionPoint(startPoint), endSpanKey = selectionPoint.getChildKeyFromSelectionPoint(endPoint); let startBlockFound = !1; for (const block of snapshot.context.value) if (block._key === startBlockKey && (startBlockFound = !0), !!selectionPoint.isTextBlock(snapshot.context, block)) { if (block._key === startBlockKey) { for (const child of block.children) if (selectionPoint.isSpan$1(snapshot.context, child)) { if (startSpanKey && child._key === startSpanKey) { if (startPoint.offset < child.text.length && selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }), startSpanKey === endSpanKey) break; continue; } if (endSpanKey && child._key === endSpanKey) { endPoint.offset > 0 && selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }); break; } selectedSpans.length > 0 && selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }); } if (startBlockKey === endBlockKey) break; continue; } if (block._key === endBlockKey) { for (const child of block.children) if (selectionPoint.isSpan$1(snapshot.context, child)) { if (endSpanKey && child._key === endSpanKey) { endPoint.offset > 0 && selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }); break; } selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }); } break; } if (startBlockFound) for (const child of block.children) selectionPoint.isSpan$1(snapshot.context, child) && selectedSpans.push({ node: child, path: [{ _key: block._key }, "children", { _key: child._key }] }); } return selectedSpans; }, getActiveAnnotations = (snapshot) => { if (!snapshot.context.selection) return []; const selectedBlocks = selector_isSelectionExpanded.getSelectedBlocks(snapshot), selectedSpans = getSelectedSpans(snapshot), focusSpan = selector_isSelectionExpanded.getFocusSpan(snapshot); if (selectedSpans.length === 0 || !focusSpan) return []; if (selectedSpans.length === 1 && selector_isSelectionExpanded.isSelectionCollapsed(snapshot)) { if (snapshot.context.selection.focus.offset === 0) return []; if (snapshot.context.selection.focus.offset === focusSpan.node.text.length) return []; } const activeAnnotations = snapshot.beta.activeAnnotations; return selectedBlocks.flatMap((block) => selectionPoint.isTextBlock(snapshot.context, block.node) ? block.node.markDefs ?? [] : []).filter((markDef) => activeAnnotations.includes(markDef._key)); }, getActiveListItem = (snapshot) => { if (!snapshot.context.selection) return; const selectedTextBlocks = selector_isSelectionExpanded.getSelectedBlocks(snapshot).map((block) => block.node).filter((block) => selectionPoint.isTextBlock(snapshot.context, block)), firstTextBlock = selectedTextBlocks.at(0); if (!firstTextBlock) return; const firstListItem = firstTextBlock.listItem; if (firstListItem && selectedTextBlocks.every((block) => block.listItem === firstListItem)) return firstListItem; }, getActiveStyle = (snapshot) => { if (!snapshot.context.selection) return; const selectedTextBlocks = selector_isSelectionExpanded.getSelectedBlocks(snapshot).map((block) => block.node).filter((block) => selectionPoint.isTextBlock(snapshot.context, block)), firstTextBlock = selectedTextBlocks.at(0); if (!firstTextBlock) return; const firstStyle = firstTextBlock.style; if (firstStyle && selectedTextBlocks.every((block) => block.style === firstStyle)) return firstStyle; }, getNextInlineObject = (snapshot) => { const focusTextBlock = selector_isSelectionExpanded.getFocusTextBlock(snapshot), selectionEndPoint = getSelectionEndPoint(snapshot), selectionEndPointChildKey = selectionEndPoint && types.isKeySegment(selectionEndPoint.path[2]) ? selectionEndPoint.path[2]._key : void 0; if (!focusTextBlock || !selectionEndPointChildKey) return; let endPointChildFound = !1, inlineObject; for (const child of focusTextBlock.node.children) { if (child._key === selectionEndPointChildKey) { endPointChildFound = !0; continue; } if (!selectionPoint.isSpan(snapshot.context, child) && endPointChildFound) { inlineObject = { node: child, path: [...focusTextBlock.path, "children", { _key: child._key }] }; break; } } return inlineObject; }, getCaretWordSelection = (snapshot) => { if (!snapshot.context.selection || !selector_isSelectionExpanded.isSelectionCollapsed(snapshot)) return null; const focusTextBlock = selector_isSelectionExpanded.getFocusTextBlock(snapshot), selectionStartPoint = selector_isSelectionExpanded.getSelectionStartPoint(snapshot), selectionStartOffset = selectionStartPoint ? selectionPoint.spanSelectionPointToBlockOffset({ context: snapshot.context, selectionPoint: selectionStartPoint }) : void 0; if (!focusTextBlock || !selectionStartPoint || !selectionStartOffset) return null; const previousInlineObject = selector_isSelectionExpanded.getPreviousInlineObject(snapshot), blockStartPoint = selectionPoint.getBlockStartPoint({ context: snapshot.context, block: focusTextBlock }), textDirectlyBefore = selector_isSelectionExpanded.getSelectionText({ context: { ...snapshot.context, selection: { anchor: previousInlineObject ? { path: previousInlineObject.path, offset: 0 } : blockStartPoint, focus: selectionStartPoint } } }).split(/\s+/).at(-1), nextInlineObject = getNextInlineObject(snapshot), blockEndPoint = util_isEqualSelectionPoints.getBlockEndPoint({ context: snapshot.context, block: focusTextBlock }), textDirectlyAfter = selector_isSelectionExpanded.getSelectionText({ context: { ...snapshot.context, selection: { anchor: selectionStartPoint, focus: nextInlineObject ? { path: nextInlineObject.path, offset: 0 } : blockEndPoint } } }).split(/\s+/).at(0); if ((textDirectlyBefore === void 0 || textDirectlyBefore === "") && (textDirectlyAfter === void 0 || textDirectlyAfter === "")) return null; const caretWordStartOffset = textDirectlyBefore ? { ...selectionStartOffset, offset: selectionStartOffset.offset - textDirectlyBefore.length } : selectionStartOffset, caretWordEndOffset = textDirectlyAfter ? { ...selectionStartOffset, offset: selectionStartOffset.offset + textDirectlyAfter.length } : selectionStartOffset, caretWordStartSelectionPoint = selectionPoint.blockOffsetToSpanSelectionPoint({ context: snapshot.context, blockOffset: caretWordStartOffset, direction: "backward" }), caretWordEndSelectionPoint = selectionPoint.blockOffsetToSpanSelectionPoint({ context: snapshot.context, blockOffset: caretWordEndOffset, direction: "forward" }); if (!caretWordStartSelectionPoint || !caretWordEndSelectionPoint) return null; const caretWordSelection = { anchor: caretWordStartSelectionPoint, focus: caretWordEndSelectionPoint }; return selector_isSelectionExpanded.isSelectionExpanded({ context: { ...snapshot.context, selection: caretWordSelection } }) ? caretWordSelection : null; }, getFocusInlineObject = (snapshot) => { const focusChild = selector_isSelectionExpanded.getFocusChild(snapshot); return focusChild && !types.isPortableTextSpan(focusChild.node) ? { node: focusChild.node, path: focusChild.path } : void 0; }, getSelectedTextBlocks = (snapshot) => { if (!snapshot.context.selection) return []; const selectedTextBlocks = [], startPoint = selectionPoint.getSelectionStartPoint(snapshot.context.selection), endPoint = selectionPoint.getSelectionEndPoint(snapshot.context.selection), startBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(startPoint), endBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(endPoint); if (!startBlockKey || !endBlockKey) return selectedTextBlocks; for (const block of snapshot.context.value) { if (block._key === startBlockKey) { if (selectionPoint.isTextBlock(snapshot.context, block) && selectedTextBlocks.push({ node: block, path: [{ _key: block._key }] }), startBlockKey === endBlockKey) break; continue; } if (block._key === endBlockKey) { selectionPoint.isTextBlock(snapshot.context, block) && selectedTextBlocks.push({ node: block, path: [{ _key: block._key }] }); break; } selectedTextBlocks.length > 0 && selectionPoint.isTextBlock(snapshot.context, block) && selectedTextBlocks.push({ node: block, path: [{ _key: block._key }] }); } return selectedTextBlocks; }, getTrimmedSelection = (snapshot) => { if (!snapshot.context.selection) return snapshot.context.selection; const startPoint = selectionPoint.getSelectionStartPoint(snapshot.context.selection), endPoint = selectionPoint.getSelectionEndPoint(snapshot.context.selection), startBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(startPoint), startChildKey = selectionPoint.getChildKeyFromSelectionPoint(startPoint), endBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(endPoint), endChildKey = selectionPoint.getChildKeyFromSelectionPoint(endPoint); if (!startBlockKey || !endBlockKey) return snapshot.context.selection; let startBlockFound = !1, adjustedStartPoint, trimStartPoint = !1, adjustedEndPoint, trimEndPoint = !1, previousPotentialEndpoint; for (const block of snapshot.context.value) if (!(block._key === startBlockKey && (startBlockFound = !0, selectionPoint.isTextBlock(snapshot.context, block) && util_isEqualSelectionPoints.isEmptyTextBlock(snapshot.context, block))) && startBlockFound && selectionPoint.isTextBlock(snapshot.context, block)) { if (block._key === endBlockKey && util_isEqualSelectionPoints.isEmptyTextBlock(snapshot.context, block)) break; for (const child of block.children) { if (child._key === endChildKey && (!selectionPoint.isSpan$1(snapshot.context, child) || endPoint.offset === 0)) { adjustedEndPoint = previousPotentialEndpoint ? { path: [{ _key: previousPotentialEndpoint.blockKey }, "children", { _key: previousPotentialEndpoint.span._key }], offset: previousPotentialEndpoint.span.text.length } : void 0, trimEndPoint = !0; break; } if (trimStartPoint) { const lonelySpan = selectionPoint.isSpan$1(snapshot.context, child) && block.children.length === 1; (selectionPoint.isSpan$1(snapshot.context, child) && child.text.length > 0 || lonelySpan) && (adjustedStartPoint = { path: [{ _key: block._key }, "children", { _key: child._key }], offset: 0 }, previousPotentialEndpoint = { blockKey: block._key, span: child }, trimStartPoint = !1); continue; } if (child._key === startChildKey) { if (!selectionPoint.isSpan$1(snapshot.context, child)) { trimStartPoint = !0; continue; } if (startPoint.offset === child.text.length) { trimStartPoint = !0, previousPotentialEndpoint = child.text.length > 0 ? { blockKey: block._key, span: child } : previousPotentialEndpoint; continue; } } previousPotentialEndpoint = selectionPoint.isSpan$1(snapshot.context, child) && child.text.length > 0 ? { blockKey: block._key, span: child } : previousPotentialEndpoint; } if (block._key === endBlockKey) break; } const trimmedSelection = snapshot.context.selection.backward ? { anchor: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint, focus: adjustedStartPoint ?? startPoint, backward: !0 } : { anchor: adjustedStartPoint ?? startPoint, focus: trimEndPoint && adjustedEndPoint ? adjustedEndPoint : endPoint }; if (selector_isSelectionExpanded.isSelectionCollapsed({ context: { ...snapshot.context, selection: trimmedSelection } })) { const focusTextBlock = selector_isSelectionExpanded.getFocusTextBlock({ context: { ...snapshot.context, selection: trimmedSelection } }); if (focusTextBlock && !util_isEqualSelectionPoints.isEmptyTextBlock(snapshot.context, focusTextBlock.node)) return null; } return trimmedSelection; }; function isActiveAnnotation(annotation) { return (snapshot) => selector_isSelectionExpanded.getSelectedBlocks(snapshot).flatMap((block) => selectionPoint.isTextBlock(snapshot.context, block.node) ? block.node.markDefs ?? [] : []).filter((markDef) => markDef._type === annotation && snapshot.beta.activeAnnotations.includes(markDef._key)).length > 0; } function isActiveDecorator(decorator) { return (snapshot) => { if (selector_isSelectionExpanded.isSelectionExpanded(snapshot)) { const selectedSpans = getSelectedSpans(snapshot); return selectedSpans.length > 0 && selectedSpans.every((span) => span.node.marks?.includes(decorator)); } return snapshot.beta.activeDecorators.includes(decorator); }; } function isActiveListItem(listItem) { return (snapshot) => getActiveListItem(snapshot) === listItem; } function isActiveStyle(style) { return (snapshot) => getActiveStyle(snapshot) === style; } function isAtTheEndOfBlock(block) { return (snapshot) => { if (!snapshot.context.selection || !selector_isSelectionExpanded.isSelectionCollapsed(snapshot)) return !1; const blockEndPoint = util_isEqualSelectionPoints.getBlockEndPoint({ context: snapshot.context, block }); return util_isEqualSelectionPoints.isEqualSelectionPoints(snapshot.context.selection.focus, blockEndPoint); }; } function isAtTheStartOfBlock(block) { return (snapshot) => { if (!snapshot.context.selection || !selector_isSelectionExpanded.isSelectionCollapsed(snapshot)) return !1; const blockStartPoint = selectionPoint.getBlockStartPoint({ context: snapshot.context, block }); return util_isEqualSelectionPoints.isEqualSelectionPoints(snapshot.context.selection.focus, blockStartPoint); }; } function isPointAfterSelection(point) { return (snapshot) => { if (!snapshot.context.selection) return !1; const endPoint = selectionPoint.getSelectionEndPoint(snapshot.context.selection), endBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(endPoint), endChildKey = selectionPoint.getChildKeyFromSelectionPoint(endPoint), pointBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(point), pointChildKey = selectionPoint.getChildKeyFromSelectionPoint(point); if (!pointBlockKey || !endBlockKey) return !1; let after = !1; for (const block of snapshot.context.value) { if (block._key === endBlockKey) { if (block._key !== pointBlockKey) { after = !0; break; } if (!selectionPoint.isTextBlock(snapshot.context, block) || !pointChildKey || !endChildKey) break; for (const child of block.children) { if (child._key === endChildKey) { if (child._key !== pointChildKey) { after = !0; break; } after = point.offset > endPoint.offset; break; } if (child._key === pointChildKey) break; } } if (block._key === pointBlockKey) break; } return after; }; } function isPointBeforeSelection(point) { return (snapshot) => { if (!snapshot.context.selection) return !1; const startPoint = selectionPoint.getSelectionStartPoint(snapshot.context.selection), startBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(startPoint), startChildKey = selectionPoint.getChildKeyFromSelectionPoint(startPoint), pointBlockKey = selectionPoint.getBlockKeyFromSelectionPoint(point), pointChildKey = selectionPoint.getChildKeyFromSelectionPoint(point); if (!pointBlockKey || !startBlockKey) return !1; let before = !1; for (const block of snapshot.context.value) { if (block._key === pointBlockKey) { if (block._key !== startBlockKey) { before = !0; break; } if (!selectionPoint.isTextBlock(snapshot.context, block) || !pointChildKey || !startChildKey) break; for (const child of block.children) { if (child._key === pointChildKey) { if (child._key !== startChildKey) { before = !0; break; } before = point.offset < startPoint.offset; break; } if (child._key === startChildKey) break; } } if (block._key === startBlockKey) break; } return before; }; } function isOverlappingSelection(selection) { return (snapshot) => { if (!selection || !snapshot.context.selection) return !1; const selectionStartPoint = selector_isSelectionExpanded.getSelectionStartPoint({ context: { ...snapshot.context, selection } }), selectionEndPoint = getSelectionEndPoint({ context: { ...snapshot.context, selection } }), originalSelectionStartPoint = selector_isSelectionExpanded.getSelectionStartPoint(snapshot), originalSelectionEndPoint = getSelectionEndPoint(snapshot); if (!selectionStartPoint || !selectionEndPoint || !originalSelectionStartPoint || !originalSelectionEndPoint) return !1; const startPointBeforeSelection = isPointBeforeSelection(selectionStartPoint)(snapshot), startPointAfterSelection = isPointAfterSelection(selectionStartPoint)(snapshot), endPointBeforeSelection = isPointBeforeSelection(selectionEndPoint)(snapshot), endPointAfterSelection = isPointAfterSelection(selectionEndPoint)(snapshot), originalStartPointBeforeStartPoint = isPointBeforeSelection(originalSelectionStartPoint)({ ...snapshot, context: { ...snapshot.context, selection: { anchor: selectionStartPoint, focus: selectionStartPoint } } }), originalStartPointAfterStartPoint = isPointAfterSelection(originalSelectionStartPoint)({ ...snapshot, context: { ...snapshot.context, selection: { anchor: selectionStartPoint, focus: selectionStartPoint } } }), originalEndPointBeforeEndPoint = isPointBeforeSelection(originalSelectionEndPoint)({ ...snapshot, context: { ...snapshot.context, selection: { anchor: selectionEndPoint, focus: selectionEndPoint } } }), originalEndPointAfterEndPoint = isPointAfterSelection(originalSelectionEndPoint)({ ...snapshot, context: { ...snapshot.context, selection: { anchor: selectionEndPoint, focus: selectionEndPoint } } }), endPointEqualToOriginalStartPoint = util_isEqualSelectionPoints.isEqualSelectionPoints(selectionEndPoint, originalSelectionStartPoint), startPointEqualToOriginalEndPoint = util_isEqualSelectionPoints.isEqualSelectionPoints(selectionStartPoint, originalSelectionEndPoint); return endPointBeforeSelection && !endPointEqualToOriginalStartPoint || startPointAfterSelection && !startPointEqualToOriginalEndPoint ? !1 : !originalStartPointBeforeStartPoint && originalStartPointAfterStartPoint && !originalEndPointBeforeEndPoint && originalEndPointAfterEndPoint ? !endPointEqualToOriginalStartPoint : originalStartPointBeforeStartPoint && !originalStartPointAfterStartPoint && originalEndPointBeforeEndPoint && !originalEndPointAfterEndPoint ? !startPointEqualToOriginalEndPoint : !startPointAfterSelection || !startPointBeforeSelection || !endPointAfterSelection || !endPointBeforeSelection; }; } const isSelectingEntireBlocks = (snapshot) => { if (!snapshot.context.selection) return !1; const 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 = selector_isSelectionExpanded.getSelectionStartBlock(snapshot), endBlock = selector_isSelectionExpanded.getSelectionEndBlock(snapshot); if (!startBlock || !endBlock) return !1; const startBlockStartPoint = selectionPoint.getBlockStartPoint({ context: snapshot.context, block: startBlock }), endBlockEndPoint = util_isEqualSelectionPoints.getBlockEndPoint({ context: snapshot.context, block: endBlock }); return util_isEqualSelectionPoints.isEqualSelectionPoints(startBlockStartPoint, startPoint) && util_isEqualSelectionPoints.isEqualSelectionPoints(endBlockEndPoint, endPoint); }; exports.getActiveAnnotations = getActiveAnnotations; exports.getActiveListItem = getActiveListItem; exports.getActiveStyle = getActiveStyle; exports.getCaretWordSelection = getCaretWordSelection; exports.getFocusInlineObject = getFocusInlineObject; exports.getNextInlineObject = getNextInlineObject; exports.getSelectedSpans = getSelectedSpans; exports.getSelectedTextBlocks = getSelectedTextBlocks; exports.getSelectionEndPoint = getSelectionEndPoint; exports.getTrimmedSelection = getTrimmedSelection; exports.isActiveAnnotation = isActiveAnnotation; exports.isActiveDecorator = isActiveDecorator; exports.isActiveListItem = isActiveListItem; exports.isActiveStyle = isActiveStyle; exports.isAtTheEndOfBlock = isAtTheEndOfBlock; exports.isAtTheStartOfBlock = isAtTheStartOfBlock; exports.isOverlappingSelection = isOverlappingSelection; exports.isPointAfterSelection = isPointAfterSelection; exports.isPointBeforeSelection = isPointBeforeSelection; exports.isSelectingEntireBlocks = isSelectingEntireBlocks; //# sourceMappingURL=selector.is-selecting-entire-blocks.cjs.map