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
|
@@ -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
|
+
})();
|
package/lib/esm/Toast/index.scss
CHANGED
|
@@ -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:
|
|
17
|
-
--toasts-progress-bg: rgba(
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
94
|
+
/* Rendering of 3D transformations */
|
|
95
|
+
backface-visibility: hidden;
|
|
96
|
+
transform-style: preserve-3d;
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
+
}
|