Files
2026-06-24 09:48:54 +02:00

88 lines
3.1 KiB
JavaScript

/** Controller that encapsulates layer-dropdown integration logic */
import { getElementSelectorId } from "../utils.js";
import { buildLayerChain } from "./utils.js";
import { enhanceLabelWithChevron, showDropdown, closeDropdown, isDropdownOpen, } from "./dropdown-ui.js";
export function createLayerController(config) {
let layerPreviewOverlay = null;
let escapeHandler = null;
let dropdownSourceLayer = null;
const clearLayerPreview = () => {
if (layerPreviewOverlay && layerPreviewOverlay.parentNode) {
layerPreviewOverlay.remove();
}
layerPreviewOverlay = null;
};
const showLayerPreview = (layer) => {
clearLayerPreview();
if (getElementSelectorId(layer.element) === config.getSelectedElementId())
return;
layerPreviewOverlay = config.createPreviewOverlay(layer.element);
};
const selectLayer = (layer) => {
clearLayerPreview();
closeDropdown();
if (escapeHandler) {
document.removeEventListener("keydown", escapeHandler, true);
escapeHandler = null;
}
dropdownSourceLayer = null;
const firstOverlay = config.selectElement(layer.element);
attachToOverlay(firstOverlay, layer.element);
};
const restoreSelection = () => {
if (escapeHandler) {
document.removeEventListener("keydown", escapeHandler, true);
escapeHandler = null;
}
if (dropdownSourceLayer) {
selectLayer(dropdownSourceLayer);
dropdownSourceLayer = null;
}
};
const handleLabelClick = (e, label, element, layers, currentId) => {
e.stopPropagation();
e.preventDefault();
if (isDropdownOpen()) {
closeDropdown();
restoreSelection();
}
else {
dropdownSourceLayer = {
element,
tagName: element.tagName.toLowerCase(),
selectorId: currentId,
};
config.onDeselect();
escapeHandler = (ev) => {
if (ev.key === "Escape") {
ev.stopPropagation();
closeDropdown();
restoreSelection();
}
};
document.addEventListener("keydown", escapeHandler, true);
showDropdown(label, layers, element, { onSelect: selectLayer, onHover: showLayerPreview, onHoverEnd: clearLayerPreview });
}
};
const attachToOverlay = (overlay, element) => {
if (!overlay)
return;
const label = overlay.querySelector("div");
if (!label)
return;
const layers = buildLayerChain(element);
if (layers.length <= 1)
return;
const currentId = getElementSelectorId(element);
enhanceLabelWithChevron(label);
label.addEventListener("click", (e) => {
handleLabelClick(e, label, element, layers, currentId);
});
};
const cleanup = () => {
clearLayerPreview();
closeDropdown();
};
return { attachToOverlay, cleanup };
}
//# sourceMappingURL=controller.js.map