@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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export default {
|
|
13
13
|
name: 'VTDrawerMain',
|
|
14
14
|
|
|
15
|
-
inject: ['
|
|
15
|
+
inject: ['apiDrawer'],
|
|
16
16
|
|
|
17
17
|
props: {
|
|
18
18
|
as: {
|
|
@@ -23,15 +23,15 @@ export default {
|
|
|
23
23
|
|
|
24
24
|
computed: {
|
|
25
25
|
dark() {
|
|
26
|
-
return this.
|
|
26
|
+
return this.apiDrawer().isDark;
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
headless() {
|
|
30
|
-
return this.
|
|
30
|
+
return this.apiDrawer().isHeadless;
|
|
31
31
|
},
|
|
32
32
|
|
|
33
33
|
id() {
|
|
34
|
-
return `${this.
|
|
34
|
+
return `${this.apiDrawer().id}-desc`;
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
37
|
|
|
@@ -42,7 +42,7 @@ export default {
|
|
|
42
42
|
methods: {
|
|
43
43
|
// In here because if there is no body, the dialog will not be described by
|
|
44
44
|
setDialogDescribedby() {
|
|
45
|
-
const dialog = document.getElementById(this.
|
|
45
|
+
const dialog = document.getElementById(this.apiDrawer().id);
|
|
46
46
|
|
|
47
47
|
if (dialog) {
|
|
48
48
|
dialog.setAttribute('aria-describedby', this.id);
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
|
-
import FadeInOut from
|
|
15
|
+
import FadeInOut from '../Transitions/FadeInOut.vue';
|
|
16
16
|
|
|
17
17
|
export default {
|
|
18
18
|
components: {
|
|
19
19
|
FadeInOut,
|
|
20
20
|
},
|
|
21
21
|
|
|
22
|
-
inject: [
|
|
22
|
+
inject: ['apiDrawer'],
|
|
23
23
|
|
|
24
24
|
data() {
|
|
25
25
|
return {
|
|
@@ -29,21 +29,21 @@ export default {
|
|
|
29
29
|
|
|
30
30
|
computed: {
|
|
31
31
|
dark() {
|
|
32
|
-
return this.
|
|
32
|
+
return this.apiDrawer().isDark;
|
|
33
33
|
},
|
|
34
34
|
|
|
35
35
|
headless() {
|
|
36
|
-
return this.
|
|
36
|
+
return this.apiDrawer().isHeadless;
|
|
37
37
|
},
|
|
38
38
|
|
|
39
39
|
id() {
|
|
40
|
-
return `${this.
|
|
40
|
+
return `${this.apiDrawer().id}-overlay`;
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
|
|
44
44
|
mounted() {
|
|
45
45
|
this.visible = true;
|
|
46
|
-
this.
|
|
46
|
+
this.apiDrawer().registerOverlay(this);
|
|
47
47
|
},
|
|
48
48
|
|
|
49
49
|
methods: {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
export default {
|
|
16
16
|
name: 'VTDrawerTitle',
|
|
17
17
|
|
|
18
|
-
inject: ['
|
|
18
|
+
inject: ['apiDrawer'],
|
|
19
19
|
|
|
20
20
|
props: {
|
|
21
21
|
as: {
|
|
@@ -26,15 +26,15 @@ export default {
|
|
|
26
26
|
|
|
27
27
|
computed: {
|
|
28
28
|
dark() {
|
|
29
|
-
return this.
|
|
29
|
+
return this.apiDrawer().isDark;
|
|
30
30
|
},
|
|
31
31
|
|
|
32
32
|
headless() {
|
|
33
|
-
return this.
|
|
33
|
+
return this.apiDrawer().isHeadless;
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
id() {
|
|
37
|
-
return `${this.
|
|
37
|
+
return `${this.apiDrawer().id}-title`;
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ export default {
|
|
|
45
45
|
methods: {
|
|
46
46
|
// In here because if there is no header, the dialog will not be labelled by
|
|
47
47
|
setDialogLabelledby() {
|
|
48
|
-
const dialog = document.getElementById(this.
|
|
48
|
+
const dialog = document.getElementById(this.apiDrawer().id);
|
|
49
49
|
|
|
50
50
|
if (dialog) {
|
|
51
51
|
dialog.setAttribute('aria-labelledby', this.id);
|
|
@@ -5,45 +5,47 @@
|
|
|
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: 'VTDropdownMenu',
|
|
13
|
+
|
|
14
|
+
mixins: [floatingUiMixin],
|
|
12
15
|
|
|
13
16
|
provide() {
|
|
14
17
|
return {
|
|
15
|
-
|
|
16
|
-
const { dark: isDark, headless: isHeadless, right: isRight } = this;
|
|
17
|
-
const { id, trigger, content, items } = this;
|
|
18
|
-
|
|
18
|
+
apiDropdownMenu: () => {
|
|
19
19
|
const registerTrigger = (trigger) => {
|
|
20
|
-
|
|
20
|
+
if (!trigger) return;
|
|
21
|
+
this.componentTrigger = trigger;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const registerContent = (content) => {
|
|
24
|
-
|
|
25
|
+
if (!content) return;
|
|
26
|
+
this.componentContent = content;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
const registerItem = (item) => {
|
|
30
|
+
if (!item) return;
|
|
28
31
|
this.items.push(item);
|
|
29
32
|
};
|
|
30
33
|
|
|
31
|
-
const
|
|
32
|
-
this.items
|
|
34
|
+
const unregisterItem = (id) => {
|
|
35
|
+
const index = this.items.findIndex((item) => item.id === id);
|
|
36
|
+
this.items.splice(index, 1);
|
|
33
37
|
};
|
|
34
38
|
|
|
35
39
|
return {
|
|
36
|
-
id,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
content,
|
|
42
|
-
items,
|
|
40
|
+
id: this.componentId,
|
|
41
|
+
component: this.component,
|
|
42
|
+
componentTrigger: this.componentTrigger,
|
|
43
|
+
componentContent: this.componentContent,
|
|
44
|
+
items: this.items,
|
|
43
45
|
registerTrigger,
|
|
44
46
|
registerContent,
|
|
45
47
|
registerItem,
|
|
46
|
-
|
|
48
|
+
unregisterItem,
|
|
47
49
|
};
|
|
48
50
|
},
|
|
49
51
|
};
|
|
@@ -54,23 +56,38 @@ export default {
|
|
|
54
56
|
type: Boolean,
|
|
55
57
|
default: false,
|
|
56
58
|
},
|
|
57
|
-
|
|
58
|
-
type:
|
|
59
|
-
default:
|
|
60
|
-
},
|
|
61
|
-
right: {
|
|
62
|
-
type: Boolean,
|
|
63
|
-
default: false,
|
|
59
|
+
placement: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: 'bottom-start',
|
|
64
62
|
},
|
|
65
63
|
},
|
|
66
64
|
|
|
67
65
|
data() {
|
|
68
66
|
return {
|
|
69
|
-
|
|
70
|
-
trigger: null,
|
|
71
|
-
content: null,
|
|
67
|
+
componentId: genId(),
|
|
72
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,
|
|
73
84
|
};
|
|
74
85
|
},
|
|
86
|
+
|
|
87
|
+
computed: {
|
|
88
|
+
id() {
|
|
89
|
+
return `dropdown-menu-${this.componentId}`;
|
|
90
|
+
},
|
|
91
|
+
},
|
|
75
92
|
};
|
|
76
93
|
</script>
|
|
@@ -1,93 +1,58 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
leave-class="translate-y-0 opacity-100"
|
|
8
|
-
leave-to-class="translate-y-[15px] opacity-0"
|
|
9
|
-
@after-leave="hide"
|
|
2
|
+
<FloatingUi
|
|
3
|
+
:id="id"
|
|
4
|
+
:visible="visible"
|
|
5
|
+
:headless="headless"
|
|
6
|
+
component="dropdown"
|
|
10
7
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
:id="id"
|
|
14
|
-
:class="{
|
|
15
|
-
MenuList: headless,
|
|
16
|
-
'absolute top-full mt-3 grid min-w-[222px] overflow-hidden rounded border border-solid py-2 px-3 transition-all':
|
|
17
|
-
!headless,
|
|
18
|
-
'border-gray-100 bg-white shadow-300': !dark,
|
|
19
|
-
'bg-forest-default border-gray-700 shadow-gray-700': dark,
|
|
20
|
-
'left-0': !right,
|
|
21
|
-
'right-0': right,
|
|
22
|
-
}"
|
|
23
|
-
>
|
|
24
|
-
<slot></slot>
|
|
25
|
-
</div>
|
|
26
|
-
</transition>
|
|
8
|
+
<slot></slot>
|
|
9
|
+
</FloatingUi>
|
|
27
10
|
</template>
|
|
28
11
|
|
|
29
12
|
<script>
|
|
30
|
-
import {
|
|
13
|
+
import { floatingUiContentMixin } from '../../../mixins/floating-ui-content';
|
|
31
14
|
|
|
32
15
|
export default {
|
|
33
16
|
name: 'VTDropdownMenuContent',
|
|
34
17
|
|
|
35
|
-
|
|
18
|
+
inheritAttrs: false,
|
|
36
19
|
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
id: `menucontent-${genId()}`,
|
|
40
|
-
visible: false,
|
|
41
|
-
};
|
|
42
|
-
},
|
|
20
|
+
mixins: [floatingUiContentMixin],
|
|
43
21
|
|
|
44
|
-
|
|
45
|
-
dark() {
|
|
46
|
-
return this.api().isDark;
|
|
47
|
-
},
|
|
22
|
+
inject: ['apiDropdownMenu'],
|
|
48
23
|
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
computed: {
|
|
25
|
+
id() {
|
|
26
|
+
return `dropdown-menu-content-${this.apiDropdownMenu().id}`;
|
|
51
27
|
},
|
|
52
28
|
|
|
53
|
-
|
|
54
|
-
return this.
|
|
29
|
+
component() {
|
|
30
|
+
return this.apiDropdownMenu().component;
|
|
55
31
|
},
|
|
56
32
|
|
|
57
|
-
|
|
58
|
-
return this.
|
|
33
|
+
componentTrigger() {
|
|
34
|
+
return this.apiDropdownMenu().componentTrigger;
|
|
59
35
|
},
|
|
60
36
|
},
|
|
61
37
|
|
|
62
38
|
mounted() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// TODO: Create a directive or mixin for this
|
|
70
|
-
document.addEventListener('click', (e) => {
|
|
71
|
-
e.stopPropagation();
|
|
72
|
-
if (this.visible && !this.$el.contains(e.target)) this.trigger.onClick();
|
|
73
|
-
});
|
|
74
|
-
},
|
|
39
|
+
const content = {
|
|
40
|
+
id: this.id,
|
|
41
|
+
hide: this.hide,
|
|
42
|
+
show: this.show,
|
|
43
|
+
setActiveDescedant: this.setActiveDescedant,
|
|
44
|
+
};
|
|
75
45
|
|
|
76
|
-
|
|
77
|
-
// TODO: Create a directive or mixin for this
|
|
78
|
-
document.removeEventListener('click', this.trigger.onClick());
|
|
46
|
+
this.apiDropdownMenu().registerContent(content);
|
|
79
47
|
},
|
|
80
48
|
|
|
81
49
|
methods: {
|
|
82
|
-
|
|
83
|
-
this
|
|
84
|
-
this.$emit('shown');
|
|
50
|
+
hidden() {
|
|
51
|
+
this.$emit('hidden');
|
|
85
52
|
},
|
|
86
53
|
|
|
87
|
-
|
|
88
|
-
this
|
|
89
|
-
this.$emit('hidden');
|
|
90
|
-
this.api().unregisterItems();
|
|
54
|
+
shown() {
|
|
55
|
+
this.$emit('shown');
|
|
91
56
|
},
|
|
92
57
|
},
|
|
93
58
|
};
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
:class="
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
'bg-gray-200': !dark,
|
|
7
|
-
'bg-fd-500': dark,
|
|
8
|
-
}"
|
|
3
|
+
:class="[
|
|
4
|
+
headless ? 'dropdown-menu-divider' : '-mx-3 my-2 h-[1px] bg-gray-200',
|
|
5
|
+
]"
|
|
9
6
|
></div>
|
|
10
7
|
</template>
|
|
11
8
|
|
|
@@ -13,15 +10,12 @@
|
|
|
13
10
|
export default {
|
|
14
11
|
name: 'VTDropdownMenuDivider',
|
|
15
12
|
|
|
16
|
-
inject: ['
|
|
13
|
+
inject: ['apiDropdownMenu'],
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
headless() {
|
|
24
|
-
return this.api().isHeadless;
|
|
15
|
+
props: {
|
|
16
|
+
headless: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
default: false,
|
|
25
19
|
},
|
|
26
20
|
},
|
|
27
21
|
};
|
|
@@ -3,20 +3,14 @@
|
|
|
3
3
|
:is="as"
|
|
4
4
|
:id="id"
|
|
5
5
|
:to="to"
|
|
6
|
-
:class="
|
|
7
|
-
MenuItem: headless,
|
|
8
|
-
'-mx-3 flex min-w-max items-center gap-3 px-3 py-2 text-inherit no-underline':
|
|
9
|
-
!headless,
|
|
10
|
-
'hover:bg-secondary-200/10': !dark,
|
|
11
|
-
'text-white hover:bg-fd-450 focus:bg-fd-450': dark,
|
|
12
|
-
'pointer-events-none opacity-75': disabled,
|
|
13
|
-
}"
|
|
14
|
-
:tabindex="tabIndex"
|
|
6
|
+
:class="classComputed"
|
|
15
7
|
:aria-disabled="disabled"
|
|
8
|
+
:tabindex="tabIndex"
|
|
9
|
+
class="-mx-3"
|
|
16
10
|
role="menuitem"
|
|
17
11
|
@click.stop.prevent="onClick"
|
|
18
|
-
@keydown.down.prevent="
|
|
19
|
-
@keydown.up.prevent="
|
|
12
|
+
@keydown.down.prevent="focusNextItem"
|
|
13
|
+
@keydown.up.prevent="focusPreviousItem"
|
|
20
14
|
@keydown.home.prevent="focusFirstItem"
|
|
21
15
|
@keydown.end.prevent="focusLastItem"
|
|
22
16
|
@keydown.esc.prevent="onKeyEsc"
|
|
@@ -28,12 +22,14 @@
|
|
|
28
22
|
</template>
|
|
29
23
|
|
|
30
24
|
<script>
|
|
31
|
-
import {
|
|
25
|
+
import { floatingUiItemMixin } from '../../../mixins/floating-ui-item';
|
|
32
26
|
|
|
33
27
|
export default {
|
|
34
28
|
name: 'VTDropdownMenuItem',
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
mixins: [floatingUiItemMixin],
|
|
31
|
+
|
|
32
|
+
inject: ['apiDropdownMenu'],
|
|
37
33
|
|
|
38
34
|
props: {
|
|
39
35
|
to: {
|
|
@@ -44,128 +40,19 @@ export default {
|
|
|
44
40
|
type: String,
|
|
45
41
|
default: null,
|
|
46
42
|
},
|
|
47
|
-
disabled: {
|
|
48
|
-
type: Boolean,
|
|
49
|
-
default: false,
|
|
50
|
-
},
|
|
51
43
|
},
|
|
52
44
|
|
|
53
45
|
data() {
|
|
54
46
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
tabIndex: 0,
|
|
47
|
+
apiInjected: this.apiDropdownMenu,
|
|
48
|
+
componentName: 'dropdown-menu-item',
|
|
58
49
|
};
|
|
59
50
|
},
|
|
60
51
|
|
|
61
52
|
computed: {
|
|
62
|
-
dark() {
|
|
63
|
-
return this.api().isDark;
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
headless() {
|
|
67
|
-
return this.api().isHeadless;
|
|
68
|
-
},
|
|
69
|
-
|
|
70
53
|
as() {
|
|
71
54
|
return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
|
|
72
55
|
},
|
|
73
|
-
|
|
74
|
-
items() {
|
|
75
|
-
return this.api().items;
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
el() {
|
|
79
|
-
return this.$el;
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
trigger() {
|
|
83
|
-
return this.api().trigger;
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
content() {
|
|
87
|
-
return this.api().content;
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
mounted() {
|
|
92
|
-
const item = {
|
|
93
|
-
focus: this.focus,
|
|
94
|
-
el: this.el,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
this.api().registerItem(item);
|
|
98
|
-
|
|
99
|
-
this.index = this.items.length - 1;
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
methods: {
|
|
103
|
-
focus() {
|
|
104
|
-
if (!this.el) return;
|
|
105
|
-
|
|
106
|
-
this.tabIndex = -1;
|
|
107
|
-
this.el.focus();
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
focusFirstItem() {
|
|
111
|
-
this.setFocusToItem(0);
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
focusLastItem() {
|
|
115
|
-
this.setFocusToItem(this.items.length - 1);
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Focus the previous item in the menu.
|
|
120
|
-
* If is the first item, jump to the last item.
|
|
121
|
-
*/
|
|
122
|
-
focusPreviousItem() {
|
|
123
|
-
const isLast = this.index === this.items.length - 1;
|
|
124
|
-
const goToIndex = isLast ? 0 : this.index + 1;
|
|
125
|
-
|
|
126
|
-
this.setFocusToItem(goToIndex);
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Focus the next item in the menu.
|
|
131
|
-
* If is the last item, jump to the first item.
|
|
132
|
-
*/
|
|
133
|
-
focusNextItem() {
|
|
134
|
-
const isFirst = this.index === 0;
|
|
135
|
-
const goToIndex = isFirst ? this.items.length - 1 : this.index - 1;
|
|
136
|
-
|
|
137
|
-
this.setFocusToItem(goToIndex);
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Focus item by remove its tabindex and calling
|
|
142
|
-
* focus to the element.
|
|
143
|
-
*
|
|
144
|
-
* @param {Number, String} goToIndex
|
|
145
|
-
*/
|
|
146
|
-
setFocusToItem(goToIndex) {
|
|
147
|
-
this.tabIndex = 0;
|
|
148
|
-
this.items[goToIndex].focus();
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Hides content/menu and focus on trigger
|
|
153
|
-
*/
|
|
154
|
-
leaveMenu() {
|
|
155
|
-
if (this.content) this.content.hide();
|
|
156
|
-
if (this.trigger) this.trigger.focus();
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
onKeyEsc() {
|
|
160
|
-
this.leaveMenu();
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
onClick() {
|
|
164
|
-
if (this.disabled) return;
|
|
165
|
-
|
|
166
|
-
this.$emit('click');
|
|
167
|
-
this.$nextTick(() => this.leaveMenu());
|
|
168
|
-
},
|
|
169
56
|
},
|
|
170
57
|
};
|
|
171
58
|
</script>
|
|
@@ -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>
|
|
@@ -15,15 +10,11 @@
|
|
|
15
10
|
export default {
|
|
16
11
|
name: 'VTDropdownMenuLabel',
|
|
17
12
|
|
|
18
|
-
inject: ['
|
|
13
|
+
inject: ['apiDropdownMenu'],
|
|
19
14
|
|
|
20
15
|
computed: {
|
|
21
|
-
dark() {
|
|
22
|
-
return this.api().isDark;
|
|
23
|
-
},
|
|
24
|
-
|
|
25
16
|
headless() {
|
|
26
|
-
return this.
|
|
17
|
+
return this.apiDropdownMenu().isHeadless;
|
|
27
18
|
},
|
|
28
19
|
},
|
|
29
20
|
};
|