@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
244 lines (242 loc) • 7.65 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/editor/src/components/collaborators-overlay/cursor-dom-utils.ts
var cursor_dom_utils_exports = {};
__export(cursor_dom_utils_exports, {
findInnerBlockOffset: () => findInnerBlockOffset,
getBlocksBetween: () => getBlocksBetween,
getCursorPosition: () => getCursorPosition,
getFullBlockSelectionRects: () => getFullBlockSelectionRects,
getSelectionRects: () => getSelectionRects,
isNodeBefore: () => isNodeBefore
});
module.exports = __toCommonJS(cursor_dom_utils_exports);
var MAX_NODE_OFFSET_COUNT = 500;
var getCursorPosition = (absolutePositionIndex, blockElement, editorDocument, overlayRect) => {
if (absolutePositionIndex === null || !blockElement) {
return null;
}
return getOffsetPositionInBlock(
blockElement,
absolutePositionIndex,
editorDocument,
overlayRect
) ?? null;
};
var getOffsetPositionInBlock = (blockElement, charOffset, editorDocument, overlayRect) => {
const { node, offset } = findInnerBlockOffset(
blockElement,
charOffset,
editorDocument
);
const cursorRange = editorDocument.createRange();
try {
cursorRange.setStart(node, offset);
} catch (error) {
return null;
}
cursorRange.collapse(true);
const cursorRect = cursorRange.getBoundingClientRect();
const blockRect = blockElement.getBoundingClientRect();
let cursorX = 0;
let cursorY = 0;
if (cursorRect.x === 0 && cursorRect.y === 0 && cursorRect.width === 0 && cursorRect.height === 0) {
cursorX = blockRect.left - overlayRect.left;
cursorY = blockRect.top - overlayRect.top;
} else {
cursorX = cursorRect.left - overlayRect.left;
cursorY = cursorRect.top - overlayRect.top;
}
let cursorHeight = cursorRect.height;
if (cursorHeight === 0) {
const view = editorDocument.defaultView ?? window;
cursorHeight = parseInt(view.getComputedStyle(blockElement).lineHeight, 10) || blockRect.height;
}
return {
x: cursorX,
y: cursorY,
height: cursorHeight
};
};
var getSelectionRects = (blockElement, startOffset, endOffset, editorDocument, overlayRect) => {
let normalizedStart = startOffset;
let normalizedEnd = endOffset;
if (normalizedStart > normalizedEnd) {
[normalizedStart, normalizedEnd] = [normalizedEnd, normalizedStart];
}
const startPos = findInnerBlockOffset(
blockElement,
normalizedStart,
editorDocument
);
const endPos = findInnerBlockOffset(
blockElement,
normalizedEnd,
editorDocument
);
const range = editorDocument.createRange();
try {
range.setStart(startPos.node, startPos.offset);
range.setEnd(endPos.node, endPos.offset);
} catch {
return null;
}
const clientRects = range.getClientRects();
const rects = [];
for (const rect of clientRects) {
if (rect.width === 0 && rect.height === 0) {
continue;
}
const x = rect.left - overlayRect.left;
const y = rect.top - overlayRect.top;
const isDuplicate = rects.some(
(r) => r.x === x && r.y === y && r.width === rect.width && r.height === rect.height
);
if (isDuplicate) {
continue;
}
rects.push({
x,
y,
width: rect.width,
height: rect.height
});
}
return rects.length > 0 ? rects : null;
};
var getFullBlockSelectionRects = (blockElement, editorDocument, overlayRect) => {
const range = editorDocument.createRange();
range.selectNodeContents(blockElement);
const clientRects = range.getClientRects();
const rects = [];
for (const rect of clientRects) {
if (rect.width === 0 && rect.height === 0) {
continue;
}
rects.push({
x: rect.left - overlayRect.left,
y: rect.top - overlayRect.top,
width: rect.width,
height: rect.height
});
}
if (rects.length === 0) {
const blockRect = blockElement.getBoundingClientRect();
if (blockRect.width > 0 && blockRect.height > 0) {
rects.push({
x: blockRect.left - overlayRect.left,
y: blockRect.top - overlayRect.top,
width: blockRect.width,
height: blockRect.height
});
}
}
return rects;
};
var getBlocksBetween = (startBlockId, endBlockId, editorDocument) => {
const allBlocks = editorDocument.querySelectorAll("[data-block]");
let startIndex = -1;
let endIndex = -1;
for (let i = 0; i < allBlocks.length; i++) {
const blockId = allBlocks[i].getAttribute("data-block");
if (blockId === startBlockId) {
startIndex = i;
}
if (blockId === endBlockId) {
endIndex = i;
}
}
if (startIndex === -1 || endIndex === -1) {
return [];
}
if (startIndex > endIndex) {
[startIndex, endIndex] = [endIndex, startIndex];
}
const result = [];
for (let i = startIndex + 1; i < endIndex; i++) {
result.push(allBlocks[i]);
}
return result;
};
var findInnerBlockOffset = (blockElement, offset, editorDocument) => {
const treeWalker = editorDocument.createTreeWalker(
blockElement,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT
// eslint-disable-line no-bitwise
);
let currentOffset = 0;
let lastTextNode = null;
let node = null;
let nodeCount = 1;
while (node = treeWalker.nextNode()) {
nodeCount++;
if (nodeCount > MAX_NODE_OFFSET_COUNT) {
if (lastTextNode) {
return { node: lastTextNode, offset: 0 };
}
return { node: blockElement, offset: 0 };
}
const nodeLength = node.nodeValue?.length ?? 0;
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.nodeName === "BR") {
if (currentOffset + 1 >= offset) {
const nodeAfterBr = treeWalker.nextNode();
if (nodeAfterBr?.nodeType === Node.TEXT_NODE) {
return { node: nodeAfterBr, offset: 0 };
} else if (lastTextNode) {
return {
node: lastTextNode,
offset: lastTextNode.nodeValue?.length ?? 0
};
}
return { node: blockElement, offset: 0 };
}
currentOffset += 1;
continue;
} else {
continue;
}
}
if (nodeLength === 0) {
continue;
}
if (currentOffset + nodeLength >= offset) {
return { node, offset: offset - currentOffset };
}
currentOffset += nodeLength;
if (node.nodeType === Node.TEXT_NODE) {
lastTextNode = node;
}
}
if (lastTextNode && lastTextNode.nodeValue?.length) {
return { node: lastTextNode, offset: lastTextNode.nodeValue.length };
}
return { node: blockElement, offset: 0 };
};
var isNodeBefore = (a, b) => a.compareDocumentPosition(b) === Node.DOCUMENT_POSITION_FOLLOWING;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
findInnerBlockOffset,
getBlocksBetween,
getCursorPosition,
getFullBlockSelectionRects,
getSelectionRects,
isNodeBefore
});
//# sourceMappingURL=cursor-dom-utils.cjs.map