Skip to content

Commit

Permalink
fix(types): add missing generic types
Browse files Browse the repository at this point in the history
fixes #17379
fixes #18666
  • Loading branch information
KaelWD committed Nov 13, 2023
1 parent 7d476d9 commit 8030d40
Show file tree
Hide file tree
Showing 36 changed files with 331 additions and 124 deletions.
17 changes: 11 additions & 6 deletions packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import type { VFieldSlots } from '@/components/VField/VField'
import type { VInputSlots } from '@/components/VInput/VInput'
import type { FilterMatch } from '@/composables/filter'
import type { ListItem } from '@/composables/list-items'
import type { GenericProps } from '@/util'
import type { GenericProps, SelectItemKey } from '@/util'

function highlightResult (text: string, matches: FilterMatch | undefined, length: number) {
if (matches == null) return text
Expand Down Expand Up @@ -87,19 +87,24 @@ export const makeVAutocompleteProps = propsFactory({
...makeTransitionProps({ transition: false }),
}, 'VAutocomplete')

type ItemType<T> = T extends readonly (infer U)[] ? U : never

export const VAutocomplete = genericComponent<new <
T extends readonly any[],
Item = T extends readonly (infer U)[] ? U : never,
Item = ItemType<T>,
ReturnObject extends boolean = false,
Multiple extends boolean = false,
V extends Value<Item, ReturnObject, Multiple> = Value<Item, ReturnObject, Multiple>
>(
props: {
items?: T
itemTitle?: SelectItemKey<ItemType<T>>
itemValue?: SelectItemKey<ItemType<T>>
itemProps?: SelectItemKey<ItemType<T>>
returnObject?: ReturnObject
multiple?: Multiple
modelValue?: V | null
'onUpdate:modelValue'?: (val: V) => void
'onUpdate:modelValue'?: (value: V) => void
},
slots: Omit<VInputSlots & VFieldSlots, 'default'> & {
item: { item: ListItem<Item>, index: number, props: Record<string, unknown> }
Expand All @@ -116,9 +121,9 @@ export const VAutocomplete = genericComponent<new <

emits: {
'update:focused': (focused: boolean) => true,
'update:search': (val: any) => true,
'update:modelValue': (val: any) => true,
'update:menu': (val: boolean) => true,
'update:search': (value: any) => true,
'update:modelValue': (value: any) => true,
'update:menu': (value: boolean) => true,
},

setup (props, { slots }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import { makeThemeProps, useTheme } from '@/composables/theme'
import { computed, toRef } from 'vue'
import { convertToUnit, genericComponent, propsFactory, useRender } from '@/util'

// Types
import type { GenericProps } from '@/util'

export const makeVBottomNavigationProps = propsFactory({
bgColor: String,
color: String,
Expand Down Expand Up @@ -53,7 +56,13 @@ export const makeVBottomNavigationProps = propsFactory({
...makeThemeProps(),
}, 'VBottomNavigation')

export const VBottomNavigation = genericComponent()({
export const VBottomNavigation = genericComponent<new <T>(
props: {
modelValue?: T
'onUpdate:modelValue'?: (value: T) => void
},
slots: { default: never },
) => GenericProps<typeof props, typeof slots>>()({
name: 'VBottomNavigation',

props: makeVBottomNavigationProps(),
Expand Down
11 changes: 9 additions & 2 deletions packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { genericComponent, propsFactory, useRender } from '@/util'
// Types
import type { InjectionKey } from 'vue'
import type { GroupProvide } from '@/composables/group'
import type { GenericProps } from '@/util'

export type BtnToggleSlotProps = 'isSelected' | 'select' | 'selected' | 'next' | 'prev'
export interface DefaultBtnToggleSlot extends Pick<GroupProvide, BtnToggleSlotProps> {}
Expand All @@ -28,7 +29,13 @@ export const makeVBtnToggleProps = propsFactory({
...makeGroupProps(),
}, 'VBtnToggle')

export const VBtnToggle = genericComponent<VBtnToggleSlots>()({
export const VBtnToggle = genericComponent<new <T>(
props: {
modelValue?: T
'onUpdate:modelValue'?: (value: T) => void
},
slots: VBtnToggleSlots,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VBtnToggle',

props: makeVBtnToggleProps(),
Expand Down Expand Up @@ -58,7 +65,7 @@ export const VBtnToggle = genericComponent<VBtnToggleSlots>()({
prev,
select,
selected,
} as DefaultBtnToggleSlot)}
})}
</VBtnGroup>
)
})
Expand Down
11 changes: 9 additions & 2 deletions packages/vuetify/src/components/VCarousel/VCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { convertToUnit, genericComponent, propsFactory, useRender } from '@/util
import type { PropType } from 'vue'
import type { VWindowSlots } from '@/components/VWindow/VWindow'
import type { GroupProvide } from '@/composables/group'
import type { GenericProps } from '@/util'

export const makeVCarouselProps = propsFactory({
color: String,
Expand Down Expand Up @@ -60,13 +61,19 @@ type VCarouselSlots = VWindowSlots & {
}
}

export const VCarousel = genericComponent<VCarouselSlots>()({
export const VCarousel = genericComponent<new <T>(
props: {
modelValue?: T
'onUpdate:modelValue'?: (value: T) => void
},
slots: VCarouselSlots,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VCarousel',

props: makeVCarouselProps(),

emits: {
'update:modelValue': (val: any) => true,
'update:modelValue': (value: any) => true,
},

setup (props, { slots }) {
Expand Down
11 changes: 9 additions & 2 deletions packages/vuetify/src/components/VCheckbox/VCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { filterInputAttrs, genericComponent, getUid, omit, propsFactory, useRend
// Types
import type { VSelectionControlSlots } from '../VSelectionControl/VSelectionControl'
import type { VInputSlots } from '@/components/VInput/VInput'
import type { GenericProps } from '@/util'

export type VCheckboxSlots = Omit<VInputSlots, 'default'> & VSelectionControlSlots

Expand All @@ -24,15 +25,21 @@ export const makeVCheckboxProps = propsFactory({
...omit(makeVCheckboxBtnProps(), ['inline']),
}, 'VCheckbox')

export const VCheckbox = genericComponent<VCheckboxSlots>()({
export const VCheckbox = genericComponent<new <T>(
props: {
modelValue?: T | null
'onUpdate:modelValue'?: (value: T | null) => void
},
slots: VCheckboxSlots,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VCheckbox',

inheritAttrs: false,

props: makeVCheckboxProps(),

emits: {
'update:modelValue': (value: boolean) => true,
'update:modelValue': (value: any) => true,
'update:focused': (focused: boolean) => true,
},

Expand Down
11 changes: 9 additions & 2 deletions packages/vuetify/src/components/VCheckbox/VCheckboxBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { genericComponent, omit, propsFactory, useRender } from '@/util'

// Types
import type { VSelectionControlSlots } from '@/components/VSelectionControl/VSelectionControl'
import type { GenericProps } from '@/util'

export const makeVCheckboxBtnProps = propsFactory({
indeterminate: Boolean,
Expand All @@ -25,14 +26,20 @@ export const makeVCheckboxBtnProps = propsFactory({
}),
}, 'VCheckboxBtn')

export const VCheckboxBtn = genericComponent<VSelectionControlSlots>()({
export const VCheckboxBtn = genericComponent<new <T>(
props: {
modelValue?: T
'onUpdate:modelValue'?: (value: T) => void
},
slots: VSelectionControlSlots,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VCheckboxBtn',

props: makeVCheckboxBtnProps(),

emits: {
'update:modelValue': (value: any) => true,
'update:indeterminate': (val: boolean) => true,
'update:indeterminate': (value: boolean) => true,
},

setup (props, { slots }) {
Expand Down
9 changes: 8 additions & 1 deletion packages/vuetify/src/components/VChipGroup/VChipGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { deepEqual, genericComponent, propsFactory, useRender } from '@/util'

// Types
import type { PropType } from 'vue'
import type { GenericProps } from '@/util'

export const VChipGroupSymbol = Symbol.for('vuetify:v-chip-group')

Expand Down Expand Up @@ -43,7 +44,13 @@ type VChipGroupSlots = {
}
}

export const VChipGroup = genericComponent<VChipGroupSlots>()({
export const VChipGroup = genericComponent<new <T>(
props: {
modelValue?: T
'onUpdate:modelValue'?: (value: T) => void
},
slots: VChipGroupSlots,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VChipGroup',

props: makeVChipGroupProps(),
Expand Down
17 changes: 11 additions & 6 deletions packages/vuetify/src/components/VCombobox/VCombobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import type { VFieldSlots } from '@/components/VField/VField'
import type { VInputSlots } from '@/components/VInput/VInput'
import type { FilterMatch } from '@/composables/filter'
import type { ListItem } from '@/composables/list-items'
import type { GenericProps } from '@/util'
import type { GenericProps, SelectItemKey } from '@/util'

function highlightResult (text: string, matches: FilterMatch | undefined, length: number) {
if (matches == null) return text
Expand Down Expand Up @@ -88,19 +88,24 @@ export const makeVComboboxProps = propsFactory({
...makeTransitionProps({ transition: false }),
}, 'VCombobox')

type ItemType<T> = T extends readonly (infer U)[] ? U : never

export const VCombobox = genericComponent<new <
T extends readonly any[],
Item = T extends readonly (infer U)[] ? U : never,
Item = ItemType<T>,
ReturnObject extends boolean = true,
Multiple extends boolean = false,
V extends Value<Item, ReturnObject, Multiple> = Value<Item, ReturnObject, Multiple>
>(
props: {
items?: T
itemTitle?: SelectItemKey<ItemType<T>>
itemValue?: SelectItemKey<ItemType<T>>
itemProps?: SelectItemKey<ItemType<T>>
returnObject?: ReturnObject
multiple?: Multiple
modelValue?: V | null
'onUpdate:modelValue'?: (val: V) => void
'onUpdate:modelValue'?: (value: V) => void
},
slots: Omit<VInputSlots & VFieldSlots, 'default'> & {
item: { item: ListItem<Item>, index: number, props: Record<string, unknown> }
Expand All @@ -117,9 +122,9 @@ export const VCombobox = genericComponent<new <

emits: {
'update:focused': (focused: boolean) => true,
'update:modelValue': (val: any) => true,
'update:search': (val: string) => true,
'update:menu': (val: boolean) => true,
'update:modelValue': (value: any) => true,
'update:search': (value: string) => true,
'update:menu': (value: boolean) => true,
},

setup (props, { emit, slots }) {
Expand Down
48 changes: 31 additions & 17 deletions packages/vuetify/src/components/VDataTable/VDataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import { genericComponent, propsFactory, useRender } from '@/util'
// Types
import type { UnwrapRef } from 'vue'
import type { Group } from './composables/group'
import type { DataTableItem, InternalDataTableHeader } from './types'
import type { CellProps, DataTableItem, InternalDataTableHeader, RowProps } from './types'
import type { VDataTableHeadersSlots } from './VDataTableHeaders'
import type { VDataTableRowsSlots } from './VDataTableRows'
import type { GenericProps, SelectItemKey } from '@/util'

export type VDataTableSlotProps = {
export type VDataTableSlotProps<T> = {
page: number
itemsPerPage: number
sortBy: UnwrapRef<ReturnType<typeof provideSort>['sortBy']>
Expand All @@ -47,24 +48,24 @@ export type VDataTableSlotProps = {
toggleExpand: ReturnType<typeof provideExpanded>['toggleExpand']
isGroupOpen: ReturnType<typeof provideGroupBy>['isGroupOpen']
toggleGroup: ReturnType<typeof provideGroupBy>['toggleGroup']
items: readonly any[]
items: readonly T[]
internalItems: readonly DataTableItem[]
groupedItems: readonly (DataTableItem | Group<DataTableItem>)[]
groupedItems: readonly (DataTableItem<T> | Group<DataTableItem<T>>)[]
columns: InternalDataTableHeader[]
headers: InternalDataTableHeader[][]
}

export type VDataTableSlots = VDataTableRowsSlots & VDataTableHeadersSlots & {
default: VDataTableSlotProps
colgroup: VDataTableSlotProps
top: VDataTableSlotProps
body: VDataTableSlotProps
tbody: VDataTableSlotProps
thead: VDataTableSlotProps
tfoot: VDataTableSlotProps
bottom: VDataTableSlotProps
'body.prepend': VDataTableSlotProps
'body.append': VDataTableSlotProps
export type VDataTableSlots<T> = VDataTableRowsSlots<T> & VDataTableHeadersSlots & {
default: VDataTableSlotProps<T>
colgroup: VDataTableSlotProps<T>
top: VDataTableSlotProps<T>
body: VDataTableSlotProps<T>
tbody: VDataTableSlotProps<T>
thead: VDataTableSlotProps<T>
tfoot: VDataTableSlotProps<T>
bottom: VDataTableSlotProps<T>
'body.prepend': VDataTableSlotProps<T>
'body.append': VDataTableSlotProps<T>
'footer.prepend': never
}

Expand All @@ -91,7 +92,20 @@ export const makeVDataTableProps = propsFactory({
...makeVDataTableFooterProps(),
}, 'VDataTable')

export const VDataTable = genericComponent<VDataTableSlots>()({
type ItemType<T> = T extends readonly (infer U)[] ? U : never

export const VDataTable = genericComponent<new <T extends readonly any[], V>(
props: {
items?: T
itemValue?: SelectItemKey<ItemType<T>>
rowProps?: RowProps<ItemType<T>>
cellProps?: CellProps<ItemType<T>>
itemSelectable?: SelectItemKey<ItemType<T>>
modelValue?: V
'onUpdate:modelValue'?: (value: V) => void
},
slots: VDataTableSlots<ItemType<T>>,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VDataTable',

props: makeVDataTableProps(),
Expand Down Expand Up @@ -165,7 +179,7 @@ export const VDataTable = genericComponent<VDataTableSlots>()({
},
})

const slotProps = computed<VDataTableSlotProps>(() => ({
const slotProps = computed<VDataTableSlotProps<any>>(() => ({
page: page.value,
itemsPerPage: itemsPerPage.value,
sortBy: sortBy.value,
Expand Down
21 changes: 14 additions & 7 deletions packages/vuetify/src/components/VDataTable/VDataTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,29 @@ import { EventProp, genericComponent, getObjectValueByPath, propsFactory, useRen
// Types
import type { PropType } from 'vue'
import type { CellProps, DataTableItem, ItemKeySlot } from './types'
import type { GenericProps } from '@/util'

export type VDataTableRowSlots = {
'item.data-table-select': Omit<ItemKeySlot, 'value'>
'item.data-table-expand': Omit<ItemKeySlot, 'value'>
} & { [key: `item.${string}`]: ItemKeySlot }
export type VDataTableRowSlots<T> = {
'item.data-table-select': Omit<ItemKeySlot<T>, 'value'>
'item.data-table-expand': Omit<ItemKeySlot<T>, 'value'>
} & { [key: `item.${string}`]: ItemKeySlot<T> }

export const makeVDataTableRowProps = propsFactory({
index: Number,
item: Object as PropType<DataTableItem>,
cellProps: [Object, Function] as PropType<CellProps>,
cellProps: [Object, Function] as PropType<CellProps<any>>,
onClick: EventProp<[MouseEvent]>(),
onContextmenu: EventProp<[MouseEvent]>(),
onDblclick: EventProp<[MouseEvent]>(),
}, 'VDataTableRow')

export const VDataTableRow = genericComponent<VDataTableRowSlots>()({
export const VDataTableRow = genericComponent<new <T>(
props: {
item?: DataTableItem<T>
cellProps?: CellProps<T>
},
slots: VDataTableRowSlots<T>,
) => GenericProps<typeof props, typeof slots>>()({
name: 'VDataTableRow',

props: makeVDataTableRowProps(),
Expand Down Expand Up @@ -65,7 +72,7 @@ export const VDataTableRow = genericComponent<VDataTableRowSlots>()({
toggleSelect,
isExpanded,
toggleExpand,
} satisfies ItemKeySlot
} satisfies ItemKeySlot<any>

const cellProps = typeof props.cellProps === 'function'
? props.cellProps({
Expand Down
Loading

0 comments on commit 8030d40

Please sign in to comment.