@wishbone-media/spark 0.38.0 → 0.40.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.css +1 -1
- package/dist/index.js +818 -845
- package/formkit.theme.mjs +3415 -3415
- package/package.json +31 -1
- package/src/assets/css/spark-table.css +1 -1
- package/src/assets/css/spark-tooltip.css +9 -3
- package/src/components/SparkAddressInput.vue +20 -3
- package/src/components/SparkAppSelector.vue +7 -7
- package/src/components/SparkBrandSelector.vue +2 -2
- package/src/components/SparkButton.vue +4 -4
- package/src/components/SparkButtonGroup.vue +2 -2
- package/src/components/SparkCard.vue +5 -3
- package/src/components/SparkEntityBadge.vue +3 -9
- package/src/components/SparkFileDragUpload.vue +13 -9
- package/src/components/SparkImageUpload.vue +4 -1
- package/src/components/SparkModalContainer.vue +23 -19
- package/src/components/SparkModalDialog.vue +36 -17
- package/src/components/SparkNotificationOutlet.vue +1 -1
- package/src/components/SparkOverlay.vue +20 -24
- package/src/components/SparkSubNav.vue +7 -14
- package/src/components/SparkTable.vue +72 -73
- package/src/components/SparkTablePaginationPaging.vue +2 -2
- package/src/components/SparkTableToolbar.vue +1 -1
- package/src/components/SparkToastContainer.vue +25 -41
- package/src/components/SparkTooltip.vue +14 -22
- package/src/components/plugins/SparkTableFilterButtons.vue +5 -1
- package/src/components/plugins/SparkTableFilterSelect.vue +1 -4
- package/src/components/plugins/SparkTableReset.vue +21 -19
- package/src/components/plugins/SparkTableSearch.vue +3 -2
- package/src/composables/index.js +1 -1
- package/src/composables/sparkModalService.js +64 -64
- package/src/composables/sparkNotificationService.js +10 -8
- package/src/composables/sparkOverlayService.js +36 -36
- package/src/composables/useCrudResource.js +1 -7
- package/src/composables/useFormSubmission.js +1 -3
- package/src/composables/useSparkOverlay.js +1 -1
- package/src/composables/useSparkTableRouteSync.js +4 -6
- package/src/composables/useSubNavigation.js +18 -15
- package/src/containers/SparkDefaultContainer.vue +8 -8
- package/src/containers/SparkPublicContainer.vue +1 -2
- package/src/directives/sparkTooltip.js +4 -11
- package/src/index.js +1 -1
- package/src/plugins/app-bootstrap.js +1 -1
- package/src/plugins/axios.js +1 -1
- package/src/plugins/fontawesome.js +3 -3
- package/src/plugins/index.js +17 -3
- package/src/plugins/router.js +8 -12
- package/src/stores/auth.js +1 -1
- package/src/stores/brand-filter.js +40 -40
- package/src/stores/index.js +1 -1
- package/src/stores/navigation.js +1 -1
- package/src/utils/formatTemporal.js +4 -4
- package/src/utils/sparkTable/renderers/badge.js +1 -1
- package/src/utils/sparkTable/renderers/boolean.js +3 -3
- package/src/utils/sparkTable/renderers/currency.js +1 -1
- package/src/utils/sparkTable/renderers/date.js +14 -6
- package/src/utils/sparkTable/renderers/datetime.js +1 -1
- package/src/utils/sparkTable/renderers/image.js +1 -1
- package/src/utils/sparkTable/renderers/link.js +1 -1
- package/src/views/SparkError403View.vue +3 -7
- package/src/views/SparkError404View.vue +3 -9
- package/src/views/SparkErrorGeneralView.vue +1 -3
- package/src/views/SparkForgotPasswordView.vue +7 -4
- package/src/views/SparkLoginView.vue +8 -7
- package/src/views/SparkLogoutView.vue +2 -1
- package/src/views/SparkResetPasswordView.vue +4 -6
|
@@ -2,74 +2,74 @@ import { reactive, markRaw } from 'vue'
|
|
|
2
2
|
import SparkModalDialog from '@/components/SparkModalDialog.vue'
|
|
3
3
|
|
|
4
4
|
class SparkModalService {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
constructor() {
|
|
6
|
+
this.state = reactive({
|
|
7
|
+
isVisible: false,
|
|
8
|
+
content: null,
|
|
9
|
+
props: {},
|
|
10
|
+
eventHandlers: {},
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
show = (component, props = {}, eventHandlers = {}) => {
|
|
15
|
+
this.state.content = markRaw(component)
|
|
16
|
+
this.state.props = props
|
|
17
|
+
this.state.eventHandlers = eventHandlers
|
|
18
|
+
this.state.isVisible = true
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
hide = () => {
|
|
22
|
+
this.state.isVisible = false
|
|
23
|
+
this.state.eventHandlers = {}
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Show a confirmation dialog and return a Promise
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} options - Confirmation options
|
|
30
|
+
* @param {string} [options.title='Confirm'] - Dialog title
|
|
31
|
+
* @param {string} [options.message='Are you sure?'] - Dialog message
|
|
32
|
+
* @param {string} [options.type='warning'] - Dialog type (info, success, warning, danger)
|
|
33
|
+
* @param {string} [options.confirmText='Confirm'] - Confirm button text
|
|
34
|
+
* @param {string} [options.cancelText='Cancel'] - Cancel button text
|
|
35
|
+
* @param {string} [options.confirmVariant='primary'] - Confirm button variant
|
|
36
|
+
* @returns {Promise<boolean>} - Resolves to true if confirmed, false if cancelled
|
|
37
|
+
*/
|
|
38
|
+
confirm = (options = {}) => {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
const {
|
|
41
|
+
title = 'Confirm',
|
|
42
|
+
message = 'Are you sure?',
|
|
43
|
+
type = 'warning',
|
|
44
|
+
confirmText = 'Confirm',
|
|
45
|
+
cancelText = 'Cancel',
|
|
46
|
+
confirmVariant = 'primary',
|
|
47
|
+
} = options
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
this.show(
|
|
50
|
+
SparkModalDialog,
|
|
51
|
+
{
|
|
52
|
+
title,
|
|
53
|
+
message,
|
|
54
|
+
type,
|
|
55
|
+
buttons: [
|
|
56
|
+
{ text: confirmText, variant: confirmVariant, event: 'confirm' },
|
|
57
|
+
{ text: cancelText, variant: 'secondary', event: 'cancel' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
confirm: () => {
|
|
62
|
+
this.hide()
|
|
63
|
+
resolve(true)
|
|
64
|
+
},
|
|
65
|
+
cancel: () => {
|
|
66
|
+
this.hide()
|
|
67
|
+
resolve(false)
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
export const sparkModalService = new SparkModalService()
|
|
@@ -286,7 +286,10 @@ class SparkNotificationService {
|
|
|
286
286
|
if (options.maxToasts !== undefined) {
|
|
287
287
|
this.toastState.maxToasts = options.maxToasts
|
|
288
288
|
}
|
|
289
|
-
if (
|
|
289
|
+
if (
|
|
290
|
+
options.defaultPosition !== undefined &&
|
|
291
|
+
TOAST_POSITIONS.includes(options.defaultPosition)
|
|
292
|
+
) {
|
|
290
293
|
this.toastState.defaultPosition = options.defaultPosition
|
|
291
294
|
}
|
|
292
295
|
if (options.newestOnTop !== undefined) {
|
|
@@ -321,9 +324,8 @@ class SparkNotificationService {
|
|
|
321
324
|
const id = ++this._toastIdCounter
|
|
322
325
|
|
|
323
326
|
// Determine effective values
|
|
324
|
-
const effectivePosition =
|
|
325
|
-
? position
|
|
326
|
-
: this.toastState.defaultPosition
|
|
327
|
+
const effectivePosition =
|
|
328
|
+
position && TOAST_POSITIONS.includes(position) ? position : this.toastState.defaultPosition
|
|
327
329
|
const effectiveDuration = duration !== null ? duration : DEFAULT_DURATIONS[type]
|
|
328
330
|
|
|
329
331
|
// Create toast object
|
|
@@ -340,7 +342,7 @@ class SparkNotificationService {
|
|
|
340
342
|
}
|
|
341
343
|
|
|
342
344
|
// Remove oldest toasts if at capacity (per position)
|
|
343
|
-
const positionToasts = this.toastState.toasts.filter(t => t.position === effectivePosition)
|
|
345
|
+
const positionToasts = this.toastState.toasts.filter((t) => t.position === effectivePosition)
|
|
344
346
|
if (positionToasts.length >= this.toastState.maxToasts) {
|
|
345
347
|
// Remove oldest: when newestOnTop, oldest is at end; otherwise at beginning
|
|
346
348
|
const oldest = this.toastState.newestOnTop
|
|
@@ -352,7 +354,7 @@ class SparkNotificationService {
|
|
|
352
354
|
// Add toast to array
|
|
353
355
|
if (this.toastState.newestOnTop) {
|
|
354
356
|
// Find insertion point: after all toasts of same position
|
|
355
|
-
const insertIndex = this.toastState.toasts.findIndex(t => t.position === effectivePosition)
|
|
357
|
+
const insertIndex = this.toastState.toasts.findIndex((t) => t.position === effectivePosition)
|
|
356
358
|
if (insertIndex === -1) {
|
|
357
359
|
this.toastState.toasts.push(toast)
|
|
358
360
|
} else {
|
|
@@ -379,7 +381,7 @@ class SparkNotificationService {
|
|
|
379
381
|
this._clearToastTimer(toastId)
|
|
380
382
|
|
|
381
383
|
// Remove from array
|
|
382
|
-
const index = this.toastState.toasts.findIndex(t => t.id === toastId)
|
|
384
|
+
const index = this.toastState.toasts.findIndex((t) => t.id === toastId)
|
|
383
385
|
if (index !== -1) {
|
|
384
386
|
this.toastState.toasts.splice(index, 1)
|
|
385
387
|
}
|
|
@@ -436,7 +438,7 @@ class SparkNotificationService {
|
|
|
436
438
|
* @returns {Array} Toasts at that position
|
|
437
439
|
*/
|
|
438
440
|
getToastsByPosition(position) {
|
|
439
|
-
return this.toastState.toasts.filter(t => t.position === position)
|
|
441
|
+
return this.toastState.toasts.filter((t) => t.position === position)
|
|
440
442
|
}
|
|
441
443
|
|
|
442
444
|
// ============================================
|
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
import { useSparkOverlay } from '@/composables/useSparkOverlay'
|
|
2
2
|
|
|
3
3
|
class SparkOverlayService {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
constructor() {
|
|
5
|
+
this.left = useSparkOverlay()
|
|
6
|
+
this.right = useSparkOverlay()
|
|
7
|
+
}
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
this.left.show(component, props, handlers, options)
|
|
9
|
+
showLeft = (component, props = {}, eventHandlers = {}, options = {}) => {
|
|
10
|
+
const handlers = {
|
|
11
|
+
close: () => {
|
|
12
|
+
// Call user's close handler if provided
|
|
13
|
+
eventHandlers.close?.()
|
|
14
|
+
// Then close the overlay
|
|
15
|
+
this.closeLeft()
|
|
16
|
+
},
|
|
17
|
+
...eventHandlers,
|
|
20
18
|
}
|
|
19
|
+
this.left.show(component, props, handlers, options)
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
this.right.show(component, props, handlers, options)
|
|
22
|
+
showRight = (component, props = {}, eventHandlers = {}, options = {}) => {
|
|
23
|
+
const handlers = {
|
|
24
|
+
close: () => {
|
|
25
|
+
// Call user's close handler if provided
|
|
26
|
+
eventHandlers.close?.()
|
|
27
|
+
// Then close the overlay
|
|
28
|
+
this.closeRight()
|
|
29
|
+
},
|
|
30
|
+
...eventHandlers,
|
|
33
31
|
}
|
|
32
|
+
this.right.show(component, props, handlers, options)
|
|
33
|
+
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
closeLeft = () => {
|
|
36
|
+
this.left.close()
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
closeRight = () => {
|
|
40
|
+
this.right.close()
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
closeAll = () => {
|
|
44
|
+
this.left.close()
|
|
45
|
+
this.right.close()
|
|
46
|
+
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
export const sparkOverlayService = new SparkOverlayService()
|
|
@@ -72,13 +72,7 @@ export function useCrudResource(endpoint, options = {}) {
|
|
|
72
72
|
* @returns {{ handleDelete }}
|
|
73
73
|
*/
|
|
74
74
|
export function useTableDelete(tableRef, options = {}) {
|
|
75
|
-
const {
|
|
76
|
-
endpoint,
|
|
77
|
-
successMessage,
|
|
78
|
-
errorMessage,
|
|
79
|
-
onSuccess,
|
|
80
|
-
onError,
|
|
81
|
-
} = options
|
|
75
|
+
const { endpoint, successMessage, errorMessage, onSuccess, onError } = options
|
|
82
76
|
|
|
83
77
|
async function handleDelete(row) {
|
|
84
78
|
try {
|
|
@@ -71,9 +71,7 @@ export function useFormSubmission(options = {}) {
|
|
|
71
71
|
|
|
72
72
|
// Redirect after create (if specified and not in edit mode)
|
|
73
73
|
if (!isEditMode && redirectTo) {
|
|
74
|
-
const location = typeof redirectTo === 'function'
|
|
75
|
-
? redirectTo(data)
|
|
76
|
-
: redirectTo
|
|
74
|
+
const location = typeof redirectTo === 'function' ? redirectTo(data) : redirectTo
|
|
77
75
|
await router.push(location)
|
|
78
76
|
}
|
|
79
77
|
|
|
@@ -73,14 +73,14 @@ export const useSparkTableRouteSync = (sparkTable, options = {}) => {
|
|
|
73
73
|
* Unflatten query params back to nested structure
|
|
74
74
|
* e.g., { 'filter[role]': 'admin' } => { filter: { role: 'admin' } }
|
|
75
75
|
*/
|
|
76
|
-
const
|
|
76
|
+
const _unflattenParams = (flatParams) => {
|
|
77
77
|
const unflattened = {}
|
|
78
78
|
|
|
79
79
|
Object.keys(flatParams).forEach((key) => {
|
|
80
80
|
const value = flatParams[key]
|
|
81
81
|
|
|
82
82
|
// Parse bracket notation: "filter[role]" => ["filter", "role"]
|
|
83
|
-
const matches = key.match(/([
|
|
83
|
+
const matches = key.match(/([^[]+)(?:\[([^\]]+)\])?/)
|
|
84
84
|
if (!matches) return
|
|
85
85
|
|
|
86
86
|
const [, rootKey, nestedKey] = matches
|
|
@@ -265,7 +265,7 @@ export const useSparkTableRouteSync = (sparkTable, options = {}) => {
|
|
|
265
265
|
|
|
266
266
|
// First, try to restore from URL
|
|
267
267
|
if (syncToRoute) {
|
|
268
|
-
let hasRelevantParams
|
|
268
|
+
let hasRelevantParams
|
|
269
269
|
|
|
270
270
|
if (useFlatUrls) {
|
|
271
271
|
// Flat mode: check if any query param looks like a table param
|
|
@@ -273,9 +273,7 @@ export const useSparkTableRouteSync = (sparkTable, options = {}) => {
|
|
|
273
273
|
} else {
|
|
274
274
|
// Namespaced mode: check for namespace prefix
|
|
275
275
|
const prefix = `${namespace}[`
|
|
276
|
-
hasRelevantParams = Object.keys(route.query).some((key) =>
|
|
277
|
-
key.startsWith(prefix)
|
|
278
|
-
)
|
|
276
|
+
hasRelevantParams = Object.keys(route.query).some((key) => key.startsWith(prefix))
|
|
279
277
|
}
|
|
280
278
|
|
|
281
279
|
if (hasRelevantParams) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, computed,
|
|
1
|
+
import { ref, computed, markRaw } from 'vue'
|
|
2
2
|
import { useRouter, useRoute } from 'vue-router'
|
|
3
3
|
import { sparkModalService } from './sparkModalService.js'
|
|
4
4
|
import { sparkOverlayService } from './sparkOverlayService.js'
|
|
@@ -79,14 +79,14 @@ export function useSubNavigation(options = {}) {
|
|
|
79
79
|
* Get visible items (not hidden)
|
|
80
80
|
*/
|
|
81
81
|
const visibleItems = computed(() => {
|
|
82
|
-
return items.value.filter(item => !evaluate(item.hidden))
|
|
82
|
+
return items.value.filter((item) => !evaluate(item.hidden))
|
|
83
83
|
})
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* Check if an item is disabled
|
|
87
87
|
*/
|
|
88
88
|
function isDisabled(item) {
|
|
89
|
-
const itemObj = typeof item === 'string' ? items.value.find(i => i.id === item) : item
|
|
89
|
+
const itemObj = typeof item === 'string' ? items.value.find((i) => i.id === item) : item
|
|
90
90
|
return itemObj ? evaluate(itemObj.disabled) : false
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -94,13 +94,11 @@ export function useSubNavigation(options = {}) {
|
|
|
94
94
|
* Check if an item is the currently active one (for route-based items)
|
|
95
95
|
*/
|
|
96
96
|
function isActive(item) {
|
|
97
|
-
const itemObj = typeof item === 'string' ? items.value.find(i => i.id === item) : item
|
|
97
|
+
const itemObj = typeof item === 'string' ? items.value.find((i) => i.id === item) : item
|
|
98
98
|
if (!itemObj || !itemObj.route) return false
|
|
99
99
|
|
|
100
100
|
// Handle route as string (route name) or object
|
|
101
|
-
const itemRoute = typeof itemObj.route === 'string'
|
|
102
|
-
? { name: itemObj.route }
|
|
103
|
-
: itemObj.route
|
|
101
|
+
const itemRoute = typeof itemObj.route === 'string' ? { name: itemObj.route } : itemObj.route
|
|
104
102
|
|
|
105
103
|
// Match by route name
|
|
106
104
|
if (itemRoute.name && route.name === itemRoute.name) {
|
|
@@ -121,12 +119,12 @@ export function useSubNavigation(options = {}) {
|
|
|
121
119
|
*/
|
|
122
120
|
const activeItem = computed(() => {
|
|
123
121
|
// Find item matching current route
|
|
124
|
-
const matchedItem = visibleItems.value.find(item => isActive(item))
|
|
122
|
+
const matchedItem = visibleItems.value.find((item) => isActive(item))
|
|
125
123
|
if (matchedItem) return matchedItem
|
|
126
124
|
|
|
127
125
|
// Fall back to default or first visible item
|
|
128
126
|
if (defaultId) {
|
|
129
|
-
return visibleItems.value.find(item => item.id === defaultId) || visibleItems.value[0]
|
|
127
|
+
return visibleItems.value.find((item) => item.id === defaultId) || visibleItems.value[0]
|
|
130
128
|
}
|
|
131
129
|
|
|
132
130
|
return visibleItems.value[0] || null
|
|
@@ -143,7 +141,7 @@ export function useSubNavigation(options = {}) {
|
|
|
143
141
|
* @returns {Promise<boolean>} - Whether navigation/action was executed
|
|
144
142
|
*/
|
|
145
143
|
async function navigateTo(item) {
|
|
146
|
-
const itemObj = typeof item === 'string' ? items.value.find(i => i.id === item) : item
|
|
144
|
+
const itemObj = typeof item === 'string' ? items.value.find((i) => i.id === item) : item
|
|
147
145
|
|
|
148
146
|
if (!itemObj) {
|
|
149
147
|
console.warn(`[useSubNavigation] Item not found: ${item}`)
|
|
@@ -156,16 +154,21 @@ export function useSubNavigation(options = {}) {
|
|
|
156
154
|
|
|
157
155
|
// Handle route navigation
|
|
158
156
|
if (itemObj.route) {
|
|
159
|
-
const routeConfig =
|
|
160
|
-
? { name: itemObj.route }
|
|
161
|
-
: itemObj.route
|
|
157
|
+
const routeConfig =
|
|
158
|
+
typeof itemObj.route === 'string' ? { name: itemObj.route } : itemObj.route
|
|
162
159
|
await router.push(routeConfig)
|
|
163
160
|
return true
|
|
164
161
|
}
|
|
165
162
|
|
|
166
163
|
// Handle overlay
|
|
167
164
|
if (itemObj.overlay) {
|
|
168
|
-
const {
|
|
165
|
+
const {
|
|
166
|
+
component,
|
|
167
|
+
props = {},
|
|
168
|
+
eventHandlers = {},
|
|
169
|
+
position = 'right',
|
|
170
|
+
size,
|
|
171
|
+
} = itemObj.overlay
|
|
169
172
|
const showMethod = position === 'left' ? 'showLeft' : 'showRight'
|
|
170
173
|
sparkOverlayService[showMethod](markRaw(component), props, eventHandlers, { size })
|
|
171
174
|
return true
|
|
@@ -205,7 +208,7 @@ export function useSubNavigation(options = {}) {
|
|
|
205
208
|
* @param {Object} updates - Properties to update
|
|
206
209
|
*/
|
|
207
210
|
function updateItem(id, updates) {
|
|
208
|
-
const index = items.value.findIndex(item => item.id === id)
|
|
211
|
+
const index = items.value.findIndex((item) => item.id === id)
|
|
209
212
|
if (index !== -1) {
|
|
210
213
|
items.value[index] = normalizeItem({ ...items.value[index], ...updates })
|
|
211
214
|
}
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
<font-awesome-icon :icon="Icons[appIcon]" class="size-5" />
|
|
14
14
|
</a>
|
|
15
15
|
<a
|
|
16
|
-
@click.prevent="mainNavStore.goto(appStore.state.homeRoute)"
|
|
17
16
|
v-if="!mainNavStore.state.collapsed"
|
|
18
17
|
class="font-medium text-gray-800 ml-[10px] cursor-pointer"
|
|
18
|
+
@click.prevent="mainNavStore.goto(appStore.state.homeRoute)"
|
|
19
19
|
>
|
|
20
20
|
{{ appStore.state.app }}
|
|
21
21
|
</a>
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
@click.prevent="mainNavStore.goto(item.href)"
|
|
38
38
|
>
|
|
39
39
|
<font-awesome-icon
|
|
40
|
+
v-if="item.icon"
|
|
40
41
|
:icon="Icons[item.icon]"
|
|
41
42
|
:class="[isCurrentRoute(item) ? 'text-gray-400' : 'text-gray-400']"
|
|
42
43
|
class="size-4"
|
|
43
|
-
v-if="item.icon"
|
|
44
44
|
/>
|
|
45
45
|
<span
|
|
46
46
|
v-if="!mainNavStore.state.collapsed"
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
{{ item.name }}
|
|
55
55
|
</span>
|
|
56
56
|
<div v-else-if="item?.children" class="w-full flex justify-center">
|
|
57
|
-
<div class="w-[10px] h-px bg-gray-400"
|
|
57
|
+
<div class="w-[10px] h-px bg-gray-400" />
|
|
58
58
|
</div>
|
|
59
59
|
</a>
|
|
60
60
|
<ul v-if="item.children" class="mt-[5px] flex flex-col gap-[5px]">
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
:class="[isCurrentRoute(child) ? 'text-gray-400' : 'text-gray-400']"
|
|
72
72
|
class="size-4"
|
|
73
73
|
/>
|
|
74
|
-
<span
|
|
74
|
+
<span v-if="!mainNavStore.state.collapsed" class="text-[13px]">
|
|
75
75
|
{{ child.name }}
|
|
76
76
|
</span>
|
|
77
77
|
</a>
|
|
@@ -151,18 +151,18 @@
|
|
|
151
151
|
</main>
|
|
152
152
|
</div>
|
|
153
153
|
|
|
154
|
-
<
|
|
154
|
+
<SparkOverlay
|
|
155
155
|
position="left"
|
|
156
156
|
:overlay-instance="sparkOverlayService.left"
|
|
157
157
|
@close="emit('overlayClose', 'left')"
|
|
158
158
|
/>
|
|
159
|
-
<
|
|
159
|
+
<SparkOverlay
|
|
160
160
|
position="right"
|
|
161
161
|
:overlay-instance="sparkOverlayService.right"
|
|
162
162
|
@close="emit('overlayClose', 'right')"
|
|
163
163
|
/>
|
|
164
164
|
|
|
165
|
-
<
|
|
165
|
+
<SparkModalContainer />
|
|
166
166
|
</template>
|
|
167
167
|
|
|
168
168
|
<script setup>
|
|
@@ -245,7 +245,7 @@ const toggleAppSelector = () => {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
sparkOverlayService.showRight(SparkAppSelector, slotProps, {
|
|
248
|
-
select: (
|
|
248
|
+
select: () => {
|
|
249
249
|
sparkOverlayService.closeRight()
|
|
250
250
|
},
|
|
251
251
|
})
|
|
@@ -51,11 +51,7 @@ function createTooltipElement(config) {
|
|
|
51
51
|
async function updatePosition(el, tooltip, config) {
|
|
52
52
|
const arrowEl = tooltip.querySelector(`.${ARROW_CLASS}`)
|
|
53
53
|
|
|
54
|
-
const middleware = [
|
|
55
|
-
offset(config.offset ?? 8),
|
|
56
|
-
flip(),
|
|
57
|
-
shift({ padding: 8 }),
|
|
58
|
-
]
|
|
54
|
+
const middleware = [offset(config.offset ?? 8), flip(), shift({ padding: 8 })]
|
|
59
55
|
|
|
60
56
|
if (arrowEl) {
|
|
61
57
|
middleware.push(arrow({ element: arrowEl, padding: 5 }))
|
|
@@ -94,9 +90,8 @@ function showTooltip(el) {
|
|
|
94
90
|
|
|
95
91
|
clearTimeout(state.hideTimeout)
|
|
96
92
|
|
|
97
|
-
const delay =
|
|
98
|
-
? state.config.delay
|
|
99
|
-
: state.config.delay?.show ?? 200
|
|
93
|
+
const delay =
|
|
94
|
+
typeof state.config.delay === 'number' ? state.config.delay : (state.config.delay?.show ?? 200)
|
|
100
95
|
|
|
101
96
|
state.showTimeout = setTimeout(() => {
|
|
102
97
|
if (state.tooltipEl) return // Already visible
|
|
@@ -118,9 +113,7 @@ function hideTooltip(el) {
|
|
|
118
113
|
|
|
119
114
|
clearTimeout(state.showTimeout)
|
|
120
115
|
|
|
121
|
-
const delay = typeof state.config.delay === 'number'
|
|
122
|
-
? 0
|
|
123
|
-
: state.config.delay?.hide ?? 0
|
|
116
|
+
const delay = typeof state.config.delay === 'number' ? 0 : (state.config.delay?.hide ?? 0)
|
|
124
117
|
|
|
125
118
|
state.hideTimeout = setTimeout(() => {
|
|
126
119
|
if (state.tooltipEl) {
|
package/src/index.js
CHANGED
package/src/plugins/axios.js
CHANGED
|
@@ -31,7 +31,7 @@ export function createAxiosInstance(config = {}) {
|
|
|
31
31
|
// Otherwise use normal token from cookie
|
|
32
32
|
requestConfig.headers.Authorization = `Bearer ${authStore.state.token}`
|
|
33
33
|
}
|
|
34
|
-
} catch
|
|
34
|
+
} catch {
|
|
35
35
|
// Auth store not initialized yet, skip adding token
|
|
36
36
|
// This can happen during app initialization
|
|
37
37
|
}
|
|
@@ -144,7 +144,7 @@ export const formKitIcons = Object.fromEntries(
|
|
|
144
144
|
Object.entries(Icons).map(([key, iconDef]) => {
|
|
145
145
|
const result = faIconToSvg(iconDef)
|
|
146
146
|
return [key, result?.html?.[0] || '']
|
|
147
|
-
})
|
|
147
|
+
}),
|
|
148
148
|
)
|
|
149
149
|
|
|
150
150
|
/**
|
|
@@ -180,7 +180,7 @@ export const formKitGenesisOverride = Object.fromEntries(
|
|
|
180
180
|
Object.entries(genesisIconMapping).map(([key, iconDef]) => {
|
|
181
181
|
const result = faIconToSvg(iconDef)
|
|
182
182
|
return [key, result?.html?.[0] || '']
|
|
183
|
-
})
|
|
183
|
+
}),
|
|
184
184
|
)
|
|
185
185
|
|
|
186
186
|
/**
|
|
@@ -208,4 +208,4 @@ export function setupFontAwesome(app) {
|
|
|
208
208
|
|
|
209
209
|
// Auto-register tooltip directive (used by SparkEntityBadge and available to all consumers)
|
|
210
210
|
setupTooltip(app)
|
|
211
|
-
}
|
|
211
|
+
}
|
package/src/plugins/index.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
1
|
+
export {
|
|
2
|
+
Icons,
|
|
3
|
+
addIcons,
|
|
4
|
+
setupFontAwesome,
|
|
5
|
+
formKitIcons,
|
|
6
|
+
formKitIconLoader,
|
|
7
|
+
formKitGenesisOverride,
|
|
8
|
+
} from './fontawesome.js'
|
|
9
|
+
export {
|
|
10
|
+
createAuthRoutes,
|
|
11
|
+
setupAuthGuards,
|
|
12
|
+
create403Route,
|
|
13
|
+
create404Route,
|
|
14
|
+
setupBootstrapGuard,
|
|
15
|
+
setupDirtyFormGuard,
|
|
16
|
+
} from './router.js'
|
|
3
17
|
export { createAxiosInstance, setupAxios, getAxiosInstance } from './axios.js'
|
|
4
18
|
export { createBootstrapService } from './app-bootstrap.js'
|
|
5
|
-
export { setupTooltip } from './tooltip.js'
|
|
19
|
+
export { setupTooltip } from './tooltip.js'
|