@zag-js/dismissable 0.69.0 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,49 +1,19 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ 'use strict';
19
2
 
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- trackDismissableBranch: () => trackDismissableBranch,
24
- trackDismissableElement: () => trackDismissableElement
25
- });
26
- module.exports = __toCommonJS(src_exports);
3
+ var domQuery = require('@zag-js/dom-query');
4
+ var interactOutside = require('@zag-js/interact-outside');
5
+ var utils = require('@zag-js/utils');
6
+ var domEvent = require('@zag-js/dom-event');
27
7
 
28
8
  // src/dismissable-layer.ts
29
- var import_dom_query4 = require("@zag-js/dom-query");
30
- var import_interact_outside = require("@zag-js/interact-outside");
31
- var import_utils = require("@zag-js/utils");
32
-
33
- // src/escape-keydown.ts
34
- var import_dom_event = require("@zag-js/dom-event");
35
- var import_dom_query = require("@zag-js/dom-query");
36
9
  function trackEscapeKeydown(node, fn) {
37
10
  const handleKeyDown = (event) => {
38
11
  if (event.key !== "Escape") return;
39
12
  if (event.isComposing) return;
40
13
  fn?.(event);
41
14
  };
42
- return (0, import_dom_event.addDomEvent)((0, import_dom_query.getDocument)(node), "keydown", handleKeyDown, { capture: true });
15
+ return domEvent.addDomEvent(domQuery.getDocument(node), "keydown", handleKeyDown, { capture: true });
43
16
  }
