@zag-js/popover 0.1.6 → 0.1.9

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.mjs CHANGED
@@ -18,307 +18,30 @@ var __spreadValues = (a, b) => {
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
 
21
- // ../../../node_modules/compute-scroll-into-view/dist/index.module.js
22
- function t(t3) {
23
- return typeof t3 == "object" && t3 != null && t3.nodeType === 1;
24
- }
25
- function e(t3, e2) {
26
- return (!e2 || t3 !== "hidden") && t3 !== "visible" && t3 !== "clip";
27
- }
28
- function n(t3, n2) {
29
- if (t3.clientHeight < t3.scrollHeight || t3.clientWidth < t3.scrollWidth) {
30
- var r2 = getComputedStyle(t3, null);
31
- return e(r2.overflowY, n2) || e(r2.overflowX, n2) || function(t4) {
32
- var e2 = function(t5) {
33
- if (!t5.ownerDocument || !t5.ownerDocument.defaultView)
34
- return null;
35
- try {
36
- return t5.ownerDocument.defaultView.frameElement;
37
- } catch (t6) {
38
- return null;
39
- }
40
- }(t4);
41
- return !!e2 && (e2.clientHeight < t4.scrollHeight || e2.clientWidth < t4.scrollWidth);
42
- }(t3);
43
- }
44
- return false;
45
- }
46
- function r(t3, e2, n2, r2, i, o, l, d) {
47
- return o < t3 && l > e2 || o > t3 && l < e2 ? 0 : o <= t3 && d <= n2 || l >= e2 && d >= n2 ? o - t3 - r2 : l > e2 && d < n2 || o < t3 && d > n2 ? l - e2 + i : 0;
48
- }
49
- function index_module_default(e2, i) {
50
- var o = window, l = i.scrollMode, d = i.block, u = i.inline, h = i.boundary, a = i.skipOverflowHiddenElements, c = typeof h == "function" ? h : function(t3) {
51
- return t3 !== h;
52
- };
53
- if (!t(e2))
54
- throw new TypeError("Invalid target");
55
- for (var f = document.scrollingElement || document.documentElement, s = [], p = e2; t(p) && c(p); ) {
56
- if ((p = p.parentElement) === f) {
57
- s.push(p);
58
- break;
59
- }
60
- p != null && p === document.body && n(p) && !n(document.documentElement) || p != null && n(p, a) && s.push(p);
61
- }
62
- for (var m = o.visualViewport ? o.visualViewport.width : innerWidth, g = o.visualViewport ? o.visualViewport.height : innerHeight, w = window.scrollX || pageXOffset, v = window.scrollY || pageYOffset, W = e2.getBoundingClientRect(), b = W.height, H = W.width, y = W.top, E = W.right, M = W.bottom, V = W.left, x = d === "start" || d === "nearest" ? y : d === "end" ? M : y + b / 2, I = u === "center" ? V + H / 2 : u === "end" ? E : V, C = [], T = 0; T < s.length; T++) {
63
- var k = s[T], B = k.getBoundingClientRect(), D = B.height, O = B.width, R = B.top, X = B.right, Y = B.bottom, L = B.left;
64
- if (l === "if-needed" && y >= 0 && V >= 0 && M <= g && E <= m && y >= R && M <= Y && V >= L && E <= X)
65
- return C;
66
- var S = getComputedStyle(k), j = parseInt(S.borderLeftWidth, 10), q = parseInt(S.borderTopWidth, 10), z = parseInt(S.borderRightWidth, 10), A = parseInt(S.borderBottomWidth, 10), F = 0, G = 0, J = "offsetWidth" in k ? k.offsetWidth - k.clientWidth - j - z : 0, K = "offsetHeight" in k ? k.offsetHeight - k.clientHeight - q - A : 0;
67
- if (f === k)
68
- F = d === "start" ? x : d === "end" ? x - g : d === "nearest" ? r(v, v + g, g, q, A, v + x, v + x + b, b) : x - g / 2, G = u === "start" ? I : u === "center" ? I - m / 2 : u === "end" ? I - m : r(w, w + m, m, j, z, w + I, w + I + H, H), F = Math.max(0, F + v), G = Math.max(0, G + w);
69
- else {
70
- F = d === "start" ? x - R - q : d === "end" ? x - Y + A + K : d === "nearest" ? r(R, Y, D, q, A + K, x, x + b, b) : x - (R + D / 2) + K / 2, G = u === "start" ? I - L - j : u === "center" ? I - (L + O / 2) + J / 2 : u === "end" ? I - X + z + J : r(L, X, O, j, z + J, I, I + H, H);
71
- var N = k.scrollLeft, P = k.scrollTop;
72
- x += P - (F = Math.max(0, Math.min(P + F, k.scrollHeight - D + K))), I += N - (G = Math.max(0, Math.min(N + G, k.scrollWidth - O + J)));
73
- }
74
- C.push({ el: k, top: F, left: G });
75
- }
76
- return C;
77
- }
78
-
79
- // ../../utilities/dom/node_modules/scroll-into-view-if-needed/es/index.js
80
- function isOptionsObject(options) {
81
- return options === Object(options) && Object.keys(options).length !== 0;
82
- }
83
- function defaultBehavior(actions, behavior) {
84
- if (behavior === void 0) {
85
- behavior = "auto";
86
- }
87
- var canSmoothScroll = "scrollBehavior" in document.body.style;
88
- actions.forEach(function(_ref) {
89
- var el = _ref.el, top = _ref.top, left = _ref.left;
90
- if (el.scroll && canSmoothScroll) {
91
- el.scroll({
92
- top,
93
- left,
94
- behavior
95
- });
96
- } else {
97
- el.scrollTop = top;
98
- el.scrollLeft = left;
99
- }
100
- });
101
- }
102
- function getOptions(options) {
103
- if (options === false) {
104
- return {
105
- block: "end",
106
- inline: "nearest"
107
- };
108
- }
109
- if (isOptionsObject(options)) {
110
- return options;
111
- }
112
- return {
113
- block: "start",
114
- inline: "nearest"
115
- };
116
- }
117
- function scrollIntoView(target, options) {
118
- var isTargetAttached = target.isConnected || target.ownerDocument.documentElement.contains(target);
119
- if (isOptionsObject(options) && typeof options.behavior === "function") {
120
- return options.behavior(isTargetAttached ? index_module_default(target, options) : []);
121
- }
122
- if (!isTargetAttached) {
123
- return;
124
- }
125
- var computeOptions = getOptions(options);
126
- return defaultBehavior(index_module_default(target, computeOptions), computeOptions.behavior);
127
- }
128
- var es_default = scrollIntoView;
129
-
130
21
  // ../../utilities/dom/dist/index.mjs
131
22
  var dataAttr = (guard) => {
132
23
  return guard ? "" : void 0;
133
24
  };
134
- function getStyleCache() {
135
- ;
136
- globalThis.__styleCache__ = globalThis.__styleCache__ || /* @__PURE__ */ new WeakMap();
137
- return globalThis.__styleCache__;
138
- }
139
- function getComputedStyle2(el) {
140
- var _a;
141
- if (!el)
142
- return {};
143
- const cache = getStyleCache();
144
- let style = cache.get(el);
145
- if (!style) {
146
- const win = (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
147
- style = win.getComputedStyle(el);
148
- cache.set(el, style);
149
- }
150
- return style;
151
- }
152
- function nextTick(fn) {
153
- const set = /* @__PURE__ */ new Set();
154
- function raf2(fn2) {
155
- const id = globalThis.requestAnimationFrame(fn2);
156
- set.add(() => globalThis.cancelAnimationFrame(id));
157
- }
158
- raf2(() => raf2(fn));
159
- return function cleanup() {
160
- set.forEach(function(fn2) {
161
- fn2();
162
- });
163
- };
164
- }
165
- function raf(fn) {
166
- const id = globalThis.requestAnimationFrame(fn);
167
- return function cleanup() {
168
- globalThis.cancelAnimationFrame(id);
169
- };
170
- }
171
- var noop = () => {
25
+ var runIfFn = (v, ...a) => {
26
+ const res = typeof v === "function" ? v(...a) : v;
27
+ return res != null ? res : void 0;
172
28
  };
173
- var pipe = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
174
- var platform = (v) => isDom() && v.test(navigator.platform);
175
- var isDom = () => !!(typeof window !== "undefined");
176
- var isMac = () => platform(/^Mac/);
177
- var isIPhone = () => platform(/^iPhone/);
178
- var isIPad = () => platform(/^iPad/) || isMac() && navigator.maxTouchPoints > 1;
179
- var isIos = () => isIPhone() || isIPad();
180
- var isLeftClick = (v) => v.button === 0;
181
- function getListenerElements() {
182
- ;
183
- globalThis.__listenerElements__ = globalThis.__listenerElements__ || /* @__PURE__ */ new Map();
184
- return globalThis.__listenerElements__;
185
- }
186
- function getListenerCache() {
187
- ;
188
- globalThis.__listenerCache__ = globalThis.__listenerCache__ || /* @__PURE__ */ new Map();
189
- return globalThis.__listenerCache__;
190
- }
191
- function globalEventBus(node, type, handler, options) {
192
- var _a;
193
- if (!node)
194
- return noop;
195
- const hash = JSON.stringify({ type, options });
196
- const listenerElements = getListenerElements();
197
- const listenerCache = getListenerCache();
198
- const group = listenerElements.get(node);
199
- if (!listenerElements.has(node)) {
200
- const group2 = /* @__PURE__ */ new Map([[hash, /* @__PURE__ */ new Set([handler])]]);
201
- listenerElements.set(node, group2);
202
- } else if (group == null ? void 0 : group.has(hash)) {
203
- (_a = group == null ? void 0 : group.get(hash)) == null ? void 0 : _a.add(handler);
204
- } else {
205
- group == null ? void 0 : group.set(hash, /* @__PURE__ */ new Set([handler]));
206
- }
207
- function attach(node2) {
208
- var _a2, _b;
209
- function listener(event) {
210
- var _a3;
211
- const group2 = listenerElements.get(node2);
212
- (_a3 = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _a3.forEach((fn) => fn(event));
213
- }
214
- if (!(listenerCache == null ? void 0 : listenerCache.has(node2))) {
215
- listenerCache.set(node2, /* @__PURE__ */ new Map([[hash, listener]]));
216
- node2.addEventListener(type, listener, options);
217
- return;
218
- }
219
- if (!((_a2 = listenerCache == null ? void 0 : listenerCache.get(node2)) == null ? void 0 : _a2.has(hash))) {
220
- (_b = listenerCache.get(node2)) == null ? void 0 : _b.set(hash, listener);
221
- node2.addEventListener(type, listener, options);
222
- }
223
- }
224
- attach(node);
225
- return function remove() {
226
- var _a2, _b, _c, _d;
227
- if (!listenerElements.has(node))
228
- return;
229
- const group2 = listenerElements.get(node);
230
- (_a2 = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _a2.delete(handler);
231
- if (((_b = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _b.size) === 0) {
232
- const listener = (_c = listenerCache.get(node)) == null ? void 0 : _c.get(hash);
233
- node.removeEventListener(type, listener, options);
234
- group2 == null ? void 0 : group2.delete(hash);
235
- (_d = listenerCache.get(node)) == null ? void 0 : _d.delete(hash);
236
- if ((group2 == null ? void 0 : group2.size) === 0) {
237
- listenerElements.delete(node);
238
- listenerCache.delete(node);
239
- }
240
- }
241
- };
242
- }
243
- var t2 = (v) => Object.prototype.toString.call(v).slice(8, -1);
244
- var isRef = (v) => t2(v) === "Object" && "current" in v;
245
- var runIfFn = (fn) => t2(fn) === "Function" ? fn() : fn;
246
- function addDomEvent(target, event, listener, options) {
247
- const node = isRef(target) ? target.current : runIfFn(target);
248
- return globalEventBus(node, event, listener, options);
29
+ var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
30
+ function isWindow(value) {
31
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
249
32
  }
250
- var changeCount = 0;
251
- var originalBodyPointerEvents;
252
- function preventBodyPointerEvents(el, opts = {}) {
253
- const { disabled = false, document: docProp } = opts;
254
- const doc = docProp || document;
255
- let isTouchOrPenPressed = false;
256
- let isLeftClickPressed = false;
257
- function listen() {
258
- const onPointerDown = (event) => {
259
- const isMouse = event.pointerType === "mouse";
260
- isTouchOrPenPressed = !isMouse;
261
- isLeftClickPressed = isMouse && isLeftClick(event);
262
- };
263
- const onPointerUp = () => {
264
- isTouchOrPenPressed = false;
265
- isLeftClickPressed = false;
266
- };
267
- return pipe(addDomEvent(doc, "pointerdown", onPointerDown), addDomEvent(doc, "pointerup", onPointerUp));
268
- }
269
- function reset() {
270
- changeCount--;
271
- if (changeCount === 0) {
272
- doc.body.style.pointerEvents = originalBodyPointerEvents;
273
- }
274
- if (el) {
275
- el.style.pointerEvents = "";
276
- }
277
- }
278
- function apply() {
279
- if (disabled)
280
- return;
281
- if (changeCount === 0) {
282
- originalBodyPointerEvents = doc.body.style.pointerEvents;
283
- }
284
- doc.body.style.pointerEvents = "none";
285
- if (el) {
286
- el.style.pointerEvents = "auto";
287
- }
288
- changeCount++;
289
- return function() {
290
- if (isTouchOrPenPressed) {
291
- addDomEvent(doc, "click", reset, { once: true });
292
- } else if (isLeftClickPressed) {
293
- addDomEvent(doc, "pointerup", reset, { once: true });
294
- } else {
295
- reset();
296
- }
297
- };
298
- }
299
- const cleanups = [];
300
- cleanups.push(apply());
301
- nextTick(() => {
302
- cleanups.push(listen());
303
- });
304
- return function() {
305
- cleanups.forEach((cleanup) => cleanup == null ? void 0 : cleanup());
306
- };
33
+ function isFrame(element) {
34
+ return element.localName === "iframe";
307
35
  }
308
- function getOwnerDocument(el) {
36
+ function getDocument(el) {
309
37
  var _a;
310
38
  if (isWindow(el))
311
39
  return el.document;
312
40
  return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
313
41
  }
314
- function getNodeName(node) {
315
- return isWindow(node) ? "" : node ? node.localName || "" : "";
316
- }
317
- function getParent(el) {
318
- const doc = getOwnerDocument(el);
319
- if (getNodeName(el) === "html")
320
- return el;
321
- return el.assignedSlot || el.parentElement || doc.documentElement;
42
+ function getEventTarget(event) {
43
+ var _a, _b;
44
+ return (_b = (_a = event.composedPath) == null ? void 0 : _a.call(event)[0]) != null ? _b : event.target;
322
45
  }
323
46
  function contains(parent, child) {
324
47
  if (!parent)
@@ -328,259 +51,102 @@ function contains(parent, child) {
328
51
  function isHTMLElement(v) {
329
52
  return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
330
53
  }
331
- function isWindow(value) {
332
- return (value == null ? void 0 : value.toString()) === "[object Window]";
54
+ function isVisible(el) {
55
+ if (!isHTMLElement(el))
56
+ return false;
57
+ return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
333
58
  }
334
- var isDisabled = (el) => {
335
- return (el == null ? void 0 : el.getAttribute("disabled")) != null || !!(el == null ? void 0 : el.getAttribute("aria-disabled")) === true;
336
- };
337
- function isScrollParent(el) {
338
- const { overflow, overflowX, overflowY } = getComputedStyle2(el);
339
- return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
59
+ var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
60
+ function hasNegativeTabIndex(element) {
61
+ const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10);
62
+ return tabIndex < 0;
340
63
  }
341
- function getScrollParent(el) {
342
- if (["html", "body", "#document"].includes(getNodeName(el))) {
343
- return getOwnerDocument(el).body;
344
- }
345
- if (isHTMLElement(el) && isScrollParent(el)) {
346
- return el;
64
+ var focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type";
65
+ var getFocusables = (container, includeContainer = false) => {
66
+ if (!container)
67
+ return [];
68
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
69
+ const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0;
70
+ if (include && isHTMLElement(container) && isFocusable(container)) {
71
+ elements.unshift(container);
347
72
  }
348
- return getScrollParent(getParent(el));
73
+ const focusableElements = elements.filter(isFocusable);
74
+ focusableElements.forEach((element, i) => {
75
+ if (isFrame(element) && element.contentDocument) {
76
+ const frameBody = element.contentDocument.body;
77
+ focusableElements.splice(i, 1, ...getFocusables(frameBody));
78
+ }
79
+ });
80
+ return focusableElements;
81
+ };
82
+ function isFocusable(element) {
83
+ if (!element)
84
+ return false;
85
+ return element.matches(focusableSelector) && isVisible(element);
349
86
  }
350
- var nonTextInputTypes = /* @__PURE__ */ new Set(["checkbox", "radio", "range", "color", "file", "image", "button", "submit", "reset"]);
351
- function preventBodyScroll(opts) {
352
- var _a;
353
- const { document: docProp, disabled = false, allowPinchZoom } = opts != null ? opts : {};
354
- const doc = docProp != null ? docProp : document;
355
- const win = (_a = doc == null ? void 0 : doc.defaultView) != null ? _a : window;
356
- const viewport = isDom() ? win.visualViewport : null;
357
- const docEl = doc.documentElement;
358
- function preventScrollStandard() {
359
- if (docEl.hasAttribute("scroll-lock"))
360
- return;
361
- const fn = pipe(setStyle(docEl, "paddingRight", `${win.innerWidth - docEl.clientWidth}px`), setStyle(docEl, "overflow", "hidden"), () => docEl.setAttribute("scroll-lock", "true"));
362
- return pipe(fn, () => docEl.removeAttribute("scroll-lock"));
87
+ function getTabbables(container, includeContainer) {
88
+ if (!container)
89
+ return [];
90
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
91
+ const tabbableElements = elements.filter(isTabbable);
92
+ if (includeContainer && isTabbable(container)) {
93
+ tabbableElements.unshift(container);
363
94
  }
364
- function preventScrollMobileSafari() {
365
- if (docEl.hasAttribute("scroll-lock"))
366
- return;
367
- let scrollable;
368
- let lastY = 0;
369
- let onTouchStart = (e2) => {
370
- scrollable = getScrollParent(e2.target);
371
- if (scrollable === docEl && scrollable === doc.body) {
372
- return;
373
- }
374
- lastY = e2.changedTouches[0].pageY;
375
- };
376
- let onTouchMove = (e2) => {
377
- if (e2.touches.length === 2 && allowPinchZoom)
378
- return;
379
- if (!scrollable || scrollable === docEl || scrollable === doc.body) {
380
- e2.preventDefault();
381
- return;
382
- }
383
- let y = e2.changedTouches[0].pageY;
384
- let scrollTop = scrollable.scrollTop;
385
- let bottom = scrollable.scrollHeight - scrollable.clientHeight;
386
- if (scrollTop <= 0 && y > lastY || scrollTop >= bottom && y < lastY) {
387
- e2.preventDefault();
388
- }
389
- lastY = y;
390
- };
391
- let onTouchEnd = (e2) => {
392
- let target = e2.target;
393
- if (target instanceof win.HTMLInputElement && !nonTextInputTypes.has(target.type)) {
394
- e2.preventDefault();
395
- target.style.transform = "translateY(-2000px)";
396
- target.focus();
397
- win.requestAnimationFrame(() => {
398
- target.style.transform = "";
399
- });
400
- }
401
- };
402
- let onFocus = (e2) => {
403
- let target = e2.target;
404
- if (target instanceof win.HTMLInputElement && !nonTextInputTypes.has(target.type)) {
405
- target.style.transform = "translateY(-2000px)";
406
- win.requestAnimationFrame(() => {
407
- target.style.transform = "";
408
- if (!viewport)
409
- return;
410
- if (viewport.height < win.innerHeight) {
411
- win.requestAnimationFrame(function() {
412
- es_default(target, { scrollMode: "if-needed" });
413
- });
414
- } else {
415
- const onResize = () => {
416
- es_default(target, { scrollMode: "if-needed" });
417
- };
418
- addDomEvent(viewport, "resize", onResize, { once: true });
419
- }
420
- });
421
- }
422
- };
423
- let onWindowScroll = () => {
424
- win.scrollTo(0, 0);
425
- };
426
- let scrollX = win.scrollX;
427
- let scrollY = win.scrollY;
428
- let restoreStyles = pipe(setStyle(docEl, "paddingRight", `${win.innerWidth - docEl.clientWidth}px`), setStyle(docEl, "overflow", "hidden"), setStyle(doc.body, "marginTop", `-${scrollY}px`));
429
- win.scrollTo(0, 0);
430
- let removeEvents = pipe(addDomEvent(doc, "touchstart", onTouchStart, { passive: false, capture: true }), addDomEvent(doc, "touchmove", onTouchMove, { passive: false, capture: true }), addDomEvent(doc, "touchend", onTouchEnd, { passive: false, capture: true }), addDomEvent(doc, "focus", onFocus, true), addDomEvent(win, "scroll", onWindowScroll), () => docEl.setAttribute("scroll-lock", "true"));
431
- return () => {
432
- restoreStyles();
433
- removeEvents();
434
- win.scrollTo(scrollX, scrollY);
435
- docEl.removeAttribute("scroll-lock");
436
- };
95
+ tabbableElements.forEach((element, i) => {
96
+ if (isFrame(element) && element.contentDocument) {
97
+ const frameBody = element.contentDocument.body;
98
+ const allFrameTabbable = getTabbables(frameBody);
99
+ tabbableElements.splice(i, 1, ...allFrameTabbable);
100
+ }
101
+ });
102
+ if (!tabbableElements.length && includeContainer) {
103
+ return elements;
437
104
  }
438
- if (disabled)
439
- return noop;
440
- return isIos() ? preventScrollMobileSafari() : preventScrollStandard();
105
+ return tabbableElements;
441
106
  }
442
- function setStyle(el, key, value) {
443
- let cur = el.style[key];
444
- el.style[key] = value;
445
- return () => {
446
- el.style[key] = cur;
447
- };
107
+ function isTabbable(el) {
108
+ return isFocusable(el) && !hasNegativeTabIndex(el);
448
109
  }
449
- function validateBlur(event, opts) {
450
- var _a;
451
- const exclude = Array.isArray(opts.exclude) ? opts.exclude : [opts.exclude];
452
- const relatedTarget = (_a = event.relatedTarget) != null ? _a : opts.fallback;
453
- return exclude.every((el) => !(el == null ? void 0 : el.contains(relatedTarget)));
454
- }
455
- var focusableSelector = /* @__PURE__ */ [
456
- "input:not([disabled]):not([type=hidden])",
457
- "select:not([disabled])",
458
- "textarea:not([disabled])",
459
- "button:not([disabled])",
460
- "embed",
461
- "iframe",
462
- "object",
463
- "a[href]",
464
- "area[href]",
465
- "[tabindex]",
466
- "audio[controls]",
467
- "video[controls]",
468
- "*[tabindex]:not([aria-disabled])",
469
- "[contenteditable]:not([contenteditable=false])",
470
- "details > summary:first-of-type"
471
- ].join(",");
472
- function isHidden(el, until) {
473
- const style = getComputedStyle2(el);
474
- if (!el || style.getPropertyValue("visibility") === "hidden")
475
- return true;
476
- while (el) {
477
- if (until != null && el === until)
478
- return false;
479
- if (style.getPropertyValue("display") === "none")
480
- return true;
481
- el = el.parentElement;
482
- }
483
- return false;
110
+ function getFirstTabbable(container, includeContainer) {
111
+ const [first] = getTabbables(container, includeContainer);
112
+ return first || null;
484
113
  }
485
- var getFocusables = (el, includeContainer = false) => {
486
- if (!el)
487
- return [];
488
- let els = Array.from(el.querySelectorAll(focusableSelector));
489
- if (includeContainer && isHTMLElement(el)) {
490
- els.unshift(el);
491
- }
492
- return els.filter((el2) => isFocusable(el2) && !isHidden(el2));
493
- };
494
- var isFocusable = (el) => {
495
- if (!isHTMLElement(el) || isHidden(el) || isDisabled(el))
496
- return false;
497
- return el == null ? void 0 : el.matches(focusableSelector);
498
- };
499
- var getTabbables = (el, includeContainer = false) => {
500
- return getFocusables(el, includeContainer).filter(isTabbable);
501
- };
502
- var isTabbable = (el) => {
503
- return isFocusable(el) && !isDisabled(el) && !isHidden(el);
504
- };
505
- function itemById(v, id) {
506
- return v.find((node) => node.id === id);
114
+ function getLastTabbable(container, includeContainer) {
115
+ const elements = getTabbables(container, includeContainer);
116
+ return elements[elements.length - 1] || null;
507
117
  }
508
- function indexOfId(v, id) {
509
- const item = itemById(v, id);
510
- return item ? v.indexOf(item) : -1;
118
+ var isRef = (v) => hasProp(v, "current");
119
+ function addDomEvent(target, eventName, handler, options) {
120
+ const node = isRef(target) ? target.current : runIfFn(target);
121
+ node == null ? void 0 : node.addEventListener(eventName, handler, options);
122
+ return () => {
123
+ node == null ? void 0 : node.removeEventListener(eventName, handler, options);
124
+ };
511
125
  }
512
- var getValueText = (item) => {
513
- var _a, _b;
514
- return (_b = (_a = item.dataset.valuetext) != null ? _a : item.textContent) != null ? _b : "";
515
- };
516
- var match = (valueText, query2) => valueText.toLowerCase().startsWith(query2.toLowerCase());
517
- var wrap = (v, idx) => {
518
- return v.map((_, index) => v[(Math.max(idx, 0) + index) % v.length]);
519
- };
520
- function findByText(v, text, currentId) {
521
- const index = currentId ? indexOfId(v, currentId) : -1;
522
- let items = currentId ? wrap(v, index) : v;
523
- const isSingleKey = text.length === 1;
524
- if (isSingleKey) {
525
- items = items.filter((item) => item.id !== currentId);
126
+ function nextTick(fn) {
127
+ const set = /* @__PURE__ */ new Set();
128
+ function raf2(fn2) {
129
+ const id = globalThis.requestAnimationFrame(fn2);
130
+ set.add(() => globalThis.cancelAnimationFrame(id));
526
131
  }
527
- return items.find((item) => match(getValueText(item), text));
132
+ raf2(() => raf2(fn));
133
+ return function cleanup() {
134
+ set.forEach(function(fn2) {
135
+ fn2();
136
+ });
137
+ };
528
138
  }
529
- function trackPointerDown(doc, onPointerDown) {
530
- var _a;
531
- const win = (_a = doc.defaultView) != null ? _a : window;
532
- const fn = (event) => {
533
- if (event.target instanceof win.HTMLElement) {
534
- onPointerDown(event.target);
535
- }
139
+ function raf(fn) {
140
+ const id = globalThis.requestAnimationFrame(fn);
141
+ return function cleanup() {
142
+ globalThis.cancelAnimationFrame(id);
536
143
  };
537
- return addDomEvent(doc, "pointerdown", fn);
538
- }
539
- function findByTypeahead(_items, options) {
540
- const { state: state2, activeId, key, timeout = 350 } = options;
541
- const search = state2.keysSoFar + key;
542
- const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
543
- const query2 = isRepeated ? search[0] : search;
544
- let items = _items.slice();
545
- const next2 = findByText(items, query2, activeId);
546
- function cleanup() {
547
- clearTimeout(state2.timer);
548
- state2.timer = -1;
549
- }
550
- function update(value) {
551
- state2.keysSoFar = value;
552
- cleanup();
553
- if (value !== "") {
554
- state2.timer = +setTimeout(() => {
555
- update("");
556
- cleanup();
557
- }, timeout);
558
- }
559
- }
560
- update(search);
561
- return next2;
562
144
  }
563
- findByTypeahead.defaultOptions = {
564
- keysSoFar: "",
565
- timer: -1
566
- };
567
145
 
568
146
  // src/popover.connect.ts
569
147
  import { getPlacementStyles } from "@zag-js/popper";
570
148
 
571
- // ../../types/dist/index.mjs
572
- function createNormalizer(fn) {
573
- return new Proxy({}, {
574
- get() {
575
- return fn;
576
- }
577
- });
578
- }
579
- var normalizeProp = createNormalizer((v) => v);
580
-
581
149
  // ../../utilities/core/dist/index.mjs
582
- var first = (v) => v[0];
583
- var last = (v) => v[v.length - 1];
584
150
  function nextIndex(v, idx, opts = {}) {
585
151
  const { step = 1, loop = true } = opts;
586
152
  const next2 = idx + step;
@@ -601,7 +167,6 @@ var runIfFn2 = (v, ...a) => {
601
167
  const res = typeof v === "function" ? v(...a) : v;
602
168
  return res != null ? res : void 0;
603
169
  };
604
- var cast = (v) => v;
605
170
 
606
171
  // src/popover.dom.ts
607
172
  var dom = {
@@ -609,6 +174,10 @@ var dom = {
609
174
  var _a;
610
175
  return (_a = ctx.doc) != null ? _a : document;
611
176
  },
177
+ getWin: (ctx) => {
178
+ var _a;
179
+ return (_a = dom.getDoc(ctx).defaultView) != null ? _a : window;
180
+ },
612
181
  getActiveEl: (ctx) => dom.getDoc(ctx).activeElement,
613
182
  getRootNode: (ctx) => {
614
183
  var _a;
@@ -648,29 +217,32 @@ var dom = {
648
217
  getDescriptionEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getDescriptionId(ctx)),
649
218
  getFocusableEls: (ctx) => getFocusables(dom.getContentEl(ctx)),
650
219
  getFirstFocusableEl: (ctx) => dom.getFocusableEls(ctx)[0],
651
- getDocTabbableEls: (ctx) => getTabbables(cast(dom.getDoc(ctx))),
652
- getTabbableEls: (ctx) => {
653
- const el = dom.getContentEl(ctx);
654
- return el ? getTabbables(el) : [];
655
- },
656
- getFirstTabbableEl: (ctx) => first(dom.getTabbableEls(ctx)),
657
- getLastTabbableEl: (ctx) => last(dom.getTabbableEls(ctx)),
220
+ getDocTabbableEls: (ctx) => getTabbables(dom.getDoc(ctx).body),
221
+ getTabbableEls: (ctx) => getTabbables(dom.getContentEl(ctx), "if-empty"),
222
+ getFirstTabbableEl: (ctx) => getFirstTabbable(dom.getContentEl(ctx), "if-empty"),
223
+ getLastTabbableEl: (ctx) => getLastTabbable(dom.getContentEl(ctx), "if-empty"),
658
224
  getInitialFocusEl: (ctx) => {
659
- var _a;
660
- return (_a = runIfFn2(ctx.initialFocusEl)) != null ? _a : dom.getFirstFocusableEl(ctx);
225
+ let el = runIfFn2(ctx.initialFocusEl);
226
+ if (!el && ctx.autoFocus)
227
+ el = dom.getFirstFocusableEl(ctx);
228
+ if (!el)
229
+ el = dom.getContentEl(ctx);
230
+ return el;
661
231
  }
662
232
  };
663
233
 
664
234
  // src/popover.connect.ts
665
- function connect(state, send, normalize = normalizeProp) {
235
+ function connect(state, send, normalize) {
666
236
  const isOpen = state.matches("open");
667
- const pointerdownNode = state.context.pointerdownNode;
237
+ const currentPlacement = state.context.currentPlacement;
238
+ const portalled = state.context.currentPortalled;
239
+ const rendered = state.context.renderedElements;
668
240
  const popperStyles = getPlacementStyles({
669
241
  measured: !!state.context.isPlacementComplete,
670
- placement: state.context.currentPlacement
242
+ placement: currentPlacement
671
243
  });
672
244
  return {
673
- portalled: state.context.currentPortalled,
245
+ portalled,
674
246
  isOpen,
675
247
  open() {
676
248
  send("OPEN");
@@ -694,14 +266,17 @@ function connect(state, send, normalize = normalizeProp) {
694
266
  triggerProps: normalize.button({
695
267
  "data-part": "trigger",
696
268
  type: "button",
697
- "data-placement": state.context.currentPlacement,
269
+ "data-placement": currentPlacement,
698
270
  id: dom.getTriggerId(state.context),
699
271
  "aria-haspopup": "dialog",
700
272
  "aria-expanded": isOpen,
701
273
  "data-expanded": dataAttr(isOpen),
702
274
  "aria-controls": dom.getContentId(state.context),
703
275
  onClick() {
704
- send("TRIGGER_CLICK");
276
+ send("TOGGLE");
277
+ },
278
+ onBlur(event) {
279
+ send({ type: "TRIGGER_BLUR", target: event.relatedTarget });
705
280
  }
706
281
  }),
707
282
  positionerProps: normalize.element({
@@ -716,34 +291,9 @@ function connect(state, send, normalize = normalizeProp) {
716
291
  role: "dialog",
717
292
  hidden: !isOpen,
718
293
  "data-expanded": dataAttr(isOpen),
719
- "aria-labelledby": state.context.isTitleRendered ? dom.getTitleId(state.context) : void 0,
720
- "aria-describedby": state.context.isDescriptionRendered ? dom.getDescriptionId(state.context) : void 0,
721
- "data-placement": state.context.currentPlacement,
722
- onKeyDown(event) {
723
- const keyMap = {
724
- Escape(event2) {
725
- send("ESCAPE");
726
- event2.stopPropagation();
727
- },
728
- Tab(event2) {
729
- const type = event2.shiftKey ? "SHIFT_TAB" : "TAB";
730
- send({ type, preventDefault: () => event2.preventDefault() });
731
- }
732
- };
733
- const exec = keyMap[event.key];
734
- exec == null ? void 0 : exec(event);
735
- },
736
- onBlur(event) {
737
- var _a;
738
- const isValidBlur = validateBlur(event, {
739
- exclude: [dom.getTriggerEl(state.context), dom.getContentEl(state.context)],
740
- fallback: pointerdownNode
741
- });
742
- if (isValidBlur) {
743
- const el = (_a = event.relatedTarget) != null ? _a : pointerdownNode;
744
- send({ type: "INTERACT_OUTSIDE", focusable: isFocusable(el) });
745
- }
746
- }
294
+ "aria-labelledby": rendered.title ? dom.getTitleId(state.context) : void 0,
295
+ "aria-describedby": rendered.description ? dom.getDescriptionId(state.context) : void 0,
296
+ "data-placement": currentPlacement
747
297
  }),
748
298
  titleProps: normalize.element({
749
299
  "data-part": "title",
@@ -759,28 +309,345 @@ function connect(state, send, normalize = normalizeProp) {
759
309
  type: "button",
760
310
  "aria-label": "close",
761
311
  onClick() {
762
- send("CLOSE");
312
+ send("REQUEST_CLOSE");
763
313
  }
764
314
  })
765
315
  };
766
316
  }
767
317
 
768
318
  // src/popover.machine.ts
769
- import { choose, createMachine, guards, ref } from "@zag-js/core";
770
- import { getPlacement } from "@zag-js/popper";
771
319
  import { ariaHidden } from "@zag-js/aria-hidden";
320
+ import { createMachine, guards, ref } from "@zag-js/core";
321
+
322
+ // ../../utilities/interact-outside/dist/index.mjs
323
+ var runIfFn3 = (v, ...a) => {
324
+ const res = typeof v === "function" ? v(...a) : v;
325
+ return res != null ? res : void 0;
326
+ };
327
+ var hasProp2 = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
328
+ var isDom = () => typeof window !== "undefined";
329
+ function getPlatform() {
330
+ var _a;
331
+ const agent = navigator.userAgentData;
332
+ return (_a = agent == null ? void 0 : agent.platform) != null ? _a : navigator.platform;
333
+ }
334
+ var pt = (v) => isDom() && v.test(getPlatform());
335
+ var isTouchDevice = () => isDom() && !!navigator.maxTouchPoints;
336
+ var isMac = () => pt(/^Mac/) && !isTouchDevice;
337
+ function isWindow2(value) {
338
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
339
+ }
340
+ function getDocument2(el) {
341
+ var _a;
342
+ if (isWindow2(el))
343
+ return el.document;
344
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
345
+ }
346
+ function getWindow(el) {
347
+ var _a;
348
+ return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
349
+ }
350
+ function getEventTarget2(event) {
351
+ var _a, _b;
352
+ return (_b = (_a = event.composedPath) == null ? void 0 : _a.call(event)[0]) != null ? _b : event.target;
353
+ }
354
+ function contains2(parent, child) {
355
+ if (!parent)
356
+ return false;
357
+ return parent === child || isHTMLElement2(parent) && isHTMLElement2(child) && parent.contains(child);
358
+ }
359
+ function isHTMLElement2(v) {
360
+ return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
361
+ }
362
+ function isVisible2(el) {
363
+ if (!isHTMLElement2(el))
364
+ return false;
365
+ return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
366
+ }
367
+ var isContextMenuEvent = (e) => {
368
+ return e.button === 2 || isCtrlKey(e) && e.button === 0;
369
+ };
370
+ var isCtrlKey = (v) => isMac() ? v.metaKey && !v.ctrlKey : v.ctrlKey && !v.metaKey;
371
+ function fireCustomEvent(el, type, init) {
372
+ if (!el)
373
+ return;
374
+ const win = getWindow(el);
375
+ const event = new win.CustomEvent(type, init);
376
+ return el.dispatchEvent(event);
377
+ }
378
+ var focusableSelector2 = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type";
379
+ function isFocusable2(element) {
380
+ if (!element)
381
+ return false;
382
+ return element.matches(focusableSelector2) && isVisible2(element);
383
+ }
384
+ var isRef2 = (v) => hasProp2(v, "current");
385
+ function addDomEvent2(target, eventName, handler, options) {
386
+ const node = isRef2(target) ? target.current : runIfFn3(target);
387
+ node == null ? void 0 : node.addEventListener(eventName, handler, options);
388
+ return () => {
389
+ node == null ? void 0 : node.removeEventListener(eventName, handler, options);
390
+ };
391
+ }
392
+ var POINTER_OUTSIDE_EVENT = "pointerdown.outside";
393
+ var FOCUS_OUTSIDE_EVENT = "focus.outside";
394
+ function trackInteractOutside(node, options) {
395
+ const { exclude, onFocusOutside, onPointerDownOutside } = options;
396
+ if (!node)
397
+ return;
398
+ const doc = getDocument2(node);
399
+ const win = getWindow(node);
400
+ function isEventOutside(event) {
401
+ const target = getEventTarget2(event);
402
+ if (!(target instanceof win.HTMLElement)) {
403
+ return false;
404
+ }
405
+ if (!contains2(doc.documentElement, target)) {
406
+ return false;
407
+ }
408
+ if (contains2(node, target)) {
409
+ return false;
410
+ }
411
+ return !(exclude == null ? void 0 : exclude(target));
412
+ }
413
+ let clickHandler;
414
+ function onPointerDown(event) {
415
+ function handler() {
416
+ if (!node || !isEventOutside(event))
417
+ return;
418
+ if (onPointerDownOutside) {
419
+ node.addEventListener(POINTER_OUTSIDE_EVENT, onPointerDownOutside, { once: true });
420
+ }
421
+ fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {
422
+ bubbles: false,
423
+ cancelable: true,
424
+ detail: {
425
+ originalEvent: event,
426
+ contextmenu: isContextMenuEvent(event),
427
+ focusable: isFocusable2(getEventTarget2(event))
428
+ }
429
+ });
430
+ }
431
+ if (event.pointerType === "touch") {
432
+ doc.removeEventListener("click", handler);
433
+ clickHandler = handler;
434
+ doc.addEventListener("click", handler, { once: true });
435
+ } else {
436
+ handler();
437
+ }
438
+ }
439
+ const cleanups = /* @__PURE__ */ new Set();
440
+ const timer = setTimeout(() => {
441
+ cleanups.add(addDomEvent2(doc, "pointerdown", onPointerDown, true));
442
+ }, 0);
443
+ function onFocusin(event) {
444
+ if (!node || !isEventOutside(event))
445
+ return;
446
+ if (onFocusOutside) {
447
+ node.addEventListener(FOCUS_OUTSIDE_EVENT, onFocusOutside, { once: true });
448
+ }
449
+ fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {
450
+ bubbles: false,
451
+ cancelable: true,
452
+ detail: {
453
+ originalEvent: event,
454
+ contextmenu: false,
455
+ focusable: isFocusable2(getEventTarget2(event))
456
+ }
457
+ });
458
+ }
459
+ cleanups.add(addDomEvent2(doc, "focusin", onFocusin, true));
460
+ return () => {
461
+ clearTimeout(timer);
462
+ if (clickHandler)
463
+ doc.removeEventListener("click", clickHandler);
464
+ cleanups.forEach((fn) => fn());
465
+ };
466
+ }
467
+
468
+ // ../../utilities/dismissable/src/escape-keydown.ts
469
+ function trackEscapeKeydown(fn) {
470
+ const handleKeyDown = (event) => {
471
+ if (event.key === "Escape")
472
+ fn == null ? void 0 : fn(event);
473
+ };
474
+ return addDomEvent(document, "keydown", handleKeyDown);
475
+ }
476
+
477
+ // ../../utilities/dismissable/src/layer-stack.ts
478
+ var layerStack = {
479
+ layers: [],
480
+ branches: [],
481
+ count() {
482
+ return this.layers.length;
483
+ },
484
+ pointerBlockingLayers() {
485
+ return this.layers.filter((layer) => layer.pointerBlocking);
486
+ },
487
+ topMostPointerBlockingLayer() {
488
+ return [...this.pointerBlockingLayers()].slice(-1)[0];
489
+ },
490
+ hasPointerBlockingLayer() {
491
+ return this.pointerBlockingLayers().length > 0;
492
+ },
493
+ isBelowPointerBlockingLayer(node) {
494
+ var _a;
495
+ const index = this.indexOf(node);
496
+ const highestBlockingIndex = this.topMostPointerBlockingLayer() ? this.indexOf((_a = this.topMostPointerBlockingLayer()) == null ? void 0 : _a.node) : -1;
497
+ return index < highestBlockingIndex;
498
+ },
499
+ isTopMost(node) {
500
+ const layer = this.layers[this.count() - 1];
501
+ return (layer == null ? void 0 : layer.node) === node;
502
+ },
503
+ getNestedLayers(node) {
504
+ return Array.from(this.layers).slice(this.indexOf(node) + 1);
505
+ },
506
+ isInNestedLayer(node, target) {
507
+ return this.getNestedLayers(node).some((layer) => contains(layer.node, target));
508
+ },
509
+ isInBranch(target) {
510
+ return Array.from(this.branches).some((branch) => contains(branch, target));
511
+ },
512
+ add(layer) {
513
+ this.layers.push(layer);
514
+ },
515
+ addBranch(node) {
516
+ this.branches.push(node);
517
+ },
518
+ remove(node) {
519
+ const index = this.indexOf(node);
520
+ if (index < 0)
521
+ return;
522
+ if (index < this.count() - 1) {
523
+ const _layers = this.getNestedLayers(node);
524
+ _layers.forEach((layer) => layer.dismiss());
525
+ }
526
+ this.layers.splice(index, 1);
527
+ },
528
+ removeBranch(node) {
529
+ const index = this.branches.indexOf(node);
530
+ if (index >= 0)
531
+ this.branches.splice(index, 1);
532
+ },
533
+ indexOf(node) {
534
+ return this.layers.findIndex((layer) => layer.node === node);
535
+ },
536
+ dismiss(node) {
537
+ var _a;
538
+ (_a = this.layers[this.indexOf(node)]) == null ? void 0 : _a.dismiss();
539
+ },
540
+ clear() {
541
+ this.remove(this.layers[0].node);
542
+ }
543
+ };
544
+
545
+ // ../../utilities/dismissable/src/pointer-event-outside.ts
546
+ var originalBodyPointerEvents;
547
+ function assignPointerEventToLayers() {
548
+ layerStack.layers.forEach(({ node }) => {
549
+ node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto";
550
+ });
551
+ }
552
+ function clearPointerEvent(node) {
553
+ node.style.pointerEvents = "";
554
+ }
555
+ var DATA_ATTR = "data-inert";
556
+ function disablePointerEventsOutside(node) {
557
+ const doc = getDocument(node);
558
+ if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute(DATA_ATTR)) {
559
+ originalBodyPointerEvents = document.body.style.pointerEvents;
560
+ doc.body.style.pointerEvents = "none";
561
+ doc.body.setAttribute(DATA_ATTR, "");
562
+ }
563
+ return () => {
564
+ if (layerStack.hasPointerBlockingLayer())
565
+ return;
566
+ doc.body.style.pointerEvents = originalBodyPointerEvents;
567
+ doc.body.removeAttribute(DATA_ATTR);
568
+ if (doc.body.style.length === 0)
569
+ doc.body.removeAttribute("style");
570
+ };
571
+ }
572
+
573
+ // ../../utilities/dismissable/src/dismissable-layer.ts
574
+ function trackDismissableElement(node, options) {
575
+ if (!node)
576
+ return;
577
+ const { onDismiss, pointerBlocking, exclude: excludeContainers, debug } = options;
578
+ const layer = { dismiss: onDismiss, node, pointerBlocking };
579
+ layerStack.add(layer);
580
+ assignPointerEventToLayers();
581
+ function onPointerDownOutside(event) {
582
+ var _a, _b;
583
+ const target = getEventTarget(event.detail.originalEvent);
584
+ if (layerStack.isBelowPointerBlockingLayer(node) || layerStack.isInBranch(target))
585
+ return;
586
+ (_a = options.onPointerDownOutside) == null ? void 0 : _a.call(options, event);
587
+ (_b = options.onInteractOutside) == null ? void 0 : _b.call(options, event);
588
+ if (event.defaultPrevented)
589
+ return;
590
+ if (debug) {
591
+ console.log("onPointerDownOutside:", event.detail.originalEvent);
592
+ }
593
+ onDismiss == null ? void 0 : onDismiss();
594
+ }
595
+ function onFocusOutside(event) {
596
+ var _a, _b;
597
+ const target = getEventTarget(event.detail.originalEvent);
598
+ if (layerStack.isInBranch(target))
599
+ return;
600
+ (_a = options.onFocusOutside) == null ? void 0 : _a.call(options, event);
601
+ (_b = options.onInteractOutside) == null ? void 0 : _b.call(options, event);
602
+ if (event.defaultPrevented)
603
+ return;
604
+ if (debug) {
605
+ console.log("onFocusOutside:", event.detail.originalEvent);
606
+ }
607
+ onDismiss == null ? void 0 : onDismiss();
608
+ }
609
+ function onEscapeKeyDown(event) {
610
+ var _a;
611
+ if (!layerStack.isTopMost(node))
612
+ return;
613
+ (_a = options.onEscapeKeyDown) == null ? void 0 : _a.call(options, event);
614
+ if (!event.defaultPrevented && onDismiss) {
615
+ event.preventDefault();
616
+ onDismiss();
617
+ }
618
+ }
619
+ function exclude(target) {
620
+ if (!node)
621
+ return false;
622
+ const containers = typeof excludeContainers === "function" ? excludeContainers() : excludeContainers;
623
+ const _containers = Array.isArray(containers) ? containers : [containers];
624
+ return _containers.some((node2) => contains(node2, target)) || layerStack.isInNestedLayer(node, target);
625
+ }
626
+ const cleanups = [
627
+ pointerBlocking ? disablePointerEventsOutside(node) : void 0,
628
+ trackEscapeKeydown(onEscapeKeyDown),
629
+ trackInteractOutside(node, { exclude, onFocusOutside, onPointerDownOutside })
630
+ ];
631
+ return () => {
632
+ layerStack.remove(node);
633
+ assignPointerEventToLayers();
634
+ clearPointerEvent(node);
635
+ cleanups.forEach((fn) => fn == null ? void 0 : fn());
636
+ };
637
+ }
638
+
639
+ // src/popover.machine.ts
640
+ import { getPlacement } from "@zag-js/popper";
641
+ import { preventBodyScroll } from "@zag-js/remove-scroll";
772
642
  import { createFocusTrap } from "focus-trap";
773
- var { and, or } = guards;
643
+ var { and, or, not } = guards;
774
644
  function machine(ctx = {}) {
775
645
  return createMachine({
776
646
  id: "popover",
777
647
  initial: "unknown",
778
- context: __spreadValues({
779
- isTitleRendered: true,
780
- isDescriptionRendered: true,
781
- isAnchorRendered: false,
648
+ context: __spreadProps(__spreadValues({
782
649
  uid: "",
783
- closeOnBlur: true,
650
+ closeOnInteractOutside: true,
784
651
  closeOnEsc: true,
785
652
  autoFocus: true,
786
653
  modal: false,
@@ -788,7 +655,14 @@ function machine(ctx = {}) {
788
655
  placement: "bottom"
789
656
  }, ctx.positioning),
790
657
  currentPlacement: void 0
791
- }, ctx),
658
+ }, ctx), {
659
+ focusTriggerOnClose: true,
660
+ renderedElements: {
661
+ title: true,
662
+ description: true,
663
+ anchor: false
664
+ }
665
+ }),
792
666
  computed: {
793
667
  currentPortalled: (ctx2) => !!ctx2.modal || !!ctx2.portalled
794
668
  },
@@ -796,7 +670,7 @@ function machine(ctx = {}) {
796
670
  unknown: {
797
671
  on: {
798
672
  SETUP: {
799
- target: "closed",
673
+ target: ctx.defaultOpen ? "open" : "closed",
800
674
  actions: ["setupDocument", "checkRenderedElements"]
801
675
  }
802
676
  }
@@ -804,61 +678,46 @@ function machine(ctx = {}) {
804
678
  closed: {
805
679
  entry: ["clearPointerDown", "invokeOnClose"],
806
680
  on: {
807
- TRIGGER_CLICK: "open",
681
+ TOGGLE: "open",
808
682
  OPEN: "open"
809
683
  }
810
684
  },
811
685
  open: {
812
686
  activities: [
813
- "trackPointerDown",
814
687
  "trapFocus",
815
688
  "preventScroll",
816
689
  "hideContentBelow",
817
- "disableOutsidePointerEvents",
818
- "computePlacement"
690
+ "computePlacement",
691
+ "trackInteractionOutside",
692
+ "trackTabKeyDown"
819
693
  ],
820
- entry: choose([
821
- {
822
- guard: "autoFocus",
823
- actions: ["setInitialFocus", "invokeOnOpen"]
824
- },
825
- { actions: ["focusContent", "invokeOnOpen"] }
826
- ]),
694
+ entry: ["setInitialFocus", "invokeOnOpen"],
827
695
  on: {
828
- CLOSE: {
696
+ CLOSE: "closed",
697
+ REQUEST_CLOSE: {
829
698
  target: "closed",
830
- actions: "focusTrigger"
699
+ actions: "focusTriggerIfNeeded"
831
700
  },
832
- TRIGGER_CLICK: {
833
- target: "closed",
834
- actions: "focusTrigger"
835
- },
836
- ESCAPE: {
837
- guard: "closeOnEsc",
838
- target: "closed",
839
- actions: "focusTrigger"
701
+ TOGGLE: "closed",
702
+ TRIGGER_BLUR: {
703
+ guard: not("isRelatedTargetWithinContent"),
704
+ target: "closed"
840
705
  },
841
- TAB: {
842
- guard: and("isLastTabbableElement", "closeOnBlur", "portalled"),
843
- target: "closed",
844
- actions: "focusNextTabbableElementAfterTrigger"
845
- },
846
- SHIFT_TAB: {
847
- guard: and(or("isFirstTabbableElement", "isContentFocused"), "closeOnBlur", "portalled"),
848
- target: "closed",
849
- actions: "focusTrigger"
850
- },
851
- INTERACT_OUTSIDE: [
706
+ TAB: [
852
707
  {
853
- guard: and("closeOnBlur", "isRelatedTargetFocusable"),
854
- target: "closed"
708
+ guard: and("isTriggerFocused", "portalled"),
709
+ actions: "focusFirstTabbableElement"
855
710
  },
856
711
  {
857
- guard: "closeOnBlur",
712
+ guard: and("isLastTabbableElement", "closeOnInteractOutside", "portalled"),
858
713
  target: "closed",
859
- actions: "focusTrigger"
714
+ actions: "focusNextTabbableElementAfterTrigger"
860
715
  }
861
- ]
716
+ ],
717
+ SHIFT_TAB: {
718
+ guard: and(or("isFirstTabbableElement", "isContentFocused"), "portalled"),
719
+ actions: "focusTriggerIfNeeded"
720
+ }
862
721
  }
863
722
  }
864
723
  }
@@ -866,7 +725,7 @@ function machine(ctx = {}) {
866
725
  activities: {
867
726
  computePlacement(ctx2) {
868
727
  ctx2.currentPlacement = ctx2.positioning.placement;
869
- const anchorEl = ctx2.isAnchorRendered ? dom.getAnchorEl(ctx2) : dom.getTriggerEl(ctx2);
728
+ const anchorEl = ctx2.renderedElements.anchor ? dom.getAnchorEl(ctx2) : dom.getTriggerEl(ctx2);
870
729
  return getPlacement(anchorEl, dom.getPositionerEl(ctx2), __spreadProps(__spreadValues({}, ctx2.positioning), {
871
730
  onComplete(data) {
872
731
  ctx2.currentPlacement = data.placement;
@@ -878,33 +737,70 @@ function machine(ctx = {}) {
878
737
  }
879
738
  }));
880
739
  },
881
- trackPointerDown(ctx2) {
882
- return trackPointerDown(dom.getDoc(ctx2), (el) => {
883
- ctx2.pointerdownNode = ref(el);
740
+ trackInteractionOutside(ctx2, _evt, { send }) {
741
+ return trackDismissableElement(dom.getContentEl(ctx2), {
742
+ pointerBlocking: ctx2.modal,
743
+ exclude: dom.getTriggerEl(ctx2),
744
+ onEscapeKeyDown(event) {
745
+ var _a;
746
+ (_a = ctx2.onEscapeKeyDown) == null ? void 0 : _a.call(ctx2, event);
747
+ if (ctx2.closeOnEsc)
748
+ return;
749
+ ctx2.focusTriggerOnClose = true;
750
+ event.preventDefault();
751
+ },
752
+ onInteractOutside(event) {
753
+ var _a;
754
+ (_a = ctx2.onInteractOutside) == null ? void 0 : _a.call(ctx2, event);
755
+ if (event.defaultPrevented)
756
+ return;
757
+ ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
758
+ if (!ctx2.closeOnInteractOutside) {
759
+ event.preventDefault();
760
+ }
761
+ },
762
+ onPointerDownOutside(event) {
763
+ var _a;
764
+ (_a = ctx2.onPointerDownOutside) == null ? void 0 : _a.call(ctx2, event);
765
+ },
766
+ onFocusOutside(event) {
767
+ var _a;
768
+ (_a = ctx2.onFocusOutside) == null ? void 0 : _a.call(ctx2, event);
769
+ if (ctx2.currentPortalled) {
770
+ event.preventDefault();
771
+ }
772
+ },
773
+ onDismiss() {
774
+ send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
775
+ }
884
776
  });
885
777
  },
886
- disableOutsidePointerEvents(ctx2) {
887
- const el = dom.getContentEl(ctx2);
888
- return preventBodyPointerEvents(el, {
889
- document: dom.getDoc(ctx2),
890
- disabled: !ctx2.modal
891
- });
778
+ trackTabKeyDown(ctx2, _evt, { send }) {
779
+ if (ctx2.modal)
780
+ return;
781
+ return addDomEvent(dom.getWin(ctx2), "keydown", (event) => {
782
+ const isTabKey = event.key === "Tab" && !isModifiedEvent(event);
783
+ if (!isTabKey)
784
+ return;
785
+ send({
786
+ type: event.shiftKey ? "SHIFT_TAB" : "TAB",
787
+ preventDefault: () => event.preventDefault()
788
+ });
789
+ }, true);
892
790
  },
893
791
  hideContentBelow(ctx2) {
894
792
  if (!ctx2.modal)
895
793
  return;
896
- let unhide;
794
+ let cleanup;
897
795
  nextTick(() => {
898
- unhide = ariaHidden([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
796
+ cleanup = ariaHidden([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
899
797
  });
900
- return () => unhide == null ? void 0 : unhide();
798
+ return () => cleanup == null ? void 0 : cleanup();
901
799
  },
902
800
  preventScroll(ctx2) {
903
- return preventBodyScroll({
904
- allowPinchZoom: true,
905
- disabled: !ctx2.modal,
906
- document: dom.getDoc(ctx2)
907
- });
801
+ if (!ctx2.modal)
802
+ return;
803
+ return preventBodyScroll(dom.getDoc(ctx2));
908
804
  },
909
805
  trapFocus(ctx2) {
910
806
  if (!ctx2.modal)
@@ -924,29 +820,29 @@ function machine(ctx = {}) {
924
820
  });
925
821
  try {
926
822
  trap.activate();
927
- } catch (e2) {
823
+ } catch (e) {
928
824
  }
929
825
  });
930
826
  return () => trap == null ? void 0 : trap.deactivate();
931
827
  }
932
828
  },
933
829
  guards: {
934
- closeOnEsc: (ctx2) => !!ctx2.closeOnEsc,
935
- autoFocus: (ctx2) => !!ctx2.autoFocus,
936
- modal: (ctx2) => !!ctx2.modal,
937
- portalled: (ctx2) => !!ctx2.portalled,
938
- isRelatedTargetFocusable: (_ctx, evt) => evt.focusable,
939
- closeOnBlur: (ctx2) => !!ctx2.closeOnBlur,
830
+ portalled: (ctx2) => ctx2.currentPortalled,
831
+ isRelatedTargetWithinContent: (ctx2, evt) => contains(dom.getContentEl(ctx2), evt.target),
832
+ closeOnInteractOutside: (ctx2) => !!ctx2.closeOnInteractOutside,
940
833
  isContentFocused: (ctx2) => dom.getContentEl(ctx2) === dom.getActiveEl(ctx2),
834
+ isTriggerFocused: (ctx2) => dom.getTriggerEl(ctx2) === dom.getActiveEl(ctx2),
941
835
  isFirstTabbableElement: (ctx2) => dom.getFirstTabbableEl(ctx2) === dom.getActiveEl(ctx2),
942
836
  isLastTabbableElement: (ctx2) => dom.getLastTabbableEl(ctx2) === dom.getActiveEl(ctx2)
943
837
  },
944
838
  actions: {
945
839
  checkRenderedElements(ctx2) {
946
840
  raf(() => {
947
- ctx2.isAnchorRendered = !!dom.getAnchorEl(ctx2);
948
- ctx2.isTitleRendered = !!dom.getTitleEl(ctx2);
949
- ctx2.isDescriptionRendered = !!dom.getDescriptionEl(ctx2);
841
+ Object.assign(ctx2.renderedElements, {
842
+ title: !!dom.getTitleEl(ctx2),
843
+ description: !!dom.getDescriptionEl(ctx2),
844
+ anchor: !!dom.getAnchorEl(ctx2)
845
+ });
950
846
  });
951
847
  },
952
848
  setupDocument(ctx2, evt) {
@@ -959,44 +855,44 @@ function machine(ctx = {}) {
959
855
  clearPointerDown(ctx2) {
960
856
  ctx2.pointerdownNode = null;
961
857
  },
962
- focusContent(ctx2) {
963
- raf(() => {
964
- var _a;
965
- (_a = dom.getContentEl(ctx2)) == null ? void 0 : _a.focus();
966
- });
967
- },
968
858
  setInitialFocus(ctx2) {
969
859
  raf(() => {
970
860
  var _a;
971
861
  (_a = dom.getInitialFocusEl(ctx2)) == null ? void 0 : _a.focus();
972
862
  });
973
863
  },
974
- focusTrigger(ctx2) {
864
+ focusTriggerIfNeeded(ctx2) {
865
+ if (!ctx2.focusTriggerOnClose)
866
+ return;
975
867
  raf(() => {
976
868
  var _a;
977
- (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
869
+ return (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
978
870
  });
979
871
  },
872
+ focusFirstTabbableElement(ctx2, evt) {
873
+ var _a;
874
+ evt.preventDefault();
875
+ (_a = dom.getFirstTabbableEl(ctx2)) == null ? void 0 : _a.focus();
876
+ },
980
877
  invokeOnOpen(ctx2, evt) {
981
878
  var _a;
982
879
  if (evt.type !== "SETUP") {
983
- (_a = ctx2.onOpen) == null ? void 0 : _a.call(ctx2);
880
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, true);
984
881
  }
985
882
  },
986
883
  invokeOnClose(ctx2, evt) {
987
884
  var _a;
988
885
  if (evt.type !== "SETUP") {
989
- (_a = ctx2.onClose) == null ? void 0 : _a.call(ctx2);
886
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, false);
990
887
  }
991
888
  },
992
889
  focusNextTabbableElementAfterTrigger(ctx2, evt) {
993
890
  const content = dom.getContentEl(ctx2);
994
- const doc = dom.getDoc(ctx2);
995
891
  const button = dom.getTriggerEl(ctx2);
996
892
  if (!content || !button)
997
893
  return;
998
894
  const lastTabbable = dom.getLastTabbableEl(ctx2);
999
- if (lastTabbable !== doc.activeElement)
895
+ if (lastTabbable !== dom.getActiveEl(ctx2))
1000
896
  return;
1001
897
  let tabbables = dom.getDocTabbableEls(ctx2);
1002
898
  let elementAfterTrigger = next(tabbables, tabbables.indexOf(button), { loop: false });
@@ -1016,4 +912,3 @@ export {
1016
912
  connect,
1017
913
  machine
1018
914
  };
1019
- //# sourceMappingURL=index.mjs.map