mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-27 10:20:42 +01:00
chore(Link): add pickLinkProps util
This commit is contained in:
@@ -11,7 +11,7 @@ const appConfig = _appConfig as AppConfig & { ui: { breadcrumb: Partial<typeof t
|
|||||||
|
|
||||||
const breadcrumb = tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb || {}) })
|
const breadcrumb = tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb || {}) })
|
||||||
|
|
||||||
export interface BreadcrumbItem extends LinkProps {
|
export interface BreadcrumbItem extends Omit<LinkProps, 'custom'> {
|
||||||
label?: string
|
label?: string
|
||||||
icon?: string
|
icon?: string
|
||||||
avatar?: AvatarProps
|
avatar?: AvatarProps
|
||||||
@@ -41,7 +41,7 @@ import { computed } from 'vue'
|
|||||||
import { Primitive } from 'radix-vue'
|
import { Primitive } from 'radix-vue'
|
||||||
import { useAppConfig } from '#imports'
|
import { useAppConfig } from '#imports'
|
||||||
import { ULink, UIcon, UAvatar } from '#components'
|
import { ULink, UIcon, UAvatar } from '#components'
|
||||||
import { omit } from '#ui/utils'
|
import { pickLinkProps } from '#ui/utils/link'
|
||||||
|
|
||||||
const props = defineProps<BreadcrumbProps<T>>()
|
const props = defineProps<BreadcrumbProps<T>>()
|
||||||
const slots = defineSlots<BreadcrumbSlots<T>>()
|
const slots = defineSlots<BreadcrumbSlots<T>>()
|
||||||
@@ -56,7 +56,7 @@ const ui = computed(() => tv({ extend: breadcrumb, slots: props.ui })())
|
|||||||
<ol :class="ui.list()">
|
<ol :class="ui.list()">
|
||||||
<template v-for="(item, index) in items" :key="index">
|
<template v-for="(item, index) in items" :key="index">
|
||||||
<li :class="ui.itemWrapper()">
|
<li :class="ui.itemWrapper()">
|
||||||
<ULink as="span" v-bind="omit(item, ['label', 'icon', 'avatar', 'slot'])" :aria-current="index === items!.length - 1 ? 'page' : undefined" :class="ui.item({ active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })" raw>
|
<ULink v-bind="pickLinkProps(item)" as="span" :aria-current="index === items!.length - 1 ? 'page' : undefined" :class="ui.item({ active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })" raw>
|
||||||
<slot :name="item.slot || 'item'" :item="item" :index="index">
|
<slot :name="item.slot || 'item'" :item="item" :index="index">
|
||||||
<slot :name="item.slot ? `${item.slot}-leading`: 'item-leading'" :item="item" :active="index === items!.length - 1" :index="index">
|
<slot :name="item.slot ? `${item.slot}-leading`: 'item-leading'" :item="item" :active="index === items!.length - 1" :index="index">
|
||||||
<UAvatar v-if="item.avatar" size="2xs" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ active: index === items!.length - 1 })" />
|
<UAvatar v-if="item.avatar" size="2xs" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ active: index === items!.length - 1 })" />
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const button = tv({ extend: tv(theme), ...(appConfig.ui?.button || {}) })
|
|||||||
|
|
||||||
type ButtonVariants = VariantProps<typeof button>
|
type ButtonVariants = VariantProps<typeof button>
|
||||||
|
|
||||||
export interface ButtonProps extends UseComponentIconsProps, LinkProps {
|
export interface ButtonProps extends UseComponentIconsProps, Omit<LinkProps, 'custom'> {
|
||||||
label?: string
|
label?: string
|
||||||
color?: ButtonVariants['color']
|
color?: ButtonVariants['color']
|
||||||
variant?: ButtonVariants['variant']
|
variant?: ButtonVariants['variant']
|
||||||
@@ -34,14 +34,14 @@ export interface ButtonSlots {
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useForwardProps } from 'radix-vue'
|
import { useForwardProps } from 'radix-vue'
|
||||||
import { reactiveOmit } from '@vueuse/core'
|
|
||||||
import { useComponentIcons, useButtonGroup } from '#imports'
|
import { useComponentIcons, useButtonGroup } from '#imports'
|
||||||
import { UIcon, ULink } from '#components'
|
import { UIcon, ULink } from '#components'
|
||||||
|
import { pickLinkProps } from '#ui/utils/link'
|
||||||
|
|
||||||
const props = defineProps<ButtonProps>()
|
const props = defineProps<ButtonProps>()
|
||||||
const slots = defineSlots<ButtonSlots>()
|
const slots = defineSlots<ButtonSlots>()
|
||||||
|
|
||||||
const linkProps = useForwardProps(reactiveOmit(props, 'type', 'label', 'color', 'variant', 'size', 'icon', 'leading', 'leadingIcon', 'trailing', 'trailingIcon', 'loading', 'loadingIcon', 'square', 'block', 'disabled', 'truncate', 'class', 'ui'))
|
const linkProps = useForwardProps(pickLinkProps(props))
|
||||||
|
|
||||||
const { orientation, size: buttonSize } = useButtonGroup<ButtonProps>(props)
|
const { orientation, size: buttonSize } = useButtonGroup<ButtonProps>(props)
|
||||||
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
|
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const appConfig = _appConfig as AppConfig & { ui: { contextMenu: Partial<typeof
|
|||||||
|
|
||||||
const contextMenu = tv({ extend: tv(theme), ...(appConfig.ui?.contextMenu || {}) })
|
const contextMenu = tv({ extend: tv(theme), ...(appConfig.ui?.contextMenu || {}) })
|
||||||
|
|
||||||
export interface ContextMenuItem extends Omit<LinkProps, 'type'>, Pick<ContextMenuItemProps, 'disabled'> {
|
export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'custom'>, Pick<ContextMenuItemProps, 'disabled'> {
|
||||||
label?: string
|
label?: string
|
||||||
icon?: string
|
icon?: string
|
||||||
avatar?: AvatarProps
|
avatar?: AvatarProps
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ interface ContextMenuContentProps<T> extends Omit<RadixContextMenuContentProps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ContextMenuContentEmits extends RadixContextMenuContentEmits {}
|
interface ContextMenuContentEmits extends RadixContextMenuContentEmits {}
|
||||||
|
|
||||||
type ContextMenuContentSlots<T extends { slot?: string }> = ContextMenuSlots<T>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts" generic="T extends ContextMenuItem">
|
<script setup lang="ts" generic="T extends ContextMenuItem">
|
||||||
@@ -27,14 +25,15 @@ import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
|
|||||||
import { useAppConfig } from '#imports'
|
import { useAppConfig } from '#imports'
|
||||||
import { ULink } from '#components'
|
import { ULink } from '#components'
|
||||||
import { omit } from '#ui/utils'
|
import { omit } from '#ui/utils'
|
||||||
|
import { pickLinkProps } from '#ui/utils/link'
|
||||||
|
|
||||||
const props = defineProps<ContextMenuContentProps<T>>()
|
const props = defineProps<ContextMenuContentProps<T>>()
|
||||||
const emits = defineEmits<ContextMenuContentEmits>()
|
const emits = defineEmits<ContextMenuContentEmits>()
|
||||||
const slots = defineSlots<ContextMenuContentSlots<T>>()
|
const slots = defineSlots<ContextMenuSlots<T>>()
|
||||||
|
|
||||||
const appConfig = useAppConfig()
|
const appConfig = useAppConfig()
|
||||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'class', 'ui'), emits)
|
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'class', 'ui'), emits)
|
||||||
const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuContentSlots<T>[string]>
|
const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
|
||||||
|
|
||||||
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate()
|
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate()
|
||||||
|
|
||||||
@@ -102,7 +101,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
|||||||
</UContextMenuContent>
|
</UContextMenuContent>
|
||||||
</ContextMenu.Sub>
|
</ContextMenu.Sub>
|
||||||
<ContextMenu.Item v-else as-child :disabled="item.disabled" :text-value="item.label" @select="item.select">
|
<ContextMenu.Item v-else as-child :disabled="item.disabled" :text-value="item.label" @select="item.select">
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="omit((item as ContextMenuItem), ['label', 'icon', 'avatar', 'content', 'kbds', 'slot', 'open', 'defaultOpen', 'select', 'children', 'type'])" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom>
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ active })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ active })">
|
||||||
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const appConfig = _appConfig as AppConfig & { ui: { dropdownMenu: Partial<typeof
|
|||||||
|
|
||||||
const dropdownMenu = tv({ extend: tv(theme), ...(appConfig.ui?.dropdownMenu || {}) })
|
const dropdownMenu = tv({ extend: tv(theme), ...(appConfig.ui?.dropdownMenu || {}) })
|
||||||
|
|
||||||
export interface DropdownMenuItem extends Omit<LinkProps, 'type'>, Pick<DropdownMenuItemProps, 'disabled'> {
|
export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'custom'>, Pick<DropdownMenuItemProps, 'disabled'> {
|
||||||
label?: string
|
label?: string
|
||||||
icon?: string
|
icon?: string
|
||||||
avatar?: AvatarProps
|
avatar?: AvatarProps
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ interface DropdownMenuContentProps<T> extends Omit<RadixDropdownMenuContentProps
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DropdownMenuContentEmits extends RadixDropdownMenuContentEmits {}
|
interface DropdownMenuContentEmits extends RadixDropdownMenuContentEmits {}
|
||||||
|
|
||||||
type DropdownMenuContentSlots<T extends { slot?: string }> = DropdownMenuSlots<T>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts" generic="T extends DropdownMenuItem">
|
<script setup lang="ts" generic="T extends DropdownMenuItem">
|
||||||
@@ -27,14 +25,15 @@ import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
|
|||||||
import { useAppConfig } from '#imports'
|
import { useAppConfig } from '#imports'
|
||||||
import { ULink } from '#components'
|
import { ULink } from '#components'
|
||||||
import { omit } from '#ui/utils'
|
import { omit } from '#ui/utils'
|
||||||
|
import { pickLinkProps } from '#ui/utils/link'
|
||||||
|
|
||||||
const props = defineProps<DropdownMenuContentProps<T>>()
|
const props = defineProps<DropdownMenuContentProps<T>>()
|
||||||
const emits = defineEmits<DropdownMenuContentEmits>()
|
const emits = defineEmits<DropdownMenuContentEmits>()
|
||||||
const slots = defineSlots<DropdownMenuContentSlots<T>>()
|
const slots = defineSlots<DropdownMenuSlots<T>>()
|
||||||
|
|
||||||
const appConfig = useAppConfig()
|
const appConfig = useAppConfig()
|
||||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'class', 'ui'), emits)
|
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'class', 'ui'), emits)
|
||||||
const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuContentSlots<T>[string]>
|
const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuSlots<T>[string]>
|
||||||
|
|
||||||
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate()
|
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate()
|
||||||
|
|
||||||
@@ -105,7 +104,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
|||||||
</UDropdownMenuContent>
|
</UDropdownMenuContent>
|
||||||
</DropdownMenu.Sub>
|
</DropdownMenu.Sub>
|
||||||
<DropdownMenu.Item v-else as-child :disabled="item.disabled" :text-value="item.label" @select="item.select">
|
<DropdownMenu.Item v-else as-child :disabled="item.disabled" :text-value="item.label" @select="item.select">
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="omit((item as DropdownMenuItem), ['label', 'icon', 'avatar', 'content', 'kbds', 'slot', 'open', 'defaultOpen', 'select', 'children', 'type'])" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom>
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ active })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ active })">
|
||||||
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
||||||
</ULinkBase>
|
</ULinkBase>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const appConfig = _appConfig as AppConfig & { ui: { navigationMenu: Partial<type
|
|||||||
|
|
||||||
const navigationMenu = tv({ extend: tv(theme), ...(appConfig.ui?.navigationMenu || {}) })
|
const navigationMenu = tv({ extend: tv(theme), ...(appConfig.ui?.navigationMenu || {}) })
|
||||||
|
|
||||||
export interface NavigationMenuItem extends LinkProps, Pick<NavigationMenuItemProps, 'value'> {
|
export interface NavigationMenuItem extends Omit<LinkProps, 'custom'>, Pick<NavigationMenuItemProps, 'value'> {
|
||||||
label?: string
|
label?: string
|
||||||
icon?: string
|
icon?: string
|
||||||
avatar?: AvatarProps
|
avatar?: AvatarProps
|
||||||
@@ -44,7 +44,7 @@ import { computed } from 'vue'
|
|||||||
import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuLink, useForwardPropsEmits } from 'radix-vue'
|
import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationMenuLink, useForwardPropsEmits } from 'radix-vue'
|
||||||
import { reactivePick } from '@vueuse/core'
|
import { reactivePick } from '@vueuse/core'
|
||||||
import { UIcon, UAvatar, UBadge, ULink, ULinkBase } from '#components'
|
import { UIcon, UAvatar, UBadge, ULink, ULinkBase } from '#components'
|
||||||
import { omit } from '#ui/utils'
|
import { pickLinkProps } from '#ui/utils/link'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<NavigationMenuProps<T>>(), { orientation: 'horizontal' })
|
const props = withDefaults(defineProps<NavigationMenuProps<T>>(), { orientation: 'horizontal' })
|
||||||
const emits = defineEmits<NavigationMenuEmits>()
|
const emits = defineEmits<NavigationMenuEmits>()
|
||||||
@@ -62,7 +62,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
|
|||||||
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
|
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
|
||||||
<NavigationMenuList :class="ui.list()">
|
<NavigationMenuList :class="ui.list()">
|
||||||
<NavigationMenuItem v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :value="item.value || String(index)" :class="ui.itemWrapper()">
|
<NavigationMenuItem v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :value="item.value || String(index)" :class="ui.itemWrapper()">
|
||||||
<ULink v-slot="{ active, ...slotProps }" v-bind="omit(item, ['label', 'value', 'icon', 'avatar', 'badge', 'slot', 'select'])" custom>
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
||||||
<NavigationMenuLink as-child :active="active" @select="item.select">
|
<NavigationMenuLink as-child :active="active" @select="item.select">
|
||||||
<ULinkBase v-bind="slotProps" :class="ui.item({ active, disabled: !!item.disabled })">
|
<ULinkBase v-bind="slotProps" :class="ui.item({ active, disabled: !!item.disabled })">
|
||||||
<slot :name="item.slot || 'item'" :item="item" :index="index">
|
<slot :name="item.slot || 'item'" :item="item" :index="index">
|
||||||
|
|||||||
6
src/runtime/utils/link.ts
Normal file
6
src/runtime/utils/link.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { reactivePick } from '@vueuse/core'
|
||||||
|
import type { LinkProps } from '#ui/types'
|
||||||
|
|
||||||
|
export function pickLinkProps(link: LinkProps) {
|
||||||
|
return reactivePick(link, 'active', 'activeClass', 'ariaCurrentValue', 'as', 'disabled', 'exact', 'exactActiveClass', 'exactHash', 'exactQuery', 'external', 'href', 'inactiveClass', 'noPrefetch', 'noRel', 'prefetch', 'prefetchedClass', 'rel', 'replace', 'target', 'to', 'type')
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user