@veritree/ui 0.19.2 → 0.20.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 -68
- package/mixins/floating-ui-content.js +81 -0
- package/mixins/floating-ui-item.js +266 -0
- package/mixins/floating-ui.js +67 -0
- package/mixins/form-control-icon.js +53 -0
- package/mixins/form-control.js +71 -0
- package/nuxt.js +30 -23
- package/package.json +9 -4
- package/src/components/Alert/VTAlert.vue +55 -14
- package/src/components/Avatar/VTAvatar.vue +32 -29
- package/src/components/Button/VTButton.vue +9 -6
- 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 -32
- package/src/components/Dialog/VTDialogClose.vue +19 -25
- package/src/components/Dialog/VTDialogContent.vue +24 -19
- package/src/components/Dialog/VTDialogFooter.vue +11 -16
- package/src/components/Dialog/VTDialogHeader.vue +16 -18
- package/src/components/Dialog/VTDialogMain.vue +11 -18
- package/src/components/Dialog/VTDialogOverlay.vue +14 -18
- package/src/components/Dialog/VTDialogTitle.vue +10 -7
- 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 +14 -16
- package/src/components/Drawer/VTDrawerClose.vue +9 -9
- package/src/components/Drawer/VTDrawerContent.vue +8 -8
- package/src/components/Drawer/VTDrawerFooter.vue +3 -3
- 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 +45 -28
- package/src/components/DropdownMenu/VTDropdownMenuContent.vue +29 -64
- package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +8 -14
- package/src/components/DropdownMenu/VTDropdownMenuItem.vue +11 -124
- package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +3 -12
- package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +91 -121
- package/src/components/Form/VTFormFeedback.vue +39 -22
- 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 +40 -0
- package/src/components/Form/VTInputIcon.vue +35 -0
- package/src/components/Form/VTInputPassword.vue +55 -0
- package/src/components/Form/VTTextarea.vue +22 -0
- package/src/components/Listbox/VTListbox.vue +122 -50
- package/src/components/Listbox/VTListboxContent.vue +20 -116
- package/src/components/Listbox/VTListboxItem.vue +115 -166
- package/src/components/Listbox/VTListboxLabel.vue +3 -14
- package/src/components/Listbox/VTListboxList.vue +10 -40
- package/src/components/Listbox/VTListboxSearch.vue +76 -68
- package/src/components/Listbox/VTListboxTrigger.vue +75 -86
- package/src/components/Popover/VTPopover.vue +42 -29
- package/src/components/Popover/VTPopoverContent.vue +24 -59
- package/src/components/Popover/VTPopoverDivider.vue +4 -11
- package/src/components/Popover/VTPopoverItem.vue +21 -14
- package/src/components/Popover/VTPopoverTrigger.vue +126 -21
- 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 +4 -3
- package/src/components/Tabs/VTTabGroup.vue +9 -7
- package/src/components/Tabs/VTTabPanel.vue +4 -5
- 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/Transitions/FadeInOut.vue +2 -2
- package/src/components/Utils/FloatingUi.vue +93 -0
- package/package-lock.json +0 -13
- 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
|
@@ -1,39 +1,57 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="{
|
|
2
|
+
<div :class="{ listbox: headless }">
|
|
3
3
|
<slot></slot>
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script>
|
|
8
|
-
import {
|
|
8
|
+
import { floatingUiMixin } from '../../../mixins/floating-ui';
|
|
9
|
+
import { genId } from '../../utils/ids';
|
|
9
10
|
|
|
10
11
|
export default {
|
|
11
|
-
name:
|
|
12
|
+
name: 'VTListbox',
|
|
13
|
+
|
|
14
|
+
mixins: [floatingUiMixin],
|
|
12
15
|
|
|
13
16
|
provide() {
|
|
14
17
|
return {
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
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
|
-
this.
|
|
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
|
-
this.
|
|
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.
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const registerList = (list) => {
|
|
35
|
-
if (!list) return;
|
|
36
|
-
this.list = list;
|
|
54
|
+
this.componentSearch = search;
|
|
37
55
|
};
|
|
38
56
|
|
|
39
57
|
const registerItem = (item) => {
|
|
@@ -46,27 +64,37 @@ 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 {
|
|
55
|
-
id,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
id: this.componentId,
|
|
83
|
+
component: this.component,
|
|
84
|
+
componentTrigger: this.componentTrigger,
|
|
85
|
+
componentContent: this.componentContent,
|
|
86
|
+
componentSearch: this.componentSearch,
|
|
87
|
+
items: this.items,
|
|
88
|
+
multiple: this.multiple,
|
|
89
|
+
search: this.search,
|
|
90
|
+
$mutable,
|
|
64
91
|
registerTrigger,
|
|
65
92
|
registerContent,
|
|
66
93
|
registerSearch,
|
|
67
|
-
registerList,
|
|
68
94
|
registerItem,
|
|
69
95
|
unregisterItem,
|
|
96
|
+
pushSearch,
|
|
97
|
+
clearSearch,
|
|
70
98
|
emit,
|
|
71
99
|
};
|
|
72
100
|
},
|
|
@@ -74,19 +102,52 @@ export default {
|
|
|
74
102
|
},
|
|
75
103
|
|
|
76
104
|
props: {
|
|
77
|
-
|
|
78
|
-
|
|
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],
|
|
79
112
|
default: null,
|
|
80
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
|
+
*/
|
|
81
122
|
headless: {
|
|
82
123
|
type: Boolean,
|
|
83
124
|
default: false,
|
|
84
125
|
},
|
|
85
|
-
|
|
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: {
|
|
86
142
|
type: Boolean,
|
|
87
143
|
default: false,
|
|
88
144
|
},
|
|
89
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Determines whether the component should allow multiple selections.
|
|
147
|
+
* @type {boolean}
|
|
148
|
+
* @default false
|
|
149
|
+
*/
|
|
150
|
+
multiple: {
|
|
90
151
|
type: Boolean,
|
|
91
152
|
default: false,
|
|
92
153
|
},
|
|
@@ -94,31 +155,42 @@ export default {
|
|
|
94
155
|
|
|
95
156
|
data() {
|
|
96
157
|
return {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
content: null,
|
|
101
|
-
search: null,
|
|
102
|
-
list: null,
|
|
158
|
+
componentId: genId(),
|
|
159
|
+
componentSearch: null,
|
|
160
|
+
search: '',
|
|
103
161
|
items: [],
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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,
|
|
112
178
|
};
|
|
113
179
|
},
|
|
114
180
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.
|
|
181
|
+
computed: {
|
|
182
|
+
id() {
|
|
183
|
+
return `listbox-${this.componentId}`;
|
|
118
184
|
},
|
|
119
185
|
|
|
120
|
-
|
|
121
|
-
|
|
186
|
+
valueComputed: {
|
|
187
|
+
get() {
|
|
188
|
+
return this.modelValue;
|
|
189
|
+
},
|
|
190
|
+
set(newValue) {
|
|
191
|
+
this.$emit('update:modelValue', newValue);
|
|
192
|
+
this.$emit('change', newValue);
|
|
193
|
+
},
|
|
122
194
|
},
|
|
123
195
|
},
|
|
124
196
|
};
|
|
@@ -1,95 +1,43 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@after-leave="hide"
|
|
2
|
+
<FloatingUi
|
|
3
|
+
:id="id"
|
|
4
|
+
:visible="visible"
|
|
5
|
+
:headless="headless"
|
|
6
|
+
:aria-activedescendant="activeDescedant"
|
|
7
|
+
component="listbox"
|
|
8
|
+
role="listbox"
|
|
10
9
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
:id="id"
|
|
14
|
-
:aria-activedescendant="activeDescedant"
|
|
15
|
-
:class="{
|
|
16
|
-
MenuList: headless,
|
|
17
|
-
'absolute z-10 grid w-full min-w-[222px] overflow-hidden rounded-md py-2 px-3':
|
|
18
|
-
!headless,
|
|
19
|
-
'border-gray-100 bg-white shadow-300': !dark && !headless,
|
|
20
|
-
'bg-forest-default border border-solid border-gray-700 shadow-gray-700':
|
|
21
|
-
dark && !headless,
|
|
22
|
-
'left-0': !right && !headless,
|
|
23
|
-
'right-0': right && !headless,
|
|
24
|
-
'top-full mt-3': isTop && !headless,
|
|
25
|
-
'bottom-full mb-3': isBottom && !headless,
|
|
26
|
-
}"
|
|
27
|
-
role="listbox"
|
|
28
|
-
>
|
|
29
|
-
<slot></slot>
|
|
30
|
-
</div>
|
|
31
|
-
</transition>
|
|
10
|
+
<slot></slot>
|
|
11
|
+
</FloatingUi>
|
|
32
12
|
</template>
|
|
33
13
|
|
|
34
14
|
<script>
|
|
35
|
-
import {
|
|
15
|
+
import { floatingUiContentMixin } from '../../../mixins/floating-ui-content';
|
|
36
16
|
|
|
37
17
|
export default {
|
|
38
|
-
name:
|
|
18
|
+
name: 'VTListboxContent',
|
|
39
19
|
|
|
40
|
-
|
|
20
|
+
mixins: [floatingUiContentMixin],
|
|
41
21
|
|
|
42
|
-
|
|
43
|
-
headless: {
|
|
44
|
-
type: Boolean,
|
|
45
|
-
default: false,
|
|
46
|
-
},
|
|
47
|
-
bottom: {
|
|
48
|
-
type: Boolean,
|
|
49
|
-
default: false,
|
|
50
|
-
},
|
|
51
|
-
top: {
|
|
52
|
-
type: Boolean,
|
|
53
|
-
default: true,
|
|
54
|
-
},
|
|
55
|
-
},
|
|
22
|
+
inject: ['apiListbox'],
|
|
56
23
|
|
|
57
24
|
data() {
|
|
58
25
|
return {
|
|
59
|
-
id: `listboxcontent-${genId()}`,
|
|
60
26
|
activeDescedant: null,
|
|
61
|
-
visible: false,
|
|
62
27
|
};
|
|
63
28
|
},
|
|
64
29
|
|
|
65
30
|
computed: {
|
|
66
|
-
|
|
67
|
-
return this.
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
right() {
|
|
71
|
-
return this.api().isRight;
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
listbox() {
|
|
75
|
-
return this.api().listbox;
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
trigger() {
|
|
79
|
-
return this.api().trigger;
|
|
31
|
+
id() {
|
|
32
|
+
return `listbox-content-${this.apiListbox().id}`;
|
|
80
33
|
},
|
|
81
34
|
|
|
82
|
-
|
|
83
|
-
return this.
|
|
35
|
+
component() {
|
|
36
|
+
return this.apiListbox().component;
|
|
84
37
|
},
|
|
85
38
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return this.top && !this.bottom;
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
isBottom() {
|
|
92
|
-
return this.bottom;
|
|
39
|
+
componentTrigger() {
|
|
40
|
+
return this.apiListbox().componentTrigger;
|
|
93
41
|
},
|
|
94
42
|
},
|
|
95
43
|
|
|
@@ -101,51 +49,7 @@ export default {
|
|
|
101
49
|
setActiveDescedant: this.setActiveDescedant,
|
|
102
50
|
};
|
|
103
51
|
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
// TODO: Create a directive or mixin for this
|
|
107
|
-
document.addEventListener("click", (e) => {
|
|
108
|
-
e.stopPropagation();
|
|
109
|
-
if (this.visible && !this.$el.contains(e.target)) this.trigger.onClick();
|
|
110
|
-
});
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
destroyed() {
|
|
114
|
-
// TODO: Create a directive or mixin for this
|
|
115
|
-
document.removeEventListener("click", this.trigger.onClick());
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
methods: {
|
|
119
|
-
show() {
|
|
120
|
-
if (this.visible) return;
|
|
121
|
-
|
|
122
|
-
this.visible = true;
|
|
123
|
-
|
|
124
|
-
this.$nextTick(() => {
|
|
125
|
-
this.listbox.setActive();
|
|
126
|
-
|
|
127
|
-
if (this.search) this.search.el.focus();
|
|
128
|
-
});
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
hide() {
|
|
132
|
-
if (!this.visible) return;
|
|
133
|
-
|
|
134
|
-
this.visible = false;
|
|
135
|
-
|
|
136
|
-
this.$nextTick(() => {
|
|
137
|
-
this.trigger.focus();
|
|
138
|
-
|
|
139
|
-
setTimeout(() => {
|
|
140
|
-
this.listbox.clearActive();
|
|
141
|
-
this.trigger.contract();
|
|
142
|
-
}, 100);
|
|
143
|
-
});
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
setActiveDescedant(id) {
|
|
147
|
-
this.activeDescedant = id;
|
|
148
|
-
},
|
|
52
|
+
this.apiListbox().registerContent(content);
|
|
149
53
|
},
|
|
150
54
|
};
|
|
151
55
|
</script>
|