@dolanske/vui 1.1.4 → 1.2.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/dist/components/Accordion/AccordionGroup.vue.d.ts +3 -17
- package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +1 -11
- package/dist/components/Kbd/KbdGroup.vue.d.ts +1 -6
- package/dist/components/Radio/RadioGroup.vue.d.ts +1 -6
- package/dist/components/Tabs/Tab.vue.d.ts +1 -1
- package/dist/components/Tabs/Tabs.vue.d.ts +1 -15
- package/dist/shared/slots.d.ts +20 -0
- package/dist/vui.css +1 -1
- package/dist/vui.js +2975 -2941
- package/package.json +12 -10
- package/src/components/Accordion/AccordionGroup.vue +18 -12
- package/src/components/Breadcrumbs/Breadcrumbs.vue +6 -7
- package/src/components/Button/button.scss +5 -0
- package/src/components/Divider/divider.scss +1 -1
- package/src/components/Dropdown/Dropdown.vue +0 -1
- package/src/components/Kbd/KbdGroup.vue +6 -5
- package/src/components/Radio/RadioGroup.vue +5 -11
- package/src/components/Select/Select.vue +2 -2
- package/src/components/Select/select.scss +1 -0
- package/src/components/Sidebar/Sidebar.vue +7 -6
- package/src/components/Tabs/Tab.vue +4 -4
- package/src/components/Tabs/Tabs.vue +14 -14
- package/src/components/Tabs/tabs.scss +2 -2
- package/src/examples/ExampleAccordions.vue +13 -15
- package/src/examples/ExampleButtons.vue +11 -3
- package/src/examples/ExampleFlexGrid.vue +4 -4
- package/src/examples/ExampleInputs.vue +3 -1
- package/src/examples/ExamplePopouts.vue +2 -2
- package/src/examples/ExampleSidebars.vue +10 -4
- package/src/examples/ExampleTabs.vue +37 -32
- package/src/shared/slots.ts +61 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Icon } from '@iconify/vue'
|
|
3
3
|
import { ref } from 'vue'
|
|
4
4
|
import Button from '../components/Button/Button.vue'
|
|
5
|
+
import Flex from '../components/Flex/Flex.vue'
|
|
5
6
|
import Tab from '../components/Tabs/Tab.vue'
|
|
6
7
|
import Tabs from '../components/Tabs/Tabs.vue'
|
|
7
8
|
// import Flex from '../components/Flex/Flex.vue'
|
|
@@ -9,8 +10,8 @@ import Tabs from '../components/Tabs/Tabs.vue'
|
|
|
9
10
|
const activeTab = ref('Home')
|
|
10
11
|
|
|
11
12
|
// Dynamic test
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
const dynamicTabs = ref(['First', 'Second', 'Third'])
|
|
14
|
+
const activeDynamic = ref(dynamicTabs.value[0])
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
17
|
<template>
|
|
@@ -24,9 +25,9 @@ const activeTab = ref('Home')
|
|
|
24
25
|
<th>Base</th>
|
|
25
26
|
<td>
|
|
26
27
|
<Tabs v-model="activeTab">
|
|
27
|
-
<Tab
|
|
28
|
-
<Tab
|
|
29
|
-
<Tab
|
|
28
|
+
<Tab value="Home" />
|
|
29
|
+
<Tab value="About" />
|
|
30
|
+
<Tab value="You" />
|
|
30
31
|
</Tabs>
|
|
31
32
|
</td>
|
|
32
33
|
</tr>
|
|
@@ -34,9 +35,9 @@ const activeTab = ref('Home')
|
|
|
34
35
|
<th>Filled</th>
|
|
35
36
|
<td>
|
|
36
37
|
<Tabs v-model="activeTab" variant="filled">
|
|
37
|
-
<Tab
|
|
38
|
-
<Tab
|
|
39
|
-
<Tab
|
|
38
|
+
<Tab value="Home" />
|
|
39
|
+
<Tab value="About" />
|
|
40
|
+
<Tab value="You" />
|
|
40
41
|
</Tabs>
|
|
41
42
|
</td>
|
|
42
43
|
</tr>
|
|
@@ -44,17 +45,17 @@ const activeTab = ref('Home')
|
|
|
44
45
|
<th>Expanded</th>
|
|
45
46
|
<td class="w-100">
|
|
46
47
|
<Tabs v-model="activeTab" expand>
|
|
47
|
-
<Tab
|
|
48
|
-
<Tab
|
|
49
|
-
<Tab
|
|
48
|
+
<Tab value="Home" />
|
|
49
|
+
<Tab value="About" />
|
|
50
|
+
<Tab value="You" />
|
|
50
51
|
</Tabs>
|
|
51
52
|
|
|
52
53
|
<div class="mb-xl" />
|
|
53
54
|
|
|
54
55
|
<Tabs v-model="activeTab" expand variant="filled">
|
|
55
|
-
<Tab
|
|
56
|
-
<Tab
|
|
57
|
-
<Tab
|
|
56
|
+
<Tab value="Home" />
|
|
57
|
+
<Tab value="About" />
|
|
58
|
+
<Tab value="You" />
|
|
58
59
|
</Tabs>
|
|
59
60
|
</td>
|
|
60
61
|
</tr>
|
|
@@ -70,17 +71,17 @@ const activeTab = ref('Home')
|
|
|
70
71
|
Sidebar
|
|
71
72
|
</Button>
|
|
72
73
|
</template>
|
|
73
|
-
<Tab
|
|
74
|
-
<Tab
|
|
75
|
-
<Tab
|
|
74
|
+
<Tab value="Home" />
|
|
75
|
+
<Tab value="About" />
|
|
76
|
+
<Tab value="You" />
|
|
76
77
|
</Tabs>
|
|
77
78
|
|
|
78
79
|
<div class="mb-xl" />
|
|
79
80
|
|
|
80
81
|
<Tabs v-model="activeTab" variant="filled">
|
|
81
|
-
<Tab
|
|
82
|
-
<Tab
|
|
83
|
-
<Tab
|
|
82
|
+
<Tab value="Home" />
|
|
83
|
+
<Tab value="About" />
|
|
84
|
+
<Tab value="You" />
|
|
84
85
|
|
|
85
86
|
<template #end>
|
|
86
87
|
<Button icon="ph:x" plain />
|
|
@@ -100,17 +101,17 @@ const activeTab = ref('Home')
|
|
|
100
101
|
Sidebar
|
|
101
102
|
</Button>
|
|
102
103
|
</template>
|
|
103
|
-
<Tab
|
|
104
|
-
<Tab
|
|
105
|
-
<Tab
|
|
104
|
+
<Tab value="Home" />
|
|
105
|
+
<Tab value="About" />
|
|
106
|
+
<Tab value="You" />
|
|
106
107
|
</Tabs>
|
|
107
108
|
|
|
108
109
|
<div class="mb-xl" />
|
|
109
110
|
|
|
110
111
|
<Tabs v-model="activeTab" expand variant="filled">
|
|
111
|
-
<Tab
|
|
112
|
-
<Tab
|
|
113
|
-
<Tab
|
|
112
|
+
<Tab value="Home" />
|
|
113
|
+
<Tab value="About" />
|
|
114
|
+
<Tab value="You" />
|
|
114
115
|
|
|
115
116
|
<template #end>
|
|
116
117
|
<Button icon="ph:x" plain />
|
|
@@ -118,18 +119,22 @@ const activeTab = ref('Home')
|
|
|
118
119
|
</Tabs>
|
|
119
120
|
</td>
|
|
120
121
|
</tr>
|
|
121
|
-
|
|
122
|
+
<tr>
|
|
122
123
|
<th>Dynamic</th>
|
|
123
124
|
<td>
|
|
124
125
|
<Flex>
|
|
125
|
-
<Button @click="dynamicTabs.push(`Tab ${dynamicTabs.length}`)">
|
|
126
|
-
|
|
126
|
+
<Button @click="dynamicTabs.push(`Tab ${dynamicTabs.length}`)">
|
|
127
|
+
Add
|
|
128
|
+
</Button>
|
|
129
|
+
<Button @click="dynamicTabs.shift()">
|
|
130
|
+
Remove
|
|
131
|
+
</Button>
|
|
127
132
|
</Flex>
|
|
128
|
-
<Tabs v-model="
|
|
129
|
-
<Tab v-for="tab in dynamicTabs" />
|
|
133
|
+
<Tabs v-model="activeDynamic">
|
|
134
|
+
<Tab v-for="tab in dynamicTabs" :key="tab" :value="tab" />
|
|
130
135
|
</Tabs>
|
|
131
136
|
</td>
|
|
132
|
-
</tr>
|
|
137
|
+
</tr>
|
|
133
138
|
</tbody>
|
|
134
139
|
</table>
|
|
135
140
|
</div>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ShallowRef, VNode } from 'vue'
|
|
2
|
+
import { computed, Fragment, shallowRef, watchEffect } from 'vue'
|
|
3
|
+
|
|
4
|
+
type VNodesProps<T extends object> = Array<VNode & { props: T }>
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Flattens slot children and keeps them in sync reactively.
|
|
8
|
+
* @param slotFn The slot function (e.g., slots.default)
|
|
9
|
+
* @returns Computed array of flattened VNodes
|
|
10
|
+
*/
|
|
11
|
+
export function useFlattenedSlot<T extends object>(slotFn?: () => VNode[] | undefined): ShallowRef<VNodesProps<T>> {
|
|
12
|
+
const rawChildren = shallowRef<VNodesProps<T>>([])
|
|
13
|
+
|
|
14
|
+
// Flatten VNodes recursively (handles Fragments)
|
|
15
|
+
function flatten(vnodes: VNode[]): VNodesProps<T> {
|
|
16
|
+
const result: VNode[] = []
|
|
17
|
+
|
|
18
|
+
const walk = (nodes: VNode[] | VNode | undefined): void => {
|
|
19
|
+
if (!nodes)
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
if (Array.isArray(nodes)) {
|
|
23
|
+
nodes.forEach(walk)
|
|
24
|
+
}
|
|
25
|
+
else if (nodes.type === Fragment || Array.isArray(nodes.children)) {
|
|
26
|
+
walk(nodes.children as VNode[])
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
result.push(nodes)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
walk(vnodes)
|
|
34
|
+
return result as VNodesProps<T>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Re-compute children whenever slot content changes
|
|
38
|
+
watchEffect(() => {
|
|
39
|
+
const content = slotFn?.() ?? []
|
|
40
|
+
rawChildren.value = flatten(content)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return computed(() => rawChildren.value)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Checks whether all of the provided VNodes are of the same type. Throws an
|
|
48
|
+
* error if not. This function should be used in components that only allow a
|
|
49
|
+
* single type of component
|
|
50
|
+
*
|
|
51
|
+
* @param vnodes Array of VNodes to check
|
|
52
|
+
* @param name Expected name of the components
|
|
53
|
+
*/
|
|
54
|
+
export function enforceSlotType(vnodes: ShallowRef<VNodesProps<any>>, name: string): void {
|
|
55
|
+
watchEffect(() => {
|
|
56
|
+
// @ts-expect-error Accessing internals
|
|
57
|
+
if (vnodes.value.some(item => item.type.__name !== name)) {
|
|
58
|
+
throw new Error(`You can only pass \`<${name} />\` components as children.`)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|