@zag-js/popover 0.7.0 → 0.9.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.
@@ -29,7 +29,6 @@ function machine(userContext) {
29
29
  },
30
30
  currentPlacement: void 0,
31
31
  ...ctx,
32
- focusTriggerOnClose: true,
33
32
  renderedElements: {
34
33
  title: true,
35
34
  description: true
@@ -44,10 +43,15 @@ function machine(userContext) {
44
43
  entry: ["checkRenderedElements"],
45
44
  states: {
46
45
  closed: {
47
- entry: "invokeOnClose",
48
46
  on: {
49
- TOGGLE: "open",
50
- OPEN: "open"
47
+ TOGGLE: {
48
+ target: "open",
49
+ actions: ["invokeOnOpen"]
50
+ },
51
+ OPEN: {
52
+ target: "open",
53
+ actions: ["invokeOnOpen"]
54
+ }
51
55
  }
52
56
  },
53
57
  open: {
@@ -59,14 +63,20 @@ function machine(userContext) {
59
63
  "trackDismissableElement",
60
64
  "proxyTabFocus"
61
65
  ],
62
- entry: ["setInitialFocus", "invokeOnOpen"],
66
+ entry: ["setInitialFocus"],
63
67
  on: {
64
- CLOSE: "closed",
68
+ CLOSE: {
69
+ target: "closed",
70
+ actions: ["invokeOnClose"]
71
+ },
65
72
  REQUEST_CLOSE: {
66
73
  target: "closed",
67
- actions: "focusTriggerIfNeeded"
74
+ actions: ["restoreFocusIfNeeded", "invokeOnClose"]
75
+ },
76
+ TOGGLE: {
77
+ target: "closed",
78
+ actions: ["invokeOnClose"]
68
79
  },
69
- TOGGLE: "closed",
70
80
  SET_POSITIONING: {
71
81
  actions: "setPositioning"
72
82
  }
@@ -79,8 +89,10 @@ function machine(userContext) {
79
89
  trackPositioning(ctx2) {
80
90
  ctx2.currentPlacement = ctx2.positioning.placement;
81
91
  const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
82
- return getPlacement(anchorEl, dom.getPositionerEl(ctx2), {
92
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
93
+ return getPlacement(anchorEl, getPositionerEl, {
83
94
  ...ctx2.positioning,
95
+ defer: true,
84
96
  onComplete(data) {
85
97
  ctx2.currentPlacement = data.placement;
86
98
  },
@@ -90,21 +102,23 @@ function machine(userContext) {
90
102
  });
91
103
  },
92
104
  trackDismissableElement(ctx2, _evt, { send }) {
93
- return trackDismissableElement(dom.getContentEl(ctx2), {
105
+ const getContentEl = () => dom.getContentEl(ctx2);
106
+ let restoreFocus = true;
107
+ return trackDismissableElement(getContentEl, {
94
108
  pointerBlocking: ctx2.modal,
95
109
  exclude: dom.getTriggerEl(ctx2),
110
+ defer: true,
96
111
  onEscapeKeyDown(event) {
97
112
  ctx2.onEscapeKeyDown?.(event);
98
113
  if (ctx2.closeOnEsc)
99
114
  return;
100
- ctx2.focusTriggerOnClose = true;
101
115
  event.preventDefault();
102
116
  },
103
117
  onInteractOutside(event) {
104
118
  ctx2.onInteractOutside?.(event);
105
119
  if (event.defaultPrevented)
106
120
  return;
107
- ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
121
+ restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
108
122
  if (!ctx2.closeOnInteractOutside) {
109
123
  event.preventDefault();
110
124
  }
@@ -116,25 +130,27 @@ function machine(userContext) {
116
130
  ctx2.onFocusOutside?.(event);
117
131
  },
118
132
  onDismiss() {
119
- send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
133
+ send({ type: "REQUEST_CLOSE", src: "interact-outside", restoreFocus });
120
134
  }
121
135
  });
122
136
  },
123
137
  proxyTabFocus(ctx2) {
124
138
  if (ctx2.modal || !ctx2.portalled)
125
139
  return;
126
- return proxyTabFocus(dom.getContentEl(ctx2), dom.getTriggerEl(ctx2), (el) => {
127
- el.focus({ preventScroll: true });
140
+ const getContentEl = () => dom.getContentEl(ctx2);
141
+ return proxyTabFocus(getContentEl, {
142
+ triggerElement: dom.getTriggerEl(ctx2),
143
+ defer: true,
144
+ onFocus(el) {
145
+ el.focus({ preventScroll: true });
146
+ }
128
147
  });
129
148
  },
130
149
  hideContentBelow(ctx2) {
131
150
  if (!ctx2.modal)
132
151
  return;
133
- let cleanup;
134
- nextTick(() => {
135
- cleanup = ariaHidden([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
136
- });
137
- return () => cleanup?.();
152
+ const getElements = () => [dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)];
153
+ return ariaHidden(getElements, { defer: true });
138
154
  },
139
155
  preventScroll(ctx2) {
140
156
  if (!ctx2.modal)
@@ -167,13 +183,13 @@ function machine(userContext) {
167
183
  },
168
184
  actions: {
169
185
  setPositioning(ctx2, evt) {
170
- raf(() => {
171
- const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
172
- getPlacement(anchorEl, dom.getPositionerEl(ctx2), {
173
- ...ctx2.positioning,
174
- ...evt.options,
175
- listeners: false
176
- });
186
+ const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
187
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
188
+ getPlacement(anchorEl, getPositionerEl, {
189
+ ...ctx2.positioning,
190
+ ...evt.options,
191
+ defer: true,
192
+ listeners: false
177
193
  });
178
194
  },
179
195
  checkRenderedElements(ctx2) {
@@ -189,10 +205,12 @@ function machine(userContext) {
189
205
  dom.getInitialFocusEl(ctx2)?.focus();
190
206
  });
191
207
  },
192
- focusTriggerIfNeeded(ctx2) {
193
- if (!ctx2.focusTriggerOnClose)
208
+ restoreFocusIfNeeded(ctx2, evt) {
209
+ if (!evt.restoreFocus)
194
210
  return;
195
- raf(() => dom.getTriggerEl(ctx2)?.focus());
211
+ raf(() => {
212
+ dom.getTriggerEl(ctx2)?.focus();
213
+ });
196
214
  },
197
215
  invokeOnOpen(ctx2) {
198
216
  ctx2.onOpen?.();
package/dist/index.js CHANGED
@@ -209,7 +209,6 @@ function machine(userContext) {
209
209
  },
210
210
  currentPlacement: void 0,
211
211
  ...ctx,
212
- focusTriggerOnClose: true,
213
212
  renderedElements: {
214
213
  title: true,
215
214
  description: true
@@ -224,10 +223,15 @@ function machine(userContext) {
224
223
  entry: ["checkRenderedElements"],
225
224
  states: {
226
225
  closed: {
227
- entry: "invokeOnClose",
228
226
  on: {
229
- TOGGLE: "open",
230
- OPEN: "open"
227
+ TOGGLE: {
228
+ target: "open",
229
+ actions: ["invokeOnOpen"]
230
+ },
231
+ OPEN: {
232
+ target: "open",
233
+ actions: ["invokeOnOpen"]
234
+ }
231
235
  }
232
236
  },
233
237
  open: {
@@ -239,14 +243,20 @@ function machine(userContext) {
239
243
  "trackDismissableElement",
240
244
  "proxyTabFocus"
241
245
  ],
242
- entry: ["setInitialFocus", "invokeOnOpen"],
246
+ entry: ["setInitialFocus"],
243
247
  on: {
244
- CLOSE: "closed",
248
+ CLOSE: {
249
+ target: "closed",
250
+ actions: ["invokeOnClose"]
251
+ },
245
252
  REQUEST_CLOSE: {
246
253
  target: "closed",
247
- actions: "focusTriggerIfNeeded"
254
+ actions: ["restoreFocusIfNeeded", "invokeOnClose"]
255
+ },
256
+ TOGGLE: {
257
+ target: "closed",
258
+ actions: ["invokeOnClose"]
248
259
  },
249
- TOGGLE: "closed",
250
260
  SET_POSITIONING: {
251
261
  actions: "setPositioning"
252
262
  }
@@ -259,8 +269,10 @@ function machine(userContext) {
259
269
  trackPositioning(ctx2) {
260
270
  ctx2.currentPlacement = ctx2.positioning.placement;
261
271
  const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
262
- return (0, import_popper2.getPlacement)(anchorEl, dom.getPositionerEl(ctx2), {
272
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
273
+ return (0, import_popper2.getPlacement)(anchorEl, getPositionerEl, {
263
274
  ...ctx2.positioning,
275
+ defer: true,
264
276
  onComplete(data) {
265
277
  ctx2.currentPlacement = data.placement;
266
278
  },
@@ -270,21 +282,23 @@ function machine(userContext) {
270
282
  });
271
283
  },
272
284
  trackDismissableElement(ctx2, _evt, { send }) {
273
- return (0, import_dismissable.trackDismissableElement)(dom.getContentEl(ctx2), {
285
+ const getContentEl = () => dom.getContentEl(ctx2);
286
+ let restoreFocus = true;
287
+ return (0, import_dismissable.trackDismissableElement)(getContentEl, {
274
288
  pointerBlocking: ctx2.modal,
275
289
  exclude: dom.getTriggerEl(ctx2),
290
+ defer: true,
276
291
  onEscapeKeyDown(event) {
277
292
  ctx2.onEscapeKeyDown?.(event);
278
293
  if (ctx2.closeOnEsc)
279
294
  return;
280
- ctx2.focusTriggerOnClose = true;
281
295
  event.preventDefault();
282
296
  },
283
297
  onInteractOutside(event) {
284
298
  ctx2.onInteractOutside?.(event);
285
299
  if (event.defaultPrevented)
286
300
  return;
287
- ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
301
+ restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
288
302
  if (!ctx2.closeOnInteractOutside) {
289
303
  event.preventDefault();
290
304
  }
@@ -296,25 +310,27 @@ function machine(userContext) {
296
310
  ctx2.onFocusOutside?.(event);
297
311
  },
298
312
  onDismiss() {
299
- send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
313
+ send({ type: "REQUEST_CLOSE", src: "interact-outside", restoreFocus });
300
314
  }
301
315
  });
302
316
  },
303
317
  proxyTabFocus(ctx2) {
304
318
  if (ctx2.modal || !ctx2.portalled)
305
319
  return;
306
- return (0, import_tabbable2.proxyTabFocus)(dom.getContentEl(ctx2), dom.getTriggerEl(ctx2), (el) => {
307
- el.focus({ preventScroll: true });
320
+ const getContentEl = () => dom.getContentEl(ctx2);
321
+ return (0, import_tabbable2.proxyTabFocus)(getContentEl, {
322
+ triggerElement: dom.getTriggerEl(ctx2),
323
+ defer: true,
324
+ onFocus(el) {
325
+ el.focus({ preventScroll: true });
326
+ }
308
327
  });
309
328
  },
310
329
  hideContentBelow(ctx2) {
311
330
  if (!ctx2.modal)
312
331
  return;
313
- let cleanup;
314
- (0, import_dom_query3.nextTick)(() => {
315
- cleanup = (0, import_aria_hidden.ariaHidden)([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
316
- });
317
- return () => cleanup?.();
332
+ const getElements = () => [dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)];
333
+ return (0, import_aria_hidden.ariaHidden)(getElements, { defer: true });
318
334
  },
319
335
  preventScroll(ctx2) {
320
336
  if (!ctx2.modal)
@@ -347,13 +363,13 @@ function machine(userContext) {
347
363
  },
348
364
  actions: {
349
365
  setPositioning(ctx2, evt) {
350
- (0, import_dom_query3.raf)(() => {
351
- const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
352
- (0, import_popper2.getPlacement)(anchorEl, dom.getPositionerEl(ctx2), {
353
- ...ctx2.positioning,
354
- ...evt.options,
355
- listeners: false
356
- });
366
+ const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
367
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
368
+ (0, import_popper2.getPlacement)(anchorEl, getPositionerEl, {
369
+ ...ctx2.positioning,
370
+ ...evt.options,
371
+ defer: true,
372
+ listeners: false
357
373
  });
358
374
  },
359
375
  checkRenderedElements(ctx2) {
@@ -369,10 +385,12 @@ function machine(userContext) {
369
385
  dom.getInitialFocusEl(ctx2)?.focus();
370
386
  });
371
387
  },
372
- focusTriggerIfNeeded(ctx2) {
373
- if (!ctx2.focusTriggerOnClose)
388
+ restoreFocusIfNeeded(ctx2, evt) {
389
+ if (!evt.restoreFocus)
374
390
  return;
375
- (0, import_dom_query3.raf)(() => dom.getTriggerEl(ctx2)?.focus());
391
+ (0, import_dom_query3.raf)(() => {
392
+ dom.getTriggerEl(ctx2)?.focus();
393
+ });
376
394
  },
377
395
  invokeOnOpen(ctx2) {
378
396
  ctx2.onOpen?.();
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-KTOPDXGV.mjs";
7
7
  import {
8
8
  machine
9
- } from "./chunk-HXXI3VDD.mjs";
9
+ } from "./chunk-KWS6ZCAX.mjs";
10
10
  import "./chunk-UA4OMIJI.mjs";
11
11
  export {
12
12
  anatomy,
@@ -87,7 +87,6 @@ function machine(userContext) {
87
87
  },
88
88
  currentPlacement: void 0,
89
89
  ...ctx,
90
- focusTriggerOnClose: true,
91
90
  renderedElements: {
92
91
  title: true,
93
92
  description: true
@@ -102,10 +101,15 @@ function machine(userContext) {
102
101
  entry: ["checkRenderedElements"],
103
102
  states: {
104
103
  closed: {
105
- entry: "invokeOnClose",
106
104
  on: {
107
- TOGGLE: "open",
108
- OPEN: "open"
105
+ TOGGLE: {
106
+ target: "open",
107
+ actions: ["invokeOnOpen"]
108
+ },
109
+ OPEN: {
110
+ target: "open",
111
+ actions: ["invokeOnOpen"]
112
+ }
109
113
  }
110
114
  },
111
115
  open: {
@@ -117,14 +121,20 @@ function machine(userContext) {
117
121
  "trackDismissableElement",
118
122
  "proxyTabFocus"
119
123
  ],
120
- entry: ["setInitialFocus", "invokeOnOpen"],
124
+ entry: ["setInitialFocus"],
121
125
  on: {
122
- CLOSE: "closed",
126
+ CLOSE: {
127
+ target: "closed",
128
+ actions: ["invokeOnClose"]
129
+ },
123
130
  REQUEST_CLOSE: {
124
131
  target: "closed",
125
- actions: "focusTriggerIfNeeded"
132
+ actions: ["restoreFocusIfNeeded", "invokeOnClose"]
133
+ },
134
+ TOGGLE: {
135
+ target: "closed",
136
+ actions: ["invokeOnClose"]
126
137
  },
127
- TOGGLE: "closed",
128
138
  SET_POSITIONING: {
129
139
  actions: "setPositioning"
130
140
  }
@@ -137,8 +147,10 @@ function machine(userContext) {
137
147
  trackPositioning(ctx2) {
138
148
  ctx2.currentPlacement = ctx2.positioning.placement;
139
149
  const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
140
- return (0, import_popper.getPlacement)(anchorEl, dom.getPositionerEl(ctx2), {
150
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
151
+ return (0, import_popper.getPlacement)(anchorEl, getPositionerEl, {
141
152
  ...ctx2.positioning,
153
+ defer: true,
142
154
  onComplete(data) {
143
155
  ctx2.currentPlacement = data.placement;
144
156
  },
@@ -148,21 +160,23 @@ function machine(userContext) {
148
160
  });
149
161
  },
150
162
  trackDismissableElement(ctx2, _evt, { send }) {
151
- return (0, import_dismissable.trackDismissableElement)(dom.getContentEl(ctx2), {
163
+ const getContentEl = () => dom.getContentEl(ctx2);
164
+ let restoreFocus = true;
165
+ return (0, import_dismissable.trackDismissableElement)(getContentEl, {
152
166
  pointerBlocking: ctx2.modal,
153
167
  exclude: dom.getTriggerEl(ctx2),
168
+ defer: true,
154
169
  onEscapeKeyDown(event) {
155
170
  ctx2.onEscapeKeyDown?.(event);
156
171
  if (ctx2.closeOnEsc)
157
172
  return;
158
- ctx2.focusTriggerOnClose = true;
159
173
  event.preventDefault();
160
174
  },
161
175
  onInteractOutside(event) {
162
176
  ctx2.onInteractOutside?.(event);
163
177
  if (event.defaultPrevented)
164
178
  return;
165
- ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
179
+ restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
166
180
  if (!ctx2.closeOnInteractOutside) {
167
181
  event.preventDefault();
168
182
  }
@@ -174,25 +188,27 @@ function machine(userContext) {
174
188
  ctx2.onFocusOutside?.(event);
175
189
  },
176
190
  onDismiss() {
177
- send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
191
+ send({ type: "REQUEST_CLOSE", src: "interact-outside", restoreFocus });
178
192
  }
179
193
  });
180
194
  },
181
195
  proxyTabFocus(ctx2) {
182
196
  if (ctx2.modal || !ctx2.portalled)
183
197
  return;
184
- return (0, import_tabbable2.proxyTabFocus)(dom.getContentEl(ctx2), dom.getTriggerEl(ctx2), (el) => {
185
- el.focus({ preventScroll: true });
198
+ const getContentEl = () => dom.getContentEl(ctx2);
199
+ return (0, import_tabbable2.proxyTabFocus)(getContentEl, {
200
+ triggerElement: dom.getTriggerEl(ctx2),
201
+ defer: true,
202
+ onFocus(el) {
203
+ el.focus({ preventScroll: true });
204
+ }
186
205
  });
187
206
  },
188
207
  hideContentBelow(ctx2) {
189
208
  if (!ctx2.modal)
190
209
  return;
191
- let cleanup;
192
- (0, import_dom_query2.nextTick)(() => {
193
- cleanup = (0, import_aria_hidden.ariaHidden)([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
194
- });
195
- return () => cleanup?.();
210
+ const getElements = () => [dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)];
211
+ return (0, import_aria_hidden.ariaHidden)(getElements, { defer: true });
196
212
  },
197
213
  preventScroll(ctx2) {
198
214
  if (!ctx2.modal)
@@ -225,13 +241,13 @@ function machine(userContext) {
225
241
  },
226
242
  actions: {
227
243
  setPositioning(ctx2, evt) {
228
- (0, import_dom_query2.raf)(() => {
229
- const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
230
- (0, import_popper.getPlacement)(anchorEl, dom.getPositionerEl(ctx2), {
231
- ...ctx2.positioning,
232
- ...evt.options,
233
- listeners: false
234
- });
244
+ const anchorEl = dom.getAnchorEl(ctx2) ?? dom.getTriggerEl(ctx2);
245
+ const getPositionerEl = () => dom.getPositionerEl(ctx2);
246
+ (0, import_popper.getPlacement)(anchorEl, getPositionerEl, {
247
+ ...ctx2.positioning,
248
+ ...evt.options,
249
+ defer: true,
250
+ listeners: false
235
251
  });
236
252
  },
237
253
  checkRenderedElements(ctx2) {
@@ -247,10 +263,12 @@ function machine(userContext) {
247
263
  dom.getInitialFocusEl(ctx2)?.focus();
248
264
  });
249
265
  },
250
- focusTriggerIfNeeded(ctx2) {
251
- if (!ctx2.focusTriggerOnClose)
266
+ restoreFocusIfNeeded(ctx2, evt) {
267
+ if (!evt.restoreFocus)
252
268
  return;
253
- (0, import_dom_query2.raf)(() => dom.getTriggerEl(ctx2)?.focus());
269
+ (0, import_dom_query2.raf)(() => {
270
+ dom.getTriggerEl(ctx2)?.focus();
271
+ });
254
272
  },
255
273
  invokeOnOpen(ctx2) {
256
274
  ctx2.onOpen?.();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  machine
3
- } from "./chunk-HXXI3VDD.mjs";
3
+ } from "./chunk-KWS6ZCAX.mjs";
4
4
  import "./chunk-UA4OMIJI.mjs";
5
5
  export {
6
6
  machine
@@ -74,12 +74,7 @@ type ComputedContext = Readonly<{
74
74
  */
75
75
  currentPortalled: boolean;
76
76
  }>;
77
- type PrivateContext = Context<{
78
- /**
79
- * Whether to prevent returning focus to the trigger
80
- */
81
- focusTriggerOnClose?: boolean;
82
- }>;
77
+ type PrivateContext = Context<{}>;
83
78
  type MachineContext = PublicContext & ComputedContext & PrivateContext;
84
79
  type MachineState = {
85
80
  value: "open" | "closed";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/popover",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Core logic for the popover widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -26,15 +26,15 @@
26
26
  "url": "https://github.com/chakra-ui/zag/issues"
27
27
  },
28
28
  "dependencies": {
29
- "focus-trap": "7.4.0",
30
- "@zag-js/anatomy": "0.1.4",
31
- "@zag-js/aria-hidden": "0.2.2",
29
+ "focus-trap": "7.4.1",
30
+ "@zag-js/anatomy": "0.9.0",
31
+ "@zag-js/aria-hidden": "0.8.0",
32
32
  "@zag-js/core": "0.7.0",
33
33
  "@zag-js/dom-query": "0.1.4",
34
34
  "@zag-js/utils": "0.3.4",
35
- "@zag-js/dismissable": "0.6.0",
36
- "@zag-js/tabbable": "0.1.1",
37
- "@zag-js/popper": "0.2.7",
35
+ "@zag-js/dismissable": "0.8.0",
36
+ "@zag-js/tabbable": "0.8.0",
37
+ "@zag-js/popper": "0.8.0",
38
38
  "@zag-js/remove-scroll": "0.2.4",
39
39
  "@zag-js/types": "0.5.0"
40
40
  },