@zag-js/popover 0.1.8 → 0.1.11

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
@@ -1,35 +1,116 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __defProps = Object.defineProperties;
4
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __spreadValues = (a, b) => {
10
- for (var prop in b || (b = {}))
11
- if (__hasOwnProp.call(b, prop))
12
- __defNormalProp(a, prop, b[prop]);
13
- if (__getOwnPropSymbols)
14
- for (var prop of __getOwnPropSymbols(b)) {
15
- if (__propIsEnum.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- }
18
- return a;
19
- };
20
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
-
22
1
  // ../../utilities/dom/dist/index.mjs
23
2
  var dataAttr = (guard) => {
24
3
  return guard ? "" : void 0;
25
4
  };
26
- var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
27
- var isLeftClick = (v) => v.button === 0;
28
5
  var runIfFn = (v, ...a) => {
29
6
  const res = typeof v === "function" ? v(...a) : v;
30
- return res != null ? res : void 0;
7
+ return res ?? void 0;
31
8
  };
32
- var pipe = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
9
+ var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
10
+ function isDocument(el) {
11
+ return el.nodeType === Node.DOCUMENT_NODE;
12
+ }
13
+ function isWindow(value) {
14
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
15
+ }
16
+ function isFrame(element) {
17
+ return element.localName === "iframe";
18
+ }
19
+ function getDocument(el) {
20
+ if (isWindow(el))
21
+ return el.document;
22
+ if (isDocument(el))
23
+ return el;
24
+ return (el == null ? void 0 : el.ownerDocument) ?? document;
25
+ }
26
+ function defineDomHelpers(helpers) {
27
+ const dom2 = {
28
+ getRootNode: (ctx) => {
29
+ var _a;
30
+ return ((_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) ?? document;
31
+ },
32
+ getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
33
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
34
+ getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
35
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
36
+ };
37
+ return {
38
+ ...dom2,
39
+ ...helpers
40
+ };
41
+ }
42
+ function contains(parent, child) {
43
+ if (!parent)
44
+ return false;
45
+ return parent === child || isHTMLElement(parent) && isHTMLElement(child) && parent.contains(child);
46
+ }
47
+ function isHTMLElement(v) {
48
+ return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
49
+ }
50
+ function isVisible(el) {
51
+ if (!isHTMLElement(el))
52
+ return false;
53
+ return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
54
+ }
55
+ var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
56
+ function hasNegativeTabIndex(element) {
57
+ const tabIndex = parseInt(element.getAttribute("tabindex") || "0", 10);
58
+ return tabIndex < 0;
59
+ }
60
+ 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";
61
+ var getFocusables = (container, includeContainer = false) => {
62
+ if (!container)
63
+ return [];
64
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
65
+ const include = includeContainer == true || includeContainer == "if-empty" && elements.length === 0;
66
+ if (include && isHTMLElement(container) && isFocusable(container)) {
67
+ elements.unshift(container);
68
+ }
69
+ const focusableElements = elements.filter(isFocusable);
70
+ focusableElements.forEach((element, i) => {
71
+ if (isFrame(element) && element.contentDocument) {
72
+ const frameBody = element.contentDocument.body;
73
+ focusableElements.splice(i, 1, ...getFocusables(frameBody));
74
+ }
75
+ });
76
+ return focusableElements;
77
+ };
78
+ function isFocusable(element) {
79
+ if (!element)
80
+ return false;
81
+ return element.matches(focusableSelector) && isVisible(element);
82
+ }
83
+ function getTabbables(container, includeContainer) {
84
+ if (!container)
85
+ return [];
86
+ const elements = Array.from(container.querySelectorAll(focusableSelector));
87
+ const tabbableElements = elements.filter(isTabbable);
88
+ if (includeContainer && isTabbable(container)) {
89
+ tabbableElements.unshift(container);
90
+ }
91
+ tabbableElements.forEach((element, i) => {
92
+ if (isFrame(element) && element.contentDocument) {
93
+ const frameBody = element.contentDocument.body;
94
+ const allFrameTabbable = getTabbables(frameBody);
95
+ tabbableElements.splice(i, 1, ...allFrameTabbable);
96
+ }
97
+ });
98
+ if (!tabbableElements.length && includeContainer) {
99
+ return elements;
100
+ }
101
+ return tabbableElements;
102
+ }
103
+ function isTabbable(el) {
104
+ return isFocusable(el) && !hasNegativeTabIndex(el);
105
+ }
106
+ function getFirstTabbable(container, includeContainer) {
107
+ const [first] = getTabbables(container, includeContainer);
108
+ return first || null;
109
+ }
110
+ function getLastTabbable(container, includeContainer) {
111
+ const elements = getTabbables(container, includeContainer);
112
+ return elements[elements.length - 1] || null;
113
+ }
33
114
  var isRef = (v) => hasProp(v, "current");
34
115
  function addDomEvent(target, eventName, handler, options) {
35
116
  const node = isRef(target) ? target.current : runIfFn(target);
@@ -57,179 +138,11 @@ function raf(fn) {
57
138
  globalThis.cancelAnimationFrame(id);
58
139
  };
59
140
  }
60
- var changeCount = 0;
61
- var originalBodyPointerEvents;
62
- function preventBodyPointerEvents(el, opts = {}) {
63
- const { disabled = false, document: docProp } = opts;
64
- const doc = docProp || document;
65
- let isTouchOrPenPressed = false;
66
- let isLeftClickPressed = false;
67
- function listen() {
68
- const onPointerDown = (event) => {
69
- const isMouse = event.pointerType === "mouse";
70
- isTouchOrPenPressed = !isMouse;
71
- isLeftClickPressed = isMouse && isLeftClick(event);
72
- };
73
- const onPointerUp = () => {
74
- isTouchOrPenPressed = false;
75
- isLeftClickPressed = false;
76
- };
77
- return pipe(addDomEvent(doc, "pointerdown", onPointerDown), addDomEvent(doc, "pointerup", onPointerUp));
78
- }
79
- function reset() {
80
- changeCount--;
81
- if (changeCount === 0) {
82
- doc.body.style.pointerEvents = originalBodyPointerEvents;
83
- }
84
- if (el) {
85
- el.style.pointerEvents = "";
86
- }
87
- }
88
- function apply() {
89
- if (disabled)
90
- return;
91
- if (changeCount === 0) {
92
- originalBodyPointerEvents = doc.body.style.pointerEvents;
93
- }
94
- doc.body.style.pointerEvents = "none";
95
- if (el) {
96
- el.style.pointerEvents = "auto";
97
- }
98
- changeCount++;
99
- return function() {
100
- if (isTouchOrPenPressed) {
101
- addDomEvent(doc, "click", reset, { once: true });
102
- } else if (isLeftClickPressed) {
103
- addDomEvent(doc, "pointerup", reset, { once: true });
104
- } else {
105
- reset();
106
- }
107
- };
108
- }
109
- const cleanups = [];
110
- cleanups.push(apply());
111
- nextTick(() => {
112
- cleanups.push(listen());
113
- });
114
- return function() {
115
- cleanups.forEach((cleanup) => cleanup == null ? void 0 : cleanup());
116
- };
117
- }
118
- function getStyleCache() {
119
- ;
120
- globalThis.__styleCache__ = globalThis.__styleCache__ || /* @__PURE__ */ new WeakMap();
121
- return globalThis.__styleCache__;
122
- }
123
- function getComputedStyle(el) {
124
- var _a;
125
- if (!el)
126
- return {};
127
- const cache = getStyleCache();
128
- let style = cache.get(el);
129
- if (!style) {
130
- const win = (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
131
- style = win.getComputedStyle(el);
132
- cache.set(el, style);
133
- }
134
- return style;
135
- }
136
- function contains(parent, child) {
137
- if (!parent)
138
- return false;
139
- return parent === child || isHTMLElement(parent) && isHTMLElement(child) && parent.contains(child);
140
- }
141
- function isHTMLElement(v) {
142
- return typeof v === "object" && (v == null ? void 0 : v.nodeType) === Node.ELEMENT_NODE && typeof (v == null ? void 0 : v.nodeName) === "string";
143
- }
144
- var isDisabled = (el) => {
145
- return (el == null ? void 0 : el.getAttribute("disabled")) != null || !!(el == null ? void 0 : el.getAttribute("aria-disabled")) === true;
146
- };
147
- function validateBlur(event, opts) {
148
- var _a;
149
- const exclude = Array.isArray(opts.exclude) ? opts.exclude : [opts.exclude];
150
- const relatedTarget = (_a = event.relatedTarget) != null ? _a : opts.fallback;
151
- return exclude.every((el) => !(el == null ? void 0 : el.contains(relatedTarget)));
152
- }
153
- var focusableSelector = /* @__PURE__ */ [
154
- "input:not([disabled]):not([type=hidden])",
155
- "select:not([disabled])",
156
- "textarea:not([disabled])",
157
- "button:not([disabled])",
158
- "embed",
159
- "iframe",
160
- "object",
161
- "a[href]",
162
- "area[href]",
163
- "[tabindex]",
164
- "audio[controls]",
165
- "video[controls]",
166
- "*[tabindex]:not([aria-disabled])",
167
- "[contenteditable]:not([contenteditable=false])",
168
- "details > summary:first-of-type"
169
- ].join(",");
170
- function isHidden(el, until) {
171
- const style = getComputedStyle(el);
172
- if (!el || style.getPropertyValue("visibility") === "hidden")
173
- return true;
174
- while (el) {
175
- if (until != null && el === until)
176
- return false;
177
- if (style.getPropertyValue("display") === "none")
178
- return true;
179
- el = el.parentElement;
180
- }
181
- return false;
182
- }
183
- var getFocusables = (el, includeContainer = false) => {
184
- if (!el)
185
- return [];
186
- let els = Array.from(el.querySelectorAll(focusableSelector));
187
- const shouldAddContainer = includeContainer == true || includeContainer == "if-empty" && els.length === 0;
188
- if (shouldAddContainer && isHTMLElement(el)) {
189
- els.unshift(el);
190
- }
191
- return els.filter((el2) => isFocusable(el2) && !isHidden(el2));
192
- };
193
- var isFocusable = (el) => {
194
- if (!isHTMLElement(el) || isHidden(el) || isDisabled(el))
195
- return false;
196
- return el == null ? void 0 : el.matches(focusableSelector);
197
- };
198
- var getTabbables = (el, includeContainer = false) => {
199
- if (!el)
200
- return [];
201
- return getFocusables(el, includeContainer).filter(isTabbable);
202
- };
203
- var isTabbable = (el) => {
204
- return isFocusable(el) && !isDisabled(el) && !isHidden(el);
205
- };
206
- function trackPointerDown(doc, onPointerDown) {
207
- var _a;
208
- const win = (_a = doc.defaultView) != null ? _a : window;
209
- const fn = (event) => {
210
- if (event.target instanceof win.HTMLElement) {
211
- onPointerDown(event.target);
212
- }
213
- };
214
- return addDomEvent(doc, "pointerdown", fn);
215
- }
216
141
 
217
142
  // src/popover.connect.ts
218
143
  import { getPlacementStyles } from "@zag-js/popper";
219
144
 
220
- // ../../types/dist/index.mjs
221
- function createNormalizer(fn) {
222
- return new Proxy({}, {
223
- get() {
224
- return fn;
225
- }
226
- });
227
- }
228
- var normalizeProp = createNormalizer((v) => v);
229
-
230
145
  // ../../utilities/core/dist/index.mjs
231
- var first = (v) => v[0];
232
- var last = (v) => v[v.length - 1];
233
146
  function nextIndex(v, idx, opts = {}) {
234
147
  const { step = 1, loop = true } = opts;
235
148
  const next2 = idx + step;
@@ -248,59 +161,50 @@ function next(v, idx, opts = {}) {
248
161
  }
249
162
  var runIfFn2 = (v, ...a) => {
250
163
  const res = typeof v === "function" ? v(...a) : v;
251
- return res != null ? res : void 0;
164
+ return res ?? void 0;
252
165
  };
253
- var cast = (v) => v;
254
166
 
255
167
  // src/popover.dom.ts
256
- var dom = {
257
- getDoc: (ctx) => {
258
- var _a;
259
- return (_a = ctx.doc) != null ? _a : document;
260
- },
168
+ var dom = defineDomHelpers({
261
169
  getActiveEl: (ctx) => dom.getDoc(ctx).activeElement,
262
- getRootNode: (ctx) => {
263
- var _a;
264
- return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
265
- },
266
170
  getAnchorId: (ctx) => {
267
- var _a, _b;
268
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.anchor) != null ? _b : `popover:${ctx.uid}:anchor`;
171
+ var _a;
172
+ return ((_a = ctx.ids) == null ? void 0 : _a.anchor) ?? `popover:${ctx.id}:anchor`;
269
173
  },
270
174
  getTriggerId: (ctx) => {
271
- var _a, _b;
272
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.trigger) != null ? _b : `popover:${ctx.uid}:trigger`;
175
+ var _a;
176
+ return ((_a = ctx.ids) == null ? void 0 : _a.trigger) ?? `popover:${ctx.id}:trigger`;
273
177
  },
274
178
  getContentId: (ctx) => {
275
- var _a, _b;
276
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.content) != null ? _b : `popover:${ctx.uid}:content`;
179
+ var _a;
180
+ return ((_a = ctx.ids) == null ? void 0 : _a.content) ?? `popover:${ctx.id}:content`;
277
181
  },
278
- getPositionerId: (ctx) => `popover:${ctx.uid}:popper`,
279
- getArrowId: (ctx) => `popover:${ctx.uid}:arrow`,
182
+ getPositionerId: (ctx) => `popover:${ctx.id}:popper`,
183
+ getArrowId: (ctx) => `popover:${ctx.id}:arrow`,
280
184
  getTitleId: (ctx) => {
281
- var _a, _b;
282
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.title) != null ? _b : `popover:${ctx.uid}:title`;
185
+ var _a;
186
+ return ((_a = ctx.ids) == null ? void 0 : _a.title) ?? `popover:${ctx.id}:title`;
283
187
  },
284
188
  getDescriptionId: (ctx) => {
285
- var _a, _b;
286
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.description) != null ? _b : `popover:${ctx.uid}:desc`;
189
+ var _a;
190
+ return ((_a = ctx.ids) == null ? void 0 : _a.description) ?? `popover:${ctx.id}:desc`;
287
191
  },
288
192
  getCloseButtonId: (ctx) => {
289
- var _a, _b;
290
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.closeBtn) != null ? _b : `popover:${ctx.uid}:close-button`;
193
+ var _a;
194
+ return ((_a = ctx.ids) == null ? void 0 : _a.closeBtn) ?? `popover:${ctx.id}:close-button`;
291
195
  },
292
- getAnchorEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getAnchorId(ctx)),
293
- getTriggerEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getTriggerId(ctx)),
294
- getContentEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getContentId(ctx)),
295
- getPositionerEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getPositionerId(ctx)),
296
- getTitleEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getTitleId(ctx)),
297
- getDescriptionEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getDescriptionId(ctx)),
196
+ getAnchorEl: (ctx) => dom.getById(ctx, dom.getAnchorId(ctx)),
197
+ getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
198
+ getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
199
+ getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
200
+ getTitleEl: (ctx) => dom.getById(ctx, dom.getTitleId(ctx)),
201
+ getDescriptionEl: (ctx) => dom.getById(ctx, dom.getDescriptionId(ctx)),
298
202
  getFocusableEls: (ctx) => getFocusables(dom.getContentEl(ctx)),
