@zag-js/interact-outside 0.10.5 → 0.11.1

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.
@@ -0,0 +1,22 @@
1
+ type InteractOutsideHandlers = {
2
+ onPointerDownOutside?: (event: PointerDownOutsideEvent) => void;
3
+ onFocusOutside?: (event: FocusOutsideEvent) => void;
4
+ onInteractOutside?: (event: InteractOutsideEvent) => void;
5
+ };
6
+ type InteractOutsideOptions = InteractOutsideHandlers & {
7
+ exclude?: (target: HTMLElement) => boolean;
8
+ defer?: boolean;
9
+ };
10
+ type EventDetails<T> = {
11
+ originalEvent: T;
12
+ contextmenu: boolean;
13
+ focusable: boolean;
14
+ };
15
+ type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
16
+ type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
17
+ type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent;
18
+ type MaybeElement = HTMLElement | null | undefined;
19
+ type NodeOrFn = MaybeElement | (() => MaybeElement);
20
+ declare function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions): () => void;
21
+
22
+ export { FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, InteractOutsideOptions, PointerDownOutsideEvent, trackInteractOutside };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- export type InteractOutsideHandlers = {
1
+ type InteractOutsideHandlers = {
2
2
  onPointerDownOutside?: (event: PointerDownOutsideEvent) => void;
3
3
  onFocusOutside?: (event: FocusOutsideEvent) => void;
4
4
  onInteractOutside?: (event: InteractOutsideEvent) => void;
5
5
  };
6
- export type InteractOutsideOptions = InteractOutsideHandlers & {
6
+ type InteractOutsideOptions = InteractOutsideHandlers & {
7
7
  exclude?: (target: HTMLElement) => boolean;
8
8
  defer?: boolean;
9
9
  };
@@ -12,10 +12,11 @@ type EventDetails<T> = {
12
12
  contextmenu: boolean;
13
13
  focusable: boolean;
14
14
  };
15
- export type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
16
- export type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
17
- export type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent;
15
+ type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
16
+ type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
17
+ type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent;
18
18
  type MaybeElement = HTMLElement | null | undefined;
19
19
  type NodeOrFn = MaybeElement | (() => MaybeElement);
20
- export declare function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions): () => void;
21
- export {};
20
+ declare function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions): () => void;
21
+
22
+ export { FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, InteractOutsideOptions, PointerDownOutsideEvent, trackInteractOutside };
package/dist/index.js CHANGED
@@ -1,19 +1,79 @@
1
- 'use strict';
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2
19
 
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ trackInteractOutside: () => trackInteractOutside
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+ var import_dom_event = require("@zag-js/dom-event");
27
+ var import_dom_query = require("@zag-js/dom-query");
28
+ var import_tabbable = require("@zag-js/tabbable");
29
+ var import_utils = require("@zag-js/utils");
4
30
 
5
- const domEvent = require('@zag-js/dom-event');
6
- const domQuery = require('@zag-js/dom-query');
7
- const tabbable = require('@zag-js/tabbable');
8
- const utils = require('@zag-js/utils');
9
- const getWindowFrames = require('./get-window-frames.js');
31
+ // src/get-window-frames.ts
32
+ function getWindowFrames(win) {
33
+ const frames = {
34
+ each(cb) {
35
+ for (let i = 0; i < win.frames?.length; i += 1) {
36
+ const frame = win.frames[i];
37
+ if (frame)
38
+ cb(frame);
39
+ }
40
+ },
41
+ addEventListener(event, listener, options) {
42
+ frames.each((frame) => {
43
+ try {
44
+ frame.document.addEventListener(event, listener, options);
45
+ } catch (err) {
46
+ console.warn(err);
47
+ }
48
+ });
49
+ return () => {
50
+ try {
51
+ frames.removeEventListener(event, listener, options);
52
+ } catch (err) {
53
+ console.warn(err);
54
+ }
55
+ };
56
+ },
57
+ removeEventListener(event, listener, options) {
58
+ frames.each((frame) => {
59
+ try {
60
+ frame.document.removeEventListener(event, listener, options);
61
+ } catch (err) {
62
+ console.warn(err);
63
+ }
64
+ });
65
+ }
66
+ };
67
+ return frames;
68
+ }
10
69
 
