UNPKG

@wordpress/block-editor

Version:
189 lines (187 loc) 7.24 kB
"use strict"; 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/block-editor/src/components/writing-flow/use-selection-observer.js var use_selection_observer_exports = {}; __export(use_selection_observer_exports, { default: () => useSelectionObserver }); module.exports = __toCommonJS(use_selection_observer_exports); var import_data = require("@wordpress/data"); var import_compose = require("@wordpress/compose"); var import_rich_text = require("@wordpress/rich-text"); var import_dom = require("@wordpress/dom"); var import_store = require("../../store"); var import_dom2 = require("../../utils/dom"); function extractSelectionStartNode(selection) { const { anchorNode, anchorOffset } = selection; if (anchorNode.nodeType === anchorNode.TEXT_NODE) { return anchorNode; } if (anchorOffset === 0) { return anchorNode; } return anchorNode.childNodes[anchorOffset - 1]; } function extractSelectionEndNode(selection) { const { focusNode, focusOffset } = selection; if (focusNode.nodeType === focusNode.TEXT_NODE) { return focusNode; } if (focusOffset === focusNode.childNodes.length) { return focusNode; } if (focusOffset === 0 && (0, import_dom.isSelectionForward)(selection)) { return focusNode.previousSibling ?? focusNode.parentElement; } return focusNode.childNodes[focusOffset]; } function findDepth(a, b) { let depth = 0; while (a[depth] === b[depth]) { depth++; } return depth; } function setContentEditableWrapper(node, value) { if (node.contentEditable !== String(value)) { node.contentEditable = value; if (value) { node.focus(); } } } function getRichTextElement(node) { const element = node.nodeType === node.ELEMENT_NODE ? node : node.parentElement; return element?.closest("[data-wp-block-attribute-key]"); } function useSelectionObserver() { const { multiSelect, selectBlock, selectionChange } = (0, import_data.useDispatch)(import_store.store); const { getBlockParents, getBlockSelectionStart, isMultiSelecting } = (0, import_data.useSelect)(import_store.store); return (0, import_compose.useRefEffect)( (node) => { const { ownerDocument } = node; const { defaultView } = ownerDocument; function onSelectionChange(event) { const selection = defaultView.getSelection(); if (!selection.rangeCount) { return; } const startNode = extractSelectionStartNode(selection); const endNode = extractSelectionEndNode(selection); if (!node.contains(startNode) || !node.contains(endNode)) { return; } const isClickShift = event.shiftKey && event.type === "mouseup"; if (selection.isCollapsed && !isClickShift) { if (node.contentEditable === "true" && !isMultiSelecting()) { setContentEditableWrapper(node, false); let element = startNode.nodeType === startNode.ELEMENT_NODE ? startNode : startNode.parentElement; element = element?.closest("[contenteditable]"); element?.focus(); } return; } let startClientId = (0, import_dom2.getBlockClientId)(startNode); let endClientId = (0, import_dom2.getBlockClientId)(endNode); if (isClickShift) { const selectedClientId = getBlockSelectionStart(); const clickedClientId = (0, import_dom2.getBlockClientId)(event.target); const focusNodeIsNonSelectable = clickedClientId !== endClientId; if (startClientId === endClientId && selection.isCollapsed || !endClientId || focusNodeIsNonSelectable) { endClientId = clickedClientId; } if (startClientId !== selectedClientId) { startClientId = selectedClientId; } } if (startClientId === void 0 && endClientId === void 0) { setContentEditableWrapper(node, false); return; } const isSingularSelection = startClientId === endClientId; if (isSingularSelection) { if (!isMultiSelecting()) { selectBlock(startClientId); } else { multiSelect(startClientId, startClientId); } } else { const startPath = [ ...getBlockParents(startClientId), startClientId ]; const endPath = [ ...getBlockParents(endClientId), endClientId ]; const depth = findDepth(startPath, endPath); if (startPath[depth] !== startClientId || endPath[depth] !== endClientId) { multiSelect(startPath[depth], endPath[depth]); return; } const richTextElementStart = getRichTextElement(startNode); const richTextElementEnd = getRichTextElement(endNode); if (richTextElementStart && richTextElementEnd) { const range = selection.getRangeAt(0); const richTextDataStart = (0, import_rich_text.create)({ element: richTextElementStart, range, __unstableIsEditableTree: true }); const richTextDataEnd = (0, import_rich_text.create)({ element: richTextElementEnd, range, __unstableIsEditableTree: true }); const startOffset = richTextDataStart.start ?? richTextDataStart.end; const endOffset = richTextDataEnd.start ?? richTextDataEnd.end; selectionChange({ start: { clientId: startClientId, attributeKey: richTextElementStart.dataset.wpBlockAttributeKey, offset: startOffset }, end: { clientId: endClientId, attributeKey: richTextElementEnd.dataset.wpBlockAttributeKey, offset: endOffset } }); } else { multiSelect(startClientId, endClientId); } } } ownerDocument.addEventListener( "selectionchange", onSelectionChange ); defaultView.addEventListener("mouseup", onSelectionChange); return () => { ownerDocument.removeEventListener( "selectionchange", onSelectionChange ); defaultView.removeEventListener("mouseup", onSelectionChange); }; }, [multiSelect, selectBlock, selectionChange, getBlockParents] ); } //# sourceMappingURL=use-selection-observer.js.map