@fy-/fws-vue 2.1.6 → 2.1.7
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/components/fws/CmsArticleBoxed.vue +23 -20
- package/components/fws/CmsArticleSingle.vue +74 -68
- package/components/fws/DataTable.vue +132 -125
- package/components/fws/FilterData.vue +99 -101
- package/components/fws/UserData.vue +33 -32
- package/components/fws/UserFlow.vue +163 -155
- package/components/fws/UserOAuth2.vue +73 -72
- package/components/fws/UserProfile.vue +98 -101
- package/components/fws/UserProfileStrict.vue +65 -64
- package/components/ssr/ClientOnly.ts +7 -7
- package/components/ui/DefaultBreadcrumb.vue +13 -13
- package/components/ui/DefaultConfirm.vue +35 -34
- package/components/ui/DefaultDateSelection.vue +19 -17
- package/components/ui/DefaultDropdown.vue +25 -25
- package/components/ui/DefaultDropdownLink.vue +15 -14
- package/components/ui/DefaultGallery.vue +179 -168
- package/components/ui/DefaultInput.vue +121 -126
- package/components/ui/DefaultLoader.vue +17 -17
- package/components/ui/DefaultModal.vue +35 -33
- package/components/ui/DefaultNotif.vue +50 -52
- package/components/ui/DefaultPaging.vue +92 -95
- package/components/ui/DefaultSidebar.vue +29 -25
- package/components/ui/DefaultTagInput.vue +121 -119
- package/components/ui/transitions/CollapseTransition.vue +1 -1
- package/components/ui/transitions/ExpandTransition.vue +1 -1
- package/components/ui/transitions/FadeTransition.vue +1 -1
- package/components/ui/transitions/ScaleTransition.vue +1 -1
- package/components/ui/transitions/SlideTransition.vue +3 -3
- package/composables/event-bus.ts +10 -8
- package/composables/rest.ts +59 -56
- package/composables/seo.ts +106 -95
- package/composables/ssr.ts +64 -62
- package/composables/templating.ts +57 -57
- package/composables/translations.ts +13 -13
- package/env.d.ts +6 -4
- package/index.ts +101 -98
- package/package.json +7 -7
- package/stores/serverRouter.ts +25 -25
- package/stores/user.ts +79 -72
- package/types.d.ts +65 -65
|
@@ -1,50 +1,47 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { Component } from 'vue'
|
|
3
|
+
|
|
2
4
|
import {
|
|
3
|
-
|
|
4
|
-
DialogPanel,
|
|
5
|
-
DialogTitle,
|
|
6
|
-
TransitionRoot,
|
|
7
|
-
} from "@headlessui/vue";
|
|
8
|
-
import { ref, onMounted, onUnmounted } from "vue";
|
|
9
|
-
import {
|
|
5
|
+
CheckCircleIcon,
|
|
10
6
|
ExclamationTriangleIcon,
|
|
11
7
|
LightBulbIcon,
|
|
12
|
-
|
|
13
|
-
} from
|
|
14
|
-
import { useEventBus } from
|
|
15
|
-
import
|
|
16
|
-
|
|
8
|
+
} from '@heroicons/vue/24/solid'
|
|
9
|
+
import { onMounted, onUnmounted, ref } from 'vue'
|
|
10
|
+
import { useEventBus } from '../../composables/event-bus'
|
|
11
|
+
import ScaleTransition from './transitions/ScaleTransition.vue'
|
|
12
|
+
|
|
17
13
|
interface NotifProps {
|
|
18
|
-
imgSrc?: string
|
|
19
|
-
imgIcon?: Component
|
|
20
|
-
title: string
|
|
21
|
-
content?: string
|
|
22
|
-
ctaText?: string
|
|
23
|
-
ctaLink?: string
|
|
24
|
-
ctaAction?: () => void
|
|
25
|
-
type?:
|
|
26
|
-
time?: number
|
|
14
|
+
imgSrc?: string
|
|
15
|
+
imgIcon?: Component
|
|
16
|
+
title: string
|
|
17
|
+
content?: string
|
|
18
|
+
ctaText?: string
|
|
19
|
+
ctaLink?: string
|
|
20
|
+
ctaAction?: () => void
|
|
21
|
+
type?: 'info' | 'warning' | 'success'
|
|
22
|
+
time?: number
|
|
27
23
|
}
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const onCall = (data: NotifProps) => {
|
|
24
|
+
const eventBus = useEventBus()
|
|
25
|
+
const currentNotif = ref<NotifProps | null>(null)
|
|
26
|
+
let currentTimeout: any | null = null
|
|
27
|
+
function onCall(data: NotifProps) {
|
|
33
28
|
if (currentNotif.value !== null) {
|
|
34
|
-
hideNotif()
|
|
29
|
+
hideNotif()
|
|
35
30
|
}
|
|
36
|
-
const actualIcon = ref(data.imgIcon)
|
|
31
|
+
const actualIcon = ref(data.imgIcon)
|
|
37
32
|
if (data.imgIcon === undefined) {
|
|
38
|
-
if (data.type ===
|
|
39
|
-
actualIcon.value = LightBulbIcon
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
if (!data.time || data.time < 1000) {
|
|
47
|
-
data.time = 5000
|
|
44
|
+
data.time = 5000
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
currentNotif.value = {
|
|
@@ -57,27 +54,29 @@ const onCall = (data: NotifProps) => {
|
|
|
57
54
|
time: data.time,
|
|
58
55
|
type: data.type,
|
|
59
56
|
ctaAction: data.ctaAction,
|
|
60
|
-
}
|
|
57
|
+
}
|
|
61
58
|
|
|
62
|
-
currentTimeout = setTimeout(hideNotif, currentNotif.value.time)
|
|
63
|
-
}
|
|
59
|
+
currentTimeout = setTimeout(hideNotif, currentNotif.value.time)
|
|
60
|
+
}
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
currentNotif.value = null
|
|
62
|
+
function hideNotif() {
|
|
63
|
+
currentNotif.value = null
|
|
67
64
|
if (currentTimeout !== null) {
|
|
68
|
-
clearTimeout(currentTimeout)
|
|
65
|
+
clearTimeout(currentTimeout)
|
|
69
66
|
}
|
|
70
|
-
}
|
|
67
|
+
}
|
|
71
68
|
onMounted(() => {
|
|
72
|
-
eventBus.on(
|
|
73
|
-
})
|
|
69
|
+
eventBus.on('SendNotif', onCall)
|
|
70
|
+
})
|
|
74
71
|
onUnmounted(() => {
|
|
75
|
-
eventBus.off(
|
|
76
|
-
})
|
|
72
|
+
eventBus.off('SendNotif', onCall)
|
|
73
|
+
})
|
|
77
74
|
</script>
|
|
75
|
+
|
|
78
76
|
<template>
|
|
79
77
|
<ScaleTransition>
|
|
80
78
|
<div
|
|
79
|
+
v-if="currentNotif !== null"
|
|
81
80
|
id="base-notif"
|
|
82
81
|
class="p-2 mb-4 fixed bottom-4 right-8 !z-[2000] bg-fv-neutral-50/[.6] dark:bg-neutral-800/[.6]"
|
|
83
82
|
role="alert"
|
|
@@ -89,33 +88,32 @@ onUnmounted(() => {
|
|
|
89
88
|
'text-green-800 border border-green-300 rounded-lg dark:text-green-300 dark:border-green-800':
|
|
90
89
|
currentNotif.type === 'success',
|
|
91
90
|
}"
|
|
92
|
-
v-if="currentNotif !== null"
|
|
93
91
|
>
|
|
94
92
|
<div class="flex items-center gap-2">
|
|
95
93
|
<img
|
|
94
|
+
v-if="currentNotif.imgSrc"
|
|
96
95
|
class="flex-shrink-0 w-6 h-6"
|
|
97
96
|
:src="currentNotif.imgSrc"
|
|
98
97
|
:alt="currentNotif.title"
|
|
99
|
-
|
|
100
|
-
/>
|
|
98
|
+
>
|
|
101
99
|
<component
|
|
102
100
|
:is="currentNotif.imgIcon"
|
|
103
|
-
class="flex-shrink-0 w-6 h-6"
|
|
104
101
|
v-else
|
|
102
|
+
class="flex-shrink-0 w-6 h-6"
|
|
105
103
|
/>
|
|
106
104
|
<h3 class="text-lg font-medium" v-text="currentNotif.title" />
|
|
107
105
|
</div>
|
|
108
106
|
<div
|
|
107
|
+
v-if="currentNotif.content"
|
|
109
108
|
class="mt-2text-sm"
|
|
110
109
|
v-text="currentNotif.content"
|
|
111
|
-
v-if="currentNotif.content"
|
|
112
110
|
/>
|
|
113
111
|
<div class="flex justify-end gap-2 pt-3">
|
|
114
112
|
<button
|
|
115
113
|
type="button"
|
|
116
114
|
class="btn neutral small"
|
|
117
|
-
@click="hideNotif"
|
|
118
115
|
aria-label="Close"
|
|
116
|
+
@click="hideNotif"
|
|
119
117
|
>
|
|
120
118
|
{{ $t("dismiss_cta") }}
|
|
121
119
|
</button>
|
|
@@ -1,145 +1,142 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
WatchStopHandle,
|
|
4
|
+
} from 'vue'
|
|
5
|
+
import type { RouteLocationRaw } from 'vue-router'
|
|
6
|
+
import type { APIPaging } from '../../composables/rest'
|
|
7
|
+
import { getURL, hasFW } from '@fy-/fws-js'
|
|
8
|
+
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/vue/24/solid'
|
|
9
|
+
import { useHead } from '@unhead/vue'
|
|
4
10
|
import {
|
|
5
|
-
|
|
11
|
+
computed,
|
|
12
|
+
onMounted,
|
|
6
13
|
onUnmounted,
|
|
7
14
|
ref,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from
|
|
12
|
-
import
|
|
13
|
-
import { useEventBus } from "../../composables/event-bus";
|
|
14
|
-
import { useServerRouter } from "../../stores/serverRouter";
|
|
15
|
-
import { LocationQueryValue, RouteLocationRaw, useRoute } from "vue-router";
|
|
16
|
-
import { useHead } from "@unhead/vue";
|
|
17
|
-
import { hasFW, getURL } from "@fy-/fws-js";
|
|
15
|
+
watch,
|
|
16
|
+
} from 'vue'
|
|
17
|
+
import { useRoute } from 'vue-router'
|
|
18
|
+
import { useEventBus } from '../../composables/event-bus'
|
|
19
|
+
import { useServerRouter } from '../../stores/serverRouter'
|
|
18
20
|
|
|
19
21
|
const props = withDefaults(
|
|
20
22
|
defineProps<{
|
|
21
|
-
items: APIPaging
|
|
22
|
-
id: string
|
|
23
|
-
hash?: string
|
|
24
|
-
showLegend?: boolean
|
|
23
|
+
items: APIPaging
|
|
24
|
+
id: string
|
|
25
|
+
hash?: string
|
|
26
|
+
showLegend?: boolean
|
|
25
27
|
}>(),
|
|
26
28
|
{
|
|
27
29
|
showLegend: true,
|
|
28
|
-
hash:
|
|
30
|
+
hash: '',
|
|
29
31
|
},
|
|
30
|
-
)
|
|
31
|
-
const route = useRoute()
|
|
32
|
-
const eventBus = useEventBus()
|
|
33
|
-
const history = useServerRouter()
|
|
34
|
-
const prevNextSeo = ref<any>({})
|
|
35
|
-
|
|
32
|
+
)
|
|
33
|
+
const route = useRoute()
|
|
34
|
+
const eventBus = useEventBus()
|
|
35
|
+
const history = useServerRouter()
|
|
36
|
+
const prevNextSeo = ref<any>({})
|
|
37
|
+
function isNewPage(page: number) {
|
|
36
38
|
return (
|
|
37
|
-
page >= 1 && page <= props.items.page_max && page
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
const pageWatcher = ref<WatchStopHandle>()
|
|
39
|
+
page >= 1 && page <= props.items.page_max && page !== props.items.page_no
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
const pageWatcher = ref<WatchStopHandle>()
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
const page = props.items.page_no + 1
|
|
44
|
+
function next() {
|
|
45
|
+
const page = props.items.page_no + 1
|
|
44
46
|
|
|
45
|
-
if (!isNewPage(page)) return
|
|
46
|
-
const newQuery = { ...route.query }
|
|
47
|
-
newQuery.page = page.toString()
|
|
47
|
+
if (!isNewPage(page)) return
|
|
48
|
+
const newQuery = { ...route.query }
|
|
49
|
+
newQuery.page = page.toString()
|
|
48
50
|
history.push({
|
|
49
51
|
path: history.currentRoute.path,
|
|
50
52
|
query: newQuery,
|
|
51
|
-
hash: props.hash
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const page = props.items.page_no - 1
|
|
56
|
-
if (!isNewPage(page)) return
|
|
57
|
-
const newQuery = { ...route.query }
|
|
58
|
-
newQuery.page = page.toString()
|
|
53
|
+
hash: props.hash !== '' ? `#${props.hash}` : undefined,
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
function prev() {
|
|
57
|
+
const page = props.items.page_no - 1
|
|
58
|
+
if (!isNewPage(page)) return
|
|
59
|
+
const newQuery = { ...route.query }
|
|
60
|
+
newQuery.page = page.toString()
|
|
59
61
|
history.push({
|
|
60
62
|
path: history.currentRoute.path,
|
|
61
63
|
query: newQuery,
|
|
62
|
-
hash: props.hash
|
|
63
|
-
})
|
|
64
|
-
}
|
|
64
|
+
hash: props.hash !== '' ? `#${props.hash}` : undefined,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
const newQuery = { ...route.query }
|
|
68
|
-
newQuery.page = page.toString()
|
|
68
|
+
function page(page: number): RouteLocationRaw {
|
|
69
|
+
const newQuery = { ...route.query }
|
|
70
|
+
newQuery.page = page.toString()
|
|
69
71
|
return {
|
|
70
72
|
path: history.currentRoute.path,
|
|
71
73
|
query: newQuery,
|
|
72
|
-
hash: props.hash
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const currentUrl = computed(() => {
|
|
76
|
-
/*
|
|
77
|
-
const url = getURL();
|
|
78
|
-
return `${url.Path}?page=`;
|
|
79
|
-
*/
|
|
80
|
-
// user router url instead of getURL
|
|
81
|
-
return `${history.currentRoute.path}?page=`;
|
|
82
|
-
});
|
|
74
|
+
hash: props.hash !== '' ? `#${props.hash}` : undefined,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
83
77
|
|
|
84
|
-
|
|
85
|
-
prevNextSeo.value.next = undefined
|
|
86
|
-
prevNextSeo.value.prev = undefined
|
|
87
|
-
const pagePlus = page + 1
|
|
88
|
-
const pageMinus = page - 1
|
|
78
|
+
function checkPageNumber(page: number = 1) {
|
|
79
|
+
prevNextSeo.value.next = undefined
|
|
80
|
+
prevNextSeo.value.prev = undefined
|
|
81
|
+
const pagePlus = page + 1
|
|
82
|
+
const pageMinus = page - 1
|
|
89
83
|
if (hasFW()) {
|
|
90
|
-
const url = getURL()
|
|
84
|
+
const url = getURL()
|
|
91
85
|
if (pagePlus <= props.items.page_max && url) {
|
|
92
|
-
prevNextSeo.value.next
|
|
93
|
-
`${url.Scheme}://${url.Host}${route.path}?page=${pagePlus}
|
|
94
|
-
|
|
86
|
+
prevNextSeo.value.next
|
|
87
|
+
= `${url.Scheme}://${url.Host}${route.path}?page=${pagePlus}${
|
|
88
|
+
props.hash !== '' ? `#${props.hash}` : ''}`
|
|
95
89
|
}
|
|
96
90
|
if (pageMinus >= 1 && url) {
|
|
97
|
-
prevNextSeo.value.prev
|
|
98
|
-
`${url.Scheme}://${url.Host}${route.path}?page=${pageMinus}
|
|
99
|
-
|
|
91
|
+
prevNextSeo.value.prev
|
|
92
|
+
= `${url.Scheme}://${url.Host}${route.path}?page=${pageMinus}${
|
|
93
|
+
props.hash !== '' ? `#${props.hash}` : ''}`
|
|
100
94
|
}
|
|
101
95
|
}
|
|
102
|
-
}
|
|
96
|
+
}
|
|
103
97
|
|
|
104
98
|
pageWatcher.value = watch(
|
|
105
99
|
() => route.query.page,
|
|
106
100
|
(v) => {
|
|
107
|
-
eventBus.emit(`${props.id}GoToPage`, v
|
|
101
|
+
eventBus.emit(`${props.id}GoToPage`, v || 1)
|
|
108
102
|
},
|
|
109
|
-
)
|
|
103
|
+
)
|
|
110
104
|
onMounted(() => {
|
|
111
|
-
eventBus.on(`${props.id}GoToPage`, checkPageNumber)
|
|
112
|
-
})
|
|
105
|
+
eventBus.on(`${props.id}GoToPage`, checkPageNumber)
|
|
106
|
+
})
|
|
113
107
|
onUnmounted(() => {
|
|
114
|
-
eventBus.off(`${props.id}GoToPage`, checkPageNumber)
|
|
115
|
-
//if (pageWatcher.value) pageWatcher.value();
|
|
116
|
-
})
|
|
108
|
+
eventBus.off(`${props.id}GoToPage`, checkPageNumber)
|
|
109
|
+
// if (pageWatcher.value) pageWatcher.value();
|
|
110
|
+
})
|
|
117
111
|
|
|
118
|
-
checkPageNumber(props.items.page_no)
|
|
112
|
+
checkPageNumber(props.items.page_no)
|
|
119
113
|
useHead({
|
|
120
114
|
link: computed(() => {
|
|
121
|
-
const result: any = []
|
|
122
|
-
if (prevNextSeo.value.next)
|
|
115
|
+
const result: any = []
|
|
116
|
+
if (prevNextSeo.value.next) {
|
|
123
117
|
result.push({
|
|
124
118
|
href: prevNextSeo.value.next,
|
|
125
|
-
rel:
|
|
126
|
-
key:
|
|
127
|
-
})
|
|
128
|
-
|
|
119
|
+
rel: 'next',
|
|
120
|
+
key: 'next',
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
if (prevNextSeo.value.prev) {
|
|
129
124
|
result.push({
|
|
130
125
|
href: prevNextSeo.value.prev,
|
|
131
|
-
rel:
|
|
132
|
-
key:
|
|
133
|
-
})
|
|
126
|
+
rel: 'prev',
|
|
127
|
+
key: 'prev',
|
|
128
|
+
})
|
|
129
|
+
}
|
|
134
130
|
|
|
135
|
-
return result
|
|
131
|
+
return result
|
|
136
132
|
}),
|
|
137
|
-
})
|
|
133
|
+
})
|
|
138
134
|
</script>
|
|
135
|
+
|
|
139
136
|
<template>
|
|
140
137
|
<div
|
|
141
|
-
class="flex items-center justify-center"
|
|
142
138
|
v-if="items && items.page_max > 1 && items.page_no"
|
|
139
|
+
class="flex items-center justify-center"
|
|
143
140
|
>
|
|
144
141
|
<div class="paging-container">
|
|
145
142
|
<nav aria-label="Pagination">
|
|
@@ -147,8 +144,8 @@ useHead({
|
|
|
147
144
|
<li v-if="items.page_no >= 2">
|
|
148
145
|
<button
|
|
149
146
|
type="button"
|
|
150
|
-
@click="prev()"
|
|
151
147
|
class="flex items-center justify-center px-1.5 h-8 leading-tight text-fv-neutral-500 bg-white border border-fv-neutral-300 hover:bg-fv-neutral-100 hover:text-fv-neutral-700 dark:bg-fv-neutral-800 dark:border-fv-neutral-700 dark:text-fv-neutral-400 dark:hover:bg-fv-neutral-700 dark:hover:text-white"
|
|
148
|
+
@click="prev()"
|
|
152
149
|
>
|
|
153
150
|
<span class="sr-only">{{ $t("previous_paging") }}</span>
|
|
154
151
|
<ChevronLeftIcon class="w-4 h-4" />
|
|
@@ -193,8 +190,8 @@ useHead({
|
|
|
193
190
|
</li>
|
|
194
191
|
<template v-for="i in 2">
|
|
195
192
|
<li
|
|
196
|
-
:key="`page-x-${items.page_no + i}`"
|
|
197
193
|
v-if="items.page_no + i <= items.page_max"
|
|
194
|
+
:key="`page-x-${items.page_no + i}`"
|
|
198
195
|
>
|
|
199
196
|
<router-link
|
|
200
197
|
class="flex items-center justify-center px-3 h-8 leading-tight text-fv-neutral-500 bg-white border border-fv-neutral-300 hover:bg-fv-neutral-100 hover:text-fv-neutral-700 dark:bg-fv-neutral-800 dark:border-fv-neutral-700 dark:text-fv-neutral-400 dark:hover:bg-fv-neutral-700 dark:hover:text-white"
|
|
@@ -221,9 +218,9 @@ useHead({
|
|
|
221
218
|
</li>
|
|
222
219
|
<li v-if="items.page_no < items.page_max - 1">
|
|
223
220
|
<button
|
|
224
|
-
@click="next()"
|
|
225
221
|
type="button"
|
|
226
222
|
class="flex items-center justify-center px-1.5 h-8 leading-tight text-fv-neutral-500 bg-white border border-fv-neutral-300 hover:bg-fv-neutral-100 hover:text-fv-neutral-700 dark:bg-fv-neutral-800 dark:border-fv-neutral-700 dark:text-fv-neutral-400 dark:hover:bg-fv-neutral-700 dark:hover:text-white"
|
|
223
|
+
@click="next()"
|
|
227
224
|
>
|
|
228
225
|
<span class="sr-only">{{ $t("next_paging") }}</span>
|
|
229
226
|
<ChevronRightIcon class="w-4 h-4" />
|
|
@@ -232,8 +229,8 @@ useHead({
|
|
|
232
229
|
</ul>
|
|
233
230
|
</nav>
|
|
234
231
|
<p
|
|
235
|
-
class="text-xs text-fv-neutral-700 dark:text-fv-neutral-400 pt-0.5"
|
|
236
232
|
v-if="showLegend"
|
|
233
|
+
class="text-xs text-fv-neutral-700 dark:text-fv-neutral-400 pt-0.5"
|
|
237
234
|
>
|
|
238
235
|
{{
|
|
239
236
|
$t("global_paging", {
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { NavLink } from
|
|
3
|
-
import {
|
|
4
|
-
import { useStorage } from
|
|
5
|
-
import { useRoute } from
|
|
2
|
+
import type { NavLink } from '../../types'
|
|
3
|
+
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/vue/24/solid'
|
|
4
|
+
import { useStorage } from '@vueuse/core'
|
|
5
|
+
import { useRoute } from 'vue-router'
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(
|
|
8
8
|
defineProps<{
|
|
9
|
-
links: NavLink[]
|
|
10
|
-
id?: string
|
|
11
|
-
baseUrl?: string
|
|
9
|
+
links: NavLink[]
|
|
10
|
+
id?: string
|
|
11
|
+
baseUrl?: string
|
|
12
12
|
}>(),
|
|
13
13
|
{
|
|
14
|
-
id:
|
|
15
|
-
baseUrl:
|
|
14
|
+
id: 'main',
|
|
15
|
+
baseUrl: '/',
|
|
16
16
|
},
|
|
17
|
-
)
|
|
18
|
-
const route = useRoute()
|
|
19
|
-
|
|
20
|
-
if (link.to
|
|
21
|
-
if (route.path
|
|
22
|
-
return
|
|
23
|
-
} else {
|
|
24
|
-
if (route.path == link.to) {
|
|
25
|
-
return "fvside-active";
|
|
17
|
+
)
|
|
18
|
+
const route = useRoute()
|
|
19
|
+
function isLinkActive(link: NavLink) {
|
|
20
|
+
if (link.to !== props.baseUrl) {
|
|
21
|
+
if (route.path === link.to || route.path.includes(link.to)) {
|
|
22
|
+
return 'fvside-active'
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
else {
|
|
26
|
+
if (route.path === link.to) {
|
|
27
|
+
return 'fvside-active'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return ''
|
|
31
|
+
}
|
|
32
|
+
const isOpen = useStorage(`isOpenSidebar-${props.id}`, true)
|
|
31
33
|
</script>
|
|
34
|
+
|
|
32
35
|
<template>
|
|
33
36
|
<aside class="fui-sidebar" :class="isOpen ? '' : 'fui-sidebar__md'">
|
|
34
37
|
<div class="fui-sidebar__controller">
|
|
@@ -42,8 +45,8 @@ const isOpen = useStorage(`isOpenSidebar-${props.id}`, true);
|
|
|
42
45
|
<span class="sr-only">{{ $t("sidebar_size_control") }}</span>
|
|
43
46
|
</button>
|
|
44
47
|
</div>
|
|
45
|
-
<slot name="before"
|
|
46
|
-
<ul
|
|
48
|
+
<slot name="before" />
|
|
49
|
+
<ul id="side-nav" role="list">
|
|
47
50
|
<li v-for="(link, index) of links" :key="`aside_link_${index}`">
|
|
48
51
|
<RouterLink
|
|
49
52
|
:to="link.to"
|
|
@@ -58,11 +61,12 @@ const isOpen = useStorage(`isOpenSidebar-${props.id}`, true);
|
|
|
58
61
|
<span class="sr-only">{{ link.name }}</span>
|
|
59
62
|
</RouterLink>
|
|
60
63
|
</li>
|
|
61
|
-
<slot name="lis"
|
|
64
|
+
<slot name="lis" />
|
|
62
65
|
</ul>
|
|
63
|
-
<slot name="after"
|
|
66
|
+
<slot name="after" />
|
|
64
67
|
</aside>
|
|
65
68
|
</template>
|
|
69
|
+
|
|
66
70
|
<style lang="scss" scoped>
|
|
67
71
|
.fui-sidebar {
|
|
68
72
|
@apply w-60 transition-all duration-300 ease-in-out;
|