From 8030d407c5767f96c0474d94828b2a79b40e7c17 Mon Sep 17 00:00:00 2001 From: Kael Date: Tue, 14 Nov 2023 03:01:56 +1100 Subject: [PATCH] fix(types): add missing generic types fixes #17379 fixes #18666 --- .../VAutocomplete/VAutocomplete.tsx | 17 ++++--- .../VBottomNavigation/VBottomNavigation.tsx | 11 ++++- .../src/components/VBtnToggle/VBtnToggle.tsx | 11 ++++- .../src/components/VCarousel/VCarousel.tsx | 11 ++++- .../src/components/VCheckbox/VCheckbox.tsx | 11 ++++- .../src/components/VCheckbox/VCheckboxBtn.tsx | 11 ++++- .../src/components/VChipGroup/VChipGroup.tsx | 9 +++- .../src/components/VCombobox/VCombobox.tsx | 17 ++++--- .../src/components/VDataTable/VDataTable.tsx | 48 ++++++++++++------- .../components/VDataTable/VDataTableRow.tsx | 21 +++++--- .../components/VDataTable/VDataTableRows.tsx | 20 +++++--- .../VDataTable/VDataTableServer.tsx | 19 +++++++- .../VDataTable/VDataTableVirtual.tsx | 41 ++++++++++++---- .../VDataTable/composables/items.ts | 4 +- .../VDataTable/composables/paginate.ts | 5 +- .../VDataTable/composables/select.ts | 3 +- .../src/components/VDataTable/types.ts | 16 +++---- .../vuetify/src/components/VField/VField.tsx | 4 +- .../vuetify/src/components/VInput/VInput.tsx | 11 ++++- .../src/components/VItemGroup/VItemGroup.tsx | 11 ++++- .../vuetify/src/components/VList/VList.tsx | 26 +++++++--- .../components/VRadioGroup/VRadioGroup.tsx | 11 ++++- .../src/components/VSelect/VSelect.tsx | 15 ++++-- .../VSelectionControl/VSelectionControl.tsx | 10 ++-- .../VSelectionControlGroup.tsx | 11 ++++- .../components/VSlideGroup/VSlideGroup.tsx | 9 +++- .../src/components/VSwitch/VSwitch.tsx | 13 +++-- .../components/VValidation/VValidation.tsx | 13 ++++- .../src/components/VWindow/VWindow.tsx | 11 ++++- packages/vuetify/src/composables/form.ts | 3 +- packages/vuetify/src/composables/group.ts | 5 +- .../vuetify/src/composables/nested/nested.ts | 5 +- .../vuetify/src/composables/proxiedModel.ts | 3 +- .../vuetify/src/composables/validation.ts | 4 +- packages/vuetify/src/util/defineComponent.tsx | 9 +++- packages/vuetify/src/util/helpers.ts | 6 +-- 36 files changed, 331 insertions(+), 124 deletions(-) diff --git a/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx b/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx index 231a07e568c..ca23d6be456 100644 --- a/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx +++ b/packages/vuetify/src/components/VAutocomplete/VAutocomplete.tsx @@ -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 @@ -87,19 +87,24 @@ export const makeVAutocompleteProps = propsFactory({ ...makeTransitionProps({ transition: false }), }, 'VAutocomplete') +type ItemType = T extends readonly (infer U)[] ? U : never + export const VAutocomplete = genericComponent, ReturnObject extends boolean = false, Multiple extends boolean = false, V extends Value = Value >( props: { items?: T + itemTitle?: SelectItemKey> + itemValue?: SelectItemKey> + itemProps?: SelectItemKey> returnObject?: ReturnObject multiple?: Multiple modelValue?: V | null - 'onUpdate:modelValue'?: (val: V) => void + 'onUpdate:modelValue'?: (value: V) => void }, slots: Omit & { item: { item: ListItem, index: number, props: Record } @@ -116,9 +121,9 @@ export const VAutocomplete = genericComponent 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 }) { diff --git a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx index 246cdbc8e2d..d666b124eaf 100644 --- a/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx +++ b/packages/vuetify/src/components/VBottomNavigation/VBottomNavigation.tsx @@ -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, @@ -53,7 +56,13 @@ export const makeVBottomNavigationProps = propsFactory({ ...makeThemeProps(), }, 'VBottomNavigation') -export const VBottomNavigation = genericComponent()({ +export const VBottomNavigation = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: { default: never }, +) => GenericProps>()({ name: 'VBottomNavigation', props: makeVBottomNavigationProps(), diff --git a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx index 2d53f04e8d6..4cb26d25755 100644 --- a/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx +++ b/packages/vuetify/src/components/VBtnToggle/VBtnToggle.tsx @@ -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 {} @@ -28,7 +29,13 @@ export const makeVBtnToggleProps = propsFactory({ ...makeGroupProps(), }, 'VBtnToggle') -export const VBtnToggle = genericComponent()({ +export const VBtnToggle = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VBtnToggleSlots, +) => GenericProps>()({ name: 'VBtnToggle', props: makeVBtnToggleProps(), @@ -58,7 +65,7 @@ export const VBtnToggle = genericComponent()({ prev, select, selected, - } as DefaultBtnToggleSlot)} + })} ) }) diff --git a/packages/vuetify/src/components/VCarousel/VCarousel.tsx b/packages/vuetify/src/components/VCarousel/VCarousel.tsx index c6587fd0944..bfdaccf6b26 100644 --- a/packages/vuetify/src/components/VCarousel/VCarousel.tsx +++ b/packages/vuetify/src/components/VCarousel/VCarousel.tsx @@ -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, @@ -60,13 +61,19 @@ type VCarouselSlots = VWindowSlots & { } } -export const VCarousel = genericComponent()({ +export const VCarousel = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VCarouselSlots, +) => GenericProps>()({ name: 'VCarousel', props: makeVCarouselProps(), emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/components/VCheckbox/VCheckbox.tsx b/packages/vuetify/src/components/VCheckbox/VCheckbox.tsx index c5d292b06d2..d188ade61ba 100644 --- a/packages/vuetify/src/components/VCheckbox/VCheckbox.tsx +++ b/packages/vuetify/src/components/VCheckbox/VCheckbox.tsx @@ -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 & VSelectionControlSlots @@ -24,7 +25,13 @@ export const makeVCheckboxProps = propsFactory({ ...omit(makeVCheckboxBtnProps(), ['inline']), }, 'VCheckbox') -export const VCheckbox = genericComponent()({ +export const VCheckbox = genericComponent( + props: { + modelValue?: T | null + 'onUpdate:modelValue'?: (value: T | null) => void + }, + slots: VCheckboxSlots, +) => GenericProps>()({ name: 'VCheckbox', inheritAttrs: false, @@ -32,7 +39,7 @@ export const VCheckbox = genericComponent()({ props: makeVCheckboxProps(), emits: { - 'update:modelValue': (value: boolean) => true, + 'update:modelValue': (value: any) => true, 'update:focused': (focused: boolean) => true, }, diff --git a/packages/vuetify/src/components/VCheckbox/VCheckboxBtn.tsx b/packages/vuetify/src/components/VCheckbox/VCheckboxBtn.tsx index 9177f363940..98f74f291c9 100644 --- a/packages/vuetify/src/components/VCheckbox/VCheckboxBtn.tsx +++ b/packages/vuetify/src/components/VCheckbox/VCheckboxBtn.tsx @@ -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, @@ -25,14 +26,20 @@ export const makeVCheckboxBtnProps = propsFactory({ }), }, 'VCheckboxBtn') -export const VCheckboxBtn = genericComponent()({ +export const VCheckboxBtn = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VSelectionControlSlots, +) => GenericProps>()({ name: 'VCheckboxBtn', props: makeVCheckboxBtnProps(), emits: { 'update:modelValue': (value: any) => true, - 'update:indeterminate': (val: boolean) => true, + 'update:indeterminate': (value: boolean) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx index bd535c739ea..7a30c413ecb 100644 --- a/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx +++ b/packages/vuetify/src/components/VChipGroup/VChipGroup.tsx @@ -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') @@ -43,7 +44,13 @@ type VChipGroupSlots = { } } -export const VChipGroup = genericComponent()({ +export const VChipGroup = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VChipGroupSlots, +) => GenericProps>()({ name: 'VChipGroup', props: makeVChipGroupProps(), diff --git a/packages/vuetify/src/components/VCombobox/VCombobox.tsx b/packages/vuetify/src/components/VCombobox/VCombobox.tsx index b78f52d66fb..996349902d4 100644 --- a/packages/vuetify/src/components/VCombobox/VCombobox.tsx +++ b/packages/vuetify/src/components/VCombobox/VCombobox.tsx @@ -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 @@ -88,19 +88,24 @@ export const makeVComboboxProps = propsFactory({ ...makeTransitionProps({ transition: false }), }, 'VCombobox') +type ItemType = T extends readonly (infer U)[] ? U : never + export const VCombobox = genericComponent, ReturnObject extends boolean = true, Multiple extends boolean = false, V extends Value = Value >( props: { items?: T + itemTitle?: SelectItemKey> + itemValue?: SelectItemKey> + itemProps?: SelectItemKey> returnObject?: ReturnObject multiple?: Multiple modelValue?: V | null - 'onUpdate:modelValue'?: (val: V) => void + 'onUpdate:modelValue'?: (value: V) => void }, slots: Omit & { item: { item: ListItem, index: number, props: Record } @@ -117,9 +122,9 @@ export const VCombobox = genericComponent 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 }) { diff --git a/packages/vuetify/src/components/VDataTable/VDataTable.tsx b/packages/vuetify/src/components/VDataTable/VDataTable.tsx index 10da003c44f..4a7402407bc 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTable.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTable.tsx @@ -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 = { page: number itemsPerPage: number sortBy: UnwrapRef['sortBy']> @@ -47,24 +48,24 @@ export type VDataTableSlotProps = { toggleExpand: ReturnType['toggleExpand'] isGroupOpen: ReturnType['isGroupOpen'] toggleGroup: ReturnType['toggleGroup'] - items: readonly any[] + items: readonly T[] internalItems: readonly DataTableItem[] - groupedItems: readonly (DataTableItem | Group)[] + groupedItems: readonly (DataTableItem | Group>)[] 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 = VDataTableRowsSlots & VDataTableHeadersSlots & { + default: VDataTableSlotProps + colgroup: VDataTableSlotProps + top: VDataTableSlotProps + body: VDataTableSlotProps + tbody: VDataTableSlotProps + thead: VDataTableSlotProps + tfoot: VDataTableSlotProps + bottom: VDataTableSlotProps + 'body.prepend': VDataTableSlotProps + 'body.append': VDataTableSlotProps 'footer.prepend': never } @@ -91,7 +92,20 @@ export const makeVDataTableProps = propsFactory({ ...makeVDataTableFooterProps(), }, 'VDataTable') -export const VDataTable = genericComponent()({ +type ItemType = T extends readonly (infer U)[] ? U : never + +export const VDataTable = genericComponent( + props: { + items?: T + itemValue?: SelectItemKey> + rowProps?: RowProps> + cellProps?: CellProps> + itemSelectable?: SelectItemKey> + modelValue?: V + 'onUpdate:modelValue'?: (value: V) => void + }, + slots: VDataTableSlots>, +) => GenericProps>()({ name: 'VDataTable', props: makeVDataTableProps(), @@ -165,7 +179,7 @@ export const VDataTable = genericComponent()({ }, }) - const slotProps = computed(() => ({ + const slotProps = computed>(() => ({ page: page.value, itemsPerPage: itemsPerPage.value, sortBy: sortBy.value, diff --git a/packages/vuetify/src/components/VDataTable/VDataTableRow.tsx b/packages/vuetify/src/components/VDataTable/VDataTableRow.tsx index c6bc7816f6d..380a2454e28 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTableRow.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTableRow.tsx @@ -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 - 'item.data-table-expand': Omit -} & { [key: `item.${string}`]: ItemKeySlot } +export type VDataTableRowSlots = { + 'item.data-table-select': Omit, 'value'> + 'item.data-table-expand': Omit, 'value'> +} & { [key: `item.${string}`]: ItemKeySlot } export const makeVDataTableRowProps = propsFactory({ index: Number, item: Object as PropType, - cellProps: [Object, Function] as PropType, + cellProps: [Object, Function] as PropType>, onClick: EventProp<[MouseEvent]>(), onContextmenu: EventProp<[MouseEvent]>(), onDblclick: EventProp<[MouseEvent]>(), }, 'VDataTableRow') -export const VDataTableRow = genericComponent()({ +export const VDataTableRow = genericComponent( + props: { + item?: DataTableItem + cellProps?: CellProps + }, + slots: VDataTableRowSlots, +) => GenericProps>()({ name: 'VDataTableRow', props: makeVDataTableRowProps(), @@ -65,7 +72,7 @@ export const VDataTableRow = genericComponent()({ toggleSelect, isExpanded, toggleExpand, - } satisfies ItemKeySlot + } satisfies ItemKeySlot const cellProps = typeof props.cellProps === 'function' ? props.cellProps({ diff --git a/packages/vuetify/src/components/VDataTable/VDataTableRows.tsx b/packages/vuetify/src/components/VDataTable/VDataTableRows.tsx index 4fede8ec102..89d61b3e800 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTableRows.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTableRows.tsx @@ -19,13 +19,14 @@ import type { Group } from './composables/group' import type { CellProps, DataTableItem, GroupHeaderSlot, ItemSlot, RowProps } from './types' import type { VDataTableGroupHeaderRowSlots } from './VDataTableGroupHeaderRow' import type { VDataTableRowSlots } from './VDataTableRow' +import type { GenericProps } from '@/util' -export type VDataTableRowsSlots = VDataTableGroupHeaderRowSlots & VDataTableRowSlots & { - item: ItemSlot & { props: Record } +export type VDataTableRowsSlots = VDataTableGroupHeaderRowSlots & VDataTableRowSlots & { + item: ItemSlot & { props: Record } loading: never 'group-header': GroupHeaderSlot 'no-data': never - 'expanded-row': ItemSlot + 'expanded-row': ItemSlot } export const makeVDataTableRowsProps = propsFactory({ @@ -44,11 +45,16 @@ export const makeVDataTableRowsProps = propsFactory({ default: '$vuetify.noDataText', }, rowHeight: Number, - rowProps: [Object, Function] as PropType, - cellProps: [Object, Function] as PropType, + rowProps: [Object, Function] as PropType>, + cellProps: [Object, Function] as PropType>, }, 'VDataTableRows') -export const VDataTableRows = genericComponent()({ +export const VDataTableRows = genericComponent( + props: { + items?: readonly (DataTableItem | Group)[] + }, + slots: VDataTableRowsSlots, +) => GenericProps>()({ name: 'VDataTableRows', inheritAttrs: false, @@ -124,7 +130,7 @@ export const VDataTableRows = genericComponent()({ toggleExpand, isSelected, toggleSelect, - } satisfies ItemSlot + } satisfies ItemSlot const itemSlotProps = { ...slotProps, diff --git a/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx b/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx index c41041e88bd..5cdec91857a 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTableServer.tsx @@ -22,6 +22,8 @@ import { genericComponent, propsFactory, useRender } from '@/util' // Types import type { VDataTableSlotProps, VDataTableSlots } from './VDataTable' +import type { CellProps, RowProps } from '@/components/VDataTable/types' +import type { GenericProps, SelectItemKey } from '@/util' export const makeVDataTableServerProps = propsFactory({ itemsLength: { @@ -34,7 +36,20 @@ export const makeVDataTableServerProps = propsFactory({ ...makeVDataTableFooterProps(), }, 'VDataTableServer') -export const VDataTableServer = genericComponent()({ +type ItemType = T extends readonly (infer U)[] ? U : never + +export const VDataTableServer = genericComponent( + props: { + items?: T + itemValue?: SelectItemKey> + rowProps?: RowProps> + cellProps?: CellProps> + itemSelectable?: SelectItemKey> + modelValue?: V + 'onUpdate:modelValue'?: (value: V) => void + }, + slots: VDataTableSlots>, +) => GenericProps>()({ name: 'VDataTableServer', props: makeVDataTableServerProps(), @@ -102,7 +117,7 @@ export const VDataTableServer = genericComponent()({ }, }) - const slotProps = computed(() => ({ + const slotProps = computed>(() => ({ page: page.value, itemsPerPage: itemsPerPage.value, sortBy: sortBy.value, diff --git a/packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx b/packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx index 624391b3b65..5fe5f2c875c 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx +++ b/packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx @@ -27,15 +27,23 @@ import type { Ref } from 'vue' import type { VDataTableSlotProps } from './VDataTable' import type { VDataTableHeadersSlots } from './VDataTableHeaders' import type { VDataTableRowsSlots } from './VDataTableRows' - -type VDataTableVirtualSlotProps = Omit - -export type VDataTableVirtualSlots = VDataTableRowsSlots & VDataTableHeadersSlots & { - top: VDataTableVirtualSlotProps +import type { CellProps, RowProps } from '@/components/VDataTable/types' +import type { GenericProps, SelectItemKey } from '@/util' + +type VDataTableVirtualSlotProps = Omit< + VDataTableSlotProps, + | 'setItemsPerPage' + | 'page' + | 'pageCount' + | 'itemsPerPage' +> + +export type VDataTableVirtualSlots = VDataTableRowsSlots & VDataTableHeadersSlots & { + top: VDataTableVirtualSlotProps headers: VDataTableHeadersSlots['headers'] - bottom: VDataTableVirtualSlotProps - 'body.prepend': VDataTableVirtualSlotProps - 'body.append': VDataTableVirtualSlotProps + bottom: VDataTableVirtualSlotProps + 'body.prepend': VDataTableVirtualSlotProps + 'body.append': VDataTableVirtualSlotProps item: { itemRef: Ref } @@ -48,7 +56,20 @@ export const makeVDataTableVirtualProps = propsFactory({ ...makeFilterProps(), }, 'VDataTableVirtual') -export const VDataTableVirtual = genericComponent()({ +type ItemType = T extends readonly (infer U)[] ? U : never + +export const VDataTableVirtual = genericComponent( + props: { + items?: T + itemValue?: SelectItemKey> + rowProps?: RowProps> + cellProps?: CellProps> + itemSelectable?: SelectItemKey> + modelValue?: V + 'onUpdate:modelValue'?: (value: V) => void + }, + slots: VDataTableVirtualSlots>, +) => GenericProps>()({ name: 'VDataTableVirtual', props: makeVDataTableVirtualProps(), @@ -121,7 +142,7 @@ export const VDataTableVirtual = genericComponent()({ }, }) - const slotProps = computed(() => ({ + const slotProps = computed>(() => ({ sortBy: sortBy.value, toggleSort, someSelected: someSelected.value, diff --git a/packages/vuetify/src/components/VDataTable/composables/items.ts b/packages/vuetify/src/components/VDataTable/composables/items.ts index d116a559ba9..9529af56a79 100644 --- a/packages/vuetify/src/components/VDataTable/composables/items.ts +++ b/packages/vuetify/src/components/VDataTable/composables/items.ts @@ -28,8 +28,8 @@ export const makeDataTableItemsProps = propsFactory({ type: [String, Array, Function] as PropType, default: null, }, - rowProps: [Object, Function] as PropType, - cellProps: [Object, Function] as PropType, + rowProps: [Object, Function] as PropType>, + cellProps: [Object, Function] as PropType>, returnObject: Boolean, }, 'DataTable-items') diff --git a/packages/vuetify/src/components/VDataTable/composables/paginate.ts b/packages/vuetify/src/components/VDataTable/composables/paginate.ts index 423b46ac062..c2a345d12b8 100644 --- a/packages/vuetify/src/components/VDataTable/composables/paginate.ts +++ b/packages/vuetify/src/components/VDataTable/composables/paginate.ts @@ -8,6 +8,7 @@ import { clamp, propsFactory } from '@/util' // Types import type { InjectionKey, Ref } from 'vue' import type { Group } from './group' +import type { EventProp } from '@/util' export const makeDataTablePaginateProps = propsFactory({ page: { @@ -35,9 +36,9 @@ const VDataTablePaginationSymbol: InjectionKey<{ type PaginationProps = { page: number | string - 'onUpdate:page': ((val: any) => void) | undefined + 'onUpdate:page': EventProp | undefined itemsPerPage: number | string - 'onUpdate:itemsPerPage': ((val: any) => void) | undefined + 'onUpdate:itemsPerPage': EventProp | undefined itemsLength?: number | string } diff --git a/packages/vuetify/src/components/VDataTable/composables/select.ts b/packages/vuetify/src/components/VDataTable/composables/select.ts index 1895e505725..419aecef2fb 100644 --- a/packages/vuetify/src/components/VDataTable/composables/select.ts +++ b/packages/vuetify/src/components/VDataTable/composables/select.ts @@ -8,6 +8,7 @@ import { deepEqual, propsFactory, wrapInArray } from '@/util' // Types import type { InjectionKey, PropType, Ref } from 'vue' import type { DataTableItemProps } from './items' +import type { EventProp } from '@/util' export interface SelectableItem { value: any @@ -37,7 +38,7 @@ type SelectionProps = Pick & { modelValue: readonly any[] selectStrategy: 'single' | 'page' | 'all' valueComparator: typeof deepEqual - 'onUpdate:modelValue': ((value: any[]) => void) | undefined + 'onUpdate:modelValue': EventProp<[any[]]> | undefined } const singleSelectStrategy: DataTableSelectStrategy = { diff --git a/packages/vuetify/src/components/VDataTable/types.ts b/packages/vuetify/src/components/VDataTable/types.ts index 2d50828dbcc..3bb5a61a54d 100644 --- a/packages/vuetify/src/components/VDataTable/types.ts +++ b/packages/vuetify/src/components/VDataTable/types.ts @@ -60,7 +60,7 @@ export type GroupHeaderSlot = { isGroupOpen: ReturnType['isGroupOpen'] } -type ItemSlotBase = { +type ItemSlotBase = { index: number item: T internalItem: DataTableItem @@ -70,23 +70,23 @@ type ItemSlotBase = { toggleSelect: ReturnType['toggleSelect'] } -export type ItemSlot = ItemSlotBase & { +export type ItemSlot = ItemSlotBase & { columns: InternalDataTableHeader[] } -export type ItemKeySlot = ItemSlotBase & { +export type ItemKeySlot = ItemSlotBase & { value: any column: InternalDataTableHeader } -export type RowProps = +export type RowProps = | Record - | ((data: Pick) => Record) + | ((data: Pick, 'index' | 'item' | 'internalItem'>) => Record) -export type CellProps = +export type CellProps = | Record - | ((data: Pick) => Record) + | ((data: Pick, 'index' | 'item' | 'internalItem' | 'value' | 'column'>) => Record) export type HeaderCellProps = | Record - | ((data: Pick) => Record) + | ((data: Pick, 'index' | 'item' | 'internalItem' | 'value'>) => Record) diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index 1efc86359d0..238f27ce288 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -107,7 +107,7 @@ export type VFieldSlots = { export const VField = genericComponent( props: { modelValue?: T - 'onUpdate:modelValue'?: (val: T) => any + 'onUpdate:modelValue'?: (value: T) => void }, slots: VFieldSlots ) => GenericProps>()({ @@ -124,7 +124,7 @@ export const VField = genericComponent( emits: { 'update:focused': (focused: boolean) => true, - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { attrs, emit, slots }) { diff --git a/packages/vuetify/src/components/VInput/VInput.tsx b/packages/vuetify/src/components/VInput/VInput.tsx index f112484616f..7b79f1f4180 100644 --- a/packages/vuetify/src/components/VInput/VInput.tsx +++ b/packages/vuetify/src/components/VInput/VInput.tsx @@ -19,6 +19,7 @@ import { EventProp, genericComponent, getUid, propsFactory, useRender } from '@/ // Types import type { ComputedRef, PropType, Ref } from 'vue' import type { VMessageSlot } from '@/components/VMessages/VMessages' +import type { GenericProps } from '@/util' export interface VInputSlot { id: ComputedRef @@ -72,7 +73,13 @@ export type VInputSlots = { message: VMessageSlot } -export const VInput = genericComponent()({ +export const VInput = genericComponent( + props: { + modelValue?: T | null + 'onUpdate:modelValue'?: (value: T | null) => void + }, + slots: VInputSlots, +) => GenericProps>()({ name: 'VInput', props: { @@ -80,7 +87,7 @@ export const VInput = genericComponent()({ }, emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { attrs, slots, emit }) { diff --git a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx index 202ff756e92..d33ac86c024 100644 --- a/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx +++ b/packages/vuetify/src/components/VItemGroup/VItemGroup.tsx @@ -10,6 +10,9 @@ import { makeThemeProps, provideTheme } from '@/composables/theme' // Utilities import { genericComponent, propsFactory } from '@/util' +// Types +import type { GenericProps } from '@/util' + export const VItemGroupSymbol = Symbol.for('vuetify:v-item-group') export const makeVItemGroupProps = propsFactory({ @@ -31,7 +34,13 @@ type VItemGroupSlots = { } } -export const VItemGroup = genericComponent()({ +export const VItemGroup = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VItemGroupSlots, +) => GenericProps>()({ name: 'VItemGroup', props: makeVItemGroupProps(), diff --git a/packages/vuetify/src/components/VList/VList.tsx b/packages/vuetify/src/components/VList/VList.tsx index 436447ba997..9161a8c262a 100644 --- a/packages/vuetify/src/components/VList/VList.tsx +++ b/packages/vuetify/src/components/VList/VList.tsx @@ -28,7 +28,7 @@ import { focusChild, genericComponent, getPropertyFromItem, omit, propsFactory, import type { PropType } from 'vue' import type { VListChildrenSlots } from './VListChildren' import type { ItemProps, ListItem } from '@/composables/list-items' -import type { GenericProps } from '@/util' +import type { GenericProps, SelectItemKey } from '@/util' export interface InternalListItem extends ListItem { type?: 'item' | 'subheader' | 'divider' @@ -113,19 +113,33 @@ export const makeVListProps = propsFactory({ ...makeVariantProps({ variant: 'text' } as const), }, 'VList') -export const VList = genericComponent( +type ItemType = T extends readonly (infer U)[] ? U : never + +export const VList = genericComponent( props: { - items?: T[] + items?: T + itemTitle?: SelectItemKey> + itemValue?: SelectItemKey> + itemChildren?: SelectItemKey> + itemProps?: SelectItemKey> + selected?: readonly S[] + 'onUpdate:selected'?: (value: S[]) => void + opened?: readonly O[] + 'onUpdate:opened'?: (value: O[]) => void }, - slots: VListChildrenSlots + slots: VListChildrenSlots> ) => GenericProps>()({ name: 'VList', props: makeVListProps(), emits: { - 'update:selected': (val: unknown[]) => true, - 'update:opened': (val: unknown[]) => true, + 'update:selected': (value: unknown[]) => true, + 'update:opened': (value: unknown[]) => true, 'click:open': (value: { id: unknown, value: boolean, path: unknown[] }) => true, 'click:select': (value: { id: unknown, value: boolean, path: unknown[] }) => true, }, diff --git a/packages/vuetify/src/components/VRadioGroup/VRadioGroup.tsx b/packages/vuetify/src/components/VRadioGroup/VRadioGroup.tsx index c4f75229c96..fe9af1fc96a 100644 --- a/packages/vuetify/src/components/VRadioGroup/VRadioGroup.tsx +++ b/packages/vuetify/src/components/VRadioGroup/VRadioGroup.tsx @@ -17,6 +17,7 @@ import { filterInputAttrs, genericComponent, getUid, omit, propsFactory, useRend // Types import type { VInputSlots } from '@/components/VInput/VInput' +import type { GenericProps } from '@/util' export type VRadioGroupSlots = Omit & { default: never @@ -49,7 +50,13 @@ export const makeVRadioGroupProps = propsFactory({ }, }, 'VRadioGroup') -export const VRadioGroup = genericComponent()({ +export const VRadioGroup = genericComponent( + props: { + modelValue?: T | null + 'onUpdate:modelValue'?: (value: T | null) => void + }, + slots: VRadioGroupSlots, +) => GenericProps>()({ name: 'VRadioGroup', inheritAttrs: false, @@ -57,7 +64,7 @@ export const VRadioGroup = genericComponent()({ props: makeVRadioGroupProps(), emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { attrs, slots }) { diff --git a/packages/vuetify/src/components/VSelect/VSelect.tsx b/packages/vuetify/src/components/VSelect/VSelect.tsx index 8224fe4a6eb..71605f7682f 100644 --- a/packages/vuetify/src/components/VSelect/VSelect.tsx +++ b/packages/vuetify/src/components/VSelect/VSelect.tsx @@ -40,7 +40,7 @@ import type { Component, PropType } from 'vue' import type { VFieldSlots } from '@/components/VField/VField' import type { VInputSlots } from '@/components/VInput/VInput' import type { ListItem } from '@/composables/list-items' -import type { GenericProps } from '@/util' +import type { GenericProps, SelectItemKey } from '@/util' type Primitive = string | number | boolean | symbol @@ -95,19 +95,24 @@ export const makeVSelectProps = propsFactory({ ...makeTransitionProps({ transition: { component: VDialogTransition as Component } }), }, 'VSelect') +type ItemType = T extends readonly (infer U)[] ? U : never + export const VSelect = genericComponent, ReturnObject extends boolean = false, Multiple extends boolean = false, V extends Value = Value >( props: { items?: T + itemTitle?: SelectItemKey> + itemValue?: SelectItemKey> + itemProps?: SelectItemKey> returnObject?: ReturnObject multiple?: Multiple modelValue?: V | null - 'onUpdate:modelValue'?: (val: V) => void + 'onUpdate:modelValue'?: (value: V) => void }, slots: Omit & { item: { item: ListItem, index: number, props: Record } @@ -124,8 +129,8 @@ export const VSelect = genericComponent true, - 'update:modelValue': (val: any) => true, - 'update:menu': (val: boolean) => true, + 'update:modelValue': (value: any) => true, + 'update:menu': (ue: boolean) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/components/VSelectionControl/VSelectionControl.tsx b/packages/vuetify/src/components/VSelectionControl/VSelectionControl.tsx index c36872662de..e519cefb42f 100644 --- a/packages/vuetify/src/components/VSelectionControl/VSelectionControl.tsx +++ b/packages/vuetify/src/components/VSelectionControl/VSelectionControl.tsx @@ -30,10 +30,10 @@ import { // Types import type { CSSProperties, ExtractPropTypes, Ref, VNode, WritableComputedRef } from 'vue' import type { IconValue } from '@/composables/icons' -import type { GenericProps } from '@/util' +import type { EventProp, GenericProps } from '@/util' export type SelectionControlSlot = { - model: WritableComputedRef + model: WritableComputedRef textColorClasses: Ref textColorStyles: Ref backgroundColorClasses: Ref @@ -69,7 +69,7 @@ export const makeVSelectionControlProps = propsFactory({ export function useSelectionControl ( props: ExtractPropTypes> & { - 'onUpdate:modelValue': ((val: any) => void) | undefined + 'onUpdate:modelValue': EventProp | undefined } ) { const group = inject(VSelectionControlGroupSymbol, undefined) @@ -144,7 +144,7 @@ export function useSelectionControl ( export const VSelectionControl = genericComponent( props: { modelValue?: T - 'onUpdate:modelValue'?: (val: T) => any + 'onUpdate:modelValue'?: (value: T) => void }, slots: VSelectionControlSlots, ) => GenericProps>()({ @@ -157,7 +157,7 @@ export const VSelectionControl = genericComponent( props: makeVSelectionControlProps(), emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { attrs, slots }) { diff --git a/packages/vuetify/src/components/VSelectionControlGroup/VSelectionControlGroup.tsx b/packages/vuetify/src/components/VSelectionControlGroup/VSelectionControlGroup.tsx index c180280cabf..e737619cdca 100644 --- a/packages/vuetify/src/components/VSelectionControlGroup/VSelectionControlGroup.tsx +++ b/packages/vuetify/src/components/VSelectionControlGroup/VSelectionControlGroup.tsx @@ -15,6 +15,7 @@ import { deepEqual, genericComponent, getUid, propsFactory, useRender } from '@/ // Types import type { InjectionKey, PropType, Ref } from 'vue' +import type { GenericProps } from '@/util' export interface VSelectionGroupContext { modelValue: Ref @@ -64,13 +65,19 @@ export const makeVSelectionControlGroupProps = propsFactory({ }), }, 'VSelectionControlGroup') -export const VSelectionControlGroup = genericComponent()({ +export const VSelectionControlGroup = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: { default: never }, +) => GenericProps>()({ name: 'VSelectionControlGroup', props: makeVSelectionControlGroupProps(), emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx index b6f6966a760..fb788926668 100644 --- a/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx +++ b/packages/vuetify/src/components/VSlideGroup/VSlideGroup.tsx @@ -22,6 +22,7 @@ import { clamp, focusableChildren, genericComponent, IN_BROWSER, propsFactory, u // Types import type { InjectionKey, PropType } from 'vue' import type { GroupProvide } from '@/composables/group' +import type { GenericProps } from '@/util' export const VSlideGroupSymbol: InjectionKey = Symbol.for('vuetify:v-slide-group') @@ -75,7 +76,13 @@ export const makeVSlideGroupProps = propsFactory({ }), }, 'VSlideGroup') -export const VSlideGroup = genericComponent()({ +export const VSlideGroup = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VSlideGroupSlots, +) => GenericProps>()({ name: 'VSlideGroup', props: makeVSlideGroupProps(), diff --git a/packages/vuetify/src/components/VSwitch/VSwitch.tsx b/packages/vuetify/src/components/VSwitch/VSwitch.tsx index b69d386a62c..4449ae12b0a 100644 --- a/packages/vuetify/src/components/VSwitch/VSwitch.tsx +++ b/packages/vuetify/src/components/VSwitch/VSwitch.tsx @@ -21,6 +21,7 @@ import { filterInputAttrs, genericComponent, getUid, propsFactory, useRender } f import type { VInputSlots } from '@/components/VInput/VInput' import type { VSelectionControlSlots } from '@/components/VSelectionControl/VSelectionControl' import type { LoaderSlotProps } from '@/composables/loader' +import type { GenericProps } from '@/util' export type VSwitchSlots = & VInputSlots @@ -40,7 +41,13 @@ export const makeVSwitchProps = propsFactory({ ...makeVSelectionControlProps(), }, 'VSwitch') -export const VSwitch = genericComponent()({ +export const VSwitch = genericComponent( + props: { + modelValue?: T | null + 'onUpdate:modelValue'?: (value: T | null) => void + }, + slots: VSwitchSlots, +) => GenericProps>()({ name: 'VSwitch', inheritAttrs: false, @@ -49,8 +56,8 @@ export const VSwitch = genericComponent()({ emits: { 'update:focused': (focused: boolean) => true, - 'update:modelValue': () => true, - 'update:indeterminate': (val: boolean) => true, + 'update:modelValue': (value: any) => true, + 'update:indeterminate': (value: boolean) => true, }, setup (props, { attrs, slots }) { diff --git a/packages/vuetify/src/components/VValidation/VValidation.tsx b/packages/vuetify/src/components/VValidation/VValidation.tsx index a530cca3447..b487c8350b5 100644 --- a/packages/vuetify/src/components/VValidation/VValidation.tsx +++ b/packages/vuetify/src/components/VValidation/VValidation.tsx @@ -4,17 +4,26 @@ import { makeValidationProps, useValidation } from '@/composables/validation' // Utilities import { genericComponent } from '@/util' +// Types +import type { GenericProps } from '@/util' + export type VValidationSlots = { default: ReturnType } -export const VValidation = genericComponent()({ +export const VValidation = genericComponent( + props: { + modelValue?: T | null + 'onUpdate:modelValue'?: (value: T | null) => void + }, + slots: VValidationSlots, +) => GenericProps>()({ name: 'VValidation', props: makeValidationProps(), emits: { - 'update:modelValue': (val: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/components/VWindow/VWindow.tsx b/packages/vuetify/src/components/VWindow/VWindow.tsx index 6bc1a2a555e..9310a725ebe 100644 --- a/packages/vuetify/src/components/VWindow/VWindow.tsx +++ b/packages/vuetify/src/components/VWindow/VWindow.tsx @@ -23,6 +23,7 @@ import type { ComputedRef, InjectionKey, PropType, Ref } from 'vue' import type { GroupItemProvide, GroupProvide } from '@/composables/group' import type { IconValue } from '@/composables/icons' import type { TouchHandlers } from '@/directives/touch' +import type { GenericProps } from '@/util' export type VWindowSlots = { default: { group: GroupProvide } @@ -90,7 +91,13 @@ export const makeVWindowProps = propsFactory({ ...makeThemeProps(), }, 'VWindow') -export const VWindow = genericComponent()({ +export const VWindow = genericComponent( + props: { + modelValue?: T + 'onUpdate:modelValue'?: (value: T) => void + }, + slots: VWindowSlots, +) => GenericProps>()({ name: 'VWindow', directives: { @@ -100,7 +107,7 @@ export const VWindow = genericComponent()({ props: makeVWindowProps(), emits: { - 'update:modelValue': (v: any) => true, + 'update:modelValue': (value: any) => true, }, setup (props, { slots }) { diff --git a/packages/vuetify/src/composables/form.ts b/packages/vuetify/src/composables/form.ts index e76d15f96b2..22bd3313e45 100644 --- a/packages/vuetify/src/composables/form.ts +++ b/packages/vuetify/src/composables/form.ts @@ -8,6 +8,7 @@ import { consoleWarn, propsFactory } from '@/util' // Types import type { ComputedRef, InjectionKey, PropType, Ref } from 'vue' import type { ValidationProps } from './validation' +import type { EventProp } from '@/util' export interface FormProvide { register: (item: { @@ -54,7 +55,7 @@ export interface FormProps { fastFail: boolean readonly: boolean modelValue: boolean | null - 'onUpdate:modelValue': ((val: boolean | null) => void) | undefined + 'onUpdate:modelValue': EventProp<[boolean | null]> | undefined validateOn: ValidationProps['validateOn'] } diff --git a/packages/vuetify/src/composables/group.ts b/packages/vuetify/src/composables/group.ts index 85285a33d08..40fd4726405 100644 --- a/packages/vuetify/src/composables/group.ts +++ b/packages/vuetify/src/composables/group.ts @@ -7,6 +7,7 @@ import { consoleWarn, deepEqual, findChildrenWithProvide, getCurrentInstance, ge // Types import type { ComponentInternalInstance, ComputedRef, ExtractPropTypes, InjectionKey, PropType, Ref, UnwrapRef } from 'vue' +import type { EventProp } from '@/util' export interface GroupItem { id: number @@ -21,7 +22,7 @@ export interface GroupProps { mandatory?: boolean | 'force' | undefined max?: number | undefined selectedClass: string | undefined - 'onUpdate:modelValue': ((val: unknown) => void) | undefined + 'onUpdate:modelValue': EventProp<[unknown]> | undefined } export interface GroupProvide { @@ -72,7 +73,7 @@ export const makeGroupItemProps = propsFactory({ }, 'group-item') export interface GroupItemProps extends ExtractPropTypes> { - 'onGroup:selected': ((val: { value: boolean }) => void) | undefined + 'onGroup:selected': EventProp<[{ value: boolean }]> | undefined } // Composables diff --git a/packages/vuetify/src/composables/nested/nested.ts b/packages/vuetify/src/composables/nested/nested.ts index ece83bd771e..d6f8073a694 100644 --- a/packages/vuetify/src/composables/nested/nested.ts +++ b/packages/vuetify/src/composables/nested/nested.ts @@ -17,6 +17,7 @@ import { getCurrentInstance, getUid, propsFactory } from '@/util' import type { InjectionKey, PropType, Ref } from 'vue' import type { OpenStrategy } from './openStrategies' import type { SelectStrategyFn } from './selectStrategies' +import type { EventProp } from '@/util' export type SelectStrategy = 'single-leaf' | 'leaf' | 'independent' | 'single-independent' | 'classic' | SelectStrategyFn export type OpenStrategyProp = 'single' | 'multiple' | 'list' | OpenStrategy @@ -27,8 +28,8 @@ export interface NestedProps { selected: readonly unknown[] | undefined opened: readonly unknown[] | undefined mandatory: boolean - 'onUpdate:selected': ((val: unknown[]) => void) | undefined - 'onUpdate:opened': ((val: unknown[]) => void) | undefined + 'onUpdate:selected': EventProp<[unknown[]]> | undefined + 'onUpdate:opened': EventProp<[unknown[]]> | undefined } type NestedProvide = { diff --git a/packages/vuetify/src/composables/proxiedModel.ts b/packages/vuetify/src/composables/proxiedModel.ts index 5cf1b693f90..29367695536 100644 --- a/packages/vuetify/src/composables/proxiedModel.ts +++ b/packages/vuetify/src/composables/proxiedModel.ts @@ -7,12 +7,13 @@ import { getCurrentInstance, toKebabCase } from '@/util' // Types import type { Ref } from 'vue' +import type { EventProp } from '@/util' type InnerVal = T extends any[] ? Readonly : T // Composables export function useProxiedModel< - Props extends object & { [key in Prop as `onUpdate:${Prop}`]: ((val: any) => void) | undefined }, + Props extends object & { [key in Prop as `onUpdate:${Prop}`]: EventProp | undefined }, Prop extends Extract, Inner = Props[Prop], > ( diff --git a/packages/vuetify/src/composables/validation.ts b/packages/vuetify/src/composables/validation.ts index 569bbcdee81..73a787d05a3 100644 --- a/packages/vuetify/src/composables/validation.ts +++ b/packages/vuetify/src/composables/validation.ts @@ -10,7 +10,7 @@ import { getCurrentInstanceName, getUid, propsFactory, wrapInArray } from '@/uti // Types import type { PropType } from 'vue' -import type { MaybeRef } from '@/util' +import type { EventProp, MaybeRef } from '@/util' export type ValidationResult = string | boolean export type ValidationRule = @@ -32,7 +32,7 @@ export interface ValidationProps { readonly: boolean | null rules: readonly ValidationRule[] modelValue: any - 'onUpdate:modelValue': ((val: any) => void) | undefined + 'onUpdate:modelValue': EventProp | undefined validateOn?: ValidateOnValue | `${ValidateOnValue} lazy` | `lazy ${ValidateOnValue}` | 'lazy' validationValue: any } diff --git a/packages/vuetify/src/util/defineComponent.tsx b/packages/vuetify/src/util/defineComponent.tsx index 292256d733e..7753afd4673 100644 --- a/packages/vuetify/src/util/defineComponent.tsx +++ b/packages/vuetify/src/util/defineComponent.tsx @@ -185,6 +185,11 @@ type DefineComponentWithGenericProps, P = III extends Record<'$props', any> ? Omit : PropsOptions, + EEE extends EmitsOptions = E extends any[] + ? E + : III extends Record<'$props', any> + ? Omit> + : E, Base = DefineComponent< P, RawBindings, @@ -193,10 +198,10 @@ type DefineComponentWithGenericProps, M, Mixin, Extends, - E extends any[] ? E : III extends Record<'$props', any> ? Omit> : E, + EEE, EE, PublicProps, - ExtractPropTypes

& ({} extends E ? {} : EmitsToProps), + ExtractPropTypes

& ({} extends E ? {} : EmitsToProps), ExtractDefaultPropTypes

, S > diff --git a/packages/vuetify/src/util/helpers.ts b/packages/vuetify/src/util/helpers.ts index 38a8fc174c5..2222a833707 100644 --- a/packages/vuetify/src/util/helpers.ts +++ b/packages/vuetify/src/util/helpers.ts @@ -70,11 +70,11 @@ export function getObjectValueByPath (obj: any, path?: string | null, fallback?: return getNestedValue(obj, path.split('.'), fallback) } -export type SelectItemKey = +export type SelectItemKey> = | boolean | null | undefined // Ignored | string // Lookup by key, can use dot notation for nested objects | readonly (string | number)[] // Nested lookup by key, each array item is a key in the next level - | ((item: Record, fallback?: any) => any) + | ((item: T, fallback?: any) => any) export function getPropertyFromItem ( item: any, @@ -669,7 +669,7 @@ export function eventName (propName: string) { return propName[2].toLowerCase() + propName.slice(3) } -export type EventProp any> = F | F[] +export type EventProp void> = F export const EventProp = () => [Function, Array] as PropType> export function hasEvent (props: Record, name: string) {