@veritree/ui 0.24.1 → 0.25.0-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/index.js +64 -72
- package/mixins/floating-ui-content.js +1 -1
- package/mixins/floating-ui-item.js +8 -6
- package/mixins/floating-ui.js +8 -1
- package/mixins/form-control-icon.js +3 -3
- package/mixins/form-control.js +9 -14
- package/nuxt.js +30 -24
- package/package.json +14 -6
- package/src/components/Alert/VTAlert.vue +55 -14
- package/src/components/Avatar/VTAvatarImage.vue +6 -26
- package/src/components/Button/VTButton.vue +25 -11
- package/src/components/Checkbox/VTCheckbox.vue +134 -0
- package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
- package/src/components/Checkbox/VTCheckboxText.vue +20 -0
- package/src/components/Dialog/VTDialog.vue +22 -23
- package/src/components/Dialog/VTDialogClose.vue +1 -1
- package/src/components/Dialog/VTDialogContent.vue +13 -5
- package/src/components/Dialog/VTDialogFooter.vue +8 -2
- package/src/components/Dialog/VTDialogHeader.vue +2 -1
- package/src/components/Dialog/VTDialogMain.vue +1 -1
- package/src/components/Dialog/VTDialogOverlay.vue +5 -1
- package/src/components/Disclosure/VTDisclosureContent.vue +1 -1
- package/src/components/Disclosure/VTDisclosureDetails.vue +1 -1
- package/src/components/Disclosure/VTDisclosureHeader.vue +2 -2
- package/src/components/Disclosure/VTDisclosureIcon.vue +1 -1
- package/src/components/Drawer/VTDrawer.vue +6 -15
- package/src/components/Drawer/VTDrawerClose.vue +5 -5
- package/src/components/Drawer/VTDrawerContent.vue +10 -10
- package/src/components/Drawer/VTDrawerFooter.vue +4 -4
- package/src/components/Drawer/VTDrawerHeader.vue +4 -4
- package/src/components/Drawer/VTDrawerMain.vue +5 -5
- package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
- package/src/components/Drawer/VTDrawerTitle.vue +5 -5
- package/src/components/DropdownMenu/VTDropdownMenu.vue +0 -6
- package/src/components/DropdownMenu/VTDropdownMenuContent.vue +10 -1
- package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
- package/src/components/DropdownMenu/VTDropdownMenuItem.vue +5 -1
- package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
- package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
- package/src/components/Form/VTFormFeedback.vue +7 -1
- package/src/components/Form/VTFormGroup.vue +5 -7
- package/src/components/Form/VTFormLabel.vue +22 -0
- package/src/components/Form/VTFormRow.vue +5 -0
- package/src/components/Form/VTInput.vue +2 -5
- package/src/components/Form/VTInputIcon.vue +1 -2
- package/src/components/Form/VTInputPassword.vue +14 -5
- package/src/components/Form/VTTextarea.vue +3 -6
- package/src/components/Image/VTImage.vue +39 -8
- package/src/components/Listbox/VTListbox.vue +72 -5
- package/src/components/Listbox/VTListboxContent.vue +0 -1
- package/src/components/Listbox/VTListboxItem.vue +11 -1
- package/src/components/Listbox/VTListboxLabel.vue +3 -4
- package/src/components/Listbox/VTListboxList.vue +3 -1
- package/src/components/Listbox/VTListboxSearch.vue +7 -6
- package/src/components/Listbox/VTListboxTrigger.vue +2 -0
- package/src/components/Popover/VTPopoverContent.vue +3 -3
- package/src/components/Popover/VTPopoverItem.vue +6 -2
- package/src/components/ProgressBar/VTProgressBar.vue +21 -3
- package/src/components/Skeleton/VTSkeleton.vue +11 -0
- package/src/components/Skeleton/VTSkeletonItem.vue +9 -0
- package/src/components/Tabs/VTTab.vue +6 -5
- package/src/components/Tabs/VTTabGroup.vue +9 -7
- package/src/components/Tabs/VTTabPanel.vue +4 -5
- package/src/components/Tooltip/VTTooltipTrigger.vue +3 -5
- package/src/components/Transitions/FadeInOut.vue +2 -2
- package/src/components/Utils/FloatingUi.vue +31 -13
- package/src/utils/components.js +18 -0
- package/src/utils/images.js +18 -25
- package/src/components/Input/VTInput.vue +0 -82
- package/src/components/Input/VTInputDate.vue +0 -36
- package/src/components/Input/VTInputFile.vue +0 -60
- package/src/components/Input/VTInputUpload.vue +0 -54
- package/src/components/Modal/VTModal.vue +0 -69
- package/src/utils/genId.js +0 -13
|
@@ -16,16 +16,39 @@ export default {
|
|
|
16
16
|
provide() {
|
|
17
17
|
return {
|
|
18
18
|
apiListbox: () => {
|
|
19
|
+
const $mutable = {};
|
|
20
|
+
|
|
21
|
+
// Used to get and update the value computed
|
|
22
|
+
// that will then emit the value up to the
|
|
23
|
+
// parent component
|
|
24
|
+
Object.defineProperty($mutable, 'valueComputed', {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: () => this.valueComputed,
|
|
27
|
+
set: (value) => (this.valueComputed = value),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* This function registers a trigger by setting its value to the componentTrigger property of the current object.
|
|
32
|
+
* @param {VueComponent} trigger - The trigger to be registered.
|
|
33
|
+
*/
|
|
19
34
|
const registerTrigger = (trigger) => {
|
|
20
35
|
if (!trigger) return;
|
|
21
36
|
this.componentTrigger = trigger;
|
|
22
37
|
};
|
|
23
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Registers content to be used in the children components by setting its value to the componentContent property of the current object.
|
|
41
|
+
* @param {any} content - The content to be registered.
|
|
42
|
+
*/
|
|
24
43
|
const registerContent = (content) => {
|
|
25
44
|
if (!content) return;
|
|
26
45
|
this.componentContent = content;
|
|
27
46
|
};
|
|
28
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Registers search to be used in the children components by setting its value to the componentSearch property of the current object.
|
|
50
|
+
* @param {any} search - The search to be registered.
|
|
51
|
+
*/
|
|
29
52
|
const registerSearch = (search) => {
|
|
30
53
|
if (!search) return;
|
|
31
54
|
this.componentSearch = search;
|
|
@@ -52,8 +75,7 @@ export default {
|
|
|
52
75
|
};
|
|
53
76
|
|
|
54
77
|
const emit = (value) => {
|
|
55
|
-
this
|
|
56
|
-
this.$emit('change', value);
|
|
78
|
+
this.valueComputed = value;
|
|
57
79
|
};
|
|
58
80
|
|
|
59
81
|
return {
|
|
@@ -63,8 +85,9 @@ export default {
|
|
|
63
85
|
componentContent: this.componentContent,
|
|
64
86
|
componentSearch: this.componentSearch,
|
|
65
87
|
items: this.items,
|
|
88
|
+
multiple: this.multiple,
|
|
66
89
|
search: this.search,
|
|
67
|
-
|
|
90
|
+
$mutable,
|
|
68
91
|
registerTrigger,
|
|
69
92
|
registerContent,
|
|
70
93
|
registerSearch,
|
|
@@ -79,22 +102,55 @@ export default {
|
|
|
79
102
|
},
|
|
80
103
|
|
|
81
104
|
props: {
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The value of the component. Can be a string, number, object, or array.
|
|
107
|
+
* @type {string|number|object|array}
|
|
108
|
+
* @default null
|
|
109
|
+
*/
|
|
110
|
+
modelValue: {
|
|
111
|
+
type: [String, Number, Object, Array],
|
|
84
112
|
default: null,
|
|
85
113
|
},
|
|
114
|
+
/**
|
|
115
|
+
* Determines whether the button will use its default atomic style (tailwind) or its default class
|
|
116
|
+
* @type {boolean}
|
|
117
|
+
* @values
|
|
118
|
+
* - true: The button will have no default style and can be fully customized with a custom class
|
|
119
|
+
* - false: The button will use its default atomic style (tailwind) and can be further customized with additional classes
|
|
120
|
+
* @default null
|
|
121
|
+
*/
|
|
86
122
|
headless: {
|
|
87
123
|
type: Boolean,
|
|
88
124
|
default: false,
|
|
89
125
|
},
|
|
126
|
+
/**
|
|
127
|
+
* The placement of the component relative to its trigger element.
|
|
128
|
+
* @type {string}
|
|
129
|
+
* @values 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'
|
|
130
|
+
* @default 'bottom-start'
|
|
131
|
+
*/
|
|
90
132
|
placement: {
|
|
91
133
|
type: String,
|
|
92
134
|
default: 'bottom-start',
|
|
93
135
|
},
|
|
136
|
+
/**
|
|
137
|
+
* Determines whether the component should be aligned to the right of its trigger element.
|
|
138
|
+
* @type {boolean}
|
|
139
|
+
* @default false
|
|
140
|
+
*/
|
|
94
141
|
right: {
|
|
95
142
|
type: Boolean,
|
|
96
143
|
default: false,
|
|
97
144
|
},
|
|
145
|
+
/**
|
|
146
|
+
* Determines whether the component should allow multiple selections.
|
|
147
|
+
* @type {boolean}
|
|
148
|
+
* @default false
|
|
149
|
+
*/
|
|
150
|
+
multiple: {
|
|
151
|
+
type: Boolean,
|
|
152
|
+
default: false,
|
|
153
|
+
},
|
|
98
154
|
},
|
|
99
155
|
|
|
100
156
|
data() {
|
|
@@ -103,6 +159,7 @@ export default {
|
|
|
103
159
|
componentSearch: null,
|
|
104
160
|
search: '',
|
|
105
161
|
items: [],
|
|
162
|
+
itemsChecked: [],
|
|
106
163
|
/**
|
|
107
164
|
* Explaining the need for the floatingUiMinWidth data
|
|
108
165
|
*
|
|
@@ -125,6 +182,16 @@ export default {
|
|
|
125
182
|
id() {
|
|
126
183
|
return `listbox-${this.componentId}`;
|
|
127
184
|
},
|
|
185
|
+
|
|
186
|
+
valueComputed: {
|
|
187
|
+
get() {
|
|
188
|
+
return this.modelValue;
|
|
189
|
+
},
|
|
190
|
+
set(newValue) {
|
|
191
|
+
this.$emit('update:modelValue', newValue);
|
|
192
|
+
this.$emit('change', newValue);
|
|
193
|
+
},
|
|
194
|
+
},
|
|
128
195
|
},
|
|
129
196
|
};
|
|
130
197
|
</script>
|
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
@keydown.enter.prevent="onClick"
|
|
17
17
|
@keydown.tab.prevent
|
|
18
18
|
>
|
|
19
|
+
<span v-if="apiListbox().multiple">
|
|
20
|
+
<input
|
|
21
|
+
v-model="apiListbox().$mutable.valueComputed"
|
|
22
|
+
:id="`${id}-checkbox`"
|
|
23
|
+
:value="value"
|
|
24
|
+
type="checkbox"
|
|
25
|
+
@click.stop
|
|
26
|
+
@change="onChange"
|
|
27
|
+
/>
|
|
28
|
+
</span>
|
|
19
29
|
<slot></slot>
|
|
20
30
|
<span v-if="wasSelected" class="ml-auto">
|
|
21
31
|
<IconCheckOutline class="text-secondary-200 h-5 w-5" />
|
|
@@ -75,7 +85,7 @@ export default {
|
|
|
75
85
|
wasSelected() {
|
|
76
86
|
return (
|
|
77
87
|
JSON.stringify(this.value) ===
|
|
78
|
-
JSON.stringify(this.apiListbox().
|
|
88
|
+
JSON.stringify(this.apiListbox().$mutable.valueComputed)
|
|
79
89
|
);
|
|
80
90
|
},
|
|
81
91
|
},
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<component
|
|
3
3
|
:is="as"
|
|
4
|
-
:class="
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}"
|
|
4
|
+
:class="[
|
|
5
|
+
headless ? 'listbox-label' : 'mb-2 block text-xs font-normal uppercase',
|
|
6
|
+
]"
|
|
8
7
|
>
|
|
9
8
|
<slot></slot>
|
|
10
9
|
</component>
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<div class="-mx-3 -mt-2">
|
|
3
3
|
<input
|
|
4
4
|
ref="search"
|
|
5
|
-
|
|
5
|
+
:value="modelValue"
|
|
6
6
|
v-bind="$attrs"
|
|
7
7
|
type="text"
|
|
8
8
|
class="leading-0 font-inherit w-full max-w-full appearance-none border-b border-solid border-gray-300 py-2 px-3 text-base text-inherit"
|
|
9
|
-
@input="
|
|
9
|
+
@input="onInput"
|
|
10
10
|
@click.stop
|
|
11
11
|
@keydown.down.prevent="focusNextItem"
|
|
12
12
|
@keydown.up.prevent="focusPreviousItem"
|
|
@@ -62,9 +62,9 @@ export default {
|
|
|
62
62
|
this.$nextTick(() => setTimeout(() => this.$refs.search.focus(), 150));
|
|
63
63
|
},
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
beforeUnmount() {
|
|
66
66
|
this.search = '';
|
|
67
|
-
this.$emit('
|
|
67
|
+
this.$emit('update:modelValue', '');
|
|
68
68
|
},
|
|
69
69
|
|
|
70
70
|
methods: {
|
|
@@ -111,6 +111,7 @@ export default {
|
|
|
111
111
|
|
|
112
112
|
// select new item
|
|
113
113
|
if (this.items[newSelectedIndex]) {
|
|
114
|
+
this.index = newSelectedIndex;
|
|
114
115
|
this.items[newSelectedIndex].select();
|
|
115
116
|
}
|
|
116
117
|
},
|
|
@@ -123,11 +124,11 @@ export default {
|
|
|
123
124
|
return this.items.findIndex((item) => item.isSelected());
|
|
124
125
|
},
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
onInput(event) {
|
|
127
128
|
this.index = 0;
|
|
128
129
|
if (this.item) this.item.select();
|
|
129
130
|
|
|
130
|
-
this.$emit('
|
|
131
|
+
this.$emit('update:modelValue', event.target.value);
|
|
131
132
|
},
|
|
132
133
|
|
|
133
134
|
onKeyEnter() {
|
|
@@ -41,6 +41,7 @@ export default {
|
|
|
41
41
|
|
|
42
42
|
data() {
|
|
43
43
|
return {
|
|
44
|
+
name: 'listbox-trigger',
|
|
44
45
|
expanded: false,
|
|
45
46
|
hasPopup: false,
|
|
46
47
|
};
|
|
@@ -123,6 +124,7 @@ export default {
|
|
|
123
124
|
|
|
124
125
|
onClick(e) {
|
|
125
126
|
this.init(e);
|
|
127
|
+
this.$emit('click');
|
|
126
128
|
},
|
|
127
129
|
|
|
128
130
|
onKeyDownOrUp(e) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FloatingUi
|
|
3
|
-
:id="id"
|
|
4
3
|
:visible="visible"
|
|
4
|
+
:id="id"
|
|
5
5
|
:headless="headless"
|
|
6
|
-
:
|
|
7
|
-
|
|
6
|
+
:class="{ 'popover-content': headless }"
|
|
7
|
+
:floating-ui-class="floatingUiClass"
|
|
8
8
|
>
|
|
9
9
|
<slot></slot>
|
|
10
10
|
</FloatingUi>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// default styles
|
|
6
6
|
headless
|
|
7
7
|
? 'popover-item'
|
|
8
|
-
: 'relative z-10 -mx-3 flex items-center gap-2 px-3 py-2 text-inherit no-underline
|
|
8
|
+
: 'hover:bg-secondary-200/10 relative z-10 -mx-3 flex items-center gap-2 px-3 py-2 text-inherit no-underline',
|
|
9
9
|
]"
|
|
10
10
|
@click="onClick"
|
|
11
11
|
>
|
|
@@ -44,7 +44,11 @@ export default {
|
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
as() {
|
|
47
|
-
return this.href
|
|
47
|
+
return this.href
|
|
48
|
+
? 'a'
|
|
49
|
+
: this.to
|
|
50
|
+
? resolveComponent('NuxtLink')
|
|
51
|
+
: 'button';
|
|
48
52
|
},
|
|
49
53
|
},
|
|
50
54
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
]"
|
|
8
8
|
role="progressbar"
|
|
9
9
|
aria-valuemin="0"
|
|
10
|
-
aria-valuemax="
|
|
10
|
+
:aria-valuemax="max"
|
|
11
11
|
:aria-valuenow="value"
|
|
12
12
|
:aria-label="label"
|
|
13
13
|
>
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
:class="[
|
|
16
16
|
headless
|
|
17
17
|
? 'progress-bar__indicator'
|
|
18
|
-
: 'absolute left-0 h-full
|
|
18
|
+
: 'bg-secondary-200 absolute left-0 h-full transition-all',
|
|
19
19
|
]"
|
|
20
|
-
:style="{ width: `${
|
|
20
|
+
:style="{ width: `${percentageComputed}%` }"
|
|
21
21
|
></div>
|
|
22
22
|
</div>
|
|
23
23
|
</template>
|
|
@@ -37,6 +37,24 @@ export default {
|
|
|
37
37
|
type: [String, Number],
|
|
38
38
|
default: 0,
|
|
39
39
|
},
|
|
40
|
+
max: {
|
|
41
|
+
type: [String, Number],
|
|
42
|
+
default: 100,
|
|
43
|
+
},
|
|
44
|
+
percentage: {
|
|
45
|
+
type: [String, Number],
|
|
46
|
+
default: null,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
computed: {
|
|
51
|
+
percentageComputed() {
|
|
52
|
+
if (typeof this.percentage !== 'undefined' && this.percentage !== null) {
|
|
53
|
+
return this.percentage;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (this.value / this.max) * 100;
|
|
57
|
+
},
|
|
40
58
|
},
|
|
41
59
|
};
|
|
42
60
|
</script>
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
]"
|
|
19
19
|
role="tab"
|
|
20
20
|
type="button"
|
|
21
|
-
@click.stop="onClick"
|
|
21
|
+
@click.prevent.stop="onClick"
|
|
22
22
|
@keydown="onKeyDown"
|
|
23
23
|
@blur="onBlur"
|
|
24
24
|
>
|
|
25
|
-
<slot></slot>
|
|
25
|
+
<slot :selected="selected"></slot>
|
|
26
26
|
</button>
|
|
27
27
|
</template>
|
|
28
28
|
|
|
@@ -32,7 +32,7 @@ import { keys } from '../../utils/keyboard';
|
|
|
32
32
|
export default {
|
|
33
33
|
name: 'VTTabItem',
|
|
34
34
|
|
|
35
|
-
inject: ['
|
|
35
|
+
inject: ['apiTabs'],
|
|
36
36
|
|
|
37
37
|
props: {
|
|
38
38
|
headless: {
|
|
@@ -43,7 +43,7 @@ export default {
|
|
|
43
43
|
|
|
44
44
|
data() {
|
|
45
45
|
return {
|
|
46
|
-
api: this.
|
|
46
|
+
api: this.apiTabs(),
|
|
47
47
|
index: null,
|
|
48
48
|
indexFocus: null,
|
|
49
49
|
selected: false,
|
|
@@ -60,7 +60,7 @@ export default {
|
|
|
60
60
|
this.api.registerTab(this);
|
|
61
61
|
},
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
beforeUnmount() {
|
|
64
64
|
this.api.unregisterTab(this.index);
|
|
65
65
|
},
|
|
66
66
|
|
|
@@ -106,6 +106,7 @@ export default {
|
|
|
106
106
|
onClick() {
|
|
107
107
|
this.api.selectTab(this.index);
|
|
108
108
|
this.$emit('change');
|
|
109
|
+
this.$emit('click');
|
|
109
110
|
},
|
|
110
111
|
|
|
111
112
|
onKeyDown(event) {
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<style scoped>
|
|
8
|
-
.TabGroup.vertical{
|
|
8
|
+
.TabGroup.vertical {
|
|
9
9
|
display: flex;
|
|
10
10
|
}
|
|
11
|
-
.TabGroup.vertical .TabList{
|
|
11
|
+
.TabGroup.vertical .TabList {
|
|
12
12
|
display: flex;
|
|
13
13
|
flex-direction: column;
|
|
14
14
|
}
|
|
@@ -17,15 +17,17 @@
|
|
|
17
17
|
<script>
|
|
18
18
|
export default {
|
|
19
19
|
name: 'VTTabGroup',
|
|
20
|
+
|
|
20
21
|
props: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
vertical: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: false,
|
|
25
|
+
},
|
|
25
26
|
},
|
|
27
|
+
|
|
26
28
|
provide() {
|
|
27
29
|
return {
|
|
28
|
-
|
|
30
|
+
apiTabs: () => {
|
|
29
31
|
const registerTab = (tab) => {
|
|
30
32
|
_register(this.tabs, tab);
|
|
31
33
|
if (tab.index === 0) tab.select();
|
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
export default {
|
|
15
15
|
name: 'VTTabPanel',
|
|
16
16
|
|
|
17
|
-
inject: ['
|
|
17
|
+
inject: ['apiTabs'],
|
|
18
18
|
|
|
19
19
|
data() {
|
|
20
20
|
return {
|
|
21
|
-
api: this.api(),
|
|
22
21
|
index: null,
|
|
23
22
|
visible: false,
|
|
24
23
|
};
|
|
@@ -31,11 +30,11 @@ export default {
|
|
|
31
30
|
},
|
|
32
31
|
|
|
33
32
|
mounted() {
|
|
34
|
-
this.
|
|
33
|
+
this.apiTabs().registerTabPanel(this);
|
|
35
34
|
},
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
this.
|
|
36
|
+
beforeUnmount() {
|
|
37
|
+
this.apiTabs().unregisterTabPanel(this.id);
|
|
39
38
|
},
|
|
40
39
|
|
|
41
40
|
methods: {
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
<div
|
|
3
3
|
:id="id"
|
|
4
4
|
:aria-describedby="ariaDescribedBy"
|
|
5
|
-
class="inline-flex"
|
|
6
5
|
@mouseenter="onMouseenter"
|
|
7
|
-
@mouseleave="
|
|
6
|
+
@mouseleave="onmouseout"
|
|
8
7
|
>
|
|
9
8
|
<slot />
|
|
10
9
|
</div>
|
|
@@ -55,7 +54,7 @@ export default {
|
|
|
55
54
|
}, this.apiTooltip().delayDuration);
|
|
56
55
|
},
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
onmouseout() {
|
|
59
58
|
clearTimeout(tooltipTriggerTimeout);
|
|
60
59
|
this.cancel();
|
|
61
60
|
},
|
|
@@ -75,8 +74,7 @@ export default {
|
|
|
75
74
|
// delay stop propagation to close other visible
|
|
76
75
|
// dropdowns and delay click event to control
|
|
77
76
|
// this dropdown visibility
|
|
78
|
-
|
|
79
|
-
setTimeout(() => this.showComponentContent(), 100);
|
|
77
|
+
this.showComponentContent();
|
|
80
78
|
},
|
|
81
79
|
|
|
82
80
|
cancel() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<transition
|
|
3
3
|
enter-active-class="duration-300 ease-out"
|
|
4
|
-
enter-class="transform opacity-0"
|
|
4
|
+
enter-from-class="transform opacity-0"
|
|
5
5
|
enter-to-class="opacity-100"
|
|
6
6
|
leave-active-class="duration-300 ease-in"
|
|
7
|
-
leave-class="opacity-100"
|
|
7
|
+
leave-from-class="opacity-100"
|
|
8
8
|
leave-to-class="transform opacity-0"
|
|
9
9
|
@after-enter="afterEnter"
|
|
10
10
|
@after-leave="afterLeave"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<Teleport to="body">
|
|
3
3
|
<transition
|
|
4
4
|
enter-active-class="duration-200 ease-out"
|
|
5
|
-
enter-class="
|
|
6
|
-
enter-to-class="
|
|
5
|
+
:enter-from-class="transitionEnterClass"
|
|
6
|
+
:enter-to-class="transitionEnterToClass"
|
|
7
7
|
leave-active-class="duration-200 ease-in"
|
|
8
|
-
leave-class="
|
|
9
|
-
leave-to-class="
|
|
8
|
+
:leave-from-class="transitionLeaveClass"
|
|
9
|
+
:leave-to-class="transitionLeaveToClass"
|
|
10
10
|
@after-leave="hidden"
|
|
11
11
|
@after-enter="shown"
|
|
12
12
|
>
|
|
@@ -15,23 +15,19 @@
|
|
|
15
15
|
:class="[
|
|
16
16
|
headless
|
|
17
17
|
? `${this.component}-content`
|
|
18
|
-
: `
|
|
18
|
+
: `absolute z-50 grid overflow-hidden rounded-md shadow-md ${this.classes} ${this.portalClass}`,
|
|
19
19
|
]"
|
|
20
20
|
v-bind="$attrs"
|
|
21
21
|
>
|
|
22
22
|
<slot />
|
|
23
23
|
</div>
|
|
24
24
|
</transition>
|
|
25
|
-
</
|
|
25
|
+
</Teleport>
|
|
26
26
|
</template>
|
|
27
27
|
|
|
28
28
|
<script>
|
|
29
|
-
import { Portal } from '@linusborg/vue-simple-portal';
|
|
30
|
-
|
|
31
29
|
export default {
|
|
32
|
-
|
|
33
|
-
Portal,
|
|
34
|
-
},
|
|
30
|
+
inheritAttrs: false,
|
|
35
31
|
|
|
36
32
|
props: {
|
|
37
33
|
component: {
|
|
@@ -46,6 +42,10 @@ export default {
|
|
|
46
42
|
type: Boolean,
|
|
47
43
|
default: false,
|
|
48
44
|
},
|
|
45
|
+
ariaActivedescendant: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: null,
|
|
48
|
+
},
|
|
49
49
|
portalClass: {
|
|
50
50
|
type: [String, Function],
|
|
51
51
|
default: null,
|
|
@@ -58,7 +58,25 @@ export default {
|
|
|
58
58
|
},
|
|
59
59
|
|
|
60
60
|
classes() {
|
|
61
|
-
return this.isTooltip
|
|
61
|
+
return this.isTooltip
|
|
62
|
+
? 'bg-gray-800 text-sm text-white py-1 px-2'
|
|
63
|
+
: 'bg-white py-2 px-3';
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
transitionEnterClass() {
|
|
67
|
+
return this.isTooltip ? 'opacity-0' : 'translate-y-[15px] opacity-0';
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
transitionEnterToClass() {
|
|
71
|
+
return this.isTooltip ? 'opacity-100' : 'translate-y-0 opacity-100';
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
transitionLeaveClass() {
|
|
75
|
+
return this.transitionEnterToClass;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
transitionLeaveToClass() {
|
|
79
|
+
return this.transitionEnterClass;
|
|
62
80
|
},
|
|
63
81
|
},
|
|
64
82
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {HTMLElement} el
|
|
4
|
+
* @param {HTMLElement} parent
|
|
5
|
+
*/
|
|
6
|
+
export const scrollElementIntoView = (el, parent) => {
|
|
7
|
+
// this works better than scrollIntoView
|
|
8
|
+
if (parent.scrollHeight <= parent.clientHeight) return;
|
|
9
|
+
|
|
10
|
+
const scrollBottom = parent.clientHeight + parent.scrollTop;
|
|
11
|
+
const elBottom = el.offsetTop + el.offsetHeight;
|
|
12
|
+
|
|
13
|
+
if (elBottom > scrollBottom) {
|
|
14
|
+
parent.scrollTop = elBottom - parent.clientHeight;
|
|
15
|
+
} else if (el.offsetTop < parent.scrollTop) {
|
|
16
|
+
parent.scrollTop = el.offsetTop;
|
|
17
|
+
}
|
|
18
|
+
};
|