@zag-js/dismissable
Version:
Dismissable layer utilities for the DOM
157 lines (155 loc) • 5.42 kB
JavaScript
"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);
// src/layer-stack.ts
var layer_stack_exports = {};
__export(layer_stack_exports, {
layerStack: () => layerStack
});
module.exports = __toCommonJS(layer_stack_exports);
var import_dom_query = require("@zag-js/dom-query");
var LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
var layerStack = {
layers: [],
branches: [],
recentlyRemoved: /* @__PURE__ */ new Set(),
count() {
return this.layers.length;
},
pointerBlockingLayers() {
return this.layers.filter((layer) => layer.pointerBlocking);
},
topMostPointerBlockingLayer() {
return [...this.pointerBlockingLayers()].slice(-1)[0];
},
hasPointerBlockingLayer() {
return this.pointerBlockingLayers().length > 0;
},
isBelowPointerBlockingLayer(node) {
const index = this.indexOf(node);
const highestBlockingIndex = this.topMostPointerBlockingLayer() ? this.indexOf(this.topMostPointerBlockingLayer()?.node) : -1;
return index < highestBlockingIndex;
},
isTopMost(node) {
const layer = this.layers[this.count() - 1];
return layer?.node === node;
},
getNestedLayers(node) {
return Array.from(this.layers).slice(this.indexOf(node) + 1);
},
getLayersByType(type) {
return this.layers.filter((layer) => layer.type === type);
},
getNestedLayersByType(node, type) {
const index = this.indexOf(node);
if (index === -1) return [];
return this.layers.slice(index + 1).filter((layer) => layer.type === type);
},
getParentLayerOfType(node, type) {
const index = this.indexOf(node);
if (index <= 0) return void 0;
return this.layers.slice(0, index).reverse().find((layer) => layer.type === type);
},
countNestedLayersOfType(node, type) {
return this.getNestedLayersByType(node, type).length;
},
isInNestedLayer(node, target) {
const inNested = this.getNestedLayers(node).some((layer) => (0, import_dom_query.contains)(layer.node, target));
if (inNested) return true;
if (this.recentlyRemoved.size > 0) return true;
return false;
},
isInBranch(target) {
return Array.from(this.branches).some((branch) => (0, import_dom_query.contains)(branch, target));
},
add(layer) {
this.layers.push(layer);
this.syncLayers();
},
addBranch(node) {
this.branches.push(node);
},
remove(node) {
const index = this.indexOf(node);
if (index < 0) return;
this.recentlyRemoved.add(node);
(0, import_dom_query.nextTick)(() => this.recentlyRemoved.delete(node));
if (index < this.count() - 1) {
const _layers = this.getNestedLayers(node);
_layers.forEach((layer) => layerStack.dismiss(layer.node, node));
}
this.layers.splice(index, 1);
this.syncLayers();
},
removeBranch(node) {
const index = this.branches.indexOf(node);
if (index >= 0) this.branches.splice(index, 1);
},
syncLayers() {
this.layers.forEach((layer, index) => {
layer.node.style.setProperty("--layer-index", `${index}`);
layer.node.removeAttribute("data-nested");
layer.node.removeAttribute("data-has-nested");
const parentOfSameType = this.getParentLayerOfType(layer.node, layer.type);
if (parentOfSameType) {
layer.node.setAttribute("data-nested", layer.type);
}
const nestedCount = this.countNestedLayersOfType(layer.node, layer.type);
if (nestedCount > 0) {
layer.node.setAttribute("data-has-nested", layer.type);
}
layer.node.style.setProperty("--nested-layer-count", `${nestedCount}`);
});
},
indexOf(node) {
return this.layers.findIndex((layer) => layer.node === node);
},
dismiss(node, parent) {
const index = this.indexOf(node);
if (index === -1) return;
const layer = this.layers[index];
addListenerOnce(node, LAYER_REQUEST_DISMISS_EVENT, (event) => {
layer.requestDismiss?.(event);
if (!event.defaultPrevented) {
layer?.dismiss();
}
});
fireCustomEvent(node, LAYER_REQUEST_DISMISS_EVENT, {
originalLayer: node,
targetLayer: parent,
originalIndex: index,
targetIndex: parent ? this.indexOf(parent) : -1
});
this.syncLayers();
},
clear() {
this.remove(this.layers[0].node);
}
};
function fireCustomEvent(el, type, detail) {
const win = el.ownerDocument.defaultView || window;
const event = new win.CustomEvent(type, { cancelable: true, bubbles: true, detail });
return el.dispatchEvent(event);
}
function addListenerOnce(el, type, callback) {
el.addEventListener(type, callback, { once: true });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
layerStack
});