299
203
  getFirstFocusableEl: (ctx) => dom.getFocusableEls(ctx)[0],
300
- getDocTabbableEls: (ctx) => getTabbables(cast(dom.getDoc(ctx))),
204
+ getDocTabbableEls: (ctx) => getTabbables(dom.getDoc(ctx).body),
301
205
  getTabbableEls: (ctx) => getTabbables(dom.getContentEl(ctx), "if-empty"),
302
- getFirstTabbableEl: (ctx) => first(dom.getTabbableEls(ctx)),
303
- getLastTabbableEl: (ctx) => last(dom.getTabbableEls(ctx)),
206
+ getFirstTabbableEl: (ctx) => getFirstTabbable(dom.getContentEl(ctx), "if-empty"),
207
+ getLastTabbableEl: (ctx) => getLastTabbable(dom.getContentEl(ctx), "if-empty"),
304
208
  getInitialFocusEl: (ctx) => {
305
209
  let el = runIfFn2(ctx.initialFocusEl);
306
210
  if (!el && ctx.autoFocus)
@@ -309,19 +213,20 @@ var dom = {
309
213
  el = dom.getContentEl(ctx);
310
214
  return el;
311
215
  }
312
- };
216
+ });
313
217
 
314
218
  // src/popover.connect.ts
