rnnovaui 0.7.0 → 0.7.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/package.json
CHANGED
|
@@ -3,35 +3,142 @@ import React, {
|
|
|
3
3
|
useCallback,
|
|
4
4
|
useContext,
|
|
5
5
|
useMemo,
|
|
6
|
+
useRef,
|
|
6
7
|
useState,
|
|
7
8
|
} from "react";
|
|
8
9
|
|
|
10
|
+
import { StyleSheet, View } from "react-native";
|
|
11
|
+
|
|
9
12
|
import { UIToast } from "./UIToast";
|
|
10
13
|
|
|
11
14
|
const ToastContext = createContext(null);
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
const DEFAULT_MAX_TOASTS = 3;
|
|
17
|
+
|
|
18
|
+
let toastIdCounter = 0;
|
|
19
|
+
|
|
20
|
+
function createToastId() {
|
|
21
|
+
toastIdCounter += 1;
|
|
22
|
+
|
|
23
|
+
return `ui-toast-${Date.now()}-${toastIdCounter}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function UIToastProvider({
|
|
27
|
+
children,
|
|
28
|
+
maxToasts = DEFAULT_MAX_TOASTS,
|
|
29
|
+
defaultDuration = 3000,
|
|
30
|
+
}) {
|
|
14
31
|
const [toasts, setToasts] = useState([]);
|
|
15
32
|
|
|
33
|
+
const mountedRef = useRef(true);
|
|
34
|
+
|
|
35
|
+
const timersRef = useRef(new Map());
|
|
36
|
+
|
|
16
37
|
const removeToast = useCallback((id) => {
|
|
38
|
+
const timer = timersRef.current.get(id);
|
|
39
|
+
|
|
40
|
+
if (timer) {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
|
|
43
|
+
timersRef.current.delete(id);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!mountedRef.current) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
17
50
|
setToasts((previous) => previous.filter((toast) => toast.id !== id));
|
|
18
51
|
}, []);
|
|
19
52
|
|
|
53
|
+
const scheduleDismiss = useCallback(
|
|
54
|
+
(id, duration) => {
|
|
55
|
+
if (!duration || duration <= 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const existingTimer = timersRef.current.get(id);
|
|
60
|
+
|
|
61
|
+
if (existingTimer) {
|
|
62
|
+
clearTimeout(existingTimer);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const timer = setTimeout(() => {
|
|
66
|
+
timersRef.current.delete(id);
|
|
67
|
+
|
|
68
|
+
removeToast(id);
|
|
69
|
+
}, duration);
|
|
70
|
+
|
|
71
|
+
timersRef.current.set(id, timer);
|
|
72
|
+
},
|
|
73
|
+
[removeToast],
|
|
74
|
+
);
|
|
75
|
+
|
|
20
76
|
const showToast = useCallback(
|
|
21
|
-
(options) => {
|
|
22
|
-
const id = options
|
|
77
|
+
(options = {}) => {
|
|
78
|
+
const id = options.id || createToastId();
|
|
79
|
+
|
|
80
|
+
const duration =
|
|
81
|
+
options.duration !== undefined ? options.duration : defaultDuration;
|
|
23
82
|
|
|
24
83
|
const toast = {
|
|
25
84
|
...options,
|
|
85
|
+
|
|
26
86
|
id,
|
|
87
|
+
|
|
27
88
|
visible: true,
|
|
89
|
+
|
|
90
|
+
duration,
|
|
28
91
|
};
|
|
29
92
|
|
|
30
|
-
setToasts((previous) =>
|
|
93
|
+
setToasts((previous) => {
|
|
94
|
+
const filtered = previous.filter((item) => item.id !== id);
|
|
95
|
+
|
|
96
|
+
const next = [...filtered, toast];
|
|
97
|
+
|
|
98
|
+
if (next.length <= maxToasts) {
|
|
99
|
+
return next;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const removed = next.slice(0, next.length - maxToasts);
|
|
103
|
+
|
|
104
|
+
removed.forEach((item) => {
|
|
105
|
+
const timer = timersRef.current.get(item.id);
|
|
106
|
+
|
|
107
|
+
if (timer) {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
|
|
110
|
+
timersRef.current.delete(item.id);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return next.slice(-maxToasts);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
scheduleDismiss(id, duration);
|
|
31
118
|
|
|
32
119
|
return id;
|
|
33
120
|
},
|
|
34
|
-
[maxToasts],
|
|
121
|
+
[defaultDuration, maxToasts, scheduleDismiss],
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const updateToast = useCallback(
|
|
125
|
+
(id, updates = {}) => {
|
|
126
|
+
setToasts((previous) =>
|
|
127
|
+
previous.map((toast) =>
|
|
128
|
+
toast.id === id
|
|
129
|
+
? {
|
|
130
|
+
...toast,
|
|
131
|
+
...updates,
|
|
132
|
+
}
|
|
133
|
+
: toast,
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (updates.duration !== undefined) {
|
|
138
|
+
scheduleDismiss(id, updates.duration);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
[scheduleDismiss],
|
|
35
142
|
);
|
|
36
143
|
|
|
37
144
|
const dismissToast = useCallback(
|
|
@@ -41,75 +148,176 @@ function UIToastProvider({ children, maxToasts = 3 }) {
|
|
|
41
148
|
[removeToast],
|
|
42
149
|
);
|
|
43
150
|
|
|
151
|
+
const dismissAll = useCallback(() => {
|
|
152
|
+
timersRef.current.forEach((timer) => {
|
|
153
|
+
clearTimeout(timer);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
timersRef.current.clear();
|
|
157
|
+
|
|
158
|
+
setToasts([]);
|
|
159
|
+
}, []);
|
|
160
|
+
|
|
44
161
|
const success = useCallback(
|
|
45
|
-
(message, options = {}) =>
|
|
46
|
-
showToast({
|
|
162
|
+
(message, options = {}) => {
|
|
163
|
+
return showToast({
|
|
47
164
|
...options,
|
|
165
|
+
|
|
48
166
|
message,
|
|
167
|
+
|
|
49
168
|
variant: "success",
|
|
50
|
-
})
|
|
169
|
+
});
|
|
170
|
+
},
|
|
51
171
|
[showToast],
|
|
52
172
|
);
|
|
53
173
|
|
|
54
174
|
const error = useCallback(
|
|
55
|
-
(message, options = {}) =>
|
|
56
|
-
showToast({
|
|
175
|
+
(message, options = {}) => {
|
|
176
|
+
return showToast({
|
|
57
177
|
...options,
|
|
178
|
+
|
|
58
179
|
message,
|
|
180
|
+
|
|
59
181
|
variant: "danger",
|
|
60
|
-
})
|
|
182
|
+
});
|
|
183
|
+
},
|
|
61
184
|
[showToast],
|
|
62
185
|
);
|
|
63
186
|
|
|
64
187
|
const warning = useCallback(
|
|
65
|
-
(message, options = {}) =>
|
|
66
|
-
showToast({
|
|
188
|
+
(message, options = {}) => {
|
|
189
|
+
return showToast({
|
|
67
190
|
...options,
|
|
191
|
+
|
|
68
192
|
message,
|
|
193
|
+
|
|
69
194
|
variant: "warning",
|
|
70
|
-
})
|
|
195
|
+
});
|
|
196
|
+
},
|
|
71
197
|
[showToast],
|
|
72
198
|
);
|
|
73
199
|
|
|
74
200
|
const info = useCallback(
|
|
75
|
-
(message, options = {}) =>
|
|
76
|
-
showToast({
|
|
201
|
+
(message, options = {}) => {
|
|
202
|
+
return showToast({
|
|
77
203
|
...options,
|
|
204
|
+
|
|
78
205
|
message,
|
|
206
|
+
|
|
79
207
|
variant: "info",
|
|
80
|
-
})
|
|
208
|
+
});
|
|
209
|
+
},
|
|
81
210
|
[showToast],
|
|
82
211
|
);
|
|
83
212
|
|
|
84
|
-
const
|
|
85
|
-
|
|
213
|
+
const primary = useCallback(
|
|
214
|
+
(message, options = {}) => {
|
|
215
|
+
return showToast({
|
|
216
|
+
...options,
|
|
217
|
+
|
|
218
|
+
message,
|
|
219
|
+
|
|
220
|
+
variant: "primary",
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
[showToast],
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const toast = useCallback(
|
|
227
|
+
(message, options = {}) => {
|
|
228
|
+
return showToast({
|
|
229
|
+
...options,
|
|
230
|
+
|
|
231
|
+
message,
|
|
232
|
+
|
|
233
|
+
variant: options.variant || "default",
|
|
234
|
+
});
|
|
235
|
+
},
|
|
236
|
+
[showToast],
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
/*
|
|
240
|
+
* Cleanup timers when
|
|
241
|
+
* provider unmounts.
|
|
242
|
+
*/
|
|
243
|
+
React.useEffect(() => {
|
|
244
|
+
mountedRef.current = true;
|
|
245
|
+
|
|
246
|
+
return () => {
|
|
247
|
+
mountedRef.current = false;
|
|
248
|
+
|
|
249
|
+
timersRef.current.forEach((timer) => {
|
|
250
|
+
clearTimeout(timer);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
timersRef.current.clear();
|
|
254
|
+
};
|
|
86
255
|
}, []);
|
|
87
256
|
|
|
88
257
|
const contextValue = useMemo(
|
|
89
258
|
() => ({
|
|
259
|
+
toasts,
|
|
260
|
+
|
|
90
261
|
showToast,
|
|
262
|
+
|
|
263
|
+
updateToast,
|
|
264
|
+
|
|
91
265
|
dismissToast,
|
|
266
|
+
|
|
267
|
+
dismissAll,
|
|
268
|
+
|
|
269
|
+
toast,
|
|
270
|
+
|
|
92
271
|
success,
|
|
272
|
+
|
|
93
273
|
error,
|
|
274
|
+
|
|
94
275
|
warning,
|
|
276
|
+
|
|
95
277
|
info,
|
|
96
|
-
|
|
278
|
+
|
|
279
|
+
primary,
|
|
97
280
|
}),
|
|
98
|
-
[
|
|
281
|
+
[
|
|
282
|
+
toasts,
|
|
283
|
+
showToast,
|
|
284
|
+
updateToast,
|
|
285
|
+
dismissToast,
|
|
286
|
+
dismissAll,
|
|
287
|
+
toast,
|
|
288
|
+
success,
|
|
289
|
+
error,
|
|
290
|
+
warning,
|
|
291
|
+
info,
|
|
292
|
+
primary,
|
|
293
|
+
],
|
|
99
294
|
);
|
|
100
295
|
|
|
101
296
|
return (
|
|
102
297
|
<ToastContext.Provider value={contextValue}>
|
|
103
298
|
{children}
|
|
104
299
|
|
|
300
|
+
<ToastContainer toasts={toasts} onDismiss={dismissToast} />
|
|
301
|
+
</ToastContext.Provider>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function ToastContainer({ toasts, onDismiss }) {
|
|
306
|
+
/*
|
|
307
|
+
* Keep toast rendering
|
|
308
|
+
* outside the main application
|
|
309
|
+
* layout.
|
|
310
|
+
*/
|
|
311
|
+
return (
|
|
312
|
+
<View pointerEvents="box-none" style={styles.container}>
|
|
105
313
|
{toasts.map((toast) => (
|
|
106
314
|
<UIToast
|
|
107
315
|
key={toast.id}
|
|
108
316
|
{...toast}
|
|
109
|
-
onDismiss={() =>
|
|
317
|
+
onDismiss={() => onDismiss(toast.id)}
|
|
110
318
|
/>
|
|
111
319
|
))}
|
|
112
|
-
</
|
|
320
|
+
</View>
|
|
113
321
|
);
|
|
114
322
|
}
|
|
115
323
|
|
|
@@ -123,4 +331,35 @@ export function useUIToast() {
|
|
|
123
331
|
return context;
|
|
124
332
|
}
|
|
125
333
|
|
|
334
|
+
/*
|
|
335
|
+
* IMPORTANT:
|
|
336
|
+
* Named export.
|
|
337
|
+
*
|
|
338
|
+
* This prevents:
|
|
339
|
+
*
|
|
340
|
+
* Cannot read property
|
|
341
|
+
* 'displayName' of undefined
|
|
342
|
+
*/
|
|
343
|
+
export { UIToastProvider };
|
|
344
|
+
|
|
126
345
|
export default UIToastProvider;
|
|
346
|
+
|
|
347
|
+
const styles = StyleSheet.create({
|
|
348
|
+
container: {
|
|
349
|
+
position: "absolute",
|
|
350
|
+
|
|
351
|
+
top: 0,
|
|
352
|
+
|
|
353
|
+
right: 0,
|
|
354
|
+
|
|
355
|
+
bottom: 0,
|
|
356
|
+
|
|
357
|
+
left: 0,
|
|
358
|
+
|
|
359
|
+
zIndex: 99999,
|
|
360
|
+
|
|
361
|
+
elevation: 99999,
|
|
362
|
+
|
|
363
|
+
pointerEvents: "box-none",
|
|
364
|
+
},
|
|
365
|
+
});
|