UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

454 lines (453 loc) 19.4 kB
"use strict"; var util_sliceBlocks = require("./util.slice-blocks.cjs"), types = require("@sanity/types"); const isSelectionCollapsed = (snapshot) => snapshot.context.selection ? JSON.stringify(snapshot.context.selection.anchor.path) === JSON.stringify(snapshot.context.selection.focus.path) && snapshot.context.selection?.anchor.offset === snapshot.context.selection?.focus.offset : !1; function createGuards({ schema }) { function isListBlock(block) { return types.isPortableTextListBlock(block) && block._type === schema.block.name; } function isTextBlock(block) { return types.isPortableTextTextBlock(block) && block._type === schema.block.name; } return { isListBlock, isTextBlock }; } const getFocusBlock = (snapshot) => { const key = snapshot.context.selection && types.isKeySegment(snapshot.context.selection.focus.path[0]) ? snapshot.context.selection.focus.path[0]._key : void 0, node = key ? snapshot.context.value.find((block) => block._key === key) : void 0; return node && key ? { node, path: [{ _key: key }] } : void 0; }, getFocusListBlock = (snapshot) => { const guards = createGuards(snapshot.context), focusBlock = getFocusBlock(snapshot); return focusBlock && guards.isListBlock(focusBlock.node) ? { node: focusBlock.node, path: focusBlock.path } : void 0; }, getFocusTextBlock = (snapshot) => { const focusBlock = getFocusBlock(snapshot); return focusBlock && types.isPortableTextTextBlock(focusBlock.node) ? { node: focusBlock.node, path: focusBlock.path } : void 0; }, getFocusBlockObject = (snapshot) => { const focusBlock = getFocusBlock(snapshot); return focusBlock && !types.isPortableTextTextBlock(focusBlock.node) ? { node: focusBlock.node, path: focusBlock.path } : void 0; }, getFocusChild = (snapshot) => { const focusBlock = getFocusTextBlock(snapshot); if (!focusBlock) return; const key = snapshot.context.selection && types.isKeySegment(snapshot.context.selection.focus.path[2]) ? snapshot.context.selection.focus.path[2]._key : void 0, node = key ? focusBlock.node.children.find((span) => span._key === key) : void 0; return node && key ? { node, path: [...focusBlock.path, "children", { _key: key }] } : void 0; }, getFocusSpan = (snapshot) => { const focusChild = getFocusChild(snapshot); return focusChild && types.isPortableTextSpan(focusChild.node) ? { node: focusChild.node, path: focusChild.path } : void 0; }, getFirstBlock = (snapshot) => { const node = snapshot.context.value[0]; return node ? { node, path: [{ _key: node._key }] } : void 0; }, getLastBlock = (snapshot) => { const node = snapshot.context.value[snapshot.context.value.length - 1] ? snapshot.context.value[snapshot.context.value.length - 1] : void 0; return node ? { node, path: [{ _key: node._key }] } : void 0; }, getSelectedBlocks = (snapshot) => { if (!snapshot.context.selection) return []; const selectedBlocks = [], startKey = snapshot.context.selection.backward ? types.isKeySegment(snapshot.context.selection.focus.path[0]) ? snapshot.context.selection.focus.path[0]._key : void 0 : types.isKeySegment(snapshot.context.selection.anchor.path[0]) ? snapshot.context.selection.anchor.path[0]._key : void 0, endKey = snapshot.context.selection.backward ? types.isKeySegment(snapshot.context.selection.anchor.path[0]) ? snapshot.context.selection.anchor.path[0]._key : void 0 : types.isKeySegment(snapshot.context.selection.focus.path[0]) ? snapshot.context.selection.focus.path[0]._key : void 0; if (!startKey || !endKey) return selectedBlocks; for (const block of snapshot.context.value) { if (block._key === startKey) { if (selectedBlocks.push({ node: block, path: [{ _key: block._key }] }), startKey === endKey) break; continue; } if (block._key === endKey) { selectedBlocks.push({ node: block, path: [{ _key: block._key }] }); break; } selectedBlocks.length > 0 && selectedBlocks.push({ node: block, path: [{ _key: block._key }] }); } return selectedBlocks; }, getSelectionStartBlock = (snapshot) => { if (!snapshot.context.selection) return; const key = snapshot.context.selection.backward ? types.isKeySegment(snapshot.context.selection.focus.path[0]) ? snapshot.context.selection.focus.path[0]._key : void 0 : types.isKeySegment(snapshot.context.selection.anchor.path[0]) ? snapshot.context.selection.anchor.path[0]._key : void 0, node = key ? snapshot.context.value.find((block) => block._key === key) : void 0; return node && key ? { node, path: [{ _key: key }] } : void 0; }, getSelectionEndBlock = (snapshot) => { if (!snapshot.context.selection) return; const key = snapshot.context.selection.backward ? types.isKeySegment(snapshot.context.selection.anchor.path[0]) ? snapshot.context.selection.anchor.path[0]._key : void 0 : types.isKeySegment(snapshot.context.selection.focus.path[0]) ? snapshot.context.selection.focus.path[0]._key : void 0, node = key ? snapshot.context.value.find((block) => block._key === key) : void 0; return node && key ? { node, path: [{ _key: key }] } : void 0; }, getPreviousBlock = (snapshot) => { let previousBlock; const selectionStartBlock = getSelectionStartBlock(snapshot); if (!selectionStartBlock) return; let foundSelectionStartBlock = !1; for (const block of snapshot.context.value) { if (block._key === selectionStartBlock.node._key) { foundSelectionStartBlock = !0; break; } previousBlock = { node: block, path: [{ _key: block._key }] }; } if (foundSelectionStartBlock && previousBlock) return previousBlock; }, getNextBlock = (snapshot) => { let nextBlock; const selectionEndBlock = getSelectionEndBlock(snapshot); if (!selectionEndBlock) return; let foundSelectionEndBlock = !1; for (const block of snapshot.context.value) { if (block._key === selectionEndBlock.node._key) { foundSelectionEndBlock = !0; continue; } if (foundSelectionEndBlock) { nextBlock = { node: block, path: [{ _key: block._key }] }; break; } } if (foundSelectionEndBlock && nextBlock) return nextBlock; }, getSelectionEndPoint = (snapshot) => { if (snapshot.context.selection) return snapshot.context.selection.backward ? snapshot.context.selection.anchor : snapshot.context.selection.focus; }, getSelectionStartPoint = (snapshot) => { if (snapshot.context.selection) return snapshot.context.selection.backward ? snapshot.context.selection.focus : snapshot.context.selection.anchor; }, getNextInlineObject = (snapshot) => { const focusTextBlock = 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 (!util_sliceBlocks.isSpan(snapshot.context, child) && endPointChildFound) { inlineObject = { node: child, path: [...focusTextBlock.path, "children", { _key: child._key }] }; break; } } return inlineObject; }, getPreviousInlineObject = (snapshot) => { const focusTextBlock = getFocusTextBlock(snapshot), selectionStartPoint = getSelectionStartPoint(snapshot), selectionStartPointChildKey = selectionStartPoint && types.isKeySegment(selectionStartPoint.path[2]) ? selectionStartPoint.path[2]._key : void 0; if (!focusTextBlock || !selectionStartPointChildKey) return; let inlineObject; for (const child of focusTextBlock.node.children) { if (child._key === selectionStartPointChildKey) break; util_sliceBlocks.isSpan(snapshot.context, child) || (inlineObject = { node: child, path: [...focusTextBlock.path, "children", { _key: child._key }] }); } return inlineObject; }, getSelectedSlice = (snapshot) => util_sliceBlocks.sliceBlocks({ blocks: snapshot.context.value, selection: snapshot.context.selection }), getSelectionText = (snapshot) => getSelectedSlice(snapshot).reduce((text, block) => types.isPortableTextTextBlock(block) ? text + block.children.reduce((text2, child) => types.isPortableTextSpan(child) ? text2 + child.text : text2, "") : text, ""), isSelectionExpanded = (snapshot) => !isSelectionCollapsed(snapshot), getCaretWordSelection = (snapshot) => { if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return null; const focusTextBlock = getFocusTextBlock(snapshot), selectionStartPoint = getSelectionStartPoint(snapshot), selectionStartOffset = selectionStartPoint ? util_sliceBlocks.spanSelectionPointToBlockOffset({ value: snapshot.context.value, selectionPoint: selectionStartPoint }) : void 0; if (!focusTextBlock || !selectionStartPoint || !selectionStartOffset) return null; const previousInlineObject = getPreviousInlineObject(snapshot), blockStartPoint = util_sliceBlocks.getBlockStartPoint(focusTextBlock), textDirectlyBefore = getSelectionText({ context: { ...snapshot.context, selection: { anchor: previousInlineObject ? { path: previousInlineObject.path, offset: 0 } : blockStartPoint, focus: selectionStartPoint } } }).split(/\s+/).at(-1), nextInlineObject = getNextInlineObject(snapshot), blockEndPoint = util_sliceBlocks.getBlockEndPoint(focusTextBlock), textDirectlyAfter = 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 = util_sliceBlocks.blockOffsetToSpanSelectionPoint({ value: snapshot.context.value, blockOffset: caretWordStartOffset, direction: "backward" }), caretWordEndSelectionPoint = util_sliceBlocks.blockOffsetToSpanSelectionPoint({ value: snapshot.context.value, blockOffset: caretWordEndOffset, direction: "forward" }); if (!caretWordStartSelectionPoint || !caretWordEndSelectionPoint) return null; const caretWordSelection = { anchor: caretWordStartSelectionPoint, focus: caretWordEndSelectionPoint }; return isSelectionExpanded({ context: { ...snapshot.context, selection: caretWordSelection } }) ? caretWordSelection : null; }; function isAtTheEndOfBlock(block) { return (snapshot) => { if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return !1; const blockEndPoint = util_sliceBlocks.getBlockEndPoint(block); return util_sliceBlocks.isEqualSelectionPoints(snapshot.context.selection.focus, blockEndPoint); }; } function isAtTheStartOfBlock(block) { return (snapshot) => { if (!snapshot.context.selection || !isSelectionCollapsed(snapshot)) return !1; const blockStartPoint = util_sliceBlocks.getBlockStartPoint(block); return util_sliceBlocks.isEqualSelectionPoints(snapshot.context.selection.focus, blockStartPoint); }; } function isPointAfterSelection(point) { return (snapshot) => { if (!snapshot.context.selection) return !1; const selection = snapshot.context.selection.backward ? util_sliceBlocks.reverseSelection(snapshot.context.selection) : snapshot.context.selection, pointBlockKey = types.isKeySegment(point.path[0]) ? point.path[0]._key : void 0, pointChildKey = types.isKeySegment(point.path[2]) ? point.path[2]._key : void 0, endBlockKey = types.isKeySegment(selection.focus.path[0]) ? selection.focus.path[0]._key : void 0, endChildKey = types.isKeySegment(selection.focus.path[2]) ? selection.focus.path[2]._key : void 0; 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 (!types.isPortableTextTextBlock(block) || !pointChildKey || !endChildKey) break; for (const child of block.children) { if (child._key === endChildKey) { if (child._key !== pointChildKey) { after = !0; break; } after = point.offset > selection.focus.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 selection = snapshot.context.selection.backward ? util_sliceBlocks.reverseSelection(snapshot.context.selection) : snapshot.context.selection, pointBlockKey = types.isKeySegment(point.path[0]) ? point.path[0]._key : void 0, pointChildKey = types.isKeySegment(point.path[2]) ? point.path[2]._key : void 0, startBlockKey = types.isKeySegment(selection.anchor.path[0]) ? selection.anchor.path[0]._key : void 0, startChildKey = types.isKeySegment(selection.anchor.path[2]) ? selection.anchor.path[2]._key : void 0; 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 (!types.isPortableTextTextBlock(block) || !pointChildKey || !startChildKey) break; for (const child of block.children) { if (child._key === pointChildKey) { if (child._key !== startChildKey) { before = !0; break; } before = point.offset < selection.anchor.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 = getSelectionStartPoint({ context: { ...snapshot.context, selection } }), selectionEndPoint = getSelectionEndPoint({ context: { ...snapshot.context, selection } }), originalSelectionStartPoint = 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_sliceBlocks.isEqualSelectionPoints(selectionEndPoint, originalSelectionStartPoint), startPointEqualToOriginalEndPoint = util_sliceBlocks.isEqualSelectionPoints(selectionStartPoint, originalSelectionEndPoint); return endPointBeforeSelection && !endPointEqualToOriginalStartPoint || startPointAfterSelection && !startPointEqualToOriginalEndPoint ? !1 : !originalStartPointBeforeStartPoint && originalStartPointAfterStartPoint && !originalEndPointBeforeEndPoint && originalEndPointAfterEndPoint ? !endPointEqualToOriginalStartPoint : originalStartPointBeforeStartPoint && !originalStartPointAfterStartPoint && originalEndPointBeforeEndPoint && !originalEndPointAfterEndPoint ? !startPointEqualToOriginalEndPoint : !startPointAfterSelection || !startPointBeforeSelection || !endPointAfterSelection || !endPointBeforeSelection; }; } exports.createGuards = createGuards; exports.getCaretWordSelection = getCaretWordSelection; exports.getFirstBlock = getFirstBlock; exports.getFocusBlock = getFocusBlock; exports.getFocusBlockObject = getFocusBlockObject; exports.getFocusChild = getFocusChild; exports.getFocusListBlock = getFocusListBlock; exports.getFocusSpan = getFocusSpan; exports.getFocusTextBlock = getFocusTextBlock; exports.getLastBlock = getLastBlock; exports.getNextBlock = getNextBlock; exports.getNextInlineObject = getNextInlineObject; exports.getPreviousBlock = getPreviousBlock; exports.getPreviousInlineObject = getPreviousInlineObject; exports.getSelectedBlocks = getSelectedBlocks; exports.getSelectedSlice = getSelectedSlice; exports.getSelectionEndBlock = getSelectionEndBlock; exports.getSelectionEndPoint = getSelectionEndPoint; exports.getSelectionStartBlock = getSelectionStartBlock; exports.getSelectionStartPoint = getSelectionStartPoint; exports.getSelectionText = getSelectionText; exports.isAtTheEndOfBlock = isAtTheEndOfBlock; exports.isAtTheStartOfBlock = isAtTheStartOfBlock; exports.isOverlappingSelection = isOverlappingSelection; exports.isPointAfterSelection = isPointAfterSelection; exports.isPointBeforeSelection = isPointBeforeSelection; exports.isSelectionCollapsed = isSelectionCollapsed; exports.isSelectionExpanded = isSelectionExpanded; //# sourceMappingURL=selector.is-overlapping-selection.cjs.map