Compare commits

..

10 Commits

Author SHA1 Message Date
HugoRCD
f14314387a up 2025-07-08 14:17:51 +02:00
HugoRCD
8a20b7118d up 2025-07-08 13:54:40 +02:00
HugoRCD
08da06a78c up 2025-07-08 12:03:20 +02:00
HugoRCD
20fc6bfaad Merge remote-tracking branch 'origin/v3' into refactor/toast-animations 2025-07-08 11:49:42 +02:00
HugoRCD
2afce33038 Merge remote-tracking branch 'origin/v3' into refactor/toast-animations 2025-07-08 11:47:43 +02:00
HugoRCD
8e82780df0 up 2025-07-08 11:18:00 +02:00
HugoRCD
f81687724e up 2025-07-08 10:52:07 +02:00
HugoRCD
dbf19913a2 Merge remote-tracking branch 'origin/v3' into refactor/toast-animations 2025-07-08 10:46:35 +02:00
HugoRCD
faae76e796 up 2025-07-07 15:10:00 +02:00
HugoRCD
6ea33aba68 refactor(Toaster): improve animations 2025-07-07 14:58:12 +02:00
109 changed files with 1109 additions and 1451 deletions

View File

@@ -53,7 +53,7 @@ provide('navigation', mappedNavigation)
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
<template v-if="!route.path.startsWith('/examples')">
<Banner />
<!-- <Banner /> -->
<Header :links="links" />
</template>

View File

@@ -1,19 +1,15 @@
<template>
<UBanner
id="nuxtlabs-join-vercel"
title="NuxtLabs is joining Vercel"
icon="i-simple-icons-vercel"
to="https://nuxtlabs.com/?utm_source=nuxt-ui&utm_medium=banner&utm_campaign=nuxtlabs-vercel"
target="_blank"
id="ui3-launch"
title="Nuxt UI v3 is officially released!"
icon="i-lucide-rocket"
:actions="[
{
label: 'Discover Nuxt UI Pro',
to: '/pro/pricing',
trailingIcon: 'i-lucide-arrow-right'
}
]"
close
:actions="[{
label: 'Read the announcement',
color: 'neutral',
variant: 'outline',
trailingIcon: 'i-lucide-arrow-right',
to: 'https://nuxtlabs.com/?utm_source=nuxt-ui&utm_medium=banner&utm_campaign=nuxtlabs-vercel',
target: '_blank',
class: 'ring-0'
}]"
/>
</template>

View File

@@ -14,8 +14,8 @@ const items = [
v-slot="{ item }"
orientation="vertical"
:items="items"
:ui="{ container: 'h-[336px]' }"
class="w-full max-w-xs mx-auto"
:ui="{ container: 'h-[336px]' }"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>

View File

@@ -1,31 +0,0 @@
<script setup lang="ts">
const { data: users } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
email: user.email,
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
},
lazy: true
})
</script>
<template>
<UInputMenu
:items="users"
icon="i-lucide-user"
placeholder="Select user"
:ui="{ content: 'min-w-fit' }"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</UInputMenu>
</template>

View File

@@ -35,7 +35,6 @@ const items = ref([
}
}
] satisfies InputMenuItem[])
const value = ref(items.value[0])
</script>

View File

@@ -40,9 +40,9 @@ const text = computed(() => {
placeholder="Password"
:color="color"
:type="show ? 'text' : 'password'"
:ui="{ trailing: 'pe-1' }"
:aria-invalid="score < 4"
aria-describedby="password-strength"
:ui="{ trailing: 'pe-1' }"
class="w-full"
>
<template #trailing>

View File

@@ -62,13 +62,13 @@ const items = [
<template>
<UNavigationMenu
:items="items"
class="w-full justify-center"
:ui="{
viewport: 'sm:w-(--reka-navigation-menu-viewport-width)',
content: 'sm:w-auto',
childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2'
}"
class="w-full justify-center"
>
<template #docs-content="{ item }">
<ul class="grid gap-2 p-4 lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">

View File

@@ -1,32 +0,0 @@
<script setup lang="ts">
const { data: users } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
value: String(user.id),
email: user.email,
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
},
lazy: true
})
</script>
<template>
<USelectMenu
:items="users"
icon="i-lucide-user"
placeholder="Select user"
:ui="{ content: 'min-w-fit' }"
class="w-48"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</USelectMenu>
</template>

View File

@@ -35,7 +35,6 @@ const items = ref([
}
}
] satisfies SelectMenuItem[])
const value = ref(items.value[0])
</script>

View File

@@ -24,7 +24,6 @@ const items = ref([
}
}
] satisfies SelectMenuItem[])
const value = ref(items.value[0])
</script>

View File

@@ -23,7 +23,6 @@ const items = ref([
icon: 'i-lucide-circle-check'
}
] satisfies SelectMenuItem[])
const value = ref(items.value[0])
</script>

View File

