@zag-js/dismissable 1.21.9 → 1.22.1

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.d.mts CHANGED
@@ -2,6 +2,14 @@ import { InteractOutsideHandlers } from '@zag-js/interact-outside';
2
2
  export { FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, PointerDownOutsideEvent } from '@zag-js/interact-outside';
3
3
  import { MaybeFunction } from '@zag-js/utils';
4
4
 
5
+ type LayerDismissEventDetail = {
6
+ originalLayer: HTMLElement;
7
+ targetLayer: HTMLElement | undefined;
8
+ originalIndex: number;
9
+ targetIndex: number;
10
+ };
11
+ type LayerDismissEvent = CustomEvent<LayerDismissEventDetail>;
12
+
5
13
  type MaybeElement = HTMLElement | null;
6
14
  type Container = MaybeElement | Array<MaybeElement>;
7
15
  type NodeOrFn = MaybeFunction<MaybeElement>;
@@ -10,6 +18,10 @@ interface DismissableElementHandlers extends InteractOutsideHandlers {
10
18
  * Function called when the escape key is pressed
11
19
  */
12
20
  onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;
21
+ /**
22
+ * Function called when this layer is closed due to a parent layer being closed
23
+ */
24
+ onRequestDismiss?: ((event: LayerDismissEvent) => void) | undefined;
13
25
  }
14
26
  interface PersistentElementOptions {
15
27
  /**
package/dist/index.d.ts CHANGED
@@ -2,6 +2,14 @@ import { InteractOutsideHandlers } from '@zag-js/interact-outside';
2
2
  export { FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, PointerDownOutsideEvent } from '@zag-js/interact-outside';
3
3
  import { MaybeFunction } from '@zag-js/utils';
4
4
 
5
+ type LayerDismissEventDetail = {
6
+ originalLayer: HTMLElement;
7
+ targetLayer: HTMLElement | undefined;
8
+ originalIndex: number;
9
+ targetIndex: number;
10
+ };
11
+ type LayerDismissEvent = CustomEvent<LayerDismissEventDetail>;
12
+
5
13
  type MaybeElement = HTMLElement | null;
6
14
  type Container = MaybeElement | Array<MaybeElement>;
7
15
  type NodeOrFn = MaybeFunction<MaybeElement>;
@@ -10,6 +18,10 @@ interface DismissableElementHandlers extends InteractOutsideHandlers {
10
18
  * Function called when the escape key is pressed
11
19
  */
12
20
  onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;
21
+ /**
22
+ * Function called when this layer is closed due to a parent layer being closed
23
+ */
24
+ onRequestDismiss?: ((event: LayerDismissEvent) => void) | undefined;
13
25
  }