44
-
45
- // src/layer-stack.ts
46
- var import_dom_query2 = require("@zag-js/dom-query");
47
17
  var layerStack = {
48
18
  layers: [],
49
19
  branches: [],
@@ -72,10 +42,10 @@ var layerStack = {
72
42
  return Array.from(this.layers).slice(this.indexOf(node) + 1);
73
43
  },
74
44
  isInNestedLayer(node, target) {
75
- return this.getNestedLayers(node).some((layer) => (0, import_dom_query2.contains)(layer.node, target));
45
+ return this.getNestedLayers(node).some((layer) => domQuery.contains(layer.node, target));
76
46
  },
77
47
  isInBranch(target) {
78
- return Array.from(this.branches).some((branch) => (0, import_dom_query2.contains)(branch, target));
48
+ return Array.from(this.branches).some((branch) => domQuery.contains(branch, target));
79
49
  },
80
50
  add(layer) {
81
51
  const num = this.layers.push(layer);
@@ -108,9 +78,6 @@ var layerStack = {
108
78
  this.remove(this.layers[0].node);
109
79
  }
110
80
  };
111
-
112
- // src/pointer-event-outside.ts
113
- var import_dom_query3 = require("@zag-js/dom-query");
114
81
  var originalBodyPointerEvents;
115
82
  function assignPointerEventToLayers() {
116
83
  layerStack.layers.forEach(({ node }) => {
@@ -121,7 +88,7 @@ function clearPointerEvent(node) {
121
88
  node.style.pointerEvents = "";
122
89
  }
123
90
  function disablePointerEventsOutside(node, peristentElements) {
124
- const doc = (0, import_dom_query3.getDocument)(node);
91
+ const doc = domQuery.getDocument(node);
125
92
  const cleanups = [];
126
93
  if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
127
94
  originalBodyPointerEvents = document.body.style.pointerEvents;
@@ -131,8 +98,8 @@ function disablePointerEventsOutside(node, peristentElements) {
131
98
  });
132
99
  }
133
100
  if (peristentElements) {
134
- const persistedCleanup = (0, import_dom_query3.waitForElements)(peristentElements, (el) => {
135
- cleanups.push((0, import_dom_query3.setStyle)(el, { pointerEvents: "auto" }));
101
+ const persistedCleanup = domQuery.waitForElements(peristentElements, (el) => {
102
+ cleanups.push(domQuery.setStyle(el, { pointerEvents: "auto" }));
136
103
  });
137
104
  cleanups.push(persistedCleanup);
138
105
  }
@@ -150,7 +117,7 @@ function disablePointerEventsOutside(node, peristentElements) {
150
117
  // src/dismissable-layer.ts
151
118
  function trackDismissableElementImpl(node, options) {
152
119
  if (!node) {
153
- (0, import_utils.warn)("[@zag-js/dismissable] node is `null` or `undefined`");
120
+ utils.warn("[@zag-js/dismissable] node is `null` or `undefined`");
154
121
  return;
155
122
  }
156
123
  const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
@@ -158,7 +125,7 @@ function trackDismissableElementImpl(node, options) {
158
125
  layerStack.add(layer);
159
126
  assignPointerEventToLayers();
160
127
  function onPointerDownOutside(event) {
161
- const target = (0, import_dom_query4.getEventTarget)(event.detail.originalEvent);
128
+ const target = domQuery.getEventTarget(event.detail.originalEvent);
162
129
  if (layerStack.isBelowPointerBlockingLayer(node) || layerStack.isInBranch(target)) return;
163
130
  options.onPointerDownOutside?.(event);
164
131
  options.onInteractOutside?.(event);
@@ -169,7 +136,7 @@ function trackDismissableElementImpl(node, options) {
169
136
  onDismiss?.();
170
137
  }
171
138
  function onFocusOutside(event) {
172
- const target = (0, import_dom_query4.getEventTarget)(event.detail.originalEvent);
139
+ const target = domQuery.getEventTarget(event.detail.originalEvent);
173
140
  if (layerStack.isInBranch(target)) return;
174
141
  options.onFocusOutside?.(event);
175
142
  options.onInteractOutside?.(event);
@@ -191,14 +158,14 @@ function trackDismissableElementImpl(node, options) {
191
158
  if (!node) return false;
192
159
  const containers = typeof excludeContainers === "function" ? excludeContainers() : excludeContainers;
193
160
  const _containers = Array.isArray(containers) ? containers : [containers];
194
- const persistentElements = options.persistentElements?.map((fn) => fn()).filter(import_dom_query4.isHTMLElement);
161
+ const persistentElements = options.persistentElements?.map((fn) => fn()).filter(domQuery.isHTMLElement);
195
162
  if (persistentElements) _containers.push(...persistentElements);
196
- return _containers.some((node2) => (0, import_dom_query4.contains)(node2, target)) || layerStack.isInNestedLayer(node, target);
163
+ return _containers.some((node2) => domQuery.contains(node2, target)) || layerStack.isInNestedLayer(node, target);
197
164
  }
198
165
  const cleanups = [
199
166
  pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : void 0,
200
167
  trackEscapeKeydown(node, onEscapeKeyDown),
201
- (0, import_interact_outside.trackInteractOutside)(node, { exclude, onFocusOutside, onPointerDownOutside, defer: options.defer })
168
+ interactOutside.trackInteractOutside(node, { exclude, onFocusOutside, onPointerDownOutside, defer: options.defer })
202
169
  ];
203
170
  return () => {
204
171
  layerStack.remove(node);
@@ -209,11 +176,11 @@ function trackDismissableElementImpl(node, options) {
209
176
  }
210
177
  function trackDismissableElement(nodeOrFn, options) {
211
178
  const { defer } = options;
212
- const func = defer ? import_dom_query4.raf : (v) => v();
179
+ const func = defer ? domQuery.raf : (v) => v();
213
180
  const cleanups = [];
214
181
  cleanups.push(
215
182
  func(() => {
216
- const node = (0, import_utils.isFunction)(nodeOrFn) ? nodeOrFn() : nodeOrFn;
183
+ const node = utils.isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn;
217
184
  cleanups.push(trackDismissableElementImpl(node, options));
218
185
  })
219
186
  );
@@ -223,13 +190,13 @@ function trackDismissableElement(nodeOrFn, options) {
223
190
  }
224
191
  function trackDismissableBranch(nodeOrFn, options = {}) {
225
192
  const { defer } = options;
226
- const func = defer ? import_dom_query4.raf : (v) => v();
193
+ const func = defer ? domQuery.raf : (v) => v();
227
194
  const cleanups = [];
228
195
  cleanups.push(
229
196
  func(() => {
230
- const node = (0, import_utils.isFunction)(nodeOrFn) ? nodeOrFn() : nodeOrFn;
197
+ const node = utils.isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn;
231
198
  if (!node) {
232
- (0, import_utils.warn)("[@zag-js/dismissable] branch node is `null` or `undefined`");
199
+ utils.warn("[@zag-js/dismissable] branch node is `null` or `undefined`");
233
200
  return;
234
201
  }
235
202
  layerStack.addBranch(node);
@@ -242,9 +209,6 @@ function trackDismissableBranch(nodeOrFn, options = {}) {
242
209
  cleanups.forEach((fn) => fn?.());
243
210
  };
244
211
  }
245
- // Annotate the CommonJS export names for ESM import in node:
246
- 0 && (module.exports = {
247
- trackDismissableBranch,
248
- trackDismissableElement
249
- });
250
- //# sourceMappingURL=index.js.map
212
+
213
+ exports.trackDismissableBranch = trackDismissableBranch;
214
+ exports.trackDismissableElement = trackDismissableElement;
package/dist/index.mjs CHANGED
@@ -1,13 +1,9 @@
1
- // src/dismissable-layer.ts
2
- import { contains as contains2, getEventTarget, isHTMLElement, raf } from "@zag-js/dom-query";
3
- import {
4
- trackInteractOutside
5
- } from "@zag-js/interact-outside";
6
- import { isFunction, warn } from "@zag-js/utils";
1
+ import { contains, raf, getDocument, waitForElements, setStyle, getEventTarget, isHTMLElement } from '@zag-js/dom-query';
2
+ import { trackInteractOutside } from '@zag-js/interact-outside';
3
+ import { isFunction, warn } from '@zag-js/utils';
4
+ import { addDomEvent } from '@zag-js/dom-event';
7
5
 
8
- // src/escape-keydown.ts
9
- import { addDomEvent } from "@zag-js/dom-event";
10
- import { getDocument } from "@zag-js/dom-query";
6
+ // src/dismissable-layer.ts
11
7
  function trackEscapeKeydown(node, fn) {
12
8
  const handleKeyDown = (event) => {
13
9
  if (event.key !== "Escape") return;
@@ -16,9 +12,6 @@ function trackEscapeKeydown(node, fn) {
16
12
  };
17
13
  return addDomEvent(getDocument(node), "keydown", handleKeyDown, { capture: true });
18
14
  }
19
-
20
- // src/layer-stack.ts
21
- import { contains } from "@zag-js/dom-query";
22
15
  var layerStack = {
23
16
  layers: [],
24
17
  branches: [],
@@ -83,9 +76,6 @@ var layerStack = {
83
76
  this.remove(this.layers[0].node);
84
77
  }
85
78
  };
86
-
87
- // src/pointer-event-outside.ts
88
- import { getDocument as getDocument2, setStyle, waitForElements } from "@zag-js/dom-query";
89
79
  var originalBodyPointerEvents;
90
80
  function assignPointerEventToLayers() {
91
81
  layerStack.layers.forEach(({ node }) => {
@@ -96,7 +86,7 @@ function clearPointerEvent(node) {
96
86
  node.style.pointerEvents = "";
97
87
  }
98
88
  function disablePointerEventsOutside(node, peristentElements) {
99
- const doc = getDocument2(node);
89
+ const doc = getDocument(node);
100
90
  const cleanups = [];
101
91
  if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
102
92
  originalBodyPointerEvents = document.body.style.pointerEvents;
@@ -168,7 +158,7 @@ function trackDismissableElementImpl(node, options) {
168
158
  const _containers = Array.isArray(containers) ? containers : [containers];
169
159
  const persistentElements = options.persistentElements?.map((fn) => fn()).filter(isHTMLElement);
170
160
  if (persistentElements) _containers.push(...persistentElements);
171
- return _containers.some((node2) => contains2(node2, target)) || layerStack.isInNestedLayer(node, target);
161
+ return _containers.some((node2) => contains(node2, target)) || layerStack.isInNestedLayer(node, target);
172
162
  }
173
163
  const cleanups = [
174
164
  pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : void 0,
@@ -217,8 +207,5 @@ function trackDismissableBranch(nodeOrFn, options = {}) {
217
207
  cleanups.forEach((fn) => fn?.());
218
208
  };
219
209
  }
220
- export {
221
- trackDismissableBranch,
222
- trackDismissableElement
223
- };
224
- //# sourceMappingURL=index.mjs.map
210
+
211
+ export { trackDismissableBranch, trackDismissableElement };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/dismissable",
3
- "version": "0.69.0",
3
+ "version": "0.71.0",
4
4
  "description": "Dismissable layer utilities for the DOM",
5
5
  "keywords": [
6
6
  "js",
@@ -17,17 +17,16 @@
17
17
  "repository": "https://github.com/chakra-ui/zag/tree/main/packages/utilities/interact-outside",
18
18
  "sideEffects": false,
19
19
  "files": [
20
- "dist",
21
- "src"
20
+ "dist"
22
21
  ],
23
22
  "publishConfig": {
24
23
  "access": "public"
25
24
  },
26
25
  "dependencies": {
27
- "@zag-js/interact-outside": "0.69.0",
28
- "@zag-js/dom-query": "0.69.0",
29
- "@zag-js/dom-event": "0.69.0",
30
- "@zag-js/utils": "0.69.0"
26
+ "@zag-js/interact-outside": "0.71.0",
27
+ "@zag-js/dom-query": "0.71.0",
28
+ "@zag-js/utils": "0.71.0",
29
+ "@zag-js/dom-event": "0.71.0"
31
30
  },
32
31
  "devDependencies": {
33
32
  "clean-package": "2.2.0"
@@ -49,7 +48,7 @@
49
48
  },
50
49
  "scripts": {
51
50
  "build": "tsup",
52
- "test": "jest --config ../../../jest.config.js --rootDir tests",
51
+ "test": "vitest",
53
52
  "lint": "eslint src",
54
53
  "test-ci": "pnpm test --ci --runInBand -u",
55
54
  "test-watch": "pnpm test --watchAll"
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/dismissable-layer.ts","../src/escape-keydown.ts","../src/layer-stack.ts","../src/pointer-event-outside.ts"],"sourcesContent":["export type {\n FocusOutsideEvent,\n InteractOutsideEvent,\n InteractOutsideHandlers,\n PointerDownOutsideEvent,\n} from \"@zag-js/interact-outside\"\nexport * from \"./dismissable-layer\"\n","import { contains, getEventTarget, isHTMLElement, raf } from \"@zag-js/dom-query\"\nimport {\n trackInteractOutside,\n type FocusOutsideEvent,\n type InteractOutsideHandlers,\n type PointerDownOutsideEvent,\n} from \"@zag-js/interact-outside\"\nimport { isFunction, warn, type MaybeFunction } from \"@zag-js/utils\"\nimport { trackEscapeKeydown } from \"./escape-keydown\"\nimport { layerStack, type Layer } from \"./layer-stack\"\nimport { assignPointerEventToLayers, clearPointerEvent, disablePointerEventsOutside } from \"./pointer-event-outside\"\n\ntype MaybeElement = HTMLElement | null\ntype Container = MaybeElement | Array<MaybeElement>\ntype NodeOrFn = MaybeFunction<MaybeElement>\n\nexport interface DismissableElementHandlers extends InteractOutsideHandlers {\n /**\n * Function called when the escape key is pressed\n */\n onEscapeKeyDown?: (event: KeyboardEvent) => void\n}\n\nexport interface PersistentElementOptions {\n /**\n * Returns the persistent elements that:\n * - should not have pointer-events disabled\n * - should not trigger the dismiss event\n */\n persistentElements?: Array<() => Element | null>\n}\n\nexport interface DismissableElementOptions extends DismissableElementHandlers, PersistentElementOptions {\n /**\n * Whether to log debug information\n */\n debug?: boolean\n /**\n * Whether to block pointer events outside the dismissable element\n */\n pointerBlocking?: boolean\n /**\n * Function called when the dismissable element is dismissed\n */\n onDismiss: VoidFunction\n /**\n * Exclude containers from the interact outside event\n */\n exclude?: MaybeFunction<Container>\n /**\n * Defer the interact outside event to the next frame\n */\n defer?: boolean\n}\n\nfunction trackDismissableElementImpl(node: MaybeElement, options: DismissableElementOptions) {\n if (!node) {\n warn(\"[@zag-js/dismissable] node is `null` or `undefined`\")\n return\n }\n\n const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options\n\n const layer: Layer = { dismiss: onDismiss, node, pointerBlocking }\n\n layerStack.add(layer)\n assignPointerEventToLayers()\n\n function onPointerDownOutside(event: PointerDownOutsideEvent) {\n const target = getEventTarget(event.detail.originalEvent)\n if (layerStack.isBelowPointerBlockingLayer(node!) || layerStack.isInBranch(target)) return\n options.onPointerDownOutside?.(event)\n options.onInteractOutside?.(event)\n if (event.defaultPrevented) return\n if (debug) {\n console.log(\"onPointerDownOutside:\", event.detail.originalEvent)\n }\n onDismiss?.()\n }\n\n function onFocusOutside(event: FocusOutsideEvent) {\n const target = getEventTarget(event.detail.originalEvent)\n if (layerStack.isInBranch(target)) return\n options.onFocusOutside?.(event)\n options.onInteractOutside?.(event)\n if (event.defaultPrevented) return\n if (debug) {\n console.log(\"onFocusOutside:\", event.detail.originalEvent)\n }\n onDismiss?.()\n }\n\n function onEscapeKeyDown(event: KeyboardEvent) {\n if (!layerStack.isTopMost(node!)) return\n options.onEscapeKeyDown?.(event)\n if (!event.defaultPrevented && onDismiss) {\n event.preventDefault()\n onDismiss()\n }\n }\n\n function exclude(target: Element) {\n if (!node) return false\n const containers = typeof excludeContainers === \"function\" ? excludeContainers() : excludeContainers\n const _containers = Array.isArray(containers) ? containers : [containers]\n const persistentElements = options.persistentElements?.map((fn) => fn()).filter(isHTMLElement)\n if (persistentElements) _containers.push(...persistentElements)\n return _containers.some((node) => contains(node, target)) || layerStack.isInNestedLayer(node, target)\n }\n\n const cleanups = [\n pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : undefined,\n trackEscapeKeydown(node, onEscapeKeyDown),\n trackInteractOutside(node, { exclude, onFocusOutside, onPointerDownOutside, defer: options.defer }),\n ]\n\n return () => {\n layerStack.remove(node!)\n // re-assign pointer event to remaining layers\n assignPointerEventToLayers()\n // remove pointer event from removed layer\n clearPointerEvent(node!)\n cleanups.forEach((fn) => fn?.())\n }\n}\n\nexport function trackDismissableElement(nodeOrFn: NodeOrFn, options: DismissableElementOptions) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn\n cleanups.push(trackDismissableElementImpl(node, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n\nexport function trackDismissableBranch(nodeOrFn: NodeOrFn, options: { defer?: boolean } = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n\n cleanups.push(\n func(() => {\n const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn\n if (!node) {\n warn(\"[@zag-js/dismissable] branch node is `null` or `undefined`\")\n return\n }\n layerStack.addBranch(node)\n cleanups.push(() => {\n layerStack.removeBranch(node)\n })\n }),\n )\n\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n","import { addDomEvent } from \"@zag-js/dom-event\"\nimport { getDocument } from \"@zag-js/dom-query\"\n\nexport function trackEscapeKeydown(node: HTMLElement, fn?: (event: KeyboardEvent) => void) {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return\n if (event.isComposing) return\n fn?.(event)\n }\n\n return addDomEvent(getDocument(node), \"keydown\", handleKeyDown, { capture: true })\n}\n","import { contains } from \"@zag-js/dom-query\"\n\nexport interface Layer {\n dismiss: VoidFunction\n node: HTMLElement\n pointerBlocking?: boolean\n}\n\nexport const layerStack = {\n layers: [] as Layer[],\n branches: [] as HTMLElement[],\n count(): number {\n return this.layers.length\n },\n pointerBlockingLayers(): Layer[] {\n return this.layers.filter((layer) => layer.pointerBlocking)\n },\n topMostPointerBlockingLayer(): Layer | undefined {\n return [...this.pointerBlockingLayers()].slice(-1)[0]\n },\n hasPointerBlockingLayer(): boolean {\n return this.pointerBlockingLayers().length > 0\n },\n isBelowPointerBlockingLayer(node: HTMLElement) {\n const index = this.indexOf(node)\n const highestBlockingIndex = this.topMostPointerBlockingLayer()\n ? this.indexOf(this.topMostPointerBlockingLayer()?.node)\n : -1\n return index < highestBlockingIndex\n },\n isTopMost(node: HTMLElement | null) {\n const layer = this.layers[this.count() - 1]\n return layer?.node === node\n },\n getNestedLayers(node: HTMLElement) {\n return Array.from(this.layers).slice(this.indexOf(node) + 1)\n },\n isInNestedLayer(node: HTMLElement, target: HTMLElement | EventTarget | null) {\n return this.getNestedLayers(node).some((layer) => contains(layer.node, target))\n },\n isInBranch(target: HTMLElement | EventTarget | null) {\n return Array.from(this.branches).some((branch) => contains(branch, target))\n },\n add(layer: Layer) {\n const num = this.layers.push(layer)\n layer.node.style.setProperty(\"--layer-index\", `${num}`)\n },\n addBranch(node: HTMLElement) {\n this.branches.push(node)\n },\n remove(node: HTMLElement) {\n const index = this.indexOf(node)\n if (index < 0) return\n\n // dismiss nested layers\n if (index < this.count() - 1) {\n const _layers = this.getNestedLayers(node)\n _layers.forEach((layer) => layer.dismiss())\n }\n // remove this layer\n this.layers.splice(index, 1)\n node.style.removeProperty(\"--layer-index\")\n },\n removeBranch(node: HTMLElement) {\n const index = this.branches.indexOf(node)\n if (index >= 0) this.branches.splice(index, 1)\n },\n indexOf(node: HTMLElement | undefined) {\n return this.layers.findIndex((layer) => layer.node === node)\n },\n dismiss(node: HTMLElement) {\n this.layers[this.indexOf(node)]?.dismiss()\n },\n clear() {\n this.remove(this.layers[0].node)\n },\n}\n","import { getDocument, setStyle, waitForElements } from \"@zag-js/dom-query\"\nimport { layerStack } from \"./layer-stack\"\n\nlet originalBodyPointerEvents: string\n\nexport function assignPointerEventToLayers() {\n layerStack.layers.forEach(({ node }) => {\n node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? \"none\" : \"auto\"\n })\n}\n\nexport function clearPointerEvent(node: HTMLElement) {\n node.style.pointerEvents = \"\"\n}\n\nexport function disablePointerEventsOutside(node: HTMLElement, peristentElements?: Array<() => Element | null>) {\n const doc = getDocument(node)\n\n const cleanups: VoidFunction[] = []\n\n if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute(\"data-inert\")) {\n originalBodyPointerEvents = document.body.style.pointerEvents\n queueMicrotask(() => {\n doc.body.style.pointerEvents = \"none\"\n doc.body.setAttribute(\"data-inert\", \"\")\n })\n }\n\n if (peristentElements) {\n const persistedCleanup = waitForElements(peristentElements, (el) => {\n cleanups.push(setStyle(el, { pointerEvents: \"auto\" }))\n })\n cleanups.push(persistedCleanup)\n }\n\n return () => {\n if (layerStack.hasPointerBlockingLayer()) return\n queueMicrotask(() => {\n doc.body.style.pointerEvents = originalBodyPointerEvents\n doc.body.removeAttribute(\"data-inert\")\n if (doc.body.style.length === 0) doc.body.removeAttribute(\"style\")\n })\n cleanups.forEach((fn) => fn())\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,oBAA6D;AAC7D,8BAKO;AACP,mBAAqD;;;ACPrD,uBAA4B;AAC5B,uBAA4B;AAErB,SAAS,mBAAmB,MAAmB,IAAqC;AACzF,QAAM,gBAAgB,CAAC,UAAyB;AAC9C,QAAI,MAAM,QAAQ,SAAU;AAC5B,QAAI,MAAM,YAAa;AACvB,SAAK,KAAK;AAAA,EACZ;AAEA,aAAO,kCAAY,8BAAY,IAAI,GAAG,WAAW,eAAe,EAAE,SAAS,KAAK,CAAC;AACnF;;;ACXA,IAAAC,oBAAyB;AAQlB,IAAM,aAAa;AAAA,EACxB,QAAQ,CAAC;AAAA,EACT,UAAU,CAAC;AAAA,EACX,QAAgB;AACd,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EACA,wBAAiC;AAC/B,WAAO,KAAK,OAAO,OAAO,CAAC,UAAU,MAAM,eAAe;AAAA,EAC5D;AAAA,EACA,8BAAiD;AAC/C,WAAO,CAAC,GAAG,KAAK,sBAAsB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;AAAA,EACtD;AAAA,EACA,0BAAmC;AACjC,WAAO,KAAK,sBAAsB,EAAE,SAAS;AAAA,EAC/C;AAAA,EACA,4BAA4B,MAAmB;AAC7C,UAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,UAAM,uBAAuB,KAAK,4BAA4B,IAC1D,KAAK,QAAQ,KAAK,4BAA4B,GAAG,IAAI,IACrD;AACJ,WAAO,QAAQ;AAAA,EACjB;AAAA,EACA,UAAU,MAA0B;AAClC,UAAM,QAAQ,KAAK,OAAO,KAAK,MAAM,IAAI,CAAC;AAC1C,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EACA,gBAAgB,MAAmB;AACjC,WAAO,MAAM,KAAK,KAAK,MAAM,EAAE,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,EAC7D;AAAA,EACA,gBAAgB,MAAmB,QAA0C;AAC3E,WAAO,KAAK,gBAAgB,IAAI,EAAE,KAAK,CAAC,cAAU,4BAAS,MAAM,MAAM,MAAM,CAAC;AAAA,EAChF;AAAA,EACA,WAAW,QAA0C;AACnD,WAAO,MAAM,KAAK,KAAK,QAAQ,EAAE,KAAK,CAAC,eAAW,4BAAS,QAAQ,MAAM,CAAC;AAAA,EAC5E;AAAA,EACA,IAAI,OAAc;AAChB,UAAM,MAAM,KAAK,OAAO,KAAK,KAAK;AAClC,UAAM,KAAK,MAAM,YAAY,iBAAiB,GAAG,GAAG,EAAE;AAAA,EACxD;AAAA,EACA,UAAU,MAAmB;AAC3B,SAAK,SAAS,KAAK,IAAI;AAAA,EACzB;AAAA,EACA,OAAO,MAAmB;AACxB,UAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,QAAI,QAAQ,EAAG;AAGf,QAAI,QAAQ,KAAK,MAAM,IAAI,GAAG;AAC5B,YAAM,UAAU,KAAK,gBAAgB,IAAI;AACzC,cAAQ,QAAQ,CAAC,UAAU,MAAM,QAAQ,CAAC;AAAA,IAC5C;AAEA,SAAK,OAAO,OAAO,OAAO,CAAC;AAC3B,SAAK,MAAM,eAAe,eAAe;AAAA,EAC3C;AAAA,EACA,aAAa,MAAmB;AAC9B,UAAM,QAAQ,KAAK,SAAS,QAAQ,IAAI;AACxC,QAAI,SAAS,EAAG,MAAK,SAAS,OAAO,OAAO,CAAC;AAAA,EAC/C;AAAA,EACA,QAAQ,MAA+B;AACrC,WAAO,KAAK,OAAO,UAAU,CAAC,UAAU,MAAM,SAAS,IAAI;AAAA,EAC7D;AAAA,EACA,QAAQ,MAAmB;AACzB,SAAK,OAAO,KAAK,QAAQ,IAAI,CAAC,GAAG,QAAQ;AAAA,EAC3C;AAAA,EACA,QAAQ;AACN,SAAK,OAAO,KAAK,OAAO,CAAC,EAAE,IAAI;AAAA,EACjC;AACF;;;AC5EA,IAAAC,oBAAuD;AAGvD,IAAI;AAEG,SAAS,6BAA6B;AAC3C,aAAW,OAAO,QAAQ,CAAC,EAAE,KAAK,MAAM;AACtC,SAAK,MAAM,gBAAgB,WAAW,4BAA4B,IAAI,IAAI,SAAS;AAAA,EACrF,CAAC;AACH;AAEO,SAAS,kBAAkB,MAAmB;AACnD,OAAK,MAAM,gBAAgB;AAC7B;AAEO,SAAS,4BAA4B,MAAmB,mBAAiD;AAC9G,QAAM,UAAM,+BAAY,IAAI;AAE5B,QAAM,WAA2B,CAAC;AAElC,MAAI,WAAW,wBAAwB,KAAK,CAAC,IAAI,KAAK,aAAa,YAAY,GAAG;AAChF,gCAA4B,SAAS,KAAK,MAAM;AAChD,mBAAe,MAAM;AACnB,UAAI,KAAK,MAAM,gBAAgB;AAC/B,UAAI,KAAK,aAAa,cAAc,EAAE;AAAA,IACxC,CAAC;AAAA,EACH;AAEA,MAAI,mBAAmB;AACrB,UAAM,uBAAmB,mCAAgB,mBAAmB,CAAC,OAAO;AAClE,eAAS,SAAK,4BAAS,IAAI,EAAE,eAAe,OAAO,CAAC,CAAC;AAAA,IACvD,CAAC;AACD,aAAS,KAAK,gBAAgB;AAAA,EAChC;AAEA,SAAO,MAAM;AACX,QAAI,WAAW,wBAAwB,EAAG;AAC1C,mBAAe,MAAM;AACnB,UAAI,KAAK,MAAM,gBAAgB;AAC/B,UAAI,KAAK,gBAAgB,YAAY;AACrC,UAAI,IAAI,KAAK,MAAM,WAAW,EAAG,KAAI,KAAK,gBAAgB,OAAO;AAAA,IACnE,CAAC;AACD,aAAS,QAAQ,CAAC,OAAO,GAAG,CAAC;AAAA,EAC/B;AACF;;;AHWA,SAAS,4BAA4B,MAAoB,SAAoC;AAC3F,MAAI,CAAC,MAAM;AACT,2BAAK,qDAAqD;AAC1D;AAAA,EACF;AAEA,QAAM,EAAE,WAAW,iBAAiB,SAAS,mBAAmB,MAAM,IAAI;AAE1E,QAAM,QAAe,EAAE,SAAS,WAAW,MAAM,gBAAgB;AAEjE,aAAW,IAAI,KAAK;AACpB,6BAA2B;AAE3B,WAAS,qBAAqB,OAAgC;AAC5D,UAAM,aAAS,kCAAe,MAAM,OAAO,aAAa;AACxD,QAAI,WAAW,4BAA4B,IAAK,KAAK,WAAW,WAAW,MAAM,EAAG;AACpF,YAAQ,uBAAuB,KAAK;AACpC,YAAQ,oBAAoB,KAAK;AACjC,QAAI,MAAM,iBAAkB;AAC5B,QAAI,OAAO;AACT,cAAQ,IAAI,yBAAyB,MAAM,OAAO,aAAa;AAAA,IACjE;AACA,gBAAY;AAAA,EACd;AAEA,WAAS,eAAe,OAA0B;AAChD,UAAM,aAAS,kCAAe,MAAM,OAAO,aAAa;AACxD,QAAI,WAAW,WAAW,MAAM,EAAG;AACnC,YAAQ,iBAAiB,KAAK;AAC9B,YAAQ,oBAAoB,KAAK;AACjC,QAAI,MAAM,iBAAkB;AAC5B,QAAI,OAAO;AACT,cAAQ,IAAI,mBAAmB,MAAM,OAAO,aAAa;AAAA,IAC3D;AACA,gBAAY;AAAA,EACd;AAEA,WAAS,gBAAgB,OAAsB;AAC7C,QAAI,CAAC,WAAW,UAAU,IAAK,EAAG;AAClC,YAAQ,kBAAkB,KAAK;AAC/B,QAAI,CAAC,MAAM,oBAAoB,WAAW;AACxC,YAAM,eAAe;AACrB,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,WAAS,QAAQ,QAAiB;AAChC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,aAAa,OAAO,sBAAsB,aAAa,kBAAkB,IAAI;AACnF,UAAM,cAAc,MAAM,QAAQ,UAAU,IAAI,aAAa,CAAC,UAAU;AACxE,UAAM,qBAAqB,QAAQ,oBAAoB,IAAI,CAAC,OAAO,GAAG,CAAC,EAAE,OAAO,+BAAa;AAC7F,QAAI,mBAAoB,aAAY,KAAK,GAAG,kBAAkB;AAC9D,WAAO,YAAY,KAAK,CAACC,cAAS,4BAASA,OAAM,MAAM,CAAC,KAAK,WAAW,gBAAgB,MAAM,MAAM;AAAA,EACtG;AAEA,QAAM,WAAW;AAAA,IACf,kBAAkB,4BAA4B,MAAM,QAAQ,kBAAkB,IAAI;AAAA,IAClF,mBAAmB,MAAM,eAAe;AAAA,QACxC,8CAAqB,MAAM,EAAE,SAAS,gBAAgB,sBAAsB,OAAO,QAAQ,MAAM,CAAC;AAAA,EACpG;AAEA,SAAO,MAAM;AACX,eAAW,OAAO,IAAK;AAEvB,+BAA2B;AAE3B,sBAAkB,IAAK;AACvB,aAAS,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,EACjC;AACF;AAEO,SAAS,wBAAwB,UAAoB,SAAoC;AAC9F,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,OAAO,QAAQ,wBAAM,CAAC,MAAW,EAAE;AACzC,QAAM,WAAyC,CAAC;AAChD,WAAS;AAAA,IACP,KAAK,MAAM;AACT,YAAM,WAAO,yBAAW,QAAQ,IAAI,SAAS,IAAI;AACjD,eAAS,KAAK,4BAA4B,MAAM,OAAO,CAAC;AAAA,IAC1D,CAAC;AAAA,EACH;AACA,SAAO,MAAM;AACX,aAAS,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,EACjC;AACF;AAEO,SAAS,uBAAuB,UAAoB,UAA+B,CAAC,GAAG;AAC5F,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,OAAO,QAAQ,wBAAM,CAAC,MAAW,EAAE;AACzC,QAAM,WAAyC,CAAC;AAEhD,WAAS;AAAA,IACP,KAAK,MAAM;AACT,YAAM,WAAO,yBAAW,QAAQ,IAAI,SAAS,IAAI;AACjD,UAAI,CAAC,MAAM;AACT,+BAAK,4DAA4D;AACjE;AAAA,MACF;AACA,iBAAW,UAAU,IAAI;AACzB,eAAS,KAAK,MAAM;AAClB,mBAAW,aAAa,IAAI;AAAA,MAC9B,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,SAAO,MAAM;AACX,aAAS,QAAQ,CAAC,OAAO,KAAK,CAAC;AAAA,EACjC;AACF;","names":["import_dom_query","import_dom_query","import_dom_query","node"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dismissable-layer.ts","../src/escape-keydown.ts","../src/layer-stack.ts","../src/pointer-event-outside.ts"],"sourcesContent":["import { contains, getEventTarget, isHTMLElement, raf } from \"@zag-js/dom-query\"\nimport {\n trackInteractOutside,\n type FocusOutsideEvent,\n type InteractOutsideHandlers,\n type PointerDownOutsideEvent,\n} from \"@zag-js/interact-outside\"\nimport { isFunction, warn, type MaybeFunction } from \"@zag-js/utils\"\nimport { trackEscapeKeydown } from \"./escape-keydown\"\nimport { layerStack, type Layer } from \"./layer-stack\"\nimport { assignPointerEventToLayers, clearPointerEvent, disablePointerEventsOutside } from \"./pointer-event-outside\"\n\ntype MaybeElement = HTMLElement | null\ntype Container = MaybeElement | Array<MaybeElement>\ntype NodeOrFn = MaybeFunction<MaybeElement>\n\nexport interface DismissableElementHandlers extends InteractOutsideHandlers {\n /**\n * Function called when the escape key is pressed\n */\n onEscapeKeyDown?: (event: KeyboardEvent) => void\n}\n\nexport interface PersistentElementOptions {\n /**\n * Returns the persistent elements that:\n * - should not have pointer-events disabled\n * - should not trigger the dismiss event\n */\n persistentElements?: Array<() => Element | null>\n}\n\nexport interface DismissableElementOptions extends DismissableElementHandlers, PersistentElementOptions {\n /**\n * Whether to log debug information\n */\n debug?: boolean\n /**\n * Whether to block pointer events outside the dismissable element\n */\n pointerBlocking?: boolean\n /**\n * Function called when the dismissable element is dismissed\n */\n onDismiss: VoidFunction\n /**\n * Exclude containers from the interact outside event\n */\n exclude?: MaybeFunction<Container>\n /**\n * Defer the interact outside event to the next frame\n */\n defer?: boolean\n}\n\nfunction trackDismissableElementImpl(node: MaybeElement, options: DismissableElementOptions) {\n if (!node) {\n warn(\"[@zag-js/dismissable] node is `null` or `undefined`\")\n return\n }\n\n const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options\n\n const layer: Layer = { dismiss: onDismiss, node, pointerBlocking }\n\n layerStack.add(layer)\n assignPointerEventToLayers()\n\n function onPointerDownOutside(event: PointerDownOutsideEvent) {\n const target = getEventTarget(event.detail.originalEvent)\n if (layerStack.isBelowPointerBlockingLayer(node!) || layerStack.isInBranch(target)) return\n options.onPointerDownOutside?.(event)\n options.onInteractOutside?.(event)\n if (event.defaultPrevented) return\n if (debug) {\n console.log(\"onPointerDownOutside:\", event.detail.originalEvent)\n }\n onDismiss?.()\n }\n\n function onFocusOutside(event: FocusOutsideEvent) {\n const target = getEventTarget(event.detail.originalEvent)\n if (layerStack.isInBranch(target)) return\n options.onFocusOutside?.(event)\n options.onInteractOutside?.(event)\n if (event.defaultPrevented) return\n if (debug) {\n console.log(\"onFocusOutside:\", event.detail.originalEvent)\n }\n onDismiss?.()\n }\n\n function onEscapeKeyDown(event: KeyboardEvent) {\n if (!layerStack.isTopMost(node!)) return\n options.onEscapeKeyDown?.(event)\n if (!event.defaultPrevented && onDismiss) {\n event.preventDefault()\n onDismiss()\n }\n }\n\n function exclude(target: Element) {\n if (!node) return false\n const containers = typeof excludeContainers === \"function\" ? excludeContainers() : excludeContainers\n const _containers = Array.isArray(containers) ? containers : [containers]\n const persistentElements = options.persistentElements?.map((fn) => fn()).filter(isHTMLElement)\n if (persistentElements) _containers.push(...persistentElements)\n return _containers.some((node) => contains(node, target)) || layerStack.isInNestedLayer(node, target)\n }\n\n const cleanups = [\n pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : undefined,\n trackEscapeKeydown(node, onEscapeKeyDown),\n trackInteractOutside(node, { exclude, onFocusOutside, onPointerDownOutside, defer: options.defer }),\n ]\n\n return () => {\n layerStack.remove(node!)\n // re-assign pointer event to remaining layers\n assignPointerEventToLayers()\n // remove pointer event from removed layer\n clearPointerEvent(node!)\n cleanups.forEach((fn) => fn?.())\n }\n}\n\nexport function trackDismissableElement(nodeOrFn: NodeOrFn, options: DismissableElementOptions) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn\n cleanups.push(trackDismissableElementImpl(node, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n\nexport function trackDismissableBranch(nodeOrFn: NodeOrFn, options: { defer?: boolean } = {}) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n\n cleanups.push(\n func(() => {\n const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn\n if (!node) {\n warn(\"[@zag-js/dismissable] branch node is `null` or `undefined`\")\n return\n }\n layerStack.addBranch(node)\n cleanups.push(() => {\n layerStack.removeBranch(node)\n })\n }),\n )\n\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n","import { addDomEvent } from \"@zag-js/dom-event\"\nimport { getDocument } from \"@zag-js/dom-query\"\n\nexport function trackEscapeKeydown(node: HTMLElement, fn?: (event: KeyboardEvent) => void) {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return\n if (event.isComposing) return\n fn?.(event)\n }\n\n return addDomEvent(getDocument(node), \"keydown\", handleKeyDown, { capture: true })\n}\n","import { contains } from \"@zag-js/dom-query\"\n\nexport interface Layer {\n dismiss: VoidFunction\n node: HTMLElement\n pointerBlocking?: boolean\n}\n\nexport const layerStack = {\n layers: [] as Layer[],\n branches: [] as HTMLElement[],\n count(): number {\n return this.layers.length\n },\n pointerBlockingLayers(): Layer[] {\n return this.layers.filter((layer) => layer.pointerBlocking)\n },\n topMostPointerBlockingLayer(): Layer | undefined {\n return [...this.pointerBlockingLayers()].slice(-1)[0]\n },\n hasPointerBlockingLayer(): boolean {\n return this.pointerBlockingLayers().length > 0\n },\n isBelowPointerBlockingLayer(node: HTMLElement) {\n const index = this.indexOf(node)\n const highestBlockingIndex = this.topMostPointerBlockingLayer()\n ? this.indexOf(this.topMostPointerBlockingLayer()?.node)\n : -1\n return index < highestBlockingIndex\n },\n isTopMost(node: HTMLElement | null) {\n const layer = this.layers[this.count() - 1]\n return layer?.node === node\n },\n getNestedLayers(node: HTMLElement) {\n return Array.from(this.layers).slice(this.indexOf(node) + 1)\n },\n isInNestedLayer(node: HTMLElement, target: HTMLElement | EventTarget | null) {\n return this.getNestedLayers(node).some((layer) => contains(layer.node, target))\n },\n isInBranch(target: HTMLElement | EventTarget | null) {\n return Array.from(this.branches).some((branch) => contains(branch, target))\n },\n add(layer: Layer) {\n const num = this.layers.push(layer)\n layer.node.style.setProperty(\"--layer-index\", `${num}`)\n },\n addBranch(node: HTMLElement) {\n this.branches.push(node)\n },\n remove(node: HTMLElement) {\n const index = this.indexOf(node)\n if (index < 0) return\n\n // dismiss nested layers\n if (index < this.count() - 1) {\n const _layers = this.getNestedLayers(node)\n _layers.forEach((layer) => layer.dismiss())\n }\n // remove this layer\n this.layers.splice(index, 1)\n node.style.removeProperty(\"--layer-index\")\n },\n removeBranch(node: HTMLElement) {\n const index = this.branches.indexOf(node)\n if (index >= 0) this.branches.splice(index, 1)\n },\n indexOf(node: HTMLElement | undefined) {\n return this.layers.findIndex((layer) => layer.node === node)\n },\n dismiss(node: HTMLElement) {\n this.layers[this.indexOf(node)]?.dismiss()\n },\n clear() {\n this.remove(this.layers[0].node)\n },\n}\n","import { getDocument, setStyle, waitForElements } from \"@zag-js/dom-query\"\nimport { layerStack } from \"./layer-stack\"\n\nlet originalBodyPointerEvents: string\n\nexport function assignPointerEventToLayers() {\n layerStack.layers.forEach(({ node }) => {\n node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? \"none\" : \"auto\"\n })\n}\n\nexport function clearPointerEvent(node: HTMLElement) {\n node.style.pointerEvents = \"\"\n}\n\nexport function disablePointerEventsOutside(node: HTMLElement, peristentElements?: Array<() => Element | null>) {\n const doc = getDocument(node)\n\n const cleanups: VoidFunction[] = []\n\n if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute(\"data-inert\")) {\n originalBodyPointerEvents = document.body.style.pointerEvents\n queueMicrotask(() => {\n doc.body.style.pointerEvents = \"none\"\n doc.body.setAttribute(\"data-inert\", \"\")\n })\n }\n\n if (peristentElements) {\n const persistedCleanup = waitForElements(peristentElements, (el) => {\n cleanups.push(setStyle(el, { pointerEvents: \"auto\" }))\n })\n cleanups.push(persistedCleanup)\n }\n\n return () => {\n if (layerStack.hasPointerBlockingLayer()) return\n queueMicrotask(() => {\n doc.body.style.pointerEvents = originalBodyPointerEvents\n doc.body.removeAttribute(\"data-inert\")\n if (doc.body.style.length === 0) doc.body.removeAttribute(\"style\")\n })\n cleanups.forEach((fn) => fn())\n }\n}\n"],"mappings":"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","names":["contains","getDocument","getDocument","node","contains"]}
@@ -1,164 +0,0 @@
1
- import { contains, getEventTarget, isHTMLElement, raf } from "@zag-js/dom-query"
2
- import {
3
- trackInteractOutside,
4
- type FocusOutsideEvent,
5
- type InteractOutsideHandlers,
6
- type PointerDownOutsideEvent,
7
- } from "@zag-js/interact-outside"
8
- import { isFunction, warn, type MaybeFunction } from "@zag-js/utils"
9
- import { trackEscapeKeydown } from "./escape-keydown"
10
- import { layerStack, type Layer } from "./layer-stack"
11
- import { assignPointerEventToLayers, clearPointerEvent, disablePointerEventsOutside } from "./pointer-event-outside"
12
-
13
- type MaybeElement = HTMLElement | null
14
- type Container = MaybeElement | Array<MaybeElement>
15
- type NodeOrFn = MaybeFunction<MaybeElement>
16
-
17
- export interface DismissableElementHandlers extends InteractOutsideHandlers {
18
- /**
19
- * Function called when the escape key is pressed
20
- */
21
- onEscapeKeyDown?: (event: KeyboardEvent) => void
22
- }
23
-
24
- export interface PersistentElementOptions {
25
- /**
26
- * Returns the persistent elements that:
27
- * - should not have pointer-events disabled
28
- * - should not trigger the dismiss event
29
- */
30
- persistentElements?: Array<() => Element | null>
31
- }
32
-
33
- export interface DismissableElementOptions extends DismissableElementHandlers, PersistentElementOptions {
34
- /**
35
- * Whether to log debug information
36
- */
37
- debug?: boolean
38
- /**
39
- * Whether to block pointer events outside the dismissable element
40
- */
41
- pointerBlocking?: boolean
42
- /**
43
- * Function called when the dismissable element is dismissed
44
- */
45
- onDismiss: VoidFunction
46
- /**
47
- * Exclude containers from the interact outside event
48
- */
49
- exclude?: MaybeFunction<Container>
50
- /**
51
- * Defer the interact outside event to the next frame
52
- */
53
- defer?: boolean
54
- }
55
-
56
- function trackDismissableElementImpl(node: MaybeElement, options: DismissableElementOptions) {
57
- if (!node) {
58
- warn("[@zag-js/dismissable] node is `null` or `undefined`")
59
- return
60
- }
61
-
62
- const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options
63
-
64
- const layer: Layer = { dismiss: onDismiss, node, pointerBlocking }
65
-
66
- layerStack.add(layer)
67
- assignPointerEventToLayers()
68
-
69
- function onPointerDownOutside(event: PointerDownOutsideEvent) {
70
- const target = getEventTarget(event.detail.originalEvent)
71
- if (layerStack.isBelowPointerBlockingLayer(node!) || layerStack.isInBranch(target)) return
72
- options.onPointerDownOutside?.(event)
73
- options.onInteractOutside?.(event)
74
- if (event.defaultPrevented) return
75
- if (debug) {
76
- console.log("onPointerDownOutside:", event.detail.originalEvent)
77
- }
78
- onDismiss?.()
79
- }
80
-
81
- function onFocusOutside(event: FocusOutsideEvent) {
82
- const target = getEventTarget(event.detail.originalEvent)
83
- if (layerStack.isInBranch(target)) return
84
- options.onFocusOutside?.(event)
85
- options.onInteractOutside?.(event)
86
- if (event.defaultPrevented) return
87
- if (debug) {
88
- console.log("onFocusOutside:", event.detail.originalEvent)
89
- }
90
- onDismiss?.()
91
- }
92
-
93
- function onEscapeKeyDown(event: KeyboardEvent) {
94
- if (!layerStack.isTopMost(node!)) return
95
- options.onEscapeKeyDown?.(event)
96
- if (!event.defaultPrevented && onDismiss) {
97
- event.preventDefault()
98
- onDismiss()
99
- }
100
- }
101
-
102
- function exclude(target: Element) {
103
- if (!node) return false
104
- const containers = typeof excludeContainers === "function" ? excludeContainers() : excludeContainers
105
- const _containers = Array.isArray(containers) ? containers : [containers]
106
- const persistentElements = options.persistentElements?.map((fn) => fn()).filter(isHTMLElement)
107
- if (persistentElements) _containers.push(...persistentElements)
108
- return _containers.some((node) => contains(node, target)) || layerStack.isInNestedLayer(node, target)
109
- }
110
-
111
- const cleanups = [
112
- pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : undefined,
113
- trackEscapeKeydown(node, onEscapeKeyDown),
114
- trackInteractOutside(node, { exclude, onFocusOutside, onPointerDownOutside, defer: options.defer }),
115
- ]
116
-
117
- return () => {
118
- layerStack.remove(node!)
119
- // re-assign pointer event to remaining layers
120
- assignPointerEventToLayers()
121
- // remove pointer event from removed layer
122
- clearPointerEvent(node!)
123
- cleanups.forEach((fn) => fn?.())
124
- }
125
- }
126
-
127
- export function trackDismissableElement(nodeOrFn: NodeOrFn, options: DismissableElementOptions) {
128
- const { defer } = options
129
- const func = defer ? raf : (v: any) => v()
130
- const cleanups: (VoidFunction | undefined)[] = []
131
- cleanups.push(
132
- func(() => {
133
- const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn
134
- cleanups.push(trackDismissableElementImpl(node, options))
135
- }),
136
- )
137
- return () => {
138
- cleanups.forEach((fn) => fn?.())
139
- }
140
- }
141
-
142
- export function trackDismissableBranch(nodeOrFn: NodeOrFn, options: { defer?: boolean } = {}) {
143
- const { defer } = options
144
- const func = defer ? raf : (v: any) => v()
145
- const cleanups: (VoidFunction | undefined)[] = []
146
-
147
- cleanups.push(
148
- func(() => {
149
- const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn
150
- if (!node) {
151
- warn("[@zag-js/dismissable] branch node is `null` or `undefined`")
152
- return
153
- }
154
- layerStack.addBranch(node)
155
- cleanups.push(() => {
156
- layerStack.removeBranch(node)
157
- })
158
- }),
159
- )
160
-
161
- return () => {
162
- cleanups.forEach((fn) => fn?.())
163
- }
164
- }
@@ -1,12 +0,0 @@
1
- import { addDomEvent } from "@zag-js/dom-event"
2
- import { getDocument } from "@zag-js/dom-query"
3
-
4
- export function trackEscapeKeydown(node: HTMLElement, fn?: (event: KeyboardEvent) => void) {
5
- const handleKeyDown = (event: KeyboardEvent) => {
6
- if (event.key !== "Escape") return
7
- if (event.isComposing) return
8
- fn?.(event)
9
- }
10
-
11
- return addDomEvent(getDocument(node), "keydown", handleKeyDown, { capture: true })
12
- }
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export type {
2
- FocusOutsideEvent,
3
- InteractOutsideEvent,
4
- InteractOutsideHandlers,
5
- PointerDownOutsideEvent,
6
- } from "@zag-js/interact-outside"
7
- export * from "./dismissable-layer"
@@ -1,77 +0,0 @@
1
- import { contains } from "@zag-js/dom-query"
2
-
3
- export interface Layer {
4
- dismiss: VoidFunction
5
- node: HTMLElement
6
- pointerBlocking?: boolean
7
- }
8
-
9
- export const layerStack = {
10
- layers: [] as Layer[],
11
- branches: [] as HTMLElement[],
12
- count(): number {
13
- return this.layers.length
14
- },
15
- pointerBlockingLayers(): Layer[] {
16
- return this.layers.filter((layer) => layer.pointerBlocking)
17
- },
18
- topMostPointerBlockingLayer(): Layer | undefined {
19
- return [...this.pointerBlockingLayers()].slice(-1)[0]
20
- },
21
- hasPointerBlockingLayer(): boolean {
22
- return this.pointerBlockingLayers().length > 0
23
- },
24
- isBelowPointerBlockingLayer(node: HTMLElement) {
25
- const index = this.indexOf(node)
26
- const highestBlockingIndex = this.topMostPointerBlockingLayer()
27
- ? this.indexOf(this.topMostPointerBlockingLayer()?.node)
28
- : -1
29
- return index < highestBlockingIndex
30
- },
31
- isTopMost(node: HTMLElement | null) {
32
- const layer = this.layers[this.count() - 1]
33
- return layer?.node === node
34
- },
35
- getNestedLayers(node: HTMLElement) {
36
- return Array.from(this.layers).slice(this.indexOf(node) + 1)
37
- },
38
- isInNestedLayer(node: HTMLElement, target: HTMLElement | EventTarget | null) {
39
- return this.getNestedLayers(node).some((layer) => contains(layer.node, target))
40
- },
41
- isInBranch(target: HTMLElement | EventTarget | null) {
42
- return Array.from(this.branches).some((branch) => contains(branch, target))
43
- },
44
- add(layer: Layer) {
45
- const num = this.layers.push(layer)
46
- layer.node.style.setProperty("--layer-index", `${num}`)
47
- },
48
- addBranch(node: HTMLElement) {
49
- this.branches.push(node)
50
- },
51
- remove(node: HTMLElement) {
52
- const index = this.indexOf(node)
53
- if (index < 0) return
54
-
55
- // dismiss nested layers
56
- if (index < this.count() - 1) {
57
- const _layers = this.getNestedLayers(node)
58
- _layers.forEach((layer) => layer.dismiss())
59
- }
60
- // remove this layer
61
- this.layers.splice(index, 1)
62
- node.style.removeProperty("--layer-index")
63
- },
64
- removeBranch(node: HTMLElement) {
65
- const index = this.branches.indexOf(node)
66
- if (index >= 0) this.branches.splice(index, 1)
67
- },
68
- indexOf(node: HTMLElement | undefined) {
69
- return this.layers.findIndex((layer) => layer.node === node)
70
- },
71
- dismiss(node: HTMLElement) {
72
- this.layers[this.indexOf(node)]?.dismiss()
73
- },
74
- clear() {
75
- this.remove(this.layers[0].node)
76
- },
77
- }
@@ -1,45 +0,0 @@
1
- import { getDocument, setStyle, waitForElements } from "@zag-js/dom-query"
2
- import { layerStack } from "./layer-stack"
3
-
4
- let originalBodyPointerEvents: string
5
-
6
- export function assignPointerEventToLayers() {
7
- layerStack.layers.forEach(({ node }) => {
8
- node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto"
9
- })
10
- }
11
-
12
- export function clearPointerEvent(node: HTMLElement) {
13
- node.style.pointerEvents = ""
14
- }
15
-
16
- export function disablePointerEventsOutside(node: HTMLElement, peristentElements?: Array<() => Element | null>) {
17
- const doc = getDocument(node)
18
-
19
- const cleanups: VoidFunction[] = []
20
-
21
- if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
22
- originalBodyPointerEvents = document.body.style.pointerEvents
23
- queueMicrotask(() => {
24
- doc.body.style.pointerEvents = "none"
25
- doc.body.setAttribute("data-inert", "")
26
- })
27
- }
28
-
29
- if (peristentElements) {
30
- const persistedCleanup = waitForElements(peristentElements, (el) => {
31
- cleanups.push(setStyle(el, { pointerEvents: "auto" }))
32
- })
33
- cleanups.push(persistedCleanup)
34
- }
35
-
36
- return () => {
37
- if (layerStack.hasPointerBlockingLayer()) return
38
- queueMicrotask(() => {
39
- doc.body.style.pointerEvents = originalBodyPointerEvents
40
- doc.body.removeAttribute("data-inert")
41
- if (doc.body.style.length === 0) doc.body.removeAttribute("style")
42
- })
43
- cleanups.forEach((fn) => fn())
44
- }
45
- }