@fy-/fws-vue 2.1.42 → 2.1.44
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.
|
@@ -388,7 +388,7 @@ onUnmounted(() => {
|
|
|
388
388
|
</Dialog>
|
|
389
389
|
</TransitionRoot>
|
|
390
390
|
|
|
391
|
-
<div v-if="mode === 'grid' || mode === 'mason' || mode === 'custom'" class="min-h-[600px]
|
|
391
|
+
<div v-if="mode === 'grid' || mode === 'mason' || mode === 'custom'" class="min-h-[600px]">
|
|
392
392
|
<div
|
|
393
393
|
:class="{
|
|
394
394
|
' grid grid-cols-2 md:grid-cols-4 xl:grid-cols-6 gap-4 items-start':
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { Component } from 'vue'
|
|
3
|
-
|
|
4
3
|
import {
|
|
5
4
|
CheckCircleIcon,
|
|
6
5
|
ExclamationTriangleIcon,
|
|
7
6
|
LightBulbIcon,
|
|
7
|
+
SparklesIcon,
|
|
8
8
|
} from '@heroicons/vue/24/solid'
|
|
9
9
|
import { onMounted, onUnmounted, ref } from 'vue'
|
|
10
10
|
import { useEventBus } from '../../composables/event-bus'
|
|
11
11
|
import ScaleTransition from './transitions/ScaleTransition.vue'
|
|
12
12
|
|
|
13
|
+
/** Notification interface */
|
|
13
14
|
interface NotifProps {
|
|
14
15
|
imgSrc?: string
|
|
15
16
|
imgIcon?: Component
|
|
@@ -18,56 +19,97 @@ interface NotifProps {
|
|
|
18
19
|
ctaText?: string
|
|
19
20
|
ctaLink?: string
|
|
20
21
|
ctaAction?: () => void
|
|
21
|
-
|
|
22
|
+
/** Add your new 'secret' type */
|
|
23
|
+
type?: 'info' | 'warning' | 'success' | 'secret'
|
|
24
|
+
/** Notification timeout in milliseconds */
|
|
22
25
|
time?: number
|
|
23
26
|
}
|
|
27
|
+
|
|
28
|
+
/** Our global event bus (replace with your own logic if needed) */
|
|
24
29
|
const eventBus = useEventBus()
|
|
30
|
+
|
|
31
|
+
/** Current displayed notification */
|
|
25
32
|
const currentNotif = ref<NotifProps | null>(null)
|
|
26
|
-
|
|
33
|
+
|
|
34
|
+
/** Progress percentage (0 to 100) for the notification’s life */
|
|
35
|
+
const progress = ref(0)
|
|
36
|
+
|
|
37
|
+
/** References to setTimeout / setInterval so we can clear them properly */
|
|
38
|
+
let hideTimeout: ReturnType<typeof setTimeout> | null = null
|
|
39
|
+
let progressInterval: ReturnType<typeof setInterval> | null = null
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Primary logic when a 'SendNotif' event is called.
|
|
43
|
+
* - Clears any existing notification first
|
|
44
|
+
* - Sets up the new notification
|
|
45
|
+
* - Starts a progress bar
|
|
46
|
+
*/
|
|
27
47
|
function onCall(data: NotifProps) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (data.imgIcon === undefined) {
|
|
33
|
-
if (data.type === 'info') {
|
|
34
|
-
actualIcon.value = LightBulbIcon
|
|
35
|
-
}
|
|
36
|
-
else if (data.type === 'warning') {
|
|
37
|
-
actualIcon.value = ExclamationTriangleIcon
|
|
38
|
-
}
|
|
39
|
-
else if (data.type === 'success') {
|
|
40
|
-
actualIcon.value = CheckCircleIcon
|
|
41
|
-
}
|
|
42
|
-
}
|
|
48
|
+
// If there's an existing notification, remove it first
|
|
49
|
+
hideNotif()
|
|
50
|
+
|
|
51
|
+
// Ensure a minimum of 1s if time is too short or undefined
|
|
43
52
|
if (!data.time || data.time < 1000) {
|
|
44
53
|
data.time = 5000
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
// Automatically compute an icon if none is provided
|
|
57
|
+
if (!data.imgIcon) {
|
|
58
|
+
if (data.type === 'info') data.imgIcon = LightBulbIcon
|
|
59
|
+
else if (data.type === 'warning') data.imgIcon = ExclamationTriangleIcon
|
|
60
|
+
else if (data.type === 'success') data.imgIcon = CheckCircleIcon
|
|
61
|
+
else if (data.type === 'secret') data.imgIcon = SparklesIcon
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Set the new notification
|
|
47
65
|
currentNotif.value = {
|
|
48
|
-
|
|
49
|
-
imgIcon: actualIcon.value,
|
|
50
|
-
title: data.title,
|
|
51
|
-
content: data.content,
|
|
52
|
-
ctaText: data.ctaText,
|
|
53
|
-
ctaLink: data.ctaLink,
|
|
54
|
-
time: data.time,
|
|
55
|
-
type: data.type,
|
|
56
|
-
ctaAction: data.ctaAction,
|
|
66
|
+
...data,
|
|
57
67
|
}
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
// (A) Hide the notification after the specified time
|
|
70
|
+
hideTimeout = setTimeout(() => hideNotif(), data.time)
|
|
71
|
+
|
|
72
|
+
// (B) Animate the progress bar from 0 to 100% within that time
|
|
73
|
+
progress.value = 0
|
|
74
|
+
progressInterval = setInterval(() => {
|
|
75
|
+
if (currentNotif.value && data.time) {
|
|
76
|
+
// update progress based on a 100ms tick
|
|
77
|
+
progress.value += (100 / (data.time / 100))
|
|
78
|
+
// if progress hits or exceeds 100, hide
|
|
79
|
+
if (progress.value >= 100) {
|
|
80
|
+
hideNotif()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, 100)
|
|
60
84
|
}
|
|
61
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Clears everything related to the current notification
|
|
88
|
+
*/
|
|
62
89
|
function hideNotif() {
|
|
63
90
|
currentNotif.value = null
|
|
64
|
-
|
|
65
|
-
|
|
91
|
+
progress.value = 0
|
|
92
|
+
|
|
93
|
+
if (hideTimeout) {
|
|
94
|
+
clearTimeout(hideTimeout)
|
|
95
|
+
hideTimeout = null
|
|
96
|
+
}
|
|
97
|
+
if (progressInterval) {
|
|
98
|
+
clearInterval(progressInterval)
|
|
99
|
+
progressInterval = null
|
|
66
100
|
}
|
|
67
101
|
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Setup: Listen to the global event bus
|
|
105
|
+
*/
|
|
68
106
|
onMounted(() => {
|
|
69
107
|
eventBus.on('SendNotif', onCall)
|
|
70
108
|
})
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Cleanup: remove event listeners
|
|
112
|
+
*/
|
|
71
113
|
onUnmounted(() => {
|
|
72
114
|
eventBus.off('SendNotif', onCall)
|
|
73
115
|
})
|
|
@@ -78,17 +120,20 @@ onUnmounted(() => {
|
|
|
78
120
|
<div
|
|
79
121
|
v-if="currentNotif !== null"
|
|
80
122
|
id="base-notif"
|
|
81
|
-
class="p-2 mb-4 fixed bottom-4 right-8 !z-[2000] bg-fv-neutral-50/[.6] dark:bg-neutral-800/[.6]"
|
|
123
|
+
class="p-2 mb-4 fixed bottom-4 right-8 !z-[2000] bg-fv-neutral-50/[.6] dark:bg-neutral-800/[.6] rounded-lg border"
|
|
82
124
|
role="alert"
|
|
83
125
|
:class="{
|
|
84
|
-
'text-fv-neutral-800 border
|
|
126
|
+
'text-fv-neutral-800 border-fv-neutral-300 dark:text-fv-neutral-400 dark:border-fv-neutral-600':
|
|
85
127
|
currentNotif.type === 'info',
|
|
86
|
-
'text-red-800 border
|
|
128
|
+
'text-red-800 border-red-300 dark:text-red-300 dark:border-red-800':
|
|
87
129
|
currentNotif.type === 'warning',
|
|
88
|
-
'text-green-800 border
|
|
130
|
+
'text-green-800 border-green-300 dark:text-green-300 dark:border-green-800':
|
|
89
131
|
currentNotif.type === 'success',
|
|
132
|
+
'text-fuchsia-800 border-fuchsia-300 dark:text-fuchsia-300 dark:border-fuchsia-800':
|
|
133
|
+
currentNotif.type === 'secret',
|
|
90
134
|
}"
|
|
91
135
|
>
|
|
136
|
+
<!-- Title + icon or image -->
|
|
92
137
|
<div class="flex items-center gap-2">
|
|
93
138
|
<img
|
|
94
139
|
v-if="currentNotif.imgSrc"
|
|
@@ -103,11 +148,24 @@ onUnmounted(() => {
|
|
|
103
148
|
/>
|
|
104
149
|
<h3 class="text-lg font-medium" v-text="currentNotif.title" />
|
|
105
150
|
</div>
|
|
151
|
+
|
|
152
|
+
<!-- Optional content -->
|
|
106
153
|
<div
|
|
107
154
|
v-if="currentNotif.content"
|
|
108
|
-
class="mt-
|
|
155
|
+
class="mt-2 text-sm"
|
|
109
156
|
v-text="currentNotif.content"
|
|
110
157
|
/>
|
|
158
|
+
|
|
159
|
+
<!-- Progress bar (3px) -->
|
|
160
|
+
<div class="relative mt-3 h-[3px] bg-gray-200 rounded-full overflow-hidden">
|
|
161
|
+
<!-- We re-use text color (text-*) as background or define a custom color -->
|
|
162
|
+
<div
|
|
163
|
+
class="absolute left-0 top-0 h-full bg-current transition-[width]"
|
|
164
|
+
:style="{ width: `${progress}%` }"
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<!-- CTA row (if you need more buttons, just extend it) -->
|
|
111
169
|
<div class="flex justify-end gap-2 pt-3">
|
|
112
170
|
<button
|
|
113
171
|
type="button"
|
|
@@ -115,6 +173,7 @@ onUnmounted(() => {
|
|
|
115
173
|
aria-label="Close"
|
|
116
174
|
@click="hideNotif"
|
|
117
175
|
>
|
|
176
|
+
<!-- i18n example, or plain text like "Dismiss" -->
|
|
118
177
|
{{ $t("dismiss_cta") }}
|
|
119
178
|
</button>
|
|
120
179
|
</div>
|