14
26
  interface PersistentElementOptions {
15
27
  /**
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ function trackEscapeKeydown(node, fn) {
13
13
  };
14
14
  return domQuery.addDomEvent(domQuery.getDocument(node), "keydown", handleKeyDown, { capture: true });
15
15
  }
16
+ var LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
16
17
  var layerStack = {
17
18
  layers: [],
18
19
  branches: [],
@@ -47,8 +48,8 @@ var layerStack = {
47
48
  return Array.from(this.branches).some((branch) => domQuery.contains(branch, target));
48
49
  },
49
50
  add(layer) {
50
- const num = this.layers.push(layer);
51
- layer.node.style.setProperty("--layer-index", `${num}`);
51
+ this.layers.push(layer);
52
+ this.syncLayerIndex();
52
53
  },
53
54
  addBranch(node) {
54
55
  this.branches.push(node);
@@ -58,25 +59,53 @@ var layerStack = {
58
59
  if (index < 0) return;
59
60
  if (index < this.count() - 1) {
60
61
  const _layers = this.getNestedLayers(node);
61
- _layers.forEach((layer) => layer.dismiss());
62
+ _layers.forEach((layer) => layerStack.dismiss(layer.node, node));
62
63
  }
63
64
  this.layers.splice(index, 1);
64
- node.style.removeProperty("--layer-index");
65
+ this.syncLayerIndex();
65
66
  },
66
67
  removeBranch(node) {
67
68
  const index = this.branches.indexOf(node);
68
69
  if (index >= 0) this.branches.splice(index, 1);
69
70
  },
71
+ syncLayerIndex() {
72
+ this.layers.forEach((layer, index) => {
73
+ layer.node.style.setProperty("--layer-index", `${index}`);
74
+ });
75
+ },
70
76
  indexOf(node) {
71
77
  return this.layers.findIndex((layer) => layer.node === node);
72
78
  },
73
- dismiss(node) {
74
- this.layers[this.indexOf(node)]?.dismiss();
79
+ dismiss(node, parent) {
80
+ const index = this.indexOf(node);
81
+ if (index === -1) return;
82
+ const layer = this.layers[index];
83
+ addListenerOnce(node, LAYER_REQUEST_DISMISS_EVENT, (event) => {
84
+ layer.requestDismiss?.(event);
85
+ if (!event.defaultPrevented) {
86
+ layer?.dismiss();
87
+ }
88
+ });
89
+ fireCustomEvent(node, LAYER_REQUEST_DISMISS_EVENT, {
90
+ originalLayer: node,
91
+ targetLayer: parent,
92
+ originalIndex: index,
93
+ targetIndex: parent ? this.indexOf(parent) : -1
94
+ });
95
+ this.syncLayerIndex();
75
96
  },
76
97
  clear() {
77
98
  this.remove(this.layers[0].node);
78
99
  }
79
100
  };
101
+ function fireCustomEvent(el, type, detail) {
102
+ const win = el.ownerDocument.defaultView || window;
103
+ const event = new win.CustomEvent(type, { cancelable: true, bubbles: true, detail });
104
+ return el.dispatchEvent(event);
105
+ }
106
+ function addListenerOnce(el, type, callback) {
107
+ el.addEventListener(type, callback, { once: true });
108
+ }
80
109
  var originalBodyPointerEvents;
81
110
  function assignPointerEventToLayers() {
82
111
  layerStack.layers.forEach(({ node }) => {
@@ -128,8 +157,8 @@ function trackDismissableElementImpl(node, options) {
128
157
  if (!node) {
129
158
  return;
130
159
  }
131
- const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
132
- const layer = { dismiss: onDismiss, node, pointerBlocking };
160
+ const { onDismiss, onRequestDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
161
+ const layer = { dismiss: onDismiss, node, pointerBlocking, requestDismiss: onRequestDismiss };
133
162
  layerStack.add(layer);
134
163
  assignPointerEventToLayers();
135
164
  function onPointerDownOutside(event) {
package/dist/index.mjs CHANGED
@@ -11,6 +11,7 @@ function trackEscapeKeydown(node, fn) {
11
11
  };
12
12
  return addDomEvent(getDocument(node), "keydown", handleKeyDown, { capture: true });
13
13
  }
14
+ var LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
14
15
  var layerStack = {
15
16
  layers: [],
16
17
  branches: [],
@@ -45,8 +46,8 @@ var layerStack = {
45
46
  return Array.from(this.branches).some((branch) => contains(branch, target));
46
47
  },
47
48
  add(layer) {
48
- const num = this.layers.push(layer);
49
- layer.node.style.setProperty("--layer-index", `${num}`);
49
+ this.layers.push(layer);
50
+ this.syncLayerIndex();
50
51
  },
51
52
  addBranch(node) {
52
53
  this.branches.push(node);
@@ -56,25 +57,53 @@ var layerStack = {
56
57
  if (index < 0) return;
57
58
  if (index < this.count() - 1) {
58
59
  const _layers = this.getNestedLayers(node);
59
- _layers.forEach((layer) => layer.dismiss());
60
+ _layers.forEach((layer) => layerStack.dismiss(layer.node, node));
60
61
  }
61
62
  this.layers.splice(index, 1);
62
- node.style.removeProperty("--layer-index");
63
+ this.syncLayerIndex();
63
64
  },
64
65
  removeBranch(node) {
65
66
  const index = this.branches.indexOf(node);
66
67
  if (index >= 0) this.branches.splice(index, 1);
67
68
  },
69
+ syncLayerIndex() {
70
+ this.layers.forEach((layer, index) => {
71
+ layer.node.style.setProperty("--layer-index", `${index}`);
72
+ });
73
+ },
68
74
  indexOf(node) {
69
75
  return this.layers.findIndex((layer) => layer.node === node);
70
76
  },
71
- dismiss(node) {
72
- this.layers[this.indexOf(node)]?.dismiss();
77
+ dismiss(node, parent) {
78
+ const index = this.indexOf(node);
79
+ if (index === -1) return;
80
+ const layer = this.layers[index];
81
+ addListenerOnce(node, LAYER_REQUEST_DISMISS_EVENT, (event) => {
82
+ layer.requestDismiss?.(event);
83
+ if (!event.defaultPrevented) {
84
+ layer?.dismiss();
85
+ }
86
+ });
87
+ fireCustomEvent(node, LAYER_REQUEST_DISMISS_EVENT, {
88
+ originalLayer: node,
89
+ targetLayer: parent,
90
+ originalIndex: index,
91
+ targetIndex: parent ? this.indexOf(parent) : -1
92
+ });
93
+ this.syncLayerIndex();
73
94
  },
74
95
  clear() {
75
96
  this.remove(this.layers[0].node);
76
97
  }
77
98
  };
99
+ function fireCustomEvent(el, type, detail) {
100
+ const win = el.ownerDocument.defaultView || window;
101
+ const event = new win.CustomEvent(type, { cancelable: true, bubbles: true, detail });
102
+ return el.dispatchEvent(event);
103
+ }
104
+ function addListenerOnce(el, type, callback) {
105
+ el.addEventListener(type, callback, { once: true });
106
+ }
78
107
  var originalBodyPointerEvents;
79
108
  function assignPointerEventToLayers() {
80
109
  layerStack.layers.forEach(({ node }) => {
@@ -126,8 +155,8 @@ function trackDismissableElementImpl(node, options) {
126
155
  if (!node) {
127
156
  return;
128
157
  }
129
- const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
130
- const layer = { dismiss: onDismiss, node, pointerBlocking };
158
+ const { onDismiss, onRequestDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
159
+ const layer = { dismiss: onDismiss, node, pointerBlocking, requestDismiss: onRequestDismiss };
131
160
  layerStack.add(layer);
132
161
  assignPointerEventToLayers();
133
162
  function onPointerDownOutside(event) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/dismissable",
3
- "version": "1.21.9",
3
+ "version": "1.22.1",
4
4
  "description": "Dismissable layer utilities for the DOM",
5
5
  "keywords": [
6
6
  "js",
@@ -23,9 +23,9 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@zag-js/interact-outside": "1.21.9",
27
- "@zag-js/dom-query": "1.21.9",
28
- "@zag-js/utils": "1.21.9"
26
+ "@zag-js/interact-outside": "1.22.1",
27
+ "@zag-js/dom-query": "1.22.1",
28
+ "@zag-js/utils": "1.22.1"
29
29
  },
30
30
  "devDependencies": {
31
31
  "clean-package": "2.2.0"