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.
Files changed (55) hide show
  1. package/Chatbox/index.js +8 -3
  2. package/Checkbox/index.js +10 -1
  3. package/Date/index.js +12 -2
  4. package/Input/index.js +6 -1
  5. package/LiveSearch/index.js +5 -0
  6. package/MultipleCheckboxes/index.js +27 -1
  7. package/NumberInput/index.js +6 -1
  8. package/Radio/index.js +22 -1
  9. package/RangeSlider/index.js +6 -1
  10. package/Stepper/index.css +7 -8
  11. package/Stepper/index.d.ts +1 -1
  12. package/Stepper/index.js +7 -1
  13. package/TagInput/index.js +10 -1
  14. package/Textarea/index.js +6 -1
  15. package/Toast/index.css +23 -75
  16. package/Toast/index.d.ts +3 -34
  17. package/Toast/index.js +652 -175
  18. package/lib/cjs/Chatbox/index.js +8 -3
  19. package/lib/cjs/Checkbox/index.js +10 -1
  20. package/lib/cjs/Date/index.js +12 -2
  21. package/lib/cjs/Input/index.js +6 -1
  22. package/lib/cjs/LiveSearch/index.js +5 -0
  23. package/lib/cjs/MultipleCheckboxes/index.js +27 -1
  24. package/lib/cjs/NumberInput/index.js +6 -1
  25. package/lib/cjs/Radio/index.js +22 -1
  26. package/lib/cjs/RangeSlider/index.js +6 -1
  27. package/lib/cjs/Stepper/index.d.ts +1 -1
  28. package/lib/cjs/Stepper/index.js +7 -1
  29. package/lib/cjs/TagInput/index.js +10 -1
  30. package/lib/cjs/Textarea/index.js +6 -1
  31. package/lib/cjs/Toast/index.d.ts +3 -34
  32. package/lib/cjs/Toast/index.js +652 -175
  33. package/lib/css/Stepper/index.css +7 -8
  34. package/lib/css/Toast/index.css +23 -75
  35. package/lib/esm/Chatbox/index.tsx +2 -2
  36. package/lib/esm/Checkbox/index.tsx +12 -1
  37. package/lib/esm/Date/index.tsx +8 -1
  38. package/lib/esm/Input/index.tsx +8 -1
  39. package/lib/esm/LiveSearch/index.tsx +7 -0
  40. package/lib/esm/MultipleCheckboxes/index.tsx +19 -1
  41. package/lib/esm/NumberInput/index.tsx +8 -1
  42. package/lib/esm/Radio/index.tsx +17 -1
  43. package/lib/esm/Stepper/index.scss +7 -8
  44. package/lib/esm/Stepper/index.tsx +2 -2
  45. package/lib/esm/TagInput/index.tsx +8 -1
  46. package/lib/esm/Textarea/index.tsx +8 -1
  47. package/lib/esm/Toast/Item.tsx +52 -11
  48. package/lib/esm/Toast/Toast.tsx +391 -0
  49. package/lib/esm/Toast/ToastContext.tsx +104 -0
  50. package/lib/esm/Toast/__toast.vanilla.js +422 -0
  51. package/lib/esm/Toast/index.scss +24 -96
  52. package/lib/esm/Toast/index.tsx +3 -374
  53. package/lib/esm/Toast/types.ts +60 -0
  54. package/lib/esm/Toast/useToast.tsx +72 -0
  55. package/package.json +1 -1