315
- function connect(state, send, normalize = normalizeProp) {
219
+ function connect(state, send, normalize) {
316
220
  const isOpen = state.matches("open");
317
- const pointerdownNode = state.context.pointerdownNode;
318
221
  const currentPlacement = state.context.currentPlacement;
222
+ const portalled = state.context.currentPortalled;
223
+ const rendered = state.context.renderedElements;
319
224
  const popperStyles = getPlacementStyles({
320
225
  measured: !!state.context.isPlacementComplete,
321
226
  placement: currentPlacement
322
227
  });
323
228
  return {
324
- portalled: state.context.currentPortalled,
229
+ portalled,
325
230
  isOpen,
326
231
  open() {
327
232
  send("OPEN");
@@ -352,12 +257,10 @@ function connect(state, send, normalize = normalizeProp) {
352
257
  "data-expanded": dataAttr(isOpen),
353
258
  "aria-controls": dom.getContentId(state.context),
354
259
  onClick() {
355
- send("TRIGGER_CLICK");
260
+ send("TOGGLE");
356
261
  },
357
- onKeyDown(event) {
358
- if (event.key === "Escape") {
359
- send("ESCAPE");
360
- }
262
+ onBlur(event) {
263
+ send({ type: "TRIGGER_BLUR", target: event.relatedTarget });
361
264
  }
362
265
  }),
363
266
  positionerProps: normalize.element({
@@ -372,34 +275,9 @@ function connect(state, send, normalize = normalizeProp) {
372
275
  role: "dialog",
373
276
  hidden: !isOpen,
374
277
  "data-expanded": dataAttr(isOpen),
375
- "aria-labelledby": state.context.renderedElements.title ? dom.getTitleId(state.context) : void 0,
376
- "aria-describedby": state.context.renderedElements.description ? dom.getDescriptionId(state.context) : void 0,
377
- "data-placement": currentPlacement,
378
- onKeyDown(event) {
379
- const keyMap = {
380
- Escape(event2) {
381
- send("ESCAPE");
382
- event2.stopPropagation();
383
- },
384
- Tab(event2) {
385
- const type = event2.shiftKey ? "SHIFT_TAB" : "TAB";
386
- send({ type, preventDefault: () => event2.preventDefault() });
387
- }
388
- };
389
- const exec = keyMap[event.key];
390
- exec == null ? void 0 : exec(event);
391
- },
392
- onBlur(event) {
393
- var _a;
394
- const isValidBlur = validateBlur(event, {
395
- exclude: [dom.getTriggerEl(state.context), dom.getContentEl(state.context)],
396
- fallback: pointerdownNode
397
- });
398
- if (isValidBlur) {
399
- const el = (_a = event.relatedTarget) != null ? _a : pointerdownNode;
400
- send({ type: "INTERACT_OUTSIDE", focusable: isFocusable(el) });
401
- }
402
- }
278
+ "aria-labelledby": rendered.title ? dom.getTitleId(state.context) : void 0,
279
+ "aria-describedby": rendered.description ? dom.getDescriptionId(state.context) : void 0,
280
+ "data-placement": currentPlacement
403
281
  }),
404
282
  titleProps: normalize.element({
405
283
  "data-part": "title",
@@ -415,7 +293,7 @@ function connect(state, send, normalize = normalizeProp) {
415
293
  type: "button",
416
294
  "aria-label": "close",
417
295
  onClick() {
418
- send("CLOSE");
296
+ send("REQUEST_CLOSE");
419
297
  }
420
298
  })
421
299
  };
@@ -423,32 +301,34 @@ function connect(state, send, normalize = normalizeProp) {
423
301
 
424
302
  // src/popover.machine.ts
425
303
  import { ariaHidden } from "@zag-js/aria-hidden";
426
- import { createMachine, guards, ref } from "@zag-js/core";
304
+ import { createMachine, guards } from "@zag-js/core";
305
+ import { trackDismissableElement } from "@zag-js/dismissable";
427
306
  import { getPlacement } from "@zag-js/popper";
428
307
  import { preventBodyScroll } from "@zag-js/remove-scroll";
429
308
  import { createFocusTrap } from "focus-trap";
430
- var { and, or } = guards;
431
- function machine(ctx = {}) {
309
+ var { and, or, not } = guards;
310
+ function machine(ctx) {
432
311
  return createMachine({
433
312
  id: "popover",
434
313
  initial: "unknown",
435
- context: __spreadProps(__spreadValues({
436
- uid: "",
437
- closeOnBlur: true,
314
+ context: {
315
+ closeOnInteractOutside: true,
438
316
  closeOnEsc: true,
439
317
  autoFocus: true,
440
318
  modal: false,
441
- positioning: __spreadValues({
442
- placement: "bottom"
443
- }, ctx.positioning),
444
- currentPlacement: void 0
445
- }, ctx), {
319
+ positioning: {
320
+ placement: "bottom",
321
+ ...ctx.positioning
322
+ },
323
+ currentPlacement: void 0,
324
+ ...ctx,
325
+ focusTriggerOnClose: true,
446
326
  renderedElements: {
447
327
  title: true,
448
328
  description: true,
449
329
  anchor: false
450
330
  }
451
- }),
331
+ },
452
332
  computed: {
453
333
  currentPortalled: (ctx2) => !!ctx2.modal || !!ctx2.portalled
454
334
  },
@@ -456,63 +336,54 @@ function machine(ctx = {}) {
456
336
  unknown: {
457
337
  on: {
458
338
  SETUP: {
459
- target: ctx.open ? "open" : "closed",
460
- actions: ["setupDocument", "checkRenderedElements"]
339
+ target: ctx.defaultOpen ? "open" : "closed",
340
+ actions: "checkRenderedElements"
461
341
  }
462
342
  }
463
343
  },
464
344
  closed: {
465
- entry: ["clearPointerDown", "invokeOnClose"],
345
+ entry: "invokeOnClose",
466
346
  on: {
467
- TRIGGER_CLICK: "open",
347
+ TOGGLE: "open",
468
348
  OPEN: "open"
469
349
  }
470
350
  },
471
351
  open: {
472
352
  activities: [
473
- "trackPointerDown",
474
353
  "trapFocus",
475
354
  "preventScroll",
476
355
  "hideContentBelow",
477
- "disableOutsidePointerEvents",
478
- "computePlacement"
356
+ "computePlacement",
357
+ "trackInteractionOutside",
358
+ "trackTabKeyDown"
479
359
  ],
480
360
  entry: ["setInitialFocus", "invokeOnOpen"],
481
361
  on: {
482
- CLOSE: {
362
+ CLOSE: "closed",
363
+ REQUEST_CLOSE: {
483
364
  target: "closed",
484
- actions: "focusTrigger"
365
+ actions: "focusTriggerIfNeeded"
485
366
  },
486
- TRIGGER_CLICK: {
487
- target: "closed",
488
- actions: "focusTrigger"
367
+ TOGGLE: "closed",
368
+ TRIGGER_BLUR: {
369
+ guard: not("isRelatedTargetWithinContent"),
370
+ target: "closed"
489
371
  },
490
- ESCAPE: {
491
- guard: "closeOnEsc",
492
- target: "closed",
493
- actions: "focusTrigger"
494
- },
495
- TAB: {
496
- guard: and("isLastTabbableElement", "closeOnBlur", "portalled"),
497
- target: "closed",
498
- actions: "focusNextTabbableElementAfterTrigger"
499
- },
500
- SHIFT_TAB: {
501
- guard: and(or("isFirstTabbableElement", "isContentFocused"), "closeOnBlur", "portalled"),
502
- target: "closed",
503
- actions: "focusTrigger"
504
- },
505
- INTERACT_OUTSIDE: [
372
+ TAB: [
506
373
  {
507
- guard: and("closeOnBlur", "isRelatedTargetFocusable"),
508
- target: "closed"
374
+ guard: and("isTriggerFocused", "portalled"),
375
+ actions: "focusFirstTabbableElement"
509
376
  },
510
377
  {
511
- guard: "closeOnBlur",
378
+ guard: and("isLastTabbableElement", "closeOnInteractOutside", "portalled"),
512
379
  target: "closed",
513
- actions: "focusTrigger"
380
+ actions: "focusNextTabbableElementAfterTrigger"
514
381
  }
515
- ]
382
+ ],
383
+ SHIFT_TAB: {
384
+ guard: and(or("isFirstTabbableElement", "isContentFocused"), "portalled"),
385
+ actions: "focusTriggerIfNeeded"
386
+ }
516
387
  }
517
388
  }
518
389
  }
@@ -521,7 +392,8 @@ function machine(ctx = {}) {
521
392
  computePlacement(ctx2) {
522
393
  ctx2.currentPlacement = ctx2.positioning.placement;
523
394
  const anchorEl = ctx2.renderedElements.anchor ? dom.getAnchorEl(ctx2) : dom.getTriggerEl(ctx2);
524
- return getPlacement(anchorEl, dom.getPositionerEl(ctx2), __spreadProps(__spreadValues({}, ctx2.positioning), {
395
+ return getPlacement(anchorEl, dom.getPositionerEl(ctx2), {
396
+ ...ctx2.positioning,
525
397
  onComplete(data) {
526
398
  ctx2.currentPlacement = data.placement;
527
399
  ctx2.isPlacementComplete = true;
@@ -530,34 +402,72 @@ function machine(ctx = {}) {
530
402
  ctx2.currentPlacement = void 0;
531
403
  ctx2.isPlacementComplete = false;
532
404
  }
533
- }));
534
- },
535
- trackPointerDown(ctx2) {
536
- return trackPointerDown(dom.getDoc(ctx2), (el) => {
537
- ctx2.pointerdownNode = ref(el);
538
405
  });
539
406
  },
540
- disableOutsidePointerEvents(ctx2) {
541
- const el = dom.getContentEl(ctx2);
542
- return preventBodyPointerEvents(el, {
543
- document: dom.getDoc(ctx2),
544
- disabled: !ctx2.modal
407
+ trackInteractionOutside(ctx2, _evt, { send }) {
408
+ return trackDismissableElement(dom.getContentEl(ctx2), {
409
+ pointerBlocking: ctx2.modal,
410
+ exclude: dom.getTriggerEl(ctx2),
411
+ onEscapeKeyDown(event) {
412
+ var _a;
413
+ (_a = ctx2.onEscapeKeyDown) == null ? void 0 : _a.call(ctx2, event);
414
+ if (ctx2.closeOnEsc)
415
+ return;
416
+ ctx2.focusTriggerOnClose = true;
417
+ event.preventDefault();
418
+ },
419
+ onInteractOutside(event) {
420
+ var _a;
421
+ (_a = ctx2.onInteractOutside) == null ? void 0 : _a.call(ctx2, event);
422
+ if (event.defaultPrevented)
423
+ return;
424
+ ctx2.focusTriggerOnClose = !(event.detail.focusable || event.detail.contextmenu);
425
+ if (!ctx2.closeOnInteractOutside) {
426
+ event.preventDefault();
427
+ }
428
+ },
429
+ onPointerDownOutside(event) {
430
+ var _a;
431
+ (_a = ctx2.onPointerDownOutside) == null ? void 0 : _a.call(ctx2, event);
432
+ },
433
+ onFocusOutside(event) {
434
+ var _a;
435
+ (_a = ctx2.onFocusOutside) == null ? void 0 : _a.call(ctx2, event);
436
+ if (ctx2.currentPortalled) {
437
+ event.preventDefault();
438
+ }
439
+ },
440
+ onDismiss() {
441
+ send({ type: "REQUEST_CLOSE", src: "#interact-outside" });
442
+ }
545
443
  });
546
444
  },
445
+ trackTabKeyDown(ctx2, _evt, { send }) {
446
+ if (ctx2.modal)
447
+ return;
448
+ return addDomEvent(dom.getWin(ctx2), "keydown", (event) => {
449
+ const isTabKey = event.key === "Tab" && !isModifiedEvent(event);
450
+ if (!isTabKey)
451
+ return;
452
+ send({
453
+ type: event.shiftKey ? "SHIFT_TAB" : "TAB",
454
+ preventDefault: () => event.preventDefault()
455
+ });
456
+ }, true);
457
+ },
547
458
  hideContentBelow(ctx2) {
548
459
  if (!ctx2.modal)
549
460
  return;
550
- let unhide;
461
+ let cleanup;
551
462
  nextTick(() => {
552
- unhide = ariaHidden([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
463
+ cleanup = ariaHidden([dom.getContentEl(ctx2), dom.getTriggerEl(ctx2)]);
553
464
  });
554
- return () => unhide == null ? void 0 : unhide();
465
+ return () => cleanup == null ? void 0 : cleanup();
555
466
  },
556
467
  preventScroll(ctx2) {
557
- return preventBodyScroll({
558
- disabled: !ctx2.modal,
559
- document: dom.getDoc(ctx2)
560
- });
468
+ if (!ctx2.modal)
469
+ return;
470
+ return preventBodyScroll(dom.getDoc(ctx2));
561
471
  },
562
472
  trapFocus(ctx2) {
563
473
  if (!ctx2.modal)
@@ -577,20 +487,18 @@ function machine(ctx = {}) {
577
487
  });
578
488
  try {
579
489
  trap.activate();
580
- } catch (e) {
490
+ } catch {
581
491
  }
582
492
  });
583
493
  return () => trap == null ? void 0 : trap.deactivate();
584
494
  }
585
495
  },
586
496
  guards: {
587
- closeOnEsc: (ctx2) => !!ctx2.closeOnEsc,
588
- autoFocus: (ctx2) => !!ctx2.autoFocus,
589
- modal: (ctx2) => !!ctx2.modal,
590
- portalled: (ctx2) => !!ctx2.portalled,
591
- isRelatedTargetFocusable: (_ctx, evt) => evt.focusable,
592
- closeOnBlur: (ctx2) => !!ctx2.closeOnBlur,
497
+ portalled: (ctx2) => ctx2.currentPortalled,
498
+ isRelatedTargetWithinContent: (ctx2, evt) => contains(dom.getContentEl(ctx2), evt.target),
499
+ closeOnInteractOutside: (ctx2) => !!ctx2.closeOnInteractOutside,
593
500
  isContentFocused: (ctx2) => dom.getContentEl(ctx2) === dom.getActiveEl(ctx2),
501
+ isTriggerFocused: (ctx2) => dom.getTriggerEl(ctx2) === dom.getActiveEl(ctx2),
594
502
  isFirstTabbableElement: (ctx2) => dom.getFirstTabbableEl(ctx2) === dom.getActiveEl(ctx2),
595
503
  isLastTabbableElement: (ctx2) => dom.getLastTabbableEl(ctx2) === dom.getActiveEl(ctx2)
596
504
  },
@@ -604,48 +512,44 @@ function machine(ctx = {}) {
604
512
  });
605
513
  });
606
514
  },
607
- setupDocument(ctx2, evt) {
608
- if (evt.doc)
609
- ctx2.doc = ref(evt.doc);
610
- if (evt.root)
611
- ctx2.rootNode = ref(evt.root);
612
- ctx2.uid = evt.id;
613
- },
614
- clearPointerDown(ctx2) {
615
- ctx2.pointerdownNode = null;
616
- },
617
515
  setInitialFocus(ctx2) {
618
516
  raf(() => {
619
517
  var _a;
620
518
  (_a = dom.getInitialFocusEl(ctx2)) == null ? void 0 : _a.focus();
621
519
  });
622
520
  },
623
- focusTrigger(ctx2) {
521
+ focusTriggerIfNeeded(ctx2) {
522
+ if (!ctx2.focusTriggerOnClose)
523
+ return;
624
524
  raf(() => {
625
525
  var _a;
626
- (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
526
+ return (_a = dom.getTriggerEl(ctx2)) == null ? void 0 : _a.focus();
627
527
  });
628
528
  },
529
+ focusFirstTabbableElement(ctx2, evt) {
530
+ var _a;
531
+ evt.preventDefault();
532
+ (_a = dom.getFirstTabbableEl(ctx2)) == null ? void 0 : _a.focus();
533
+ },
629
534
  invokeOnOpen(ctx2, evt) {
630
535
  var _a;
631
536
  if (evt.type !== "SETUP") {
632
- (_a = ctx2.onOpen) == null ? void 0 : _a.call(ctx2);
537
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, true);
633
538
  }
634
539
  },
635
540
  invokeOnClose(ctx2, evt) {
636
541
  var _a;
637
542
  if (evt.type !== "SETUP") {
638
- (_a = ctx2.onClose) == null ? void 0 : _a.call(ctx2);
543
+ (_a = ctx2.onOpenChange) == null ? void 0 : _a.call(ctx2, false);
639
544
  }
640
545
  },
641
546
  focusNextTabbableElementAfterTrigger(ctx2, evt) {
642
547
  const content = dom.getContentEl(ctx2);
643
- const doc = dom.getDoc(ctx2);
644
548
  const button = dom.getTriggerEl(ctx2);
645
549
  if (!content || !button)
646
550
  return;
647
551
  const lastTabbable = dom.getLastTabbableEl(ctx2);
648
- if (lastTabbable !== doc.activeElement)
552
+ if (lastTabbable !== dom.getActiveEl(ctx2))
649
553
  return;
650
554
  let tabbables = dom.getDocTabbableEls(ctx2);
651
555
  let elementAfterTrigger = next(tabbables, tabbables.indexOf(button), { loop: false });