funda-ui 4.7.103 → 4.7.107
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/Chatbox/index.js +8 -3
- package/Checkbox/index.js +10 -1
- package/Date/index.js +12 -2
- package/Input/index.js +6 -1
- package/LiveSearch/index.js +5 -0
- package/MultipleCheckboxes/index.js +27 -1
- package/NumberInput/index.js +6 -1
- package/Radio/index.js +22 -1
- package/RangeSlider/index.js +6 -1
- package/Stepper/index.css +7 -8
- package/Stepper/index.d.ts +1 -1
- package/Stepper/index.js +7 -1
- package/TagInput/index.js +10 -1
- package/Textarea/index.js +6 -1
- package/Toast/index.css +23 -75
- package/Toast/index.d.ts +3 -34
- package/Toast/index.js +652 -175
- package/lib/cjs/Chatbox/index.js +8 -3
- package/lib/cjs/Checkbox/index.js +10 -1
- package/lib/cjs/Date/index.js +12 -2
- package/lib/cjs/Input/index.js +6 -1
- package/lib/cjs/LiveSearch/index.js +5 -0
- package/lib/cjs/MultipleCheckboxes/index.js +27 -1
- package/lib/cjs/NumberInput/index.js +6 -1
- package/lib/cjs/Radio/index.js +22 -1
- package/lib/cjs/RangeSlider/index.js +6 -1
- package/lib/cjs/Stepper/index.d.ts +1 -1
- package/lib/cjs/Stepper/index.js +7 -1
- package/lib/cjs/TagInput/index.js +10 -1
- package/lib/cjs/Textarea/index.js +6 -1
- package/lib/cjs/Toast/index.d.ts +3 -34
- package/lib/cjs/Toast/index.js +652 -175
- package/lib/css/Stepper/index.css +7 -8
- package/lib/css/Toast/index.css +23 -75
- package/lib/esm/Chatbox/index.tsx +2 -2
- package/lib/esm/Checkbox/index.tsx +12 -1
- package/lib/esm/Date/index.tsx +8 -1
- package/lib/esm/Input/index.tsx +8 -1
- package/lib/esm/LiveSearch/index.tsx +7 -0
- package/lib/esm/MultipleCheckboxes/index.tsx +19 -1
- package/lib/esm/NumberInput/index.tsx +8 -1
- package/lib/esm/Radio/index.tsx +17 -1
- package/lib/esm/Stepper/index.scss +7 -8
- package/lib/esm/Stepper/index.tsx +2 -2
- package/lib/esm/TagInput/index.tsx +8 -1
- package/lib/esm/Textarea/index.tsx +8 -1
- package/lib/esm/Toast/Item.tsx +52 -11
- package/lib/esm/Toast/Toast.tsx +391 -0
- package/lib/esm/Toast/ToastContext.tsx +104 -0
- package/lib/esm/Toast/__toast.vanilla.js +422 -0
- package/lib/esm/Toast/index.scss +24 -96
- package/lib/esm/Toast/index.tsx +3 -374
- package/lib/esm/Toast/types.ts +60 -0
- package/lib/esm/Toast/useToast.tsx +72 -0
- package/package.json +1 -1
package/lib/esm/Toast/index.tsx
CHANGED
|
@@ -1,374 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import RootPortal from 'funda-root-portal';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import Item from './Item';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export type ToastProps = {
|
|
13
|
-
/** The class name of the toast wrapper. */
|
|
14
|
-
wrapperClassName?: string;
|
|
15
|
-
/** Specify data of toasts as a JSON string format. */
|
|
16
|
-
data: any[any];
|
|
17
|
-
/** Automatically hide multiple items */
|
|
18
|
-
autoHideMultiple?: boolean;
|
|
19
|
-
/** The direction of the toast. */
|
|
20
|
-
direction?: string;
|
|
21
|
-
/** Set an automatic closing time, multiple items will be accumulated in order.
|
|
22
|
-
* Amount of time measured in milliseconds. If false or without this attribute, Auto-Close will be disabled.
|
|
23
|
-
*/
|
|
24
|
-
autoCloseTime?: boolean | number;
|
|
25
|
-
/** You can not close pop-win when it is enabled */
|
|
26
|
-
lock?: boolean;
|
|
27
|
-
/** Whether to use cascading styles */
|
|
28
|
-
cascading?: boolean;
|
|
29
|
-
/** Self-defined class name for body*/
|
|
30
|
-
schemeBody?: string;
|
|
31
|
-
/** Self-defined class name for header */
|
|
32
|
-
schemeHeader?: string;
|
|
33
|
-
/** Set the color of the close button */
|
|
34
|
-
closeBtnColor?: string;
|
|
35
|
-
/** Disable the close button. */
|
|
36
|
-
closeDisabled?: boolean;
|
|
37
|
-
/** */
|
|
38
|
-
async?: boolean;
|
|
39
|
-
/** -- */
|
|
40
|
-
id?: string;
|
|
41
|
-
onClose?: (e: HTMLDivElement, currentIndex: number, data: HTMLDivElement[]) => void;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const Toast = (props: ToastProps) => {
|
|
46
|
-
const {
|
|
47
|
-
wrapperClassName,
|
|
48
|
-
async,
|
|
49
|
-
autoHideMultiple,
|
|
50
|
-
direction,
|
|
51
|
-
autoCloseTime,
|
|
52
|
-
lock,
|
|
53
|
-
cascading,
|
|
54
|
-
data,
|
|
55
|
-
schemeBody,
|
|
56
|
-
schemeHeader,
|
|
57
|
-
closeBtnColor,
|
|
58
|
-
closeDisabled,
|
|
59
|
-
id,
|
|
60
|
-
onClose
|
|
61
|
-
} = props;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const ANIM_SPEED = 300;
|
|
65
|
-
const DEFAULT_AUTO_CLOSE_TIME = 3000;
|
|
66
|
-
const uniqueID = useComId();
|
|
67
|
-
const idRes = id || uniqueID;
|
|
68
|
-
const rootRef = useRef<any>(null);
|
|
69
|
-
const depth: number = autoHideMultiple ? data.slice(-2).length + 1 : data.length + 1;
|
|
70
|
-
const cascadingEnabled = typeof cascading === 'undefined' ? true : cascading;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// force display
|
|
74
|
-
const [initPopRoot, setInitPopRoot] = useState<boolean>(false);
|
|
75
|
-
|
|
76
|
-
// auto close
|
|
77
|
-
const AUTO_CLOSE_TIME: any = typeof (autoCloseTime) === 'undefined' || autoCloseTime === false ? false : autoCloseTime;
|
|
78
|
-
|
|
79
|
-
// progress animation
|
|
80
|
-
const PROGRESS_TRANSITION_TIME: any = typeof (autoCloseTime) === 'undefined' || autoCloseTime === false ? DEFAULT_AUTO_CLOSE_TIME : autoCloseTime;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const progressPausedRef = useRef<any[]>(data.map((v: any) => false));
|
|
84
|
-
const progressObjRef = useRef<any[]>([]);
|
|
85
|
-
const progressIntervalRef = useRef<any[]>(data.map((v: any) => null));
|
|
86
|
-
const startProgressTimer = useCallback((el: any, i: number) => {
|
|
87
|
-
|
|
88
|
-
// init progress
|
|
89
|
-
let progressCurrentChunk = 100 / (PROGRESS_TRANSITION_TIME / 100);
|
|
90
|
-
el.firstChild.style.width = 100 + '%';
|
|
91
|
-
el.firstChild.ariaValueNow = 100;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// animation
|
|
95
|
-
progressIntervalRef.current[i] = setInterval(() => {
|
|
96
|
-
// console.log('toast setInterval');
|
|
97
|
-
|
|
98
|
-
if (!progressPausedRef.current[i]) {
|
|
99
|
-
|
|
100
|
-
const progPercent = 100 - progressCurrentChunk;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
el.firstChild.style.width = progPercent + '%';
|
|
104
|
-
el.firstChild.ariaValueNow = progPercent;
|
|
105
|
-
progressCurrentChunk++;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
if (progPercent === 0 || progPercent < 1) { // may be 0.xxx
|
|
110
|
-
el.classList.add('complete');
|
|
111
|
-
|
|
112
|
-
// stop current animation
|
|
113
|
-
stopProgressTimer(i);
|
|
114
|
-
|
|
115
|
-
// hide toast item
|
|
116
|
-
const currentItem = el.closest('.toast-container');
|
|
117
|
-
handleClose(null, i as never, currentItem as never);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
}, PROGRESS_TRANSITION_TIME / 100);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}, []);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const clearAllProgressTimer = useCallback((curIndex: number | undefined = undefined) => {
|
|
129
|
-
if (typeof curIndex === 'undefined') {
|
|
130
|
-
data.forEach((item: any, i: number) => {
|
|
131
|
-
clearInterval(progressIntervalRef.current[i]);
|
|
132
|
-
progressIntervalRef.current[i] = null;
|
|
133
|
-
});
|
|
134
|
-
} else {
|
|
135
|
-
data.forEach((item: any, i: number) => {
|
|
136
|
-
if (i === curIndex) {
|
|
137
|
-
clearInterval(progressIntervalRef.current[i]);
|
|
138
|
-
progressIntervalRef.current[i] = null;
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
}, [data]);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const stopProgressTimer = useCallback((index: number) => {
|
|
148
|
-
clearInterval(progressIntervalRef.current[index]);
|
|
149
|
-
progressIntervalRef.current[index] = null;
|
|
150
|
-
|
|
151
|
-
}, [data]);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
function progressAnimBegin() {
|
|
155
|
-
data.forEach((item: any, i: number) => {
|
|
156
|
-
const el = progressObjRef.current[i];
|
|
157
|
-
if (el !== null && typeof el !== 'undefined') startProgressTimer(el, i);
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
function handleProgressPaused(e: any) {
|
|
163
|
-
const _currentIndex = e.currentTarget.dataset.index;
|
|
164
|
-
progressPausedRef.current[_currentIndex] = true;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function handleProgressStart(e: any) {
|
|
168
|
-
const _currentIndex = e.currentTarget.dataset.index;
|
|
169
|
-
progressPausedRef.current[_currentIndex] = false;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
function init() {
|
|
174
|
-
if (rootRef.current === null) return;
|
|
175
|
-
|
|
176
|
-
const $toast = rootRef.current;
|
|
177
|
-
|
|
178
|
-
// Automatically hide multiple items
|
|
179
|
-
// It creates a transition animation effect with multiple records and only one displayed.
|
|
180
|
-
//------------------------------------------
|
|
181
|
-
if (autoHideMultiple) {
|
|
182
|
-
|
|
183
|
-
const _list: HTMLDivElement[] = [].slice.call($toast.querySelectorAll('.toast-container'));
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (_list.length === 2) {
|
|
187
|
-
_list.forEach((node: any, i: number) => {
|
|
188
|
-
node.classList.remove('auto-anim-switch', 'auto-anim-switch--initfirst', 'auto-anim-switch--first');
|
|
189
|
-
|
|
190
|
-
if (i !== _list.length - 1) {
|
|
191
|
-
node.classList.add('auto-anim-switch--initfirst'); // top element of source code
|
|
192
|
-
} else {
|
|
193
|
-
node.classList.add('auto-anim-switch--initfirst'); // bottom element of source code
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
setTimeout(() => {
|
|
200
|
-
_list.forEach((node: any, i: number) => {
|
|
201
|
-
if (i !== _list.length - 1) {
|
|
202
|
-
node.classList.add('auto-anim-switch');
|
|
203
|
-
} else {
|
|
204
|
-
node.classList.add('auto-anim-switch--initfirst', 'auto-anim-switch--first');
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
}, ANIM_SPEED/2);
|
|
208
|
-
} else {
|
|
209
|
-
|
|
210
|
-
_list.forEach((node: any, i: number) => {
|
|
211
|
-
if (i !== _list.length - 1) {
|
|
212
|
-
node.classList.add('auto-anim-switch');
|
|
213
|
-
} else {
|
|
214
|
-
node.classList.add('auto-anim-switch--initfirst', 'auto-anim-switch--first');
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
// Initialize data
|
|
224
|
-
//--------------
|
|
225
|
-
if ( $toast.dataset.async == 'true' ) {
|
|
226
|
-
const _list: HTMLDivElement[] = [].slice.call($toast.querySelectorAll('.toast-container'));
|
|
227
|
-
_list.forEach((node: any, i: number) => {
|
|
228
|
-
node.classList.remove('hide-end');
|
|
229
|
-
// rearrange
|
|
230
|
-
if (cascadingEnabled) node.style.transform = `perspective(100px) translateZ(-${2 * i}px) translateY(${35 * i}px)`;
|
|
231
|
-
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
function autoClose() {
|
|
240
|
-
|
|
241
|
-
// Auto hide
|
|
242
|
-
//--------------
|
|
243
|
-
if (AUTO_CLOSE_TIME !== false) {
|
|
244
|
-
|
|
245
|
-
// start animation
|
|
246
|
-
progressAnimBegin();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function handleClose(e: any, index: number, currentItem: HTMLDivElement) {
|
|
252
|
-
if (typeof e !== 'undefined' && e !== null) e.preventDefault();
|
|
253
|
-
if (rootRef.current === null) return;
|
|
254
|
-
|
|
255
|
-
const curIndex = Number(index);
|
|
256
|
-
|
|
257
|
-
const _list: HTMLDivElement[] = [].slice.call(rootRef.current.querySelectorAll('.toast-container'));
|
|
258
|
-
currentItem.classList.add('hide-start');
|
|
259
|
-
|
|
260
|
-
//Let the removed animation show
|
|
261
|
-
setTimeout(() => {
|
|
262
|
-
|
|
263
|
-
_list.forEach((node: any, i: number) => {
|
|
264
|
-
node.classList.remove('hide-start');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// remove current
|
|
268
|
-
currentItem.classList.add('hide-end');
|
|
269
|
-
|
|
270
|
-
// rearrange
|
|
271
|
-
if (cascadingEnabled) {
|
|
272
|
-
_list.filter((node: any) => !node.classList.contains('hide-end')).forEach((node: any, k: number) => {
|
|
273
|
-
node.style.transform = `perspective(100px) translateZ(-${2 * k}px) translateY(${35 * k}px)`;
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// stop all animations or current animation
|
|
278
|
-
if (_list.length === 1 || autoHideMultiple) {
|
|
279
|
-
clearAllProgressTimer();
|
|
280
|
-
} else {
|
|
281
|
-
clearAllProgressTimer(curIndex);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
//
|
|
286
|
-
onClose?.(rootRef.current, curIndex, _list.filter((node: HTMLDivElement) => !node.classList.contains('hide-end') ));
|
|
287
|
-
|
|
288
|
-
}, ANIM_SPEED);
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
useEffect(() => {
|
|
295
|
-
|
|
296
|
-
if (initPopRoot) {
|
|
297
|
-
|
|
298
|
-
// Initialize Toast Item
|
|
299
|
-
//------------------------------------------
|
|
300
|
-
init();
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// Initialize Progress
|
|
304
|
-
//------------------------------------------
|
|
305
|
-
autoClose();
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// Remove the global list of events, especially as scroll and interval.
|
|
309
|
-
//--------------
|
|
310
|
-
return () => {
|
|
311
|
-
|
|
312
|
-
// Stop all animations
|
|
313
|
-
clearAllProgressTimer();
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}, [data, initPopRoot]);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
useEffect(() => {
|
|
323
|
-
setInitPopRoot(true);
|
|
324
|
-
}, []);
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
return (
|
|
329
|
-
<>
|
|
330
|
-
<RootPortal show={initPopRoot} containerClassName="Toast">
|
|
331
|
-
|
|
332
|
-
<div
|
|
333
|
-
id={`toasts__wrapper-${idRes}`}
|
|
334
|
-
data-async={async ? async : false}
|
|
335
|
-
className={`toasts__wrapper toasts__wrapper--${direction ? direction : 'bottom-center'} ${cascadingEnabled ? 'toasts__wrapper--cascading' : ''} ${wrapperClassName || ''}`}
|
|
336
|
-
ref={rootRef}
|
|
337
|
-
>
|
|
338
|
-
<div className="toasts">
|
|
339
|
-
{(autoHideMultiple ? data.slice(-2) : data).map((item: any, i: number) => {
|
|
340
|
-
return <Item
|
|
341
|
-
ref={el => progressObjRef.current[i] = el}
|
|
342
|
-
onlyOne={data.length === 1 ? true : false}
|
|
343
|
-
depth={depth - i}
|
|
344
|
-
key={i}
|
|
345
|
-
index={i}
|
|
346
|
-
title={item.title}
|
|
347
|
-
note={item.note}
|
|
348
|
-
theme={item.theme}
|
|
349
|
-
lock={lock}
|
|
350
|
-
cascading={cascadingEnabled}
|
|
351
|
-
schemeBody={schemeBody}
|
|
352
|
-
schemeHeader={schemeHeader}
|
|
353
|
-
closeBtnColor={closeBtnColor}
|
|
354
|
-
closeDisabled={closeDisabled}
|
|
355
|
-
message={item.message}
|
|
356
|
-
autoCloseTime={AUTO_CLOSE_TIME}
|
|
357
|
-
evStart={handleProgressStart}
|
|
358
|
-
evPause={handleProgressPaused}
|
|
359
|
-
evClose={handleClose}
|
|
360
|
-
/>
|
|
361
|
-
|
|
362
|
-
})}
|
|
363
|
-
</div>
|
|
364
|
-
|
|
365
|
-
</div>
|
|
366
|
-
</RootPortal>
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
</>
|
|
370
|
-
)
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
export default Toast;
|
|
1
|
+
export { useToast } from './useToast';
|
|
2
|
+
export { ToastProvider } from './ToastContext';
|
|
3
|
+
export type { ToastOptions } from './types';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface ToastOptions {
|
|
2
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
3
|
+
/** IDENTIFIER */
|
|
4
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
5
|
+
actionId?: string | number | null | undefined;
|
|
6
|
+
|
|
7
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
8
|
+
/** GENERIC */
|
|
9
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
10
|
+
wrapperClassName?: string;
|
|
11
|
+
/** Automatically hide multiple items */
|
|
12
|
+
onlyShowOne?: boolean;
|
|
13
|
+
/** Allow data to be reversed */
|
|
14
|
+
reverseDisplay?: boolean;
|
|
15
|
+
/** The direction of the toast. */
|
|
16
|
+
direction?: 'bottom-left' | 'bottom-center' | 'bottom-right' | 'top-left' | 'top-center' | 'top-right' | 'vertical-center';
|
|
17
|
+
/** Set an automatic closing time, multiple items will be accumulated in order.
|
|
18
|
+
* Amount of time measured in milliseconds. If false or without this attribute, Auto-Close will be disabled.
|
|
19
|
+
*/
|
|
20
|
+
autoCloseTime?: boolean | number;
|
|
21
|
+
/** You can not close pop-win when it is enabled */
|
|
22
|
+
lock?: boolean;
|
|
23
|
+
/** Whether to use cascading styles */
|
|
24
|
+
cascading?: boolean;
|
|
25
|
+
/** Self-defined class name for body*/
|
|
26
|
+
schemeBody?: string;
|
|
27
|
+
/** Self-defined class name for header */
|
|
28
|
+
schemeHeader?: string;
|
|
29
|
+
/** Set the color of the close button */
|
|
30
|
+
closeBtnColor?: string;
|
|
31
|
+
/** Disable the close button. */
|
|
32
|
+
closeDisabled?: boolean;
|
|
33
|
+
/** -- */
|
|
34
|
+
onClose?: (e: HTMLDivElement, currentIndex: number, displayedElements: HTMLDivElement[]) => void;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
38
|
+
/** ITEM */
|
|
39
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
40
|
+
title?: string;
|
|
41
|
+
note?: string;
|
|
42
|
+
theme?: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' | 'light' | 'dark' | undefined;
|
|
43
|
+
message?: React.ReactNode;
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
47
|
+
/** AUTO */
|
|
48
|
+
/** +++++++++++++++++++++++++++++++++++++++++++++++++ */
|
|
49
|
+
id?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
// Configure the interface globally
|
|
54
|
+
export interface ToastGlobalConfig {
|
|
55
|
+
defaultWrapperClassName?: string;
|
|
56
|
+
defaultOnlyShowOne?: boolean;
|
|
57
|
+
defaultDirection?: ToastOptions['direction'];
|
|
58
|
+
defaultCascading?: boolean;
|
|
59
|
+
defaultReverseDisplay?: boolean;
|
|
60
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useToastContext } from './ToastContext';
|
|
3
|
+
import type { ToastOptions, ToastGlobalConfig } from './types';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export interface ToastItem extends ToastOptions {
|
|
7
|
+
id: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export const useToast = () => {
|
|
12
|
+
const { state, dispatch } = useToastContext();
|
|
13
|
+
|
|
14
|
+
const show = useCallback((options: ToastOptions): ToastItem => {
|
|
15
|
+
const id = Math.random().toString(36).substring(2, 9);
|
|
16
|
+
const toast: ToastItem = {
|
|
17
|
+
id,
|
|
18
|
+
|
|
19
|
+
// Configure the interface globally, but overrides are allowed to be overridden by the instance configuration.
|
|
20
|
+
wrapperClassName: state.config.defaultWrapperClassName,
|
|
21
|
+
direction: state.config.defaultDirection,
|
|
22
|
+
onlyShowOne: state.config.defaultOnlyShowOne,
|
|
23
|
+
cascading: state.config.defaultCascading,
|
|
24
|
+
reverseDisplay: state.config.defaultReverseDisplay,
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
...options,
|
|
28
|
+
};
|
|
29
|
+
dispatch({
|
|
30
|
+
type: 'ADD_TOAST',
|
|
31
|
+
payload: toast,
|
|
32
|
+
});
|
|
33
|
+
return toast; // Returns the full toast object
|
|
34
|
+
}, [dispatch, state.config]);
|
|
35
|
+
|
|
36
|
+
const updateConfig = useCallback((config: Partial<ToastGlobalConfig>) => {
|
|
37
|
+
dispatch({
|
|
38
|
+
type: 'UPDATE_CONFIG',
|
|
39
|
+
payload: config
|
|
40
|
+
});
|
|
41
|
+
}, [dispatch]);
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const close = useCallback((id: string) => {
|
|
45
|
+
dispatch({ type: 'REMOVE_TOAST', payload: id });
|
|
46
|
+
}, [dispatch]);
|
|
47
|
+
|
|
48
|
+
const closeByIndex = useCallback((index: number) => {
|
|
49
|
+
const toast = state.toasts[index];
|
|
50
|
+
if (toast) {
|
|
51
|
+
dispatch({ type: 'REMOVE_TOAST', payload: toast.id });
|
|
52
|
+
}
|
|
53
|
+
}, [state.toasts, dispatch]);
|
|
54
|
+
|
|
55
|
+
const closeAll = useCallback(() => {
|
|
56
|
+
dispatch({ type: 'REMOVE_ALL' });
|
|
57
|
+
}, [dispatch]);
|
|
58
|
+
|
|
59
|
+
// Get all current toasts
|
|
60
|
+
const getToasts = useCallback((): ToastItem[] => {
|
|
61
|
+
return state.toasts;
|
|
62
|
+
}, [state.toasts]);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
show,
|
|
66
|
+
close,
|
|
67
|
+
closeByIndex,
|
|
68
|
+
closeAll,
|
|
69
|
+
getToasts,
|
|
70
|
+
updateConfig
|
|
71
|
+
};
|
|
72
|
+
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "UIUX Lab",
|
|
3
3
|
"email": "uiuxlab@gmail.com",
|
|
4
4
|
"name": "funda-ui",
|
|
5
|
-
"version": "4.7.
|
|
5
|
+
"version": "4.7.107",
|
|
6
6
|
"description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|