@veritree/ui 0.14.0 → 0.16.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 +10 -6
- package/nuxt.js +1 -0
- package/package.json +4 -2
- package/src/components/Dialog/VTDialog.vue +24 -17
- package/src/components/Disclosure/VTDisclosure.vue +59 -0
- package/src/components/Disclosure/VTDisclosureContent.vue +95 -0
- package/src/components/Disclosure/VTDisclosureDetails.vue +84 -0
- package/src/components/Disclosure/VTDisclosureHeader.vue +136 -0
- package/src/components/Disclosure/VTDisclosureIcon.vue +63 -0
- package/src/components/Drawer/VTDrawerHeader.vue +4 -4
- package/src/components/Drawer/VTDrawerTitle.vue +5 -5
- package/src/components/Accordion/VTAccordion.vue +0 -105
- package/src/components/Accordion/VTAccordionButton.vue +0 -56
- package/src/components/Accordion/VTAccordionGroup.vue +0 -25
- package/src/components/Accordion/VTAccordionPanel.vue +0 -53
- package/src/components/icons/IconChevronDown.vue +0 -14
- package/src/components/icons/IconChevronUp.vue +0 -14
package/index.js
CHANGED
|
@@ -34,22 +34,17 @@ import VTInputDate from "./src/components/Input/VTInputDate.vue";
|
|
|
34
34
|
import VTInputFile from "./src/components/Input/VTInputFile.vue";
|
|
35
35
|
import VTInputUpload from "./src/components/Input/VTInputUpload.vue";
|
|
36
36
|
import VTProgressBar from "./src/components/ProgressBar/VTProgressBar.vue";
|
|
37
|
-
|
|
38
37
|
import VTTextarea from "./src/components/Textarea/VTTextarea.vue";
|
|
39
|
-
|
|
40
38
|
import VTModal from "./src/components/Modal/VTModal.vue";
|
|
41
|
-
|
|
42
39
|
import VTAccordion from "./src/components/Accordion/VTAccordion.vue";
|
|
43
40
|
import VTAccordionButton from "./src/components/Accordion/VTAccordionButton.vue";
|
|
44
41
|
import VTAccordionGroup from "./src/components/Accordion/VTAccordionGroup.vue";
|
|
45
42
|
import VTAccordionPanel from "./src/components/Accordion/VTAccordionPanel.vue";
|
|
46
|
-
|
|
47
43
|
import VTTab from "./src/components/Tabs/VTTab.vue";
|
|
48
44
|
import VTTabGroup from "./src/components/Tabs/VTTabGroup.vue";
|
|
49
45
|
import VTTabList from "./src/components/Tabs/VTTabList.vue";
|
|
50
46
|
import VTTabPanel from "./src/components/Tabs/VTTabPanel.vue";
|
|
51
47
|
import VTTabPanels from "./src/components/Tabs/VTTabPanels.vue";
|
|
52
|
-
|
|
53
48
|
import VTDialog from "./src/components/Dialog/VTDialog.vue";
|
|
54
49
|
import VTDialogClose from "./src/components/Dialog/VTDialogClose.vue";
|
|
55
50
|
import VTDialogContent from "./src/components/Dialog/VTDialogContent.vue";
|
|
@@ -58,7 +53,6 @@ import VTDialogHeader from "./src/components/Dialog/VTDialogHeader.vue";
|
|
|
58
53
|
import VTDialogMain from "./src/components/Dialog/VTDialogMain.vue";
|
|
59
54
|
import VTDialogOverlay from "./src/components/Dialog/VTDialogOverlay.vue";
|
|
60
55
|
import VTDialogTitle from "./src/components/Dialog/VTDialogTitle.vue";
|
|
61
|
-
|
|
62
56
|
import VTDrawer from "./src/components/Drawer/VTDrawer.vue";
|
|
63
57
|
import VTDrawerClose from "./src/components/Drawer/VTDrawerClose.vue";
|
|
64
58
|
import VTDrawerContent from "./src/components/Drawer/VTDrawerContent.vue";
|
|
@@ -67,6 +61,11 @@ import VTDrawerHeader from "./src/components/Drawer/VTDrawerHeader.vue";
|
|
|
67
61
|
import VTDrawerTitle from "./src/components/Drawer/VTDrawerTitle.vue";
|
|
68
62
|
import VTDrawerMain from "./src/components/Drawer/VTDrawerMain.vue";
|
|
69
63
|
import VTDrawerOverlay from "./src/components/Drawer/VTDrawerOverlay.vue";
|
|
64
|
+
import VTDisclosure from "./src/components/Disclosure/VTDisclosure.vue";
|
|
65
|
+
import VTDisclosureDetails from "./src/components/Disclosure/VTDisclosureDetails.vue";
|
|
66
|
+
import VTDisclosureHeader from "./src/components/Disclosure/VTDisclosureHeader.vue";
|
|
67
|
+
import VTDisclosureIcon from "./src/components/Disclosure/VTDisclosureIcon.vue";
|
|
68
|
+
import VTDisclosureContent from "./src/components/Disclosure/VTDisclosureContent.vue";
|
|
70
69
|
|
|
71
70
|
export {
|
|
72
71
|
VTAvatar,
|
|
@@ -132,4 +131,9 @@ export {
|
|
|
132
131
|
VTDialogMain,
|
|
133
132
|
VTDialogOverlay,
|
|
134
133
|
VTDialogTitle,
|
|
134
|
+
VTDisclosure,
|
|
135
|
+
VTDisclosureDetails,
|
|
136
|
+
VTDisclosureHeader,
|
|
137
|
+
VTDisclosureIcon,
|
|
138
|
+
VTDisclosureContent,
|
|
135
139
|
};
|
package/nuxt.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veritree/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "veritree ui library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"access": "public"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@linusborg/vue-simple-portal": "^0.1.5",
|
|
14
15
|
"@veritree/icons": "^0.19.0"
|
|
15
|
-
}
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {}
|
|
16
18
|
}
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
<Portal>
|
|
3
|
+
<div
|
|
4
|
+
v-if="visible"
|
|
5
|
+
:id="id"
|
|
6
|
+
:class="{
|
|
7
|
+
Dialog: headless,
|
|
8
|
+
'fixed inset-0 z-50 grid grid-cols-1 grid-rows-1 p-4 md:p-8': !headless,
|
|
9
|
+
}"
|
|
10
|
+
aria-modal="true"
|
|
11
|
+
@click="onClick"
|
|
12
|
+
>
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</div>
|
|
15
|
+
</Portal>
|
|
14
16
|
</template>
|
|
15
17
|
|
|
16
18
|
<script>
|
|
17
|
-
import {
|
|
19
|
+
import { Portal } from '@linusborg/vue-simple-portal';
|
|
20
|
+
import { genId } from '../../utils/ids';
|
|
18
21
|
|
|
19
22
|
export default {
|
|
20
|
-
name:
|
|
23
|
+
name: 'VTDialog',
|
|
24
|
+
|
|
25
|
+
components: {
|
|
26
|
+
Portal,
|
|
27
|
+
},
|
|
21
28
|
|
|
22
29
|
provide() {
|
|
23
30
|
return {
|
|
@@ -56,7 +63,7 @@ export default {
|
|
|
56
63
|
},
|
|
57
64
|
|
|
58
65
|
model: {
|
|
59
|
-
prop:
|
|
66
|
+
prop: 'visible',
|
|
60
67
|
},
|
|
61
68
|
|
|
62
69
|
props: {
|
|
@@ -115,8 +122,8 @@ export default {
|
|
|
115
122
|
|
|
116
123
|
emit() {
|
|
117
124
|
this.$nextTick(() => {
|
|
118
|
-
this.$emit(
|
|
119
|
-
this.$emit(
|
|
125
|
+
this.$emit('input', false);
|
|
126
|
+
this.$emit('hidden');
|
|
120
127
|
});
|
|
121
128
|
},
|
|
122
129
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<slot></slot>
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
export default {
|
|
9
|
+
name: 'VTDisclosure',
|
|
10
|
+
|
|
11
|
+
provide() {
|
|
12
|
+
return {
|
|
13
|
+
apiDisclosure: () => {
|
|
14
|
+
const details = this.details;
|
|
15
|
+
const contents = this.contents;
|
|
16
|
+
const accordion = this.accordion;
|
|
17
|
+
const headers = this.headers;
|
|
18
|
+
const icons = this.icons;
|
|
19
|
+
|
|
20
|
+
const register = (objKey, item) => {
|
|
21
|
+
if (!item) return;
|
|
22
|
+
this[objKey].push(item);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const unregister = (objKey, id) => {
|
|
26
|
+
const index = this[objKey].findIndex((item) => item.id === id);
|
|
27
|
+
this[objKey].splice(index, 1);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
details,
|
|
32
|
+
contents,
|
|
33
|
+
headers,
|
|
34
|
+
icons,
|
|
35
|
+
accordion,
|
|
36
|
+
register,
|
|
37
|
+
unregister,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
props: {
|
|
44
|
+
accordion: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
data() {
|
|
51
|
+
return {
|
|
52
|
+
details: [],
|
|
53
|
+
contents: [],
|
|
54
|
+
headers: [],
|
|
55
|
+
icons: [],
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:id="id"
|
|
4
|
+
:class="[
|
|
5
|
+
headless
|
|
6
|
+
? 'details-content'
|
|
7
|
+
: 'overflow-hidden transition-[height] duration-300 ease-linear',
|
|
8
|
+
invisible ? 'absolute opacity-0' : 'h-[var(--height)]',
|
|
9
|
+
]"
|
|
10
|
+
:style="`--height: ${height};`"
|
|
11
|
+
>
|
|
12
|
+
<slot></slot>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script>
|
|
17
|
+
export default {
|
|
18
|
+
name: 'VTDisclosureContent',
|
|
19
|
+
|
|
20
|
+
inject: ['apiDisclosure', 'apiDetails'],
|
|
21
|
+
|
|
22
|
+
props: {
|
|
23
|
+
headless: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
data() {
|
|
30
|
+
return {
|
|
31
|
+
idGroup: this.apiDetails().idGroup,
|
|
32
|
+
expanded: false,
|
|
33
|
+
expandedHeight: null,
|
|
34
|
+
invisible: false,
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
computed: {
|
|
39
|
+
id() {
|
|
40
|
+
return `disclosure-content-${this.idGroup}`;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
height() {
|
|
44
|
+
return this.expanded ? this.expandedHeight : 0;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
mounted() {
|
|
49
|
+
this.handleVisibleHeight();
|
|
50
|
+
|
|
51
|
+
const content = {
|
|
52
|
+
id: this.id,
|
|
53
|
+
idGroup: this.idGroup,
|
|
54
|
+
collapse: this.collapse,
|
|
55
|
+
expand: this.expand,
|
|
56
|
+
isVisible: this.isVisible,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
this.apiDisclosure().register('contents', content);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
beforeDestroy() {
|
|
63
|
+
this.apiDisclosure().unregister('contents', this.id);
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
methods: {
|
|
67
|
+
handleVisibleHeight() {
|
|
68
|
+
// make panel position absolute and opacity 0,
|
|
69
|
+
// to have it fully opened but not visible
|
|
70
|
+
this.invisible = true;
|
|
71
|
+
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
// get computed height now since its fully opened
|
|
74
|
+
// this height will be used by a css custom property to enable the transition
|
|
75
|
+
this.expandedHeight = window.getComputedStyle(this.$el).height;
|
|
76
|
+
|
|
77
|
+
// make invisible false once the full height is set
|
|
78
|
+
this.invisible = false;
|
|
79
|
+
}, 500);
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
expand() {
|
|
83
|
+
this.expanded = true;
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
collapse() {
|
|
87
|
+
this.expanded = false;
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
isVisible() {
|
|
91
|
+
return this.expanded;
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
</script>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
headless ? 'disclosure-details' : 'group relative',
|
|
5
|
+
headless ? (visible ? 'is-open' : null) : null,
|
|
6
|
+
]"
|
|
7
|
+
>
|
|
8
|
+
<slot></slot>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
import { genId } from '@/utils/ids';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'VTDisclosureDetails',
|
|
17
|
+
|
|
18
|
+
inject: ['apiDisclosure'],
|
|
19
|
+
|
|
20
|
+
provide() {
|
|
21
|
+
return {
|
|
22
|
+
apiDetails: () => {
|
|
23
|
+
const idGroup = this.idGroup;
|
|
24
|
+
const idHeader = `details-header-${idGroup}`;
|
|
25
|
+
const idIcon = `details-icon-${idGroup}`;
|
|
26
|
+
const idContent = `details-content-${idGroup}`;
|
|
27
|
+
|
|
28
|
+
const isVisible = () => this.isVisible();
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
idGroup,
|
|
32
|
+
idHeader,
|
|
33
|
+
idIcon,
|
|
34
|
+
idContent,
|
|
35
|
+
isVisible,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
props: {
|
|
42
|
+
headless: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
data() {
|
|
49
|
+
return {
|
|
50
|
+
idGroup: genId(),
|
|
51
|
+
visible: false,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
mounted() {
|
|
56
|
+
const detail = {
|
|
57
|
+
idGroup: this.idGroup,
|
|
58
|
+
show: this.show,
|
|
59
|
+
hide: this.hide,
|
|
60
|
+
isVisible: this.isVisible,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
this.apiDisclosure().register('details', detail);
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
beforeDestroy() {
|
|
67
|
+
this.apiDisclosure().unregister('details', this.id);
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
methods: {
|
|
71
|
+
show() {
|
|
72
|
+
this.visible = true;
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
hide() {
|
|
76
|
+
this.visible = false;
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
isVisible() {
|
|
80
|
+
return this.visible;
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<header
|
|
3
|
+
:id="id"
|
|
4
|
+
:class="[
|
|
5
|
+
headless
|
|
6
|
+
? 'details-header'
|
|
7
|
+
: 'flex cursor-pointer justify-between gap-3 text-body font-semibold',
|
|
8
|
+
]"
|
|
9
|
+
:aria-controls="ariaControls"
|
|
10
|
+
:aria-expanded="String(ariaExpanded)"
|
|
11
|
+
role="button"
|
|
12
|
+
tabindex="0"
|
|
13
|
+
@click.prevent="toggle"
|
|
14
|
+
@keydown.enter="toggle"
|
|
15
|
+
>
|
|
16
|
+
<slot></slot>
|
|
17
|
+
</header>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
export default {
|
|
22
|
+
name: 'VTDisclosureHeader',
|
|
23
|
+
|
|
24
|
+
inject: ['apiDisclosure', 'apiDetails'],
|
|
25
|
+
|
|
26
|
+
props: {
|
|
27
|
+
headless: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
data() {
|
|
34
|
+
return {
|
|
35
|
+
ariaExpanded: false,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
computed: {
|
|
40
|
+
id() {
|
|
41
|
+
return this.apiDetails().idSummary;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
idGroup() {
|
|
45
|
+
return this.apiDetails().idGroup;
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
ariaControls() {
|
|
49
|
+
return this.apiDetails().idContent;
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
details() {
|
|
53
|
+
return this.apiDisclosure().details;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
headers() {
|
|
57
|
+
return this.apiDisclosure().headers;
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
icons() {
|
|
61
|
+
return this.apiDisclosure().icons;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
contents() {
|
|
65
|
+
return this.apiDisclosure().contents;
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
mounted() {
|
|
70
|
+
this.isExpanded();
|
|
71
|
+
|
|
72
|
+
const header = {
|
|
73
|
+
id: this.id,
|
|
74
|
+
idGroup: this.idGroup,
|
|
75
|
+
isExpanded: this.isExpanded,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.apiDisclosure().register('headers', header);
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
beforeDestroy() {
|
|
82
|
+
this.apiDisclosure().unregister('headers', this.id);
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
methods: {
|
|
86
|
+
toggle() {
|
|
87
|
+
this.toggleDetails();
|
|
88
|
+
this.toggleHeaders();
|
|
89
|
+
this.toggleContents();
|
|
90
|
+
this.toggleIcons();
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
isExpanded() {
|
|
94
|
+
this.ariaExpanded = this.apiDetails().isVisible();
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
toggleDetails() {
|
|
98
|
+
this.details.forEach((detail) => {
|
|
99
|
+
const isSameGroup = detail.idGroup === this.idGroup;
|
|
100
|
+
const isAccordion = this.apiDisclosure().accordion;
|
|
101
|
+
|
|
102
|
+
if (isSameGroup) {
|
|
103
|
+
detail.isVisible() ? detail.hide() : detail.show();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isAccordion && !isSameGroup) {
|
|
107
|
+
detail.hide();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
toggleContents() {
|
|
113
|
+
this.contents.forEach((content) => {
|
|
114
|
+
const isSameGroup = content.idGroup === this.idGroup;
|
|
115
|
+
const isAccordion = this.apiDisclosure().accordion;
|
|
116
|
+
|
|
117
|
+
if (isSameGroup) {
|
|
118
|
+
content.isVisible() ? content.collapse() : content.expand();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isAccordion && !isSameGroup) {
|
|
122
|
+
content.collapse();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
toggleHeaders() {
|
|
128
|
+
this.headers.forEach((summary) => summary.isExpanded());
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
toggleIcons() {
|
|
132
|
+
this.icons.forEach((icon) => icon.isExpanded());
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
</script>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span
|
|
3
|
+
:class="[
|
|
4
|
+
headless ? 'disclosure-icon' : 'shrink-0 transition-all',
|
|
5
|
+
headless ? null : expanded ? 'rotate-180' : 'rotate-0',
|
|
6
|
+
]"
|
|
7
|
+
>
|
|
8
|
+
<slot><IconChevronDown /></slot>
|
|
9
|
+
</span>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
export default {
|
|
14
|
+
name: 'VTDisclosureIcon',
|
|
15
|
+
|
|
16
|
+
inject: ['apiDisclosure', 'apiDetails'],
|
|
17
|
+
|
|
18
|
+
props: {
|
|
19
|
+
headless: {
|
|
20
|
+
type: Boolean,
|
|
21
|
+
default: false,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
data() {
|
|
26
|
+
return {
|
|
27
|
+
expanded: false,
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
computed: {
|
|
32
|
+
id() {
|
|
33
|
+
return this.apiDetails().idIcon;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
idGroup() {
|
|
37
|
+
return this.apiDetails().idGroup;
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
mounted() {
|
|
42
|
+
this.isExpanded();
|
|
43
|
+
|
|
44
|
+
const icon = {
|
|
45
|
+
id: this.id,
|
|
46
|
+
idGroup: this.idGroup,
|
|
47
|
+
isExpanded: this.isExpanded,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
this.apiDisclosure().register('icons', icon);
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
beforeDestroy() {
|
|
54
|
+
this.apiDisclosure().unregister('icons', this.id);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
methods: {
|
|
58
|
+
isExpanded() {
|
|
59
|
+
this.expanded = this.apiDetails().isVisible();
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
</script>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
:id="id"
|
|
5
5
|
:class="{
|
|
6
6
|
'Drawer-header': headless,
|
|
7
|
-
'flex items-center justify-between': !headless,
|
|
7
|
+
'mb-8 flex items-center justify-between gap-3': !headless,
|
|
8
8
|
}"
|
|
9
9
|
>
|
|
10
10
|
<slot></slot>
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
15
|
export default {
|
|
16
|
-
name:
|
|
16
|
+
name: 'VTDrawerHeader',
|
|
17
17
|
|
|
18
|
-
inject: [
|
|
18
|
+
inject: ['api'],
|
|
19
19
|
|
|
20
20
|
props: {
|
|
21
21
|
as: {
|
|
22
22
|
type: String,
|
|
23
|
-
default:
|
|
23
|
+
default: 'header',
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
:id="id"
|
|
5
5
|
:class="{
|
|
6
6
|
'Drawer-title': headless,
|
|
7
|
-
'
|
|
7
|
+
'text-2xl font-semibold': !headless,
|
|
8
8
|
}"
|
|
9
9
|
>
|
|
10
10
|
<slot></slot>
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
<script>
|
|
15
15
|
export default {
|
|
16
|
-
name:
|
|
16
|
+
name: 'VTDrawerTitle',
|
|
17
17
|
|
|
18
|
-
inject: [
|
|
18
|
+
inject: ['api'],
|
|
19
19
|
|
|
20
20
|
props: {
|
|
21
21
|
as: {
|
|
22
22
|
type: String,
|
|
23
|
-
default:
|
|
23
|
+
default: 'div',
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
|
|
@@ -48,7 +48,7 @@ export default {
|
|
|
48
48
|
const dialog = document.getElementById(this.api().id);
|
|
49
49
|
|
|
50
50
|
if (dialog) {
|
|
51
|
-
dialog.setAttribute(
|
|
51
|
+
dialog.setAttribute('aria-labelledby', this.id);
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
},
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="accordion" :multiple="multiple"><slot></slot></div>
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script>
|
|
6
|
-
export default {
|
|
7
|
-
name: 'VTAccordion',
|
|
8
|
-
props: {
|
|
9
|
-
multiple: {
|
|
10
|
-
type: Boolean,
|
|
11
|
-
default: false
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
provide() {
|
|
15
|
-
return {
|
|
16
|
-
api: () => {
|
|
17
|
-
// Get children components
|
|
18
|
-
const getAccordion = () => this.accordion;
|
|
19
|
-
const getAccordionGroup = () => this.accordionGroup;
|
|
20
|
-
const getAccordionPanel = () => this.accordionPanel;
|
|
21
|
-
const getAccordionButton = () => this.accordionButton;
|
|
22
|
-
|
|
23
|
-
// Handle registering and unregistering
|
|
24
|
-
const registerAccordion = (accordion) => {
|
|
25
|
-
if (!accordion) return;
|
|
26
|
-
this.accordion = accordion;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const registerAccordionButton = (button) => {
|
|
30
|
-
if (!button) return;
|
|
31
|
-
this.accordionButton = button;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const registerAccordionGroup = (group) => {
|
|
35
|
-
if (!group) return;
|
|
36
|
-
_register(this.accordionGroup, group);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const registerAccordionPanel = (panel) => {
|
|
40
|
-
if (!panel) return;
|
|
41
|
-
_register(this.accordionPanel, panel);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const unregisterAccordionPanel = (id) => {
|
|
45
|
-
_unregister(this.accordionPanel, id);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const selectedPanel = (panelId) => {
|
|
49
|
-
if (this.multiple) {
|
|
50
|
-
this.accordionPanel.forEach((item) => {
|
|
51
|
-
if(item.id === panelId) item.multipleActive();
|
|
52
|
-
})
|
|
53
|
-
} else{
|
|
54
|
-
this.accordionPanel.forEach((item) => {
|
|
55
|
-
item.id === panelId ? item.show() : item.hide();
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// Register helper functions
|
|
61
|
-
const _register = (arr, item) => {
|
|
62
|
-
arr.push(item);
|
|
63
|
-
_index(arr);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const _unregister = (arr, id) => {
|
|
67
|
-
const index = _getIndex(arr, id);
|
|
68
|
-
arr.splice(index, 1);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// Index helper functions
|
|
72
|
-
const _index = (arr) => {
|
|
73
|
-
arr.forEach((item, index) => (item.index = index));
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const _getIndex = (arr, id) => {
|
|
77
|
-
return arr.findIndex((item) => item.id === id);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
getAccordion,
|
|
82
|
-
getAccordionGroup,
|
|
83
|
-
getAccordionPanel,
|
|
84
|
-
getAccordionButton,
|
|
85
|
-
registerAccordionGroup,
|
|
86
|
-
registerAccordionButton,
|
|
87
|
-
registerAccordion,
|
|
88
|
-
registerAccordionPanel,
|
|
89
|
-
unregisterAccordionPanel,
|
|
90
|
-
selectedPanel,
|
|
91
|
-
};
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
data() {
|
|
97
|
-
return {
|
|
98
|
-
accordion: null,
|
|
99
|
-
accordionGroup: [],
|
|
100
|
-
accordionButton: null,
|
|
101
|
-
accordionPanel: [],
|
|
102
|
-
};
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
</script>
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<h3>
|
|
3
|
-
<button
|
|
4
|
-
:id="id"
|
|
5
|
-
:aria-expanded="String(expanded)"
|
|
6
|
-
:aria-controls="id"
|
|
7
|
-
class="accordion-trigger"
|
|
8
|
-
type="button"
|
|
9
|
-
@click.prevent="onClick"
|
|
10
|
-
>
|
|
11
|
-
<span class="Accordion-button__text"><slot></slot></span>
|
|
12
|
-
<span class="Accordion-button__icon">
|
|
13
|
-
<IconChevronUp v-if="expanded" />
|
|
14
|
-
<IconChevronDown v-else />
|
|
15
|
-
</span>
|
|
16
|
-
</button>
|
|
17
|
-
</h3>
|
|
18
|
-
</template>
|
|
19
|
-
|
|
20
|
-
<script>
|
|
21
|
-
import IconChevronDown from '../icons/IconChevronDown.vue';
|
|
22
|
-
import IconChevronUp from '../icons/IconChevronUp.vue';
|
|
23
|
-
|
|
24
|
-
export default {
|
|
25
|
-
name: 'VTAccordionButton',
|
|
26
|
-
components: { IconChevronDown, IconChevronUp },
|
|
27
|
-
inject: ['api'],
|
|
28
|
-
|
|
29
|
-
data() {
|
|
30
|
-
return {
|
|
31
|
-
api: this.api(),
|
|
32
|
-
expanded: false,
|
|
33
|
-
};
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
computed: {
|
|
37
|
-
id() {
|
|
38
|
-
return this.$parent.id;
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
mounted() {
|
|
43
|
-
this.api.registerAccordionButton(this);
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
methods: {
|
|
47
|
-
toggleExpanded() {
|
|
48
|
-
this.expanded = !this.expanded;
|
|
49
|
-
},
|
|
50
|
-
onClick() {
|
|
51
|
-
const accordion = this.api.selectedPanel(this.id);
|
|
52
|
-
this.toggleExpanded();
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
</script>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :id="id" class="accordion-group">
|
|
3
|
-
<slot></slot>
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script>
|
|
8
|
-
import { genId } from "../../utils/genId";
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
name: "VTAccordionGroup",
|
|
12
|
-
inject: ["api"],
|
|
13
|
-
|
|
14
|
-
data() {
|
|
15
|
-
return {
|
|
16
|
-
api: this.api(),
|
|
17
|
-
id: `group-${genId()}`,
|
|
18
|
-
};
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
mounted() {
|
|
22
|
-
this.api.registerAccordionGroup(this);
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
</script>
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:id="id"
|
|
4
|
-
:aria-labelledby="id"
|
|
5
|
-
v-show="active"
|
|
6
|
-
class="accordion-panel"
|
|
7
|
-
role="region"
|
|
8
|
-
>
|
|
9
|
-
<slot></slot>
|
|
10
|
-
</div>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script>
|
|
14
|
-
export default {
|
|
15
|
-
name: 'VTAccordionPanel',
|
|
16
|
-
inject: ['api'],
|
|
17
|
-
|
|
18
|
-
data() {
|
|
19
|
-
return {
|
|
20
|
-
api: this.api(),
|
|
21
|
-
active: false,
|
|
22
|
-
};
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
computed: {
|
|
26
|
-
id() {
|
|
27
|
-
return this.$parent.id;
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
mounted() {
|
|
32
|
-
this.api.registerAccordionPanel(this);
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
methods: {
|
|
36
|
-
multipleActive(){
|
|
37
|
-
this.active = !this.active;
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
show() {
|
|
41
|
-
if(this.active) {
|
|
42
|
-
this.active = false
|
|
43
|
-
} else {
|
|
44
|
-
this.active = true
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
hide() {
|
|
49
|
-
this.active = false;
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
</script>
|