11
- const POINTER_OUTSIDE_EVENT = "pointerdown.outside";
12
- const FOCUS_OUTSIDE_EVENT = "focus.outside";
70
+ // src/index.ts
71
+ var POINTER_OUTSIDE_EVENT = "pointerdown.outside";
72
+ var FOCUS_OUTSIDE_EVENT = "focus.outside";
13
73
  function isComposedPathFocusable(event) {
14
74
  const composedPath = event.composedPath() ?? [event.target];
15
75
  for (const node of composedPath) {
16
- if (domQuery.isHTMLElement(node) && tabbable.isFocusable(node))
76
+ if ((0, import_dom_query.isHTMLElement)(node) && (0, import_tabbable.isFocusable)(node))
17
77
  return true;
18
78
  }
19
79
  return false;
@@ -22,15 +82,15 @@ function trackInteractOutsideImpl(node, options) {
22
82
  const { exclude, onFocusOutside, onPointerDownOutside, onInteractOutside } = options;
23
83
  if (!node)
24
84
  return;
25
- const doc = domQuery.getDocument(node);
26
- const win = domQuery.getWindow(node);
27
- const frames = getWindowFrames.getWindowFrames(win);
85
+ const doc = (0, import_dom_query.getDocument)(node);
86
+ const win = (0, import_dom_query.getWindow)(node);
87
+ const frames = getWindowFrames(win);
28
88
  function isEventOutside(event) {
29
- const target = domQuery.getEventTarget(event);
30
- if (!domQuery.isHTMLElement(target)) {
89
+ const target = (0, import_dom_query.getEventTarget)(event);
90
+ if (!(0, import_dom_query.isHTMLElement)(target)) {
31
91
  return false;
32
92
  }
33
- if (domQuery.contains(node, target)) {
93
+ if ((0, import_dom_query.contains)(node, target)) {
34
94
  return false;
35
95
  }
36
96
  return !exclude?.(target);
@@ -41,15 +101,15 @@ function trackInteractOutsideImpl(node, options) {
41
101
  if (!node || !isEventOutside(event))
42
102
  return;
43
103
  if (onPointerDownOutside || onInteractOutside) {
44
- const handler2 = utils.callAll(onPointerDownOutside, onInteractOutside);
104
+ const handler2 = (0, import_utils.callAll)(onPointerDownOutside, onInteractOutside);
45
105
  node.addEventListener(POINTER_OUTSIDE_EVENT, handler2, { once: true });
46
106
  }
47
- domEvent.fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {
107
+ (0, import_dom_event.fireCustomEvent)(node, POINTER_OUTSIDE_EVENT, {
48
108
  bubbles: false,
49
109
  cancelable: true,
50
110
  detail: {
51
111
  originalEvent: event,
52
- contextmenu: domEvent.isContextMenuEvent(event),
112
+ contextmenu: (0, import_dom_event.isContextMenuEvent)(event),
53
113
  focusable: isComposedPathFocusable(event)
54
114
  }
55
115
  });
@@ -67,26 +127,26 @@ function trackInteractOutsideImpl(node, options) {
67
127
  const cleanups = /* @__PURE__ */ new Set();
68
128
  const timer = setTimeout(() => {
69
129
  cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
70
- cleanups.add(domEvent.addDomEvent(doc, "pointerdown", onPointerDown, true));
130
+ cleanups.add((0, import_dom_event.addDomEvent)(doc, "pointerdown", onPointerDown, true));
71
131
  }, 0);
72
132
  function onFocusin(event) {
73
133
  if (!node || !isEventOutside(event))
74
134
  return;
75
135
  if (onFocusOutside || onInteractOutside) {
76
- const handler = utils.callAll(onFocusOutside, onInteractOutside);
136
+ const handler = (0, import_utils.callAll)(onFocusOutside, onInteractOutside);
77
137
  node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
78
138
  }
79
- domEvent.fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {
139
+ (0, import_dom_event.fireCustomEvent)(node, FOCUS_OUTSIDE_EVENT, {
80
140
  bubbles: false,
81
141
  cancelable: true,
82
142
  detail: {
83
143
  originalEvent: event,
84
144
  contextmenu: false,
85
- focusable: tabbable.isFocusable(domQuery.getEventTarget(event))
145
+ focusable: (0, import_tabbable.isFocusable)((0, import_dom_query.getEventTarget)(event))
86
146
  }
87
147
  });
88
148
  }
89
- cleanups.add(domEvent.addDomEvent(doc, "focusin", onFocusin, true));
149
+ cleanups.add((0, import_dom_event.addDomEvent)(doc, "focusin", onFocusin, true));
90
150
  cleanups.add(frames.addEventListener("focusin", onFocusin, true));
91
151
  return () => {
92
152
  clearTimeout(timer);
@@ -99,7 +159,7 @@ function trackInteractOutsideImpl(node, options) {
99
159
  }
100
160
  function trackInteractOutside(nodeOrFn, options) {
101
161
  const { defer } = options;
102
- const func = defer ? domQuery.raf : (v) => v();
162
+ const func = defer ? import_dom_query.raf : (v) => v();
103
163
  const cleanups = [];
104
164
  cleanups.push(
105
165
  func(() => {
@@ -111,5 +171,8 @@ function trackInteractOutside(nodeOrFn, options) {
111
171
  cleanups.forEach((fn) => fn?.());
112
172
  };
113
173
  }
114
-
115
- exports.trackInteractOutside = trackInteractOutside;
174
+ // Annotate the CommonJS export names for ESM import in node:
175
+ 0 && (module.exports = {
176
+ trackInteractOutside
177
+ });
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/get-window-frames.ts"],"sourcesContent":["import { addDomEvent, fireCustomEvent, isContextMenuEvent } from \"@zag-js/dom-event\"\nimport { contains, getDocument, getEventTarget, getWindow, isHTMLElement, raf } from \"@zag-js/dom-query\"\nimport { isFocusable } from \"@zag-js/tabbable\"\nimport { callAll } from \"@zag-js/utils\"\nimport { getWindowFrames } from \"./get-window-frames\"\n\nexport type InteractOutsideHandlers = {\n onPointerDownOutside?: (event: PointerDownOutsideEvent) => void\n onFocusOutside?: (event: FocusOutsideEvent) => void\n onInteractOutside?: (event: InteractOutsideEvent) => void\n}\n\nexport type InteractOutsideOptions = InteractOutsideHandlers & {\n exclude?: (target: HTMLElement) => boolean\n defer?: boolean\n}\n\ntype EventDetails<T> = {\n originalEvent: T\n contextmenu: boolean\n focusable: boolean\n}\n\nconst POINTER_OUTSIDE_EVENT = \"pointerdown.outside\"\nconst FOCUS_OUTSIDE_EVENT = \"focus.outside\"\n\nexport type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>\n\nexport type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>\n\nexport type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent\n\ntype MaybeElement = HTMLElement | null | undefined\ntype NodeOrFn = MaybeElement | (() => MaybeElement)\n\nfunction isComposedPathFocusable(event: Event) {\n const composedPath = event.composedPath() ?? [event.target as HTMLElement]\n for (const node of composedPath) {\n if (isHTMLElement(node) && isFocusable(node)) return true\n }\n return false\n}\n\nfunction trackInteractOutsideImpl(node: MaybeElement, options: InteractOutsideOptions) {\n const { exclude, onFocusOutside, onPointerDownOutside, onInteractOutside } = options\n\n if (!node) return\n\n const doc = getDocument(node)\n const win = getWindow(node)\n const frames = getWindowFrames(win)\n\n function isEventOutside(event: Event): boolean {\n const target = getEventTarget(event)\n\n if (!isHTMLElement(target)) {\n return false\n }\n\n if (contains(node, target)) {\n return false\n }\n\n return !exclude?.(target)\n }\n\n let clickHandler: VoidFunction\n\n function onPointerDown(event: PointerEvent) {\n //\n function handler() {\n if (!node || !isEventOutside(event)) return\n\n if (onPointerDownOutside || onInteractOutside) {\n const handler = callAll(onPointerDownOutside, onInteractOutside) as EventListener\n node.addEventListener(POINTER_OUTSIDE_EVENT, handler, { once: true })\n }\n\n fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {\n bubbles: false,\n cancelable: true,\n detail: {\n originalEvent: event,\n contextmenu: isContextMenuEvent(event),\n focusable: isComposedPathFocusable(event),\n },\n })\n }\n\n if (event.pointerType === \"touch\") {\n frames.removeEventListener(\"click\", handler)\n doc.removeEventListener(\"click\", handler)\n\n clickHandler = handler\n\n doc.addEventListener(\"click\", handler, { once: true })\n frames.addEventListener(\"click\", handler, { once: true })\n } else {\n handler()\n }\n }\n const cleanups = new Set<VoidFunction>()\n\n const timer = setTimeout(() => {\n cleanups.add(frames.addEventListener(\"pointerdown\", onPointerDown, true))\n cleanups.add(addDomEvent(doc, \"pointerdown\", onPointerDown, true))\n }, 0)\n\n function onFocusin(event: FocusEvent) {\n //\n if (!node || !isEventOutside(event)) return\n\n if (onFocusOutside || onInteractOutside) {\n const handler = callAll(onFocusOutside, onInteractOutside) as EventListener\n node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true })\n }\n\n fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {\n bubbles: false,\n cancelable: true,\n detail: {\n originalEvent: event,\n contextmenu: false,\n focusable: isFocusable(getEventTarget(event)),\n },\n })\n }\n\n cleanups.add(addDomEvent(doc, \"focusin\", onFocusin, true))\n cleanups.add(frames.addEventListener(\"focusin\", onFocusin, true))\n\n return () => {\n clearTimeout(timer)\n if (clickHandler) {\n frames.removeEventListener(\"click\", clickHandler)\n doc.removeEventListener(\"click\", clickHandler)\n }\n cleanups.forEach((fn) => fn())\n }\n}\n\nexport function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const node = typeof nodeOrFn === \"function\" ? nodeOrFn() : nodeOrFn\n cleanups.push(trackInteractOutsideImpl(node, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n","export function getWindowFrames(win: Window) {\n const frames = {\n each(cb: (win: Window) => void) {\n for (let i = 0; i < win.frames?.length; i += 1) {\n const frame = win.frames[i]\n if (frame) cb(frame)\n }\n },\n addEventListener(event: string, listener: any, options?: any) {\n frames.each((frame) => {\n try {\n frame.document.addEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n })\n return () => {\n try {\n frames.removeEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n }\n },\n removeEventListener(event: string, listener: any, options?: any) {\n frames.each((frame) => {\n try {\n frame.document.removeEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n })\n },\n }\n return frames\n}\n"],"mappings":"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","names":["handler"]}
package/dist/index.mjs CHANGED
@@ -1,11 +1,51 @@
1
- import { addDomEvent, fireCustomEvent, isContextMenuEvent } from '@zag-js/dom-event';
2
- import { getDocument, getWindow, raf, getEventTarget, isHTMLElement, contains } from '@zag-js/dom-query';
3
- import { isFocusable } from '@zag-js/tabbable';
4
- import { callAll } from '@zag-js/utils';
5
- import { getWindowFrames } from './get-window-frames.mjs';
1
+ // src/index.ts
2
+ import { addDomEvent, fireCustomEvent, isContextMenuEvent } from "@zag-js/dom-event";
3
+ import { contains, getDocument, getEventTarget, getWindow, isHTMLElement, raf } from "@zag-js/dom-query";
4
+ import { isFocusable } from "@zag-js/tabbable";
5
+ import { callAll } from "@zag-js/utils";
6
6
 
7
- const POINTER_OUTSIDE_EVENT = "pointerdown.outside";
8
- const FOCUS_OUTSIDE_EVENT = "focus.outside";
7
+ // src/get-window-frames.ts
8
+ function getWindowFrames(win) {
9
+ const frames = {
10
+ each(cb) {
11
+ for (let i = 0; i < win.frames?.length; i += 1) {
12
+ const frame = win.frames[i];
13
+ if (frame)
14
+ cb(frame);
15
+ }
16
+ },
17
+ addEventListener(event, listener, options) {
18
+ frames.each((frame) => {
19
+ try {
20
+ frame.document.addEventListener(event, listener, options);
21
+ } catch (err) {
22
+ console.warn(err);
23
+ }
24
+ });
25
+ return () => {
26
+ try {
27
+ frames.removeEventListener(event, listener, options);
28
+ } catch (err) {
29
+ console.warn(err);
30
+ }
31
+ };
32
+ },
33
+ removeEventListener(event, listener, options) {
34
+ frames.each((frame) => {
35
+ try {
36
+ frame.document.removeEventListener(event, listener, options);
37
+ } catch (err) {
38
+ console.warn(err);
39
+ }
40
+ });
41
+ }
42
+ };
43
+ return frames;
44
+ }
45
+
46
+ // src/index.ts
47
+ var POINTER_OUTSIDE_EVENT = "pointerdown.outside";
48
+ var FOCUS_OUTSIDE_EVENT = "focus.outside";
9
49
  function isComposedPathFocusable(event) {
10
50
  const composedPath = event.composedPath() ?? [event.target];
11
51
  for (const node of composedPath) {
@@ -107,5 +147,7 @@ function trackInteractOutside(nodeOrFn, options) {
107
147
  cleanups.forEach((fn) => fn?.());
108
148
  };
109
149
  }
110
-
111
- export { trackInteractOutside };
150
+ export {
151
+ trackInteractOutside
152
+ };
153
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/get-window-frames.ts"],"sourcesContent":["import { addDomEvent, fireCustomEvent, isContextMenuEvent } from \"@zag-js/dom-event\"\nimport { contains, getDocument, getEventTarget, getWindow, isHTMLElement, raf } from \"@zag-js/dom-query\"\nimport { isFocusable } from \"@zag-js/tabbable\"\nimport { callAll } from \"@zag-js/utils\"\nimport { getWindowFrames } from \"./get-window-frames\"\n\nexport type InteractOutsideHandlers = {\n onPointerDownOutside?: (event: PointerDownOutsideEvent) => void\n onFocusOutside?: (event: FocusOutsideEvent) => void\n onInteractOutside?: (event: InteractOutsideEvent) => void\n}\n\nexport type InteractOutsideOptions = InteractOutsideHandlers & {\n exclude?: (target: HTMLElement) => boolean\n defer?: boolean\n}\n\ntype EventDetails<T> = {\n originalEvent: T\n contextmenu: boolean\n focusable: boolean\n}\n\nconst POINTER_OUTSIDE_EVENT = \"pointerdown.outside\"\nconst FOCUS_OUTSIDE_EVENT = \"focus.outside\"\n\nexport type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>\n\nexport type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>\n\nexport type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent\n\ntype MaybeElement = HTMLElement | null | undefined\ntype NodeOrFn = MaybeElement | (() => MaybeElement)\n\nfunction isComposedPathFocusable(event: Event) {\n const composedPath = event.composedPath() ?? [event.target as HTMLElement]\n for (const node of composedPath) {\n if (isHTMLElement(node) && isFocusable(node)) return true\n }\n return false\n}\n\nfunction trackInteractOutsideImpl(node: MaybeElement, options: InteractOutsideOptions) {\n const { exclude, onFocusOutside, onPointerDownOutside, onInteractOutside } = options\n\n if (!node) return\n\n const doc = getDocument(node)\n const win = getWindow(node)\n const frames = getWindowFrames(win)\n\n function isEventOutside(event: Event): boolean {\n const target = getEventTarget(event)\n\n if (!isHTMLElement(target)) {\n return false\n }\n\n if (contains(node, target)) {\n return false\n }\n\n return !exclude?.(target)\n }\n\n let clickHandler: VoidFunction\n\n function onPointerDown(event: PointerEvent) {\n //\n function handler() {\n if (!node || !isEventOutside(event)) return\n\n if (onPointerDownOutside || onInteractOutside) {\n const handler = callAll(onPointerDownOutside, onInteractOutside) as EventListener\n node.addEventListener(POINTER_OUTSIDE_EVENT, handler, { once: true })\n }\n\n fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {\n bubbles: false,\n cancelable: true,\n detail: {\n originalEvent: event,\n contextmenu: isContextMenuEvent(event),\n focusable: isComposedPathFocusable(event),\n },\n })\n }\n\n if (event.pointerType === \"touch\") {\n frames.removeEventListener(\"click\", handler)\n doc.removeEventListener(\"click\", handler)\n\n clickHandler = handler\n\n doc.addEventListener(\"click\", handler, { once: true })\n frames.addEventListener(\"click\", handler, { once: true })\n } else {\n handler()\n }\n }\n const cleanups = new Set<VoidFunction>()\n\n const timer = setTimeout(() => {\n cleanups.add(frames.addEventListener(\"pointerdown\", onPointerDown, true))\n cleanups.add(addDomEvent(doc, \"pointerdown\", onPointerDown, true))\n }, 0)\n\n function onFocusin(event: FocusEvent) {\n //\n if (!node || !isEventOutside(event)) return\n\n if (onFocusOutside || onInteractOutside) {\n const handler = callAll(onFocusOutside, onInteractOutside) as EventListener\n node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true })\n }\n\n fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {\n bubbles: false,\n cancelable: true,\n detail: {\n originalEvent: event,\n contextmenu: false,\n focusable: isFocusable(getEventTarget(event)),\n },\n })\n }\n\n cleanups.add(addDomEvent(doc, \"focusin\", onFocusin, true))\n cleanups.add(frames.addEventListener(\"focusin\", onFocusin, true))\n\n return () => {\n clearTimeout(timer)\n if (clickHandler) {\n frames.removeEventListener(\"click\", clickHandler)\n doc.removeEventListener(\"click\", clickHandler)\n }\n cleanups.forEach((fn) => fn())\n }\n}\n\nexport function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions) {\n const { defer } = options\n const func = defer ? raf : (v: any) => v()\n const cleanups: (VoidFunction | undefined)[] = []\n cleanups.push(\n func(() => {\n const node = typeof nodeOrFn === \"function\" ? nodeOrFn() : nodeOrFn\n cleanups.push(trackInteractOutsideImpl(node, options))\n }),\n )\n return () => {\n cleanups.forEach((fn) => fn?.())\n }\n}\n","export function getWindowFrames(win: Window) {\n const frames = {\n each(cb: (win: Window) => void) {\n for (let i = 0; i < win.frames?.length; i += 1) {\n const frame = win.frames[i]\n if (frame) cb(frame)\n }\n },\n addEventListener(event: string, listener: any, options?: any) {\n frames.each((frame) => {\n try {\n frame.document.addEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n })\n return () => {\n try {\n frames.removeEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n }\n },\n removeEventListener(event: string, listener: any, options?: any) {\n frames.each((frame) => {\n try {\n frame.document.removeEventListener(event, listener, options)\n } catch (err) {\n console.warn(err)\n }\n })\n },\n }\n return frames\n}\n"],"mappings":"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","names":["handler"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/interact-outside",
3
- "version": "0.10.5",
3
+ "version": "0.11.1",
4
4
  "description": "Track interations or focus outside an element",
5
5
  "keywords": [
6
6
  "js",
@@ -17,10 +17,10 @@
17
17
  "src"
18
18
  ],
19
19
  "dependencies": {
20
- "@zag-js/dom-query": "0.10.5",
21
- "@zag-js/dom-event": "0.10.5",
22
- "@zag-js/tabbable": "0.10.5",
23
- "@zag-js/utils": "0.10.5"
20
+ "@zag-js/dom-query": "0.11.1",
21
+ "@zag-js/dom-event": "0.11.1",
22
+ "@zag-js/tabbable": "0.11.1",
23
+ "@zag-js/utils": "0.11.1"
24
24
  },
25
25
  "devDependencies": {
26
26
  "clean-package": "2.2.0"
@@ -44,7 +44,7 @@
44
44
  "./package.json": "./package.json"
45
45
  },
46
46
  "scripts": {
47
- "build": "vite build -c ../../../vite.config.ts",
47
+ "build": "tsup",
48
48
  "test": "jest --config ../../../jest.config.js --rootDir tests",
49
49
  "lint": "eslint src --ext .ts,.tsx",
50
50
  "test-ci": "pnpm test --ci --runInBand -u",
@@ -1,5 +0,0 @@
1
- export declare function getWindowFrames(win: Window): {
2
- each(cb: (win: Window) => void): void;
3
- addEventListener(event: string, listener: any, options?: any): () => void;
4
- removeEventListener(event: string, listener: any, options?: any): void;
5
- };
@@ -1,43 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
-
5
- function getWindowFrames(win) {
6
- const frames = {
7
- each(cb) {
8
- for (let i = 0; i < win.frames?.length; i += 1) {
9
- const frame = win.frames[i];
10
- if (frame)
11
- cb(frame);
12
- }
13
- },
14
- addEventListener(event, listener, options) {
15
- frames.each((frame) => {
16
- try {
17
- frame.document.addEventListener(event, listener, options);
18
- } catch (err) {
19
- console.warn(err);
20
- }
21
- });
22
- return () => {
23
- try {
24
- frames.removeEventListener(event, listener, options);
25
- } catch (err) {
26
- console.warn(err);
27
- }
28
- };
29
- },
30
- removeEventListener(event, listener, options) {
31
- frames.each((frame) => {
32
- try {
33
- frame.document.removeEventListener(event, listener, options);
34
- } catch (err) {
35
- console.warn(err);
36
- }
37
- });
38
- }
39
- };
40
- return frames;
41
- }
42
-
43
- exports.getWindowFrames = getWindowFrames;
@@ -1,39 +0,0 @@
1
- function getWindowFrames(win) {
2
- const frames = {
3
- each(cb) {
4
- for (let i = 0; i < win.frames?.length; i += 1) {
5
- const frame = win.frames[i];
6
- if (frame)
7
- cb(frame);
8
- }
9
- },
10
- addEventListener(event, listener, options) {
11
- frames.each((frame) => {
12
- try {
13
- frame.document.addEventListener(event, listener, options);
14
- } catch (err) {
15
- console.warn(err);
16
- }
17
- });
18
- return () => {
19
- try {
20
- frames.removeEventListener(event, listener, options);
21
- } catch (err) {
22
- console.warn(err);
23
- }
24
- };
25
- },
26
- removeEventListener(event, listener, options) {
27
- frames.each((frame) => {
28
- try {
29
- frame.document.removeEventListener(event, listener, options);
30
- } catch (err) {
31
- console.warn(err);
32
- }
33
- });
34
- }
35
- };
36
- return frames;
37
- }
38
-
39
- export { getWindowFrames };