sprintify-ui 0.8.9 → 0.8.11
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/sprintify-ui.es.js +5345 -5237
- package/dist/types/components/BaseLayoutSidebar.vue.d.ts +3 -1
- package/dist/types/components/BaseNavbarSideItem.vue.d.ts +9 -0
- package/dist/types/components/BaseNavbarSideItemContent.vue.d.ts +9 -0
- package/dist/types/components/BaseTooltip.vue.d.ts +11 -0
- package/dist/types/composables/tooltip.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/BaseLayoutSidebar.vue +54 -13
- package/src/components/BaseLayoutSidebarConfigurable.vue +18 -6
- package/src/components/BaseLayoutStackedConfigurable.vue +7 -3
- package/src/components/BaseNavbarSideItem.vue +77 -16
- package/src/components/BaseNavbarSideItemContent.vue +22 -7
- package/src/components/BaseTooltip.vue +8 -2
- package/src/composables/tooltip.ts +32 -2
|
@@ -49,7 +49,9 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{
|
|
|
49
49
|
logoUrl: string;
|
|
50
50
|
logoTo: RouteLocationRaw;
|
|
51
51
|
}, {}>, {
|
|
52
|
-
menu?(_: {
|
|
52
|
+
menu?(_: {
|
|
53
|
+
collapsed: boolean;
|
|
54
|
+
}): any;
|
|
53
55
|
navbar?(_: {}): any;
|
|
54
56
|
default?(_: {}): any;
|
|
55
57
|
}>;
|
|
@@ -13,6 +13,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
13
13
|
default: string;
|
|
14
14
|
type: PropType<"xs" | "sm" | "md">;
|
|
15
15
|
};
|
|
16
|
+
collapsed: {
|
|
17
|
+
default: boolean;
|
|
18
|
+
type: BooleanConstructor;
|
|
19
|
+
};
|
|
16
20
|
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
17
21
|
click: (...args: any[]) => void;
|
|
18
22
|
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
@@ -28,10 +32,15 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
28
32
|
default: string;
|
|
29
33
|
type: PropType<"xs" | "sm" | "md">;
|
|
30
34
|
};
|
|
35
|
+
collapsed: {
|
|
36
|
+
default: boolean;
|
|
37
|
+
type: BooleanConstructor;
|
|
38
|
+
};
|
|
31
39
|
}>> & {
|
|
32
40
|
onClick?: ((...args: any[]) => any) | undefined;
|
|
33
41
|
}, {
|
|
34
42
|
size: "xs" | "sm" | "md";
|
|
35
43
|
dark: boolean;
|
|
44
|
+
collapsed: boolean;
|
|
36
45
|
}, {}>;
|
|
37
46
|
export default _default;
|
|
@@ -24,6 +24,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
24
24
|
default: string;
|
|
25
25
|
type: PropType<"xs" | "sm" | "md">;
|
|
26
26
|
};
|
|
27
|
+
collapsed: {
|
|
28
|
+
default: boolean;
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
};
|
|
27
31
|
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
28
32
|
label: {
|
|
29
33
|
default: undefined;
|
|
@@ -49,6 +53,10 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
49
53
|
default: string;
|
|
50
54
|
type: PropType<"xs" | "sm" | "md">;
|
|
51
55
|
};
|
|
56
|
+
collapsed: {
|
|
57
|
+
default: boolean;
|
|
58
|
+
type: BooleanConstructor;
|
|
59
|
+
};
|
|
52
60
|
}>>, {
|
|
53
61
|
size: "xs" | "sm" | "md";
|
|
54
62
|
icon: string;
|
|
@@ -56,5 +64,6 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
56
64
|
dark: boolean;
|
|
57
65
|
label: string;
|
|
58
66
|
active: boolean;
|
|
67
|
+
collapsed: boolean;
|
|
59
68
|
}, {}>;
|
|
60
69
|
export default _default;
|
|
@@ -1,23 +1,34 @@
|
|
|
1
|
+
import { UseFloatingOptions } from '@floating-ui/vue';
|
|
1
2
|
declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<{
|
|
2
3
|
visible?: boolean | undefined;
|
|
3
4
|
text?: string | null | undefined;
|
|
4
5
|
class?: string | string[] | null | undefined;
|
|
6
|
+
floatingOptions?: UseFloatingOptions | undefined;
|
|
7
|
+
interactive?: boolean | undefined;
|
|
5
8
|
}>, {
|
|
6
9
|
visible: boolean;
|
|
7
10
|
text: null;
|
|
8
11
|
class: null;
|
|
12
|
+
floatingOptions: undefined;
|
|
13
|
+
interactive: boolean;
|
|
9
14
|
}>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<{
|
|
10
15
|
visible?: boolean | undefined;
|
|
11
16
|
text?: string | null | undefined;
|
|
12
17
|
class?: string | string[] | null | undefined;
|
|
18
|
+
floatingOptions?: UseFloatingOptions | undefined;
|
|
19
|
+
interactive?: boolean | undefined;
|
|
13
20
|
}>, {
|
|
14
21
|
visible: boolean;
|
|
15
22
|
text: null;
|
|
16
23
|
class: null;
|
|
24
|
+
floatingOptions: undefined;
|
|
25
|
+
interactive: boolean;
|
|
17
26
|
}>>>, {
|
|
18
27
|
class: string | string[] | null;
|
|
19
28
|
text: string | null;
|
|
20
29
|
visible: boolean;
|
|
30
|
+
floatingOptions: UseFloatingOptions;
|
|
31
|
+
interactive: boolean;
|
|
21
32
|
}, {}>, {
|
|
22
33
|
default?(_: {}): any;
|
|
23
34
|
tooltip?(_: {}): any;
|
|
@@ -3,5 +3,5 @@ type ReturnType = UseFloatingReturn & {
|
|
|
3
3
|
showTooltip: Ref<boolean>;
|
|
4
4
|
};
|
|
5
5
|
import { Ref } from "vue";
|
|
6
|
-
declare function useTooltip(reference: Readonly<Ref<MaybeElement<any>>>, floating: Readonly<Ref<MaybeElement<HTMLElement>>>, options?: UseFloatingOptions | undefined): ReturnType;
|
|
6
|
+
declare function useTooltip(reference: Readonly<Ref<MaybeElement<any>>>, floating: Readonly<Ref<MaybeElement<HTMLElement>>>, interactive?: boolean, options?: UseFloatingOptions | undefined): ReturnType;
|
|
7
7
|
export { useTooltip };
|
package/package.json
CHANGED
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
:alt="appName"
|
|
71
71
|
>
|
|
72
72
|
</RouterLink>
|
|
73
|
+
|
|
73
74
|
<div
|
|
74
75
|
data-scroll-lock-scrollable
|
|
75
76
|
class="flex-1 h-0 mt-5 overflow-y-auto"
|
|
@@ -90,7 +91,10 @@
|
|
|
90
91
|
</Dialog>
|
|
91
92
|
</TransitionRoot>
|
|
92
93
|
|
|
93
|
-
<div
|
|
94
|
+
<div
|
|
95
|
+
class="flex flex-col min-h-full || xl:print:pl-0"
|
|
96
|
+
:class="[collapsed ? 'xl:pl-16' : 'xl:pl-64']"
|
|
97
|
+
>
|
|
94
98
|
<div class="sticky top-0 left-0 z-10 shadow shrink-0 || print:hidden">
|
|
95
99
|
<BaseSystemAlert
|
|
96
100
|
v-for="systemAlert in systemAlerts"
|
|
@@ -135,29 +139,56 @@
|
|
|
135
139
|
</div>
|
|
136
140
|
|
|
137
141
|
<!-- Static sidebar for desktop -->
|
|
138
|
-
<div
|
|
142
|
+
<div
|
|
143
|
+
class="z-10 hidden || xl:fixed xl:inset-y-0 xl:flex xl:flex-col || xl:print:hidden"
|
|
144
|
+
:class="[collapsed ? 'xl:w-16' : 'xl:w-64']"
|
|
145
|
+
>
|
|
139
146
|
<!-- Sidebar component, swap this element with another sidebar if you like -->
|
|
140
147
|
<div
|
|
141
148
|
data-scroll-lock-scrollable
|
|
142
149
|
class="flex flex-col flex-1 min-h-0 overflow-y-auto"
|
|
143
150
|
:class="[dark ? 'bg-slate-800' : 'bg-slate-50 ring-1 ring-black ring-opacity-10']"
|
|
144
151
|
>
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
class="flex items-center flex-shrink-0 px-4"
|
|
148
|
-
:style="{ height: navbarHeight + 'px' }"
|
|
152
|
+
<div
|
|
153
|
+
class="flex"
|
|
149
154
|
:class="[dark ? 'bg-slate-900' : 'border-b']"
|
|
150
|
-
|
|
155
|
+
:style="{ height: navbarHeight + 'px' }"
|
|
151
156
|
>
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
:
|
|
155
|
-
|
|
157
|
+
<RouterLink
|
|
158
|
+
v-if="!collapsed"
|
|
159
|
+
:to="logoTo"
|
|
160
|
+
class="flex items-center flex-shrink-0 grow px-4"
|
|
161
|
+
|
|
162
|
+
@click="closeMenu"
|
|
156
163
|
>
|
|
157
|
-
|
|
164
|
+
<img
|
|
165
|
+
class="block w-auto h-8"
|
|
166
|
+
:src="logoUrl"
|
|
167
|
+
:alt="appName"
|
|
168
|
+
>
|
|
169
|
+
</RouterLink>
|
|
170
|
+
<button
|
|
171
|
+
type="button"
|
|
172
|
+
class="px-3 flex justify-center items-center"
|
|
173
|
+
:class="[
|
|
174
|
+
dark ? 'text-slate-400 hover:text-slate-50' : 'text-slate-500 hover:text-slate-900',
|
|
175
|
+
collapsed ? 'grow' : 'shrink-0'
|
|
176
|
+
]"
|
|
177
|
+
@click="toggleCollapse"
|
|
178
|
+
>
|
|
179
|
+
<BaseIcon
|
|
180
|
+
icon="mdi:dock-left"
|
|
181
|
+
class="w-6 h-6"
|
|
182
|
+
/>
|
|
183
|
+
</button>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
158
186
|
<div class="flex flex-1">
|
|
159
187
|
<nav class="flex-1">
|
|
160
|
-
<slot
|
|
188
|
+
<slot
|
|
189
|
+
name="menu"
|
|
190
|
+
:collapsed="collapsed"
|
|
191
|
+
/>
|
|
161
192
|
</nav>
|
|
162
193
|
</div>
|
|
163
194
|
</div>
|
|
@@ -230,6 +261,16 @@ function closeMenu() {
|
|
|
230
261
|
showMobileMenu.value = false;
|
|
231
262
|
}
|
|
232
263
|
|
|
264
|
+
/**
|
|
265
|
+
* Collapse
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
const collapsed = ref(false);
|
|
269
|
+
|
|
270
|
+
function toggleCollapse() {
|
|
271
|
+
collapsed.value = !collapsed.value;
|
|
272
|
+
}
|
|
273
|
+
|
|
233
274
|
const navbarHeight = computed<number>(() => {
|
|
234
275
|
if (props.size === 'xs') {
|
|
235
276
|
return 50;
|
|
@@ -6,10 +6,13 @@
|
|
|
6
6
|
:dark="dark"
|
|
7
7
|
:size="size"
|
|
8
8
|
>
|
|
9
|
-
<template #menu>
|
|
10
|
-
<div
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
<template #menu="{ collapsed }">
|
|
10
|
+
<div
|
|
11
|
+
class="py-6"
|
|
12
|
+
:class="[collapsed ? '' : 'px-3']"
|
|
13
|
+
>
|
|
14
|
+
<div :class="[collapsed ? 'space-y-2' : 'space-y-8']">
|
|
15
|
+
<template
|
|
13
16
|
v-for="section in menu"
|
|
14
17
|
:key="section.label"
|
|
15
18
|
>
|
|
@@ -18,19 +21,27 @@
|
|
|
18
21
|
:key="section.label"
|
|
19
22
|
>
|
|
20
23
|
<h2
|
|
24
|
+
v-if="!collapsed"
|
|
21
25
|
class="pl-3"
|
|
22
26
|
:class="sectionLabelClasses"
|
|
23
27
|
>
|
|
24
28
|
{{ section.label }}
|
|
25
29
|
</h2>
|
|
26
30
|
|
|
27
|
-
<div
|
|
31
|
+
<div
|
|
32
|
+
:class="[
|
|
33
|
+
collapsed ? 'space-y-2' : '',
|
|
34
|
+
!collapsed && size == 'md' ? 'space-y-1' : '',
|
|
35
|
+
!collapsed && size != 'md' ? 'space-y-0.5' : '',
|
|
36
|
+
]"
|
|
37
|
+
>
|
|
28
38
|
<BaseNavbarSideItem
|
|
29
39
|
v-for="item in section.actions"
|
|
30
40
|
:key="item.label"
|
|
31
41
|
:item="item"
|
|
32
42
|
:dark="dark"
|
|
33
43
|
:size="size"
|
|
44
|
+
:collapsed="collapsed"
|
|
34
45
|
/>
|
|
35
46
|
</div>
|
|
36
47
|
</div>
|
|
@@ -40,8 +51,9 @@
|
|
|
40
51
|
:item="section"
|
|
41
52
|
:dark="dark"
|
|
42
53
|
:size="size"
|
|
54
|
+
:collapsed="collapsed"
|
|
43
55
|
/>
|
|
44
|
-
</
|
|
56
|
+
</template>
|
|
45
57
|
</div>
|
|
46
58
|
</div>
|
|
47
59
|
</template>
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
v-if="logoUrl"
|
|
15
15
|
:to="logoTo"
|
|
16
16
|
class="flex flex-shrink-0 items-center p-2 pl-0"
|
|
17
|
+
:class="{
|
|
18
|
+
'mr-4': size == 'xs',
|
|
19
|
+
'mr-6': size == 'sm',
|
|
20
|
+
'mr-8': size == 'md',
|
|
21
|
+
}"
|
|
17
22
|
>
|
|
18
23
|
<img
|
|
19
24
|
class="block h-8 w-auto"
|
|
@@ -27,9 +32,8 @@
|
|
|
27
32
|
v-if="!mobile"
|
|
28
33
|
class="flex"
|
|
29
34
|
:class="{
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'ml-8 space-x-1': size == 'md',
|
|
35
|
+
'space-x-0.5': size == 'sm',
|
|
36
|
+
'space-x-1': size == 'md',
|
|
33
37
|
}"
|
|
34
38
|
>
|
|
35
39
|
<BaseNavbarItem
|
|
@@ -1,25 +1,76 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
<BaseTooltip
|
|
4
|
+
:floating-options="{
|
|
5
|
+
placement: 'right-start',
|
|
6
|
+
}"
|
|
7
|
+
:visible="collapsed"
|
|
8
|
+
:interactive="hasItems"
|
|
8
9
|
>
|
|
9
|
-
<template #default
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
<template #default>
|
|
11
|
+
<BaseActionItem
|
|
12
|
+
v-if="!item.meta?.line"
|
|
13
|
+
:item="item"
|
|
14
|
+
class="flex w-full"
|
|
15
|
+
@click="onClick"
|
|
16
|
+
>
|
|
17
|
+
<template #default="{ active }">
|
|
18
|
+
<BaseNavbarSideItemContent
|
|
19
|
+
:label="item.label"
|
|
20
|
+
:icon="item.icon"
|
|
21
|
+
:active="active"
|
|
22
|
+
:count="item.count"
|
|
23
|
+
:dark="dark"
|
|
24
|
+
:size="size"
|
|
25
|
+
:collapsed="collapsed"
|
|
26
|
+
/>
|
|
27
|
+
</template>
|
|
28
|
+
</BaseActionItem>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<template
|
|
32
|
+
v-if="collapsed"
|
|
33
|
+
#tooltip
|
|
34
|
+
>
|
|
35
|
+
<div
|
|
36
|
+
v-if="hasItems"
|
|
37
|
+
class="bg-white px-4 py-3 shadow-lg ring-1 ring-black ring-opacity-10 rounded-md"
|
|
38
|
+
>
|
|
39
|
+
<div
|
|
40
|
+
v-for="subItem in item.actions"
|
|
41
|
+
:key="subItem.label"
|
|
42
|
+
>
|
|
43
|
+
<BaseActionItem
|
|
44
|
+
:item="subItem"
|
|
45
|
+
class="flex gap-1 items-center justify-start"
|
|
46
|
+
>
|
|
47
|
+
<template #default="{ active }">
|
|
48
|
+
<div
|
|
49
|
+
class="text-sm text-slate-600 hover:text-slate-950"
|
|
50
|
+
:class="{ 'font-medium': active }"
|
|
51
|
+
>
|
|
52
|
+
{{ subItem.label }}
|
|
53
|
+
</div>
|
|
54
|
+
<BaseCounter
|
|
55
|
+
v-if="subItem.count"
|
|
56
|
+
:count="subItem.count"
|
|
57
|
+
size="xs"
|
|
58
|
+
/>
|
|
59
|
+
</template>
|
|
60
|
+
</BaseActionItem>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
<div
|
|
64
|
+
v-else
|
|
65
|
+
class="bg-slate-900 text-white rounded shadow-lg px-2 py-1.5 text-xs"
|
|
66
|
+
>
|
|
67
|
+
<span>{{ item.label }}</span>
|
|
68
|
+
</div>
|
|
18
69
|
</template>
|
|
19
|
-
</
|
|
70
|
+
</BaseTooltip>
|
|
20
71
|
|
|
21
72
|
<div
|
|
22
|
-
v-if="
|
|
73
|
+
v-if="!collapsed && hasItems && showSubActions"
|
|
23
74
|
class="mt-1 sm:mt-2 mb-3"
|
|
24
75
|
>
|
|
25
76
|
<div
|
|
@@ -56,6 +107,8 @@ import { ActionItem } from '@/types';
|
|
|
56
107
|
import BaseActionItem from './BaseActionItem.vue';
|
|
57
108
|
import BaseNavbarSideItemContent from './BaseNavbarSideItemContent.vue';
|
|
58
109
|
import BaseCounter from './BaseCounter.vue';
|
|
110
|
+
import BaseTooltip from './BaseTooltip.vue';
|
|
111
|
+
import { flip, shift } from '@floating-ui/vue';
|
|
59
112
|
|
|
60
113
|
const router = useRouter();
|
|
61
114
|
|
|
@@ -72,6 +125,10 @@ const props = defineProps({
|
|
|
72
125
|
default: 'md',
|
|
73
126
|
type: String as PropType<'xs' | 'sm' | 'md'>,
|
|
74
127
|
},
|
|
128
|
+
collapsed: {
|
|
129
|
+
default: false,
|
|
130
|
+
type: Boolean,
|
|
131
|
+
},
|
|
75
132
|
});
|
|
76
133
|
|
|
77
134
|
const emit = defineEmits(['click']);
|
|
@@ -80,6 +137,10 @@ async function onClick() {
|
|
|
80
137
|
emit('click');
|
|
81
138
|
}
|
|
82
139
|
|
|
140
|
+
const hasItems = computed((): boolean => {
|
|
141
|
+
return !!props.item.actions && props.item.actions.length > 0;
|
|
142
|
+
});
|
|
143
|
+
|
|
83
144
|
const routeActive = computed((): boolean => {
|
|
84
145
|
if (!props.item.to) {
|
|
85
146
|
return false;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="classes">
|
|
3
|
-
<div
|
|
3
|
+
<div
|
|
4
|
+
class="group flex grow items-center"
|
|
5
|
+
:class="[collapsed ? 'justify-center' : 'justify-start']"
|
|
6
|
+
>
|
|
4
7
|
<BaseIcon
|
|
5
8
|
v-if="icon"
|
|
6
9
|
:icon="icon"
|
|
7
10
|
:class="iconClasses"
|
|
8
11
|
/>
|
|
9
|
-
<span>{{ label }}</span>
|
|
12
|
+
<span v-if="!collapsed">{{ label }}</span>
|
|
10
13
|
</div>
|
|
11
14
|
<div
|
|
12
|
-
v-if="count"
|
|
15
|
+
v-if="count && !collapsed"
|
|
13
16
|
class="relative -top-px ml-[5px]"
|
|
14
17
|
>
|
|
15
18
|
<BaseCounter
|
|
@@ -52,10 +55,18 @@ const props = defineProps({
|
|
|
52
55
|
default: 'md',
|
|
53
56
|
type: String as PropType<'xs' | 'sm' | 'md'>,
|
|
54
57
|
},
|
|
58
|
+
collapsed: {
|
|
59
|
+
default: false,
|
|
60
|
+
type: Boolean,
|
|
61
|
+
},
|
|
55
62
|
});
|
|
56
63
|
|
|
57
64
|
const classes = computed(() => {
|
|
58
|
-
const classList = ['text-left
|
|
65
|
+
const classList = ['text-left flex w-full'];
|
|
66
|
+
|
|
67
|
+
if (!props.collapsed) {
|
|
68
|
+
classList.push('rounded-md');
|
|
69
|
+
}
|
|
59
70
|
|
|
60
71
|
if (props.active) {
|
|
61
72
|
if (props.dark) {
|
|
@@ -95,15 +106,19 @@ const iconClasses = computed((): string[] => {
|
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
if (props.size == 'xs') {
|
|
98
|
-
classList.push('w-3.5 h-3.5
|
|
109
|
+
classList.push('w-3.5 h-3.5');
|
|
99
110
|
}
|
|
100
111
|
|
|
101
112
|
if (props.size == 'sm') {
|
|
102
|
-
classList.push('w-4 h-4
|
|
113
|
+
classList.push('w-4 h-4');
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
if (props.size == 'md') {
|
|
106
|
-
classList.push('w-5 h-5
|
|
117
|
+
classList.push('w-5 h-5');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!props.collapsed) {
|
|
121
|
+
classList.push('mr-2');
|
|
107
122
|
}
|
|
108
123
|
|
|
109
124
|
return classList;
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
>
|
|
12
12
|
<div
|
|
13
13
|
ref="tooltipRef"
|
|
14
|
-
class="fixed top-0 left-0
|
|
14
|
+
class="fixed top-0 left-0 z-tooltip"
|
|
15
|
+
:class="[!interactive ? 'pointer-events-none' : '']"
|
|
15
16
|
:style="floatingStyles"
|
|
16
17
|
>
|
|
17
18
|
<transition
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
<script lang="ts" setup>
|
|
40
41
|
import { useTooltip } from '@/composables/tooltip';
|
|
41
42
|
import { unrefElement } from '@vueuse/core';
|
|
43
|
+
import { UseFloatingOptions } from '@floating-ui/vue';
|
|
42
44
|
|
|
43
45
|
defineOptions({
|
|
44
46
|
inheritAttrs: false,
|
|
@@ -48,10 +50,14 @@ const props = withDefaults(defineProps<{
|
|
|
48
50
|
visible?: boolean,
|
|
49
51
|
text?: string | null | undefined;
|
|
50
52
|
class?: string[] | string | null | undefined;
|
|
53
|
+
floatingOptions?: UseFloatingOptions,
|
|
54
|
+
interactive?: boolean,
|
|
51
55
|
}>(), {
|
|
52
56
|
visible: true,
|
|
53
57
|
text: null,
|
|
54
58
|
class: null,
|
|
59
|
+
floatingOptions: undefined,
|
|
60
|
+
interactive: false,
|
|
55
61
|
});
|
|
56
62
|
|
|
57
63
|
const targetRef = ref<HTMLElement | null>(null);
|
|
@@ -60,6 +66,6 @@ const targetInternal = computed(() => unrefElement(targetRef));
|
|
|
60
66
|
|
|
61
67
|
const tooltipRef = ref<HTMLElement | null>(null)
|
|
62
68
|
|
|
63
|
-
const { floatingStyles, showTooltip } = useTooltip(targetInternal, tooltipRef);
|
|
69
|
+
const { floatingStyles, showTooltip } = useTooltip(targetInternal, tooltipRef, props.interactive, props.floatingOptions);
|
|
64
70
|
|
|
65
71
|
</script>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UseFloatingOptions, MaybeElement, UseFloatingReturn, autoUpdate, flip, offset, shift, useFloating } from "@floating-ui/vue";
|
|
2
2
|
import { unrefElement, useEventListener, } from "@vueuse/core";
|
|
3
|
+
import { debounce } from "lodash";
|
|
3
4
|
|
|
4
5
|
type ReturnType = UseFloatingReturn & {
|
|
5
6
|
showTooltip: Ref<boolean>;
|
|
@@ -10,6 +11,7 @@ import { Ref } from "vue";
|
|
|
10
11
|
function useTooltip(
|
|
11
12
|
reference: Readonly<Ref<MaybeElement<any>>>,
|
|
12
13
|
floating: Readonly<Ref<MaybeElement<HTMLElement>>>,
|
|
14
|
+
interactive: boolean = false,
|
|
13
15
|
options: UseFloatingOptions | undefined = undefined
|
|
14
16
|
): ReturnType {
|
|
15
17
|
|
|
@@ -19,14 +21,42 @@ function useTooltip(
|
|
|
19
21
|
return unrefElement(reference);
|
|
20
22
|
});
|
|
21
23
|
|
|
24
|
+
const floatingRef = computed(() => {
|
|
25
|
+
return unrefElement(floating);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let nextShow = false;
|
|
29
|
+
|
|
22
30
|
useEventListener(elementRef, 'mouseenter', () => {
|
|
23
|
-
|
|
31
|
+
nextShow = true;
|
|
32
|
+
renderShow();
|
|
24
33
|
});
|
|
25
34
|
|
|
26
35
|
useEventListener(elementRef, 'mouseleave', () => {
|
|
27
|
-
|
|
36
|
+
nextShow = false;
|
|
37
|
+
renderShow();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
useEventListener(floatingRef, 'mouseenter', () => {
|
|
41
|
+
if (!interactive) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
nextShow = true;
|
|
45
|
+
renderShow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
useEventListener(floatingRef, 'mouseleave', () => {
|
|
49
|
+
if (!interactive) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
nextShow = false;
|
|
53
|
+
renderShow();
|
|
28
54
|
});
|
|
29
55
|
|
|
56
|
+
const renderShow = debounce(() => {
|
|
57
|
+
show.value = nextShow;
|
|
58
|
+
}, interactive ? 150 : 0);
|
|
59
|
+
|
|
30
60
|
const config = {
|
|
31
61
|
placement: 'top',
|
|
32
62
|
middleware: [offset(6), flip(), shift()],
|