@wishbone-media/spark 1.3.1 → 1.4.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 +1290 -1287
- package/package.json +1 -1
- package/src/components/SparkOverlay.vue +15 -0
- package/src/composables/useSubNavigation.js +18 -2
package/package.json
CHANGED
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
<script setup>
|
|
58
58
|
import { computed, onUnmounted, ref } from 'vue'
|
|
59
59
|
import { Dialog, DialogPanel, TransitionChild, TransitionRoot } from '@headlessui/vue'
|
|
60
|
+
import { sparkModalService } from '@/composables/sparkModalService'
|
|
60
61
|
|
|
61
62
|
const panelRef = ref(null)
|
|
62
63
|
|
|
@@ -95,6 +96,20 @@ const widthClass = computed(() => {
|
|
|
95
96
|
})
|
|
96
97
|
|
|
97
98
|
const handleClose = () => {
|
|
99
|
+
// A spark modal stacked above overlay content (e.g. a confirm dialog) is a
|
|
100
|
+
// sibling Headless UI Dialog: its clicks and Escape register here as
|
|
101
|
+
// outside interactions. Ignore closes while one is open — the modal
|
|
102
|
+
// dismisses first, the overlay only on the next interaction.
|
|
103
|
+
//
|
|
104
|
+
// Two Headless UI behaviors this guard depends on (re-verify on upgrade):
|
|
105
|
+
// 1. Outside-click dismissal is dispatched on document `click` in the
|
|
106
|
+
// CAPTURE phase, so this runs before a modal button's bubble-phase
|
|
107
|
+
// handler calls hide() — isVisible is still true for the dismissing
|
|
108
|
+
// click itself.
|
|
109
|
+
// 2. Sibling Dialogs process document events in mount order; the overlay's
|
|
110
|
+
// Dialog mounts before any modal spawned from its content, so on a
|
|
111
|
+
// shared backdrop click this guard runs before the modal closes itself.
|
|
112
|
+
if (sparkModalService.state.isVisible) return
|
|
98
113
|
props.overlayInstance.close()
|
|
99
114
|
emit('close')
|
|
100
115
|
}
|
|
@@ -67,6 +67,10 @@ export function useSubNavigation(options = {}) {
|
|
|
67
67
|
// Reactive items list
|
|
68
68
|
const items = ref(initialItems.map(normalizeItem))
|
|
69
69
|
|
|
70
|
+
// Local selection for route-less items without query sync (e.g. tabs inside
|
|
71
|
+
// an overlay panel, where writing to the host route's query is undesirable)
|
|
72
|
+
const manualActiveId = ref(null)
|
|
73
|
+
|
|
70
74
|
/**
|
|
71
75
|
* Normalize item to ensure consistent structure
|
|
72
76
|
*/
|
|
@@ -124,7 +128,11 @@ export function useSubNavigation(options = {}) {
|
|
|
124
128
|
return itemObj.id === fallbackId
|
|
125
129
|
}
|
|
126
130
|
|
|
127
|
-
|
|
131
|
+
// Local mode: route-less items without query sync track manual selection
|
|
132
|
+
if (!itemObj.route) {
|
|
133
|
+
const fallbackId = defaultId || visibleItems.value[0]?.id
|
|
134
|
+
return itemObj.id === (manualActiveId.value ?? fallbackId)
|
|
135
|
+
}
|
|
128
136
|
|
|
129
137
|
// Handle route as string (route name) or object
|
|
130
138
|
const itemRoute = typeof itemObj.route === 'string' ? { name: itemObj.route } : itemObj.route
|
|
@@ -226,7 +234,9 @@ export function useSubNavigation(options = {}) {
|
|
|
226
234
|
return true
|
|
227
235
|
}
|
|
228
236
|
|
|
229
|
-
|
|
237
|
+
// Local mode: remember the selection without touching the route
|
|
238
|
+
manualActiveId.value = itemObj.id
|
|
239
|
+
return true
|
|
230
240
|
}
|
|
231
241
|
|
|
232
242
|
/**
|
|
@@ -235,6 +245,12 @@ export function useSubNavigation(options = {}) {
|
|
|
235
245
|
*/
|
|
236
246
|
function setItems(newItems) {
|
|
237
247
|
items.value = newItems.map(normalizeItem)
|
|
248
|
+
// Drop a local-mode selection whose id no longer exists — a later items
|
|
249
|
+
// update reintroducing the id would otherwise silently re-activate it.
|
|
250
|
+
// Selections whose id survives the replacement are kept.
|
|
251
|
+
if (manualActiveId.value && !items.value.some((item) => item.id === manualActiveId.value)) {
|
|
252
|
+
manualActiveId.value = null
|
|
253
|
+
}
|
|
238
254
|
}
|
|
239
255
|
|
|
240
256
|
/**
|