@@ -1,35 +0,0 @@
<script setup lang="ts">
const value = ref<string>()
const { data: users } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users-email',
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({
label: user.name,
email: user.email,
value: String(user.id),
avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` }
}))
},
lazy: true
})
</script>
<template>
<USelect
v-model="value"
:items="users"
placeholder="Select user"
value-key="value"
:ui="{ content: 'min-w-fit' }"
class="w-48"
>
<template #item-label="{ item }">
{{ item.label }}
<span class="text-muted">
{{ item.email }}
</span>
</template>
</USelect>
</template>

View File

@@ -24,8 +24,8 @@ function getUserAvatar(value: string) {
:loading="status === 'pending'"
icon="i-lucide-user"
placeholder="Select user"
value-key="value"
class="w-48"
value-key="value"
>
<template #leading="{ modelValue, ui }">
<UAvatar

View File

@@ -35,7 +35,6 @@ const items = ref([
}
}
] satisfies SelectItem[])
const value = ref(items.value[0]?.value)
const avatar = computed(() => items.value.find(item => item.value === value.value)?.avatar)

View File

@@ -23,7 +23,6 @@ const items = ref([
icon: 'i-lucide-circle-check'
}
] satisfies SelectItem[])
const value = ref(items.value[0]?.value)
const icon = computed(() => items.value.find(item => item.value === value.value)?.icon)

View File

@@ -26,7 +26,7 @@ const state = reactive({
</script>
<template>
<UTabs :items="items" variant="link" :ui="{ trigger: 'grow' }" class="gap-4 w-full">
<UTabs :items="items" variant="link" class="gap-4 w-full" :ui="{ trigger: 'grow' }">
<template #account="{ item }">
<p class="text-muted mb-4">
{{ item.description }}

View File

@@ -27,8 +27,8 @@ const items: TimelineItem[] = [{
<template>
<UTimeline
:items="items"
:default-value="2"
:ui="{ item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] even:text-right' }"
:default-value="2"
class="translate-x-[calc(50%-1rem)]"
/>
</template>

View File

@@ -42,11 +42,11 @@ const items = [{
<UTimeline
:items="items"
size="xs"
class="w-96"
:ui="{
date: 'float-end ms-1',
description: 'px-3 py-2 ring ring-default mt-2 rounded-md text-default'
}"
class="w-96"
>
<template #title="{ item }">
<span>{{ item.username }}</span>

View File

@@ -7,12 +7,12 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.duration"
size="sm"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
class="inline-flex ring ring-accented rounded-sm"
>
<UInput
v-model="appConfig.toaster.duration"

View File

@@ -7,12 +7,12 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.expand"
size="sm"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
class="inline-flex ring ring-accented rounded-sm"
>
<USelectMenu
v-model="appConfig.toaster.expand"

View File

@@ -10,12 +10,12 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.position"
size="sm"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
class="inline-flex ring ring-accented rounded-sm"
>
<USelectMenu
v-model="appConfig.toaster.position"

View File

@@ -59,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp>
<NuxtLoadingIndicator color="#FFF" />
<Banner />
<!-- <Banner /> -->
<Header :links="links" />

View File

@@ -5,17 +5,6 @@ pricing:
title: Upgrade to Nuxt UI [Pro]{class="text-primary"}.
description: On top of 40+ open source components from Nuxt UI, Pro gives you access to 50+ premium Vue components to create beautiful & responsive Nuxt applications in minutes. It includes all primitives to build landing pages, documentations, blogs, dashboards or entire SaaS products.
freePlan:
description: "**NuxtLabs is joining Vercel** :tada: As part of this transition, Nuxt UI is becoming even more accessible.<br><br> **In September, we're launching Nuxt UI v4**: a free, open-source library that unifies Nuxt UI and Nuxt UI Pro, offering 100+ components and a complete free Figma Kit for everyone."
orientation: horizontal
button:
label: Read the announcement
to: 'https://nuxtlabs.com/?utm_source=nuxt-ui&utm_medium=banner&utm_campaign=nuxtlabs-vercel'
target: _blank
color: 'neutral'
trailingIcon: 'i-lucide-arrow-right'
ui:
trailingIcon: 'ms-0'
devPlan:
title: Free in development
description: Try Nuxt UI Pro for free in development, no credit card required. Upgrade when ready to deploy.
orientation: horizontal
@@ -24,9 +13,6 @@ pricing:
to: '/getting-started/installation/pro/nuxt'
color: 'neutral'
variant: 'subtle'
trailingIcon: 'i-lucide-arrow-right'
ui:
trailingIcon: 'ms-0'
figma:
title: Figma Kit Pro
description: Get all Nuxt UI Pro components in a Figma kit to design your next application before coding. Everything you need, from wire-framing to high-fidelity web integration.

View File

@@ -34,19 +34,10 @@ useSeoMeta({
<div class="flex flex-col bg-default gap-8 lg:gap-0">
<UPricingPlan
v-bind="page.pricing.freePlan"
class="lg:rounded-none ring-primary/15 ring-inset -mb-px bg-primary/5 z-[1]"
:ui="{ description: 'mt-0 text-primary' }"
>
<template #description>
<MDC :value="page.pricing.freePlan.description" unwrap="p" />
</template>
</UPricingPlan>
<UPricingPlan
v-bind="page.pricing.devPlan"
class="lg:rounded-none ring-inset -mb-px"
variant="naked"
class="lg:rounded-none border-x border-default border-t border-b lg:border-b-0"
/>
<UPricingPlans compact class="-space-x-px">
<UPricingPlans compact>
<UPricingPlan
v-for="(plan, index) in page.pricing.plans"
:key="index"
@@ -56,17 +47,18 @@ useSeoMeta({
:discount="plan.discount"
:billing-period="plan.billing_period"
:billing-cycle="plan.billing_cycle"
:variant="plan.highlight ? 'subtle' : 'outline'"
class="lg:rounded-none ring-inset -mb-px"
:variant="plan.highlight ? 'soft' : 'outline'"
:class="['lg:rounded-none', { 'border-2 lg:border lg:border-x-0 border-primary lg:border-default': plan.highlight }]"
:features="plan.features"
:button="plan.button"
/>
</UPricingPlans>
<UPricingPlan
v-bind="page.pricing.figma"
variant="naked"
:billing-period="page.pricing.figma.billing_period"
:billing-cycle="page.pricing.figma.billing_cycle"
class="lg:rounded-none ring-inset -mb-px"
class="lg:rounded-none border lg:border-y-0 border-default"
>
<template #features>
<li v-for="(feature, index) in page.pricing.figma.features" :key="index" class="flex items-center gap-2 min-w-0">

View File

@@ -225,27 +225,6 @@ export default defineNuxtConfig({
This option adds the `transition-colors` class on components with hover or active states.
::
### `theme.defaultVariants` :badge{label="Soon" class="align-text-top"}
Use the `theme.defaultVariants` option to override the default `color` and `size` variants for components.
- Default: `{ color: 'primary', size: 'md' }`{lang="ts-type"}
```ts [nuxt.config.ts]
export default defineNuxtConfig({
modules: ['@nuxt/ui'],
css: ['~/assets/css/main.css'],
ui: {
theme: {
defaultVariants: {
color: 'neutral',
size: 'sm'
}
}
}
})
```
## Continuous Releases
Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.

View File

@@ -333,32 +333,6 @@ export default defineConfig({
This option adds the `transition-colors` class on components with hover or active states.
::
### `theme.defaultVariants` :badge{label="Soon" class="align-text-top"}
Use the `theme.defaultVariants` option to override the default `color` and `size` variants for components.
- Default: `{ color: 'primary', size: 'md' }`{lang="ts-type"}
```ts [vite.config.ts]
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
theme: {
defaultVariants: {
color: 'neutral',
size: 'sm'
}
}
})
]
})
```
### `inertia`
Use the `inertia` option to enable compatibility with [Inertia.js](https://inertiajs.com/).

View File

@@ -757,33 +757,6 @@ name: 'input-menu-filter-fields-example'
---
::
### With full content width
You can expand the content to the full width of its items by using the `ui.content` key.
::component-example
---
name: 'input-menu-content-width-example'
collapse: true
---
::
::tip
You can also change the content width globally in your `app.config.ts`:
```
export default defineAppConfig({
ui: {
inputMenu: {
slots: {
content: 'min-w-fit'
}
}
}
})
```
::
### As a CountryPicker
This example demonstrates using the InputMenu as a country picker with lazy loading - countries are only fetched when the menu is opened.

View File

@@ -790,33 +790,6 @@ name: 'select-menu-filter-fields-example'
---
::
### With full content width
You can expand the content to the full width of its items by using the `ui.content` key.
::component-example
---
name: 'select-menu-content-width-example'
collapse: true
---
::
::tip
You can also change the content width globally in your `app.config.ts`:
```
export default defineAppConfig({
ui: {
selectMenu: {
slots: {
content: 'min-w-fit'
}
}
}
})
```
::
### As a CountryPicker
This example demonstrates using the SelectMenu as a country picker with lazy loading - countries are only fetched when the menu is opened.
@@ -828,8 +801,6 @@ name: 'select-menu-countries-example'
---
::
## API
### Props

View File

@@ -695,33 +695,6 @@ collapse: true
---
::
### With full content width
You can expand the content to the full width of its items by using the `ui.content` key.
::component-example
---
name: 'select-content-width-example'
collapse: true
---
::
::tip
You can also change the content width globally in your `app.config.ts`:
```
export default defineAppConfig({
ui: {
select: {
slots: {
content: 'min-w-fit'
}
}
}
})
```
::
## API
### Props

View File

@@ -17,7 +17,7 @@
"@nuxt/content": "^3.6.3",
"@nuxt/image": "^1.10.0",
"@nuxt/ui": "workspace:*",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@17684e4",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@22fdc5e",
"@nuxthub/core": "^0.9.0",
"@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^22.0.0",
@@ -30,7 +30,7 @@
"joi": "^17.13.3",
"maska": "^3.2.0",
"motion-v": "^1.5.0",
"nuxt": "4.0.0-rc.0",
"nuxt": "^3.17.6",
"nuxt-component-meta": "^0.12.1",
"nuxt-llms": "^0.1.3",
"nuxt-og-image": "^5.1.9",

View File

@@ -116,8 +116,8 @@
"@internationalized/number": "^3.6.3",
"@nuxt/fonts": "^0.11.4",
"@nuxt/icon": "^1.15.0",
"@nuxt/kit": "4.0.0-rc.0",
"@nuxt/schema": "4.0.0-rc.0",
"@nuxt/kit": "^3.17.6",
"@nuxt/schema": "^3.17.6",
"@nuxtjs/color-mode": "^3.5.2",
"@standard-schema/spec": "^1.0.0",
"@tailwindcss/postcss": "^4.1.11",
@@ -163,7 +163,7 @@
"embla-carousel": "^8.6.0",
"eslint": "^9.30.1",
"happy-dom": "^18.0.1",
"nuxt": "4.0.0-rc.0",
"nuxt": "^3.17.6",
"release-it": "^19.0.3",
"vitest": "^3.2.4",
"vitest-environment-nuxt": "^1.0.1",

View File

@@ -16,9 +16,9 @@
"zod": "^3.25.75"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.0",
"@vitejs/plugin-vue": "^5.2.4",
"typescript": "^5.8.3",
"vite": "^7.0.4",
"vite": "^6.3.5",
"vue-tsc": "^3.0.1"
}
}

View File

@@ -14,7 +14,7 @@
"@internationalized/date": "^3.8.2",
"@nuxt/ui": "workspace:*",
"@nuxthub/core": "^0.9.0",
"nuxt": "4.0.0-rc.0",
"nuxt": "^3.17.6",
"zod": "^3.25.75"
},
"devDependencies": {

1484
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,9 +6,6 @@ import { name, version } from '../package.json'
export type * from './runtime/types'
type Color = 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error' | (string & {})
type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | (string & {})
export interface ModuleOptions {
/**
* Prefix for components
@@ -41,7 +38,7 @@ export interface ModuleOptions {
* @defaultValue `['primary', 'secondary', 'success', 'info', 'warning', 'error']`
* @link https://ui.nuxt.com/getting-started/installation/nuxt#themecolors
*/
colors?: Color[]
colors?: string[]
/**
* Enable or disable transitions on components
@@ -49,20 +46,6 @@ export interface ModuleOptions {
* @link https://ui.nuxt.com/getting-started/installation/nuxt#themetransitions
*/
transitions?: boolean
defaultVariants?: {
/**
* The default color variant to use for components
* @defaultValue `'primary'`
*/
color?: Color
/**
* The default size variant to use for components
* @defaultValue `'md'`
*/
size?: Size
}
}
}
@@ -102,7 +85,7 @@ export default defineNuxtModule<ModuleOptions>({
async function registerModule(name: string, key: string, options: Record<string, any>) {
if (!hasNuxtModule(name)) {
await installModule(name, defu((nuxt.options as any)[key], options))
await installModule(name, options)
} else {
(nuxt.options as any)[key] = defu((nuxt.options as any)[key], options)
}

View File

@@ -256,7 +256,6 @@ const scrollSnaps = ref<number[]>([])
function onInit(api: EmblaCarouselType) {
scrollSnaps.value = api?.scrollSnapList() || []
}
function onSelect(api: EmblaCarouselType) {
canScrollNext.value = api?.canScrollNext() || false
canScrollPrev.value = api?.canScrollPrev() || false
@@ -301,7 +300,8 @@ defineExpose({
<div
v-for="(item, index) in items"
:key="index"
v-bind="dots ? { role: 'tabpanel' } : { 'role': 'group', 'aria-roledescription': 'slide' }"
role="group"
aria-roledescription="slide"
:class="ui.item({ class: [props.ui?.item, isCarouselItem(item) && item.ui?.item, isCarouselItem(item) && item.class] })"
>
<slot :item="item" :index="index" />
@@ -333,15 +333,13 @@ defineExpose({
/>
</div>
<div v-if="dots" role="tablist" :aria-label="t('carousel.dots')" :class="ui.dots({ class: props.ui?.dots })">
<div v-if="dots" :class="ui.dots({ class: props.ui?.dots })">
<template v-for="(_, index) in scrollSnaps" :key="index">
<button
type="button"
role="tab"
:aria-label="t('carousel.goto', { slide: index + 1 })"
:aria-selected="selectedIndex === index"
:class="ui.dot({ class: props.ui?.dot, active: selectedIndex === index })"
:data-state="selectedIndex === index ? 'active' : undefined"
:aria-current="selectedIndex === index ? true : undefined"
@click="scrollTo(index)"
/>
</template>

View File

@@ -18,7 +18,7 @@ export interface FormFieldProps {
label?: string
description?: string
help?: string
error?: boolean | string
error?: string | boolean
hint?: string
/**
* @defaultValue 'md'
@@ -41,8 +41,8 @@ export interface FormFieldSlots {
hint(props: { hint?: string }): any
description(props: { description?: string }): any
help(props: { help?: string }): any
error(props: { error?: boolean | string }): any
default(props: { error?: boolean | string }): any
error(props: { error?: string | boolean }): any
default(props: { error?: string | boolean }): any
}
</script>

View File

@@ -177,8 +177,6 @@ import UBadge from './Badge.vue'
import UPopover from './Popover.vue'
import UTooltip from './Tooltip.vue'
defineOptions({ inheritAttrs: false })
const props = withDefaults(defineProps<NavigationMenuProps<T>>(), {
orientation: 'horizontal',
contentOrientation: 'horizontal',
@@ -394,7 +392,7 @@ function getAccordionDefaultValue(list: NavigationMenuItem[], level = 0) {
</component>
</DefineItemTemplate>
<NavigationMenuRoot v-bind="{ ...rootProps, ...$attrs }" :data-collapsed="collapsed" :class="ui.root({ class: [props.ui?.root, props.class] })">
<NavigationMenuRoot v-bind="rootProps" :data-collapsed="collapsed" :class="ui.root({ class: [props.ui?.root, props.class] })">
<slot name="list-leading" />
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">

View File

@@ -120,6 +120,8 @@ function getOffset(index: number) {
:close="(toast.close as boolean)"
:data-expanded="expanded"
:data-front="!expanded && index === toasts.length - 1"
:data-second="!expanded && index === toasts.length - 2"
:data-third="!expanded && index === toasts.length - 3"
:style="{
'--index': (index - toasts.length) + toasts.length,
'--before': toasts.length - 1 - index,

View File

@@ -107,8 +107,6 @@ import { get } from '../utils'
import { tv } from '../utils/tv'
import UIcon from './Icon.vue'
defineOptions({ inheritAttrs: false })
const props = withDefaults(defineProps<TreeProps<T, VK, M>>(), {
labelKey: 'label' as never,
valueKey: 'value' as never
@@ -163,7 +161,7 @@ const defaultExpanded = computed(() =>
@toggle="item.onToggle"
@select="item.onSelect"
>
<button type="button" :disabled="item.disabled || disabled" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], selected: isSelected, disabled: item.disabled || disabled })">
<button :disabled="item.disabled || disabled" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], 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.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
@@ -201,7 +199,7 @@ const defaultExpanded = computed(() =>
</DefineTreeTemplate>
<TreeRoot
v-bind="{ ...(rootProps as unknown as TreeRootProps<NestedItem<T>>), ...$attrs }"
v-bind="(rootProps as unknown as TreeRootProps<NestedItem<T>>)"
:class="ui.root({ class: [props.ui?.root, props.class] })"
:get-key="getItemValue"
:default-expanded="defaultExpanded"

View File

@@ -87,11 +87,11 @@ function _useOverlay() {
const open = <T extends Component>(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T> => {
const overlay = getOverlay(id)
// If props are provided, merge them with the original props, otherwise use the original props
// If props are provided, update the overlay's props
if (props) {
overlay.props = { ...overlay.originalProps, ...props }
patch(overlay.id, props)
} else {
overlay.props = { ...overlay.originalProps }
patch(overlay.id, overlay.originalProps)
}
overlay.isOpen = true

View File

@@ -1,10 +1,11 @@
import { ref, onScopeDispose } from 'vue'
import type { Ref, Plugin as VuePlugin } from 'vue'
import { createHooks } from 'hookable'
import { usePage } from '@inertiajs/vue3'
import { useColorMode as useColorModeVueUse } from '@vueuse/core'
import appConfig from '#build/app.config'
import type { NuxtApp } from '#app'
import { useColorMode as useColorModeVueUse } from '@vueuse/core'
import { usePage } from '@inertiajs/vue3'
export { useHead } from '@unhead/vue'
@@ -15,7 +16,6 @@ export { useLocale } from '../composables/useLocale'
export const useRoute = () => {
const page = usePage()
return {
fullPath: page.url
}
@@ -25,10 +25,6 @@ export const useRouter = () => {
}
export const clearError = () => {
}
export const useColorMode = () => {
if (!appConfig.colorMode) {
return {

View File

@@ -40,8 +40,7 @@ export default defineLocale<Messages>({
carousel: {
prev: 'السابق',
next: 'التالي',
dots: 'اختر الشريحة المراد عرضها',
goto: 'الذهاب إلى شريحة {slide}'
goto: 'الذهاب إلي شريحة {slide}'
},
modal: {
close: 'إغلاق'

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Əvvəlki',
next: 'Növbəti',
dots: 'Göstərmək üçün slayd seçin',
goto: 'Slayd {slide} keç'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Назад',
next: 'Напред',
dots: 'Изберете слайд за показване',
goto: 'Отидете на слайд {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'পূর্ববর্তী',
next: 'পরবর্তী',
dots: 'প্রদর্শনের জন্য স্লাইড নির্বাচন করুন',
goto: 'স্লাইড {slide} এ যান'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Anterior',
next: 'Següent',
dots: 'Tria la diapositiva a mostrar',
goto: 'Anar a la diapositiva {slide}'
},
modal: {

View File

@@ -38,9 +38,8 @@ export default defineLocale<Messages>({
close: 'داخستن'
},
carousel: {
prev: 'پێشووی',
prev: 'پێشوو',
next: 'داهاتوو',
dots: 'سلایدێک هەڵبژێرە بۆ پیشاندان',
goto: 'بڕۆ بۆ سلایدی {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Předchozí',
next: 'Další',
dots: 'Vyberte snímek k zobrazení',
goto: 'Přejít na {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Forrige',
next: 'Næste',
dots: 'Vælg dias til visning',
goto: 'Gå til slide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Zurück',
next: 'Weiter',
dots: 'Folie zur Anzeige auswählen',
goto: 'Gehe zu {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Προηγούμενο',
next: 'Επόμενο',
dots: 'Επιλέξτε διαφάνεια για εμφάνιση',
goto: 'Μετάβαση στη διαφάνεια {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Prev',
next: 'Next',
dots: 'Choose slide to display',
goto: 'Go to slide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Anterior',
next: 'Siguiente',
dots: 'Elegir diapositiva a mostrar',
goto: 'Ir a la diapositiva {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Eel',
next: 'Järg',
dots: 'Valige kuvatav slaid',
goto: 'Mine slaidile {slide}'
},
modal: {

View File

@@ -40,7 +40,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'قبلی',
next: 'بعدی',
dots: 'اسلاید مورد نظر برای نمایش را انتخاب کنید',
goto: 'رفتن به اسلاید {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Edellinen',
next: 'Seuraava',
dots: 'Valitse näytettävä dia',
goto: 'Siirry sivulle {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Précédent',
next: 'Suivant',
dots: 'Choisir la diapositive à afficher',
goto: 'Aller à {slide}'
},
modal: {

View File

@@ -38,7 +38,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'הקודם',
next: 'הבא',
dots: 'בחר שקופית להצגה',
goto: 'מעבר ל {slide}'
},
modal: {

View File

@@ -39,8 +39,7 @@ export default defineLocale<Messages>({
carousel: {
prev: 'पिछला',
next: 'अगला',
dots: 'प्रदर्शित करने के लिए स्लाइड चुनें',
goto: 'स्लाइड {slide} पर जाएं'
goto: 'स्लाइड {slide} पर जाएँ'
},
modal: {
close: 'बंद करें'

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Előző',
next: 'Következő',
dots: 'Válassza ki a megjelenítendő diát',
goto: 'Ugrás ide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Հետ',
next: 'Առաջ',
dots: 'Ընտրեք ցուցադրելու սլայդը',
goto: 'Անցնել {slide}-ին'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Sebelumnya',
next: 'Berikutnya',
dots: 'Pilih slide untuk ditampilkan',
goto: 'Pergi ke slide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Precedente',
next: 'Successiva',
dots: 'Scegli diapositiva da visualizzare',
goto: 'Vai alla slide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: '前へ',
next: '次へ',
dots: '表示するスライドを選択',
goto: 'スライド {slide} に移動'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Алдыңғы',
next: 'Келесі',
dots: 'Көрсету үшін слайдты таңдаңыз',
goto: '{slide} слайдқа өту'
},
modal: {

View File

@@ -39,8 +39,7 @@ export default defineLocale<Messages>({
carousel: {
prev: 'មុន',
next: 'បន្ទាប់',
dots: 'ជ្រើសរើស​ស្លាយ​ដើម្បី​បង្ហាញ',
goto: 'ឡើងទៅស្លាយ {slide}'
goto: 'លោតទៅកាន់ស្លាយ {slide}'
},
modal: {
close: 'បិទ'

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: '이전',
next: '다음',
dots: '표시할 슬라이드 선택',
goto: '{slide} 페이지로 이동'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Алдыңкы',
next: 'Кийинки',
dots: 'Көрсөтүү үчүн слайдды тандаңыз',
goto: '{slide} слайдга өтүү'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Präz.',
next: 'Näch.',
dots: 'Wielt Dia fir ze weisen',
goto: 'Gitt op d\'Slide {Slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Atgal',
next: 'Pirmyn',
dots: 'Pasirinkite skaidrę rodymui',
goto: 'Eiti į skaidrę {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Өмнөх',
next: 'Дараах',
dots: 'Харуулах слайдыг сонгоно уу',
goto: '{slide}-р хуудсанд шилжих'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Sebelum',
next: 'Seterusnya',
dots: 'Pilih slaid untuk dipaparkan',
goto: 'Pergi ke slaid {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Forrige',
next: 'Neste',
dots: 'Velg lysbilde som skal vises',
goto: 'Gå til lysbilde {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Vorige',
next: 'Volgende',
dots: 'Kies dia om weer te geven',
goto: 'Ga naar dia {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Poprzedni',
next: 'Następny',
dots: 'Wybierz slajd do wyświetlenia',
goto: 'Idź do {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Anterior',
next: 'Próximo',
dots: 'Escolher slide para exibir',
goto: 'Ir ao diapositivo {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Anterior',
next: 'Próximo',
dots: 'Escolher slide para exibir',
goto: 'Ir para a slide {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Anterior',
next: 'Următor',
dots: 'Alegeți diapozitivul de afișat',
goto: 'Mergi la diapozitivul {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Назад',
next: 'Далее',
dots: 'Выберите слайд для отображения',
goto: 'Перейти к {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Predchádzajúci',
next: 'Nasledujúci',
dots: 'Vyberte snímku na zobrazenie',
goto: 'Prejsť na {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Nazaj',
next: 'Naprej',
dots: 'Izberite diapozitiv za prikaz',
goto: 'Pojdi na {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Föregående',
next: 'Nästa',
dots: 'Välj bild att visa',
goto: 'Gå till {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'ย้อนกลับ',
next: 'ถัดไป',
dots: 'เลือกสไลด์ที่จะแสดง',
goto: 'ไปที่ {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Қаблӣ',
next: 'Баъдӣ',
dots: 'Слайдро барои намоиш интихоб кунед',
goto: 'Ба слайди {slide} гузаред'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Önceki',
next: 'Sonraki',
dots: 'Görüntülenecek slaydı seçin',
goto: '{slide}. slayda git'
},
modal: {

View File

@@ -40,7 +40,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'ئالدىنقى بەت',
next: 'كېيىنكى بەت',
dots: 'كۆرسىتىدىغان سلايدنى تاللاڭ',
goto: '{slide}-بەتكە ئاتلاش'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Назад',
next: 'Далі',
dots: 'Виберіть слайд для відображення',
goto: 'Перейти до {slide}'
},
modal: {

View File

@@ -40,7 +40,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'پچھلا',
next: 'اگلا',
dots: 'دکھانے کے لیے سلائیڈ منتخب کریں',
goto: 'سلائیڈ {slide} پر جائیں'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Ortga',
next: 'Oldinga',
dots: 'Koʻrsatish uchun slaydni tanlang',
goto: '{slide}-slaydga otish'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: 'Trước',
next: 'Sau',
dots: 'Chọn slide để hiển thị',
goto: 'Đi tới ô {slide}'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: '上一页',
next: '下一页',
dots: '选择要显示的幻灯片',
goto: '跳转到第 {slide} 页'
},
modal: {

View File

@@ -39,7 +39,6 @@ export default defineLocale<Messages>({
carousel: {
prev: '上一頁',
next: '下一頁',
dots: '選擇要顯示的投影片',
goto: '跳轉到第 {slide} 頁'
},
modal: {

View File

@@ -33,7 +33,6 @@ export type Messages = {
carousel: {
prev: string
next: string
dots: string
goto: string
}
modal: {

View File

@@ -1,9 +1,10 @@
import { ref, onScopeDispose } from 'vue'
import type { Ref, Plugin as VuePlugin } from 'vue'
import { createHooks } from 'hookable'
import { useColorMode as useColorModeVueUse } from '@vueuse/core'
import appConfig from '#build/app.config'
import type { NuxtApp } from '#app'
import { useColorMode as useColorModeVueUse } from '@vueuse/core'
export { useHead } from '@unhead/vue'
export { useRoute, useRouter } from 'vue-router'
@@ -13,10 +14,6 @@ export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale'
export const clearError = () => {
}
export const useColorMode = () => {
if (!appConfig.colorMode) {
return {

View File

@@ -26,14 +26,6 @@ export function getTemplates(options: ModuleOptions, uiConfig: Record<string, an
const template = (theme as any)[component]
const result = typeof template === 'function' ? template(options) : template
// Override default variants from nuxt.config.ts
if (result?.defaultVariants?.color && options.theme?.defaultVariants?.color) {
result.defaultVariants.color = options.theme.defaultVariants.color
}
if (result?.defaultVariants?.size && options.theme?.defaultVariants?.size) {
result.defaultVariants.size = options.theme.defaultVariants.size
}
const variants = Object.entries(result.variants || {})
.filter(([_, values]) => {
const keys = Object.keys(values as Record<string, unknown>)
@@ -64,10 +56,7 @@ export function getTemplates(options: ModuleOptions, uiConfig: Record<string, an
return [
`import template from ${JSON.stringify(templatePath)}`,
...generateVariantDeclarations(variants),
`const options = ${JSON.stringify(options, null, 2)}`,
`const result = typeof template === 'function' ? (template as Function)(options) : template`,
`if (result?.defaultVariants?.color && options.theme?.defaultVariants?.color) result.defaultVariants.color = options.theme.defaultVariants.color`,
`if (result?.defaultVariants?.size && options.theme?.defaultVariants?.size) result.defaultVariants.size = options.theme.defaultVariants.size`,
`const result = typeof template === 'function' ? (template as Function)(${JSON.stringify(options, null, 2)}) : template`,
`const theme = ${json}`,
`export default result as typeof theme`
].join('\n\n')

View File

@@ -1,7 +1,7 @@
export default {
slots: {
viewport: 'fixed flex flex-col w-[calc(100%-2rem)] sm:w-96 z-[100] data-[expanded=true]:h-(--height) focus:outline-none',
base: 'pointer-events-auto absolute inset-x-0 z-(--index) transform-(--transform) data-[expanded=false]:data-[front=false]:h-(--front-height) data-[expanded=false]:data-[front=false]:*:opacity-0 data-[front=false]:*:transition-opacity data-[front=false]:*:duration-100 data-[state=closed]:animate-[toast-closed_200ms_ease-in-out] data-[state=closed]:data-[expanded=false]:data-[front=false]:animate-[toast-collapsed-closed_200ms_ease-in-out] data-[swipe=move]:transition-none transition-[transform,translate,height] duration-200 ease-out'
viewport: 'fixed flex flex-col w-[calc(100%-2rem)] sm:w-96 z-[100] data-[expanded=true]:h-(--height) focus:outline-none transition-all duration-500 ease-in-out',
base: 'pointer-events-auto absolute inset-x-0 z-(--index) transform-(--transform) data-[expanded=false]:data-[front=false]:max-h-[calc(var(--front-height)+0.5rem)] data-[expanded=false]:data-[front=false]:min-h-[3rem] data-[expanded=false]:data-[front=false]:overflow-hidden data-[expanded=false]:data-[front=false]:data-[second=false]:data-[third=false]:opacity-0 data-[expanded=false]:data-[second=true]:opacity-60 data-[expanded=false]:data-[third=true]:opacity-30 data-[expanded=false]:data-[front=false]:*:opacity-0 data-[front=false]:*:transition-opacity data-[front=false]:*:duration-200 transition-[transform,translate,max-height,opacity] duration-200 ease-out data-[state=closed]:animate-[toast-closed_200ms_ease-out] data-[state=closed]:data-[expanded=false]:data-[front=false]:animate-[toast-collapsed-closed_200ms_ease-out] data-[swipe=move]:transition-none'
},
variants: {
position: {
@@ -35,13 +35,13 @@ export default {
position: ['top-left', 'top-center', 'top-right'],
class: {
viewport: 'top-4',
base: 'top-0 data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out]'
base: 'top-0 data-[state=open]:animate-[slide-in-from-top_280ms_cubic-bezier(0.4,0,0.6,1)]'
}
}, {
position: ['bottom-left', 'bottom-center', 'bottom-right'],
class: {
viewport: 'bottom-4',
base: 'bottom-0 data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out]'
base: 'bottom-0 data-[state=open]:animate-[slide-in-from-bottom_280ms_cubic-bezier(0.4,0,0.6,1)]'
}
}, {
swipeDirection: ['left', 'right'],

View File

@@ -120,7 +120,7 @@ describe('CheckboxGroup', () => {
test('no label for=... on FormField', async () => {
const { wrapper } = await createForm()
const formFieldLabel = wrapper.findAll('label').map(label => label.attributes()).filter(label => !label.for?.includes(':'))[0]
expect(formFieldLabel?.for).toBeUndefined()
expect(formFieldLabel.for).toBeUndefined()
})
})
})

View File

@@ -68,15 +68,15 @@ describe('CommandPalette', () => {
// Props
['with groups', { props }],
['without data', {}],
['with modelValue', { props: { ...props, modelValue: groups[2]?.items[0] } }],
['with defaultValue', { props: { ...props, defaultValue: groups[2]?.items[0] } }],
['with modelValue', { props: { ...props, modelValue: groups[2].items[0] } }],
['with defaultValue', { props: { ...props, defaultValue: groups[2].items[0] } }],
['with labelKey', { props: { ...props, labelKey: 'icon' } }],
['with placeholder', { props: { ...props, placeholder: 'Search...' } }],
['with disabled', { props: { ...props, disabled: true } }],
['with icon', { props: { ...props, icon: 'i-lucide-terminal' } }],
['with loading', { props: { ...props, loading: true } }],
['with loadingIcon', { props: { ...props, loading: true, loadingIcon: 'i-lucide-loader' } }],
['with selectedIcon', { props: { ...props, selectedIcon: 'i-lucide-badge-check', modelValue: groups[2]?.items[0] } }],
['with selectedIcon', { props: { ...props, selectedIcon: 'i-lucide-badge-check', modelValue: groups[2].items[0] } }],
['with close', { props: { ...props, close: true } }],
['with closeIcon', { props: { ...props, close: true, closeIcon: 'i-lucide-trash' } }],
['with as', { props: { ...props, as: 'section' } }],

View File

@@ -314,8 +314,8 @@ describe('Form', () => {
emailInput.trigger('focus')
await flushPromises()
expect(mockWatchCallback).toHaveBeenCalledTimes(1)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('email')).toBe(true)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('password')).toBe(false)
expect(mockWatchCallback.mock.calls[0][0].has('email')).toBe(true)
expect(mockWatchCallback.mock.calls[0][0].has('password')).toBe(false)
})
test('reactivity: touchedFields works on change', async () => {
@@ -327,8 +327,8 @@ describe('Form', () => {
emailInput.trigger('change')
await flushPromises()
expect(mockWatchCallback).toHaveBeenCalledTimes(1)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('email')).toBe(true)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('password')).toBe(false)
expect(mockWatchCallback.mock.calls[0][0].has('email')).toBe(true)
expect(mockWatchCallback.mock.calls[0][0].has('password')).toBe(false)
})
test('reactivity: blurredFields works', async () => {
@@ -340,8 +340,8 @@ describe('Form', () => {
emailInput.trigger('blur')
await flushPromises()
expect(mockWatchCallback).toHaveBeenCalledTimes(1)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('email')).toBe(true)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('password')).toBe(false)
expect(mockWatchCallback.mock.calls[0][0].has('email')).toBe(true)
expect(mockWatchCallback.mock.calls[0][0].has('password')).toBe(false)
})
test('reactivity: dirtyFields works', async () => {
@@ -352,8 +352,8 @@ describe('Form', () => {
emailInput.trigger('change')
await flushPromises()
expect(mockWatchCallback).toHaveBeenCalledTimes(1)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('email')).toBe(true)
expect(mockWatchCallback.mock.calls?.[0]?.[0]?.has('password')).toBe(false)
expect(mockWatchCallback.mock.calls[0][0].has('email')).toBe(true)
expect(mockWatchCallback.mock.calls[0][0].has('password')).toBe(false)
})
test('reactivity: dirty works', async () => {

Some files were not shown because too many files have changed in this diff Show More