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