fix(Link): consistent behavior between nuxt, vue and inertia (#4134)

This commit is contained in:
Benjamin Canac
2025-05-13 14:45:18 +02:00
committed by GitHub
parent 894e8a61b6
commit 67da90a2f6
10 changed files with 211 additions and 140 deletions

View File

@@ -1,9 +1,8 @@
<script lang="ts">
import type { AppConfig } from '@nuxt/schema'
import theme from '#build/ui/button'
import type { LinkProps } from './Link.vue'
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
import type { AvatarProps } from '../types'
import type { LinkProps, AvatarProps } from '../types'
import type { ComponentConfig } from '../types/utils'
type Button = ComponentConfig<typeof theme, AppConfig, 'button'>
@@ -123,14 +122,13 @@ const ui = computed(() => tv({
v-slot="{ active, ...slotProps }"
:type="type"
:disabled="disabled || isLoading"
:class="ui.base({ class: [props.ui?.base, props.class] })"
v-bind="omit(linkProps, ['type', 'disabled', 'onClick'])"
custom
>
<ULinkBase
v-bind="slotProps"
:class="ui.base({
class: [props.class, props.ui?.base],
class: [props.ui?.base, props.class],
active,
...(active && activeVariant ? { variant: activeVariant } : {}),
...(active && activeColor ? { color: activeColor } : {})

View File

@@ -89,11 +89,12 @@ export interface LinkSlots {
<script setup lang="ts">
import { computed } from 'vue'
import { defu } from 'defu'
import { isEqual, diff } from 'ohash/utils'
import { isEqual } from 'ohash/utils'
import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core'
import { useRoute, useAppConfig } from '#imports'
import { tv } from '../utils/tv'
import { isPartiallyEqual } from '../utils/link'
import ULinkBase from './LinkBase.vue'
defineOptions({ inheritAttrs: false })
@@ -111,7 +112,7 @@ defineSlots<LinkSlots>()
const route = useRoute()
const appConfig = useAppConfig() as Link['AppConfig']
const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'raw', 'class'))
const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'to', 'href', 'raw', 'custom', 'class'))
const ui = computed(() => tv({
extend: tv(theme),
@@ -125,19 +126,7 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {})
}))
function isPartiallyEqual(item1: any, item2: any) {
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
if (q.type === 'added') {
filtered.add(q.key)
}
return filtered
}, new Set<string>())
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
return isEqual(item1Filtered, item2Filtered)
}
const to = computed(() => props.to ?? props.href)
function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
if (props.active !== undefined) {
@@ -177,7 +166,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any) {
</script>
<template>
<NuxtLink v-slot="{ href, navigate, route: linkRoute, rel, target, isExternal, isActive, isExactActive }" v-bind="nuxtLinkProps" custom>
<NuxtLink v-slot="{ href, navigate, route: linkRoute, rel, target, isExternal, isActive, isExactActive }" v-bind="nuxtLinkProps" :to="to" custom>
<template v-if="custom">
<slot
v-bind="{