@wishbone-media/spark 0.20.0 → 0.21.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/dist/index.js +1634 -1095
- package/package.json +1 -1
- package/src/components/SparkAlert.vue +5 -1
- package/src/components/SparkButton.vue +2 -0
- package/src/components/SparkNotificationOutlet.vue +68 -0
- package/src/components/SparkOverlay.vue +15 -2
- package/src/components/SparkToastContainer.vue +184 -0
- package/src/components/index.js +2 -0
- package/src/composables/index.js +1 -0
- package/src/composables/sparkNotificationService.js +459 -0
- package/src/composables/sparkOverlayService.js +4 -4
- package/src/composables/useSparkOverlay.js +6 -3
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import { markRaw, reactive } from 'vue'
|
|
2
|
+
|
|
3
|
+
// Default durations by type (in ms)
|
|
4
|
+
const DEFAULT_DURATIONS = {
|
|
5
|
+
success: 5000,
|
|
6
|
+
info: 5000,
|
|
7
|
+
warning: 5000,
|
|
8
|
+
danger: 0, // sticky by default
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Valid toast positions
|
|
12
|
+
const TOAST_POSITIONS = ['top-left', 'top-right', 'center', 'bottom-left', 'bottom-right']
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a notification outlet state manager (for banner notifications)
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
function createNotificationOutlet() {
|
|
19
|
+
const state = reactive({
|
|
20
|
+
isVisible: false,
|
|
21
|
+
type: 'info',
|
|
22
|
+
message: null,
|
|
23
|
+
component: null,
|
|
24
|
+
props: {},
|
|
25
|
+
closeable: true,
|
|
26
|
+
duration: null,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// Timer state (not reactive, internal only)
|
|
30
|
+
let dismissTimeout = null
|
|
31
|
+
let remainingTime = 0
|
|
32
|
+
let isPaused = false
|
|
33
|
+
let timerStartedAt = null
|
|
34
|
+
|
|
35
|
+
const clearDismissTimeout = () => {
|
|
36
|
+
if (dismissTimeout) {
|
|
37
|
+
clearTimeout(dismissTimeout)
|
|
38
|
+
dismissTimeout = null
|
|
39
|
+
}
|
|
40
|
+
remainingTime = 0
|
|
41
|
+
isPaused = false
|
|
42
|
+
timerStartedAt = null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const hide = () => {
|
|
46
|
+
clearDismissTimeout()
|
|
47
|
+
state.isVisible = false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const startDismissTimer = (duration) => {
|
|
51
|
+
if (duration <= 0) return
|
|
52
|
+
|
|
53
|
+
remainingTime = duration
|
|
54
|
+
timerStartedAt = Date.now()
|
|
55
|
+
|
|
56
|
+
dismissTimeout = setTimeout(() => {
|
|
57
|
+
hide()
|
|
58
|
+
}, duration)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const pause = () => {
|
|
62
|
+
if (!dismissTimeout || isPaused) return
|
|
63
|
+
|
|
64
|
+
clearTimeout(dismissTimeout)
|
|
65
|
+
dismissTimeout = null
|
|
66
|
+
|
|
67
|
+
const elapsed = Date.now() - timerStartedAt
|
|
68
|
+
remainingTime = Math.max(0, remainingTime - elapsed)
|
|
69
|
+
isPaused = true
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const resume = () => {
|
|
73
|
+
if (!isPaused || remainingTime <= 0) return
|
|
74
|
+
|
|
75
|
+
isPaused = false
|
|
76
|
+
timerStartedAt = Date.now()
|
|
77
|
+
|
|
78
|
+
dismissTimeout = setTimeout(() => {
|
|
79
|
+
hide()
|
|
80
|
+
}, remainingTime)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const show = (options = {}) => {
|
|
84
|
+
clearDismissTimeout()
|
|
85
|
+
|
|
86
|
+
const {
|
|
87
|
+
type = 'info',
|
|
88
|
+
message = null,
|
|
89
|
+
component = null,
|
|
90
|
+
props = {},
|
|
91
|
+
closeable = true,
|
|
92
|
+
duration = null,
|
|
93
|
+
} = options
|
|
94
|
+
|
|
95
|
+
state.type = type
|
|
96
|
+
state.message = message
|
|
97
|
+
state.component = component ? markRaw(component) : null
|
|
98
|
+
state.props = props
|
|
99
|
+
state.closeable = closeable
|
|
100
|
+
state.isVisible = true
|
|
101
|
+
|
|
102
|
+
// Determine duration: explicit > default for type
|
|
103
|
+
const effectiveDuration = duration !== null ? duration : DEFAULT_DURATIONS[type]
|
|
104
|
+
state.duration = effectiveDuration
|
|
105
|
+
|
|
106
|
+
if (effectiveDuration > 0) {
|
|
107
|
+
startDismissTimer(effectiveDuration)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const reset = () => {
|
|
112
|
+
hide()
|
|
113
|
+
state.type = 'info'
|
|
114
|
+
state.message = null
|
|
115
|
+
state.component = null
|
|
116
|
+
state.props = {}
|
|
117
|
+
state.closeable = true
|
|
118
|
+
state.duration = null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
state,
|
|
123
|
+
show,
|
|
124
|
+
hide,
|
|
125
|
+
reset,
|
|
126
|
+
pause,
|
|
127
|
+
resume,
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Service for managing notifications (both banner and toast)
|
|
133
|
+
*
|
|
134
|
+
* Banner Usage:
|
|
135
|
+
* sparkNotificationService.show({ type: 'success', message: 'Saved!' })
|
|
136
|
+
* sparkNotificationService.show({ type: 'error', message: 'Failed' }, 'form-errors')
|
|
137
|
+
* sparkNotificationService.hide()
|
|
138
|
+
*
|
|
139
|
+
* Toast Usage:
|
|
140
|
+
* sparkNotificationService.toast({ type: 'success', message: 'Saved!' })
|
|
141
|
+
* sparkNotificationService.toast({ type: 'error', message: 'Failed', position: 'top-right' })
|
|
142
|
+
* sparkNotificationService.hideToast(toastId)
|
|
143
|
+
* sparkNotificationService.hideAllToasts()
|
|
144
|
+
*/
|
|
145
|
+
class SparkNotificationService {
|
|
146
|
+
constructor() {
|
|
147
|
+
// Banner outlets
|
|
148
|
+
this.outlets = new Map()
|
|
149
|
+
|
|
150
|
+
// Toast state
|
|
151
|
+
this.toastState = reactive({
|
|
152
|
+
toasts: [],
|
|
153
|
+
maxToasts: 3,
|
|
154
|
+
defaultPosition: 'bottom-right',
|
|
155
|
+
newestOnTop: true,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Toast timers (keyed by toast id)
|
|
159
|
+
this._toastTimers = new Map()
|
|
160
|
+
|
|
161
|
+
// Counter for unique toast IDs
|
|
162
|
+
this._toastIdCounter = 0
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ============================================
|
|
166
|
+
// Banner Notification Methods
|
|
167
|
+
// ============================================
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get or create a notification outlet by name
|
|
171
|
+
* @param {string} name - Outlet name (default: 'default')
|
|
172
|
+
* @returns {Object} Notification outlet instance
|
|
173
|
+
*/
|
|
174
|
+
getOutlet(name = 'default') {
|
|
175
|
+
if (!this.outlets.has(name)) {
|
|
176
|
+
this.outlets.set(name, createNotificationOutlet())
|
|
177
|
+
}
|
|
178
|
+
return this.outlets.get(name)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Show a banner notification in the specified outlet
|
|
183
|
+
* @param {Object} options - Notification options
|
|
184
|
+
* @param {string} options.type - Alert type: 'success' | 'warning' | 'danger' | 'info'
|
|
185
|
+
* @param {string} options.message - Simple text message (mutually exclusive with component)
|
|
186
|
+
* @param {Component} options.component - Vue component to render (mutually exclusive with message)
|
|
187
|
+
* @param {Object} options.props - Props to pass to the component
|
|
188
|
+
* @param {boolean} options.closeable - Whether to show close button (default: true)
|
|
189
|
+
* @param {number} options.duration - Auto-dismiss duration in ms (0 = sticky, null = use default)
|
|
190
|
+
* @param {string} outletName - Target outlet name (default: 'default')
|
|
191
|
+
*/
|
|
192
|
+
show(options = {}, outletName = 'default') {
|
|
193
|
+
const outlet = this.getOutlet(outletName)
|
|
194
|
+
outlet.show(options)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Hide banner notification in the specified outlet
|
|
199
|
+
* @param {string} outletName - Target outlet name (default: 'default')
|
|
200
|
+
*/
|
|
201
|
+
hide(outletName = 'default') {
|
|
202
|
+
const outlet = this.getOutlet(outletName)
|
|
203
|
+
outlet.hide()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Hide all banner notifications in all outlets
|
|
208
|
+
*/
|
|
209
|
+
hideAll() {
|
|
210
|
+
for (const outlet of this.outlets.values()) {
|
|
211
|
+
outlet.hide()
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Pause auto-dismiss timer for the specified banner outlet
|
|
217
|
+
* @param {string} outletName - Target outlet name (default: 'default')
|
|
218
|
+
*/
|
|
219
|
+
pause(outletName = 'default') {
|
|
220
|
+
const outlet = this.getOutlet(outletName)
|
|
221
|
+
outlet.pause()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Resume auto-dismiss timer for the specified banner outlet
|
|
226
|
+
* @param {string} outletName - Target outlet name (default: 'default')
|
|
227
|
+
*/
|
|
228
|
+
resume(outletName = 'default') {
|
|
229
|
+
const outlet = this.getOutlet(outletName)
|
|
230
|
+
outlet.resume()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Reset and remove a banner outlet
|
|
235
|
+
* @param {string} outletName - Target outlet name (default: 'default')
|
|
236
|
+
*/
|
|
237
|
+
reset(outletName = 'default') {
|
|
238
|
+
const outlet = this.outlets.get(outletName)
|
|
239
|
+
if (outlet) {
|
|
240
|
+
outlet.reset()
|
|
241
|
+
this.outlets.delete(outletName)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Reset all banner outlets
|
|
247
|
+
*/
|
|
248
|
+
resetAll() {
|
|
249
|
+
for (const outlet of this.outlets.values()) {
|
|
250
|
+
outlet.reset()
|
|
251
|
+
}
|
|
252
|
+
this.outlets.clear()
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ============================================
|
|
256
|
+
// Toast Notification Methods
|
|
257
|
+
// ============================================
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Configure toast defaults
|
|
261
|
+
* @param {Object} options - Configuration options
|
|
262
|
+
* @param {number} options.maxToasts - Maximum visible toasts (default: 3)
|
|
263
|
+
* @param {string} options.defaultPosition - Default position (default: 'bottom-right')
|
|
264
|
+
* @param {boolean} options.newestOnTop - Whether newest toasts appear on top (default: true)
|
|
265
|
+
*/
|
|
266
|
+
configureToasts(options = {}) {
|
|
267
|
+
if (options.maxToasts !== undefined) {
|
|
268
|
+
this.toastState.maxToasts = options.maxToasts
|
|
269
|
+
}
|
|
270
|
+
if (options.defaultPosition !== undefined && TOAST_POSITIONS.includes(options.defaultPosition)) {
|
|
271
|
+
this.toastState.defaultPosition = options.defaultPosition
|
|
272
|
+
}
|
|
273
|
+
if (options.newestOnTop !== undefined) {
|
|
274
|
+
this.toastState.newestOnTop = options.newestOnTop
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Show a toast notification
|
|
280
|
+
* @param {Object} options - Toast options
|
|
281
|
+
* @param {string} options.type - Alert type: 'success' | 'warning' | 'danger' | 'info'
|
|
282
|
+
* @param {string} options.message - Simple text message (mutually exclusive with component)
|
|
283
|
+
* @param {Component} options.component - Vue component to render (mutually exclusive with message)
|
|
284
|
+
* @param {Object} options.props - Props to pass to the component
|
|
285
|
+
* @param {boolean} options.closeable - Whether to show close button (default: true)
|
|
286
|
+
* @param {number} options.duration - Auto-dismiss duration in ms (0 = sticky, null = use default)
|
|
287
|
+
* @param {string} options.position - Position: 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center'
|
|
288
|
+
* @returns {number} Toast ID for programmatic dismissal
|
|
289
|
+
*/
|
|
290
|
+
toast(options = {}) {
|
|
291
|
+
const {
|
|
292
|
+
type = 'info',
|
|
293
|
+
message = null,
|
|
294
|
+
component = null,
|
|
295
|
+
props = {},
|
|
296
|
+
closeable = true,
|
|
297
|
+
duration = null,
|
|
298
|
+
position = null,
|
|
299
|
+
} = options
|
|
300
|
+
|
|
301
|
+
// Generate unique ID
|
|
302
|
+
const id = ++this._toastIdCounter
|
|
303
|
+
|
|
304
|
+
// Determine effective values
|
|
305
|
+
const effectivePosition = (position && TOAST_POSITIONS.includes(position))
|
|
306
|
+
? position
|
|
307
|
+
: this.toastState.defaultPosition
|
|
308
|
+
const effectiveDuration = duration !== null ? duration : DEFAULT_DURATIONS[type]
|
|
309
|
+
|
|
310
|
+
// Create toast object
|
|
311
|
+
const toast = {
|
|
312
|
+
id,
|
|
313
|
+
type,
|
|
314
|
+
message,
|
|
315
|
+
component: component ? markRaw(component) : null,
|
|
316
|
+
props,
|
|
317
|
+
closeable,
|
|
318
|
+
duration: effectiveDuration,
|
|
319
|
+
position: effectivePosition,
|
|
320
|
+
createdAt: Date.now(),
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Remove oldest toasts if at capacity (per position)
|
|
324
|
+
const positionToasts = this.toastState.toasts.filter(t => t.position === effectivePosition)
|
|
325
|
+
if (positionToasts.length >= this.toastState.maxToasts) {
|
|
326
|
+
// Remove oldest: when newestOnTop, oldest is at end; otherwise at beginning
|
|
327
|
+
const oldest = this.toastState.newestOnTop
|
|
328
|
+
? positionToasts[positionToasts.length - 1]
|
|
329
|
+
: positionToasts[0]
|
|
330
|
+
this.hideToast(oldest.id)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Add toast to array
|
|
334
|
+
if (this.toastState.newestOnTop) {
|
|
335
|
+
// Find insertion point: after all toasts of same position
|
|
336
|
+
const insertIndex = this.toastState.toasts.findIndex(t => t.position === effectivePosition)
|
|
337
|
+
if (insertIndex === -1) {
|
|
338
|
+
this.toastState.toasts.push(toast)
|
|
339
|
+
} else {
|
|
340
|
+
this.toastState.toasts.splice(insertIndex, 0, toast)
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
this.toastState.toasts.push(toast)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Start auto-dismiss timer if duration > 0
|
|
347
|
+
if (effectiveDuration > 0) {
|
|
348
|
+
this._startToastTimer(id, effectiveDuration)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return id
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Hide a specific toast by ID
|
|
356
|
+
* @param {number} toastId - Toast ID to hide
|
|
357
|
+
*/
|
|
358
|
+
hideToast(toastId) {
|
|
359
|
+
// Clear timer
|
|
360
|
+
this._clearToastTimer(toastId)
|
|
361
|
+
|
|
362
|
+
// Remove from array
|
|
363
|
+
const index = this.toastState.toasts.findIndex(t => t.id === toastId)
|
|
364
|
+
if (index !== -1) {
|
|
365
|
+
this.toastState.toasts.splice(index, 1)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Hide all toasts
|
|
371
|
+
*/
|
|
372
|
+
hideAllToasts() {
|
|
373
|
+
// Clear all timers
|
|
374
|
+
for (const id of this._toastTimers.keys()) {
|
|
375
|
+
this._clearToastTimer(id)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Clear array
|
|
379
|
+
this.toastState.toasts.splice(0, this.toastState.toasts.length)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Pause auto-dismiss timer for a specific toast
|
|
384
|
+
* @param {number} toastId - Toast ID
|
|
385
|
+
*/
|
|
386
|
+
pauseToast(toastId) {
|
|
387
|
+
const timer = this._toastTimers.get(toastId)
|
|
388
|
+
if (!timer || timer.isPaused) return
|
|
389
|
+
|
|
390
|
+
clearTimeout(timer.timeout)
|
|
391
|
+
timer.timeout = null
|
|
392
|
+
|
|
393
|
+
const elapsed = Date.now() - timer.startedAt
|
|
394
|
+
timer.remainingTime = Math.max(0, timer.remainingTime - elapsed)
|
|
395
|
+
timer.isPaused = true
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Resume auto-dismiss timer for a specific toast
|
|
400
|
+
* @param {number} toastId - Toast ID
|
|
401
|
+
*/
|
|
402
|
+
resumeToast(toastId) {
|
|
403
|
+
const timer = this._toastTimers.get(toastId)
|
|
404
|
+
if (!timer || !timer.isPaused || timer.remainingTime <= 0) return
|
|
405
|
+
|
|
406
|
+
timer.isPaused = false
|
|
407
|
+
timer.startedAt = Date.now()
|
|
408
|
+
|
|
409
|
+
timer.timeout = setTimeout(() => {
|
|
410
|
+
this.hideToast(toastId)
|
|
411
|
+
}, timer.remainingTime)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get toasts for a specific position
|
|
416
|
+
* @param {string} position - Position to filter by
|
|
417
|
+
* @returns {Array} Toasts at that position
|
|
418
|
+
*/
|
|
419
|
+
getToastsByPosition(position) {
|
|
420
|
+
return this.toastState.toasts.filter(t => t.position === position)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// ============================================
|
|
424
|
+
// Private Toast Timer Methods
|
|
425
|
+
// ============================================
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* @private
|
|
429
|
+
*/
|
|
430
|
+
_startToastTimer(toastId, duration) {
|
|
431
|
+
const timer = {
|
|
432
|
+
timeout: null,
|
|
433
|
+
remainingTime: duration,
|
|
434
|
+
startedAt: Date.now(),
|
|
435
|
+
isPaused: false,
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
timer.timeout = setTimeout(() => {
|
|
439
|
+
this.hideToast(toastId)
|
|
440
|
+
}, duration)
|
|
441
|
+
|
|
442
|
+
this._toastTimers.set(toastId, timer)
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* @private
|
|
447
|
+
*/
|
|
448
|
+
_clearToastTimer(toastId) {
|
|
449
|
+
const timer = this._toastTimers.get(toastId)
|
|
450
|
+
if (timer) {
|
|
451
|
+
if (timer.timeout) {
|
|
452
|
+
clearTimeout(timer.timeout)
|
|
453
|
+
}
|
|
454
|
+
this._toastTimers.delete(toastId)
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export const sparkNotificationService = new SparkNotificationService()
|
|
@@ -6,7 +6,7 @@ class SparkOverlayService {
|
|
|
6
6
|
this.right = useSparkOverlay()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
showLeft = (component, props = {}, eventHandlers = {}) => {
|
|
9
|
+
showLeft = (component, props = {}, eventHandlers = {}, options = {}) => {
|
|
10
10
|
const handlers = {
|
|
11
11
|
close: () => {
|
|
12
12
|
// Call user's close handler if provided
|
|
@@ -16,10 +16,10 @@ class SparkOverlayService {
|
|
|
16
16
|
},
|
|
17
17
|
...eventHandlers,
|
|
18
18
|
}
|
|
19
|
-
this.left.show(component, props, handlers)
|
|
19
|
+
this.left.show(component, props, handlers, options)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
showRight = (component, props = {}, eventHandlers = {}) => {
|
|
22
|
+
showRight = (component, props = {}, eventHandlers = {}, options = {}) => {
|
|
23
23
|
const handlers = {
|
|
24
24
|
close: () => {
|
|
25
25
|
// Call user's close handler if provided
|
|
@@ -29,7 +29,7 @@ class SparkOverlayService {
|
|
|
29
29
|
},
|
|
30
30
|
...eventHandlers,
|
|
31
31
|
}
|
|
32
|
-
this.right.show(component, props, handlers)
|
|
32
|
+
this.right.show(component, props, handlers, options)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
closeLeft = () => {
|
|
@@ -6,6 +6,7 @@ export function useSparkOverlay() {
|
|
|
6
6
|
content: null,
|
|
7
7
|
props: {},
|
|
8
8
|
eventHandlers: {},
|
|
9
|
+
size: 'md',
|
|
9
10
|
})
|
|
10
11
|
|
|
11
12
|
const toggle = () => {
|
|
@@ -17,20 +18,22 @@ export function useSparkOverlay() {
|
|
|
17
18
|
state.content = null
|
|
18
19
|
state.props = {}
|
|
19
20
|
state.eventHandlers = {}
|
|
21
|
+
state.size = 'md'
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const open = () => {
|
|
23
25
|
state.isVisible = true
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
const setContent = (content, props = {}, eventHandlers = {}) => {
|
|
28
|
+
const setContent = (content, props = {}, eventHandlers = {}, options = {}) => {
|
|
27
29
|
state.content = markRaw(content)
|
|
28
30
|
state.props = props
|
|
29
31
|
state.eventHandlers = eventHandlers
|
|
32
|
+
state.size = options.size || 'md'
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
const show = (content, props = {}, eventHandlers = {}) => {
|
|
33
|
-
if (content) setContent(content, props, eventHandlers)
|
|
35
|
+
const show = (content, props = {}, eventHandlers = {}, options = {}) => {
|
|
36
|
+
if (content) setContent(content, props, eventHandlers, options)
|
|
34
37
|
open()
|
|
35
38
|
}
|
|
36
39
|
|