@zag-js/interact-outside 1.7.0 → 1.8.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.
package/dist/index.d.mts CHANGED
@@ -20,6 +20,7 @@ interface EventDetails<T> {
20
20
  originalEvent: T;
21
21
  contextmenu: boolean;
22
22
  focusable: boolean;
23
+ target: EventTarget;
23
24
  }
24
25
  type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
25
26
  type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ interface EventDetails<T> {
20
20
  originalEvent: T;
21
21
  contextmenu: boolean;
22
22
  focusable: boolean;
23
+ target: EventTarget;
23
24
  }
24
25
  type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
25
26
  type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
package/dist/index.js CHANGED
@@ -108,8 +108,7 @@ function trackInteractOutsideImpl(node, options) {
108
108
  const win = domQuery.getWindow(node);
109
109
  const frames = getWindowFrames(win);
110
110
  const parentWin = getParentWindow(win);
111
- function isEventOutside(event) {
112
- const target = domQuery.getEventTarget(event);
111
+ function isEventOutside(event, target) {
113
112
  if (!domQuery.isHTMLElement(target)) return false;
114
113
  if (!target.isConnected) return false;
115
114
  if (domQuery.contains(node, target)) return false;
@@ -124,12 +123,15 @@ function trackInteractOutsideImpl(node, options) {
124
123
  return !exclude?.(target);
125
124
  }
126
125
  const pointerdownCleanups = /* @__PURE__ */ new Set();
126
+ const isInShadowRoot = domQuery.isShadowRoot(node?.getRootNode());
127
127
  function onPointerDown(event) {
128
- function handler() {
129
- const func = defer ? domQuery.raf : (v) => v();
130
- const composedPath = event.composedPath?.() ?? [event.target];
128
+ function handler(clickEvent) {
129
+ const func = defer && !domQuery.isTouchDevice() ? domQuery.raf : (v) => v();
130
+ const evt = clickEvent ?? event;
131
+ const composedPath = evt?.composedPath?.() ?? [evt?.target];
131
132
  func(() => {
132
- if (!node || !isEventOutside(event)) return;
133
+ const target = isInShadowRoot ? composedPath[0] : domQuery.getEventTarget(event);
134
+ if (!node || !isEventOutside(event, target)) return;
133
135
  if (onPointerDownOutside || onInteractOutside) {
134
136
  const handler2 = utils.callAll(onPointerDownOutside, onInteractOutside);
135
137
  node.addEventListener(POINTER_OUTSIDE_EVENT, handler2, { once: true });
@@ -138,9 +140,10 @@ function trackInteractOutsideImpl(node, options) {
138
140
  bubbles: false,
139
141
  cancelable: true,
140
142
  detail: {
141
- originalEvent: event,
142
- contextmenu: domQuery.isContextMenuEvent(event),
143
- focusable: isComposedPathFocusable(composedPath)
143
+ originalEvent: evt,
144
+ contextmenu: domQuery.isContextMenuEvent(evt),
145
+ focusable: isComposedPathFocusable(composedPath),
146
+ target
144
147
  }
145
148
  });
146
149
  });
@@ -163,7 +166,8 @@ function trackInteractOutsideImpl(node, options) {
163
166
  function onFocusin(event) {
164
167
  const func = defer ? domQuery.raf : (v) => v();
165
168
  func(() => {
166
- if (!node || !isEventOutside(event)) return;
169
+ const target = domQuery.getEventTarget(event);
170
+ if (!node || !isEventOutside(event, target)) return;
167
171
  if (onFocusOutside || onInteractOutside) {
168
172
  const handler = utils.callAll(onFocusOutside, onInteractOutside);
169
173
  node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
@@ -174,14 +178,17 @@ function trackInteractOutsideImpl(node, options) {
174
178
  detail: {
175
179
  originalEvent: event,
176
180
  contextmenu: false,
177
- focusable: domQuery.isFocusable(domQuery.getEventTarget(event))
181
+ focusable: domQuery.isFocusable(target),
182
+ target
178
183
  }
179
184
  });
180
185
  });
181
186
  }
182
- cleanups.add(domQuery.addDomEvent(doc, "focusin", onFocusin, true));
183
- cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
184
- cleanups.add(frames.addEventListener("focusin", onFocusin, true));
187
+ if (!domQuery.isTouchDevice()) {
188
+ cleanups.add(domQuery.addDomEvent(doc, "focusin", onFocusin, true));
189
+ cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
190
+ cleanups.add(frames.addEventListener("focusin", onFocusin, true));
191
+ }
185
192
  return () => {
186
193
  clearTimeout(timer);
187
194
  pointerdownCleanups.forEach((fn) => fn());
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { raf, getDocument, getWindow, addDomEvent, isFocusable, getEventTarget, isContextMenuEvent, isHTMLElement, contains, getNearestOverflowAncestor } from '@zag-js/dom-query';
1
+ import { raf, getDocument, getWindow, isShadowRoot, addDomEvent, isTouchDevice, getEventTarget, isFocusable, isContextMenuEvent, isHTMLElement, contains, getNearestOverflowAncestor } from '@zag-js/dom-query';
2
2
  import { callAll } from '@zag-js/utils';
3
3
 
4
4
  // src/index.ts
@@ -106,8 +106,7 @@ function trackInteractOutsideImpl(node, options) {
106
106
  const win = getWindow(node);
107
107
  const frames = getWindowFrames(win);
108
108
  const parentWin = getParentWindow(win);
109
- function isEventOutside(event) {
110
- const target = getEventTarget(event);
109
+ function isEventOutside(event, target) {
111
110
  if (!isHTMLElement(target)) return false;
112
111
  if (!target.isConnected) return false;
113
112
  if (contains(node, target)) return false;
@@ -122,12 +121,15 @@ function trackInteractOutsideImpl(node, options) {
122
121
  return !exclude?.(target);
123
122
  }
124
123
  const pointerdownCleanups = /* @__PURE__ */ new Set();
124
+ const isInShadowRoot = isShadowRoot(node?.getRootNode());
125
125
  function onPointerDown(event) {
126
- function handler() {
127
- const func = defer ? raf : (v) => v();
128
- const composedPath = event.composedPath?.() ?? [event.target];
126
+ function handler(clickEvent) {
127
+ const func = defer && !isTouchDevice() ? raf : (v) => v();
128
+ const evt = clickEvent ?? event;
129
+ const composedPath = evt?.composedPath?.() ?? [evt?.target];
129
130
  func(() => {
130
- if (!node || !isEventOutside(event)) return;
131
+ const target = isInShadowRoot ? composedPath[0] : getEventTarget(event);
132
+ if (!node || !isEventOutside(event, target)) return;
131
133
  if (onPointerDownOutside || onInteractOutside) {
132
134
  const handler2 = callAll(onPointerDownOutside, onInteractOutside);
133
135
  node.addEventListener(POINTER_OUTSIDE_EVENT, handler2, { once: true });
@@ -136,9 +138,10 @@ function trackInteractOutsideImpl(node, options) {
136
138
  bubbles: false,
137
139
  cancelable: true,
138
140
  detail: {
139
- originalEvent: event,
140
- contextmenu: isContextMenuEvent(event),
141
- focusable: isComposedPathFocusable(composedPath)
141
+ originalEvent: evt,
142
+ contextmenu: isContextMenuEvent(evt),
143
+ focusable: isComposedPathFocusable(composedPath),
144
+ target
142
145
  }
143
146
  });
144
147
  });
@@ -161,7 +164,8 @@ function trackInteractOutsideImpl(node, options) {
161
164
  function onFocusin(event) {
162
165
  const func = defer ? raf : (v) => v();
163
166
  func(() => {
164
- if (!node || !isEventOutside(event)) return;
167
+ const target = getEventTarget(event);
168
+ if (!node || !isEventOutside(event, target)) return;
165
169
  if (onFocusOutside || onInteractOutside) {
166
170
  const handler = callAll(onFocusOutside, onInteractOutside);
167
171
  node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
@@ -172,14 +176,17 @@ function trackInteractOutsideImpl(node, options) {
172
176
  detail: {
173
177
  originalEvent: event,
174
178
  contextmenu: false,
175
- focusable: isFocusable(getEventTarget(event))
179
+ focusable: isFocusable(target),
180
+ target
176
181
  }
177
182
  });
178
183
  });
179
184
  }
180
- cleanups.add(addDomEvent(doc, "focusin", onFocusin, true));
181
- cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
182
- cleanups.add(frames.addEventListener("focusin", onFocusin, true));
185
+ if (!isTouchDevice()) {
186
+ cleanups.add(addDomEvent(doc, "focusin", onFocusin, true));
187
+ cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
188
+ cleanups.add(frames.addEventListener("focusin", onFocusin, true));
189
+ }
183
190
  return () => {
184
191
  clearTimeout(timer);
185
192
  pointerdownCleanups.forEach((fn) => fn());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/interact-outside",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Track interactions or focus outside an element",
5
5
  "keywords": [
6
6
  "js",
@@ -16,8 +16,8 @@
16
16
  "dist"
17
17
  ],
18
18
  "dependencies": {
19
- "@zag-js/dom-query": "1.7.0",
20
- "@zag-js/utils": "1.7.0"
19
+ "@zag-js/dom-query": "1.8.1",
20
+ "@zag-js/utils": "1.8.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "clean-package": "2.2.0"