fix(components): improve generic types (#3331)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Sandro Circi
2025-03-24 21:38:13 +01:00
committed by GitHub
parent 370054b20c
commit b9983549a4
106 changed files with 1203 additions and 535 deletions

View File

@@ -19,9 +19,10 @@ export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
icon?: string
avatar?: AvatarProps
slot?: string
[key: string]: any
}
export interface BreadcrumbProps<T> {
export interface BreadcrumbProps<T extends BreadcrumbItem = BreadcrumbItem> {
/**
* The element or component this component should render as.
* @defaultValue 'nav'
@@ -43,15 +44,15 @@ export interface BreadcrumbProps<T> {
ui?: PartialString<typeof breadcrumb.slots>
}
type SlotProps<T> = (props: { item: T, index: number, active?: boolean }) => any
type SlotProps<T extends BreadcrumbItem> = (props: { item: T, index: number, active?: boolean }) => any
export type BreadcrumbSlots<T extends { slot?: string }> = {
export type BreadcrumbSlots<T extends BreadcrumbItem = BreadcrumbItem> = {
'item': SlotProps<T>
'item-leading': SlotProps<T>
'item-label': SlotProps<T>
'item-trailing': SlotProps<T>
'separator'(props?: {}): any
} & DynamicSlots<T, SlotProps<T>>
'separator': any
} & DynamicSlots<T, 'leading' | 'label' | 'trailing', { index: number, active?: boolean }>
</script>
@@ -88,19 +89,19 @@ const ui = breadcrumb()
<li :class="ui.item({ class: props.ui?.item })">
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
<ULinkBase v-bind="slotProps" as="span" :aria-current="active && (index === items!.length - 1) ? 'page' : undefined" :class="ui.link({ class: [props.ui?.link, item.class], active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })">
<slot :name="item.slot || 'item'" :item="item" :index="index">
<slot :name="item.slot ? `${item.slot}-leading`: 'item-leading'" :item="item" :active="index === items!.length - 1" :index="index">
<slot :name="((item.slot || 'item') as keyof BreadcrumbSlots<T>)" :item="item" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
<UIcon v-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active: index === items!.length - 1 })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active: index === items!.length - 1 })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label`: 'item-label']" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
<slot :name="item.slot ? `${item.slot}-label`: 'item-label'" :item="item" :active="index === items!.length - 1" :index="index">
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>]" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
{{ get(item, props.labelKey as string) }}
</slot>
</span>
<slot :name="item.slot ? `${item.slot}-trailing`: 'item-trailing'" :item="item" :active="index === items!.length - 1" :index="index" />
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index" />
</slot>
</ULinkBase>
</ULink>