@@ -0,0 +1,422 @@
1
+
2
+ /**
3
+ * Toast
4
+ * @since 20250417
5
+ * @based https://github.com/xizon/funda-ui/tree/main/packages/Toast
6
+ * @param {*} props
7
+ */
8
+
9
+ /**
10
+ * Configuration options for the FU_Toast function
11
+ * @typedef {Object} ToastOptions
12
+ * @property {(string|number|null|undefined)} [actionId='default'] - The identifier of toast, which can be used to determine whether different toast calls
13
+ * @property {(string|boolean)} [title=false] - Specifies an alternate and title for the toast
14
+ * @property {(string|boolean)} [note=false] - A light-colored comment next to the title, which can be information such as time
15
+ * @property {(string)} [message=false] - Specifies the content, or HTML elements to the toast
16
+ * @property {(string)} [hint=false] - Hint's content
17
+ * @property {(boolean)} [hintAutoShow=false] - Whether or not to automatically display additional hints
18
+ * @property {('primary'|'secondary'|'success'|'info'|'warning'|'danger'|'light'|'dark')} [theme='dark'] - Specifies a theme to .toast. All these colors are available as a Sass map of Bootstrap
19
+ * @property {string} [wrapperClassName=''] - The class name of the toast wrapper
20
+ * @property {boolean} [onlyShowOne=false] - Only ever going to show one toast at a time
21
+ * @property {boolean} [lock=false] - You can not close pop-win when it is enabled
22
+ * @property {boolean} [cascading=false] - Whether to use cascading styles
23
+ * @property {string} [schemeBody] - Self-defined class name for body, such as: 'align-items-center text-white bg-primary border-0'
24
+ * @property {string} [schemeHeader] - Self-defined class name for header, such as: 'text-white bg-dark'
25
+ * @property {string} [closeBtnColor] - Set the color of the close button
26
+ * @property {boolean} [closeDisabled=false] - Disable the close button
27
+ * @property {boolean} [reverseDisplay=false] - Allow data to be reversed
28
+ * @property {('bottom-left'|'bottom-center'|'bottom-right'|'top-left'|'top-center'|'top-right'|'vertical-center')} [direction='bottom-center'] - The direction of the toast
29
+ * @property {(boolean|number)} [autoCloseTime=false] - Set an automatic closing time, multiple items will be accumulated in order. Amount of time measured in milliseconds. If false or without this attribute, Auto-Close will be disabled
30
+ * @property {function(HTMLDivElement, string): void} [onClose] - Callback function when toast is closed. Parameters: (currentElement, currentToastId)
31
+ */
32
+
33
+ /**
34
+ * Creates and displays a toast notification
35
+ * @param {ToastOptions} options - The configuration options for the toast
36
+ * @param {function(string): void} [callback] - Optional callback function that receives the toast ID
37
+ * @returns {{close: function(): void}} Object containing methods to control the toast
38
+ *
39
+ */
40
+
41
+ /*
42
+ @Examples:
43
+
44
+
45
+ const showCustomToast1 = () => {
46
+
47
+ FU_Toast({
48
+ actionId: 'test-1',
49
+ title: "Custom Toast 1",
50
+ message: `<div>Text here (${Math.random()})</div>`,
51
+ autoCloseTime: 1000,
52
+ theme: 'warning',
53
+ schemeHeader: 'bg-transparent text-light',
54
+ onlyShowOne: true
55
+ });
56
+ };
57
+
58
+
59
+ const showCustomToast2 = () => {
60
+ FU_Toast({
61
+ actionId: 'test-2',
62
+ title: "Custom Toast 2",
63
+ message: `<div style="color:orange">Text here (${Math.random()})</div>`,
64
+ theme: "dark",
65
+ autoCloseTime: 5000,
66
+ direction: 'bottom-center',
67
+ schemeBody: 'align-items-center text-white border-0 p-2',
68
+ closeBtnColor: '#333',
69
+ hint: 'There are some warnings that need your attention',
70
+ hintAutoShow: false,
71
+ onClose: (currentElement, currentToastId) => {
72
+ console.log(currentElement, currentToastId);
73
+ }
74
+
75
+ });
76
+
77
+ };
78
+
79
+ const showCustomToast3 = () => {
80
+ FU_Toast({
81
+ actionId: 'test-3',
82
+ note: "11 mins ago",
83
+ message: `<div style="color:orange">Text here (${Math.random()})</div>`,
84
+ autoCloseTime: 5000,
85
+ cascading: true,
86
+ direction: 'bottom-right',
87
+ closeBtnColor: '#333',
88
+ reverseDisplay: true
89
+
90
+ });
91
+ };
92
+
93
+ const showCustomToast4 = () => {
94
+ FU_Toast({
95
+ actionId: 'test-4',
96
+ title: "Note",
97
+ message: `<div>Text here (${Math.random()})</div>`,
98
+ autoCloseTime: 5000,
99
+ direction: 'vertical-center',
100
+ theme: 'light',
101
+ schemeBody: '',
102
+ closeBtnColor: '#333'
103
+
104
+ });
105
+ };
106
+
107
+
108
+ const showCustomToast5 = () => {
109
+ FU_Toast({
110
+ actionId: 'test-5',
111
+ closeDisabled: true,
112
+ message: `<div style="color:orange">Text here (${Math.random()})</div>`,
113
+ autoCloseTime: 5000,
114
+ direction: 'bottom-left',
115
+ schemeHeader: 'p-0',
116
+ schemeBody: 'align-items-center text-white bg-dark border-0'
117
+
118
+ });
119
+ };
120
+
121
+
122
+
123
+ const showCustomToast6 = () => {
124
+ FU_Toast({
125
+ actionId: 'test-6',
126
+ direction: 'top-right',
127
+ title: "Custom Toast 1",
128
+ message: `<div>Text here (${Math.random()})</div>`,
129
+ theme: 'success',
130
+ schemeHeader: 'bg-transparent text-light',
131
+ autoCloseTime: 3000,
132
+ }, () => {
133
+ console.log('The presentation is complete');
134
+ });
135
+ };
136
+
137
+
138
+ <button onclick="showCustomToast1()">Custom Toast 1 (Only one is shown)</button>
139
+ <button onclick="showCustomToast2()">Custom Toast 2</button>
140
+ <button onclick="showCustomToast3()">Custom Toast 3</button>
141
+ <button onclick="showCustomToast4()">Custom Toast 4</button>
142
+ <button onclick="showCustomToast5()">Custom Toast 5</button>
143
+ <button onclick="showCustomToast6()">Custom Toast 6</button>
144
+
145
+ */
146
+
147
+ const FU_Toast = (function () {
148
+ 'use strict';
149
+
150
+ const REFER_LIB = "funda-ui";
151
+ const REFER_COMPONENT = "toast";
152
+
153
+ // Constants
154
+ const DEFAULT_AUTO_CLOSE_TIME = 3000;
155
+ const ANIM_SPEED = 300;
156
+
157
+ const $$FU_Toast = (options, callback) => {
158
+ // Default configuration
159
+ const defaults = {
160
+ wrapperClassName: '',
161
+ actionId: 'default',
162
+ cascading: false,
163
+ autoCloseTime: DEFAULT_AUTO_CLOSE_TIME,
164
+ direction: "top-center",
165
+ schemeBody: "align-items-center text-white border-0 p-2",
166
+ closeBtnColor: "#fff",
167
+ reverseDisplay: false,
168
+ onlyShowOne: false,
169
+ onClose: (currentElement, currentToastId) => {},
170
+
171
+ // single message
172
+ theme: 'dark',
173
+ title: false,
174
+ note: false,
175
+ hint: false,
176
+ hintAutoShow: false,
177
+ message: ''
178
+ };
179
+
180
+ // Merge options with defaults
181
+ const config = { ...defaults, ...options };
182
+
183
+ // Generate unique ID for the toast
184
+ const uniqueID = Math.random().toString(36).substring(2, 9);
185
+ const toastId = 'toast-' + uniqueID;
186
+
187
+ // Create or get toast wrapper
188
+ let rootRef = document.getElementById('toasts__wrapper-global-js__' + config.actionId);
189
+ if (!rootRef) {
190
+ rootRef = document.createElement('div');
191
+ rootRef.id = 'toasts__wrapper-global-js__' + config.actionId;
192
+
193
+ // Combine all class names
194
+ const wrapperClasses = [
195
+ 'toasts__wrapper',
196
+ `toasts__wrapper--${config.direction}`,
197
+ config.wrapperClassName
198
+ ].filter(Boolean);
199
+
200
+ rootRef.className = wrapperClasses.join(' ');
201
+
202
+ //
203
+ if (config.cascading) rootRef.classList.add('toasts__wrapper--cascading');
204
+ if (config.onlyShowOne) rootRef.classList.add('toasts__wrapper--only-one');
205
+
206
+ const toastsContainer = document.createElement('div');
207
+ toastsContainer.className = 'toasts';
208
+ rootRef.appendChild(toastsContainer);
209
+ document.body.appendChild(rootRef);
210
+ } else {
211
+ const wrapperClasses = [
212
+ 'toasts__wrapper',
213
+ `toasts__wrapper--${config.direction}`,
214
+ config.wrapperClassName,
215
+ config.cascading ? 'toasts__wrapper--cascading' : '',
216
+ config.onlyShowOne ? 'toasts__wrapper--only-one' : ''
217
+ ].filter(Boolean);
218
+
219
+ rootRef.className = wrapperClasses.join(' ');
220
+ }
221
+
222
+ // Create toast element
223
+ const toast = document.createElement('div');
224
+ toast.id = toastId;
225
+ toast.dataset.toastId = uniqueID;
226
+ toast.className = `toast-container ${config.onlyOne ? 'only-one' : ''} animate-ready`;
227
+
228
+ // Get the number of toasts in the current container as an index
229
+ const currentToasts = rootRef.querySelectorAll('.toast-container');
230
+ const index = currentToasts.length;
231
+ const itemDepth = currentToasts.length + 1;
232
+
233
+
234
+ // Calculate item style based on cascading option
235
+ const itemStyle = config.cascading ?
236
+ `transform: perspective(100px) translateZ(-${2 * index}px) translateY(${35 * index}px);
237
+ z-index: ${itemDepth};` :
238
+ `z-index: ${itemDepth}`;
239
+
240
+ toast.setAttribute('style', itemStyle);
241
+ toast.dataset.index = index;
242
+
243
+
244
+ //
245
+ const hideTitle = (config.title === '' || config.title === false) && (config.note === '' || config.note === false);
246
+
247
+ // Generate hint content based on auto show option
248
+ const hintContent = config.hint && config.hint !== '' ?
249
+ config.hintAutoShow ?
250
+ `<div class="app-io-hint-detail">${config.hint}</div>` :
251
+ `<a href="#" class="app-io-hint-btn">Details</a><div class="app-io-hint-detail d-none">${config.hint}</div>` :
252
+ '';
253
+
254
+ // Generate close button if not locked or disabled
255
+ const closeButton = !config.lock && !config.closeDisabled ?
256
+ `<button data-close="1" tabindex="-1" type="button" class="btn-close">
257
+ <svg width="12px" height="12px" viewBox="0 0 16 16">
258
+ <path fill="${config.closeBtnColor || '#000000'}" d="M9.41 8l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 00-1.71-.71L8 6.59l-3.29-3.3a1.003 1.003 0 00-1.42 1.42L6.59 8 3.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71L8 9.41l3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 00.71-1.71L9.41 8z" fill-rule="evenodd"></path>
259
+ </svg>
260
+ </button>` :
261
+ '';
262
+
263
+ // Generate toast item HTML
264
+ toast.innerHTML = `
265
+ <div class="toast fade show ${config.schemeBody || ''} ${config.theme ? `bg-${config.theme}` : ''}" role="alert">
266
+ ${!hideTitle ? `
267
+ <div class="toast-header ${config.schemeHeader || ''}">
268
+ <strong class="me-auto">${config.title || ''}</strong>
269
+ <small class="text-muted">${config.note || ''}</small>
270
+ ${closeButton}
271
+ </div>
272
+ ` : ''}
273
+
274
+ <div class="toast-body">
275
+ ${config.message}
276
+ ${hintContent}
277
+ ${hideTitle ? `<div class="position-absolute top-0 end-0 me-2 mt-2">${closeButton}</div>` : ''}
278
+
279
+ <div class="toast-progress active toast-progress ${config.autoCloseTime === false ? 'd-none' : ''}" role="progressbar">
280
+ <div class="progress-bar"></div>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ `;
285
+
286
+ // Handle only show one
287
+ if (config.onlyShowOne) {
288
+ const existingToasts = rootRef.querySelectorAll('.toast-container');
289
+ existingToasts.forEach(t => t.remove());
290
+ }
291
+
292
+ // After adding a new toast, update the index and style of all existing toasts
293
+ function updateToastIndexes() {
294
+ const allToasts = rootRef.querySelectorAll('.toast-container');
295
+ allToasts.forEach((t, idx) => {
296
+ const depth = allToasts.length - idx;
297
+ const style = config.cascading ?
298
+ `transform: perspective(100px) translateZ(-${2 * idx}px) translateY(${35 * idx}px);
299
+ z-index: ${depth};` :
300
+ `z-index: ${depth}`;
301
+
302
+ t.setAttribute('style', style);
303
+ t.dataset.index = idx;
304
+ });
305
+ }
306
+
307
+
308
+ // Add toast to container
309
+ const toastsContainer = rootRef.querySelector('.toasts');
310
+ if (config.reverseDisplay) {
311
+ toastsContainer.appendChild(toast);
312
+ } else {
313
+ toastsContainer.insertBefore(toast, toastsContainer.firstChild);
314
+ }
315
+
316
+
317
+ // Update the index of all toasts
318
+ updateToastIndexes();
319
+
320
+ // Animation
321
+ requestAnimationFrame(() => {
322
+ setTimeout(() => {
323
+ toast.classList.add('animate-in');
324
+ }, 50);
325
+ });
326
+
327
+ // Progress bar and auto close
328
+ if (config.autoCloseTime !== false) {
329
+ const progressBar = toast.querySelector('.toast-progress');
330
+ let startTime = Date.now();
331
+ let isPaused = false;
332
+
333
+ const updateProgress = () => {
334
+ if (!isPaused) {
335
+ const elapsed = Date.now() - startTime;
336
+ const progress = Math.max(0, 100 - (elapsed / config.autoCloseTime * 100));
337
+ progressBar.style.width = `${progress}%`;
338
+ progressBar.setAttribute('aria-valuenow', progress);
339
+
340
+ if (progress > 0) {
341
+ requestAnimationFrame(updateProgress);
342
+ } else {
343
+ closeToast();
344
+ }
345
+ }
346
+ };
347
+
348
+ toast.addEventListener('mouseenter', () => {
349
+ isPaused = true;
350
+ });
351
+
352
+ toast.addEventListener('mouseleave', () => {
353
+ isPaused = false;
354
+ startTime = Date.now() - (config.autoCloseTime * (1 - parseInt(progressBar.getAttribute('aria-valuenow')) / 100));
355
+ requestAnimationFrame(updateProgress);
356
+ });
357
+
358
+ requestAnimationFrame(updateProgress);
359
+ }
360
+
361
+ // Close button handler
362
+ const closeBtn = toast.querySelector('.btn-close');
363
+ if (closeBtn) {
364
+ closeBtn.addEventListener('click', () => closeToast());
365
+ }
366
+
367
+ // Close toast function
368
+ function closeToast() {
369
+ toast.classList.add('hide-start');
370
+ setTimeout(() => {
371
+ toast.classList.add('hide-end');
372
+ setTimeout(() => {
373
+ toast.remove();
374
+
375
+ // Update the index of all toasts
376
+ updateToastIndexes();
377
+
378
+ if (rootRef.querySelector('.toasts').children.length === 0) {
379
+ rootRef.remove();
380
+ }
381
+
382
+ // Callback
383
+ if (typeof config.onClose === 'function') {
384
+ config.onClose(toast, toast.dataset.toastId);
385
+ }
386
+ }, ANIM_SPEED);
387
+ }, ANIM_SPEED);
388
+ }
389
+
390
+ // Initialize hint buttons
391
+ rootRef.querySelectorAll('.app-io-hint-btn').forEach(btn => {
392
+ if (!btn.dataset.click) {
393
+ btn.addEventListener('click', function(e) {
394
+ e.preventDefault();
395
+ const detail = e.target.nextElementSibling;
396
+ if (detail?.classList.contains('app-io-hint-detail')) {
397
+ detail.style.setProperty('display', 'block', 'important');
398
+ }
399
+ e.target.style.display = 'none';
400
+ });
401
+ btn.dataset.click = '1';
402
+ }
403
+ });
404
+
405
+ // Execute callback with toast ID
406
+ if (typeof callback === 'function') {
407
+ callback(toastId);
408
+ }
409
+
410
+ // Return methods for controlling the toast
411
+ return {
412
+ close: closeToast
413
+ };
414
+ }
415
+
416
+ // Add to global scope
417
+ if (typeof window !== 'undefined') {
418
+ window.FU_Toast = $$FU_Toast;
419
+ }
420
+
421
+ return $$FU_Toast;
422
+ })();
@@ -2,8 +2,6 @@
2
2
  /* ======================================================
3
3
  <!-- Toast -->
4
4
  /* ====================================================== */
