-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathslds-accordion.vue
131 lines (113 loc) · 4.17 KB
/
slds-accordion.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<template>
<ul class="slds-accordion">
<slot>
<slds-accordion-section
v-for="section of sections"
:key="section.id"
:content="section.content"
:label="section.label"
:name="section.name"
/>
</slot>
</ul>
</template>
<script lang="ts">
import SldsAccordionSection from "./slds-accordion-section.vue"
import { defineComponent } from "vue"
import type { PropType } from "vue"
import type { AccordionSection } from "./accordion-section"
export default defineComponent({
name: "SldsAccordion",
components: {
SldsAccordionSection,
},
props: {
/**
* Expands the specified accordion section passing in a string for a single section.
* By default, only the first section in the accordion is expanded.
*/
activeSectionName: String,
/**
* Expands the specified accordion sections passing in a list of section names.
* To support multiple expanded sections, include allow-multiple-sections-open in your markup.
* By default, only the first section in the accordion is expanded.
*/
activeSectionNames: { type: Array as PropType<string[]>, default: () => [] as string[] },
/**
* If present, the accordion allows multiple open sections.
* Otherwise, opening a section closes another that's currently open.
*/
allowMultipleSectionsOpen: Boolean,
/**
* Accordion sections.
*/
sections: Array as PropType<AccordionSection[]>,
},
data() {
return {
/**
* Private variable to track the active section name.
*/
internalActiveSectionName: this.activeSectionName,
/**
* Private variable to track the active section names.
*/
internalActiveSectionNames: this.activeSectionNames,
}
},
watch: {
/**
* Watch for changes to the active section name.
* @param activeSectionName The new active section name.
*/
activeSectionName(activeSectionName: string): void {
if (this.internalActiveSectionName === activeSectionName) return
this.internalActiveSectionName = activeSectionName
this.handleActiveSectionChange(activeSectionName)
},
/**
* Watch for changes to the active section names.
* @param activeSectionNames The new active section names.
*/
activeSectionNames(activeSectionNames: string[]) {
if (this.internalActiveSectionNames === activeSectionNames) return
this.internalActiveSectionNames = activeSectionNames
this.handleActiveSectionChange(activeSectionNames)
},
/**
* Watch for changes to the sections.
*/
sections: {
deep: true,
handler() {
if (this.allowMultipleSectionsOpen) this.handleActiveSectionChange(this.activeSectionNames)
else this.handleActiveSectionChange(this.activeSectionName)
},
},
},
methods: {
/**
* Handles the active section change event.
* @param input New section name.
*/
handleActiveSectionChange(input: string | string[] | undefined): void {
if (this.allowMultipleSectionsOpen) {
if (!Array.isArray(input)) {
throw Error(`Accordion expected an array of string but got ${input}`)
}
for (const sectionName of input) {
const index = this.internalActiveSectionNames.indexOf(sectionName)
if (index === -1) this.internalActiveSectionNames.push(sectionName)
else this.internalActiveSectionNames.splice(index, 1)
}
}
else {
this.internalActiveSectionName = (this.internalActiveSectionName !== input)
? input as string
: undefined
}
this.$emit("active-section-change", input)
},
},
})
</script>