@zag-js/interact-outside 0.71.0 → 0.73.0
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 +34 -19
- package/dist/index.mjs +36 -21
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ var domQuery = require('@zag-js/dom-query');
|
|
|
5
5
|
var utils = require('@zag-js/utils');
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
|
+
|
|
9
|
+
// src/frame-utils.ts
|
|
8
10
|
function getWindowFrames(win) {
|
|
9
11
|
const frames = {
|
|
10
12
|
each(cb) {
|
|
@@ -13,21 +15,6 @@ function getWindowFrames(win) {
|
|
|
13
15
|
if (frame) cb(frame);
|
|
14
16
|
}
|
|
15
17
|
},
|
|
16
|
-
queueBeforeEvent(event, listener) {
|
|
17
|
-
const cleanup = /* @__PURE__ */ new Set();
|
|
18
|
-
frames.each((frame) => {
|
|
19
|
-
try {
|
|
20
|
-
cleanup.add(domEvent.queueBeforeEvent(frame.document, event, listener));
|
|
21
|
-
} catch {
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return () => {
|
|
25
|
-
try {
|
|
26
|
-
cleanup.forEach((fn) => fn());
|
|
27
|
-
} catch {
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
18
|
addEventListener(event, listener, options) {
|
|
32
19
|
frames.each((frame) => {
|
|
33
20
|
try {
|
|
@@ -53,6 +40,29 @@ function getWindowFrames(win) {
|
|
|
53
40
|
};
|
|
54
41
|
return frames;
|
|
55
42
|
}
|
|
43
|
+
function getParentWindow(win) {
|
|
44
|
+
const parent = win.frameElement != null ? win.parent : null;
|
|
45
|
+
return {
|
|
46
|
+
addEventListener: (event, listener, options) => {
|
|
47
|
+
try {
|
|
48
|
+
parent?.addEventListener(event, listener, options);
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return () => {
|
|
52
|
+
try {
|
|
53
|
+
parent?.removeEventListener(event, listener, options);
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
removeEventListener: (event, listener, options) => {
|
|
59
|
+
try {
|
|
60
|
+
parent?.removeEventListener(event, listener, options);
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
56
66
|
|
|
57
67
|
// src/index.ts
|
|
58
68
|
var POINTER_OUTSIDE_EVENT = "pointerdown.outside";
|
|
@@ -70,8 +80,7 @@ function isEventPointWithin(node, event) {
|
|
|
70
80
|
if (rect.width === 0 || rect.height === 0) return false;
|
|
71
81
|
return rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
|
|
72
82
|
}
|
|
73
|
-
function isEventWithinScrollbar(event) {
|
|
74
|
-
const target = domQuery.getEventTarget(event);
|
|
83
|
+
function isEventWithinScrollbar(event, target) {
|
|
75
84
|
if (!target || !isPointerEvent(event)) return false;
|
|
76
85
|
const isScrollableY = target.scrollHeight > target.clientHeight;
|
|
77
86
|
const onScrollbarY = isScrollableY && event.clientX > target.clientWidth;
|
|
@@ -85,12 +94,15 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
85
94
|
const doc = domQuery.getDocument(node);
|
|
86
95
|
const win = domQuery.getWindow(node);
|
|
87
96
|
const frames = getWindowFrames(win);
|
|
97
|
+
const parentWin = getParentWindow(win);
|
|
88
98
|
function isEventOutside(event) {
|
|
89
99
|
const target = domQuery.getEventTarget(event);
|
|
90
100
|
if (!domQuery.isHTMLElement(target)) return false;
|
|
91
101
|
if (domQuery.contains(node, target)) return false;
|
|
92
102
|
if (isEventPointWithin(node, event)) return false;
|
|
93
|
-
if (isEventWithinScrollbar(event)) return false;
|
|
103
|
+
if (isEventWithinScrollbar(event, target)) return false;
|
|
104
|
+
const scrollParent = domQuery.getNearestOverflowAncestor(node);
|
|
105
|
+
if (isEventWithinScrollbar(event, scrollParent)) return false;
|
|
94
106
|
return !exclude?.(target);
|
|
95
107
|
}
|
|
96
108
|
const pointerdownCleanups = /* @__PURE__ */ new Set();
|
|
@@ -118,6 +130,7 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
118
130
|
if (event.pointerType === "touch") {
|
|
119
131
|
pointerdownCleanups.forEach((fn) => fn());
|
|
120
132
|
pointerdownCleanups.add(domEvent.addDomEvent(doc, "click", handler, { once: true }));
|
|
133
|
+
pointerdownCleanups.add(parentWin.addEventListener("click", handler, { once: true }));
|
|
121
134
|
pointerdownCleanups.add(frames.addEventListener("click", handler, { once: true }));
|
|
122
135
|
} else {
|
|
123
136
|
handler();
|
|
@@ -125,8 +138,9 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
125
138
|
}
|
|
126
139
|
const cleanups = /* @__PURE__ */ new Set();
|
|
127
140
|
const timer = setTimeout(() => {
|
|
128
|
-
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
|
|
129
141
|
cleanups.add(domEvent.addDomEvent(doc, "pointerdown", onPointerDown, true));
|
|
142
|
+
cleanups.add(parentWin.addEventListener("pointerdown", onPointerDown, true));
|
|
143
|
+
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
|
|
130
144
|
}, 0);
|
|
131
145
|
function onFocusin(event) {
|
|
132
146
|
const func = defer ? domQuery.raf : (v) => v();
|
|
@@ -148,6 +162,7 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
148
162
|
});
|
|
149
163
|
}
|
|
150
164
|
cleanups.add(domEvent.addDomEvent(doc, "focusin", onFocusin, true));
|
|
165
|
+
cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
|
|
151
166
|
cleanups.add(frames.addEventListener("focusin", onFocusin, true));
|
|
152
167
|
return () => {
|
|
153
168
|
clearTimeout(timer);
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { addDomEvent, fireCustomEvent, isContextMenuEvent
|
|
2
|
-
import { getDocument, getWindow, raf, isFocusable, getEventTarget, isHTMLElement, contains } from '@zag-js/dom-query';
|
|
1
|
+
import { addDomEvent, fireCustomEvent, isContextMenuEvent } from '@zag-js/dom-event';
|
|
2
|
+
import { getDocument, getWindow, raf, isFocusable, getEventTarget, isHTMLElement, contains, getNearestOverflowAncestor } from '@zag-js/dom-query';
|
|
3
3
|
import { callAll } from '@zag-js/utils';
|
|
4
4
|
|
|
5
5
|
// src/index.ts
|
|
6
|
+
|
|
7
|
+
// src/frame-utils.ts
|
|
6
8
|
function getWindowFrames(win) {
|
|
7
9
|
const frames = {
|
|
8
10
|
each(cb) {
|
|
@@ -11,21 +13,6 @@ function getWindowFrames(win) {
|
|
|
11
13
|
if (frame) cb(frame);
|
|
12
14
|
}
|
|
13
15
|
},
|
|
14
|
-
queueBeforeEvent(event, listener) {
|
|
15
|
-
const cleanup = /* @__PURE__ */ new Set();
|
|
16
|
-
frames.each((frame) => {
|
|
17
|
-
try {
|
|
18
|
-
cleanup.add(queueBeforeEvent(frame.document, event, listener));
|
|
19
|
-
} catch {
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
return () => {
|
|
23
|
-
try {
|
|
24
|
-
cleanup.forEach((fn) => fn());
|
|
25
|
-
} catch {
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
},
|
|
29
16
|
addEventListener(event, listener, options) {
|
|
30
17
|
frames.each((frame) => {
|
|
31
18
|
try {
|
|
@@ -51,6 +38,29 @@ function getWindowFrames(win) {
|
|
|
51
38
|
};
|
|
52
39
|
return frames;
|
|
53
40
|
}
|
|
41
|
+
function getParentWindow(win) {
|
|
42
|
+
const parent = win.frameElement != null ? win.parent : null;
|
|
43
|
+
return {
|
|
44
|
+
addEventListener: (event, listener, options) => {
|
|
45
|
+
try {
|
|
46
|
+
parent?.addEventListener(event, listener, options);
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return () => {
|
|
50
|
+
try {
|
|
51
|
+
parent?.removeEventListener(event, listener, options);
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
removeEventListener: (event, listener, options) => {
|
|
57
|
+
try {
|
|
58
|
+
parent?.removeEventListener(event, listener, options);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
54
64
|
|
|
55
65
|
// src/index.ts
|
|
56
66
|
var POINTER_OUTSIDE_EVENT = "pointerdown.outside";
|
|
@@ -68,8 +78,7 @@ function isEventPointWithin(node, event) {
|
|
|
68
78
|
if (rect.width === 0 || rect.height === 0) return false;
|
|
69
79
|
return rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
|
|
70
80
|
}
|
|
71
|
-
function isEventWithinScrollbar(event) {
|
|
72
|
-
const target = getEventTarget(event);
|
|
81
|
+
function isEventWithinScrollbar(event, target) {
|
|
73
82
|
if (!target || !isPointerEvent(event)) return false;
|
|
74
83
|
const isScrollableY = target.scrollHeight > target.clientHeight;
|
|
75
84
|
const onScrollbarY = isScrollableY && event.clientX > target.clientWidth;
|
|
@@ -83,12 +92,15 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
83
92
|
const doc = getDocument(node);
|
|
84
93
|
const win = getWindow(node);
|
|
85
94
|
const frames = getWindowFrames(win);
|
|
95
|
+
const parentWin = getParentWindow(win);
|
|
86
96
|
function isEventOutside(event) {
|
|
87
97
|
const target = getEventTarget(event);
|
|
88
98
|
if (!isHTMLElement(target)) return false;
|
|
89
99
|
if (contains(node, target)) return false;
|
|
90
100
|
if (isEventPointWithin(node, event)) return false;
|
|
91
|
-
if (isEventWithinScrollbar(event)) return false;
|
|
101
|
+
if (isEventWithinScrollbar(event, target)) return false;
|
|
102
|
+
const scrollParent = getNearestOverflowAncestor(node);
|
|
103
|
+
if (isEventWithinScrollbar(event, scrollParent)) return false;
|
|
92
104
|
return !exclude?.(target);
|
|
93
105
|
}
|
|
94
106
|
const pointerdownCleanups = /* @__PURE__ */ new Set();
|
|
@@ -116,6 +128,7 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
116
128
|
if (event.pointerType === "touch") {
|
|
117
129
|
pointerdownCleanups.forEach((fn) => fn());
|
|
118
130
|
pointerdownCleanups.add(addDomEvent(doc, "click", handler, { once: true }));
|
|
131
|
+
pointerdownCleanups.add(parentWin.addEventListener("click", handler, { once: true }));
|
|
119
132
|
pointerdownCleanups.add(frames.addEventListener("click", handler, { once: true }));
|
|
120
133
|
} else {
|
|
121
134
|
handler();
|
|
@@ -123,8 +136,9 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
123
136
|
}
|
|
124
137
|
const cleanups = /* @__PURE__ */ new Set();
|
|
125
138
|
const timer = setTimeout(() => {
|
|
126
|
-
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
|
|
127
139
|
cleanups.add(addDomEvent(doc, "pointerdown", onPointerDown, true));
|
|
140
|
+
cleanups.add(parentWin.addEventListener("pointerdown", onPointerDown, true));
|
|
141
|
+
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
|
|
128
142
|
}, 0);
|
|
129
143
|
function onFocusin(event) {
|
|
130
144
|
const func = defer ? raf : (v) => v();
|
|
@@ -146,6 +160,7 @@ function trackInteractOutsideImpl(node, options) {
|
|
|
146
160
|
});
|
|
147
161
|
}
|
|
148
162
|
cleanups.add(addDomEvent(doc, "focusin", onFocusin, true));
|
|
163
|
+
cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
|
|
149
164
|
cleanups.add(frames.addEventListener("focusin", onFocusin, true));
|
|
150
165
|
return () => {
|
|
151
166
|
clearTimeout(timer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zag-js/interact-outside",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.0",
|
|
4
4
|
"description": "Track interations or focus outside an element",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"js",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@zag-js/dom-query": "0.
|
|
20
|
-
"@zag-js/dom-event": "0.
|
|
21
|
-
"@zag-js/utils": "0.
|
|
19
|
+
"@zag-js/dom-query": "0.73.0",
|
|
20
|
+
"@zag-js/dom-event": "0.73.0",
|
|
21
|
+
"@zag-js/utils": "0.73.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"clean-package": "2.2.0"
|