@zag-js/popover 0.1.7 → 0.1.10

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;
@@ -42,181 +43,62 @@ __export(src_exports, {
42
43
  module.exports = __toCommonJS(src_exports);
43
44
 
44
45
  // ../../utilities/dom/dist/index.mjs
46
+ var __defProp2 = Object.defineProperty;
47
+ var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
48
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
49
+ var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
50
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
51
+ var __spreadValues2 = (a, b) => {
52
+ for (var prop in b || (b = {}))
53
+ if (__hasOwnProp2.call(b, prop))
54
+ __defNormalProp2(a, prop, b[prop]);
55
+ if (__getOwnPropSymbols2)
56
+ for (var prop of __getOwnPropSymbols2(b)) {
57
+ if (__propIsEnum2.call(b, prop))
58
+ __defNormalProp2(a, prop, b[prop]);
59
+ }
60
+ return a;
61
+ };
45
62
  var dataAttr = (guard) => {
46
63
  return guard ? "" : void 0;
47
64
  };
48
- function getStyleCache() {
49
- ;
50
- globalThis.__styleCache__ = globalThis.__styleCache__ || /* @__PURE__ */ new WeakMap();
51
- return globalThis.__styleCache__;
52
- }
53
- function getComputedStyle2(el) {
54
- var _a;
55
- if (!el)
56
- return {};
57
- const cache = getStyleCache();
58
- let style = cache.get(el);
59
- if (!style) {
60
- const win = (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
61
- style = win.getComputedStyle(el);
62
- cache.set(el, style);
63
- }
64
- return style;
65
- }
66
- function nextTick(fn) {
67
- const set = /* @__PURE__ */ new Set();
68
- function raf2(fn2) {
69
- const id = globalThis.requestAnimationFrame(fn2);
70
- set.add(() => globalThis.cancelAnimationFrame(id));
71
- }
72
- raf2(() => raf2(fn));
73
- return function cleanup() {
74
- set.forEach(function(fn2) {
75
- fn2();
76
- });
77
- };
78
- }
79
- function raf(fn) {
80
- const id = globalThis.requestAnimationFrame(fn);
81
- return function cleanup() {
82
- globalThis.cancelAnimationFrame(id);
83
- };
84
- }
85
- var isDom = () => typeof window !== "undefined";
86
- var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
87
- var isTouchDevice = isDom() && !!navigator.maxTouchPoints;
88
- var isLeftClick = (v) => v.button === 0;
89
65
  var runIfFn = (v, ...a) => {
90
66
  const res = typeof v === "function" ? v(...a) : v;
91
67
  return res != null ? res : void 0;
92
68
  };
93
- var noop = () => {
94
- };
95
- var pipe = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
96
- function getListenerElements() {
97
- ;
98
- globalThis.__listenerElements__ = globalThis.__listenerElements__ || /* @__PURE__ */ new Map();
99
- return globalThis.__listenerElements__;
69
+ var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
70
+ function isDocument(el) {
71
+ return el.nodeType === Node.DOCUMENT_NODE;
100
72
  }
101
- function getListenerCache() {
102
- ;
103
- globalThis.__listenerCache__ = globalThis.__listenerCache__ || /* @__PURE__ */ new Map();
104
- return globalThis.__listenerCache__;
73
+ function isWindow(value) {
74
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
105
75
  }
106
- function addGlobalEventListener(node, type, handler, options) {
107
- var _a;
108
- if (!node)
109
- return noop;
110
- const hash = JSON.stringify({ type, options });
111
- const listenerElements = getListenerElements();
112
- const listenerCache = getListenerCache();
113
- const group = listenerElements.get(node);
114
- if (!listenerElements.has(node)) {
115
- const group2 = /* @__PURE__ */ new Map([[hash, /* @__PURE__ */ new Set([handler])]]);
116
- listenerElements.set(node, group2);
117
- } else if (group == null ? void 0 : group.has(hash)) {
118
- (_a = group == null ? void 0 : group.get(hash)) == null ? void 0 : _a.add(handler);
119
- } else {
120
- group == null ? void 0 : group.set(hash, /* @__PURE__ */ new Set([handler]));
121
- }
122
- function attach(node2) {
123
- var _a2, _b;
124
- function listener(event) {
125
- var _a3;
126
- const group2 = listenerElements.get(node2);
127
- (_a3 = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _a3.forEach((fn) => fn(event));
128
- }
129
- if (!(listenerCache == null ? void 0 : listenerCache.has(node2))) {
130
- listenerCache.set(node2, /* @__PURE__ */ new Map([[hash, listener]]));
131
- node2.addEventListener(type, listener, options);
132
- return;
133
- }
134
- if (!((_a2 = listenerCache == null ? void 0 : listenerCache.get(node2)) == null ? void 0 : _a2.has(hash))) {
135
- (_b = listenerCache.get(node2)) == null ? void 0 : _b.set(hash, listener);
136
- node2.addEventListener(type, listener, options);
137
- }
138
- }
139
- attach(node);
140
- return function remove() {
141
- var _a2, _b, _c, _d;
142
- if (!listenerElements.has(node))
143
- return;
144
- const group2 = listenerElements.get(node);
145
- (_a2 = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _a2.delete(handler);
146
- if (((_b = group2 == null ? void 0 : group2.get(hash)) == null ? void 0 : _b.size) === 0) {
147
- const listener = (_c = listenerCache.get(node)) == null ? void 0 : _c.get(hash);
148
- node.removeEventListener(type, listener, options);
149
- group2 == null ? void 0 : group2.delete(hash);
150
- (_d = listenerCache.get(node)) == null ? void 0 : _d.delete(hash);
151
- if ((group2 == null ? void 0 : group2.size) === 0) {
152
- listenerElements.delete(node);
153
- listenerCache.delete(node);
154
- }
155
- }
156
- };
76
+ function isFrame(element) {
77
+ return element.localName === "iframe";
157
78
  }
158
- var isRef = (v) => hasProp(v, "current");
159
- function addDomEvent(target, event, listener, options) {
160
- const node = isRef(target) ? target.current : runIfFn(target);
161
- return addGlobalEventListener(node, event, listener, options);
79
+ function getDocument(el) {
80
+ var _a;
81
+ if (isWindow(el))
82
+ return el.document;
83
+ if (isDocument(el))
84
+ return el;
85
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
162
86
  }
163
- var changeCount = 0;
164
- var originalBodyPointerEvents;
165
- function preventBodyPointerEvents(el, opts = {}) {
166
- const { disabled = false, document: docProp } = opts;
167
- const doc = docProp || document;
168
- let isTouchOrPenPressed = false;
169
- let isLeftClickPressed = false;
170
- function listen() {
171
- const onPointerDown = (event) => {
172
- const isMouse = event.pointerType === "mouse";
173
- isTouchOrPenPressed = !isMouse;
174
- isLeftClickPressed = isMouse && isLeftClick(event);
175
- };
176
- const onPointerUp = () => {
177
- isTouchOrPenPressed = false;
178
- isLeftClickPressed = false;
179
- };
180
- return pipe(addDomEvent(doc, "pointerdown", onPointerDown), addDomEvent(doc, "pointerup", onPointerUp));
181
- }
182
- function reset() {
183
- changeCount--;
184
- if (changeCount === 0) {
185
- doc.body.style.pointerEvents = originalBodyPointerEvents;
186
- }
187
- if (el) {
188
- el.style.pointerEvents = "";
189
- }
190
- }
191
- function apply() {
192
- if (disabled)
193
- return;
194
- if (changeCount === 0) {
195
- originalBodyPointerEvents = doc.body.style.pointerEvents;
196
- }
197
- doc.body.style.pointerEvents = "none";
198
- if (el) {
199
- el.style.pointerEvents = "auto";
200
- }
201
- changeCount++;
202
- return function() {
203
- if (isTouchOrPenPressed) {
204
- addDomEvent(doc, "click", reset, { once: true });
205
- } else if (isLeftClickPressed) {
206
- addDomEvent(doc, "pointerup", reset, { once: true });
207
- } else {
208
- reset();
209
- }
210
- };
211
- }
212
- const cleanups = [];
213
- cleanups.push(apply());
214
- nextTick(() => {
215
- cleanups.push(listen());
216
- });
217
- return function() {
218
- cleanups.forEach((cleanup) => cleanup == null ? void 0 : cleanup());
87
+ function defineDomHelpers(helpers) {
88
+ const dom2 = {
89
+ getRootNode: (ctx) => {
90
+ var _a, _b;
91
+ return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
92
+ },
93
+ getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
94
+ getWin: (ctx) => {
95
+ var _a;
96
+ return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
97
+ },
98
+ getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
99
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
219
100
  };
101
+ return __spreadValues2(__spreadValues2({}, dom2), helpers);
220
102
  }
221
103
  function contains(parent, child) {
222
104
  if (!parent)
@@ -226,147 +108,102 @@ function contains(parent, child) {
226
108
  function isHTMLElement(v) {
227
109
  return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
228
110
  }
229
- var isDisabled = (el) => {
230
- return (el == null ? void 0 : el.getAttribute("disabled")) != null || !!(el == null ? void 0 : el.getAttribute("aria-disabled")) === true;
231
- };
232
- function validateBlur(event, opts) {
233
- var _a;
234
- const exclude = Array.isArray(opts.exclude) ? opts.exclude : [opts.exclude];
235
- const relatedTarget = (_a = event.relatedTarget) != null ? _a : opts.fallback;
236
- return exclude.every((el) => !(el == null ? void 0 : el.contains(relatedTarget)));
111
+ function isVisible(el) {
112
+ if (!isHTMLElement(el))
113
+ return false;
114
+ return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
237
115
  }
238
- var focusableSelector = /* @__PURE__ */ [
239
- "input:not([disabled]):not([type=hidden])",
240
- "select:not([disabled])",
241
- "textarea:not([disabled])",
242
- "button:not([disabled])",
243
- "embed",
244
- "iframe",
245
- "object",
246
- "a[href]",
247
- "area[href]",
248
- "[tabindex]",
249
- "audio[controls]",
250
- "video[controls]",
251
- "*[tabindex]:not([aria-disabled])",
252
- "[contenteditable]:not([contenteditable=false])",
253
- "details > summary:first-of-type"
254
- ].join(",");
255
- function isHidden(el, until) {
256
- const style = getComputedStyle2(el);
257
- if (!el || style.getPropertyValue("visibility") === "hidden")
258
- return true;
259
- while (el) {
260
- if (until != null && el === until)
261
- return false;
262
- if (style.getPropertyValue("display") === "none")
263
- return true;
264
- el = el.parentElement;
265
- }
266
- return false;
116
+ var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
117
+ function hasNegativeTabIndex(element) {
118
+ const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10);
119
+ return tabIndex < 0;
267
120
  }
268
- var getFocusables = (el, includeContainer = false) => {
269
- if (!el)
121
+ 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";
122
+ var getFocusables = (container, includeContainer = false) => {
123
+ if (!container)
270
124
  return [];
271
- let els = Array.from(el.querySelectorAll(focusableSelector));
272
- const shouldAddContainer = includeContainer == true || includeContainer == "if-empty" && els.length === 0;
273
- if (shouldAddContainer && isHTMLElement(el)) {
274
- els.unshift(el);
125
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
126
+ const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0;
127
+ if (include && isHTMLElement(container) && isFocusable(container)) {
128
+ elements.unshift(container);
275
129
  }
276
- return els.filter((el2) => isFocusable(el2) && !isHidden(el2));
130
+ const focusableElements = elements.filter(isFocusable);
131
+ focusableElements.forEach((element, i) => {
132
+ if (isFrame(element) && element.contentDocument) {
133
+ const frameBody = element.contentDocument.body;
134
+ focusableElements.splice(i, 1, ...getFocusables(frameBody));
135
+ }
136
+ });
137
+ return focusableElements;
277
138
  };
278
- var isFocusable = (el) => {
279
- if (!isHTMLElement(el) || isHidden(el) || isDisabled(el))
139
+ function isFocusable(element) {
140
+ if (!element)
280
141
  return false;
281
- return el == null ? void 0 : el.matches(focusableSelector);
282
- };
283
- var getTabbables = (el, includeContainer = false) => {
284
- if (!el)
142
+ return element.matches(focusableSelector) && isVisible(element);
143
+ }
144
+ function getTabbables(container, includeContainer) {
145
+ if (!container)
285
146
  return [];
286
- return getFocusables(el, includeContainer).filter(isTabbable);
287
- };
288
- var isTabbable = (el) => {
289
- return isFocusable(el) && !isDisabled(el) && !isHidden(el);
290
- };
291
- function itemById(v, id) {
292
- return v.find((node) => node.id === id);
147
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
148
+ const tabbableElements = elements.filter(isTabbable);
149
+ if (includeContainer && isTabbable(container)) {
150
+ tabbableElements.unshift(container);
151
+ }
152
+ tabbableElements.forEach((element, i) => {
153
+ if (isFrame(element) && element.contentDocument) {
154
+ const frameBody = element.contentDocument.body;
155
+ const allFrameTabbable = getTabbables(frameBody);
156
+ tabbableElements.splice(i, 1, ...allFrameTabbable);
157
+ }
158
+ });
159
+ if (!tabbableElements.length && includeContainer) {
160
+ return elements;
161
+ }
162
+ return tabbableElements;
293
163
  }
294
- function indexOfId(v, id) {
295
- const item = itemById(v, id);
296
- return item ? v.indexOf(item) : -1;
164
+ function isTabbable(el) {
165
+ return isFocusable(el) && !hasNegativeTabIndex(el);
297
166
  }
298
- var getValueText = (item) => {
299
- var _a, _b;
300
- return (_b = (_a = item.dataset.valuetext) != null ? _a : item.textContent) != null ? _b : "";
301
- };
302
- var match = (valueText, query2) => valueText.toLowerCase().startsWith(query2.toLowerCase());
303
- var wrap = (v, idx) => {
304
- return v.map((_, index) => v[(Math.max(idx, 0) + index) % v.length]);
305
- };
306
- function findByText(v, text, currentId) {
307
- const index = currentId ? indexOfId(v, currentId) : -1;
308
- let items = currentId ? wrap(v, index) : v;
309
- const isSingleKey = text.length === 1;
310
- if (isSingleKey) {
311
- items = items.filter((item) => item.id !== currentId);
312
- }
313
- return items.find((item) => match(getValueText(item), text));
167
+ function getFirstTabbable(container, includeContainer) {
168
+ const [first] = getTabbables(container, includeContainer);
169
+ return first || null;
314
170
  }
315
- function trackPointerDown(doc, onPointerDown) {
316
- var _a;
317
- const win = (_a = doc.defaultView) != null ? _a : window;
318
- const fn = (event) => {
319
- if (event.target instanceof win.HTMLElement) {
320
- onPointerDown(event.target);
321
- }
171
+ function getLastTabbable(container, includeContainer) {
172
+ const elements = getTabbables(container, includeContainer);
173
+ return elements[elements.length - 1] || null;
174
+ }
175
+ var isRef = (v) => hasProp(v, "current");
176
+ function addDomEvent(target, eventName, handler, options) {
177
+ const node = isRef(target) ? target.current : runIfFn(target);
178
+ node == null ? void 0 : node.addEventListener(eventName, handler, options);
179
+ return () => {
180
+ node == null ? void 0 : node.removeEventListener(eventName, handler, options);
322
181
  };
323
- return addDomEvent(doc, "pointerdown", fn);
324
182
  }
325
- function findByTypeahead(_items, options) {
326
- const { state: state2, activeId, key, timeout = 350 } = options;
327
- const search = state2.keysSoFar + key;
328
- const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
329
- const query2 = isRepeated ? search[0] : search;
330
- let items = _items.slice();
331
- const next2 = findByText(items, query2, activeId);
332
- function cleanup() {
333
- clearTimeout(state2.timer);
334
- state2.timer = -1;
335
- }
336
- function update(value) {
337
- state2.keysSoFar = value;
338
- cleanup();
339
- if (value !== "") {
340
- state2.timer = +setTimeout(() => {
341
- update("");
342
- cleanup();
343
- }, timeout);
344
- }
183
+ function nextTick(fn) {
184
+ const set = /* @__PURE__ */ new Set();
185
+ function raf2(fn2) {
186
+ const id = globalThis.requestAnimationFrame(fn2);
187
+ set.add(() => globalThis.cancelAnimationFrame(id));
345
188
  }
346
- update(search);
347
- return next2;
189
+ raf2(() => raf2(fn));
190
+ return function cleanup() {
191
+ set.forEach(function(fn2) {
192
+ fn2();
193
+ });
194
+ };
195
+ }
196
+ function raf(fn) {
197
+ const id = globalThis.requestAnimationFrame(fn);
198
+ return function cleanup() {
199
+ globalThis.cancelAnimationFrame(id);
200
+ };
348
201
  }
349
- findByTypeahead.defaultOptions = {
350
- keysSoFar: "",
351
- timer: -1
352
- };
353
202
 
354
203
  // src/popover.connect.ts
355
204
  var import_popper = require("@zag-js/popper");
356
205
 
357
- // ../../types/dist/index.mjs
358
- function createNormalizer(fn) {
359
- return new Proxy({}, {
360
- get() {
361
- return fn;
362
- }
363
- });
364
- }
365
- var normalizeProp = createNormalizer((v) => v);
366
-
367
206
  // ../../utilities/core/dist/index.mjs
368
- var first = (v) => v[0];
369
- var last = (v) => v[v.length - 1];
370
207
  function nextIndex(v, idx, opts = {}) {
371
208
  const { step = 1, loop = true } = opts;
372
209
  const next2 = idx + step;
@@ -383,63 +220,52 @@ function nextIndex(v, idx, opts = {}) {
383
220
  function next(v, idx, opts = {}) {
384
221
  return v[nextIndex(v, idx, opts)];
385
222
  }
386
- var isDom2 = () => typeof window !== "undefined";
387
- var isTouchDevice2 = isDom2() && !!navigator.maxTouchPoints;
388
223
  var runIfFn2 = (v, ...a) => {
389
224
  const res = typeof v === "function" ? v(...a) : v;
390
225
  return res != null ? res : void 0;
391
226
  };
392
- var cast = (v) => v;
393
227
 
394
228
  // src/popover.dom.ts
395
- var dom = {
396
- getDoc: (ctx) => {
397
- var _a;
398
- return (_a = ctx.doc) != null ? _a : document;
399
- },
229
+ var dom = defineDomHelpers({
400
230
  getActiveEl: (ctx) => dom.getDoc(ctx).activeElement,
401
- getRootNode: (ctx) => {
402
- var _a;
403
- return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
404
- },
405
231
  getAnchorId: (ctx) => {
406
232
  var _a, _b;
407
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.anchor) != null ? _b : `popover:${ctx.uid}:anchor`;
233
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.anchor) != null ? _b : `popover:${ctx.id}:anchor`;
408
234
  },
409
235
  getTriggerId: (ctx) => {
410
236
  var _a, _b;
411
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.trigger) != null ? _b : `popover:${ctx.uid}:trigger`;
237
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.trigger) != null ? _b : `popover:${ctx.id}:trigger`;
412
238
  },
413
239
  getContentId: (ctx) => {
414
240
  var _a, _b;
415
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.content) != null ? _b : `popover:${ctx.uid}:content`;
241
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.content) != null ? _b : `popover:${ctx.id}:content`;
416
242
  },
417
- getPositionerId: (ctx) => `popover:${ctx.uid}:popper`,
418
- getArrowId: (ctx) => `popover:${ctx.uid}:arrow`,
243
+ getPositionerId: (ctx) => `popover:${ctx.id}:popper`,
244
+ getArrowId: (ctx) => `popover:${ctx.id}:arrow`,
419
245
  getTitleId: (ctx) => {
420
246
  var _a, _b;
421
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.title) != null ? _b : `popover:${ctx.uid}:title`;
247
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.title) != null ? _b : `popover:${ctx.id}:title`;
422
248
  },
423
249
  getDescriptionId: (ctx) => {
424
250
  var _a, _b;
425
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.description) != null ? _b : `popover:${ctx.uid}:desc`;
251
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.description) != null ? _b : `popover:${ctx.id}:desc`;
426
252
  },
427
253
  getCloseButtonId: (ctx) => {
428
254
  var _a, _b;
429
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.closeBtn) != null ? _b : `popover:${ctx.uid}:close-button`;
255
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.closeBtn) != null ? _b : `popover:${ctx.id}:close-button`;
430
256
  },
431
- getAnchorEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getAnchorId(ctx)),
432
- getTriggerEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getTriggerId(ctx)),
433
- getContentEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getContentId(ctx)),
434
- getPositionerEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getPositionerId(ctx)),
435
- getTitleEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getTitleId(ctx)),
436
- getDescriptionEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getDescriptionId(ctx)),
257
+ getAnchorEl: (ctx) => dom.getById(ctx, dom.getAnchorId(ctx)),
258
+ getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
259
+ getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
260
+ getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
261
+ getTitleEl: (ctx) => dom.getById(ctx, dom.getTitleId(ctx)),
262
+ getDescriptionEl: (ctx) => dom.getById(ctx, dom.getDescriptionId(ctx)),
437
263
  getFocusableEls: (ctx) => getFocusables(dom.getContentEl(ctx)),
438
264
  getFirstFocusableEl: (ctx) => dom.getFocusableEls(ctx)[0],
439
- getDocTabbableEls: (ctx) => getTabbables(cast(dom.getDoc(ctx))),
265
+ getDocTabbableEls: (ctx) => getTabbables(dom.getDoc(ctx).body),
440
266
  getTabbableEls: (ctx) => getTabbables(dom.getContentEl(ctx), "if-empty"),
441
- getFirstTabbableEl: (ctx) => first(dom.getTabbableEls(ctx)),
442
- getLastTabbableEl: (ctx) => last(dom.getTabbableEls(ctx)),
267
+ getFirstTabbableEl: (ctx) => getFirstTabbable(dom.getContentEl(ctx), "if-empty"),
268
+ getLastTabbableEl: (ctx) => getLastTabbable(dom.getContentEl(ctx), "if-empty"),
443
269
  getInitialFocusEl: (ctx) => {
444
270
  let el = runIfFn2(ctx.initialFocusEl);
445
271
  if (!el && ctx.autoFocus)
@@ -448,19 +274,20 @@ var dom = {
448
274
  el = dom.getContentEl(ctx);
449
275
  return el;
450
276
  }
451
- };
277
+ });
452
278
 
453
279
  // src/popover.connect.ts
454
- function connect(state, send, normalize = normalizeProp) {
280
+ function connect(state, send, normalize) {
455
281
  const isOpen = state.matches("open");
456
- const pointerdownNode = state.context.pointerdownNode;
457
282
  const currentPlacement = state.context.currentPlacement;
283
+ const portalled = state.context.currentPortalled;
284
+ const rendered = state.context.renderedElements;
458
285
  const popperStyles = (0, import_popper.getPlacementStyles)({
459
286
  measured: !!state.context.isPlacementComplete,
460
287
  placement: currentPlacement
461
288
  });
462
289
  return {
463
- portalled: state.context.currentPortalled,
290
+ portalled,
464
291
  isOpen,
465
292
  open() {
466
293
  send("OPEN");
@@ -491,12 +318,10 @@ function connect(state, send, normalize = normalizeProp) {
491
318
  "data-expanded": dataAttr(isOpen),
492
319
  "aria-controls": dom.getContentId(state.context),
493
320
  onClick() {
494
- send("TRIGGER_CLICK");
321
+ send("TOGGLE");
495
322
  },
496
- onKeyDown(event) {
497
- if (event.key === "Escape") {
498
- send("ESCAPE");
499
- }
323
+ onBlur(event) {
324
+ send({ type: "TRIGGER_BLUR", target: event.relatedTarget });
500
325
  }
501
326
  }),
502
327
  positionerProps: normalize.element({
@@ -511,34 +336,9 @@ function connect(state, send, normalize = normalizeProp) {
511
336
  role: "dialog",
512
337
  hidden: !isOpen,
513
338
  "data-expanded": dataAttr(isOpen),
514
- "aria-labelledby": state.context.renderedElements.title ? dom.getTitleId(state.context) : void 0,
515
- "aria-describedby": state.context.renderedElements.description ? dom.getDescriptionId(state.context) : void 0,
516
- "data-placement": currentPlacement,
517
- onKeyDown(event) {
518
- const keyMap = {
519
- Escape(event2) {
520
- send("ESCAPE");
521
- event2.stopPropagation();
522
- },
523
- Tab(event2) {
524
- const type = event2.shiftKey ? "SHIFT_TAB" : "TAB";
525
- send({ type, preventDefault: () => event2.preventDefault() });
526
- }
527
- };
528
- const exec = keyMap[event.key];
529
- exec == null ? void 0 : exec(event);
530
- },
531
- onBlur(event) {
532
- var _a;
533
- const isValidBlur = validateBlur(event, {
534
- exclude: [dom.getTriggerEl(state.context), dom.getContentEl(state.context)],
535
- fallback: pointerdownNode
536
- });
537
- if (isValidBlur) {
538
- const el = (_a = event.relatedTarget) != null ? _a : pointerdownNode;
539
- send({ type: "INTERACT_OUTSIDE", focusable: isFocusable(el) });
540
- }
541
- }
339
+ "aria-labelledby": rendered.title ? dom.getTitleId(state.context) : void 0,
340
+ "aria-describedby": rendered.description ? dom.getDescriptionId(state.context) : void 0,
341
+ "data-placement": currentPlacement
542
342
  }),
543
343
  titleProps: normalize.element({
544
344
  "data-part": "title",
@@ -554,7 +354,7 @@ function connect(state, send, normalize = normalizeProp) {
554
354
  type: "button",
555
355
  "aria-label": "close",
556
356
  onClick() {
557
- send("CLOSE");
357
+ send("REQUEST_CLOSE");
558
358
  }
559
359
  })
560
360
  };
@@ -563,17 +363,17 @@ function connect(state, send, normalize = normalizeProp) {
563
363
  // src/popover.machine.ts
564
364
  var import_aria_hidden = require("@zag-js/aria-hidden");
565
365
  var import_core = require("@zag-js/core");
366
+ var import_dismissable = require("@zag-js/dismissable");
566
367
  var import_popper2 = require("@zag-js/popper");
567
368
  var import_remove_scroll = require("@zag-js/remove-scroll");
568
369
  var import_focus_trap = require("focus-trap");
569
- var { and, or } = import_core.guards;
570
- function machine(ctx = {}) {
370
+ var { and, or, not } = import_core.guards;
371
+ function machine(ctx) {
571
372
  return (0, import_core.createMachine)({
572
373
  id: "popover",
573
374
  initial: "unknown",
574
375
  context: __spreadProps(__spreadValues({
575
- uid: "",
576
- closeOnBlur: true,
376
+ closeOnInteractOutside: true,
577
377
  closeOnEsc: true,
578
378
  autoFocus: true,
579
379
  modal: false,
@@ -582,6 +382,7 @@ function machine(ctx = {}) {
582
382
  }, ctx.positioning),
583
383
  currentPlacement: void 0
584
384
  }, ctx), {
385
+ focusTriggerOnClose: true,
585
386
  renderedElements: {
586
387
  title: true,
587
388
  description: true,
@@ -595,63 +396,54 @@ function machine(ctx = {}) {
595
396
  unknown: {
596
397
  on: {
597
398
  SETUP: {
598
- target: ctx.open ? "open" : "closed",
599
- actions: ["setupDocument", "checkRenderedElements"]
399
+ target: ctx.defaultOpen ? "open" : "closed",
400
+ actions: "checkRenderedElements"
600
401
  }
601
402
  }
602
403
  },
603
404
  closed: {
604
- entry: ["clearPointerDown", "invokeOnClose"],
405
+ entry: "invokeOnClose",
605
406
  on: {
606
- TRIGGER_CLICK: "open",
407
+ TOGGLE: "open",
607
408
  OPEN: "open"
608
409
  }
609
410
  },
610
411
  open: {
611
412
  activities: [
612
- "trackPointerDown",
613
413
  "trapFocus",
614
414
  "preventScroll",
615
415
  "hideContentBelow",
616
- "disableOutsidePointerEvents",
617
- "computePlacement"
416
+ "computePlacement",
417
+ "trackInteractionOutside",
418
+ "trackTabKeyDown"
618
419
  ],
619
420
  entry: ["setInitialFocus", "invokeOnOpen"],
620
421
  on: {
621
- CLOSE: {
622
- target: "closed",
623
- actions: "focusTrigger"
624
- },
625
- TRIGGER_CLICK: {
626
- target: "closed",
627
- actions: "focusTrigger"
628
- },
629
- ESCAPE: {
630
- guard: "closeOnEsc",
631
- target: "closed",
632
- actions: "focusTrigger"
633
- },
634
- TAB: {
635
- guard: and("isLastTabbableElement", "closeOnBlur", "portalled"),
422
+ CLOSE: "closed",
423
+ REQUEST_CLOSE: {
636
424
  target: "closed",
637
- actions: "focusNextTabbableElementAfterTrigger"
425
+ actions: "focusTriggerIfNeeded"
638
426
  },
639
- SHIFT_TAB: {
640
- guard: and(or("isFirstTabbableElement", "isContentFocused"), "closeOnBlur", "portalled"),
641
- target: "closed",
642
- actions: "focusTrigger"
427
+ TOGGLE: "closed",
428
+ TRIGGER_BLUR: {
429
+ guard: not("isRelatedTargetWithinContent"),
430
+ target: "closed"
643
431
  },
644
- INTERACT_OUTSIDE: [
432
+ TAB: [
645
433
  {
646
- guard: and("closeOnBlur", "isRelatedTargetFocusable"),
647
- target: "closed"
434
+ guard: and("isTriggerFocused", "portalled"),
435
+ actions: "focusFirstTabbableElement"
648
436
  },
649
437
  {
650
- guard: "closeOnBlur",
438
+ guard: and("isLastTabbableElement", "closeOnInteractOutside", "portalled"),
651
439
  target: "closed",
652
- actions: "focusTrigger"
440
+ actions: "focusNextTabbableElementAfterTrigger"
653
441
  }
654
- ]
442
+ ],
443
+ SHIFT_TAB: {
444
+ guard: and(or("isFirstTabbableElement", "isContentFocused"), "portalled"),
445
+ actions: "focusTriggerIfNeeded"
446
+ }
655
447
  }
656
448
  }
657
449
  }
@@ -671,32 +463,70 @@ function machine(ctx = {}) {
671
463
  }
672
464
  }));
673
465
  },
674
- trackPointerDown(ctx2) {
675
- return trackPointerDown(dom.getDoc(ctx2), (el) => {
676
- ctx2.pointerdownNode = (0, import_core.ref)(el);
466
+ trackInteractionOutside(ctx2, _evt, { send }) {
467
+ return (0, import_dismissable.trackDismissableElement)(dom.getContentEl(ctx2), {
468
+ pointerBlocking: ctx2.modal,
469
+ exclude: dom.getTriggerEl(ctx2),
470
+ onEscapeKeyDown(event) {
471
+ var _a;
472
+ (_a = ctx2.onEscapeKeyDown) == null ? void 0 : _a.call(ctx2, event);
473
+ if (ctx2.closeOnEsc)
474
+ return;
475
+ ctx2.focusTriggerOnClose = true;
476
+ event.preventDefault();
477
+ },
478
+ onInteractOutside(event) {
479
+ var _a;
480
+ (_a = ctx2.onInteractOutside) == null ? void 0 : _a.call(ctx2, event);
481
+ if (event.defaultPrevented)
482
+ return;
483
+ ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
484
+ if (!ctx2.closeOnInteractOutside) {
485
+ event.preventDefault();
486
+ }
487
+ },
488
+ onPointerDownOutside(event) {
489
+ var _a;
490
+ (_a = ctx2.onPointerDownOutside) == null ? void 0 : _a.call(ctx2, event);
491
+ },
492
+ onFocusOutside(event) {
493
+ var _a;
494
+ (_a = ctx2.onFocusOutside) == null ? void 0 : _a.call(ctx2, event);
495
+ if (ctx2.currentPortalled) {
496
+ event.preventDefault();
497
+ }
498
+ },
499
+ onDismiss() {
500
+ send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
501
+ }
677
502
  });
678
503
  },
679
- disableOutsidePointerEvents(ctx2) {
680
- const el = dom.getContentEl(ctx2);
681
- return preventBodyPointerEvents(el, {
682
- document: dom.getDoc(ctx2),
683
- disabled: !ctx2.modal
684
- });
504
+ trackTabKeyDown(ctx2, _evt, { send }) {
505
+ if (ctx2.modal)
506
+ return;
507
+ return addDomEvent(dom.getWin(ctx2), "keydown", (event) => {
508
+ const isTabKey = event.key === "Tab" && !isModifiedEvent(event);
509
+ if (!isTabKey)
510
+ return;
511
+ send({
512
+ type: event.shiftKey ? "SHIFT_TAB" : "TAB",
513
+ preventDefault: () => event.preventDefault()
514
+ });
515
+ }, true);
685
516
  },
686
517
  hideContentBelow(ctx2) {
687
518
  if (!ctx2.modal)
688
519
  return;
689
- let unhide;
520
+ let cleanup;
690
521
  nextTick(() => {
691
- unhide = (0, import_aria_hidden.ariaHidden)([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
522
+ cleanup = (0, import_aria_hidden.ariaHidden)([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
692
523
  });
693
- return () => unhide == null ? void 0 : unhide();
524
+ return () => cleanup == null ? void 0 : cleanup();
694
525
  },
695
526
  preventScroll(ctx2) {
696
- return (0, import_remove_scroll.preventBodyScroll)({
697
- disabled: !ctx2.modal,
698
- document: dom.getDoc(ctx2)
699
- });
527
+ if (!ctx2.modal)
528
+ return;
529
+ return (0, import_remove_scroll.preventBodyScroll)(dom.getDoc(ctx2));
700
530
  },
701
531
  trapFocus(ctx2) {
702
532
  if (!ctx2.modal)
@@ -723,13 +553,11 @@ function machine(ctx = {}) {
723
553
  }
724
554
  },
725
555
  guards: {
726
- closeOnEsc: (ctx2) => !!ctx2.closeOnEsc,
727
- autoFocus: (ctx2) => !!ctx2.autoFocus,
728
- modal: (ctx2) => !!ctx2.modal,
729
- portalled: (ctx2) => !!ctx2.portalled,
730
- isRelatedTargetFocusable: (_ctx, evt) => evt.focusable,
731
- closeOnBlur: (ctx2) => !!ctx2.closeOnBlur,
556
+ portalled: (ctx2) => ctx2.currentPortalled,
557
+ isRelatedTargetWithinContent: (ctx2, evt) => contains(dom.getContentEl(ctx2), evt.target),
558
+ closeOnInteractOutside: (ctx2) => !!ctx2.closeOnInteractOutside,
732
559
  isContentFocused: (ctx2) => dom.getContentEl(ctx2) === dom.getActiveEl(ctx2),
560
+ isTriggerFocused: (ctx2) => dom.getTriggerEl(ctx2) === dom.getActiveEl(ctx2),
733
561
  isFirstTabbableElement: (ctx2) => dom.getFirstTabbableEl(ctx2) === dom.getActiveEl(ctx2),
734
562
  isLastTabbableElement: (ctx2) => dom.getLastTabbableEl(ctx2) === dom.getActiveEl(ctx2)
735
563
  },
@@ -743,48 +571,44 @@ function machine(ctx = {}) {
743
571
  });
744
572
  });
745
573
  },
746
- setupDocument(ctx2, evt) {
747
- if (evt.doc)
748
- ctx2.doc = (0, import_core.ref)(evt.doc);
749
- if (evt.root)
750
- ctx2.rootNode = (0, import_core.ref)(evt.root);
751
- ctx2.uid = evt.id;
752
- },
753
- clearPointerDown(ctx2) {
754
- ctx2.pointerdownNode = null;
755
- },
756
574
  setInitialFocus(ctx2) {
757
575
  raf(() => {
758
576
  var _a;
759
577
  (_a = dom.getInitialFocusEl(ctx2)) == null ? void 0 : _a.focus();
760
578
  });
761
579
  },
762
- focusTrigger(ctx2) {
580
+ focusTriggerIfNeeded(ctx2) {
581
+ if (!ctx2.focusTriggerOnClose)
582
+ return;
763
583
  raf(() => {
764
584
  var _a;
765
- (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
585
+ return (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
766
586
  });
767
587
  },
588
+ focusFirstTabbableElement(ctx2, evt) {
589
+ var _a;
590
+ evt.preventDefault();
591
+ (_a = dom.getFirstTabbableEl(ctx2)) == null ? void 0 : _a.focus();
592
+ },
768
593
  invokeOnOpen(ctx2, evt) {
769
594
  var _a;
770
595
  if (evt.type !== "SETUP") {
771
- (_a = ctx2.onOpen) == null ? void 0 : _a.call(ctx2);
596
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, true);
772
597
  }
773
598
  },
774
599
  invokeOnClose(ctx2, evt) {
775
600
  var _a;
776
601
  if (evt.type !== "SETUP") {
777
- (_a = ctx2.onClose) == null ? void 0 : _a.call(ctx2);
602
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, false);
778
603
  }
779
604
  },
780
605
  focusNextTabbableElementAfterTrigger(ctx2, evt) {
781
606
  const content = dom.getContentEl(ctx2);
782
- const doc = dom.getDoc(ctx2);
783
607
  const button = dom.getTriggerEl(ctx2);
784
608
  if (!content || !button)
785
609
  return;
786
610
  const lastTabbable = dom.getLastTabbableEl(ctx2);
787
- if (lastTabbable !== doc.activeElement)
611
+ if (lastTabbable !== dom.getActiveEl(ctx2))
788
612
  return;
789
613
  let tabbables = dom.getDocTabbableEls(ctx2);
790
614
  let elementAfterTrigger = next(tabbables, tabbables.indexOf(button), { loop: false });
@@ -800,4 +624,3 @@ function machine(ctx = {}) {
800
624
  }
801
625
  });
802
626
  }
803
- //# sourceMappingURL=index.js.map