@quazardous/qdadm 2.28.0 → 2.29.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/package.json
CHANGED
|
@@ -340,7 +340,12 @@ export function useEntityItemShowPage<T = Record<string, unknown>>(
|
|
|
340
340
|
keep: 'short',
|
|
341
341
|
...(route?.name ? { to: { name: String(route.name), params: { ...route.params } } } : {}),
|
|
342
342
|
})
|
|
343
|
-
}, {
|
|
343
|
+
}, {
|
|
344
|
+
id: () => entityId.value,
|
|
345
|
+
// The update has arrived: say so on the badge at once — before the reload is
|
|
346
|
+
// coalesced, let alone finished (#2679).
|
|
347
|
+
onEvent: () => notifications.flash(),
|
|
348
|
+
})
|
|
344
349
|
// Cast orchestrator to include toast methods
|
|
345
350
|
const orchestrator = baseOrchestrator as Orchestrator
|
|
346
351
|
|
|
@@ -27,6 +27,12 @@ export interface UseLiveEntityOptions {
|
|
|
27
27
|
* own id: without it, changing one record reloads every open detail page.
|
|
28
28
|
*/
|
|
29
29
|
id?: () => string | number | null | undefined
|
|
30
|
+
/**
|
|
31
|
+
* Called at once for every event that concerns this screen, before the
|
|
32
|
+
* reload is coalesced (#2679) — for a cue that must not wait, like the
|
|
33
|
+
* notification badge's flash.
|
|
34
|
+
*/
|
|
35
|
+
onEvent?: () => void
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
interface LivePolicy {
|
|
@@ -129,6 +135,8 @@ export function useLiveEntity(
|
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
|
|
138
|
+
options.onEvent?.()
|
|
139
|
+
|
|
132
140
|
// Coalesce: a backend replaying fifty rows must cost one reload, not fifty.
|
|
133
141
|
if (coalesceMs <= 0) {
|
|
134
142
|
fire()
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* - something needs attention: the parent layout blinks the logo via
|
|
8
8
|
* :has(.notification-badge-zone--alert);
|
|
9
9
|
* - how many entries are unread: a count;
|
|
10
|
-
* - work is in progress: a ring, once tracked work has lasted `activityDelayMs
|
|
10
|
+
* - work is in progress: a ring, once tracked work has lasted `activityDelayMs`;
|
|
11
|
+
* - something just arrived: a short flash, immediately (#2679).
|
|
11
12
|
*
|
|
12
13
|
* Click toggles the notification panel open/close.
|
|
13
14
|
*/
|
|
@@ -29,6 +30,7 @@ const unreadLabel = computed(() => (unread.value > 99 ? '99+' : String(unread.va
|
|
|
29
30
|
@click.stop.prevent="store.toggle()"
|
|
30
31
|
>
|
|
31
32
|
<span v-if="store.isBusy.value" class="notification-badge-ring" role="progressbar" aria-label="Loading" />
|
|
33
|
+
<span v-if="store.isFlashing.value" class="notification-badge-flash" aria-hidden="true" />
|
|
32
34
|
<span v-if="unread > 0" class="notification-badge-count">{{ unreadLabel }}</span>
|
|
33
35
|
</div>
|
|
34
36
|
</template>
|
|
@@ -78,11 +80,30 @@ const unreadLabel = computed(() => (unread.value > 99 ? '99+' : String(unread.va
|
|
|
78
80
|
to { transform: rotate(360deg); }
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
/* Something just arrived: a halo that grows out of the logo and fades. */
|
|
84
|
+
.notification-badge-flash {
|
|
85
|
+
position: absolute;
|
|
86
|
+
inset: 0;
|
|
87
|
+
border-radius: 50%;
|
|
88
|
+
pointer-events: none;
|
|
89
|
+
animation: notification-badge-flash 0.9s ease-out 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@keyframes notification-badge-flash {
|
|
93
|
+
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--p-primary-color, #3b82f6) 70%, transparent); }
|
|
94
|
+
100% { box-shadow: 0 0 0 14px color-mix(in srgb, var(--p-primary-color, #3b82f6) 0%, transparent); }
|
|
95
|
+
}
|
|
96
|
+
|
|
81
97
|
@media (prefers-reduced-motion: reduce) {
|
|
82
98
|
.notification-badge-ring {
|
|
83
99
|
animation: none;
|
|
84
100
|
border-color: var(--p-primary-color, #3b82f6);
|
|
85
101
|
opacity: 0.5;
|
|
86
102
|
}
|
|
103
|
+
|
|
104
|
+
.notification-badge-flash {
|
|
105
|
+
animation: none;
|
|
106
|
+
box-shadow: 0 0 0 3px var(--p-primary-color, #3b82f6);
|
|
107
|
+
}
|
|
87
108
|
}
|
|
88
109
|
</style>
|
|
@@ -118,6 +118,14 @@ export interface NotificationStore {
|
|
|
118
118
|
track<T>(work: Promise<T>): Promise<T>
|
|
119
119
|
/** True once tracked work has been in progress for `activityDelayMs`. */
|
|
120
120
|
isBusy: ComputedRef<boolean>
|
|
121
|
+
/**
|
|
122
|
+
* Flash the badge: something just arrived — an update to the record on
|
|
123
|
+
* screen (#2679). Immediate, never delayed; a flash already running absorbs
|
|
124
|
+
* further calls, so a burst flashes once.
|
|
125
|
+
*/
|
|
126
|
+
flash(): void
|
|
127
|
+
/** True while the badge flashes. */
|
|
128
|
+
isFlashing: ComputedRef<boolean>
|
|
121
129
|
|
|
122
130
|
// Panel state
|
|
123
131
|
isOpen: Ref<boolean>
|
|
@@ -288,6 +296,20 @@ export function createNotificationStore(config: NotificationStoreConfig = {}): N
|
|
|
288
296
|
return work
|
|
289
297
|
}
|
|
290
298
|
|
|
299
|
+
// ── Flash ──────────────────────────────────────────────────────────────
|
|
300
|
+
|
|
301
|
+
const FLASH_MS = 900
|
|
302
|
+
const flashing = ref(false)
|
|
303
|
+
|
|
304
|
+
function flash(): void {
|
|
305
|
+
// A burst of updates flashes once: the running flash already says it.
|
|
306
|
+
if (flashing.value) return
|
|
307
|
+
flashing.value = true
|
|
308
|
+
setTimeout(() => {
|
|
309
|
+
flashing.value = false
|
|
310
|
+
}, FLASH_MS)
|
|
311
|
+
}
|
|
312
|
+
|
|
291
313
|
// ── Panel state ────────────────────────────────────────────────────────
|
|
292
314
|
|
|
293
315
|
function open(): void {
|
|
@@ -338,6 +360,8 @@ export function createNotificationStore(config: NotificationStoreConfig = {}): N
|
|
|
338
360
|
removeStatus,
|
|
339
361
|
track,
|
|
340
362
|
isBusy: computed(() => busy.value),
|
|
363
|
+
flash,
|
|
364
|
+
isFlashing: computed(() => flashing.value),
|
|
341
365
|
isOpen,
|
|
342
366
|
open,
|
|
343
367
|
close,
|
|
@@ -383,6 +407,8 @@ export function useNotifications(): NotificationStore {
|
|
|
383
407
|
removeStatus: () => {},
|
|
384
408
|
track: (work) => work,
|
|
385
409
|
isBusy: computed(() => false),
|
|
410
|
+
flash: () => {},
|
|
411
|
+
isFlashing: computed(() => false),
|
|
386
412
|
isOpen: ref(false),
|
|
387
413
|
open: () => {},
|
|
388
414
|
close: () => {},
|