first commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { FIXED_CONTEXT_SELECTOR, ELEMENT_TYPE_MAP } from "../constants/selectors.js";
|
||||
|
||||
/**
|
||||
* Logical type of an element for the hover tooltip: `text`, `button`, `image`,
|
||||
* or `block` otherwise. Edit targets (`data-edit-id` / `data-edit-assisted-id`)
|
||||
* that are not button/image tags are `text`.
|
||||
* @param {HTMLElement} element
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getElementType(element) {
|
||||
const tag = element?.tagName?.toLowerCase();
|
||||
const hasEditId = element?.hasAttribute?.('data-edit-id') || element?.hasAttribute?.('data-edit-assisted-id');
|
||||
|
||||
for (const [type, tags] of Object.entries(ELEMENT_TYPE_MAP)) {
|
||||
if (tags.some(candidate => candidate.toLowerCase() === tag)) {
|
||||
if (!hasEditId && type === 'text') return 'block';
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasEditId) return 'text';
|
||||
|
||||
return 'block';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The app's mount point, which roots every structural walk so the editor's own
|
||||
* body-level surfaces (panels, markers, outlines) are never traversed.
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
export function getAppRoot() {
|
||||
return document.getElementById('root') || document.body;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* True when the element sits inside a fixed/sticky ancestor, meaning overlays
|
||||
* must use viewport (fixed) positioning instead of document coordinates.
|
||||
* @param {HTMLElement} element
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isInFixedContext(element) {
|
||||
return !!element.closest(FIXED_CONTEXT_SELECTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Host-page modal dialogs that are currently open and visible. Mounted-but-closed
|
||||
* dialogs are skipped so a dismissed modal never keeps blocking the page.
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
export function getOpenModals() {
|
||||
return Array.from(document.querySelectorAll('[role="dialog"]')).filter(
|
||||
(modal) => modal.getAttribute('data-state') !== 'closed' && modal.checkVisibility?.() !== false,
|
||||
);
|
||||
}
|
||||
|
||||
const HOST_ISOLATED_EVENTS = ['pointerdown', 'pointerup', 'keydown', 'keyup'];
|
||||
|
||||
/**
|
||||
* Prevents host-page libraries (Radix DismissableLayer, FocusScope, etc.) from
|
||||
* seeing pointer and keyboard events that originate inside the editor's floating UI.
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
export function isolateEditorUiEvents(element) {
|
||||
for (const eventName of HOST_ISOLATED_EVENTS) {
|
||||
element.addEventListener(eventName, (event) => event.stopPropagation());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user