ketekny-ui-kit 1.0.46 → 1.0.48
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 +1 -1
- package/src/ui/kMessageNew.vue +73 -6
package/package.json
CHANGED
package/src/ui/kMessageNew.vue
CHANGED
|
@@ -89,13 +89,34 @@
|
|
|
89
89
|
</button>
|
|
90
90
|
</div>
|
|
91
91
|
</div>
|
|
92
|
+
|
|
93
|
+
<div
|
|
94
|
+
v-if="showDismissProgress"
|
|
95
|
+
:class="['mt-1 flex items-center justify-end gap-1 text-[10px] font-medium leading-none', colors.label]"
|
|
96
|
+
aria-hidden="true"
|
|
97
|
+
>
|
|
98
|
+
<Clock3 class="h-2.5 w-2.5" />
|
|
99
|
+
<span>{{ dismissSecondsLeft }}s</span>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div
|
|
103
|
+
v-if="showDismissProgress"
|
|
104
|
+
:class="['pointer-events-none absolute inset-x-0 bottom-0 h-1', progressTracks[type]]"
|
|
105
|
+
aria-hidden="true"
|
|
106
|
+
/>
|
|
107
|
+
<div
|
|
108
|
+
v-if="showDismissProgress"
|
|
109
|
+
:class="['pointer-events-none absolute bottom-0 left-0 h-1', progressBars[type]]"
|
|
110
|
+
:style="{ width: `${dismissElapsedPercent}%` }"
|
|
111
|
+
aria-hidden="true"
|
|
112
|
+
/>
|
|
92
113
|
</div>
|
|
93
114
|
</Transition>
|
|
94
115
|
</template>
|
|
95
116
|
|
|
96
117
|
<script setup>
|
|
97
118
|
import { computed, onBeforeUnmount, ref, useSlots, watch } from 'vue'
|
|
98
|
-
import { X as CloseIcon, Info, CircleCheckBig, TriangleAlert, OctagonX } from 'lucide-vue-next'
|
|
119
|
+
import { X as CloseIcon, Info, CircleCheckBig, TriangleAlert, OctagonX, Clock3 } from 'lucide-vue-next'
|
|
99
120
|
|
|
100
121
|
// ─── Color config ────────────────────────────────────────────────────────────
|
|
101
122
|
|
|
@@ -109,7 +130,7 @@ const colorConfig = {
|
|
|
109
130
|
label: 'text-slate-500 dark:text-slate-300',
|
|
110
131
|
},
|
|
111
132
|
standard: {
|
|
112
|
-
container: 'border-
|
|
133
|
+
container: 'border-sky-200/90 bg-sky-50/60 dark:border-sky-500/35 dark:bg-sky-950/35',
|
|
113
134
|
icon: 'bg-sky-100 border-sky-300 text-sky-700 dark:bg-sky-500/15 dark:border-sky-400/40 dark:text-sky-300',
|
|
114
135
|
title: 'text-sky-700 dark:text-sky-300',
|
|
115
136
|
body: 'text-slate-700 dark:text-slate-200',
|
|
@@ -139,7 +160,7 @@ const colorConfig = {
|
|
|
139
160
|
label: 'text-slate-500 dark:text-slate-300',
|
|
140
161
|
},
|
|
141
162
|
standard: {
|
|
142
|
-
container: 'border-
|
|
163
|
+
container: 'border-emerald-200/90 bg-emerald-50/60 dark:border-emerald-500/35 dark:bg-emerald-950/35',
|
|
143
164
|
icon: 'bg-emerald-100 border-emerald-300 text-emerald-700 dark:bg-emerald-500/15 dark:border-emerald-400/40 dark:text-emerald-300',
|
|
144
165
|
title: 'text-emerald-700 dark:text-emerald-300',
|
|
145
166
|
body: 'text-slate-700 dark:text-slate-200',
|
|
@@ -169,7 +190,7 @@ const colorConfig = {
|
|
|
169
190
|
label: 'text-slate-500 dark:text-slate-300',
|
|
170
191
|
},
|
|
171
192
|
standard: {
|
|
172
|
-
container: 'border-
|
|
193
|
+
container: 'border-amber-200/90 bg-amber-50/60 dark:border-amber-500/35 dark:bg-amber-950/35',
|
|
173
194
|
icon: 'bg-amber-100 border-amber-300 text-amber-700 dark:bg-amber-500/15 dark:border-amber-400/40 dark:text-amber-300',
|
|
174
195
|
title: 'text-amber-700 dark:text-amber-300',
|
|
175
196
|
body: 'text-slate-700 dark:text-slate-200',
|
|
@@ -199,7 +220,7 @@ const colorConfig = {
|
|
|
199
220
|
label: 'text-slate-500 dark:text-slate-300',
|
|
200
221
|
},
|
|
201
222
|
standard: {
|
|
202
|
-
container: 'border-
|
|
223
|
+
container: 'border-rose-200/90 bg-rose-50/60 dark:border-rose-500/35 dark:bg-rose-950/35',
|
|
203
224
|
icon: 'bg-rose-100 border-rose-300 text-rose-700 dark:bg-rose-500/15 dark:border-rose-400/40 dark:text-rose-300',
|
|
204
225
|
title: 'text-rose-700 dark:text-rose-300',
|
|
205
226
|
body: 'text-slate-700 dark:text-slate-200',
|
|
@@ -298,7 +319,9 @@ const slots = useSlots()
|
|
|
298
319
|
const internalVisible = ref(true)
|
|
299
320
|
const messageRef = ref(null)
|
|
300
321
|
const dismissTimer = ref(null)
|
|
322
|
+
const dismissRaf = ref(null)
|
|
301
323
|
const dismissStartedAt = ref(0)
|
|
324
|
+
const dismissRemainingAtStart = ref(0)
|
|
302
325
|
const dismissRemaining = ref(0)
|
|
303
326
|
|
|
304
327
|
const isVisible = computed(() => (props.visible !== null ? props.visible : internalVisible.value))
|
|
@@ -312,12 +335,53 @@ const dismissAfterMs = computed(() => {
|
|
|
312
335
|
const value = Number(props.dismissAfter)
|
|
313
336
|
return Number.isFinite(value) && value > 0 ? value : 0
|
|
314
337
|
})
|
|
338
|
+
const showDismissProgress = computed(() => isVisible.value && dismissAfterMs.value > 0)
|
|
339
|
+
const dismissElapsedPercent = computed(() => {
|
|
340
|
+
if (dismissAfterMs.value <= 0) return 0
|
|
341
|
+
return Math.min(100, Math.max(0, ((dismissAfterMs.value - dismissRemaining.value) / dismissAfterMs.value) * 100))
|
|
342
|
+
})
|
|
343
|
+
const dismissSecondsLeft = computed(() => Math.max(0, Math.ceil(dismissRemaining.value / 1000)))
|
|
344
|
+
|
|
345
|
+
const progressTracks = {
|
|
346
|
+
info: 'bg-sky-200/60 dark:bg-sky-900/55',
|
|
347
|
+
success: 'bg-emerald-200/60 dark:bg-emerald-900/55',
|
|
348
|
+
warning: 'bg-amber-200/60 dark:bg-amber-900/55',
|
|
349
|
+
error: 'bg-rose-200/60 dark:bg-rose-900/55',
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const progressBars = {
|
|
353
|
+
info: 'bg-sky-500/70 dark:bg-sky-400/80',
|
|
354
|
+
success: 'bg-emerald-500/70 dark:bg-emerald-400/80',
|
|
355
|
+
warning: 'bg-amber-500/80 dark:bg-amber-400/85',
|
|
356
|
+
error: 'bg-rose-500/70 dark:bg-rose-400/80',
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function stopDismissRaf() {
|
|
360
|
+
if (dismissRaf.value) {
|
|
361
|
+
cancelAnimationFrame(dismissRaf.value)
|
|
362
|
+
dismissRaf.value = null
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function syncDismissRemaining() {
|
|
367
|
+
if (!dismissTimer.value) return
|
|
368
|
+
|
|
369
|
+
const elapsed = Date.now() - dismissStartedAt.value
|
|
370
|
+
dismissRemaining.value = Math.max(0, dismissRemainingAtStart.value - elapsed)
|
|
371
|
+
|
|
372
|
+
if (dismissRemaining.value > 0) {
|
|
373
|
+
dismissRaf.value = requestAnimationFrame(syncDismissRemaining)
|
|
374
|
+
} else {
|
|
375
|
+
dismissRaf.value = null
|
|
376
|
+
}
|
|
377
|
+
}
|
|
315
378
|
|
|
316
379
|
function clearDismissTimer() {
|
|
317
380
|
if (dismissTimer.value) {
|
|
318
381
|
clearTimeout(dismissTimer.value)
|
|
319
382
|
dismissTimer.value = null
|
|
320
383
|
}
|
|
384
|
+
stopDismissRaf()
|
|
321
385
|
}
|
|
322
386
|
|
|
323
387
|
function startDismissTimer(duration) {
|
|
@@ -325,9 +389,12 @@ function startDismissTimer(duration) {
|
|
|
325
389
|
if (!isVisible.value || duration <= 0) return
|
|
326
390
|
|
|
327
391
|
dismissRemaining.value = duration
|
|
392
|
+
dismissRemainingAtStart.value = duration
|
|
328
393
|
dismissStartedAt.value = Date.now()
|
|
394
|
+
dismissRaf.value = requestAnimationFrame(syncDismissRemaining)
|
|
329
395
|
dismissTimer.value = setTimeout(() => {
|
|
330
396
|
dismissTimer.value = null
|
|
397
|
+
stopDismissRaf()
|
|
331
398
|
dismissRemaining.value = 0
|
|
332
399
|
close()
|
|
333
400
|
}, duration)
|
|
@@ -337,7 +404,7 @@ function pauseDismissTimer() {
|
|
|
337
404
|
if (!dismissTimer.value || dismissAfterMs.value <= 0) return
|
|
338
405
|
|
|
339
406
|
const elapsed = Date.now() - dismissStartedAt.value
|
|
340
|
-
dismissRemaining.value = Math.max(0,
|
|
407
|
+
dismissRemaining.value = Math.max(0, dismissRemainingAtStart.value - elapsed)
|
|
341
408
|
clearDismissTimer()
|
|
342
409
|
}
|
|
343
410
|
|