-
-
Notifications
You must be signed in to change notification settings - Fork 51
Expand file tree
/
Copy pathCodeGroup.ts
More file actions
83 lines (72 loc) · 3.12 KB
/
CodeGroup.ts
File metadata and controls
83 lines (72 loc) · 3.12 KB
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
import { defineComponent, h, ref } from 'vue'
import type { Component, VNode } from 'vue'
export default defineComponent({
name: 'CodeGroup',
setup(_, { slots }) {
// index of current active item
const activeIndex = ref(-1)
return () => {
// NOTICE: here we put the `slots.default()` inside the render function to make
// the slots reactive, otherwise the slot content won't be changed once the
// `setup()` function of current component is called
// get children code-group-item
const items = (slots.default?.() || [])
.filter(vnode => (vnode.type as Component).name === 'CodeGroupItem')
.map((vnode) => {
if (vnode.props === null)
vnode.props = {}
return vnode as VNode & { props: Exclude<VNode['props'], null> }
})
// do not render anything if there is no code-group-item
if (items.length === 0)
return null
if (activeIndex.value < 0 || activeIndex.value > items.length - 1) {
// if `activeIndex` is invalid
// find the index of the code-group-item with `active` props
activeIndex.value = items.findIndex(
vnode => vnode.props.active === '' || vnode.props.active === true,
)
// if there is no `active` props on code-group-item, set the first item active
if (activeIndex.value === -1)
activeIndex.value = 0
}
else {
// set the active item
items.forEach((vnode, i) => {
vnode.props.active = i === activeIndex.value
})
}
return h('div', { class: 'code-group' }, [
h(
'div',
{ class: 'code-group__nav' },
h(
'ul',
{ class: 'code-group__ul' },
items.map((vnode, i) => {
const isActive = i === activeIndex.value
return h(
'li',
{ class: 'code-group__li' },
h(
'button',
{
class: {
'code-group__nav-tab': true,
'code-group__nav-tab-active': isActive,
},
ariaPressed: isActive,
ariaExpanded: isActive,
onClick: () => (activeIndex.value = i),
},
vnode.props.title,
),
)
}),
),
),
items,
])
}
},
})