react-native-sooner 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +376 -0
- package/lib/module/constants.js +40 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/context.js +25 -0
- package/lib/module/context.js.map +1 -0
- package/lib/module/easings.js +9 -0
- package/lib/module/easings.js.map +1 -0
- package/lib/module/gestures.js +119 -0
- package/lib/module/gestures.js.map +1 -0
- package/lib/module/hooks.js +9 -0
- package/lib/module/hooks.js.map +1 -0
- package/lib/module/icons.js +332 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/state.js +200 -0
- package/lib/module/state.js.map +1 -0
- package/lib/module/theme.js +189 -0
- package/lib/module/theme.js.map +1 -0
- package/lib/module/toast.js +362 -0
- package/lib/module/toast.js.map +1 -0
- package/lib/module/toaster.js +198 -0
- package/lib/module/toaster.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/use-app-state.js +13 -0
- package/lib/module/use-app-state.js.map +1 -0
- package/lib/module/use-pauseable-timer.js +18 -0
- package/lib/module/use-pauseable-timer.js.map +1 -0
- package/lib/module/use-toast-state.js +37 -0
- package/lib/module/use-toast-state.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/constants.d.ts +32 -0
- package/lib/typescript/src/constants.d.ts.map +1 -0
- package/lib/typescript/src/context.d.ts +20 -0
- package/lib/typescript/src/context.d.ts.map +1 -0
- package/lib/typescript/src/easings.d.ts +6 -0
- package/lib/typescript/src/easings.d.ts.map +1 -0
- package/lib/typescript/src/gestures.d.ts +17 -0
- package/lib/typescript/src/gestures.d.ts.map +1 -0
- package/lib/typescript/src/hooks.d.ts +5 -0
- package/lib/typescript/src/hooks.d.ts.map +1 -0
- package/lib/typescript/src/icons.d.ts +15 -0
- package/lib/typescript/src/icons.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/state.d.ts +66 -0
- package/lib/typescript/src/state.d.ts.map +1 -0
- package/lib/typescript/src/theme.d.ts +163 -0
- package/lib/typescript/src/theme.d.ts.map +1 -0
- package/lib/typescript/src/toast.d.ts +3 -0
- package/lib/typescript/src/toast.d.ts.map +1 -0
- package/lib/typescript/src/toaster.d.ts +3 -0
- package/lib/typescript/src/toaster.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +264 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/use-app-state.d.ts +3 -0
- package/lib/typescript/src/use-app-state.d.ts.map +1 -0
- package/lib/typescript/src/use-pauseable-timer.d.ts +2 -0
- package/lib/typescript/src/use-pauseable-timer.d.ts.map +1 -0
- package/lib/typescript/src/use-toast-state.d.ts +7 -0
- package/lib/typescript/src/use-toast-state.d.ts.map +1 -0
- package/package.json +152 -0
- package/src/constants.ts +44 -0
- package/src/context.tsx +38 -0
- package/src/easings.ts +7 -0
- package/src/gestures.tsx +135 -0
- package/src/hooks.ts +3 -0
- package/src/icons.tsx +227 -0
- package/src/index.tsx +48 -0
- package/src/state.ts +262 -0
- package/src/theme.ts +170 -0
- package/src/toast.tsx +429 -0
- package/src/toaster.tsx +221 -0
- package/src/types.ts +311 -0
- package/src/use-app-state.ts +15 -0
- package/src/use-pauseable-timer.ts +24 -0
- package/src/use-toast-state.ts +43 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { AccessibilityRole, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toast variant types
|
|
6
|
+
*/
|
|
7
|
+
export type ToastType =
|
|
8
|
+
| "default"
|
|
9
|
+
| "success"
|
|
10
|
+
| "error"
|
|
11
|
+
| "warning"
|
|
12
|
+
| "info"
|
|
13
|
+
| "loading";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Position of the toast on screen
|
|
17
|
+
*/
|
|
18
|
+
export type Position =
|
|
19
|
+
| "top-left"
|
|
20
|
+
| "top-center"
|
|
21
|
+
| "top-right"
|
|
22
|
+
| "bottom-left"
|
|
23
|
+
| "bottom-center"
|
|
24
|
+
| "bottom-right";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Swipe direction to dismiss
|
|
28
|
+
*/
|
|
29
|
+
export type SwipeDirection = "left" | "right" | "up" | "down";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Theme options
|
|
33
|
+
*/
|
|
34
|
+
export type Theme = "light" | "dark" | "system";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolved theme (without system)
|
|
38
|
+
*/
|
|
39
|
+
export type ResolvedTheme = "light" | "dark";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Action button configuration
|
|
43
|
+
*/
|
|
44
|
+
export interface Action {
|
|
45
|
+
label: string;
|
|
46
|
+
onClick: (toast: ToastT) => void;
|
|
47
|
+
style?: StyleProp<ViewStyle>;
|
|
48
|
+
textStyle?: StyleProp<TextStyle>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Promise data for toast.promise()
|
|
53
|
+
*/
|
|
54
|
+
export interface PromiseData<T = unknown> {
|
|
55
|
+
loading: string | ReactNode;
|
|
56
|
+
success: string | ReactNode | ((data: T) => string | ReactNode);
|
|
57
|
+
error: string | ReactNode | ((error: unknown) => string | ReactNode);
|
|
58
|
+
finally?: () => void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Custom icons for toast types
|
|
63
|
+
*/
|
|
64
|
+
export interface ToastIcons {
|
|
65
|
+
success?: ReactNode;
|
|
66
|
+
error?: ReactNode;
|
|
67
|
+
warning?: ReactNode;
|
|
68
|
+
info?: ReactNode;
|
|
69
|
+
loading?: ReactNode;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Custom styles for toast parts
|
|
74
|
+
*/
|
|
75
|
+
export interface ToastStyles {
|
|
76
|
+
container?: StyleProp<ViewStyle>;
|
|
77
|
+
content?: StyleProp<ViewStyle>;
|
|
78
|
+
title?: StyleProp<TextStyle>;
|
|
79
|
+
description?: StyleProp<TextStyle>;
|
|
80
|
+
actionButton?: StyleProp<ViewStyle>;
|
|
81
|
+
actionButtonText?: StyleProp<TextStyle>;
|
|
82
|
+
cancelButton?: StyleProp<ViewStyle>;
|
|
83
|
+
cancelButtonText?: StyleProp<TextStyle>;
|
|
84
|
+
closeButton?: StyleProp<ViewStyle>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Animation configuration
|
|
89
|
+
*/
|
|
90
|
+
export interface AnimationConfig {
|
|
91
|
+
/** Entry animation duration in ms @default 350 */
|
|
92
|
+
duration?: number;
|
|
93
|
+
/** Exit animation duration in ms @default 200 */
|
|
94
|
+
exitDuration?: number;
|
|
95
|
+
/** Use spring animation for entry @default true */
|
|
96
|
+
useSpring?: boolean;
|
|
97
|
+
/** Spring damping @default 18 */
|
|
98
|
+
damping?: number;
|
|
99
|
+
/** Spring stiffness @default 140 */
|
|
100
|
+
stiffness?: number;
|
|
101
|
+
/** Spring mass @default 1 */
|
|
102
|
+
mass?: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Accessibility configuration
|
|
107
|
+
*/
|
|
108
|
+
export interface AccessibilityConfig {
|
|
109
|
+
/** Accessibility role @default "alert" */
|
|
110
|
+
role?: AccessibilityRole;
|
|
111
|
+
/** Whether to announce toast to screen readers @default true */
|
|
112
|
+
announceToScreenReader?: boolean;
|
|
113
|
+
/** Custom accessibility label */
|
|
114
|
+
accessibilityLabel?: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Internal toast data structure
|
|
119
|
+
*/
|
|
120
|
+
export interface ToastT {
|
|
121
|
+
id: string | number;
|
|
122
|
+
type: ToastType;
|
|
123
|
+
title: string | ReactNode;
|
|
124
|
+
description?: string | ReactNode;
|
|
125
|
+
icon?: ReactNode;
|
|
126
|
+
duration?: number;
|
|
127
|
+
dismissible?: boolean;
|
|
128
|
+
action?: Action;
|
|
129
|
+
cancel?: Action;
|
|
130
|
+
onDismiss?: (toast: ToastT) => void;
|
|
131
|
+
onAutoClose?: (toast: ToastT) => void;
|
|
132
|
+
styles?: ToastStyles;
|
|
133
|
+
/** Mark toast as important (won't be auto-dismissed when queue is full) */
|
|
134
|
+
important?: boolean;
|
|
135
|
+
/** Toaster ID to target specific Toaster instance */
|
|
136
|
+
toasterId?: string;
|
|
137
|
+
/** Internal: timestamp when created */
|
|
138
|
+
createdAt: number;
|
|
139
|
+
/** Internal: whether this toast is being dismissed */
|
|
140
|
+
dismissed?: boolean;
|
|
141
|
+
/** Animation configuration for this toast */
|
|
142
|
+
animation?: AnimationConfig;
|
|
143
|
+
/** Accessibility configuration */
|
|
144
|
+
accessibility?: AccessibilityConfig;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Options for updating a toast
|
|
149
|
+
*/
|
|
150
|
+
export type UpdateToastOptions = Partial<Omit<ToastT, "id" | "createdAt">>;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* External toast options (what users pass to toast())
|
|
154
|
+
*/
|
|
155
|
+
export type ExternalToast = Omit<ToastT, "id" | "type" | "title" | "createdAt"> & {
|
|
156
|
+
/** Optional custom ID for the toast */
|
|
157
|
+
id?: string | number;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Toast height tracking for stacking
|
|
162
|
+
*/
|
|
163
|
+
export interface HeightT {
|
|
164
|
+
toastId: string | number;
|
|
165
|
+
height: number;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Toaster component props
|
|
170
|
+
*/
|
|
171
|
+
export interface ToasterProps {
|
|
172
|
+
/**
|
|
173
|
+
* Position of toasts on screen
|
|
174
|
+
* @default "top-center"
|
|
175
|
+
*/
|
|
176
|
+
position?: Position;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Theme for toasts
|
|
180
|
+
* @default "system"
|
|
181
|
+
*/
|
|
182
|
+
theme?: Theme;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Maximum number of visible toasts (excess queued)
|
|
186
|
+
* @default 5
|
|
187
|
+
*/
|
|
188
|
+
visibleToasts?: number;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Default duration in milliseconds
|
|
192
|
+
* @default 3000
|
|
193
|
+
*/
|
|
194
|
+
duration?: number;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Gap between toasts in pixels
|
|
198
|
+
* @default 12
|
|
199
|
+
*/
|
|
200
|
+
gap?: number;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Offset from screen edges
|
|
204
|
+
* @default { top: 52, bottom: 52, left: 16, right: 16 }
|
|
205
|
+
*/
|
|
206
|
+
offset?: {
|
|
207
|
+
top?: number;
|
|
208
|
+
bottom?: number;
|
|
209
|
+
left?: number;
|
|
210
|
+
right?: number;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Enable swipe to dismiss
|
|
215
|
+
* @default true
|
|
216
|
+
*/
|
|
217
|
+
swipeToDismiss?: boolean;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Swipe direction(s) to dismiss
|
|
221
|
+
* @default ["left", "right"]
|
|
222
|
+
*/
|
|
223
|
+
swipeDirection?: SwipeDirection | SwipeDirection[];
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Pause toast timer when app is in background
|
|
227
|
+
* @default true
|
|
228
|
+
*/
|
|
229
|
+
pauseOnAppBackground?: boolean;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Custom icons for toast types
|
|
233
|
+
*/
|
|
234
|
+
icons?: ToastIcons;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Default styles for all toasts
|
|
238
|
+
*/
|
|
239
|
+
toastStyles?: ToastStyles;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Custom container style
|
|
243
|
+
*/
|
|
244
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Rich colors mode (more vibrant backgrounds)
|
|
248
|
+
* @default false
|
|
249
|
+
*/
|
|
250
|
+
richColors?: boolean;
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Close button on toasts
|
|
254
|
+
* @default false
|
|
255
|
+
*/
|
|
256
|
+
closeButton?: boolean;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Only show toasts with matching toasterId
|
|
260
|
+
*/
|
|
261
|
+
toasterId?: string;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Default animation configuration
|
|
265
|
+
*/
|
|
266
|
+
animation?: AnimationConfig;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Enable haptic feedback on toast actions
|
|
270
|
+
* @default false
|
|
271
|
+
*/
|
|
272
|
+
hapticFeedback?: boolean;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Individual toast component props (internal)
|
|
277
|
+
*/
|
|
278
|
+
export interface ToastProps {
|
|
279
|
+
toast: ToastT;
|
|
280
|
+
position: Position;
|
|
281
|
+
gap: number;
|
|
282
|
+
swipeToDismiss: boolean;
|
|
283
|
+
swipeDirection: SwipeDirection[];
|
|
284
|
+
theme: ResolvedTheme;
|
|
285
|
+
richColors: boolean;
|
|
286
|
+
closeButton: boolean;
|
|
287
|
+
icons?: ToastIcons;
|
|
288
|
+
defaultStyles?: ToastStyles;
|
|
289
|
+
defaultAnimation?: AnimationConfig;
|
|
290
|
+
onDismiss: (toastId: string | number) => void;
|
|
291
|
+
/** Default duration for auto-dismiss */
|
|
292
|
+
duration: number;
|
|
293
|
+
/** Pause timer when app goes to background */
|
|
294
|
+
pauseOnAppBackground: boolean;
|
|
295
|
+
hapticFeedback?: boolean;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Toast state subscriber callback
|
|
300
|
+
*/
|
|
301
|
+
export type ToastStateSubscriber = (toast: ToastT) => void;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Toast dismiss subscriber callback
|
|
305
|
+
*/
|
|
306
|
+
export type ToastDismissSubscriber = (toastId: string | number | undefined) => void;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Toast update subscriber callback
|
|
310
|
+
*/
|
|
311
|
+
export type ToastUpdateSubscriber = (toast: ToastT) => void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { AppState, type AppStateStatus } from "react-native";
|
|
3
|
+
|
|
4
|
+
export function useAppState(): AppStateStatus {
|
|
5
|
+
const [appState, setAppState] = useState<AppStateStatus>(
|
|
6
|
+
AppState.currentState as AppStateStatus
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const subscription = AppState.addEventListener("change", setAppState);
|
|
11
|
+
return () => subscription.remove();
|
|
12
|
+
}, []);
|
|
13
|
+
|
|
14
|
+
return appState;
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useAppState } from "./use-app-state";
|
|
3
|
+
|
|
4
|
+
export function usePauseableTimer(
|
|
5
|
+
callback: () => void,
|
|
6
|
+
duration: number,
|
|
7
|
+
enabled: boolean,
|
|
8
|
+
pauseOnBackground: boolean
|
|
9
|
+
): void {
|
|
10
|
+
const appState = useAppState();
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!enabled || duration <= 0 || duration === Number.POSITIVE_INFINITY) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (pauseOnBackground && appState !== "active") {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const timer = setTimeout(callback, duration);
|
|
22
|
+
return () => clearTimeout(timer);
|
|
23
|
+
}, [callback, duration, enabled, pauseOnBackground, appState]);
|
|
24
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { ToastState } from "./state";
|
|
3
|
+
import type { ToastT } from "./types";
|
|
4
|
+
|
|
5
|
+
export function useToastState() {
|
|
6
|
+
const [toasts, setToasts] = useState<ToastT[]>(() => ToastState.getToasts());
|
|
7
|
+
const toastsRef = useRef(toasts);
|
|
8
|
+
toastsRef.current = toasts;
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const unsubscribeCreate = ToastState.subscribe(() => {
|
|
12
|
+
setToasts(ToastState.getToasts());
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const unsubscribeDismiss = ToastState.subscribeToDismiss(() => {
|
|
16
|
+
setToasts(ToastState.getToasts());
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const unsubscribeUpdate = ToastState.subscribeToUpdate(() => {
|
|
20
|
+
setToasts(ToastState.getToasts());
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return () => {
|
|
24
|
+
unsubscribeCreate();
|
|
25
|
+
unsubscribeDismiss();
|
|
26
|
+
unsubscribeUpdate();
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
const getToast = useCallback((id: string | number) => {
|
|
31
|
+
return toastsRef.current.find((t) => t.id === id);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
const isActive = useCallback((id: string | number) => {
|
|
35
|
+
return toastsRef.current.some((t) => t.id === id);
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
toasts,
|
|
40
|
+
getToast,
|
|
41
|
+
isActive,
|
|
42
|
+
};
|
|
43
|
+
}
|