Skip to content

Commit 877f323

Browse files
J-SekKaelWD
andauthored
feat(VTreeview): support item-type (#21709)
Co-authored-by: Kael <[email protected]>
1 parent f3dce45 commit 877f323

File tree

6 files changed

+46
-13
lines changed

6 files changed

+46
-13
lines changed

packages/vuetify/src/components/VTreeview/VTreeview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const makeVTreeviewProps = propsFactory({
4545
collapseIcon: '$treeviewCollapse',
4646
expandIcon: '$treeviewExpand',
4747
slim: true,
48-
}), ['itemType', 'nav', 'openStrategy']),
48+
}), ['nav', 'openStrategy']),
4949

5050
modelValue: Array,
5151
}, 'VTreeview')

packages/vuetify/src/components/VTreeview/VTreeviewChildren.tsx

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
import { VTreeviewGroup } from './VTreeviewGroup'
33
import { makeVTreeviewItemProps, VTreeviewItem } from './VTreeviewItem'
44
import { VCheckboxBtn } from '@/components/VCheckbox'
5+
import { VDivider } from '@/components/VDivider'
6+
import { VListSubheader } from '@/components/VList'
57

68
// Composables
79
import { makeDensityProps } from '@/composables/density'
810
import { IconValue } from '@/composables/icons'
911

1012
// Utilities
1113
import { computed, reactive, ref, toRaw } from 'vue'
12-
import { genericComponent, getIndentLines, pick, propsFactory } from '@/util'
14+
import { genericComponent, getIndentLines, pick, propsFactory, renderSlot } from '@/util'
1315

1416
// Types
1517
import type { PropType } from 'vue'
@@ -30,6 +32,8 @@ export type VTreeviewChildrenSlots<T> = {
3032
item: T
3133
internalItem: InternalListItem<T>
3234
}
35+
divider: { props: InternalListItem['props'] }
36+
subheader: { props: InternalListItem['props'] }
3337
}
3438

3539
export const makeVTreeviewChildrenProps = propsFactory({
@@ -217,16 +221,34 @@ export const VTreeviewChildren = genericComponent<new <T extends InternalListIte
217221
),
218222
}}
219223
</VTreeviewGroup>
220-
) : (
221-
slots.item?.({ props: itemProps, item: item.raw, internalItem: item }) ?? (
222-
<VTreeviewItem
223-
{ ...itemProps }
224-
hideActions={ props.hideActions }
225-
indentLines={ indentLines.leaf }
226-
value={ props.returnObject ? toRaw(item.raw) : itemProps.value }
227-
v-slots={ slotsWithItem }
228-
/>
229-
))
224+
) : renderSlot(
225+
slots.item,
226+
{ props: itemProps, item: item.raw, internalItem: item },
227+
() => {
228+
if (item.type === 'divider') {
229+
return renderSlot(
230+
slots.divider,
231+
{ props: item.raw },
232+
() => <VDivider { ...item.props } />,
233+
)
234+
}
235+
if (item.type === 'subheader') {
236+
return renderSlot(
237+
slots.subheader,
238+
{ props: item.raw },
239+
() => <VListSubheader { ...item.props } />,
240+
)
241+
}
242+
return (
243+
<VTreeviewItem
244+
{ ...itemProps }
245+
hideActions={ props.hideActions }
246+
indentLines={ indentLines.leaf }
247+
value={ props.returnObject ? toRaw(item.raw) : itemProps.value }
248+
v-slots={ slotsWithItem }
249+
/>
250+
)
251+
})
230252
})
231253
},
232254
})

packages/vuetify/src/composables/__tests__/filter.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { deepEqual } from '@/util'
99
const itemProps = {
1010
itemTitle: 'title',
1111
itemValue: 'value',
12+
itemType: 'type',
1213
itemChildren: 'children',
1314
itemProps: 'props',
1415
returnObject: false,

packages/vuetify/src/composables/__tests__/list-items.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ describe('list-items', () => {
88
const defaults = {
99
itemTitle: 'title',
1010
itemValue: 'value',
11+
itemType: 'type',
1112
itemChildren: 'children',
1213
itemProps: () => ({}),
1314
returnObject: false,

packages/vuetify/src/composables/list-items.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export interface ItemProps {
2424
itemValue: SelectItemKey
2525
itemChildren: SelectItemKey
2626
itemProps: SelectItemKey
27-
itemType?: SelectItemKey
27+
itemType: SelectItemKey
2828
returnObject: boolean
2929
valueComparator: typeof deepEqual | undefined
3030
}

packages/vuetify/src/util/helpers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,15 @@ export function ensureValidVNode (vnodes: VNodeArrayChildren): VNodeArrayChildre
721721
: null
722722
}
723723

724+
type Slot<T> = [T] extends [never] ? () => VNodeChild : (arg: T) => VNodeChild
725+
726+
export function renderSlot <T> (slot: Slot<never> | undefined, fallback?: Slot<never> | undefined): VNodeChild
727+
export function renderSlot <T> (slot: Slot<T> | undefined, props: T, fallback?: Slot<T> | undefined): VNodeChild
728+
export function renderSlot (slot?: Slot<unknown>, props?: unknown, fallback?: Slot<unknown>) {
729+
// TODO: check if slot returns elements: #18308
730+
return slot?.(props) ?? fallback?.(props)
731+
}
732+
724733
export function defer (timeout: number, cb: () => void) {
725734
if (!IN_BROWSER || timeout === 0) {
726735
cb()

0 commit comments

Comments
 (0)