@wishbone-media/spark 0.28.0 → 0.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
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
</template>
|
|
31
31
|
|
|
32
32
|
<script setup>
|
|
33
|
-
import { computed, ref, watch } from 'vue'
|
|
33
|
+
import { computed, ref, watch, onMounted } from 'vue'
|
|
34
|
+
import { useRoute } from 'vue-router'
|
|
34
35
|
import { sparkNotificationService } from '@/composables/sparkNotificationService'
|
|
35
36
|
import SparkAlert from '@/components/SparkAlert.vue'
|
|
36
37
|
|
|
@@ -39,8 +40,13 @@ const props = defineProps({
|
|
|
39
40
|
type: String,
|
|
40
41
|
default: 'default',
|
|
41
42
|
},
|
|
43
|
+
clearOnRouteChange: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: true,
|
|
46
|
+
},
|
|
42
47
|
})
|
|
43
48
|
|
|
49
|
+
const route = useRoute()
|
|
44
50
|
const outlet = computed(() => sparkNotificationService.getOutlet(props.name))
|
|
45
51
|
|
|
46
52
|
// Generate unique key for each notification to trigger transition on content change
|
|
@@ -54,6 +60,43 @@ watch(
|
|
|
54
60
|
},
|
|
55
61
|
)
|
|
56
62
|
|
|
63
|
+
// Track which path the notification was shown on
|
|
64
|
+
watch(
|
|
65
|
+
() => outlet.value.state.isVisible,
|
|
66
|
+
(isVisible) => {
|
|
67
|
+
if (isVisible && !outlet.value.state.shownOnPath) {
|
|
68
|
+
outlet.value.state.shownOnPath = route.path
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{ immediate: true },
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// On mount, check if notification was shown on a different route
|
|
75
|
+
onMounted(() => {
|
|
76
|
+
if (!props.clearOnRouteChange) return
|
|
77
|
+
if (route.meta.preserveNotifications) return
|
|
78
|
+
if (!outlet.value.state.isVisible) return
|
|
79
|
+
if (outlet.value.state.persistent) return
|
|
80
|
+
|
|
81
|
+
// If notification was shown on a different path, hide it
|
|
82
|
+
if (outlet.value.state.shownOnPath && outlet.value.state.shownOnPath !== route.path) {
|
|
83
|
+
outlet.value.hide()
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// Auto-clear notification on route change (while mounted)
|
|
88
|
+
watch(
|
|
89
|
+
() => route.path,
|
|
90
|
+
() => {
|
|
91
|
+
if (!props.clearOnRouteChange) return
|
|
92
|
+
if (route.meta.preserveNotifications) return
|
|
93
|
+
if (!outlet.value.state.isVisible) return
|
|
94
|
+
if (outlet.value.state.persistent) return
|
|
95
|
+
|
|
96
|
+
outlet.value.hide()
|
|
97
|
+
},
|
|
98
|
+
)
|
|
99
|
+
|
|
57
100
|
const handleClose = () => {
|
|
58
101
|
sparkNotificationService.hide(props.name)
|
|
59
102
|
}
|
|
@@ -24,6 +24,8 @@ function createNotificationOutlet() {
|
|
|
24
24
|
props: {},
|
|
25
25
|
closeable: true,
|
|
26
26
|
duration: null,
|
|
27
|
+
persistent: false,
|
|
28
|
+
shownOnPath: null,
|
|
27
29
|
})
|
|
28
30
|
|
|
29
31
|
// Timer state (not reactive, internal only)
|
|
@@ -90,6 +92,7 @@ function createNotificationOutlet() {
|
|
|
90
92
|
props = {},
|
|
91
93
|
closeable = true,
|
|
92
94
|
duration = null,
|
|
95
|
+
persistent = false,
|
|
93
96
|
} = options
|
|
94
97
|
|
|
95
98
|
state.type = type
|
|
@@ -97,6 +100,7 @@ function createNotificationOutlet() {
|
|
|
97
100
|
state.component = component ? markRaw(component) : null
|
|
98
101
|
state.props = props
|
|
99
102
|
state.closeable = closeable
|
|
103
|
+
state.persistent = persistent
|
|
100
104
|
state.isVisible = true
|
|
101
105
|
|
|
102
106
|
// Determine duration: explicit > default for type
|
|
@@ -116,6 +120,8 @@ function createNotificationOutlet() {
|
|
|
116
120
|
state.props = {}
|
|
117
121
|
state.closeable = true
|
|
118
122
|
state.duration = null
|
|
123
|
+
state.persistent = false
|
|
124
|
+
state.shownOnPath = null
|
|
119
125
|
}
|
|
120
126
|
|
|
121
127
|
return {
|
|
@@ -187,6 +193,7 @@ class SparkNotificationService {
|
|
|
187
193
|
* @param {Object} options.props - Props to pass to the component
|
|
188
194
|
* @param {boolean} options.closeable - Whether to show close button (default: true)
|
|
189
195
|
* @param {number} options.duration - Auto-dismiss duration in ms (0 = sticky, null = use default)
|
|
196
|
+
* @param {boolean} options.persistent - Whether notification survives route changes (default: false)
|
|
190
197
|
* @param {string} outletName - Target outlet name (default: 'default')
|
|
191
198
|
*/
|
|
192
199
|
show(options = {}, outletName = 'default') {
|
|
@@ -212,6 +219,18 @@ class SparkNotificationService {
|
|
|
212
219
|
}
|
|
213
220
|
}
|
|
214
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Hide all non-persistent banner notifications
|
|
224
|
+
* Called by setupNotificationGuard on route change
|
|
225
|
+
*/
|
|
226
|
+
hideAllNonPersistent() {
|
|
227
|
+
for (const outlet of this.outlets.values()) {
|
|
228
|
+
if (!outlet.state.persistent) {
|
|
229
|
+
outlet.hide()
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
215
234
|
/**
|
|
216
235
|
* Pause auto-dismiss timer for the specified banner outlet
|
|
217
236
|
* @param {string} outletName - Target outlet name (default: 'default')
|