5
-
6
-
7
5
  .toasts__wrapper {
8
6
  --bs-toast-zindex: 1090;
9
7
  --bs-border-radius: 0.375rem;
@@ -13,12 +11,11 @@
13
11
  --toasts-offset-bothsides: 15px;
14
12
  --toasts-container-gap: 0.5rem;
15
13
  --toasts-container-width: 350px;
16
- --toasts-progress-height: 5px;
17
- --toasts-progress-bg: rgba(255,255,255,.6);
14
+ --toasts-progress-height: 3px;
15
+ --toasts-progress-bg: rgba(228, 228, 228, 0.6);
18
16
 
19
17
 
20
18
 
21
-
22
19
  width: var(--toasts-container-width);
23
20
  position: fixed;
24
21
  left: 50%;
@@ -90,42 +87,33 @@
90
87
  .toast-container {
91
88
  margin-bottom: var(--toasts-container-gap);
92
89
 
90
+ /* Use clip-path instead of opacity to achieve a fade effect, avoiding the problem of transparency overlay */
91
+ clip-path: inset(0 0 0 0);
92
+ transform: translateY(0);
93
93
 
94
- &.auto-anim-switch--initfirst {
95
- transform: translateY(-20px);
96
- opacity: 0;
97
- }
94
+ /* Rendering of 3D transformations */
95
+ backface-visibility: hidden;
96
+ transform-style: preserve-3d;
98
97
 
99
- &.auto-anim-switch--first {
100
- animation-name: toast-anim-show-first;
101
- animation-duration: .3s;
102
- animation-timing-function: linear;
103
- animation-delay: 0;
104
- animation-iteration-count: 1;
105
- animation-fill-mode: forwards;
98
+ /* init animation */
99
+ &.animate-ready {
100
+ pointer-events: none;
101
+ clip-path: inset(0 0 100% 0);
102
+ transform: translateY(10px);
106
103
  }
107
-
108
104
 
109
- &.auto-anim-switch:not(.only-one) {
110
- animation-name: toast-anim-hide;
111
- animation-duration: .3s;
112
- animation-timing-function: linear;
113
- animation-delay: 0;
114
- animation-iteration-count: 1;
115
- animation-fill-mode: forwards;
105
+ /* enter animation */
106
+ &.animate-in {
107
+ clip-path: inset(0 0 0 0);
108
+ transform: translateY(0);
116
109
  }
117
110
 
111
+ /* exit animation */
112
+ &.hide-start {
113
+ clip-path: inset(0 0 100% 0);
114
+ transform: translateY(-10px);
115
+ }
118
116
 
119
- &.only-one.auto-anim-switch {
120
- animation-name: toast-anim-hide--onlyone;
121
- animation-duration: .3s;
122
- animation-timing-function: linear;
123
- animation-delay: 0;
124
- animation-iteration-count: 1;
125
- animation-fill-mode: forwards;
126
- }
127
-
128
-
129
117
  }
130
118
 
131
119
  /* cascading divs */
@@ -160,6 +148,7 @@
160
148
  .progress-bar {
161
149
  background: var(--toasts-progress-bg);
162
150
  width: 100%;
151
+ height: 100%;
163
152
  transition: all .1s;
164
153
  }
165
154
  }
@@ -205,65 +194,4 @@
205
194
  }
206
195
 
207
196
 
208
- }
209
-
210
- @keyframes toast-anim-initfirst {
211
- 0% {
212
- transform: translateY(-20px);
213
- opacity: 1;
214
- }
215
-
216
- 100% {
217
- transform: translateY(20px);
218
- opacity: 0;
219
- }
220
- }
221
-
222
- @keyframes toast-anim-show-first {
223
- 0% {
224
- transform: translateY(-20px);
225
- opacity: 0;
226
- }
227
-
228
- 100% {
229
- transform: translateY(0);
230
- opacity: 1;
231
- }
232
- }
233
-
234
- @keyframes toast-anim-hide {
235
- 0% {
236
- transform: translateY(-100%);
237
- opacity: 1;
238
- }
239
-
240
- 100% {
241
- transform: translateY(10px);
242
- opacity: 0;
243
-
244
- /* prevent auto-close's item */
245
- display: block;
246
-
247
- }
248
- }
249
-
250
-
251
- @keyframes toast-anim-hide--onlyone {
252
- 0% {
253
- transform: translateY(-100%);
254
- opacity: 1;
255
-
256
-
257
- /* prevent auto-close's item */
258
- display: block;
259
- }
260
-
261
- 100% {
262
- transform: translateY(10px);
263
- opacity: 0;
264
-
265
- /* prevent auto-close's item */
266
- display: block;
267
-
268
- }
269
- }
197
+ }