@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
163 lines (162 loc) • 4.83 kB
JavaScript
// packages/editor/src/components/collaborators-overlay/compute-selection.ts
import { SelectionDirection, SelectionType } from "@wordpress/core-data";
import {
getCursorPosition,
getSelectionRects,
getFullBlockSelectionRects,
getBlocksBetween,
isNodeBefore
} from "./cursor-dom-utils.mjs";
function computeSelectionVisual(selection, start, end, overlayContext) {
if (selection.type === SelectionType.None || selection.type === SelectionType.WholeBlock) {
return {};
}
if (selection.type === SelectionType.Cursor) {
return computeCursorOnly(start, overlayContext);
}
if (!end) {
return {};
}
return computeTextSelection(selection, start, end, overlayContext);
}
function computeCursorOnly(start, overlayContext) {
if (!start.localClientId) {
return {};
}
const blockElement = overlayContext.editorDocument.querySelector(
`[data-block="${start.localClientId}"]`
);
return {
coords: getCursorPosition(
start.richTextOffset,
blockElement,
overlayContext.editorDocument,
overlayContext.overlayRect
)
};
}
function computeTextSelection(selection, start, end, overlayContext) {
if (!start.localClientId || !end.localClientId || start.richTextOffset === null || end.richTextOffset === null) {
return {};
}
const isReverse = selection.selectionDirection === SelectionDirection.Backward;
const activeEnd = isReverse ? start : end;
let allRects;
let activeEndBlock = null;
if (selection.type === SelectionType.SelectionInOneBlock) {
const result = computeSingleBlockRects(start, end, overlayContext);
allRects = result.rects;
activeEndBlock = result.blockElement;
} else {
const result = computeMultiBlockRects(start, end, overlayContext);
allRects = result.rects;
activeEndBlock = activeEnd.localClientId === result.firstBlockClientId ? result.firstBlock : result.lastBlock;
}
if (allRects.length > 0) {
return {
coords: getCursorPosition(
activeEnd.richTextOffset,
activeEndBlock,
overlayContext.editorDocument,
overlayContext.overlayRect
),
selectionRects: allRects
};
}
const startBlock = overlayContext.editorDocument.querySelector(
`[data-block="${start.localClientId}"]`
);
return {
coords: getCursorPosition(
start.richTextOffset,
startBlock,
overlayContext.editorDocument,
overlayContext.overlayRect
)
};
}
function computeSingleBlockRects(start, end, overlayContext) {
const blockElement = overlayContext.editorDocument.querySelector(
`[data-block="${start.localClientId}"]`
);
if (!blockElement || start.richTextOffset === null || end.richTextOffset === null) {
return { rects: [], blockElement: null };
}
return {
rects: getSelectionRects(
blockElement,
start.richTextOffset,
end.richTextOffset,
overlayContext.editorDocument,
overlayContext.overlayRect
) ?? [],
blockElement
};
}
function computeMultiBlockRects(start, end, overlayContext) {
let docFirst = start;
let docLast = end;
let firstBlock = overlayContext.editorDocument.querySelector(
`[data-block="${docFirst.localClientId}"]`
);
let lastBlock = overlayContext.editorDocument.querySelector(
`[data-block="${docLast.localClientId}"]`
);
if (firstBlock && lastBlock && isNodeBefore(lastBlock, firstBlock)) {
docFirst = end;
docLast = start;
[firstBlock, lastBlock] = [lastBlock, firstBlock];
}
if (!firstBlock || !lastBlock || docFirst.richTextOffset === null || docLast.richTextOffset === null || !docFirst.localClientId || !docLast.localClientId) {
return {
rects: [],
firstBlock: null,
lastBlock: null,
firstBlockClientId: null
};
}
const allRects = [];
const startRects = getSelectionRects(
firstBlock,
docFirst.richTextOffset,
Number.MAX_SAFE_INTEGER,
overlayContext.editorDocument,
overlayContext.overlayRect
);
if (startRects) {
allRects.push(...startRects);
}
const intermediateBlocks = getBlocksBetween(
docFirst.localClientId,
docLast.localClientId,
overlayContext.editorDocument
);
for (const intermediateBlock of intermediateBlocks) {
const rects = getFullBlockSelectionRects(
intermediateBlock,
overlayContext.editorDocument,
overlayContext.overlayRect
);
allRects.push(...rects);
}
const endRects = getSelectionRects(
lastBlock,
0,
docLast.richTextOffset,
overlayContext.editorDocument,
overlayContext.overlayRect
);
if (endRects) {
allRects.push(...endRects);
}
return {
rects: allRects,
firstBlock,
lastBlock,
firstBlockClientId: docFirst.localClientId
};
}
export {
computeSelectionVisual
};
//# sourceMappingURL=compute-selection.mjs.map