@veritree/ui 0.19.2-20 → 0.19.2-22
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/mixins/floating-ui-content.js +1 -22
- package/mixins/floating-ui-item.js +93 -46
- package/mixins/floating-ui.js +5 -12
- package/package.json +1 -1
- package/src/components/Alert/VTAlert.vue +55 -14
- package/src/components/Dialog/VTDialog.vue +13 -11
- package/src/components/Dialog/VTDialogClose.vue +13 -19
- package/src/components/Dialog/VTDialogContent.vue +19 -14
- package/src/components/Dialog/VTDialogFooter.vue +9 -14
- package/src/components/Dialog/VTDialogHeader.vue +11 -13
- package/src/components/Dialog/VTDialogMain.vue +6 -13
- package/src/components/Dialog/VTDialogOverlay.vue +9 -13
- package/src/components/Dialog/VTDialogTitle.vue +8 -5
- package/src/components/Disclosure/VTDisclosureHeader.vue +1 -1
- package/src/components/DropdownMenu/VTDropdownMenu.vue +19 -0
- package/src/components/DropdownMenu/VTDropdownMenuContent.vue +14 -6
- package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
- package/src/components/DropdownMenu/VTDropdownMenuItem.vue +3 -7
- package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
- package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +4 -9
- package/src/components/Listbox/VTListbox.vue +105 -14
- package/src/components/Listbox/VTListboxContent.vue +3 -7
- package/src/components/Listbox/VTListboxItem.vue +127 -6
- package/src/components/Listbox/VTListboxLabel.vue +3 -4
- package/src/components/Listbox/VTListboxList.vue +3 -24
- package/src/components/Listbox/VTListboxSearch.vue +60 -53
- package/src/components/Listbox/VTListboxTrigger.vue +12 -6
- package/src/components/Popover/VTPopover.vue +19 -0
- 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 +13 -11
- package/src/components/Tooltip/VTTooltip.vue +65 -0
- package/src/components/Tooltip/VTTooltipContent.vue +59 -0
- package/src/components/Tooltip/VTTooltipTrigger.vue +98 -0
- package/src/components/Utils/FloatingUi.vue +52 -17
- 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
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
<component
|
|
3
3
|
:is="as"
|
|
4
4
|
:id="id"
|
|
5
|
-
:class="
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
:class="[
|
|
6
|
+
headless
|
|
7
|
+
? 'dialog-header'
|
|
8
|
+
: '-mx-4 -mt-4 flex items-center justify-between gap-x-3 p-4 md:-mx-6 md:-mt-6 md:p-6',
|
|
9
|
+
]"
|
|
10
|
+
@click.stop
|
|
9
11
|
>
|
|
10
12
|
<slot></slot>
|
|
11
13
|
</component>
|
|
@@ -18,6 +20,10 @@ export default {
|
|
|
18
20
|
inject: ['apiDialog'],
|
|
19
21
|
|
|
20
22
|
props: {
|
|
23
|
+
headless: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
},
|
|
21
27
|
as: {
|
|
22
28
|
type: String,
|
|
23
29
|
default: 'header',
|
|
@@ -25,16 +31,8 @@ export default {
|
|
|
25
31
|
},
|
|
26
32
|
|
|
27
33
|
computed: {
|
|
28
|
-
dark() {
|
|
29
|
-
return this.apiDialog().isDark;
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
headless() {
|
|
33
|
-
return this.apiDialog().isHeadless;
|
|
34
|
-
},
|
|
35
|
-
|
|
36
34
|
id() {
|
|
37
|
-
return
|
|
35
|
+
return `dialog-header-${this.apiDialog().componentId}`;
|
|
38
36
|
},
|
|
39
37
|
},
|
|
40
38
|
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
<component
|
|
3
3
|
:is="as"
|
|
4
4
|
:id="id"
|
|
5
|
-
:class="
|
|
6
|
-
'Dialog-body': headless,
|
|
7
|
-
'flex-1 w-full h-full overflow-y-auto': !headless,
|
|
8
|
-
}"
|
|
5
|
+
:class="[headless ? 'dialog-body' : 'h-full flex-1 overflow-y-auto']"
|
|
9
6
|
>
|
|
10
7
|
<slot></slot>
|
|
11
8
|
</component>
|
|
@@ -18,6 +15,10 @@ export default {
|
|
|
18
15
|
inject: ['apiDialog'],
|
|
19
16
|
|
|
20
17
|
props: {
|
|
18
|
+
headless: {
|
|
19
|
+
type: Boolean,
|
|
20
|
+
default: false,
|
|
21
|
+
},
|
|
21
22
|
as: {
|
|
22
23
|
type: String,
|
|
23
24
|
default: 'main',
|
|
@@ -25,16 +26,8 @@ export default {
|
|
|
25
26
|
},
|
|
26
27
|
|
|
27
28
|
computed: {
|
|
28
|
-
dark() {
|
|
29
|
-
return this.apiDialog().isDark;
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
headless() {
|
|
33
|
-
return this.apiDialog().isHeadless;
|
|
34
|
-
},
|
|
35
|
-
|
|
36
29
|
id() {
|
|
37
|
-
return
|
|
30
|
+
return `dialog-main-${this.apiDialog().componentId}`;
|
|
38
31
|
},
|
|
39
32
|
},
|
|
40
33
|
|
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
<div
|
|
4
4
|
v-if="visible"
|
|
5
5
|
:id="id"
|
|
6
|
-
:class="
|
|
7
|
-
|
|
8
|
-
'bg-primary-200/80 fixed inset-0': !headless,
|
|
9
|
-
}"
|
|
10
|
-
></div>
|
|
6
|
+
:class="[headless ? 'dialog-overlay' : 'bg-primary-200/80 fixed inset-0']"
|
|
7
|
+
/>
|
|
11
8
|
</FadeInOut>
|
|
12
9
|
</template>
|
|
13
10
|
|
|
@@ -23,6 +20,13 @@ export default {
|
|
|
23
20
|
|
|
24
21
|
inject: ['apiDialog'],
|
|
25
22
|
|
|
23
|
+
props: {
|
|
24
|
+
headless: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
|
|
26
30
|
data() {
|
|
27
31
|
return {
|
|
28
32
|
visible: false,
|
|
@@ -33,14 +37,6 @@ export default {
|
|
|
33
37
|
id() {
|
|
34
38
|
return `dialog-overlay-${this.apiDialog().componentId}`;
|
|
35
39
|
},
|
|
36
|
-
|
|
37
|
-
dark() {
|
|
38
|
-
return this.apiDialog().isDark;
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
headless() {
|
|
42
|
-
return this.apiDialog().isHeadless;
|
|
43
|
-
},
|
|
44
40
|
},
|
|
45
41
|
|
|
46
42
|
mounted() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
3
|
:id="id"
|
|
4
|
-
:class="
|
|
4
|
+
:class="[headless ? 'dialog-header' : 'text-2xl font-semibold']"
|
|
5
5
|
>
|
|
6
6
|
<slot></slot
|
|
7
7
|
></span>
|
|
@@ -13,13 +13,16 @@ export default {
|
|
|
13
13
|
|
|
14
14
|
inject: ['apiDialog'],
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
headless
|
|
18
|
-
|
|
16
|
+
props: {
|
|
17
|
+
headless: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
19
20
|
},
|
|
21
|
+
},
|
|
20
22
|
|
|
23
|
+
computed: {
|
|
21
24
|
id() {
|
|
22
|
-
return
|
|
25
|
+
return `dialog-overlay-${this.apiDialog().componentId}`;
|
|
23
26
|
},
|
|
24
27
|
},
|
|
25
28
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
:class="[
|
|
5
5
|
headless
|
|
6
6
|
? 'details-header'
|
|
7
|
-
: 'flex cursor-pointer justify-between gap-3
|
|
7
|
+
: 'text-body flex cursor-pointer justify-between gap-3 font-semibold',
|
|
8
8
|
]"
|
|
9
9
|
:aria-controls="ariaControls"
|
|
10
10
|
:aria-expanded="String(ariaExpanded)"
|
|
@@ -56,12 +56,31 @@ export default {
|
|
|
56
56
|
type: Boolean,
|
|
57
57
|
default: false,
|
|
58
58
|
},
|
|
59
|
+
placement: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: 'bottom-start',
|
|
62
|
+
},
|
|
59
63
|
},
|
|
60
64
|
|
|
61
65
|
data() {
|
|
62
66
|
return {
|
|
63
67
|
componentId: genId(),
|
|
64
68
|
items: [],
|
|
69
|
+
/**
|
|
70
|
+
* Explaining the need for the floatingUiMinWidth data
|
|
71
|
+
*
|
|
72
|
+
* The floating ui is a result of two items:
|
|
73
|
+
*
|
|
74
|
+
* 1. Trigger: the action button
|
|
75
|
+
* 2. Content: the popper/wrapper that appears after triggering the action button
|
|
76
|
+
*
|
|
77
|
+
* By default, the content will match the triggers width.
|
|
78
|
+
* The problem with this is that the trigger width
|
|
79
|
+
* might be too small causing the content to not fit
|
|
80
|
+
* what is inside it properly. So, to avoid this,
|
|
81
|
+
* a min width is needed.
|
|
82
|
+
*/
|
|
83
|
+
floatingUiMinWidth: 200,
|
|
65
84
|
};
|
|
66
85
|
},
|
|
67
86
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FloatingUi
|
|
3
|
-
:visible="visible"
|
|
4
3
|
:id="id"
|
|
4
|
+
:visible="visible"
|
|
5
5
|
:headless="headless"
|
|
6
|
-
|
|
7
|
-
:floating-ui-class="floatingUiClass"
|
|
6
|
+
component="dropdown"
|
|
8
7
|
>
|
|
9
8
|
<slot></slot>
|
|
10
9
|
</FloatingUi>
|
|
@@ -16,6 +15,8 @@ import { floatingUiContentMixin } from '../../../mixins/floating-ui-content';
|
|
|
16
15
|
export default {
|
|
17
16
|
name: 'VTDropdownMenuContent',
|
|
18
17
|
|
|
18
|
+
inheritAttrs: false,
|
|
19
|
+
|
|
19
20
|
mixins: [floatingUiContentMixin],
|
|
20
21
|
|
|
21
22
|
inject: ['apiDropdownMenu'],
|
|
@@ -39,13 +40,20 @@ export default {
|
|
|
39
40
|
id: this.id,
|
|
40
41
|
hide: this.hide,
|
|
41
42
|
show: this.show,
|
|
42
|
-
getMousemove: this.getMousemove,
|
|
43
|
-
setMousemove: this.setMousemove,
|
|
44
|
-
unsetMousemove: this.unsetMousemove,
|
|
45
43
|
setActiveDescedant: this.setActiveDescedant,
|
|
46
44
|
};
|
|
47
45
|
|
|
48
46
|
this.apiDropdownMenu().registerContent(content);
|
|
49
47
|
},
|
|
48
|
+
|
|
49
|
+
methods: {
|
|
50
|
+
hidden() {
|
|
51
|
+
this.$emit('hidden');
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
shown() {
|
|
55
|
+
this.$emit('shown');
|
|
56
|
+
},
|
|
57
|
+
},
|
|
50
58
|
};
|
|
51
59
|
</script>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
:class="
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}"
|
|
3
|
+
:class="[
|
|
4
|
+
headless ? 'dropdown-menu-divider' : '-mx-3 my-2 h-[1px] bg-gray-200',
|
|
5
|
+
]"
|
|
7
6
|
></div>
|
|
8
7
|
</template>
|
|
9
8
|
|
|
@@ -13,18 +12,10 @@ export default {
|
|
|
13
12
|
|
|
14
13
|
inject: ['apiDropdownMenu'],
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
computed: {
|
|
22
|
-
dark() {
|
|
23
|
-
return this.apiDropdownMenu().isDark;
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
headless() {
|
|
27
|
-
return this.apiDropdownMenu().isHeadless;
|
|
15
|
+
props: {
|
|
16
|
+
headless: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
default: false,
|
|
28
19
|
},
|
|
29
20
|
},
|
|
30
21
|
};
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
class="-mx-3"
|
|
10
10
|
role="menuitem"
|
|
11
11
|
@click.stop.prevent="onClick"
|
|
12
|
-
@keydown.down.prevent="
|
|
13
|
-
@keydown.up.prevent="
|
|
12
|
+
@keydown.down.prevent="focusNextItem"
|
|
13
|
+
@keydown.up.prevent="focusPreviousItem"
|
|
14
14
|
@keydown.home.prevent="focusFirstItem"
|
|
15
15
|
@keydown.end.prevent="focusLastItem"
|
|
16
16
|
@keydown.esc.prevent="onKeyEsc"
|
|
@@ -51,11 +51,7 @@ export default {
|
|
|
51
51
|
|
|
52
52
|
computed: {
|
|
53
53
|
as() {
|
|
54
|
-
return this.href
|
|
55
|
-
? 'a'
|
|
56
|
-
: this.to
|
|
57
|
-
? resolveComponent('NuxtLink')
|
|
58
|
-
: 'button';
|
|
54
|
+
return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
|
|
59
55
|
},
|
|
60
56
|
},
|
|
61
57
|
};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span
|
|
3
|
-
:class="
|
|
4
|
-
MenuLabel: headless,
|
|
5
|
-
'mb-2 block text-xs uppercase': !headless,
|
|
6
|
-
'text-inherit': !dark,
|
|
7
|
-
'text-white': dark,
|
|
8
|
-
}"
|
|
3
|
+
:class="[headless ? 'dropdown-menu-label' : 'mb-2 block text-xs uppercase']"
|
|
9
4
|
>
|
|
10
5
|
<slot></slot>
|
|
11
6
|
</span>
|
|
@@ -18,10 +13,6 @@ export default {
|
|
|
18
13
|
inject: ['apiDropdownMenu'],
|
|
19
14
|
|
|
20
15
|
computed: {
|
|
21
|
-
dark() {
|
|
22
|
-
return this.apiDropdownMenu().isDark;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
16
|
headless() {
|
|
26
17
|
return this.apiDropdownMenu().isHeadless;
|
|
27
18
|
},
|
|
@@ -24,14 +24,13 @@ export default {
|
|
|
24
24
|
hasPopup: false,
|
|
25
25
|
controls: null,
|
|
26
26
|
trigger: null,
|
|
27
|
-
id: null,
|
|
28
27
|
};
|
|
29
28
|
},
|
|
30
29
|
|
|
31
30
|
computed: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
id() {
|
|
32
|
+
return `dropdown-menu-trigger-${this.apiDropdownMenu().id}`;
|
|
33
|
+
},
|
|
35
34
|
|
|
36
35
|
componentContent() {
|
|
37
36
|
return this.apiDropdownMenu().componentContent;
|
|
@@ -57,8 +56,6 @@ export default {
|
|
|
57
56
|
},
|
|
58
57
|
|
|
59
58
|
mounted() {
|
|
60
|
-
this.id = `dropdown-menu-trigger-${this.apiDropdownMenu().id}`;
|
|
61
|
-
|
|
62
59
|
const trigger = {
|
|
63
60
|
id: this.id,
|
|
64
61
|
el: this.$el,
|
|
@@ -92,9 +89,7 @@ export default {
|
|
|
92
89
|
* errors related to adding the event listener.
|
|
93
90
|
*/
|
|
94
91
|
addTriggerEvents() {
|
|
95
|
-
this.trigger.addEventListener('click',
|
|
96
|
-
this.onClick(e);
|
|
97
|
-
});
|
|
92
|
+
this.trigger.addEventListener('click', this.onClick);
|
|
98
93
|
},
|
|
99
94
|
|
|
100
95
|
init(e) {
|
|
@@ -16,26 +16,44 @@ 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
|
-
this.
|
|
54
|
+
this.componentSearch = search;
|
|
32
55
|
};
|
|
33
56
|
|
|
34
|
-
// const registerList = (list) => {
|
|
35
|
-
// if (!list) return;
|
|
36
|
-
// this.list = list;
|
|
37
|
-
// };
|
|
38
|
-
|
|
39
57
|
const registerItem = (item) => {
|
|
40
58
|
if (!item) return;
|
|
41
59
|
this.items.push(item);
|
|
@@ -46,9 +64,18 @@ export default {
|
|
|
46
64
|
this.items.splice(index, 1);
|
|
47
65
|
};
|
|
48
66
|
|
|
67
|
+
const pushSearch = (key) => {
|
|
68
|
+
key === 'Backspace' && this.search.length
|
|
69
|
+
? (this.search = this.search.slice(0, -1))
|
|
70
|
+
: (this.search += key);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const clearSearch = () => {
|
|
74
|
+
this.search = '';
|
|
75
|
+
};
|
|
76
|
+
|
|
49
77
|
const emit = (value) => {
|
|
50
|
-
this
|
|
51
|
-
this.$emit('change', value);
|
|
78
|
+
this.valueComputed = value;
|
|
52
79
|
};
|
|
53
80
|
|
|
54
81
|
return {
|
|
@@ -56,14 +83,18 @@ export default {
|
|
|
56
83
|
component: this.component,
|
|
57
84
|
componentTrigger: this.componentTrigger,
|
|
58
85
|
componentContent: this.componentContent,
|
|
86
|
+
componentSearch: this.componentSearch,
|
|
59
87
|
items: this.items,
|
|
88
|
+
multiple: this.multiple,
|
|
60
89
|
search: this.search,
|
|
90
|
+
$mutable,
|
|
61
91
|
registerTrigger,
|
|
62
92
|
registerContent,
|
|
63
93
|
registerSearch,
|
|
64
|
-
// registerList,
|
|
65
94
|
registerItem,
|
|
66
95
|
unregisterItem,
|
|
96
|
+
pushSearch,
|
|
97
|
+
clearSearch,
|
|
67
98
|
emit,
|
|
68
99
|
};
|
|
69
100
|
},
|
|
@@ -71,19 +102,52 @@ export default {
|
|
|
71
102
|
},
|
|
72
103
|
|
|
73
104
|
props: {
|
|
74
|
-
|
|
75
|
-
|
|
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],
|
|
76
112
|
default: null,
|
|
77
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
|
+
*/
|
|
78
122
|
headless: {
|
|
79
123
|
type: Boolean,
|
|
80
124
|
default: false,
|
|
81
125
|
},
|
|
82
|
-
|
|
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
|
+
*/
|
|
132
|
+
placement: {
|
|
133
|
+
type: String,
|
|
134
|
+
default: 'bottom-start',
|
|
135
|
+
},
|
|
136
|
+
/**
|
|
137
|
+
* Determines whether the component should be aligned to the right of its trigger element.
|
|
138
|
+
* @type {boolean}
|
|
139
|
+
* @default false
|
|
140
|
+
*/
|
|
141
|
+
right: {
|
|
83
142
|
type: Boolean,
|
|
84
143
|
default: false,
|
|
85
144
|
},
|
|
86
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Determines whether the component should allow multiple selections.
|
|
147
|
+
* @type {boolean}
|
|
148
|
+
* @default false
|
|
149
|
+
*/
|
|
150
|
+
multiple: {
|
|
87
151
|
type: Boolean,
|
|
88
152
|
default: false,
|
|
89
153
|
},
|
|
@@ -92,8 +156,25 @@ export default {
|
|
|
92
156
|
data() {
|
|
93
157
|
return {
|
|
94
158
|
componentId: genId(),
|
|
95
|
-
|
|
159
|
+
componentSearch: null,
|
|
160
|
+
search: '',
|
|
96
161
|
items: [],
|
|
162
|
+
itemsChecked: [],
|
|
163
|
+
/**
|
|
164
|
+
* Explaining the need for the floatingUiMinWidth data
|
|
165
|
+
*
|
|
166
|
+
* The floating ui is a result of two items:
|
|
167
|
+
*
|
|
168
|
+
* 1. Trigger: the action button
|
|
169
|
+
* 2. Content: the popper/wrapper that appears after triggering the action button
|
|
170
|
+
*
|
|
171
|
+
* By default, the content will match the triggers width.
|
|
172
|
+
* The problem with this is that the trigger width
|
|
173
|
+
* might be too small causing the content to not fit
|
|
174
|
+
* what is inside it properly. So, to avoid this,
|
|
175
|
+
* a min width is needed.
|
|
176
|
+
*/
|
|
177
|
+
floatingUiMinWidth: 200,
|
|
97
178
|
};
|
|
98
179
|
},
|
|
99
180
|
|
|
@@ -101,6 +182,16 @@ export default {
|
|
|
101
182
|
id() {
|
|
102
183
|
return `listbox-${this.componentId}`;
|
|
103
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
|
+
},
|
|
104
195
|
},
|
|
105
196
|
};
|
|
106
197
|
</script>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FloatingUi
|
|
3
|
-
:visible="visible"
|
|
4
3
|
:id="id"
|
|
5
|
-
:
|
|
4
|
+
:visible="visible"
|
|
6
5
|
:headless="headless"
|
|
7
|
-
:
|
|
8
|
-
|
|
6
|
+
:aria-activedescendant="activeDescedant"
|
|
7
|
+
component="listbox"
|
|
9
8
|
role="listbox"
|
|
10
9
|
>
|
|
11
10
|
<slot></slot>
|
|
@@ -47,9 +46,6 @@ export default {
|
|
|
47
46
|
id: this.id,
|
|
48
47
|
show: this.show,
|
|
49
48
|
hide: this.hide,
|
|
50
|
-
getMousemove: this.getMousemove,
|
|
51
|
-
setMousemove: this.setMousemove,
|
|
52
|
-
unsetMousemove: this.unsetMousemove,
|
|
53
49
|
setActiveDescedant: this.setActiveDescedant,
|
|
54
50
|
};
|
|
55
51
|
|