@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wishbone-media/spark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -38,14 +38,44 @@
|
|
|
38
38
|
"vue-router": "^4.6.3"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"@eslint/js": "^10.0.1",
|
|
41
42
|
"@vitejs/plugin-vue": "^6.0.2",
|
|
43
|
+
"@vue/eslint-config-prettier": "^10.2.0",
|
|
44
|
+
"eslint": "^10.1.0",
|
|
45
|
+
"eslint-config-prettier": "^10.1.8",
|
|
46
|
+
"eslint-plugin-oxlint": "^1.57.0",
|
|
47
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
48
|
+
"eslint-plugin-vue": "^10.8.0",
|
|
49
|
+
"globals": "^17.4.0",
|
|
50
|
+
"lint-staged": "^16.4.0",
|
|
51
|
+
"npm-run-all2": "^8.0.4",
|
|
52
|
+
"oxlint": "^1.57.0",
|
|
53
|
+
"prettier": "^3.8.1",
|
|
54
|
+
"simple-git-hooks": "^2.13.1",
|
|
42
55
|
"vite": "^7.2.2",
|
|
43
56
|
"vite-plugin-dts": "^4.5.4",
|
|
44
57
|
"vue": "^3.5.24"
|
|
45
58
|
},
|
|
46
59
|
"packageManager": "pnpm@10.11.1",
|
|
60
|
+
"simple-git-hooks": {
|
|
61
|
+
"pre-commit": "npx lint-staged"
|
|
62
|
+
},
|
|
63
|
+
"lint-staged": {
|
|
64
|
+
"*.{js,mjs,vue}": [
|
|
65
|
+
"eslint --fix",
|
|
66
|
+
"prettier --write"
|
|
67
|
+
],
|
|
68
|
+
"*.{css,json,md}": [
|
|
69
|
+
"prettier --write"
|
|
70
|
+
]
|
|
71
|
+
},
|
|
47
72
|
"scripts": {
|
|
48
73
|
"build": "vite build",
|
|
74
|
+
"prepare": "simple-git-hooks",
|
|
75
|
+
"lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
|
|
76
|
+
"lint:eslint": "eslint . --fix",
|
|
77
|
+
"lint": "run-s lint:* format",
|
|
78
|
+
"format": "prettier --write src/",
|
|
49
79
|
"release:patch": "npm version patch && npm publish && git push --follow-tags",
|
|
50
80
|
"release:minor": "npm version minor && npm publish && git push --follow-tags",
|
|
51
81
|
"release:major": "npm version major && npm publish && git push --follow-tags"
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
color: #fff;
|
|
15
15
|
background: #1f2937; /* gray-800 */
|
|
16
16
|
border-radius: 0.375rem;
|
|
17
|
-
box-shadow:
|
|
17
|
+
box-shadow:
|
|
18
|
+
0 4px 6px -1px rgb(0 0 0 / 0.1),
|
|
19
|
+
0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
18
20
|
pointer-events: none;
|
|
19
21
|
word-wrap: break-word;
|
|
20
22
|
white-space: pre-line;
|
|
@@ -30,11 +32,15 @@
|
|
|
30
32
|
|
|
31
33
|
/* Transitions (for SparkTooltip component) */
|
|
32
34
|
.spark-tooltip-enter-active {
|
|
33
|
-
transition:
|
|
35
|
+
transition:
|
|
36
|
+
opacity 150ms ease,
|
|
37
|
+
transform 150ms ease;
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
.spark-tooltip-leave-active {
|
|
37
|
-
transition:
|
|
41
|
+
transition:
|
|
42
|
+
opacity 100ms ease,
|
|
43
|
+
transform 100ms ease;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
.spark-tooltip-enter-from,
|
|
@@ -33,8 +33,19 @@
|
|
|
33
33
|
:disabled="disabled"
|
|
34
34
|
@click="manualExpanded = !manualExpanded"
|
|
35
35
|
>
|
|
36
|
-
<svg
|
|
37
|
-
|
|
36
|
+
<svg
|
|
37
|
+
class="h-3.5 w-3.5"
|
|
38
|
+
fill="none"
|
|
39
|
+
viewBox="0 0 24 24"
|
|
40
|
+
stroke="currentColor"
|
|
41
|
+
stroke-width="2"
|
|
42
|
+
>
|
|
43
|
+
<path
|
|
44
|
+
v-if="manualExpanded"
|
|
45
|
+
stroke-linecap="round"
|
|
46
|
+
stroke-linejoin="round"
|
|
47
|
+
d="M19 9l-7 7-7-7"
|
|
48
|
+
/>
|
|
38
49
|
<path v-else stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
|
|
39
50
|
</svg>
|
|
40
51
|
{{ manualExpanded ? 'Hide manual entry' : 'Manual entry' }}
|
|
@@ -46,7 +57,13 @@
|
|
|
46
57
|
:disabled="disabled"
|
|
47
58
|
@click="clearAddress"
|
|
48
59
|
>
|
|
49
|
-
<svg
|
|
60
|
+
<svg
|
|
61
|
+
class="h-3.5 w-3.5"
|
|
62
|
+
fill="none"
|
|
63
|
+
viewBox="0 0 24 24"
|
|
64
|
+
stroke="currentColor"
|
|
65
|
+
stroke-width="2"
|
|
66
|
+
>
|
|
50
67
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
51
68
|
</svg>
|
|
52
69
|
Clear
|
|
@@ -41,18 +41,18 @@
|
|
|
41
41
|
/>
|
|
42
42
|
</div>
|
|
43
43
|
</a>
|
|
44
|
-
<div
|
|
44
|
+
<div />
|
|
45
45
|
</div>
|
|
46
46
|
<div class="mt-auto">
|
|
47
47
|
<div v-if="$slots.bottom || bottomSlot" class="p-6">
|
|
48
48
|
<slot name="bottom">
|
|
49
|
-
<component
|
|
49
|
+
<component :is="bottomSlot" v-if="bottomSlot" />
|
|
50
50
|
</slot>
|
|
51
51
|
</div>
|
|
52
52
|
|
|
53
53
|
<div v-if="$slots.footer || footerSlot" class="bg-gray-50 p-6">
|
|
54
54
|
<slot name="footer">
|
|
55
|
-
<component
|
|
55
|
+
<component :is="footerSlot" v-if="footerSlot" />
|
|
56
56
|
</slot>
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
@@ -66,7 +66,7 @@ import { Icons } from '@/plugins/fontawesome'
|
|
|
66
66
|
import { useSparkAppSelectorStore } from '@/stores/app-selector'
|
|
67
67
|
import { useSparkAppStore } from '@/stores/app'
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
defineProps({
|
|
70
70
|
bottomSlot: {
|
|
71
71
|
type: [Object, Function],
|
|
72
72
|
default: null,
|
|
@@ -84,13 +84,13 @@ const appStore = useSparkAppStore()
|
|
|
84
84
|
|
|
85
85
|
const appsWithCurrent = computed(() => {
|
|
86
86
|
const currentAppName = appStore.state.app
|
|
87
|
-
return appSelectorStore.state.apps.map(app => ({
|
|
87
|
+
return appSelectorStore.state.apps.map((app) => ({
|
|
88
88
|
...app,
|
|
89
|
-
current: currentAppName && app.name.toLowerCase() === currentAppName.toLowerCase()
|
|
89
|
+
current: currentAppName && app.name.toLowerCase() === currentAppName.toLowerCase(),
|
|
90
90
|
}))
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
const handleAppClick = (app
|
|
93
|
+
const handleAppClick = (app) => {
|
|
94
94
|
emit('select', app)
|
|
95
95
|
}
|
|
96
96
|
</script>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
|
-
type="button"
|
|
4
3
|
ref="buttonRef"
|
|
4
|
+
type="button"
|
|
5
5
|
:class="computedButtonClass"
|
|
6
6
|
:disabled="disabled"
|
|
7
7
|
@click="$emit('click')"
|
|
8
8
|
>
|
|
9
|
-
<slot
|
|
9
|
+
<slot />
|
|
10
10
|
</button>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
@@ -72,11 +72,11 @@ const mergeClasses = (baseClasses, overrideClasses) => {
|
|
|
72
72
|
|
|
73
73
|
const filtered = base.filter((baseClass) => {
|
|
74
74
|
return !overrides.some((override) => {
|
|
75
|
-
const baseGroup = Object.entries(CONFLICT_GROUPS).find(([
|
|
75
|
+
const baseGroup = Object.entries(CONFLICT_GROUPS).find(([, regex]) =>
|
|
76
76
|
regex.test(baseClass),
|
|
77
77
|
)?.[0]
|
|
78
78
|
|
|
79
|
-
const overrideGroup = Object.entries(CONFLICT_GROUPS).find(([
|
|
79
|
+
const overrideGroup = Object.entries(CONFLICT_GROUPS).find(([, regex]) =>
|
|
80
80
|
regex.test(override),
|
|
81
81
|
)?.[0]
|
|
82
82
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="flex flex-col divide-y divide-gray-300 rounded-lg border border-gray-300 text-gray-700 bg-gray-100"
|
|
4
|
+
>
|
|
3
5
|
<div v-if="$slots.header" class="px-[30px] py-5">
|
|
4
6
|
<slot name="header" />
|
|
5
7
|
</div>
|
|
6
8
|
|
|
7
|
-
<div :class="[props.padded ? props.paddedClass : '']">
|
|
8
|
-
<slot
|
|
9
|
+
<div :class="[props.padded ? props.paddedClass : '', 'min-h-0 flex-1']">
|
|
10
|
+
<slot />
|
|
9
11
|
</div>
|
|
10
12
|
|
|
11
13
|
<div v-if="$slots.footer" class="p-5">
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component
|
|
3
3
|
:is="isLink ? 'a' : 'span'"
|
|
4
|
+
v-spark-tooltip="tooltip"
|
|
4
5
|
:href="resolvedHref || undefined"
|
|
5
6
|
:target="isLink && openNew ? '_blank' : undefined"
|
|
6
7
|
:rel="isLink && openNew ? 'noopener noreferrer' : undefined"
|
|
7
|
-
v-spark-tooltip="tooltip"
|
|
8
8
|
class="inline-flex items-center gap-1 rounded-full font-medium whitespace-nowrap"
|
|
9
9
|
:class="[variantClasses, sizeClasses, interactiveClasses]"
|
|
10
10
|
@click="handleClick"
|
|
11
11
|
>
|
|
12
12
|
<font-awesome-icon v-if="icon" :icon="icon" />
|
|
13
13
|
<slot>{{ label }}</slot>
|
|
14
|
-
<font-awesome-icon
|
|
15
|
-
v-if="copyToClipboard"
|
|
16
|
-
:icon="Icons.farCopy"
|
|
17
|
-
class="opacity-60"
|
|
18
|
-
/>
|
|
14
|
+
<font-awesome-icon v-if="copyToClipboard" :icon="Icons.farCopy" class="opacity-60" />
|
|
19
15
|
<font-awesome-icon
|
|
20
16
|
v-else-if="isNavigable && openNew"
|
|
21
17
|
:icon="Icons.farArrowUpRightFromSquare"
|
|
@@ -118,9 +114,7 @@ const sizeClasses = computed(() => SIZE_CLASSES[props.size] || SIZE_CLASSES.md)
|
|
|
118
114
|
|
|
119
115
|
// --- Navigation ---
|
|
120
116
|
|
|
121
|
-
const isNavigable = computed(
|
|
122
|
-
() => (props.routeName && props.entityId != null) || props.href,
|
|
123
|
-
)
|
|
117
|
+
const isNavigable = computed(() => (props.routeName && props.entityId != null) || props.href)
|
|
124
118
|
const isInteractive = computed(() => isNavigable.value || props.copyToClipboard)
|
|
125
119
|
const isLink = computed(() => isNavigable.value && !props.disabled)
|
|
126
120
|
|
|
@@ -70,16 +70,14 @@
|
|
|
70
70
|
<!-- Upload button -->
|
|
71
71
|
<div v-if="showUploadButton" class="flex justify-end mt-4">
|
|
72
72
|
<SparkButton size="lg" :disabled="!selectedFile || uploading" @click="upload">
|
|
73
|
-
<font-awesome-icon
|
|
74
|
-
v-if="uploading"
|
|
75
|
-
:icon="Icons.farSpinner"
|
|
76
|
-
class="mr-2 animate-spin"
|
|
77
|
-
/>
|
|
73
|
+
<font-awesome-icon v-if="uploading" :icon="Icons.farSpinner" class="mr-2 animate-spin" />
|
|
78
74
|
{{ uploading ? uploadingText : uploadText }}
|
|
79
75
|
</SparkButton>
|
|
80
76
|
</div>
|
|
81
77
|
|
|
82
|
-
<p v-if="uploading && !showUploadButton" class="text-sm text-gray-500 mt-1">
|
|
78
|
+
<p v-if="uploading && !showUploadButton" class="text-sm text-gray-500 mt-1">
|
|
79
|
+
{{ uploadingText }}
|
|
80
|
+
</p>
|
|
83
81
|
</div>
|
|
84
82
|
</template>
|
|
85
83
|
|
|
@@ -157,7 +155,13 @@ const props = defineProps({
|
|
|
157
155
|
},
|
|
158
156
|
})
|
|
159
157
|
|
|
160
|
-
const emit = defineEmits([
|
|
158
|
+
const emit = defineEmits([
|
|
159
|
+
'upload-start',
|
|
160
|
+
'upload-success',
|
|
161
|
+
'upload-error',
|
|
162
|
+
'file-selected',
|
|
163
|
+
'file-cleared',
|
|
164
|
+
])
|
|
161
165
|
|
|
162
166
|
const axios = inject('axios')
|
|
163
167
|
const selectedFile = ref(null)
|
|
@@ -222,8 +226,8 @@ function handleFormKitInput(files) {
|
|
|
222
226
|
function triggerFileDialog() {
|
|
223
227
|
const el = formkitFileRef.value?.$el
|
|
224
228
|
if (!el) return
|
|
225
|
-
const inputEl =
|
|
226
|
-
|| el.parentElement?.querySelector('input[type="file"]')
|
|
229
|
+
const inputEl =
|
|
230
|
+
el.querySelector('input[type="file"]') || el.parentElement?.querySelector('input[type="file"]')
|
|
227
231
|
if (inputEl) {
|
|
228
232
|
inputEl.click()
|
|
229
233
|
}
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
<img
|
|
7
7
|
:src="modelValue"
|
|
8
8
|
:alt="label || 'Image preview'"
|
|
9
|
-
:class="[
|
|
9
|
+
:class="[
|
|
10
|
+
height,
|
|
11
|
+
'w-auto object-contain border border-gray-300 rounded-md cursor-pointer hover:opacity-80 transition-opacity',
|
|
12
|
+
]"
|
|
10
13
|
/>
|
|
11
14
|
</a>
|
|
12
15
|
<button
|
|
@@ -2,34 +2,38 @@
|
|
|
2
2
|
<TransitionRoot as="template" :show="sparkModalService.state.isVisible">
|
|
3
3
|
<Dialog class="relative z-1000" @close="sparkModalService.hide">
|
|
4
4
|
<TransitionChild
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
as="template"
|
|
6
|
+
enter="ease-out duration-300"
|
|
7
|
+
enter-from="opacity-0"
|
|
8
|
+
enter-to="opacity-100"
|
|
9
|
+
leave="ease-in duration-200"
|
|
10
|
+
leave-from="opacity-100"
|
|
11
|
+
leave-to="opacity-0"
|
|
12
12
|
>
|
|
13
13
|
<div class="fixed inset-0 bg-gray-500/75 transition-opacity" />
|
|
14
14
|
</TransitionChild>
|
|
15
15
|
|
|
16
16
|
<div class="fixed inset-0 z-10 w-screen overflow-y-auto">
|
|
17
|
-
<div
|
|
17
|
+
<div
|
|
18
|
+
class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"
|
|
19
|
+
>
|
|
18
20
|
<TransitionChild
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
as="template"
|
|
22
|
+
enter="ease-out duration-300"
|
|
23
|
+
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
24
|
+
enter-to="opacity-100 translate-y-0 sm:scale-100"
|
|
25
|
+
leave="ease-in duration-200"
|
|
26
|
+
leave-from="opacity-100 translate-y-0 sm:scale-100"
|
|
27
|
+
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
26
28
|
>
|
|
27
|
-
<DialogPanel
|
|
29
|
+
<DialogPanel
|
|
30
|
+
class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:min-w-lg sm:max-w-max"
|
|
31
|
+
>
|
|
28
32
|
<!-- Render dynamic component -->
|
|
29
33
|
<component
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
:is="sparkModalService.state.content"
|
|
35
|
+
v-bind="sparkModalService.state.props"
|
|
36
|
+
v-on="sparkModalService.state.eventHandlers"
|
|
33
37
|
/>
|
|
34
38
|
</DialogPanel>
|
|
35
39
|
</TransitionChild>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="px-4 pt-5 pb-4 sm:p-6">
|
|
3
3
|
<!-- Icon -->
|
|
4
|
-
<div
|
|
4
|
+
<div
|
|
5
|
+
v-if="iconToUse"
|
|
6
|
+
class="mx-auto flex size-12 items-center justify-center rounded-full"
|
|
7
|
+
:class="iconBgClass"
|
|
8
|
+
>
|
|
5
9
|
<font-awesome-icon :icon="Icons[iconToUse]" class="h-5 w-5" :class="iconTextClass" />
|
|
6
10
|
</div>
|
|
7
11
|
|
|
@@ -20,14 +24,14 @@
|
|
|
20
24
|
|
|
21
25
|
<!-- Actions -->
|
|
22
26
|
<div class="mt-5 sm:mt-6" :class="buttonContainerClass">
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
<SparkButton
|
|
28
|
+
v-for="(button, index) in buttonsToShow"
|
|
29
|
+
:key="index"
|
|
30
|
+
:variant="button.variant"
|
|
31
|
+
@click="$emit(button.event, button)"
|
|
28
32
|
>
|
|
29
33
|
{{ button.text }}
|
|
30
|
-
</
|
|
34
|
+
</SparkButton>
|
|
31
35
|
</div>
|
|
32
36
|
</div>
|
|
33
37
|
</template>
|
|
@@ -35,7 +39,7 @@
|
|
|
35
39
|
<script setup>
|
|
36
40
|
import { computed } from 'vue'
|
|
37
41
|
import { Icons } from '@/plugins/fontawesome'
|
|
38
|
-
import { SparkButton } from
|
|
42
|
+
import { SparkButton } from './index.js'
|
|
39
43
|
|
|
40
44
|
const props = defineProps({
|
|
41
45
|
title: {
|
|
@@ -57,16 +61,31 @@ const props = defineProps({
|
|
|
57
61
|
},
|
|
58
62
|
buttons: {
|
|
59
63
|
type: Array,
|
|
60
|
-
default: () => [
|
|
61
|
-
{ text: 'OK', variant: 'primary', event: 'ok' }
|
|
62
|
-
],
|
|
64
|
+
default: () => [{ text: 'OK', variant: 'primary', event: 'ok' }],
|
|
63
65
|
},
|
|
64
66
|
})
|
|
65
67
|
|
|
66
68
|
defineEmits([
|
|
67
|
-
'ok',
|
|
68
|
-
'
|
|
69
|
-
'
|
|
69
|
+
'ok',
|
|
70
|
+
'confirm',
|
|
71
|
+
'cancel',
|
|
72
|
+
'close',
|
|
73
|
+
'save',
|
|
74
|
+
'discard',
|
|
75
|
+
'delete',
|
|
76
|
+
'approve',
|
|
77
|
+
'reject',
|
|
78
|
+
'submit',
|
|
79
|
+
'reset',
|
|
80
|
+
'continue',
|
|
81
|
+
'retry',
|
|
82
|
+
'edit',
|
|
83
|
+
'view',
|
|
84
|
+
'download',
|
|
85
|
+
'upload',
|
|
86
|
+
'share',
|
|
87
|
+
'copy',
|
|
88
|
+
'input',
|
|
70
89
|
])
|
|
71
90
|
|
|
72
91
|
const buttonsToShow = computed(() => {
|
|
@@ -82,11 +101,11 @@ const buttonContainerClass = computed(() => {
|
|
|
82
101
|
case 1:
|
|
83
102
|
return 'sm:grid sm:grid-flow-row-dense'
|
|
84
103
|
case 2:
|
|
85
|
-
return 'sm:grid sm:grid-cols-2 sm:gap-3'
|
|
104
|
+
return 'sm:grid sm:grid-cols-2 sm:gap-3'
|
|
86
105
|
case 3:
|
|
87
|
-
return 'sm:grid sm:grid-cols-3 sm:gap-3'
|
|
106
|
+
return 'sm:grid sm:grid-cols-3 sm:gap-3'
|
|
88
107
|
default:
|
|
89
|
-
return 'flex flex-col gap-3'
|
|
108
|
+
return 'flex flex-col gap-3'
|
|
90
109
|
}
|
|
91
110
|
})
|
|
92
111
|
|
|
@@ -1,39 +1,35 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<TransitionRoot :show="overlayInstance.state.isVisible" as="template">
|
|
3
|
-
<Dialog
|
|
4
|
-
:initialFocus="panelRef"
|
|
5
|
-
class="relative z-1000"
|
|
6
|
-
@close="handleClose"
|
|
7
|
-
>
|
|
3
|
+
<Dialog :initial-focus="panelRef" class="relative z-1000" @close="handleClose">
|
|
8
4
|
<TransitionChild
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
as="template"
|
|
6
|
+
enter="transition-opacity ease-linear duration-150"
|
|
7
|
+
enter-from="opacity-0"
|
|
8
|
+
enter-to="opacity-100"
|
|
9
|
+
leave="transition-opacity ease-linear duration-150"
|
|
10
|
+
leave-from="opacity-100"
|
|
11
|
+
leave-to="opacity-0"
|
|
16
12
|
>
|
|
17
13
|
<div class="fixed inset-0 bg-gray-600/30" />
|
|
18
14
|
</TransitionChild>
|
|
19
15
|
|
|
20
16
|
<div class="fixed inset-0 flex">
|
|
21
17
|
<TransitionChild
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
as="template"
|
|
19
|
+
enter="transition ease-in-out duration-150 transform"
|
|
20
|
+
:enter-from="
|
|
25
21
|
position === 'left' ? '-translate-x-full opacity-0' : 'translate-x-full opacity-0'
|
|
26
22
|
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
enter-to="translate-x-0 opacity-100"
|
|
24
|
+
leave="transition ease-in-out duration-150 transform"
|
|
25
|
+
leave-from="translate-x-0 opacity-100"
|
|
26
|
+
:leave-to="
|
|
31
27
|
position === 'left' ? '-translate-x-full opacity-0' : 'translate-x-full opacity-0'
|
|
32
28
|
"
|
|
33
29
|
>
|
|
34
30
|
<DialogPanel
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
ref="panelRef"
|
|
32
|
+
:class="[
|
|
37
33
|
'flex py-2.5',
|
|
38
34
|
widthClass,
|
|
39
35
|
position === 'left' ? 'relative left-[10px]' : 'absolute right-[10px] h-full',
|
|
@@ -41,9 +37,9 @@
|
|
|
41
37
|
>
|
|
42
38
|
<!-- Bind props and event handlers dynamically -->
|
|
43
39
|
<component
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
:is="overlayInstance.state.content"
|
|
41
|
+
v-bind="overlayInstance.state.props"
|
|
42
|
+
v-on="overlayInstance.state.eventHandlers"
|
|
47
43
|
/>
|
|
48
44
|
</DialogPanel>
|
|
49
45
|
</TransitionChild>
|
|
@@ -20,16 +20,9 @@
|
|
|
20
20
|
:disabled="isItemDisabled(item)"
|
|
21
21
|
@click="handleNavigate(item)"
|
|
22
22
|
>
|
|
23
|
-
<FontAwesomeIcon
|
|
24
|
-
v-if="item.icon"
|
|
25
|
-
:icon="Icons[item.icon]"
|
|
26
|
-
class="mr-1.5 size-4"
|
|
27
|
-
/>
|
|
23
|
+
<FontAwesomeIcon v-if="item.icon" :icon="Icons[item.icon]" class="mr-1.5 size-4" />
|
|
28
24
|
{{ item.label }}
|
|
29
|
-
<span
|
|
30
|
-
v-if="item.badge != null"
|
|
31
|
-
:class="getBadgeClasses(item)"
|
|
32
|
-
>
|
|
25
|
+
<span v-if="item.badge != null" :class="getBadgeClasses(item)">
|
|
33
26
|
{{ item.badge }}
|
|
34
27
|
</span>
|
|
35
28
|
</SparkButton>
|
|
@@ -58,10 +51,7 @@
|
|
|
58
51
|
:class="iconClasses"
|
|
59
52
|
/>
|
|
60
53
|
<span>{{ item.label }}</span>
|
|
61
|
-
<span
|
|
62
|
-
v-if="item.badge != null"
|
|
63
|
-
:class="getBadgeClasses(item)"
|
|
64
|
-
>
|
|
54
|
+
<span v-if="item.badge != null" :class="getBadgeClasses(item)">
|
|
65
55
|
{{ item.badge }}
|
|
66
56
|
</span>
|
|
67
57
|
</button>
|
|
@@ -261,6 +251,9 @@ function getBadgeClasses(item) {
|
|
|
261
251
|
danger: 'bg-red-100 text-red-700',
|
|
262
252
|
}
|
|
263
253
|
|
|
264
|
-
return [
|
|
254
|
+
return [
|
|
255
|
+
'ml-2 px-2 py-0.5 text-xs font-medium rounded-full',
|
|
256
|
+
variants[variant] || variants.primary,
|
|
257
|
+
]
|
|
265
258
|
}
|
|
266
259
|
</script>
|