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