mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
feat(components): add ui field in items (#4060)
Co-authored-by: Jakub <jakub.michalek@freelo.io> Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -23,6 +23,8 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `value?: string`{lang="ts-type"}
|
- `value?: string`{lang="ts-type"}
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `label?: string`{lang="ts-type"}
|
- `label?: string`{lang="ts-type"}
|
||||||
- `icon?: string`{lang="ts-type"}
|
- `icon?: string`{lang="ts-type"}
|
||||||
- `avatar?: AvatarProps`{lang="ts-type"}
|
- `avatar?: AvatarProps`{lang="ts-type"}
|
||||||
- `class?: any`{lang="ts-type"}
|
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLabel?: ClassNameValue, separator?: ClassNameValue, separatorIcon?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ class: 'p-8'
|
|||||||
---
|
---
|
||||||
::
|
::
|
||||||
|
|
||||||
|
You can also pass an array of objects with the following properties:
|
||||||
|
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
You can control how many items are visible by using the [`basis`](https://tailwindcss.com/docs/flex-basis) / [`width`](https://tailwindcss.com/docs/width) utility classes on the `item`:
|
You can control how many items are visible by using the [`basis`](https://tailwindcss.com/docs/flex-basis) / [`width`](https://tailwindcss.com/docs/width) utility classes on the `item`:
|
||||||
|
|
||||||
::component-example
|
::component-example
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ You can also pass an array of objects with the following properties:
|
|||||||
- `description?: string`{lang="ts-type"}
|
- `description?: string`{lang="ts-type"}
|
||||||
- [`value?: string`{lang="ts-type"}](#value-key)
|
- [`value?: string`{lang="ts-type"}](#value-key)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, icon?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ Each group contains an `items` array of objects that define the commands. Each i
|
|||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
- `onSelect?(e?: Event): void`{lang="ts-type"}
|
- `onSelect?(e?: Event): void`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelPrefix?: ClassNameValue, itemLabelBase?: ClassNameValue, itemLabelSuffix?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue, itemTrailingHighlightedIcon?: ClassNameValue, itemTrailingIcon?: ClassNameValue,}`{lang="ts-type"}
|
||||||
|
|
||||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
|
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
|
||||||
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
|
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- `class?: any`{lang="ts-type"}
|
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||||
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
||||||
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"}
|
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
|
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
|
||||||
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
|
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- `class?: any`{lang="ts-type"}
|
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||||
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
|
||||||
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"}
|
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ You can also pass an array of objects with the following properties:
|
|||||||
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { tagsItem?: ClassNameValue, tagsItemText?: ClassNameValue, tagsItemDelete?: ClassNameValue, tagsItemDeleteIcon?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `open?: boolean`{lang="ts-type"}
|
- `open?: boolean`{lang="ts-type"}
|
||||||
- `value?: string`{lang="ts-type"}
|
- `value?: string`{lang="ts-type"}
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- `class?: any`{lang="ts-type"}
|
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||||
- `children?: NavigationMenuChildItem[]`{lang="ts-type"}
|
- `children?: NavigationMenuChildItem[]`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { linkLeadingAvatarSize?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkLabelExternalIcon?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingBadgeSize?: ClassNameValue, linkTrailingBadge?: ClassNameValue, linkTrailingIcon?: ClassNameValue, label?: ClassNameValue, link?: ClassNameValue, content?: ClassNameValue, childList?: ClassNameValue, childItem?: ClassNameValue, childLink?: ClassNameValue, childLinkIcon?: ClassNameValue, childLinkWrapper?: ClassNameValue, childLinkLabel?: ClassNameValue, childLinkLabelExternalIcon?: ClassNameValue, childLinkDescription?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
|
||||||
|
|
||||||
@@ -134,8 +135,8 @@ Each item can take a `children` array of objects with the following properties t
|
|||||||
- `label: string`
|
- `label: string`
|
||||||
- `description?: string`
|
- `description?: string`
|
||||||
- `icon?: string`
|
- `icon?: string`
|
||||||
- `class?: any`
|
|
||||||
- `onSelect?(e: Event): void`
|
- `onSelect?(e: Event): void`
|
||||||
|
- `class?: any`
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ You can also pass an array of objects with the following properties:
|
|||||||
- `description?: string`{lang="ts-type"}
|
- `description?: string`{lang="ts-type"}
|
||||||
- [`value?: string`{lang="ts-type"}](#value-key)
|
- [`value?: string`{lang="ts-type"}](#value-key)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ You can also pass an array of objects with the following properties:
|
|||||||
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- `onSelect?(e: Event): void`{lang="ts-type"}
|
- `onSelect?(e: Event): void`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ You can also pass an array of objects with the following properties:
|
|||||||
- [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
|
- [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
|
||||||
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `value?: string | number`{lang="ts-type"}
|
- `value?: string | number`{lang="ts-type"}
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, trigger?: ClassNameValue, indicator?: ClassNameValue, icon?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `value?: string | number`{lang="ts-type"}
|
- `value?: string | number`{lang="ts-type"}
|
||||||
- `disabled?: boolean`{lang="ts-type"}
|
- `disabled?: boolean`{lang="ts-type"}
|
||||||
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { trigger?: ClassNameValue, leadingIcon?: ClassNameValue, leadingAvatar?: ClassNameValue, label?: ClassNameValue, content?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::component-code
|
::component-code
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ Use the `items` prop as an array of objects with the following properties:
|
|||||||
- `children?: TreeItem[]`{lang="ts-type"}
|
- `children?: TreeItem[]`{lang="ts-type"}
|
||||||
- `onToggle?(e: Event): void`{lang="ts-type"}
|
- `onToggle?(e: Event): void`{lang="ts-type"}
|
||||||
- `onSelect?(e?: Event): void`{lang="ts-type"}
|
- `onSelect?(e?: Event): void`{lang="ts-type"}
|
||||||
|
- `class?: any`{lang="ts-type"}
|
||||||
|
- `ui?: { item?: ClassNameValue, itemWithChildren?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingIcon?: ClassNameValue, listWithChildren?: ClassNameValue }`{lang="ts-type"}
|
||||||
|
|
||||||
::note
|
::note
|
||||||
A unique identifier is required for each item. The component will use the `value` prop as identifier, falling back to `label` if `value` is not provided. One of these must be provided for the component to work properly.
|
A unique identifier is required for each item. The component will use the `value` prop as identifier, falling back to `label` if `value` is not provided. One of these must be provided for the component to work properly.
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export interface AccordionItem {
|
|||||||
/** A unique value for the accordion item. Defaults to the index. */
|
/** A unique value for the accordion item. Defaults to the index. */
|
||||||
value?: string
|
value?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Accordion['slots'], 'item' | 'header' | 'trigger' | 'leadingIcon' | 'label' | 'trailingIcon' | 'content' | 'body'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,27 +98,27 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.accordion ||
|
|||||||
:key="index"
|
:key="index"
|
||||||
:value="item.value || String(index)"
|
:value="item.value || String(index)"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
|
||||||
>
|
>
|
||||||
<AccordionHeader as="div" :class="ui.header({ class: props.ui?.header })">
|
<AccordionHeader as="div" :class="ui.header({ class: [props.ui?.header, item.ui?.header] })">
|
||||||
<AccordionTrigger :class="ui.trigger({ class: props.ui?.trigger, disabled: item.disabled })">
|
<AccordionTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger], disabled: item.disabled })">
|
||||||
<slot name="leading" :item="item" :index="index" :open="open">
|
<slot name="leading" :item="item" :index="index" :open="open">
|
||||||
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
|
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: [props.ui?.leadingIcon, item?.ui?.leadingIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: props.ui?.label })">
|
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
|
||||||
<slot :item="item" :index="index" :open="open">{{ get(item, props.labelKey as string) }}</slot>
|
<slot :item="item" :index="index" :open="open">{{ get(item, props.labelKey as string) }}</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<slot name="trailing" :item="item" :index="index" :open="open">
|
<slot name="trailing" :item="item" :index="index" :open="open">
|
||||||
<UIcon :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
|
<UIcon :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.trailingIcon({ class: [props.ui?.trailingIcon, item.ui?.trailingIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
</AccordionHeader>
|
</AccordionHeader>
|
||||||
|
|
||||||
<AccordionContent v-if="item.content || !!slots.content || (item.slot && !!slots[item.slot as keyof AccordionSlots<T>]) || !!slots.body || (item.slot && !!slots[`${item.slot}-body` as keyof AccordionSlots<T>])" :class="ui.content({ class: props.ui?.content })">
|
<AccordionContent v-if="item.content || !!slots.content || (item.slot && !!slots[item.slot as keyof AccordionSlots<T>]) || !!slots.body || (item.slot && !!slots[`${item.slot}-body` as keyof AccordionSlots<T>])" :class="ui.content({ class: [props.ui?.content, item.ui?.content] })">
|
||||||
<slot :name="((item.slot || 'content') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
|
<slot :name="((item.slot || 'content') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
|
||||||
<div :class="ui.body({ class: props.ui?.body })">
|
<div :class="ui.body({ class: [props.ui?.body, item.ui?.body] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-body`: 'body') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
|
<slot :name="((item.slot ? `${item.slot}-body`: 'body') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
|
||||||
{{ item.content }}
|
{{ item.content }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
|
|||||||
icon?: string
|
icon?: string
|
||||||
avatar?: AvatarProps
|
avatar?: AvatarProps
|
||||||
slot?: string
|
slot?: string
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Breadcrumb['slots'], 'item' | 'link' | 'linkLeadingIcon' | 'linkLeadingAvatar' | 'linkLabel' | 'separator' | 'separatorIcon'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,16 +86,16 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb |
|
|||||||
<Primitive :as="as" aria-label="breadcrumb" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
<Primitive :as="as" aria-label="breadcrumb" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
||||||
<ol :class="ui.list({ class: props.ui?.list })">
|
<ol :class="ui.list({ class: props.ui?.list })">
|
||||||
<template v-for="(item, index) in items" :key="index">
|
<template v-for="(item, index) in items" :key="index">
|
||||||
<li :class="ui.item({ class: props.ui?.item })">
|
<li :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })">
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
<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 })">
|
<ULinkBase v-bind="slotProps" as="span" :aria-current="active && (index === items!.length - 1) ? 'page' : undefined" :class="ui.link({ class: [props.ui?.link, item.ui?.link], active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })">
|
||||||
<slot :name="((item.slot || 'item') as keyof BreadcrumbSlots<T>)" :item="item" :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">
|
<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 })" />
|
<UIcon v-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.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 })" />
|
<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, item.ui?.linkLeadingAvatar], active: index === items!.length - 1 })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<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 })">
|
<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, item.ui?.linkLabel] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
|
<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) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</slot>
|
</slot>
|
||||||
@@ -105,9 +107,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb |
|
|||||||
</ULink>
|
</ULink>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="index < items!.length - 1" role="presentation" aria-hidden="true" :class="ui.separator({ class: props.ui?.separator })">
|
<li v-if="index < items!.length - 1" role="presentation" aria-hidden="true" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator] })">
|
||||||
<slot name="separator">
|
<slot name="separator">
|
||||||
<UIcon :name="separatorIcon" :class="ui.separatorIcon({ class: props.ui?.separatorIcon })" />
|
<UIcon :name="separatorIcon" :class="ui.separatorIcon({ class: [props.ui?.separatorIcon, item.ui?.separatorIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ import type { ComponentConfig } from '../types/utils'
|
|||||||
|
|
||||||
type Carousel = ComponentConfig<typeof theme, AppConfig, 'carousel'>
|
type Carousel = ComponentConfig<typeof theme, AppConfig, 'carousel'>
|
||||||
|
|
||||||
export type CarouselItem = AcceptableValue
|
interface _CarouselItem {
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Carousel['slots'], 'item'>
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CarouselItem = _CarouselItem | AcceptableValue
|
||||||
|
|
||||||
export interface CarouselProps<T extends CarouselItem = CarouselItem> extends Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
|
export interface CarouselProps<T extends CarouselItem = CarouselItem> extends Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
|
||||||
/**
|
/**
|
||||||
@@ -254,6 +260,10 @@ function onSelect(api: EmblaCarouselType) {
|
|||||||
emits('select', selectedIndex.value)
|
emits('select', selectedIndex.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isCarouselItem(item: CarouselItem): item is _CarouselItem {
|
||||||
|
return typeof item === 'object' && item !== null
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!emblaApi.value) {
|
if (!emblaApi.value) {
|
||||||
return
|
return
|
||||||
@@ -288,7 +298,7 @@ defineExpose({
|
|||||||
:key="index"
|
:key="index"
|
||||||
role="group"
|
role="group"
|
||||||
aria-roledescription="slide"
|
aria-roledescription="slide"
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, isCarouselItem(item) && item.ui?.item, isCarouselItem(item) && item.class] })"
|
||||||
>
|
>
|
||||||
<slot :item="item" :index="index" />
|
<slot :item="item" :index="index" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export type CheckboxGroupItem = {
|
|||||||
description?: string
|
description?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
value?: string
|
value?: string
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<CheckboxGroup['slots'], 'item'> & Omit<Required<CheckboxProps>['ui'], 'root'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
} | CheckboxGroupValue
|
} | CheckboxGroupValue
|
||||||
|
|
||||||
@@ -177,8 +179,8 @@ function onUpdate(value: any) {
|
|||||||
:size="size"
|
:size="size"
|
||||||
:name="name"
|
:name="name"
|
||||||
:disabled="item.disabled || disabled"
|
:disabled="item.disabled || disabled"
|
||||||
:ui="props.ui ? omit(props.ui, ['root']) : undefined"
|
:ui="{ ...(props.ui ? omit(props.ui, ['root']) : undefined), ...(item.ui || {}) }"
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
|
||||||
>
|
>
|
||||||
<template v-for="(_, name) in proxySlots" #[name]>
|
<template v-for="(_, name) in proxySlots" #[name]>
|
||||||
<slot :name="(name as keyof CheckboxGroupSlots<T>)" :item="item" />
|
<slot :name="(name as keyof CheckboxGroupSlots<T>)" :item="item" />
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
slot?: string
|
slot?: string
|
||||||
onSelect?(e?: Event): void
|
onSelect?(e?: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<CommandPalette['slots'], 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemLabelPrefix' | 'itemLabelBase' | 'itemLabelSuffix' | 'itemTrailing' | 'itemTrailingKbds' | 'itemTrailingKbdsSize' | 'itemTrailingHighlightedIcon' | 'itemTrailingIcon'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,42 +295,42 @@ const groups = computed(() => {
|
|||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ class: props.ui?.item, active: active || item.active })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class], active: active || item.active })">
|
||||||
<slot :name="((item.slot || group.slot || 'item') as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
<slot :name="((item.slot || group.slot || 'item') as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
||||||
<slot :name="((item.slot ? `${item.slot}-leading` : group.slot ? `${group.slot}-leading` : `item-leading`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-leading` : group.slot ? `${group.slot}-leading` : `item-leading`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
||||||
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, loading: true })" />
|
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon], loading: true })" />
|
||||||
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, active: active || item.active })" />
|
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon], active: active || item.active })" />
|
||||||
<UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar, active: active || item.active })" />
|
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active: active || item.active })" />
|
||||||
<UChip
|
<UChip
|
||||||
v-else-if="item.chip"
|
v-else-if="item.chip"
|
||||||
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
||||||
inset
|
inset
|
||||||
standalone
|
standalone
|
||||||
v-bind="item.chip"
|
v-bind="item.chip"
|
||||||
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip, active: active || item.active })"
|
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip], active: active || item.active })"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>]" :class="ui.itemLabel({ class: props.ui?.itemLabel, active: active || item.active })">
|
<span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>]" :class="ui.itemLabel({ class: [props.ui?.itemLabel, item.ui?.itemLabel], active: active || item.active })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
||||||
<span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: props.ui?.itemLabelPrefix })">{{ item.prefix }}</span>
|
<span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: [props.ui?.itemLabelPrefix, item.ui?.itemLabelPrefix] })">{{ item.prefix }}</span>
|
||||||
|
|
||||||
<span :class="ui.itemLabelBase({ class: props.ui?.itemLabelBase, active: active || item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
|
<span :class="ui.itemLabelBase({ class: [props.ui?.itemLabelBase, item.ui?.itemLabelBase], active: active || item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
|
||||||
|
|
||||||
<span :class="ui.itemLabelSuffix({ class: props.ui?.itemLabelSuffix, active: active || item.active })" v-html="item.suffixHtml || item.suffix" />
|
<span :class="ui.itemLabelSuffix({ class: [props.ui?.itemLabelSuffix, item.ui?.itemLabelSuffix], active: active || item.active })" v-html="item.suffixHtml || item.suffix" />
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, item.ui?.itemTrailing] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
|
||||||
<span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: props.ui?.itemTrailingKbds })">
|
<span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [props.ui?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
|
||||||
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
||||||
</span>
|
</span>
|
||||||
<UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: props.ui?.itemTrailingHighlightedIcon })" />
|
<UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: [props.ui?.itemTrailingHighlightedIcon, item.ui?.itemTrailingHighlightedIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<ListboxItemIndicator as-child>
|
<ListboxItemIndicator as-child>
|
||||||
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })" />
|
||||||
</ListboxItemIndicator>
|
</ListboxItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custo
|
|||||||
children?: ArrayOrNested<ContextMenuItem>
|
children?: ArrayOrNested<ContextMenuItem>
|
||||||
onSelect?(e: Event): void
|
onSelect?(e: Event): void
|
||||||
onUpdateChecked?(checked: boolean): void
|
onUpdateChecked?(checked: boolean): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<ContextMenu['slots'], 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLabel' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,29 +77,29 @@ const groups = computed<ContextMenuItem[][]>(() =>
|
|||||||
<DefineItemTemplate v-slot="{ item, active, index }">
|
<DefineItemTemplate v-slot="{ item, active, index }">
|
||||||
<slot :name="((item.slot || 'item') as keyof ContextMenuSlots<T>)" :item="item" :index="index">
|
<slot :name="((item.slot || 'item') as keyof ContextMenuSlots<T>)" :item="item" :index="index">
|
||||||
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
|
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, loading: true })" />
|
||||||
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
|
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, active })" />
|
||||||
<UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
|
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>]" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
|
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>]" :class="ui.itemLabel({ class: [uiOverride?.itemLabel, item.ui?.itemLabel], active })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: [uiOverride?.itemLabelExternalIcon, item.ui?.itemLabelExternalIcon], color: item?.color, active })" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [uiOverride?.itemTrailing, item.ui?.itemTrailing] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
|
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color, active })" />
|
||||||
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
|
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [uiOverride?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
|
||||||
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<ContextMenu.ItemIndicator as-child>
|
<ContextMenu.ItemIndicator as-child>
|
||||||
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color })" />
|
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color })" />
|
||||||
</ContextMenu.ItemIndicator>
|
</ContextMenu.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -111,17 +111,17 @@ const groups = computed<ContextMenuItem[][]>(() =>
|
|||||||
|
|
||||||
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
|
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
|
||||||
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
||||||
<ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
|
<ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: [uiOverride?.label, item.ui?.label, item.class] })">
|
||||||
<ReuseItemTemplate :item="item" :index="index" />
|
<ReuseItemTemplate :item="item" :index="index" />
|
||||||
</ContextMenu.Label>
|
</ContextMenu.Label>
|
||||||
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: uiOverride?.separator })" />
|
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: [uiOverride?.separator, item.ui?.separator, item.class] })" />
|
||||||
<ContextMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
<ContextMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
||||||
<ContextMenu.SubTrigger
|
<ContextMenu.SubTrigger
|
||||||
as="button"
|
as="button"
|
||||||
type="button"
|
type="button"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:text-value="get(item, props.labelKey as string)"
|
:text-value="get(item, props.labelKey as string)"
|
||||||
:class="ui.item({ class: uiOverride?.item, color: item?.color })"
|
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
||||||
>
|
>
|
||||||
<ReuseItemTemplate :item="item" :index="index" />
|
<ReuseItemTemplate :item="item" :index="index" />
|
||||||
</ContextMenu.SubTrigger>
|
</ContextMenu.SubTrigger>
|
||||||
@@ -150,7 +150,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
|
|||||||
:model-value="item.checked"
|
:model-value="item.checked"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:text-value="get(item, props.labelKey as string)"
|
:text-value="get(item, props.labelKey as string)"
|
||||||
:class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
|
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
||||||
@update:model-value="item.onUpdateChecked"
|
@update:model-value="item.onUpdateChecked"
|
||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
@@ -164,7 +164,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
|
|||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom>
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], active, color: item?.color })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], active, color: item?.color })">
|
||||||
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
</ULink>
|
</ULink>
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
|
|||||||
children?: ArrayOrNested<DropdownMenuItem>
|
children?: ArrayOrNested<DropdownMenuItem>
|
||||||
onSelect?(e: Event): void
|
onSelect?(e: Event): void
|
||||||
onUpdateChecked?(checked: boolean): void
|
onUpdateChecked?(checked: boolean): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<DropdownMenu['slots'], 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLabel' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,29 +83,29 @@ const groups = computed<DropdownMenuItem[][]>(() =>
|
|||||||
<DefineItemTemplate v-slot="{ item, active, index }">
|
<DefineItemTemplate v-slot="{ item, active, index }">
|
||||||
<slot :name="((item.slot || 'item') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :index="index">
|
<slot :name="((item.slot || 'item') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :index="index">
|
||||||
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
||||||
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
|
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, loading: true })" />
|
||||||
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
|
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, active })" />
|
||||||
<UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
|
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>]" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
|
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>]" :class="ui.itemLabel({ class: [uiOverride?.itemLabel, item.ui?.itemLabel], active })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: [uiOverride?.itemLabelExternalIcon, item.ui?.itemLabelExternalIcon], color: item?.color, active })" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [uiOverride?.itemTrailing, item.ui?.itemTrailing] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
|
||||||
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
|
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color, active })" />
|
||||||
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
|
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [uiOverride?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
|
||||||
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<DropdownMenu.ItemIndicator as-child>
|
<DropdownMenu.ItemIndicator as-child>
|
||||||
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color })" />
|
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color })" />
|
||||||
</DropdownMenu.ItemIndicator>
|
</DropdownMenu.ItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -117,17 +117,17 @@ const groups = computed<DropdownMenuItem[][]>(() =>
|
|||||||
|
|
||||||
<DropdownMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
|
<DropdownMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
|
||||||
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
||||||
<DropdownMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
|
<DropdownMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: [uiOverride?.label, item.ui?.label, item.class] })">
|
||||||
<ReuseItemTemplate :item="item" :index="index" />
|
<ReuseItemTemplate :item="item" :index="index" />
|
||||||
</DropdownMenu.Label>
|
</DropdownMenu.Label>
|
||||||
<DropdownMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: uiOverride?.separator })" />
|
<DropdownMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: [uiOverride?.separator, item.ui?.separator, item.class] })" />
|
||||||
<DropdownMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
<DropdownMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
||||||
<DropdownMenu.SubTrigger
|
<DropdownMenu.SubTrigger
|
||||||
as="button"
|
as="button"
|
||||||
type="button"
|
type="button"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:text-value="get(item, props.labelKey as string)"
|
:text-value="get(item, props.labelKey as string)"
|
||||||
:class="ui.item({ class: uiOverride?.item, color: item?.color })"
|
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
||||||
>
|
>
|
||||||
<ReuseItemTemplate :item="item" :index="index" />
|
<ReuseItemTemplate :item="item" :index="index" />
|
||||||
</DropdownMenu.SubTrigger>
|
</DropdownMenu.SubTrigger>
|
||||||
@@ -158,7 +158,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
|
|||||||
:model-value="item.checked"
|
:model-value="item.checked"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:text-value="get(item, props.labelKey as string)"
|
:text-value="get(item, props.labelKey as string)"
|
||||||
:class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
|
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
||||||
@update:model-value="item.onUpdateChecked"
|
@update:model-value="item.onUpdateChecked"
|
||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
@@ -172,7 +172,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
|
|||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom>
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color, active })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color, active })">
|
||||||
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
</ULink>
|
</ULink>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ interface _InputMenuItem {
|
|||||||
type?: 'label' | 'separator' | 'item'
|
type?: 'label' | 'separator' | 'item'
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
onSelect?(e?: Event): void
|
onSelect?(e?: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<InputMenu['slots'], 'tagsItem' | 'tagsItemText' | 'tagsItemDelete' | 'tagsItemDeleteIcon' | 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChip' | 'itemLeadingChipSize' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean
|
export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean
|
||||||
@@ -426,16 +428,16 @@ defineExpose({
|
|||||||
@focus="onFocus"
|
@focus="onFocus"
|
||||||
@remove-tag="onRemoveTag"
|
@remove-tag="onRemoveTag"
|
||||||
>
|
>
|
||||||
<TagsInputItem v-for="(item, index) in tags" :key="index" :value="item" :class="ui.tagsItem({ class: props.ui?.tagsItem })">
|
<TagsInputItem v-for="(item, index) in tags" :key="index" :value="item" :class="ui.tagsItem({ class: [props.ui?.tagsItem, isInputItem(item) && item.ui?.tagsItem] })">
|
||||||
<TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
|
<TagsInputItemText :class="ui.tagsItemText({ class: [props.ui?.tagsItemText, isInputItem(item) && item.ui?.tagsItemText] })">
|
||||||
<slot name="tags-item-text" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="tags-item-text" :item="(item as NestedItem<T>)" :index="index">
|
||||||
{{ displayValue(item as T) }}
|
{{ displayValue(item as T) }}
|
||||||
</slot>
|
</slot>
|
||||||
</TagsInputItemText>
|
</TagsInputItemText>
|
||||||
|
|
||||||
<TagsInputItemDelete :class="ui.tagsItemDelete({ class: props.ui?.tagsItemDelete })" :disabled="disabled">
|
<TagsInputItemDelete :class="ui.tagsItemDelete({ class: [props.ui?.tagsItemDelete, isInputItem(item) && item.ui?.tagsItemDelete] })" :disabled="disabled">
|
||||||
<slot name="tags-item-delete" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="tags-item-delete" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<UIcon :name="deleteIcon || appConfig.ui.icons.close" :class="ui.tagsItemDeleteIcon({ class: props.ui?.tagsItemDeleteIcon })" />
|
<UIcon :name="deleteIcon || appConfig.ui.icons.close" :class="ui.tagsItemDeleteIcon({ class: [props.ui?.tagsItemDeleteIcon, isInputItem(item) && item.ui?.tagsItemDeleteIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
</TagsInputItemDelete>
|
</TagsInputItemDelete>
|
||||||
</TagsInputItem>
|
</TagsInputItem>
|
||||||
@@ -493,44 +495,44 @@ defineExpose({
|
|||||||
|
|
||||||
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
||||||
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
||||||
<ComboboxLabel v-if="isInputItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
<ComboboxLabel v-if="isInputItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</ComboboxLabel>
|
</ComboboxLabel>
|
||||||
|
|
||||||
<ComboboxSeparator v-else-if="isInputItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
<ComboboxSeparator v-else-if="isInputItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
|
||||||
|
|
||||||
<ComboboxItem
|
<ComboboxItem
|
||||||
v-else
|
v-else
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, isInputItem(item) && item.ui?.item, isInputItem(item) && item.class] })"
|
||||||
:disabled="isInputItem(item) && item.disabled"
|
:disabled="isInputItem(item) && item.disabled"
|
||||||
:value="props.valueKey && isInputItem(item) ? get(item, props.valueKey as string) : item"
|
:value="props.valueKey && isInputItem(item) ? get(item, props.valueKey as string) : item"
|
||||||
@select="onSelect($event, item)"
|
@select="onSelect($event, item)"
|
||||||
>
|
>
|
||||||
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<UIcon v-if="isInputItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
<UIcon v-if="isInputItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
|
||||||
<UAvatar v-else-if="isInputItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
<UAvatar v-else-if="isInputItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
|
||||||
<UChip
|
<UChip
|
||||||
v-else-if="isInputItem(item) && item.chip"
|
v-else-if="isInputItem(item) && item.chip"
|
||||||
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
||||||
inset
|
inset
|
||||||
standalone
|
standalone
|
||||||
v-bind="item.chip"
|
v-bind="item.chip"
|
||||||
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
|
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
<span :class="ui.itemLabel({ class: [props.ui?.itemLabel, isInputItem(item) && item.ui?.itemLabel] })">
|
||||||
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
||||||
{{ isInputItem(item) ? get(item, props.labelKey as string) : item }}
|
{{ isInputItem(item) ? get(item, props.labelKey as string) : item }}
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isInputItem(item) && item.ui?.itemTrailing] })">
|
||||||
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
||||||
|
|
||||||
<ComboboxItemIndicator as-child>
|
<ComboboxItemIndicator as-child>
|
||||||
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isInputItem(item) && item.ui?.itemTrailingIcon] })" />
|
||||||
</ComboboxItemIndicator>
|
</ComboboxItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps,
|
|||||||
|
|
||||||
type NavigationMenu = ComponentConfig<typeof theme, AppConfig, 'navigationMenu'>
|
type NavigationMenu = ComponentConfig<typeof theme, AppConfig, 'navigationMenu'>
|
||||||
|
|
||||||
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type'> {
|
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type' | 'ui'> {
|
||||||
/** Description is only used when `orientation` is `horizontal`. */
|
/** Description is only used when `orientation` is `horizontal`. */
|
||||||
description?: string
|
description?: string
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
@@ -56,6 +56,8 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
|||||||
collapsible?: boolean
|
collapsible?: boolean
|
||||||
children?: NavigationMenuChildItem[]
|
children?: NavigationMenuChildItem[]
|
||||||
onSelect?(e: Event): void
|
onSelect?(e: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<NavigationMenu['slots'], 'item' | 'linkLeadingAvatarSize' | 'linkLeadingAvatar' | 'linkLeadingIcon' | 'linkLabel' | 'linkLabelExternalIcon' | 'linkTrailing' | 'linkTrailingBadgeSize' | 'linkTrailingBadge' | 'linkTrailingIcon' | 'label' | 'link' | 'content' | 'childList' | 'childItem' | 'childLink' | 'childLinkIcon' | 'childLinkWrapper' | 'childLinkLabel' | 'childLinkLabelExternalIcon' | 'childLinkDescription'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,34 +222,34 @@ const lists = computed<NavigationMenuItem[][]>(() =>
|
|||||||
<DefineLinkTemplate v-slot="{ item, active, index }">
|
<DefineLinkTemplate v-slot="{ item, active, index }">
|
||||||
<slot :name="((item.slot || 'item') as keyof NavigationMenuSlots<T>)" :item="item" :index="index">
|
<slot :name="((item.slot || 'item') as keyof NavigationMenuSlots<T>)" :item="item" :index="index">
|
||||||
<slot :name="((item.slot ? `${item.slot}-leading` : 'item-leading') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-leading` : 'item-leading') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
<UAvatar v-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active, disabled: !!item.disabled })" />
|
<UAvatar v-if="item.avatar" :size="((item.ui?.linkLeadingAvatarSize || props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: [props.ui?.linkLeadingAvatar, item.ui?.linkLeadingAvatar], active, disabled: !!item.disabled })" />
|
||||||
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active, disabled: !!item.disabled })" />
|
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon], active, disabled: !!item.disabled })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>])"
|
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>])"
|
||||||
:class="ui.linkLabel({ class: props.ui?.linkLabel })"
|
:class="ui.linkLabel({ class: [props.ui?.linkLabel, item.ui?.linkLabel] })"
|
||||||
>
|
>
|
||||||
<slot :name="((item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
|
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: [props.ui?.linkLabelExternalIcon, item.ui?.linkLabelExternalIcon], active })" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[(item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
|
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[(item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>])" :class="ui.linkTrailing({ class: [props.ui?.linkTrailing, item.ui?.linkTrailing] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
<UBadge
|
<UBadge
|
||||||
v-if="item.badge"
|
v-if="item.badge"
|
||||||
color="neutral"
|
color="neutral"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
:size="((props.ui?.linkTrailingBadgeSize || ui.linkTrailingBadgeSize()) as BadgeProps['size'])"
|
:size="((item.ui?.linkTrailingBadgeSize || props.ui?.linkTrailingBadgeSize || ui.linkTrailingBadgeSize()) as BadgeProps['size'])"
|
||||||
v-bind="(typeof item.badge === 'string' || typeof item.badge === 'number') ? { label: item.badge } : item.badge"
|
v-bind="(typeof item.badge === 'string' || typeof item.badge === 'number') ? { label: item.badge } : item.badge"
|
||||||
:class="ui.linkTrailingBadge({ class: props.ui?.linkTrailingBadge })"
|
:class="ui.linkTrailingBadge({ class: [props.ui?.linkTrailingBadge, item.ui?.linkTrailingBadge] })"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length && item.collapsible !== false)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
|
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length && item.collapsible !== false)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon], active })" />
|
||||||
<UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
|
<UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon], active })" />
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -263,7 +265,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
|
|||||||
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
|
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
|
||||||
:open="item.open"
|
:open="item.open"
|
||||||
>
|
>
|
||||||
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
|
||||||
<ReuseLinkTemplate :item="item" :index="index" />
|
<ReuseLinkTemplate :item="item" :index="index" />
|
||||||
</div>
|
</div>
|
||||||
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && item.collapsible !== false) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
|
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && item.collapsible !== false) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
|
||||||
@@ -275,31 +277,31 @@ const lists = computed<NavigationMenuItem[][]>(() =>
|
|||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
<UTooltip v-if="!!item.tooltip" :content="{ side: 'right' }" v-bind="item.tooltip">
|
<UTooltip v-if="!!item.tooltip" :content="{ side: 'right' }" v-bind="item.tooltip">
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.ui?.link], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
||||||
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
|
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
<ULinkBase v-else v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
<ULinkBase v-else v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.ui?.link], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
|
||||||
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
|
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
</component>
|
</component>
|
||||||
|
|
||||||
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
|
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])" v-bind="contentProps" :class="ui.content({ class: [props.ui?.content, item.ui?.content] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
<slot :name="((item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
|
||||||
<ul :class="ui.childList({ class: props.ui?.childList })">
|
<ul :class="ui.childList({ class: [props.ui?.childList, item.ui?.childList] })">
|
||||||
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
|
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: [props.ui?.childItem, item.ui?.childItem, childItem.class] })">
|
||||||
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
|
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
|
||||||
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
|
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
|
||||||
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
|
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, item.ui?.childLink], active: childActive })">
|
||||||
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />
|
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: [props.ui?.childLinkIcon, item.ui?.childLinkIcon], active: childActive })" />
|
||||||
|
|
||||||
<div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
|
<div :class="ui.childLinkWrapper({ class: [props.ui?.childLinkWrapper, item.ui?.childLinkWrapper] })">
|
||||||
<p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
|
<p :class="ui.childLinkLabel({ class: [props.ui?.childLinkLabel, item.ui?.childLinkLabel], active: childActive })">
|
||||||
{{ get(childItem, props.labelKey as string) }}
|
{{ get(childItem, props.labelKey as string) }}
|
||||||
|
|
||||||
<UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
|
<UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: [props.ui?.childLinkLabelExternalIcon, item.ui?.childLinkLabelExternalIcon], active: childActive })" />
|
||||||
</p>
|
</p>
|
||||||
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
|
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: [props.ui?.childLinkDescription, item.ui?.childLinkDescription], active: childActive })">
|
||||||
{{ childItem.description }}
|
{{ childItem.description }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -320,7 +322,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
|
|||||||
:item="childItem"
|
:item="childItem"
|
||||||
:index="childIndex"
|
:index="childIndex"
|
||||||
:level="level + 1"
|
:level="level + 1"
|
||||||
:class="ui.childItem({ class: props.ui?.childItem })"
|
:class="ui.childItem({ class: [props.ui?.childItem, childItem.ui?.childItem, childItem.class] })"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
@@ -332,7 +334,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
|
|||||||
|
|
||||||
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
|
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
|
||||||
<NavigationMenuList :class="ui.list({ class: props.ui?.list })">
|
<NavigationMenuList :class="ui.list({ class: props.ui?.list })">
|
||||||
<ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="ui.item({ class: props.ui?.item })" />
|
<ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })" />
|
||||||
</NavigationMenuList>
|
</NavigationMenuList>
|
||||||
|
|
||||||
<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" />
|
<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" />
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ export type RadioGroupItem = {
|
|||||||
description?: string
|
description?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
value?: RadioGroupValue
|
value?: RadioGroupValue
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<RadioGroup['slots'], 'item' | 'container' | 'base' | 'indicator' | 'wrapper' | 'label' | 'description'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
} | RadioGroupValue
|
} | RadioGroupValue
|
||||||
|
|
||||||
@@ -176,25 +178,25 @@ function onUpdate(value: any) {
|
|||||||
</slot>
|
</slot>
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
<component :is="variant === 'list' ? 'div' : Label" v-for="item in normalizedItems" :key="item.value" :class="ui.item({ class: props.ui?.item })">
|
<component :is="variant === 'list' ? 'div' : Label" v-for="item in normalizedItems" :key="item.value" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })">
|
||||||
<div :class="ui.container({ class: props.ui?.container })">
|
<div :class="ui.container({ class: [props.ui?.container, item.ui?.container] })">
|
||||||
<RadioGroupItem
|
<RadioGroupItem
|
||||||
:id="item.id"
|
:id="item.id"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:class="ui.base({ class: props.ui?.base, disabled: item.disabled })"
|
:class="ui.base({ class: [props.ui?.base, item.ui?.base], disabled: item.disabled })"
|
||||||
>
|
>
|
||||||
<RadioGroupIndicator :class="ui.indicator({ class: props.ui?.indicator })" />
|
<RadioGroupIndicator :class="ui.indicator({ class: [props.ui?.indicator, item.ui?.indicator] })" />
|
||||||
</RadioGroupItem>
|
</RadioGroupItem>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: props.ui?.wrapper })">
|
<div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })">
|
||||||
<component :is="variant === 'list' ? Label : 'p'" v-if="item.label || !!slots.label" :for="item.id" :class="ui.label({ class: props.ui?.label })">
|
<component :is="variant === 'list' ? Label : 'p'" v-if="item.label || !!slots.label" :for="item.id" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
|
||||||
<slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
<slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</slot>
|
</slot>
|
||||||
</component>
|
</component>
|
||||||
<p v-if="item.description || !!slots.description" :class="ui.description({ class: props.ui?.description })">
|
<p v-if="item.description || !!slots.description" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })">
|
||||||
<slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
<slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
|
||||||
{{ item.description }}
|
{{ item.description }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ interface SelectItemBase {
|
|||||||
value?: AcceptableValue | boolean
|
value?: AcceptableValue | boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
onSelect?(e?: Event): void
|
onSelect?(e?: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Select['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
||||||
@@ -271,44 +273,44 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
|
|||||||
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
|
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
|
||||||
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
||||||
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
||||||
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</SelectLabel>
|
</SelectLabel>
|
||||||
|
|
||||||
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
|
||||||
|
|
||||||
<SelectItem
|
<SelectItem
|
||||||
v-else
|
v-else
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, isSelectItem(item) && item.ui?.item, isSelectItem(item) && item.class] })"
|
||||||
:disabled="isSelectItem(item) && item.disabled"
|
:disabled="isSelectItem(item) && item.disabled"
|
||||||
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
||||||
@select="isSelectItem(item) && item.onSelect?.($event)"
|
@select="isSelectItem(item) && item.onSelect?.($event)"
|
||||||
>
|
>
|
||||||
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
|
||||||
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
|
||||||
<UChip
|
<UChip
|
||||||
v-else-if="isSelectItem(item) && item.chip"
|
v-else-if="isSelectItem(item) && item.chip"
|
||||||
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
||||||
inset
|
inset
|
||||||
standalone
|
standalone
|
||||||
v-bind="item.chip"
|
v-bind="item.chip"
|
||||||
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
|
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<SelectItemText :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
<SelectItemText :class="ui.itemLabel({ class: [props.ui?.itemLabel, isSelectItem(item) && item.ui?.itemLabel] })">
|
||||||
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
||||||
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
||||||
</slot>
|
</slot>
|
||||||
</SelectItemText>
|
</SelectItemText>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isSelectItem(item) && item.ui?.itemTrailing] })">
|
||||||
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
||||||
|
|
||||||
<SelectItemIndicator as-child>
|
<SelectItemIndicator as-child>
|
||||||
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isSelectItem(item) && item.ui?.itemTrailingIcon] })" />
|
||||||
</SelectItemIndicator>
|
</SelectItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ interface _SelectMenuItem {
|
|||||||
type?: 'label' | 'separator' | 'item'
|
type?: 'label' | 'separator' | 'item'
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
onSelect?(e?: Event): void
|
onSelect?(e?: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<SelectMenu['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
|
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
|
||||||
@@ -420,44 +422,44 @@ function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
|
|||||||
|
|
||||||
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
||||||
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
||||||
<ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
<ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
|
||||||
{{ get(item, props.labelKey as string) }}
|
{{ get(item, props.labelKey as string) }}
|
||||||
</ComboboxLabel>
|
</ComboboxLabel>
|
||||||
|
|
||||||
<ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
|
<ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
|
||||||
|
|
||||||
<ComboboxItem
|
<ComboboxItem
|
||||||
v-else
|
v-else
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, isSelectItem(item) && item.ui?.item, isSelectItem(item) && item.class] })"
|
||||||
:disabled="isSelectItem(item) && item.disabled"
|
:disabled="isSelectItem(item) && item.disabled"
|
||||||
:value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
:value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
|
||||||
@select="onSelect($event, item)"
|
@select="onSelect($event, item)"
|
||||||
>
|
>
|
||||||
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
|
||||||
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
|
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
|
||||||
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
|
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
|
||||||
<UChip
|
<UChip
|
||||||
v-else-if="isSelectItem(item) && item.chip"
|
v-else-if="isSelectItem(item) && item.chip"
|
||||||
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
|
||||||
inset
|
inset
|
||||||
standalone
|
standalone
|
||||||
v-bind="item.chip"
|
v-bind="item.chip"
|
||||||
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
|
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
<span :class="ui.itemLabel({ class: [props.ui?.itemLabel, isSelectItem(item) && item.ui?.itemLabel] })">
|
||||||
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
|
||||||
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
|
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isSelectItem(item) && item.ui?.itemTrailing] })">
|
||||||
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
|
||||||
|
|
||||||
<ComboboxItemIndicator as-child>
|
<ComboboxItemIndicator as-child>
|
||||||
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isSelectItem(item) && item.ui?.itemTrailingIcon] })" />
|
||||||
</ComboboxItemIndicator>
|
</ComboboxItemIndicator>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ export interface StepperItem {
|
|||||||
icon?: string
|
icon?: string
|
||||||
content?: string
|
content?: string
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Stepper['slots'], 'item' | 'container' | 'trigger' | 'indicator' | 'icon' | 'separator' | 'wrapper' | 'title' | 'description'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,13 +138,13 @@ defineExpose({
|
|||||||
:key="item.value ?? count"
|
:key="item.value ?? count"
|
||||||
:step="count"
|
:step="count"
|
||||||
:disabled="item.disabled || props.disabled"
|
:disabled="item.disabled || props.disabled"
|
||||||
:class="ui.item({ class: props.ui?.item })"
|
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
|
||||||
>
|
>
|
||||||
<div :class="ui.container({ class: props.ui?.container })">
|
<div :class="ui.container({ class: [props.ui?.container, item.ui?.container] })">
|
||||||
<StepperTrigger :class="ui.trigger({ class: props.ui?.trigger })">
|
<StepperTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger] })">
|
||||||
<StepperIndicator :class="ui.indicator({ class: props.ui?.indicator })">
|
<StepperIndicator :class="ui.indicator({ class: [props.ui?.indicator, item.ui?.indicator] })">
|
||||||
<slot name="indicator" :item="item">
|
<slot name="indicator" :item="item">
|
||||||
<UIcon v-if="item.icon" :name="item.icon" :class="ui.icon({ class: props.ui?.icon })" />
|
<UIcon v-if="item.icon" :name="item.icon" :class="ui.icon({ class: [props.ui?.icon, item.ui?.icon] })" />
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ count + 1 }}
|
{{ count + 1 }}
|
||||||
</template>
|
</template>
|
||||||
@@ -152,17 +154,17 @@ defineExpose({
|
|||||||
|
|
||||||
<StepperSeparator
|
<StepperSeparator
|
||||||
v-if="count < items.length - 1"
|
v-if="count < items.length - 1"
|
||||||
:class="ui.separator({ class: props.ui?.separator })"
|
:class="ui.separator({ class: [props.ui?.separator, item.ui?.separator] })"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="ui.wrapper({ class: props.ui?.wrapper })">
|
<div :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })">
|
||||||
<StepperTitle as="div" :class="ui.title({ class: props.ui?.title })">
|
<StepperTitle as="div" :class="ui.title({ class: [props.ui?.title, item.ui?.title] })">
|
||||||
<slot name="title" :item="item">
|
<slot name="title" :item="item">
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</slot>
|
</slot>
|
||||||
</StepperTitle>
|
</StepperTitle>
|
||||||
<StepperDescription as="div" :class="ui.description({ class: props.ui?.description })">
|
<StepperDescription as="div" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })">
|
||||||
<slot name="description" :item="item">
|
<slot name="description" :item="item">
|
||||||
{{ item.description }}
|
{{ item.description }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export interface TabsItem {
|
|||||||
/** A unique value for the tab item. Defaults to the index. */
|
/** A unique value for the tab item. Defaults to the index. */
|
||||||
value?: string | number
|
value?: string | number
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Tabs['slots'], 'trigger' | 'leadingIcon' | 'leadingAvatar' | 'label' | 'content'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,13 +117,13 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tabs || {})
|
|||||||
|
|
||||||
<slot name="list-leading" />
|
<slot name="list-leading" />
|
||||||
|
|
||||||
<TabsTrigger v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :disabled="item.disabled" :class="ui.trigger({ class: props.ui?.trigger })">
|
<TabsTrigger v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :disabled="item.disabled" :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger] })">
|
||||||
<slot name="leading" :item="item" :index="index">
|
<slot name="leading" :item="item" :index="index">
|
||||||
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
|
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: [props.ui?.leadingIcon, item.ui?.leadingIcon] })" />
|
||||||
<UAvatar v-else-if="item.avatar" :size="((props.ui?.leadingAvatarSize || ui.leadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.leadingAvatar({ class: props.ui?.leadingAvatar })" />
|
<UAvatar v-else-if="item.avatar" :size="((props.ui?.leadingAvatarSize || ui.leadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.leadingAvatar({ class: [props.ui?.leadingAvatar, item.ui?.leadingAvatar] })" />
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: props.ui?.label })">
|
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
|
||||||
<slot :item="item" :index="index">{{ get(item, props.labelKey as string) }}</slot>
|
<slot :item="item" :index="index">{{ get(item, props.labelKey as string) }}</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -132,7 +134,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tabs || {})
|
|||||||
</TabsList>
|
</TabsList>
|
||||||
|
|
||||||
<template v-if="!!content">
|
<template v-if="!!content">
|
||||||
<TabsContent v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :class="ui.content({ class: props.ui?.content })">
|
<TabsContent v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :class="ui.content({ class: [props.ui?.content, item.ui?.content, item.class] })">
|
||||||
<slot :name="((item.slot || 'content') as keyof TabsSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index">
|
<slot :name="((item.slot || 'content') as keyof TabsSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index">
|
||||||
{{ item.content }}
|
{{ item.content }}
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export type TreeItem = {
|
|||||||
children?: TreeItem[]
|
children?: TreeItem[]
|
||||||
onToggle?(e: Event): void
|
onToggle?(e: Event): void
|
||||||
onSelect?(e?: Event): void
|
onSelect?(e?: Event): void
|
||||||
|
class?: any
|
||||||
|
ui?: Pick<Tree['slots'], 'item' | 'itemWithChildren' | 'link' | 'linkLeadingIcon' | 'linkLabel' | 'linkTrailing' | 'linkTrailingIcon' | 'listWithChildren'>
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +151,7 @@ const defaultExpanded = computed(() =>
|
|||||||
<li
|
<li
|
||||||
v-for="(item, index) in items"
|
v-for="(item, index) in items"
|
||||||
:key="`${level}-${index}`"
|
:key="`${level}-${index}`"
|
||||||
:class="level > 0 ? ui.itemWithChildren({ class: props.ui?.itemWithChildren }) : ui.item({ class: props.ui?.item })"
|
:class="level > 0 ? ui.itemWithChildren({ class: [props.ui?.itemWithChildren, item.ui?.itemWithChildren, item.class] }) : ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
|
||||||
>
|
>
|
||||||
<TreeItem
|
<TreeItem
|
||||||
v-slot="{ isExpanded, isSelected }"
|
v-slot="{ isExpanded, isSelected }"
|
||||||
@@ -159,37 +161,37 @@ const defaultExpanded = computed(() =>
|
|||||||
@toggle="item.onToggle"
|
@toggle="item.onToggle"
|
||||||
@select="item.onSelect"
|
@select="item.onSelect"
|
||||||
>
|
>
|
||||||
<button :disabled="item.disabled || disabled" :class="ui.link({ class: props.ui?.link, selected: isSelected, disabled: item.disabled || disabled })">
|
<button :disabled="item.disabled || disabled" :class="ui.link({ class: [props.ui?.link, item.ui?.link], selected: isSelected, disabled: item.disabled || disabled })">
|
||||||
<slot :name="((item.slot || 'item') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
<slot :name="((item.slot || 'item') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
||||||
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
||||||
<UIcon
|
<UIcon
|
||||||
v-if="item.icon"
|
v-if="item.icon"
|
||||||
:name="item.icon"
|
:name="item.icon"
|
||||||
:class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon })"
|
:class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon] })"
|
||||||
/>
|
/>
|
||||||
<UIcon
|
<UIcon
|
||||||
v-else-if="item.children?.length"
|
v-else-if="item.children?.length"
|
||||||
:name="isExpanded ? (expandedIcon ?? appConfig.ui.icons.folderOpen) : (collapsedIcon ?? appConfig.ui.icons.folder)"
|
:name="isExpanded ? (expandedIcon ?? appConfig.ui.icons.folderOpen) : (collapsedIcon ?? appConfig.ui.icons.folder)"
|
||||||
:class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon })"
|
:class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon] })"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="getItemLabel(item) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>]" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
|
<span v-if="getItemLabel(item) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>]" :class="ui.linkLabel({ class: [props.ui?.linkLabel, item.ui?.linkLabel] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
||||||
{{ getItemLabel(item) }}
|
{{ getItemLabel(item) }}
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="item.trailingIcon || item.children?.length || !!slots[(item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>]" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
|
<span v-if="item.trailingIcon || item.children?.length || !!slots[(item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>]" :class="ui.linkTrailing({ class: [props.ui?.linkTrailing, item.ui?.linkTrailing] })">
|
||||||
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
|
||||||
<UIcon v-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon })" />
|
<UIcon v-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon] })" />
|
||||||
<UIcon v-else-if="item.children?.length" :name="trailingIcon ?? appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon })" />
|
<UIcon v-else-if="item.children?.length" :name="trailingIcon ?? appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon] })" />
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ul v-if="item.children?.length && isExpanded" :class="ui.listWithChildren({ class: props.ui?.listWithChildren })">
|
<ul v-if="item.children?.length && isExpanded" :class="ui.listWithChildren({ class: [props.ui?.listWithChildren, item.ui?.listWithChildren] })">
|
||||||
<ReuseTreeTemplate :items="item.children" :level="level + 1" />
|
<ReuseTreeTemplate :items="item.children" :level="level + 1" />
|
||||||
</ul>
|
</ul>
|
||||||
</TreeItem>
|
</TreeItem>
|
||||||
|
|||||||
Reference in New Issue
Block a user