@zag-js/dismissable 2.0.0-next.0 → 2.0.0-next.2

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.
@@ -20,20 +20,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/layer-stack.ts
21
21
  var layer_stack_exports = {};
22
22
  __export(layer_stack_exports, {
23
+ isPointerBlocking: () => isPointerBlocking,
23
24
  layerStack: () => layerStack
24
25
  });
25
26
  module.exports = __toCommonJS(layer_stack_exports);
26
27
  var import_dom_query = require("@zag-js/dom-query");
28
+ var import_utils = require("@zag-js/utils");
27
29
  var LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
30
+ var layerId = 0;
31
+ function isPointerBlocking(layer) {
32
+ const value = layer.pointerBlocking;
33
+ return typeof value === "function" ? value() : !!value;
34
+ }
28
35
  var layerStack = {
29
36
  layers: [],
30
37
  branches: [],
31
38
  recentlyRemoved: /* @__PURE__ */ new Set(),
39
+ pendingReattach: /* @__PURE__ */ new Map(),
32
40
  count() {
33
41
  return this.layers.length;
34
42
  },
35
43
  pointerBlockingLayers() {
36
- return this.layers.filter((layer) => layer.pointerBlocking);
44
+ return this.layers.filter(isPointerBlocking);
37
45
  },
38
46
  topMostPointerBlockingLayer() {
39
47
  return [...this.pointerBlockingLayers()].slice(-1)[0];
@@ -50,21 +58,54 @@ var layerStack = {
50
58
  const layer = this.layers[this.count() - 1];
51
59
  return layer?.node === node;
52
60
  },
61
+ layerFor(node) {
62
+ return this.layers.find((layer) => layer.node === node);
63
+ },
64
+ isDescendantOf(layer, ancestorId) {
65
+ if (!ancestorId) return false;
66
+ const seen = /* @__PURE__ */ new Set();
67
+ let parentId = layer.parentId;
68
+ while (parentId && !seen.has(parentId)) {
69
+ if (parentId === ancestorId) return true;
70
+ seen.add(parentId);
71
+ parentId = this.layers.find((l) => l.id === parentId)?.parentId;
72
+ }
73
+ return false;
74
+ },
75
+ depthOf(layer) {
76
+ const seen = /* @__PURE__ */ new Set();
77
+ let depth = 0;
78
+ let parentId = layer.parentId;
79
+ while (parentId && !seen.has(parentId)) {
80
+ depth++;
81
+ seen.add(parentId);
82
+ parentId = this.layers.find((l) => l.id === parentId)?.parentId;
83
+ }
84
+ return depth;
85
+ },
86
+ /** Descendants, shallowest first, so a cascade dismisses parents before their own children. */
53
87
  getNestedLayers(node) {
54
- return Array.from(this.layers).slice(this.indexOf(node) + 1);
88
+ const id = this.layerFor(node)?.id;
89
+ if (!id) return [];
90
+ return this.layers.filter((layer) => this.isDescendantOf(layer, id)).sort((a, b) => this.depthOf(a) - this.depthOf(b));
55
91
  },
56
92
  getLayersByType(type) {
57
93
  return this.layers.filter((layer) => layer.type === type);
58
94
  },
59
95
  getNestedLayersByType(node, type) {
60
- const index = this.indexOf(node);
61
- if (index === -1) return [];
62
- return this.layers.slice(index + 1).filter((layer) => layer.type === type);
96
+ return this.getNestedLayers(node).filter((layer) => layer.type === type);
63
97
  },
64
98
  getParentLayerOfType(node, type) {
65
- const index = this.indexOf(node);
66
- if (index <= 0) return void 0;
67
- return this.layers.slice(0, index).reverse().find((layer) => layer.type === type);
99
+ const seen = /* @__PURE__ */ new Set();
100
+ let parentId = this.layerFor(node)?.parentId;
101
+ while (parentId && !seen.has(parentId)) {
102
+ const parent = this.layers.find((l) => l.id === parentId);
103
+ if (!parent) return void 0;
104
+ if (parent.type === type) return parent;
105
+ seen.add(parentId);
106
+ parentId = parent.parentId;
107
+ }
108
+ return void 0;
68
109
  },
69
110
  countNestedLayersOfType(node, type) {
70
111
  return this.getNestedLayersByType(node, type).length;
@@ -80,32 +121,47 @@ var layerStack = {
80
121
  },
81
122
  add(layer) {
82
123
  const existingIndex = this.indexOf(layer.node);
124
+ const existing = existingIndex !== -1 ? this.layers[existingIndex] : void 0;
125
+ const pending = this.pendingReattach.get(layer.node);
126
+ if (existing) {
127
+ layer.id ?? (layer.id = existing.id);
128
+ layer.parentId = existing.parentId;
129
+ } else if (pending) {
130
+ layer.id ?? (layer.id = pending.id);
131
+ layer.parentId = pending.parentId;
132
+ } else {
133
+ layer.id ?? (layer.id = `layer-${++layerId}`);
134
+ layer.parentId ?? (layer.parentId = this.layers[this.count() - 1]?.id);
135
+ }
83
136
  if (existingIndex !== -1) {
84
137
  this.layers.splice(existingIndex, 1);
85
138
  }
86
- this.layers.push(layer);
139
+ if (pending) {
140
+ this.pendingReattach.delete(layer.node);
141
+ this.layers.splice(Math.min(pending.index, this.count()), 0, layer);
142
+ } else {
143
+ this.layers.push(layer);
144
+ }
87
145
  this.syncLayers();
88
146
  },
89
147
  addBranch(node) {
90
148
  this.branches.push(node);
91
149
  },
92
- remove(node) {
150
+ remove(node, options) {
93
151
  const index = this.indexOf(node);
94
152
  if (index < 0) return;
95
153
  const layer = this.layers[index];
96
- layer.styleTargets?.forEach((getTarget) => {
97
- const target = getTarget();
98
- if (target) {
99
- clearLayerStyleMirror(target);
100
- }
101
- });
102
- this.recentlyRemoved.add(node);
103
- (0, import_dom_query.nextTick)(() => this.recentlyRemoved.delete(node));
104
- if (index < this.count() - 1) {
105
- const _layers = this.getNestedLayers(node);
106
- _layers.forEach((layer2) => layerStack.dismiss(layer2.node, node));
154
+ if (options?.reattach) {
155
+ this.pendingReattach.set(node, { id: layer.id, parentId: layer.parentId, index });
156
+ } else {
157
+ this.recentlyRemoved.add(node);
158
+ (0, import_dom_query.nextTick)(() => this.recentlyRemoved.delete(node));
159
+ this.getNestedLayers(node).forEach((nested) => layerStack.dismiss(nested.node, node));
107
160
  }
108
161
  this.layers.splice(index, 1);
162
+ if (layer.snapshot) {
163
+ publishSnapshot(layer, { ...layer.snapshot, active: false, blocked: false });
164
+ }
109
165
  this.syncLayers();
110
166
  },
111
167
  removeBranch(node) {
@@ -114,14 +170,20 @@ var layerStack = {
114
170
  },
115
171
  syncLayers() {
116
172
  this.layers.forEach((layer, index) => {
117
- applyLayerStackMetadata(layer, index, layer.node);
118
- layer.styleTargets?.forEach((getTarget) => {
119
- const target = getTarget();
120
- if (!target || target === layer.node) return;
121
- applyLayerStackMetadata(layer, index, target);
122
- const { zIndex } = (0, import_dom_query.getComputedStyle)(layer.node);
123
- target.style.setProperty("--z-index", zIndex);
124
- });
173
+ const parentOfSameType = layerStack.getParentLayerOfType(layer.node, layer.type);
174
+ const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
175
+ const snapshot = {
176
+ active: true,
177
+ type: layer.type,
178
+ index,
179
+ nested: parentOfSameType != null,
180
+ hasNested: nestedCount > 0,
181
+ nestedCount,
182
+ blocked: layerStack.isBelowPointerBlockingLayer(layer.node)
183
+ };
184
+ if (!(0, import_utils.isEqual)(layer.snapshot, snapshot)) {
185
+ publishSnapshot(layer, snapshot);
186
+ }
125
187
  });
126
188
  },
127
189
  indexOf(node) {
@@ -149,26 +211,9 @@ var layerStack = {
149
211
  this.remove(this.layers[0].node);
150
212
  }
151
213
  };
152
- function applyLayerStackMetadata(layer, index, el) {
153
- el.style.setProperty("--layer-index", `${index}`);
154
- el.removeAttribute("data-nested");
155
- el.removeAttribute("data-has-nested");
156
- const parentOfSameType = layerStack.getParentLayerOfType(layer.node, layer.type);
157
- if (parentOfSameType) {
158
- el.setAttribute("data-nested", layer.type);
159
- }
160
- const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
161
- if (nestedCount > 0) {
162
- el.setAttribute("data-has-nested", layer.type);
163
- }
164
- el.style.setProperty("--nested-layer-count", `${nestedCount}`);
165
- }
166
- function clearLayerStyleMirror(el) {
167
- el.style.removeProperty("--layer-index");
168
- el.style.removeProperty("--nested-layer-count");
169
- el.style.removeProperty("--z-index");
170
- el.removeAttribute("data-nested");
171
- el.removeAttribute("data-has-nested");
214
+ function publishSnapshot(layer, snapshot) {
215
+ layer.snapshot = snapshot;
216
+ layer.onLayerChange?.(snapshot);
172
217
  }
173
218
  function fireCustomEvent(el, type, detail) {
174
219
  const win = el.ownerDocument.defaultView || window;
@@ -180,5 +225,6 @@ function addListenerOnce(el, type, callback) {
180
225
  }
181
226
  // Annotate the CommonJS export names for ESM import in node:
182
227
  0 && (module.exports = {
228
+ isPointerBlocking,
183
229
  layerStack
184
230
  });
@@ -1,15 +1,22 @@
1
1
  // src/layer-stack.ts
2
- import { contains, nextTick, getComputedStyle } from "@zag-js/dom-query";
2
+ import { contains, nextTick } from "@zag-js/dom-query";
3
+ import { isEqual } from "@zag-js/utils";
3
4
  var LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
5
+ var layerId = 0;
6
+ function isPointerBlocking(layer) {
7
+ const value = layer.pointerBlocking;
8
+ return typeof value === "function" ? value() : !!value;
9
+ }
4
10
  var layerStack = {
5
11
  layers: [],
6
12
  branches: [],
7
13
  recentlyRemoved: /* @__PURE__ */ new Set(),
14
+ pendingReattach: /* @__PURE__ */ new Map(),
8
15
  count() {
9
16
  return this.layers.length;
10
17
  },
11
18
  pointerBlockingLayers() {
12
- return this.layers.filter((layer) => layer.pointerBlocking);
19
+ return this.layers.filter(isPointerBlocking);
13
20
  },
14
21
  topMostPointerBlockingLayer() {
15
22
  return [...this.pointerBlockingLayers()].slice(-1)[0];
@@ -26,21 +33,54 @@ var layerStack = {
26
33
  const layer = this.layers[this.count() - 1];
27
34
  return layer?.node === node;
28
35
  },
36
+ layerFor(node) {
37
+ return this.layers.find((layer) => layer.node === node);
38
+ },
39
+ isDescendantOf(layer, ancestorId) {
40
+ if (!ancestorId) return false;
41
+ const seen = /* @__PURE__ */ new Set();
42
+ let parentId = layer.parentId;
43
+ while (parentId && !seen.has(parentId)) {
44
+ if (parentId === ancestorId) return true;
45
+ seen.add(parentId);
46
+ parentId = this.layers.find((l) => l.id === parentId)?.parentId;
47
+ }
48
+ return false;
49
+ },
50
+ depthOf(layer) {
51
+ const seen = /* @__PURE__ */ new Set();
52
+ let depth = 0;
53
+ let parentId = layer.parentId;
54
+ while (parentId && !seen.has(parentId)) {
55
+ depth++;
56
+ seen.add(parentId);
57
+ parentId = this.layers.find((l) => l.id === parentId)?.parentId;
58
+ }
59
+ return depth;
60
+ },
61
+ /** Descendants, shallowest first, so a cascade dismisses parents before their own children. */
29
62
  getNestedLayers(node) {
30
- return Array.from(this.layers).slice(this.indexOf(node) + 1);
63
+ const id = this.layerFor(node)?.id;
64
+ if (!id) return [];
65
+ return this.layers.filter((layer) => this.isDescendantOf(layer, id)).sort((a, b) => this.depthOf(a) - this.depthOf(b));
31
66
  },
32
67
  getLayersByType(type) {
33
68
  return this.layers.filter((layer) => layer.type === type);
34
69
  },
35
70
  getNestedLayersByType(node, type) {
36
- const index = this.indexOf(node);
37
- if (index === -1) return [];
38
- return this.layers.slice(index + 1).filter((layer) => layer.type === type);
71
+ return this.getNestedLayers(node).filter((layer) => layer.type === type);
39
72
  },
40
73
  getParentLayerOfType(node, type) {
41
- const index = this.indexOf(node);
42
- if (index <= 0) return void 0;
43
- return this.layers.slice(0, index).reverse().find((layer) => layer.type === type);
74
+ const seen = /* @__PURE__ */ new Set();
75
+ let parentId = this.layerFor(node)?.parentId;
76
+ while (parentId && !seen.has(parentId)) {
77
+ const parent = this.layers.find((l) => l.id === parentId);
78
+ if (!parent) return void 0;
79
+ if (parent.type === type) return parent;
80
+ seen.add(parentId);
81
+ parentId = parent.parentId;
82
+ }
83
+ return void 0;
44
84
  },
45
85
  countNestedLayersOfType(node, type) {
46
86
  return this.getNestedLayersByType(node, type).length;
@@ -56,32 +96,47 @@ var layerStack = {
56
96
  },
57
97
  add(layer) {
58
98
  const existingIndex = this.indexOf(layer.node);
99
+ const existing = existingIndex !== -1 ? this.layers[existingIndex] : void 0;
100
+ const pending = this.pendingReattach.get(layer.node);
101
+ if (existing) {
102
+ layer.id ?? (layer.id = existing.id);
103
+ layer.parentId = existing.parentId;
104
+ } else if (pending) {
105
+ layer.id ?? (layer.id = pending.id);
106
+ layer.parentId = pending.parentId;
107
+ } else {
108
+ layer.id ?? (layer.id = `layer-${++layerId}`);
109
+ layer.parentId ?? (layer.parentId = this.layers[this.count() - 1]?.id);
110
+ }
59
111
  if (existingIndex !== -1) {
60
112
  this.layers.splice(existingIndex, 1);
61
113
  }
62
- this.layers.push(layer);
114
+ if (pending) {
115
+ this.pendingReattach.delete(layer.node);
116
+ this.layers.splice(Math.min(pending.index, this.count()), 0, layer);
117
+ } else {
118
+ this.layers.push(layer);
119
+ }
63
120
  this.syncLayers();
64
121
  },
65
122
  addBranch(node) {
66
123
  this.branches.push(node);
67
124
  },
68
- remove(node) {
125
+ remove(node, options) {
69
126
  const index = this.indexOf(node);
70
127
  if (index < 0) return;
71
128
  const layer = this.layers[index];
72
- layer.styleTargets?.forEach((getTarget) => {
73
- const target = getTarget();
74
- if (target) {
75
- clearLayerStyleMirror(target);
76
- }
77
- });
78
- this.recentlyRemoved.add(node);
79
- nextTick(() => this.recentlyRemoved.delete(node));
80
- if (index < this.count() - 1) {
81
- const _layers = this.getNestedLayers(node);
82
- _layers.forEach((layer2) => layerStack.dismiss(layer2.node, node));
129
+ if (options?.reattach) {
130
+ this.pendingReattach.set(node, { id: layer.id, parentId: layer.parentId, index });
131
+ } else {
132
+ this.recentlyRemoved.add(node);
133
+ nextTick(() => this.recentlyRemoved.delete(node));
134
+ this.getNestedLayers(node).forEach((nested) => layerStack.dismiss(nested.node, node));
83
135
  }
84
136
  this.layers.splice(index, 1);
137
+ if (layer.snapshot) {
138
+ publishSnapshot(layer, { ...layer.snapshot, active: false, blocked: false });
139
+ }
85
140
  this.syncLayers();
86
141
  },
87
142
  removeBranch(node) {
@@ -90,14 +145,20 @@ var layerStack = {
90
145
  },
91
146
  syncLayers() {
92
147
  this.layers.forEach((layer, index) => {
93
- applyLayerStackMetadata(layer, index, layer.node);
94
- layer.styleTargets?.forEach((getTarget) => {
95
- const target = getTarget();
96
- if (!target || target === layer.node) return;
97
- applyLayerStackMetadata(layer, index, target);
98
- const { zIndex } = getComputedStyle(layer.node);
99
- target.style.setProperty("--z-index", zIndex);
100
- });
148
+ const parentOfSameType = layerStack.getParentLayerOfType(layer.node, layer.type);
149
+ const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
150
+ const snapshot = {
151
+ active: true,
152
+ type: layer.type,
153
+ index,
154
+ nested: parentOfSameType != null,
155
+ hasNested: nestedCount > 0,
156
+ nestedCount,
157
+ blocked: layerStack.isBelowPointerBlockingLayer(layer.node)
158
+ };
159
+ if (!isEqual(layer.snapshot, snapshot)) {
160
+ publishSnapshot(layer, snapshot);
161
+ }
101
162
  });
102
163
  },
103
164
  indexOf(node) {
@@ -125,26 +186,9 @@ var layerStack = {
125
186
  this.remove(this.layers[0].node);
126
187
  }
127
188
  };
128
- function applyLayerStackMetadata(layer, index, el) {
129
- el.style.setProperty("--layer-index", `${index}`);
130
- el.removeAttribute("data-nested");
131
- el.removeAttribute("data-has-nested");
132
- const parentOfSameType = layerStack.getParentLayerOfType(layer.node, layer.type);
133
- if (parentOfSameType) {
134
- el.setAttribute("data-nested", layer.type);
135
- }
136
- const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
137
- if (nestedCount > 0) {
138
- el.setAttribute("data-has-nested", layer.type);
139
- }
140
- el.style.setProperty("--nested-layer-count", `${nestedCount}`);
141
- }
142
- function clearLayerStyleMirror(el) {
143
- el.style.removeProperty("--layer-index");
144
- el.style.removeProperty("--nested-layer-count");
145
- el.style.removeProperty("--z-index");
146
- el.removeAttribute("data-nested");
147
- el.removeAttribute("data-has-nested");
189
+ function publishSnapshot(layer, snapshot) {
190
+ layer.snapshot = snapshot;
191
+ layer.onLayerChange?.(snapshot);
148
192
  }
149
193
  function fireCustomEvent(el, type, detail) {
150
194
  const win = el.ownerDocument.defaultView || window;
@@ -155,5 +199,6 @@ function addListenerOnce(el, type, callback) {
155
199
  el.addEventListener(type, callback, { once: true });
156
200
  }
157
201
  export {
202
+ isPointerBlocking,
158
203
  layerStack
159
204
  };
@@ -1,5 +1,8 @@
1
- declare function assignPointerEventToLayers(): void;
2
- declare function clearPointerEvent(node: HTMLElement): void;
1
+ /**
2
+ * Re-derives pointer blocking from the stack. Needed after a layer's `pointerBlocking` getter
3
+ * changes value, since nothing was added or removed to trigger the usual sync.
4
+ */
5
+ declare function syncPointerEvents(node: HTMLElement): void;
3
6
  declare function disablePointerEventsOutside(node: HTMLElement, persistentElements?: Array<() => Element | null>): () => void;
4
7
 
5
- export { assignPointerEventToLayers, clearPointerEvent, disablePointerEventsOutside };
8
+ export { disablePointerEventsOutside, syncPointerEvents };
@@ -1,5 +1,8 @@
1
- declare function assignPointerEventToLayers(): void;
2
- declare function clearPointerEvent(node: HTMLElement): void;
1
+ /**
2
+ * Re-derives pointer blocking from the stack. Needed after a layer's `pointerBlocking` getter
3
+ * changes value, since nothing was added or removed to trigger the usual sync.
4
+ */
5
+ declare function syncPointerEvents(node: HTMLElement): void;
3
6
  declare function disablePointerEventsOutside(node: HTMLElement, persistentElements?: Array<() => Element | null>): () => void;
4
7
 
5
- export { assignPointerEventToLayers, clearPointerEvent, disablePointerEventsOutside };
8
+ export { disablePointerEventsOutside, syncPointerEvents };
@@ -20,34 +20,45 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/pointer-event-outside.ts
21
21
  var pointer_event_outside_exports = {};
22
22
  __export(pointer_event_outside_exports, {
23
- assignPointerEventToLayers: () => assignPointerEventToLayers,
24
- clearPointerEvent: () => clearPointerEvent,
25
- disablePointerEventsOutside: () => disablePointerEventsOutside
23
+ disablePointerEventsOutside: () => disablePointerEventsOutside,
24
+ syncPointerEvents: () => syncPointerEvents
26
25
  });
27
26
  module.exports = __toCommonJS(pointer_event_outside_exports);
28
27
  var import_dom_query = require("@zag-js/dom-query");
29
28
  var import_layer_stack = require("./layer-stack.js");
30
- var originalBodyPointerEvents;
31
- function assignPointerEventToLayers() {
32
- import_layer_stack.layerStack.layers.forEach(({ node }) => {
33
- node.style.pointerEvents = import_layer_stack.layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto";
29
+ var originalBodyPointerEvents = /* @__PURE__ */ new WeakMap();
30
+ function syncBodyPointerEvents(doc) {
31
+ const body = doc.body;
32
+ if (!body) return;
33
+ const shouldBlock = import_layer_stack.layerStack.hasPointerBlockingLayer();
34
+ if (shouldBlock === body.hasAttribute("data-inert")) return;
35
+ if (shouldBlock) {
36
+ originalBodyPointerEvents.set(body, body.style.pointerEvents);
37
+ queueMicrotask(() => {
38
+ if (!import_layer_stack.layerStack.hasPointerBlockingLayer()) return;
39
+ body.style.pointerEvents = "none";
40
+ body.setAttribute("data-inert", "");
41
+ });
42
+ return;
43
+ }
44
+ queueMicrotask(() => {
45
+ if (import_layer_stack.layerStack.hasPointerBlockingLayer()) return;
46
+ const original = originalBodyPointerEvents.get(body);
47
+ if (original !== void 0) {
48
+ body.style.pointerEvents = original;
49
+ originalBodyPointerEvents.delete(body);
50
+ }
51
+ body.removeAttribute("data-inert");
52
+ if (body.style.length === 0) body.removeAttribute("style");
34
53
  });
35
54
  }
36
- function clearPointerEvent(node) {
37
- node.style.pointerEvents = "";
55
+ function syncPointerEvents(node) {
56
+ syncBodyPointerEvents((0, import_dom_query.getDocument)(node));
38
57
  }
39
58
  function disablePointerEventsOutside(node, persistentElements) {
40
59
  const doc = (0, import_dom_query.getDocument)(node);
41
60
  const cleanups = [];
42
- if (import_layer_stack.layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
43
- originalBodyPointerEvents = doc.body.style.pointerEvents;
44
- queueMicrotask(() => {
45
- const body = doc.body;
46
- if (!body) return;
47
- body.style.pointerEvents = "none";
48
- body.setAttribute("data-inert", "");
49
- });
50
- }
61
+ syncBodyPointerEvents(doc);
51
62
  persistentElements?.forEach((el) => {
52
63
  const [promise, abort] = (0, import_dom_query.waitForElement)(
53
64
  () => {
@@ -60,20 +71,12 @@ function disablePointerEventsOutside(node, persistentElements) {
60
71
  cleanups.push(abort);
61
72
  });
62
73
  return () => {
63
- if (import_layer_stack.layerStack.hasPointerBlockingLayer()) return;
64
- queueMicrotask(() => {
65
- const body = doc.body;
66
- if (!body) return;
67
- body.style.pointerEvents = originalBodyPointerEvents;
68
- body.removeAttribute("data-inert");
69
- if (body.style.length === 0) body.removeAttribute("style");
70
- });
74
+ syncBodyPointerEvents(doc);
71
75
  cleanups.forEach((fn) => fn());
72
76
  };
73
77
  }
74
78
  // Annotate the CommonJS export names for ESM import in node:
75
79
  0 && (module.exports = {
76
- assignPointerEventToLayers,
77
- clearPointerEvent,
78
- disablePointerEventsOutside
80
+ disablePointerEventsOutside,
81
+ syncPointerEvents
79
82
  });
@@ -1,27 +1,39 @@
1
1
  // src/pointer-event-outside.ts
2
2
  import { getDocument, isHTMLElement, setStyle, waitForElement } from "@zag-js/dom-query";
3
3
  import { layerStack } from "./layer-stack.mjs";
4
- var originalBodyPointerEvents;
5
- function assignPointerEventToLayers() {
6
- layerStack.layers.forEach(({ node }) => {
7
- node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto";
4
+ var originalBodyPointerEvents = /* @__PURE__ */ new WeakMap();
5
+ function syncBodyPointerEvents(doc) {
6
+ const body = doc.body;
7
+ if (!body) return;
8
+ const shouldBlock = layerStack.hasPointerBlockingLayer();
9
+ if (shouldBlock === body.hasAttribute("data-inert")) return;
10
+ if (shouldBlock) {
11
+ originalBodyPointerEvents.set(body, body.style.pointerEvents);
12
+ queueMicrotask(() => {
13
+ if (!layerStack.hasPointerBlockingLayer()) return;
14
+ body.style.pointerEvents = "none";
15
+ body.setAttribute("data-inert", "");
16
+ });
17
+ return;
18
+ }
19
+ queueMicrotask(() => {
20
+ if (layerStack.hasPointerBlockingLayer()) return;
21
+ const original = originalBodyPointerEvents.get(body);
22
+ if (original !== void 0) {
23
+ body.style.pointerEvents = original;
24
+ originalBodyPointerEvents.delete(body);
25
+ }
26
+ body.removeAttribute("data-inert");
27
+ if (body.style.length === 0) body.removeAttribute("style");
8
28
  });
9
29
  }
10
- function clearPointerEvent(node) {
11
- node.style.pointerEvents = "";
30
+ function syncPointerEvents(node) {
31
+ syncBodyPointerEvents(getDocument(node));
12
32
  }
13
33
  function disablePointerEventsOutside(node, persistentElements) {
14
34
  const doc = getDocument(node);
15
35
  const cleanups = [];
16
- if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
17
- originalBodyPointerEvents = doc.body.style.pointerEvents;
18
- queueMicrotask(() => {
19
- const body = doc.body;
20
- if (!body) return;
21
- body.style.pointerEvents = "none";
22
- body.setAttribute("data-inert", "");
23
- });
24
- }
36
+ syncBodyPointerEvents(doc);
25
37
  persistentElements?.forEach((el) => {
26
38
  const [promise, abort] = waitForElement(
27
39
  () => {
@@ -34,19 +46,11 @@ function disablePointerEventsOutside(node, persistentElements) {
34
46
  cleanups.push(abort);
35
47
  });
36
48
  return () => {
37
- if (layerStack.hasPointerBlockingLayer()) return;
38
- queueMicrotask(() => {
39
- const body = doc.body;
40
- if (!body) return;
41
- body.style.pointerEvents = originalBodyPointerEvents;
42
- body.removeAttribute("data-inert");
43
- if (body.style.length === 0) body.removeAttribute("style");
44
- });
49
+ syncBodyPointerEvents(doc);
45
50
  cleanups.forEach((fn) => fn());
46
51
  };
47
52
  }
48
53
  export {
49
- assignPointerEventToLayers,
50
- clearPointerEvent,
51
- disablePointerEventsOutside
54
+ disablePointerEventsOutside,
55
+ syncPointerEvents
52
56
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/dismissable",
3
- "version": "2.0.0-next.0",
3
+ "version": "2.0.0-next.2",
4
4
  "description": "Dismissable layer utilities for the DOM",
5
5
  "keywords": [
6
6
  "js",
@@ -14,7 +14,10 @@
14
14
  "author": "Segun Adebayo <sage@adebayosegun.com>",
15
15
  "homepage": "https://github.com/chakra-ui/zag#readme",
16
16
  "license": "MIT",
17
- "repository": "https://github.com/chakra-ui/zag/tree/main/packages/utilities/interact-outside",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/chakra-ui/zag/tree/main/packages/utilities/interact-outside"
20
+ },
18
21
  "sideEffects": false,
19
22
  "files": [
20
23
  "dist"
@@ -23,9 +26,9 @@
23
26
  "access": "public"
24
27
  },
25
28
  "dependencies": {
26
- "@zag-js/interact-outside": "2.0.0-next.0",
27
- "@zag-js/dom-query": "2.0.0-next.0",
28
- "@zag-js/utils": "2.0.0-next.0"
29
+ "@zag-js/interact-outside": "2.0.0-next.2",
30
+ "@zag-js/utils": "2.0.0-next.2",
31
+ "@zag-js/dom-query": "2.0.0-next.2"
29
32
  },
30
33
  "devDependencies": {
31
34
  "clean-package": "2.2.0"
@@ -53,7 +56,7 @@
53
56
  "scripts": {
54
57
  "build": "tsup",
55
58
  "test": "vitest",
56
- "lint": "eslint src",
59
+ "lint": "oxlint src",
57
60
  "test-ci": "pnpm test --ci --runInBand -u",
58
61
  "test-watch": "pnpm test --watchAll"
59
62
  }