@radix-ui/react-toast 1.1.6-rc.6 → 1.2.0-rc.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 +49 -37
- package/dist/index.d.ts +49 -37
- package/dist/index.js +631 -704
- package/dist/index.js.map +7 -1
- package/dist/index.mjs +624 -691
- package/dist/index.mjs.map +7 -1
- package/package.json +13 -14
- package/dist/index.d.ts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,730 +1,663 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {composeEventHandlers
|
|
5
|
-
import {useComposedRefs
|
|
6
|
-
import {createCollection
|
|
7
|
-
import {createContextScope
|
|
8
|
-
import
|
|
9
|
-
import {Portal
|
|
10
|
-
import {Presence
|
|
11
|
-
import {
|
|
12
|
-
import {useCallbackRef
|
|
13
|
-
import {useControllableState
|
|
14
|
-
import {useLayoutEffect
|
|
15
|
-
import {VisuallyHidden
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
swipeDirection: swipeDirection,
|
|
53
|
-
swipeThreshold: swipeThreshold,
|
|
54
|
-
toastCount: toastCount,
|
|
55
|
-
viewport: viewport,
|
|
56
|
-
onViewportChange: setViewport,
|
|
57
|
-
onToastAdd: $eyrYI$useCallback(()=>setToastCount((prevCount)=>prevCount + 1
|
|
58
|
-
)
|
|
59
|
-
, []),
|
|
60
|
-
onToastRemove: $eyrYI$useCallback(()=>setToastCount((prevCount)=>prevCount - 1
|
|
61
|
-
)
|
|
62
|
-
, []),
|
|
63
|
-
isFocusedToastEscapeKeyDownRef: isFocusedToastEscapeKeyDownRef,
|
|
64
|
-
isClosePausedRef: isClosePausedRef
|
|
65
|
-
}, children));
|
|
1
|
+
// packages/react/toast/src/Toast.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as ReactDOM from "react-dom";
|
|
4
|
+
import { composeEventHandlers } from "@radix-ui/primitive";
|
|
5
|
+
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
6
|
+
import { createCollection } from "@radix-ui/react-collection";
|
|
7
|
+
import { createContextScope } from "@radix-ui/react-context";
|
|
8
|
+
import * as DismissableLayer from "@radix-ui/react-dismissable-layer";
|
|
9
|
+
import { Portal } from "@radix-ui/react-portal";
|
|
10
|
+
import { Presence } from "@radix-ui/react-presence";
|
|
11
|
+
import { Primitive, dispatchDiscreteCustomEvent } from "@radix-ui/react-primitive";
|
|
12
|
+
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
|
13
|
+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
14
|
+
import { useLayoutEffect } from "@radix-ui/react-use-layout-effect";
|
|
15
|
+
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
16
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
+
var PROVIDER_NAME = "ToastProvider";
|
|
18
|
+
var [Collection, useCollection, createCollectionScope] = createCollection("Toast");
|
|
19
|
+
var [createToastContext, createToastScope] = createContextScope("Toast", [createCollectionScope]);
|
|
20
|
+
var [ToastProviderProvider, useToastProviderContext] = createToastContext(PROVIDER_NAME);
|
|
21
|
+
var ToastProvider = (props) => {
|
|
22
|
+
const {
|
|
23
|
+
__scopeToast,
|
|
24
|
+
label = "Notification",
|
|
25
|
+
duration = 5e3,
|
|
26
|
+
swipeDirection = "right",
|
|
27
|
+
swipeThreshold = 50,
|
|
28
|
+
children
|
|
29
|
+
} = props;
|
|
30
|
+
const [viewport, setViewport] = React.useState(null);
|
|
31
|
+
const [toastCount, setToastCount] = React.useState(0);
|
|
32
|
+
const isFocusedToastEscapeKeyDownRef = React.useRef(false);
|
|
33
|
+
const isClosePausedRef = React.useRef(false);
|
|
34
|
+
return /* @__PURE__ */ jsx(Collection.Provider, { scope: __scopeToast, children: /* @__PURE__ */ jsx(
|
|
35
|
+
ToastProviderProvider,
|
|
36
|
+
{
|
|
37
|
+
scope: __scopeToast,
|
|
38
|
+
label,
|
|
39
|
+
duration,
|
|
40
|
+
swipeDirection,
|
|
41
|
+
swipeThreshold,
|
|
42
|
+
toastCount,
|
|
43
|
+
viewport,
|
|
44
|
+
onViewportChange: setViewport,
|
|
45
|
+
onToastAdd: React.useCallback(() => setToastCount((prevCount) => prevCount + 1), []),
|
|
46
|
+
onToastRemove: React.useCallback(() => setToastCount((prevCount) => prevCount - 1), []),
|
|
47
|
+
isFocusedToastEscapeKeyDownRef,
|
|
48
|
+
isClosePausedRef,
|
|
49
|
+
children
|
|
50
|
+
}
|
|
51
|
+
) });
|
|
66
52
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
return null;
|
|
53
|
+
ToastProvider.propTypes = {
|
|
54
|
+
label(props) {
|
|
55
|
+
if (props.label && typeof props.label === "string" && !props.label.trim()) {
|
|
56
|
+
const error = `Invalid prop \`label\` supplied to \`${PROVIDER_NAME}\`. Expected non-empty \`string\`.`;
|
|
57
|
+
return new Error(error);
|
|
74
58
|
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
75
61
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const context =
|
|
90
|
-
const getItems =
|
|
91
|
-
const wrapperRef =
|
|
92
|
-
const headFocusProxyRef =
|
|
93
|
-
const tailFocusProxyRef =
|
|
94
|
-
const ref =
|
|
95
|
-
const composedRefs =
|
|
96
|
-
const hotkeyLabel = hotkey.join(
|
|
62
|
+
ToastProvider.displayName = PROVIDER_NAME;
|
|
63
|
+
var VIEWPORT_NAME = "ToastViewport";
|
|
64
|
+
var VIEWPORT_DEFAULT_HOTKEY = ["F8"];
|
|
65
|
+
var VIEWPORT_PAUSE = "toast.viewportPause";
|
|
66
|
+
var VIEWPORT_RESUME = "toast.viewportResume";
|
|
67
|
+
var ToastViewport = React.forwardRef(
|
|
68
|
+
(props, forwardedRef) => {
|
|
69
|
+
const {
|
|
70
|
+
__scopeToast,
|
|
71
|
+
hotkey = VIEWPORT_DEFAULT_HOTKEY,
|
|
72
|
+
label = "Notifications ({hotkey})",
|
|
73
|
+
...viewportProps
|
|
74
|
+
} = props;
|
|
75
|
+
const context = useToastProviderContext(VIEWPORT_NAME, __scopeToast);
|
|
76
|
+
const getItems = useCollection(__scopeToast);
|
|
77
|
+
const wrapperRef = React.useRef(null);
|
|
78
|
+
const headFocusProxyRef = React.useRef(null);
|
|
79
|
+
const tailFocusProxyRef = React.useRef(null);
|
|
80
|
+
const ref = React.useRef(null);
|
|
81
|
+
const composedRefs = useComposedRefs(forwardedRef, ref, context.onViewportChange);
|
|
82
|
+
const hotkeyLabel = hotkey.join("+").replace(/Key/g, "").replace(/Digit/g, "");
|
|
97
83
|
const hasToasts = context.toastCount > 0;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
const handleKeyDown = (event) => {
|
|
86
|
+
const isHotkeyPressed = hotkey.every((key) => event[key] || event.code === key);
|
|
87
|
+
if (isHotkeyPressed) ref.current?.focus();
|
|
88
|
+
};
|
|
89
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
90
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
91
|
+
}, [hotkey]);
|
|
92
|
+
React.useEffect(() => {
|
|
93
|
+
const wrapper = wrapperRef.current;
|
|
94
|
+
const viewport = ref.current;
|
|
95
|
+
if (hasToasts && wrapper && viewport) {
|
|
96
|
+
const handlePause = () => {
|
|
97
|
+
if (!context.isClosePausedRef.current) {
|
|
98
|
+
const pauseEvent = new CustomEvent(VIEWPORT_PAUSE);
|
|
99
|
+
viewport.dispatchEvent(pauseEvent);
|
|
100
|
+
context.isClosePausedRef.current = true;
|
|
101
|
+
}
|
|
106
102
|
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
wrapper.addEventListener('focusout', handleFocusOutResume);
|
|
141
|
-
wrapper.addEventListener('pointermove', handlePause);
|
|
142
|
-
wrapper.addEventListener('pointerleave', handlePointerLeaveResume);
|
|
143
|
-
window.addEventListener('blur', handlePause);
|
|
144
|
-
window.addEventListener('focus', handleResume);
|
|
145
|
-
return ()=>{
|
|
146
|
-
wrapper.removeEventListener('focusin', handlePause);
|
|
147
|
-
wrapper.removeEventListener('focusout', handleFocusOutResume);
|
|
148
|
-
wrapper.removeEventListener('pointermove', handlePause);
|
|
149
|
-
wrapper.removeEventListener('pointerleave', handlePointerLeaveResume);
|
|
150
|
-
window.removeEventListener('blur', handlePause);
|
|
151
|
-
window.removeEventListener('focus', handleResume);
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
}, [
|
|
155
|
-
hasToasts,
|
|
156
|
-
context.isClosePausedRef
|
|
157
|
-
]);
|
|
158
|
-
const getSortedTabbableCandidates = $eyrYI$useCallback(({ tabbingDirection: tabbingDirection })=>{
|
|
103
|
+
const handleResume = () => {
|
|
104
|
+
if (context.isClosePausedRef.current) {
|
|
105
|
+
const resumeEvent = new CustomEvent(VIEWPORT_RESUME);
|
|
106
|
+
viewport.dispatchEvent(resumeEvent);
|
|
107
|
+
context.isClosePausedRef.current = false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const handleFocusOutResume = (event) => {
|
|
111
|
+
const isFocusMovingOutside = !wrapper.contains(event.relatedTarget);
|
|
112
|
+
if (isFocusMovingOutside) handleResume();
|
|
113
|
+
};
|
|
114
|
+
const handlePointerLeaveResume = () => {
|
|
115
|
+
const isFocusInside = wrapper.contains(document.activeElement);
|
|
116
|
+
if (!isFocusInside) handleResume();
|
|
117
|
+
};
|
|
118
|
+
wrapper.addEventListener("focusin", handlePause);
|
|
119
|
+
wrapper.addEventListener("focusout", handleFocusOutResume);
|
|
120
|
+
wrapper.addEventListener("pointermove", handlePause);
|
|
121
|
+
wrapper.addEventListener("pointerleave", handlePointerLeaveResume);
|
|
122
|
+
window.addEventListener("blur", handlePause);
|
|
123
|
+
window.addEventListener("focus", handleResume);
|
|
124
|
+
return () => {
|
|
125
|
+
wrapper.removeEventListener("focusin", handlePause);
|
|
126
|
+
wrapper.removeEventListener("focusout", handleFocusOutResume);
|
|
127
|
+
wrapper.removeEventListener("pointermove", handlePause);
|
|
128
|
+
wrapper.removeEventListener("pointerleave", handlePointerLeaveResume);
|
|
129
|
+
window.removeEventListener("blur", handlePause);
|
|
130
|
+
window.removeEventListener("focus", handleResume);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}, [hasToasts, context.isClosePausedRef]);
|
|
134
|
+
const getSortedTabbableCandidates = React.useCallback(
|
|
135
|
+
({ tabbingDirection }) => {
|
|
159
136
|
const toastItems = getItems();
|
|
160
|
-
const tabbableCandidates = toastItems.map((toastItem)=>{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
...$054eb8030ebde76e$var$getTabbableCandidates(toastNode)
|
|
165
|
-
];
|
|
166
|
-
return tabbingDirection === 'forwards' ? toastTabbableCandidates : toastTabbableCandidates.reverse();
|
|
137
|
+
const tabbableCandidates = toastItems.map((toastItem) => {
|
|
138
|
+
const toastNode = toastItem.ref.current;
|
|
139
|
+
const toastTabbableCandidates = [toastNode, ...getTabbableCandidates(toastNode)];
|
|
140
|
+
return tabbingDirection === "forwards" ? toastTabbableCandidates : toastTabbableCandidates.reverse();
|
|
167
141
|
});
|
|
168
|
-
return (tabbingDirection ===
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}; // Toasts are not in the viewport React tree so we need to bind DOM events
|
|
206
|
-
viewport.addEventListener('keydown', handleKeyDown);
|
|
207
|
-
return ()=>viewport.removeEventListener('keydown', handleKeyDown)
|
|
208
|
-
;
|
|
209
|
-
}
|
|
210
|
-
}, [
|
|
211
|
-
getItems,
|
|
212
|
-
getSortedTabbableCandidates
|
|
213
|
-
]);
|
|
214
|
-
return /*#__PURE__*/ $eyrYI$createElement($eyrYI$Branch, {
|
|
142
|
+
return (tabbingDirection === "forwards" ? tabbableCandidates.reverse() : tabbableCandidates).flat();
|
|
143
|
+
},
|
|
144
|
+
[getItems]
|
|
145
|
+
);
|
|
146
|
+
React.useEffect(() => {
|
|
147
|
+
const viewport = ref.current;
|
|
148
|
+
if (viewport) {
|
|
149
|
+
const handleKeyDown = (event) => {
|
|
150
|
+
const isMetaKey = event.altKey || event.ctrlKey || event.metaKey;
|
|
151
|
+
const isTabKey = event.key === "Tab" && !isMetaKey;
|
|
152
|
+
if (isTabKey) {
|
|
153
|
+
const focusedElement = document.activeElement;
|
|
154
|
+
const isTabbingBackwards = event.shiftKey;
|
|
155
|
+
const targetIsViewport = event.target === viewport;
|
|
156
|
+
if (targetIsViewport && isTabbingBackwards) {
|
|
157
|
+
headFocusProxyRef.current?.focus();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const tabbingDirection = isTabbingBackwards ? "backwards" : "forwards";
|
|
161
|
+
const sortedCandidates = getSortedTabbableCandidates({ tabbingDirection });
|
|
162
|
+
const index = sortedCandidates.findIndex((candidate) => candidate === focusedElement);
|
|
163
|
+
if (focusFirst(sortedCandidates.slice(index + 1))) {
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
} else {
|
|
166
|
+
isTabbingBackwards ? headFocusProxyRef.current?.focus() : tailFocusProxyRef.current?.focus();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
viewport.addEventListener("keydown", handleKeyDown);
|
|
171
|
+
return () => viewport.removeEventListener("keydown", handleKeyDown);
|
|
172
|
+
}
|
|
173
|
+
}, [getItems, getSortedTabbableCandidates]);
|
|
174
|
+
return /* @__PURE__ */ jsxs(
|
|
175
|
+
DismissableLayer.Branch,
|
|
176
|
+
{
|
|
215
177
|
ref: wrapperRef,
|
|
216
178
|
role: "region",
|
|
217
|
-
"aria-label": label.replace(
|
|
218
|
-
,
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
179
|
+
"aria-label": label.replace("{hotkey}", hotkeyLabel),
|
|
180
|
+
tabIndex: -1,
|
|
181
|
+
style: { pointerEvents: hasToasts ? void 0 : "none" },
|
|
182
|
+
children: [
|
|
183
|
+
hasToasts && /* @__PURE__ */ jsx(
|
|
184
|
+
FocusProxy,
|
|
185
|
+
{
|
|
186
|
+
ref: headFocusProxyRef,
|
|
187
|
+
onFocusFromOutsideViewport: () => {
|
|
188
|
+
const tabbableCandidates = getSortedTabbableCandidates({
|
|
189
|
+
tabbingDirection: "forwards"
|
|
190
|
+
});
|
|
191
|
+
focusFirst(tabbableCandidates);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
/* @__PURE__ */ jsx(Collection.Slot, { scope: __scopeToast, children: /* @__PURE__ */ jsx(Primitive.ol, { tabIndex: -1, ...viewportProps, ref: composedRefs }) }),
|
|
196
|
+
hasToasts && /* @__PURE__ */ jsx(
|
|
197
|
+
FocusProxy,
|
|
198
|
+
{
|
|
199
|
+
ref: tailFocusProxyRef,
|
|
200
|
+
onFocusFromOutsideViewport: () => {
|
|
201
|
+
const tabbableCandidates = getSortedTabbableCandidates({
|
|
202
|
+
tabbingDirection: "backwards"
|
|
203
|
+
});
|
|
204
|
+
focusFirst(tabbableCandidates);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
ToastViewport.displayName = VIEWPORT_NAME;
|
|
214
|
+
var FOCUS_PROXY_NAME = "ToastFocusProxy";
|
|
215
|
+
var FocusProxy = React.forwardRef(
|
|
216
|
+
(props, forwardedRef) => {
|
|
217
|
+
const { __scopeToast, onFocusFromOutsideViewport, ...proxyProps } = props;
|
|
218
|
+
const context = useToastProviderContext(FOCUS_PROXY_NAME, __scopeToast);
|
|
219
|
+
return /* @__PURE__ */ jsx(
|
|
220
|
+
VisuallyHidden,
|
|
221
|
+
{
|
|
256
222
|
"aria-hidden": true,
|
|
257
|
-
tabIndex: 0
|
|
258
|
-
|
|
259
|
-
ref: forwardedRef
|
|
260
|
-
,
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
var _context$viewport;
|
|
266
|
-
const prevFocusedElement = event.relatedTarget;
|
|
267
|
-
const isFocusFromOutsideViewport = !((_context$viewport = context.viewport) !== null && _context$viewport !== void 0 && _context$viewport.contains(prevFocusedElement));
|
|
268
|
-
if (isFocusFromOutsideViewport) onFocusFromOutsideViewport();
|
|
223
|
+
tabIndex: 0,
|
|
224
|
+
...proxyProps,
|
|
225
|
+
ref: forwardedRef,
|
|
226
|
+
style: { position: "fixed" },
|
|
227
|
+
onFocus: (event) => {
|
|
228
|
+
const prevFocusedElement = event.relatedTarget;
|
|
229
|
+
const isFocusFromOutsideViewport = !context.viewport?.contains(prevFocusedElement);
|
|
230
|
+
if (isFocusFromOutsideViewport) onFocusFromOutsideViewport();
|
|
269
231
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
onChange: onOpenChange
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
FocusProxy.displayName = FOCUS_PROXY_NAME;
|
|
237
|
+
var TOAST_NAME = "Toast";
|
|
238
|
+
var TOAST_SWIPE_START = "toast.swipeStart";
|
|
239
|
+
var TOAST_SWIPE_MOVE = "toast.swipeMove";
|
|
240
|
+
var TOAST_SWIPE_CANCEL = "toast.swipeCancel";
|
|
241
|
+
var TOAST_SWIPE_END = "toast.swipeEnd";
|
|
242
|
+
var Toast = React.forwardRef(
|
|
243
|
+
(props, forwardedRef) => {
|
|
244
|
+
const { forceMount, open: openProp, defaultOpen, onOpenChange, ...toastProps } = props;
|
|
245
|
+
const [open = true, setOpen] = useControllableState({
|
|
246
|
+
prop: openProp,
|
|
247
|
+
defaultProp: defaultOpen,
|
|
248
|
+
onChange: onOpenChange
|
|
288
249
|
});
|
|
289
|
-
return
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
open
|
|
293
|
-
|
|
250
|
+
return /* @__PURE__ */ jsx(Presence, { present: forceMount || open, children: /* @__PURE__ */ jsx(
|
|
251
|
+
ToastImpl,
|
|
252
|
+
{
|
|
253
|
+
open,
|
|
254
|
+
...toastProps,
|
|
294
255
|
ref: forwardedRef,
|
|
295
|
-
onClose: ()=>setOpen(false)
|
|
296
|
-
,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
event.currentTarget.setAttribute('data-swipe', 'start');
|
|
256
|
+
onClose: () => setOpen(false),
|
|
257
|
+
onPause: useCallbackRef(props.onPause),
|
|
258
|
+
onResume: useCallbackRef(props.onResume),
|
|
259
|
+
onSwipeStart: composeEventHandlers(props.onSwipeStart, (event) => {
|
|
260
|
+
event.currentTarget.setAttribute("data-swipe", "start");
|
|
301
261
|
}),
|
|
302
|
-
onSwipeMove:
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
262
|
+
onSwipeMove: composeEventHandlers(props.onSwipeMove, (event) => {
|
|
263
|
+
const { x, y } = event.detail.delta;
|
|
264
|
+
event.currentTarget.setAttribute("data-swipe", "move");
|
|
265
|
+
event.currentTarget.style.setProperty("--radix-toast-swipe-move-x", `${x}px`);
|
|
266
|
+
event.currentTarget.style.setProperty("--radix-toast-swipe-move-y", `${y}px`);
|
|
307
267
|
}),
|
|
308
|
-
onSwipeCancel:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
268
|
+
onSwipeCancel: composeEventHandlers(props.onSwipeCancel, (event) => {
|
|
269
|
+
event.currentTarget.setAttribute("data-swipe", "cancel");
|
|
270
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-move-x");
|
|
271
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-move-y");
|
|
272
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-end-x");
|
|
273
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-end-y");
|
|
314
274
|
}),
|
|
315
|
-
onSwipeEnd:
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
275
|
+
onSwipeEnd: composeEventHandlers(props.onSwipeEnd, (event) => {
|
|
276
|
+
const { x, y } = event.detail.delta;
|
|
277
|
+
event.currentTarget.setAttribute("data-swipe", "end");
|
|
278
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-move-x");
|
|
279
|
+
event.currentTarget.style.removeProperty("--radix-toast-swipe-move-y");
|
|
280
|
+
event.currentTarget.style.setProperty("--radix-toast-swipe-end-x", `${x}px`);
|
|
281
|
+
event.currentTarget.style.setProperty("--radix-toast-swipe-end-y", `${y}px`);
|
|
282
|
+
setOpen(false);
|
|
323
283
|
})
|
|
324
|
-
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
284
|
+
}
|
|
285
|
+
) });
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
Toast.displayName = TOAST_NAME;
|
|
289
|
+
var [ToastInteractiveProvider, useToastInteractiveContext] = createToastContext(TOAST_NAME, {
|
|
290
|
+
onClose() {
|
|
291
|
+
}
|
|
331
292
|
});
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
293
|
+
var ToastImpl = React.forwardRef(
|
|
294
|
+
(props, forwardedRef) => {
|
|
295
|
+
const {
|
|
296
|
+
__scopeToast,
|
|
297
|
+
type = "foreground",
|
|
298
|
+
duration: durationProp,
|
|
299
|
+
open,
|
|
300
|
+
onClose,
|
|
301
|
+
onEscapeKeyDown,
|
|
302
|
+
onPause,
|
|
303
|
+
onResume,
|
|
304
|
+
onSwipeStart,
|
|
305
|
+
onSwipeMove,
|
|
306
|
+
onSwipeCancel,
|
|
307
|
+
onSwipeEnd,
|
|
308
|
+
...toastProps
|
|
309
|
+
} = props;
|
|
310
|
+
const context = useToastProviderContext(TOAST_NAME, __scopeToast);
|
|
311
|
+
const [node, setNode] = React.useState(null);
|
|
312
|
+
const composedRefs = useComposedRefs(forwardedRef, (node2) => setNode(node2));
|
|
313
|
+
const pointerStartRef = React.useRef(null);
|
|
314
|
+
const swipeDeltaRef = React.useRef(null);
|
|
315
|
+
const duration = durationProp || context.duration;
|
|
316
|
+
const closeTimerStartTimeRef = React.useRef(0);
|
|
317
|
+
const closeTimerRemainingTimeRef = React.useRef(duration);
|
|
318
|
+
const closeTimerRef = React.useRef(0);
|
|
319
|
+
const { onToastAdd, onToastRemove } = context;
|
|
320
|
+
const handleClose = useCallbackRef(() => {
|
|
321
|
+
const isFocusInToast = node?.contains(document.activeElement);
|
|
322
|
+
if (isFocusInToast) context.viewport?.focus();
|
|
323
|
+
onClose();
|
|
352
324
|
});
|
|
353
|
-
const startTimer =
|
|
354
|
-
|
|
325
|
+
const startTimer = React.useCallback(
|
|
326
|
+
(duration2) => {
|
|
327
|
+
if (!duration2 || duration2 === Infinity) return;
|
|
355
328
|
window.clearTimeout(closeTimerRef.current);
|
|
356
|
-
closeTimerStartTimeRef.current = new Date().getTime();
|
|
357
|
-
closeTimerRef.current = window.setTimeout(handleClose,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}, [
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}, [
|
|
393
|
-
open,
|
|
394
|
-
duration1,
|
|
395
|
-
context.isClosePausedRef,
|
|
396
|
-
startTimer
|
|
397
|
-
]);
|
|
398
|
-
$eyrYI$useEffect(()=>{
|
|
399
|
-
onToastAdd();
|
|
400
|
-
return ()=>onToastRemove()
|
|
401
|
-
;
|
|
402
|
-
}, [
|
|
403
|
-
onToastAdd,
|
|
404
|
-
onToastRemove
|
|
405
|
-
]);
|
|
406
|
-
const announceTextContent = $eyrYI$useMemo(()=>{
|
|
407
|
-
return node1 ? $054eb8030ebde76e$var$getAnnounceTextContent(node1) : null;
|
|
408
|
-
}, [
|
|
409
|
-
node1
|
|
410
|
-
]);
|
|
329
|
+
closeTimerStartTimeRef.current = (/* @__PURE__ */ new Date()).getTime();
|
|
330
|
+
closeTimerRef.current = window.setTimeout(handleClose, duration2);
|
|
331
|
+
},
|
|
332
|
+
[handleClose]
|
|
333
|
+
);
|
|
334
|
+
React.useEffect(() => {
|
|
335
|
+
const viewport = context.viewport;
|
|
336
|
+
if (viewport) {
|
|
337
|
+
const handleResume = () => {
|
|
338
|
+
startTimer(closeTimerRemainingTimeRef.current);
|
|
339
|
+
onResume?.();
|
|
340
|
+
};
|
|
341
|
+
const handlePause = () => {
|
|
342
|
+
const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - closeTimerStartTimeRef.current;
|
|
343
|
+
closeTimerRemainingTimeRef.current = closeTimerRemainingTimeRef.current - elapsedTime;
|
|
344
|
+
window.clearTimeout(closeTimerRef.current);
|
|
345
|
+
onPause?.();
|
|
346
|
+
};
|
|
347
|
+
viewport.addEventListener(VIEWPORT_PAUSE, handlePause);
|
|
348
|
+
viewport.addEventListener(VIEWPORT_RESUME, handleResume);
|
|
349
|
+
return () => {
|
|
350
|
+
viewport.removeEventListener(VIEWPORT_PAUSE, handlePause);
|
|
351
|
+
viewport.removeEventListener(VIEWPORT_RESUME, handleResume);
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}, [context.viewport, duration, onPause, onResume, startTimer]);
|
|
355
|
+
React.useEffect(() => {
|
|
356
|
+
if (open && !context.isClosePausedRef.current) startTimer(duration);
|
|
357
|
+
}, [open, duration, context.isClosePausedRef, startTimer]);
|
|
358
|
+
React.useEffect(() => {
|
|
359
|
+
onToastAdd();
|
|
360
|
+
return () => onToastRemove();
|
|
361
|
+
}, [onToastAdd, onToastRemove]);
|
|
362
|
+
const announceTextContent = React.useMemo(() => {
|
|
363
|
+
return node ? getAnnounceTextContent(node) : null;
|
|
364
|
+
}, [node]);
|
|
411
365
|
if (!context.viewport) return null;
|
|
412
|
-
return
|
|
413
|
-
|
|
414
|
-
,
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}, /*#__PURE__*/ $eyrYI$createPortal(/*#__PURE__*/ $eyrYI$createElement($054eb8030ebde76e$var$Collection.ItemSlot, {
|
|
422
|
-
scope: __scopeToast
|
|
423
|
-
}, /*#__PURE__*/ $eyrYI$createElement($eyrYI$Root, {
|
|
424
|
-
asChild: true,
|
|
425
|
-
onEscapeKeyDown: $eyrYI$composeEventHandlers(onEscapeKeyDown, ()=>{
|
|
426
|
-
if (!context.isFocusedToastEscapeKeyDownRef.current) handleClose();
|
|
427
|
-
context.isFocusedToastEscapeKeyDownRef.current = false;
|
|
428
|
-
})
|
|
429
|
-
}, /*#__PURE__*/ $eyrYI$createElement($eyrYI$Primitive.li, $eyrYI$babelruntimehelpersesmextends({
|
|
430
|
-
// Ensure toasts are announced as status list or status when focused
|
|
431
|
-
role: "status",
|
|
432
|
-
"aria-live": "off",
|
|
433
|
-
"aria-atomic": true,
|
|
434
|
-
tabIndex: 0,
|
|
435
|
-
"data-state": open ? 'open' : 'closed',
|
|
436
|
-
"data-swipe-direction": context.swipeDirection
|
|
437
|
-
}, toastProps, {
|
|
438
|
-
ref: composedRefs,
|
|
439
|
-
style: {
|
|
440
|
-
userSelect: 'none',
|
|
441
|
-
touchAction: 'none',
|
|
442
|
-
...props.style
|
|
443
|
-
},
|
|
444
|
-
onKeyDown: $eyrYI$composeEventHandlers(props.onKeyDown, (event)=>{
|
|
445
|
-
if (event.key !== 'Escape') return;
|
|
446
|
-
onEscapeKeyDown === null || onEscapeKeyDown === void 0 || onEscapeKeyDown(event.nativeEvent);
|
|
447
|
-
if (!event.nativeEvent.defaultPrevented) {
|
|
448
|
-
context.isFocusedToastEscapeKeyDownRef.current = true;
|
|
449
|
-
handleClose();
|
|
450
|
-
}
|
|
451
|
-
}),
|
|
452
|
-
onPointerDown: $eyrYI$composeEventHandlers(props.onPointerDown, (event)=>{
|
|
453
|
-
if (event.button !== 0) return;
|
|
454
|
-
pointerStartRef.current = {
|
|
455
|
-
x: event.clientX,
|
|
456
|
-
y: event.clientY
|
|
457
|
-
};
|
|
458
|
-
}),
|
|
459
|
-
onPointerMove: $eyrYI$composeEventHandlers(props.onPointerMove, (event)=>{
|
|
460
|
-
if (!pointerStartRef.current) return;
|
|
461
|
-
const x = event.clientX - pointerStartRef.current.x;
|
|
462
|
-
const y = event.clientY - pointerStartRef.current.y;
|
|
463
|
-
const hasSwipeMoveStarted = Boolean(swipeDeltaRef.current);
|
|
464
|
-
const isHorizontalSwipe = [
|
|
465
|
-
'left',
|
|
466
|
-
'right'
|
|
467
|
-
].includes(context.swipeDirection);
|
|
468
|
-
const clamp = [
|
|
469
|
-
'left',
|
|
470
|
-
'up'
|
|
471
|
-
].includes(context.swipeDirection) ? Math.min : Math.max;
|
|
472
|
-
const clampedX = isHorizontalSwipe ? clamp(0, x) : 0;
|
|
473
|
-
const clampedY = !isHorizontalSwipe ? clamp(0, y) : 0;
|
|
474
|
-
const moveStartBuffer = event.pointerType === 'touch' ? 10 : 2;
|
|
475
|
-
const delta = {
|
|
476
|
-
x: clampedX,
|
|
477
|
-
y: clampedY
|
|
478
|
-
};
|
|
479
|
-
const eventDetail = {
|
|
480
|
-
originalEvent: event,
|
|
481
|
-
delta: delta
|
|
482
|
-
};
|
|
483
|
-
if (hasSwipeMoveStarted) {
|
|
484
|
-
swipeDeltaRef.current = delta;
|
|
485
|
-
$054eb8030ebde76e$var$handleAndDispatchCustomEvent($054eb8030ebde76e$var$TOAST_SWIPE_MOVE, onSwipeMove, eventDetail, {
|
|
486
|
-
discrete: false
|
|
487
|
-
});
|
|
488
|
-
} else if ($054eb8030ebde76e$var$isDeltaInDirection(delta, context.swipeDirection, moveStartBuffer)) {
|
|
489
|
-
swipeDeltaRef.current = delta;
|
|
490
|
-
$054eb8030ebde76e$var$handleAndDispatchCustomEvent($054eb8030ebde76e$var$TOAST_SWIPE_START, onSwipeStart, eventDetail, {
|
|
491
|
-
discrete: false
|
|
492
|
-
});
|
|
493
|
-
event.target.setPointerCapture(event.pointerId);
|
|
494
|
-
} else if (Math.abs(x) > moveStartBuffer || Math.abs(y) > moveStartBuffer) // User is swiping in wrong direction so we disable swipe gesture
|
|
495
|
-
// for the current pointer down interaction
|
|
496
|
-
pointerStartRef.current = null;
|
|
497
|
-
}),
|
|
498
|
-
onPointerUp: $eyrYI$composeEventHandlers(props.onPointerUp, (event1)=>{
|
|
499
|
-
const delta = swipeDeltaRef.current;
|
|
500
|
-
const target = event1.target;
|
|
501
|
-
if (target.hasPointerCapture(event1.pointerId)) target.releasePointerCapture(event1.pointerId);
|
|
502
|
-
swipeDeltaRef.current = null;
|
|
503
|
-
pointerStartRef.current = null;
|
|
504
|
-
if (delta) {
|
|
505
|
-
const toast = event1.currentTarget;
|
|
506
|
-
const eventDetail = {
|
|
507
|
-
originalEvent: event1,
|
|
508
|
-
delta: delta
|
|
509
|
-
};
|
|
510
|
-
if ($054eb8030ebde76e$var$isDeltaInDirection(delta, context.swipeDirection, context.swipeThreshold)) $054eb8030ebde76e$var$handleAndDispatchCustomEvent($054eb8030ebde76e$var$TOAST_SWIPE_END, onSwipeEnd, eventDetail, {
|
|
511
|
-
discrete: true
|
|
512
|
-
});
|
|
513
|
-
else $054eb8030ebde76e$var$handleAndDispatchCustomEvent($054eb8030ebde76e$var$TOAST_SWIPE_CANCEL, onSwipeCancel, eventDetail, {
|
|
514
|
-
discrete: true
|
|
515
|
-
});
|
|
516
|
-
// Prevent click event from triggering on items within the toast when
|
|
517
|
-
// pointer up is part of a swipe gesture
|
|
518
|
-
toast.addEventListener('click', (event)=>event.preventDefault()
|
|
519
|
-
, {
|
|
520
|
-
once: true
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
})
|
|
524
|
-
})))), context.viewport)));
|
|
525
|
-
});
|
|
526
|
-
$054eb8030ebde76e$var$ToastImpl.propTypes = {
|
|
527
|
-
type (props) {
|
|
528
|
-
if (props.type && ![
|
|
529
|
-
'foreground',
|
|
530
|
-
'background'
|
|
531
|
-
].includes(props.type)) {
|
|
532
|
-
const error = `Invalid prop \`type\` supplied to \`${$054eb8030ebde76e$var$TOAST_NAME}\`. Expected \`foreground | background\`.`;
|
|
533
|
-
return new Error(error);
|
|
366
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
367
|
+
announceTextContent && /* @__PURE__ */ jsx(
|
|
368
|
+
ToastAnnounce,
|
|
369
|
+
{
|
|
370
|
+
__scopeToast,
|
|
371
|
+
role: "status",
|
|
372
|
+
"aria-live": type === "foreground" ? "assertive" : "polite",
|
|
373
|
+
"aria-atomic": true,
|
|
374
|
+
children: announceTextContent
|
|
534
375
|
}
|
|
535
|
-
|
|
376
|
+
),
|
|
377
|
+
/* @__PURE__ */ jsx(ToastInteractiveProvider, { scope: __scopeToast, onClose: handleClose, children: ReactDOM.createPortal(
|
|
378
|
+
/* @__PURE__ */ jsx(Collection.ItemSlot, { scope: __scopeToast, children: /* @__PURE__ */ jsx(
|
|
379
|
+
DismissableLayer.Root,
|
|
380
|
+
{
|
|
381
|
+
asChild: true,
|
|
382
|
+
onEscapeKeyDown: composeEventHandlers(onEscapeKeyDown, () => {
|
|
383
|
+
if (!context.isFocusedToastEscapeKeyDownRef.current) handleClose();
|
|
384
|
+
context.isFocusedToastEscapeKeyDownRef.current = false;
|
|
385
|
+
}),
|
|
386
|
+
children: /* @__PURE__ */ jsx(
|
|
387
|
+
Primitive.li,
|
|
388
|
+
{
|
|
389
|
+
role: "status",
|
|
390
|
+
"aria-live": "off",
|
|
391
|
+
"aria-atomic": true,
|
|
392
|
+
tabIndex: 0,
|
|
393
|
+
"data-state": open ? "open" : "closed",
|
|
394
|
+
"data-swipe-direction": context.swipeDirection,
|
|
395
|
+
...toastProps,
|
|
396
|
+
ref: composedRefs,
|
|
397
|
+
style: { userSelect: "none", touchAction: "none", ...props.style },
|
|
398
|
+
onKeyDown: composeEventHandlers(props.onKeyDown, (event) => {
|
|
399
|
+
if (event.key !== "Escape") return;
|
|
400
|
+
onEscapeKeyDown?.(event.nativeEvent);
|
|
401
|
+
if (!event.nativeEvent.defaultPrevented) {
|
|
402
|
+
context.isFocusedToastEscapeKeyDownRef.current = true;
|
|
403
|
+
handleClose();
|
|
404
|
+
}
|
|
405
|
+
}),
|
|
406
|
+
onPointerDown: composeEventHandlers(props.onPointerDown, (event) => {
|
|
407
|
+
if (event.button !== 0) return;
|
|
408
|
+
pointerStartRef.current = { x: event.clientX, y: event.clientY };
|
|
409
|
+
}),
|
|
410
|
+
onPointerMove: composeEventHandlers(props.onPointerMove, (event) => {
|
|
411
|
+
if (!pointerStartRef.current) return;
|
|
412
|
+
const x = event.clientX - pointerStartRef.current.x;
|
|
413
|
+
const y = event.clientY - pointerStartRef.current.y;
|
|
414
|
+
const hasSwipeMoveStarted = Boolean(swipeDeltaRef.current);
|
|
415
|
+
const isHorizontalSwipe = ["left", "right"].includes(context.swipeDirection);
|
|
416
|
+
const clamp = ["left", "up"].includes(context.swipeDirection) ? Math.min : Math.max;
|
|
417
|
+
const clampedX = isHorizontalSwipe ? clamp(0, x) : 0;
|
|
418
|
+
const clampedY = !isHorizontalSwipe ? clamp(0, y) : 0;
|
|
419
|
+
const moveStartBuffer = event.pointerType === "touch" ? 10 : 2;
|
|
420
|
+
const delta = { x: clampedX, y: clampedY };
|
|
421
|
+
const eventDetail = { originalEvent: event, delta };
|
|
422
|
+
if (hasSwipeMoveStarted) {
|
|
423
|
+
swipeDeltaRef.current = delta;
|
|
424
|
+
handleAndDispatchCustomEvent(TOAST_SWIPE_MOVE, onSwipeMove, eventDetail, {
|
|
425
|
+
discrete: false
|
|
426
|
+
});
|
|
427
|
+
} else if (isDeltaInDirection(delta, context.swipeDirection, moveStartBuffer)) {
|
|
428
|
+
swipeDeltaRef.current = delta;
|
|
429
|
+
handleAndDispatchCustomEvent(TOAST_SWIPE_START, onSwipeStart, eventDetail, {
|
|
430
|
+
discrete: false
|
|
431
|
+
});
|
|
432
|
+
event.target.setPointerCapture(event.pointerId);
|
|
433
|
+
} else if (Math.abs(x) > moveStartBuffer || Math.abs(y) > moveStartBuffer) {
|
|
434
|
+
pointerStartRef.current = null;
|
|
435
|
+
}
|
|
436
|
+
}),
|
|
437
|
+
onPointerUp: composeEventHandlers(props.onPointerUp, (event) => {
|
|
438
|
+
const delta = swipeDeltaRef.current;
|
|
439
|
+
const target = event.target;
|
|
440
|
+
if (target.hasPointerCapture(event.pointerId)) {
|
|
441
|
+
target.releasePointerCapture(event.pointerId);
|
|
442
|
+
}
|
|
443
|
+
swipeDeltaRef.current = null;
|
|
444
|
+
pointerStartRef.current = null;
|
|
445
|
+
if (delta) {
|
|
446
|
+
const toast = event.currentTarget;
|
|
447
|
+
const eventDetail = { originalEvent: event, delta };
|
|
448
|
+
if (isDeltaInDirection(delta, context.swipeDirection, context.swipeThreshold)) {
|
|
449
|
+
handleAndDispatchCustomEvent(TOAST_SWIPE_END, onSwipeEnd, eventDetail, {
|
|
450
|
+
discrete: true
|
|
451
|
+
});
|
|
452
|
+
} else {
|
|
453
|
+
handleAndDispatchCustomEvent(
|
|
454
|
+
TOAST_SWIPE_CANCEL,
|
|
455
|
+
onSwipeCancel,
|
|
456
|
+
eventDetail,
|
|
457
|
+
{
|
|
458
|
+
discrete: true
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
toast.addEventListener("click", (event2) => event2.preventDefault(), {
|
|
463
|
+
once: true
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
})
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
) }),
|
|
471
|
+
context.viewport
|
|
472
|
+
) })
|
|
473
|
+
] });
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
ToastImpl.propTypes = {
|
|
477
|
+
type(props) {
|
|
478
|
+
if (props.type && !["foreground", "background"].includes(props.type)) {
|
|
479
|
+
const error = `Invalid prop \`type\` supplied to \`${TOAST_NAME}\`. Expected \`foreground | background\`.`;
|
|
480
|
+
return new Error(error);
|
|
536
481
|
}
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
537
484
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}, /*#__PURE__*/ $eyrYI$createElement($eyrYI$VisuallyHidden, announceProps, renderAnnounceText && /*#__PURE__*/ $eyrYI$createElement($eyrYI$Fragment, null, context.label, " ", children)));
|
|
485
|
+
var ToastAnnounce = (props) => {
|
|
486
|
+
const { __scopeToast, children, ...announceProps } = props;
|
|
487
|
+
const context = useToastProviderContext(TOAST_NAME, __scopeToast);
|
|
488
|
+
const [renderAnnounceText, setRenderAnnounceText] = React.useState(false);
|
|
489
|
+
const [isAnnounced, setIsAnnounced] = React.useState(false);
|
|
490
|
+
useNextFrame(() => setRenderAnnounceText(true));
|
|
491
|
+
React.useEffect(() => {
|
|
492
|
+
const timer = window.setTimeout(() => setIsAnnounced(true), 1e3);
|
|
493
|
+
return () => window.clearTimeout(timer);
|
|
494
|
+
}, []);
|
|
495
|
+
return isAnnounced ? null : /* @__PURE__ */ jsx(Portal, { asChild: true, children: /* @__PURE__ */ jsx(VisuallyHidden, { ...announceProps, children: renderAnnounceText && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
496
|
+
context.label,
|
|
497
|
+
" ",
|
|
498
|
+
children
|
|
499
|
+
] }) }) });
|
|
554
500
|
};
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
/*
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
}
|
|
575
|
-
});
|
|
576
|
-
/*#__PURE__*/ Object.assign($054eb8030ebde76e$export$ecddd96c53621d9a, {
|
|
577
|
-
displayName: $054eb8030ebde76e$var$DESCRIPTION_NAME
|
|
578
|
-
});
|
|
579
|
-
/* -------------------------------------------------------------------------------------------------
|
|
580
|
-
* ToastAction
|
|
581
|
-
* -----------------------------------------------------------------------------------------------*/ const $054eb8030ebde76e$var$ACTION_NAME = 'ToastAction';
|
|
582
|
-
const $054eb8030ebde76e$export$3019feecfda683d2 = /*#__PURE__*/ $eyrYI$forwardRef((props, forwardedRef)=>{
|
|
583
|
-
const { altText: altText , ...actionProps } = props;
|
|
501
|
+
var TITLE_NAME = "ToastTitle";
|
|
502
|
+
var ToastTitle = React.forwardRef(
|
|
503
|
+
(props, forwardedRef) => {
|
|
504
|
+
const { __scopeToast, ...titleProps } = props;
|
|
505
|
+
return /* @__PURE__ */ jsx(Primitive.div, { ...titleProps, ref: forwardedRef });
|
|
506
|
+
}
|
|
507
|
+
);
|
|
508
|
+
ToastTitle.displayName = TITLE_NAME;
|
|
509
|
+
var DESCRIPTION_NAME = "ToastDescription";
|
|
510
|
+
var ToastDescription = React.forwardRef(
|
|
511
|
+
(props, forwardedRef) => {
|
|
512
|
+
const { __scopeToast, ...descriptionProps } = props;
|
|
513
|
+
return /* @__PURE__ */ jsx(Primitive.div, { ...descriptionProps, ref: forwardedRef });
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
ToastDescription.displayName = DESCRIPTION_NAME;
|
|
517
|
+
var ACTION_NAME = "ToastAction";
|
|
518
|
+
var ToastAction = React.forwardRef(
|
|
519
|
+
(props, forwardedRef) => {
|
|
520
|
+
const { altText, ...actionProps } = props;
|
|
584
521
|
if (!altText) return null;
|
|
585
|
-
return
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
});
|
|
592
|
-
$054eb8030ebde76e$export$3019feecfda683d2.propTypes = {
|
|
593
|
-
altText (props) {
|
|
594
|
-
if (!props.altText) return new Error(`Missing prop \`altText\` expected on \`${$054eb8030ebde76e$var$ACTION_NAME}\``);
|
|
595
|
-
return null;
|
|
522
|
+
return /* @__PURE__ */ jsx(ToastAnnounceExclude, { altText, asChild: true, children: /* @__PURE__ */ jsx(ToastClose, { ...actionProps, ref: forwardedRef }) });
|
|
523
|
+
}
|
|
524
|
+
);
|
|
525
|
+
ToastAction.propTypes = {
|
|
526
|
+
altText(props) {
|
|
527
|
+
if (!props.altText) {
|
|
528
|
+
return new Error(`Missing prop \`altText\` expected on \`${ACTION_NAME}\``);
|
|
596
529
|
}
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
597
532
|
};
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}, /*#__PURE__*/ $eyrYI$createElement($eyrYI$Primitive.button, $eyrYI$babelruntimehelpersesmextends({
|
|
610
|
-
type: "button"
|
|
611
|
-
}, closeProps, {
|
|
533
|
+
ToastAction.displayName = ACTION_NAME;
|
|
534
|
+
var CLOSE_NAME = "ToastClose";
|
|
535
|
+
var ToastClose = React.forwardRef(
|
|
536
|
+
(props, forwardedRef) => {
|
|
537
|
+
const { __scopeToast, ...closeProps } = props;
|
|
538
|
+
const interactiveContext = useToastInteractiveContext(CLOSE_NAME, __scopeToast);
|
|
539
|
+
return /* @__PURE__ */ jsx(ToastAnnounceExclude, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
540
|
+
Primitive.button,
|
|
541
|
+
{
|
|
542
|
+
type: "button",
|
|
543
|
+
...closeProps,
|
|
612
544
|
ref: forwardedRef,
|
|
613
|
-
onClick:
|
|
614
|
-
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
545
|
+
onClick: composeEventHandlers(props.onClick, interactiveContext.onClose)
|
|
546
|
+
}
|
|
547
|
+
) });
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
ToastClose.displayName = CLOSE_NAME;
|
|
551
|
+
var ToastAnnounceExclude = React.forwardRef((props, forwardedRef) => {
|
|
552
|
+
const { __scopeToast, altText, ...announceExcludeProps } = props;
|
|
553
|
+
return /* @__PURE__ */ jsx(
|
|
554
|
+
Primitive.div,
|
|
555
|
+
{
|
|
556
|
+
"data-radix-toast-announce-exclude": "",
|
|
557
|
+
"data-radix-toast-announce-alt": altText || void 0,
|
|
558
|
+
...announceExcludeProps,
|
|
559
|
+
ref: forwardedRef
|
|
560
|
+
}
|
|
561
|
+
);
|
|
627
562
|
});
|
|
628
|
-
function
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
563
|
+
function getAnnounceTextContent(container) {
|
|
564
|
+
const textContent = [];
|
|
565
|
+
const childNodes = Array.from(container.childNodes);
|
|
566
|
+
childNodes.forEach((node) => {
|
|
567
|
+
if (node.nodeType === node.TEXT_NODE && node.textContent) textContent.push(node.textContent);
|
|
568
|
+
if (isHTMLElement(node)) {
|
|
569
|
+
const isHidden = node.ariaHidden || node.hidden || node.style.display === "none";
|
|
570
|
+
const isExcluded = node.dataset.radixToastAnnounceExclude === "";
|
|
571
|
+
if (!isHidden) {
|
|
572
|
+
if (isExcluded) {
|
|
573
|
+
const altText = node.dataset.radixToastAnnounceAlt;
|
|
574
|
+
if (altText) textContent.push(altText);
|
|
575
|
+
} else {
|
|
576
|
+
textContent.push(...getAnnounceTextContent(node));
|
|
642
577
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
return textContent;
|
|
646
582
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
});
|
|
657
|
-
if (discrete) $eyrYI$dispatchDiscreteCustomEvent(currentTarget, event);
|
|
658
|
-
else currentTarget.dispatchEvent(event);
|
|
583
|
+
function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) {
|
|
584
|
+
const currentTarget = detail.originalEvent.currentTarget;
|
|
585
|
+
const event = new CustomEvent(name, { bubbles: true, cancelable: true, detail });
|
|
586
|
+
if (handler) currentTarget.addEventListener(name, handler, { once: true });
|
|
587
|
+
if (discrete) {
|
|
588
|
+
dispatchDiscreteCustomEvent(currentTarget, event);
|
|
589
|
+
} else {
|
|
590
|
+
currentTarget.dispatchEvent(event);
|
|
591
|
+
}
|
|
659
592
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
593
|
+
var isDeltaInDirection = (delta, direction, threshold = 0) => {
|
|
594
|
+
const deltaX = Math.abs(delta.x);
|
|
595
|
+
const deltaY = Math.abs(delta.y);
|
|
596
|
+
const isDeltaX = deltaX > deltaY;
|
|
597
|
+
if (direction === "left" || direction === "right") {
|
|
598
|
+
return isDeltaX && deltaX > threshold;
|
|
599
|
+
} else {
|
|
600
|
+
return !isDeltaX && deltaY > threshold;
|
|
601
|
+
}
|
|
666
602
|
};
|
|
667
|
-
function
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
fn
|
|
680
|
-
]);
|
|
603
|
+
function useNextFrame(callback = () => {
|
|
604
|
+
}) {
|
|
605
|
+
const fn = useCallbackRef(callback);
|
|
606
|
+
useLayoutEffect(() => {
|
|
607
|
+
let raf1 = 0;
|
|
608
|
+
let raf2 = 0;
|
|
609
|
+
raf1 = window.requestAnimationFrame(() => raf2 = window.requestAnimationFrame(fn));
|
|
610
|
+
return () => {
|
|
611
|
+
window.cancelAnimationFrame(raf1);
|
|
612
|
+
window.cancelAnimationFrame(raf2);
|
|
613
|
+
};
|
|
614
|
+
}, [fn]);
|
|
681
615
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
616
|
+
function isHTMLElement(node) {
|
|
617
|
+
return node.nodeType === node.ELEMENT_NODE;
|
|
684
618
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
697
|
-
acceptNode: (node)=>{
|
|
698
|
-
const isHiddenInput = node.tagName === 'INPUT' && node.type === 'hidden';
|
|
699
|
-
if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP; // `.tabIndex` is not the same as the `tabindex` attribute. It works on the
|
|
700
|
-
// runtime's understanding of tabbability, so this automatically accounts
|
|
701
|
-
// for any kind of element that could be tabbed to.
|
|
702
|
-
return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
703
|
-
}
|
|
704
|
-
});
|
|
705
|
-
while(walker.nextNode())nodes.push(walker.currentNode); // we do not take into account the order of nodes with positive `tabIndex` as it
|
|
706
|
-
// hinders accessibility to have tab order different from visual order.
|
|
707
|
-
return nodes;
|
|
619
|
+
function getTabbableCandidates(container) {
|
|
620
|
+
const nodes = [];
|
|
621
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {
|
|
622
|
+
acceptNode: (node) => {
|
|
623
|
+
const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden";
|
|
624
|
+
if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP;
|
|
625
|
+
return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
while (walker.nextNode()) nodes.push(walker.currentNode);
|
|
629
|
+
return nodes;
|
|
708
630
|
}
|
|
709
|
-
function
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
});
|
|
631
|
+
function focusFirst(candidates) {
|
|
632
|
+
const previouslyFocusedElement = document.activeElement;
|
|
633
|
+
return candidates.some((candidate) => {
|
|
634
|
+
if (candidate === previouslyFocusedElement) return true;
|
|
635
|
+
candidate.focus();
|
|
636
|
+
return document.activeElement !== previouslyFocusedElement;
|
|
637
|
+
});
|
|
717
638
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
639
|
+
var Provider = ToastProvider;
|
|
640
|
+
var Viewport = ToastViewport;
|
|
641
|
+
var Root2 = Toast;
|
|
642
|
+
var Title = ToastTitle;
|
|
643
|
+
var Description = ToastDescription;
|
|
644
|
+
var Action = ToastAction;
|
|
645
|
+
var Close = ToastClose;
|
|
646
|
+
export {
|
|
647
|
+
Action,
|
|
648
|
+
Close,
|
|
649
|
+
Description,
|
|
650
|
+
Provider,
|
|
651
|
+
Root2 as Root,
|
|
652
|
+
Title,
|
|
653
|
+
Toast,
|
|
654
|
+
ToastAction,
|
|
655
|
+
ToastClose,
|
|
656
|
+
ToastDescription,
|
|
657
|
+
ToastProvider,
|
|
658
|
+
ToastTitle,
|
|
659
|
+
ToastViewport,
|
|
660
|
+
Viewport,
|
|
661
|
+
createToastScope
|
|
662
|
+
};
|
|
730
663
|
//# sourceMappingURL=index.mjs.map
|