Compare commits

..

3 Commits

Author SHA1 Message Date
Benjamin Canac
723065afa7 up 2025-03-07 15:19:38 +01:00
Benjamin Canac
e67305e412 up 2025-03-07 15:11:17 +01:00
Benjamin Canac
33ed3935a3 fix(vue): stub vue-router 2025-03-07 15:00:10 +01:00
82 changed files with 2077 additions and 2214 deletions

View File

@@ -1,36 +1,5 @@
# Changelog
## [3.0.0](https://github.com/nuxt/ui/compare/v3.0.0-beta.4...v3.0.0) (2025-03-12)
## [3.0.0-beta.4](https://github.com/nuxt/ui/compare/v3.0.0-beta.3...v3.0.0-beta.4) (2025-03-12)
### Features
* **Form:** global errors ([#3482](https://github.com/nuxt/ui/issues/3482)) ([6e03d9c](https://github.com/nuxt/ui/commit/6e03d9c6efc8f4cfc306813e733d7d3e03706323))
* **Input/Textarea:** allow `null` value in model ([#3415](https://github.com/nuxt/ui/issues/3415)) ([cfe9b2e](https://github.com/nuxt/ui/commit/cfe9b2ecf34827bc11a5281a069988ab96030047))
* **useLocale:** handle generic messages ([#3100](https://github.com/nuxt/ui/issues/3100)) ([a9c8eb3](https://github.com/nuxt/ui/commit/a9c8eb3f60a10d1a71632991c9db594716b0fba1))
### Bug Fixes
* **Button:** missing import ([21dbf01](https://github.com/nuxt/ui/commit/21dbf01888a161a9d8ac6eb0d957c1342f6cc30d)), closes [nuxt/ui#3417](https://github.com/nuxt/ui/issues/3417)
* **Form:** input blur validation on submit ([#3504](https://github.com/nuxt/ui/issues/3504)) ([97c8098](https://github.com/nuxt/ui/commit/97c8098d4a35c392719ae179d36aa008d6f8f78a))
* **vue:** prevent calling `useHead` in colors ([5ecd227](https://github.com/nuxt/ui/commit/5ecd2271ca86087cb805548397d75c38763ad412))
## [3.0.0-beta.3](https://github.com/nuxt/ui/compare/v3.0.0-beta.2...v3.0.0-beta.3) (2025-03-07)
### Features
* **Button:** handle `active` state ([bd2d484](https://github.com/nuxt/ui/commit/bd2d4848d246a3d5930f8059913f5a1a0abe29fd)), closes [#3417](https://github.com/nuxt/ui/issues/3417)
* **Table:** add `loading` slot ([99e531d](https://github.com/nuxt/ui/commit/99e531d8dfb7954322b7ab7feda3d8814c6d8d02)), closes [#3444](https://github.com/nuxt/ui/issues/3444)
### Bug Fixes
* **InputMenu/SelectMenu:** proxy `required` in root props ([60b7e2d](https://github.com/nuxt/ui/commit/60b7e2d69e80afa7e221855dcec46479d0ca5c6c))
* **InputMenu:** wrong `required` in multiple mode ([01fa230](https://github.com/nuxt/ui/commit/01fa230eae4b6623c5fd71cc218d114d9f6f0f25)), closes [#2741](https://github.com/nuxt/ui/issues/2741)
* **Pagination:** add missing slots ([a47c5ff](https://github.com/nuxt/ui/commit/a47c5ff46616eafee3158cb9801183965f5f9874)), closes [#3441](https://github.com/nuxt/ui/issues/3441)
* **Pagination:** wrong next link ([e823022](https://github.com/nuxt/ui/commit/e823022b19bb172d2e5fabb9144b4a4286a25a5f)), closes [#3008](https://github.com/nuxt/ui/issues/3008)
* **templates:** prevent overriding existing colors ([ccbd89c](https://github.com/nuxt/ui/commit/ccbd89c908fe8af54c7d723dd12da5b7f3906c8f)), closes [#3426](https://github.com/nuxt/ui/issues/3426)
## [3.0.0-beta.2](https://github.com/nuxt/ui/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2025-02-28)
### Bug Fixes

View File

@@ -14,7 +14,7 @@
We're thrilled to introduce Nuxt UI v3, a significant upgrade to our UI library that delivers extensive improvements and robust new capabilities. This major update harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Tailwind CSS v4](https://tailwindcss.com/), and [Tailwind Variants](https://www.tailwind-variants.org/) to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.
> [!NOTE]
> You are on the `v3` development branch, check out the [v2 branch](https://github.com/nuxt/ui/tree/v2) for Nuxt UI v2.
> You are on the `v3` development branch, check out the [dev branch](https://github.com/nuxt/ui/tree/dev) for Nuxt UI v2.
## Documentation

View File

@@ -275,14 +275,16 @@ faq:
content: As the Figma Pro Kit is a digital product packaged as a zip file, we cannot offer refunds once the purchase is made.
- label: Do you have a Figma to Code plugin?
content: >
We recommend the open source [TemPad Dev](https://github.com/ecomfe/tempad-dev) inspect panel with the [TemPad Dev Nuxt UI Plugin](https://github.com/Justineo/tempad-dev-plugin-nuxt-ui):
We recommend the open source [TeamPad Dev](https://github.com/ecomfe/tempad-dev) inspect panel with the [TeamPad Dev Nuxt UI Plugin](https://github.com/Justineo/tempad-dev-plugin-nuxt-ui):
1. Install the [TemPad Dev Chrome Extension](https://chromewebstore.google.com/detail/tempad-dev/lgoeakbaikpkihoiphamaeopmliaimpc)
1. Install the [TeamPad Dev Chrome Extension](https://chromewebstore.google.com/detail/tempad-dev/lgoeakbaikpkihoiphamaeopmliaimpc)
2. Open your Figma file with Nuxt UI components (reload the page if you don't see the TemPad Dev panel)
2. Open your Figma file with Nuxt UI components (reload the page if you don't see the TeamPad Dev panel)
3. Install the `@nuxt` (or `@nuxt/pro` for Nuxt UI Pro) in TemPad Dev's plugins section
3. Install the `@nuxt` in TeamPad Dev's plugins section
4. Select any Nuxt UI component and inspect the code it generates
![TemPad Dev Nuxt UI Plugin](/pro/figma/teampad-dev-nuxt-ui-plugin.gif){.w-full .rounded .mb-2 .max-w-[636px]}
![TeamPad Dev Nuxt UI Plugin](/pro/figma/teampad-dev-nuxt-ui-plugin.gif){.w-full .rounded .mb-2 .max-w-[636px]}
*Right now, only Nuxt UI components are supported, but the code of the plugin is [open source](https://github.com/Justineo/tempad-dev-plugin-nuxt-ui) and anyone can contribute to it.*

View File

@@ -189,7 +189,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
:links="page.design_system.links"
orientation="horizontal"
>
<MDC :value="page.design_system.code" cache-key="index-design-system-code" />
<MDC :value="page.design_system.code" />
</UPageSection>
<USeparator />
@@ -201,10 +201,10 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
orientation="horizontal"
>
<template #description>
<MDC :value="page.component_customization.description" cache-key="index-component-customization-description" />
<MDC :value="page.component_customization.description" />
</template>
<MDC :value="page.component_customization.code" cache-key="index-component-customization-code" />
<MDC :value="page.component_customization.code" />
</UPageSection>
<USeparator />

View File

@@ -227,17 +227,28 @@ This option adds the `transition-colors` class on components with hover or activ
Nuxt UI v3 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.
Automatic preview releases are created for all commits and PRs to the `v3` branch. Use them by replacing your package version with the specific commit hash or PR number.
Preview releases are automatically generated for every commit to the `v3` branch and pull requests targeting the `v3` branch. To use it into your project, use the installation command below by replacing `5385f84` with any commit hash or pull request number.
```diff [package.json]
{
"dependencies": {
- "@nuxt/ui": "^3.0.0-beta.3",
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
}
}
::code-group{sync="pm"}
```bash [pnpm]
pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [yarn]
yarn add https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [npm]
npm install https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [bun]
bun add https://pkg.pr.new/@nuxt/ui@5385f84
```
::
::note
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
::

View File

@@ -315,17 +315,28 @@ This option adds the `transition-colors` class on components with hover or activ
Nuxt UI v3 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.
Automatic preview releases are created for all commits and PRs to the `v3` branch. Use them by replacing your package version with the specific commit hash or PR number.
Preview releases are automatically generated for every commit to the `v3` branch and pull requests targeting the `v3` branch. To use it into your project, use the installation command below by replacing `5385f84` with any commit hash or pull request number.
```diff [package.json]
{
"dependencies": {
- "@nuxt/ui": "^3.0.0-beta.3",
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
}
}
::code-group{sync="pm"}
```bash [pnpm]
pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [yarn]
yarn add https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [npm]
npm install https://pkg.pr.new/@nuxt/ui@5385f84
```
```bash [bun]
bun add https://pkg.pr.new/@nuxt/ui@5385f84
```
::
::note
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
::

View File

@@ -439,10 +439,7 @@ This change affects the following components: `Modal`, `Popover`, `Slideover`, `
This change affects the following components: `Modal`, `Slideover`.
::
### Changed composables
1. The `useToast()` composable `timeout` prop has been renamed to `duration`:
6. The `Toast` component `timeout` prop has been renamed to `duration`:
```diff
<script setup lang="ts">
@@ -453,79 +450,6 @@ const toast = useToast()
</script>
```
2. The `useModal` and `useSlideover` composables have been removed in favor of a more generic `useOverlay` composable:
Some important differences:
- The `useOverlay` composable is now used to create overlay instances
- Overlays that are opened, can be awaited for their result
- Overlays can no longer be closed using `modal.close()` or `slideover.close()`, rather, they close automatically: either when a `closed` event is fired explicitly from the opened component OR when the overlay closes itself (clicking on backdrop, pressing the ESC key, etc)
- To capture the return value in the parent component you must explictly emit a `closed` event with the desired value
```diff
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
- modal.open(ModalExampleComponent)
+ const modal = overlay.create(ModalExampleComponent)
</script>
```
Props are now passed through a props attribute:
```diff
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
const count = ref(0)
- modal.open(ModalExampleComponent, {
- count: count.value
- })
+ const modal = overlay.create(ModalExampleComponent, {
+ props: {
+ count: count.value
+ }
+ })
</script>
```
Closing a modal is now done through the `closed` event. The `modal.open` method now returns a promise that resolves to the result of the modal whenever the modal is closed:
```diff
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
- const modal = useModal()
+ const overlay = useOverlay()
+ const modal = overlay.create(ModalExampleComponent)
- function openModal() {
- modal.open(ModalExampleComponent, {
- onSuccess() {
- toast.add({ title: 'Success!' })
- }
- })
- }
+ async function openModal() {
+ const result = await modal.open(ModalExampleComponent, {
+ count: count.value
+ })
+
+ if (result) {
+ toast.add({ title: 'Success!' })
+ }
+ }
</script>
```
---
::warning

View File

@@ -17,11 +17,6 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale
::module-only
#ui
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [app.vue]
@@ -36,42 +31,13 @@ import { fr } from '@nuxt/ui/locale'
</template>
```
:::
#ui-pro
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
```vue [app.vue]
<script setup lang="ts">
import { fr } from '@nuxt/ui-pro/locale'
</script>
<template>
<UApp :locale="fr">
<NuxtPage />
</UApp>
</template>
```
:::
::
### Custom locale
You also have the option to add your own locale using `defineLocale`:
::module-only
#ui
:::div
```vue [app.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui'
const locale = defineLocale<Messages>({
const locale = defineLocale({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
@@ -88,35 +54,6 @@ const locale = defineLocale<Messages>({
</template>
```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui-pro'
const locale = defineLocale<Messages>({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
messages: {
// implement pairs
}
})
</script>
<template>
<UApp :locale="locale">
<NuxtPage />
</UApp>
</template>
```
:::
::
::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -179,11 +116,6 @@ export default defineNuxtConfig({
#### Set the `locale` prop using `useI18n`
::module-only
#ui
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui/locale'
@@ -198,28 +130,6 @@ const { locale } = useI18n()
</template>
```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
</script>
<template>
<UApp :locale="locales[locale]">
<NuxtPage />
</UApp>
</template>
```
:::
::
::
### Dynamic direction
@@ -228,11 +138,6 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://nuxt.com/docs/api/composables/use-head) composable:
::module-only
#ui
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui/locale'
@@ -257,38 +162,6 @@ useHead({
</template>
```
:::
#ui-pro
:::div
```vue [app.vue]
<script setup lang="ts">
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
const lang = computed(() => locales[locale.value].code)
const dir = computed(() => locales[locale.value].dir)
useHead({
htmlAttrs: {
lang,
dir
}
})
</script>
<template>
<UApp :locale="locales[locale]">
<NuxtPage />
</UApp>
</template>
```
:::
::
## Supported languages
:supported-languages

View File

@@ -17,11 +17,6 @@ Nuxt UI provides an **App** component that wraps your app to provide global conf
### Locale
::module-only
#ui
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:
```vue [App.vue]
@@ -36,43 +31,15 @@ import { fr } from '@nuxt/ui/locale'
</template>
```
:::
#ui-pro
:::div
Use the `locale` prop with the locale you want to use from `@nuxt/ui-pro/locale`:
```vue [App.vue]
<script setup lang="ts">
import { fr } from '@nuxt/ui-pro/locale'
</script>
<template>
<UApp :locale="fr">
<RouterView />
</UApp>
</template>
```
:::
::
### Custom locale
You also have the option to add your locale using `defineLocale`:
::module-only
#ui
:::div
```vue [App.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui'
import { defineLocale } from '@nuxt/ui/composables/defineLocale.js'
import { defineLocale } from '@nuxt/ui/composables/defineLocale'
const locale = defineLocale<Messages>({
const locale = defineLocale({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
@@ -89,36 +56,6 @@ const locale = defineLocale<Messages>({
</template>
```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import type { Messages } from '@nuxt/ui-pro'
import { defineLocale } from '@nuxt/ui/composables/defineLocale.js'
const locale = defineLocale<Messages>({
name: 'My custom locale',
code: 'en',
dir: 'ltr',
messages: {
// implement pairs
}
})
</script>
<template>
<UApp :locale="locale">
<RouterView />
</UApp>
</template>
```
:::
::
::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
@@ -194,11 +131,6 @@ app.mount('#app')
#### Set the `locale` prop using `useI18n`
::module-only
#ui
:::div
```vue [App.vue]
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
@@ -214,29 +146,6 @@ const { locale } = useI18n()
</template>
```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
</script>
<template>
<UApp :locale="locales[locale]">
<RouterView />
</UApp>
</template>
```
:::
::
::
### Dynamic direction
@@ -245,11 +154,6 @@ Each locale has a `dir` property which will be used by the `App` component to se
In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head) composable:
::module-only
#ui
:::div
```vue [App.vue]
<script setup lang="ts">
import { computed } from 'vue'
@@ -277,41 +181,6 @@ useHead({
</template>
```
:::
#ui-pro
:::div
```vue [App.vue]
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useHead } from '@unhead/vue'
import * as locales from '@nuxt/ui-pro/locale'
const { locale } = useI18n()
const lang = computed(() => locales[locale.value].code)
const dir = computed(() => locales[locale.value].dir)
useHead({
htmlAttrs: {
lang,
dir
}
})
</script>
<template>
<UApp :locale="locales[locale]">
<RouterView />
</UApp>
</template>
```
:::
::
## Supported languages
:supported-languages

View File

@@ -55,7 +55,6 @@ export default defineNuxtConfig({
}]
},
rootAttrs: {
// @ts-expect-error - vaul-drawer-wrapper is not typed
'vaul-drawer-wrapper': '',
'class': 'bg-(--ui-bg)'
}

View File

@@ -4,25 +4,25 @@
"type": "module",
"dependencies": {
"@iconify-json/logos": "^1.2.4",
"@iconify-json/lucide": "^1.2.29",
"@iconify-json/simple-icons": "^1.2.28",
"@iconify-json/lucide": "^1.2.28",
"@iconify-json/simple-icons": "^1.2.27",
"@iconify-json/vscode-icons": "^1.2.16",
"@nuxt/content": "^3.3.0",
"@nuxt/image": "^1.9.0",
"@nuxt/ui": "latest",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@a2768ed",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@02b7ea0",
"@nuxthub/core": "^0.8.18",
"@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^21.1.1",
"@rollup/plugin-yaml": "^4.1.2",
"@vueuse/nuxt": "^13.0.0",
"@vueuse/nuxt": "^12.8.2",
"joi": "^17.13.3",
"motion": "^12.5.0",
"motion-v": "0.11.3",
"nuxt": "^3.16.0",
"motion": "^12.4.10",
"motion-v": "0.11.1",
"nuxt": "^3.15.4",
"nuxt-component-meta": "^0.10.0",
"nuxt-llms": "^0.1.0",
"nuxt-og-image": "^5.0.2",
"nuxt-og-image": "^4.2.0",
"prettier": "^3.5.3",
"shiki-transformer-color-highlight": "^1.0.0",
"superstruct": "^2.0.2",

View File

@@ -1,8 +1,8 @@
{
"name": "@nuxt/ui",
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
"version": "3.0.0",
"packageManager": "pnpm@10.6.2",
"version": "3.0.0-beta.2",
"packageManager": "pnpm@10.6.1",
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt/ui.git"
@@ -67,7 +67,7 @@
"dev:build": "nuxi build playground",
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground && nuxi prepare docs && vite build playground-vue",
"docs": "DEV=true nuxi dev docs",
"docs:build": "NODE_OPTIONS='--max-old-space-size=8192' nuxi build docs",
"docs:build": "nuxi build docs",
"docs:prepare": "nuxt-component-meta docs",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
@@ -75,23 +75,23 @@
"test": "vitest",
"test:vue": "vitest -c vitest.vue.config.ts",
"test:vue:build": "vite build playground-vue",
"release": "release-it"
"release": "release-it --preRelease=beta --npm.tag=next"
},
"dependencies": {
"@iconify/vue": "^4.3.0",
"@internationalized/date": "^3.7.0",
"@internationalized/number": "^3.6.0",
"@nuxt/fonts": "^0.11.0",
"@nuxt/icon": "^1.11.0",
"@nuxt/kit": "^3.16.0",
"@nuxt/schema": "^3.16.0",
"@nuxt/fonts": "^0.10.3",
"@nuxt/icon": "^1.10.3",
"@nuxt/kit": "^3.15.4",
"@nuxt/schema": "^3.15.4",
"@nuxtjs/color-mode": "^3.5.2",
"@tailwindcss/postcss": "^4.0.13",
"@tailwindcss/vite": "^4.0.13",
"@tailwindcss/postcss": "^4.0.12",
"@tailwindcss/vite": "^4.0.12",
"@tanstack/vue-table": "^8.21.2",
"@unhead/vue": "^2.0.0-rc.10",
"@vueuse/core": "^13.0.0",
"@vueuse/integrations": "^13.0.0",
"@unhead/vue": "^1.11.20",
"@vueuse/core": "^12.8.2",
"@vueuse/integrations": "^12.8.2",
"colortranslator": "^4.1.0",
"consola": "^3.4.0",
"defu": "^6.1.4",
@@ -110,28 +110,26 @@
"pathe": "^2.0.3",
"reka-ui": "^2.0.2",
"scule": "^1.3.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.0.13",
"tailwind-variants": "^0.3.1",
"tailwindcss": "^4.0.12",
"tinyglobby": "^0.2.12",
"unplugin": "^2.2.0",
"unplugin-auto-import": "^19.1.1",
"unplugin-vue-components": "^28.4.1",
"vaul-vue": "^0.3.0",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
"vaul-vue": "^0.3.0"
},
"devDependencies": {
"@nuxt/eslint-config": "^1.2.0",
"@nuxt/eslint-config": "^1.1.0",
"@nuxt/module-builder": "^0.8.4",
"@nuxt/test-utils": "^3.17.2",
"@nuxt/test-utils": "^3.17.1",
"@release-it/conventional-changelog": "^10.0.0",
"@standard-schema/spec": "^1.0.0",
"@vue/test-utils": "^2.4.6",
"embla-carousel": "^8.5.2",
"eslint": "^9.22.0",
"happy-dom": "^17.4.4",
"eslint": "^9.21.0",
"happy-dom": "^17.1.2",
"joi": "^17.13.3",
"nuxt": "^3.16.0",
"nuxt": "^3.15.4",
"release-it": "^18.1.2",
"superstruct": "^2.0.2",
"valibot": "^0.42.1",
@@ -148,9 +146,12 @@
"@nuxt/ui": "workspace:*",
"chokidar": "3.6.0",
"debug": "4.3.7",
"rollup": "4.34.9",
"happy-dom": "17.1.2",
"rollup": "4.32.1",
"typescript": "5.6.3",
"unimport": "3.14.5",
"unplugin": "^2.2.0",
"vue": "3.5.13",
"vue-tsc": "2.2.0"
},
"pnpm": {

View File

@@ -2,9 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nuxt UI - Vue Playground</title>
<title>Nuxt UI ❤️ Vue</title>
</head>
<body>
<div id="app" class="isolate"></div>

View File

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
<style>
.st0 { fill: #42B883; }
.st1 { fill: #35495E; }
</style>
<path class="st0" d="M78.8,10L64,35.4L49.2,10H0l64,110l64-110C128,10,78.8,10,78.8,10z" />
<path class="st1" d="M78.8,10L64,35.4L49.2,10H25.6L64,76l38.4-66H78.8z" />
</svg>

Before

Width:  |  Height:  |  Size: 316 B

View File

@@ -8,10 +8,10 @@
"generate": "nuxi generate"
},
"dependencies": {
"@iconify-json/lucide": "^1.2.29",
"@iconify-json/simple-icons": "^1.2.28",
"@iconify-json/lucide": "^1.2.28",
"@iconify-json/simple-icons": "^1.2.27",
"@nuxt/ui": "latest",
"@nuxthub/core": "^0.8.18",
"nuxt": "^3.16.0"
"nuxt": "^3.15.4"
}
}

3418
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,13 +6,13 @@
"enabled": true
},
"ignoreDeps": [
"happy-dom",
"valibot30",
"valibot31",
"typescript",
"vaul-vue",
"vue-tsc"
],
"baseBranches": ["v2", "v3"],
"baseBranches": ["dev", "v3"],
"packageRules": [{
"matchBaseBranches": ["v3"],
"labels": ["v3"]

View File

@@ -53,7 +53,7 @@ export default defineNuxtModule<ModuleOptions>({
name: 'ui',
configKey: 'ui',
compatibility: {
nuxt: '>=3.16.0'
nuxt: '>=3.13.1'
},
docs: 'https://ui3.nuxt.dev/getting-started/installation/nuxt'
},

View File

@@ -1,11 +1,12 @@
<script lang="ts">
import type { ConfigProviderProps, TooltipProviderProps } from 'reka-ui'
import type { ToasterProps, Locale, Messages } from '../types'
import { localeContextInjectionKey } from '../composables/useLocale'
import type { ToasterProps, Locale } from '../types'
export interface AppProps<T extends Messages = Messages> extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
export interface AppProps extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
tooltip?: TooltipProviderProps
toaster?: ToasterProps | null
locale?: Locale<T>
locale?: Locale
}
export interface AppSlots {
@@ -17,15 +18,14 @@ export default {
}
</script>
<script setup lang="ts" generic="T extends Messages = Messages">
<script setup lang="ts">
import { toRef, useId, provide } from 'vue'
import { ConfigProvider, TooltipProvider, useForwardProps } from 'reka-ui'
import { reactivePick } from '@vueuse/core'
import { localeContextInjectionKey } from '../composables/useLocale'
import UToaster from './Toaster.vue'
import UOverlayProvider from './OverlayProvider.vue'
const props = defineProps<AppProps<T>>()
const props = defineProps<AppProps>()
defineSlots<AppSlots>()
const configProviderProps = useForwardProps(reactivePick(props, 'scrollBody'))

View File

@@ -60,7 +60,6 @@ import { pickLinkProps } from '../utils/link'
import UIcon from './Icon.vue'
import UAvatar from './Avatar.vue'
import ULink from './Link.vue'
import ULinkBase from './LinkBase.vue'
const props = withDefaults(defineProps<ButtonProps>(), {
active: undefined,

View File

@@ -29,7 +29,7 @@ export interface FormEmits<T extends object> {
}
export interface FormSlots {
default(props?: { errors: FormError[] }): any
default(props?: {}): any
}
</script>
@@ -69,7 +69,7 @@ onMounted(async () => {
nestedForms.value.set(event.formId, { validate: event.validate })
} else if (event.type === 'detach') {
nestedForms.value.delete(event.formId)
} else if (props.validateOn?.includes(event.type) && !loading.value) {
} else if (props.validateOn?.includes(event.type)) {
if (event.type !== 'input') {
await _validate({ name: event.name, silent: true, nested: false })
} else if (event.eager || blurredFields.has(event.name)) {
@@ -121,7 +121,7 @@ const blurredFields = new Set<keyof T>()
function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
return errs.map(err => ({
...err,
id: err?.name ? inputs.value[err.name]?.id : undefined
id: inputs.value[err.name]?.id
}))
}
@@ -159,12 +159,12 @@ async function _validate(opts: { name?: keyof T | (keyof T)[], silent?: boolean,
if (names) {
const otherErrors = errors.value.filter(error => !names.some((name) => {
const pattern = inputs.value?.[name]?.pattern
return name === error.name || (pattern && error.name?.match(pattern))
return name === error.name || (pattern && error.name.match(pattern))
}))
const pathErrors = (await getErrors()).filter(error => names.some((name) => {
const pattern = inputs.value?.[name]?.pattern
return name === error.name || (pattern && error.name?.match(pattern))
return name === error.name || (pattern && error.name.match(pattern))
}))
errors.value = otherErrors.concat(pathErrors)
@@ -269,6 +269,6 @@ defineExpose<Form<T>>({
:class="form({ class: props.class })"
@submit.prevent="onSubmitWrapper"
>
<slot :errors="errors" />
<slot />
</component>
</template>

View File

@@ -63,7 +63,7 @@ const ui = computed(() => formField({
const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)
const error = computed(() => props.error || formErrors?.value?.find(error => error.name && (error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern))))?.message)
const error = computed(() => props.error || formErrors?.value?.find(error => error.name === props.name || (props.errorPattern && error.name.match(props.errorPattern)))?.message)
const id = ref(useId())
// Copies id's initial value to bind aria-attributes such as aria-describedby.

View File

@@ -82,7 +82,7 @@ const props = withDefaults(defineProps<InputProps>(), {
const emits = defineEmits<InputEmits>()
const slots = defineSlots<InputSlots>()
const [modelValue, modelModifiers] = defineModel<string | number | null>()
const [modelValue, modelModifiers] = defineModel<string | number>()
const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField<InputProps>(props, { deferInputValidation: true })
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
@@ -111,19 +111,15 @@ function autoFocus() {
}
// Custom function to handle the v-model properties
function updateInput(value: string | null) {
function updateInput(value: string) {
if (modelModifiers.trim) {
value = value?.trim() ?? null
value = value.trim()
}
if (modelModifiers.number || props.type === 'number') {
value = looseToNumber(value)
}
if (modelModifiers.nullify) {
value ||= null
}
modelValue.value = value
emitFormInput()
}

View File

@@ -1,6 +1,4 @@
<script lang="ts">
import type { LinkProps } from '../types'
export interface LinkBaseProps {
as?: string
type?: string
@@ -8,8 +6,8 @@ export interface LinkBaseProps {
onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
href?: string
navigate?: (e: MouseEvent) => void
target?: LinkProps['target']
rel?: LinkProps['rel']
rel?: string
target?: string
isExternal?: boolean
}
</script>

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import type { PaginationRootProps, PaginationRootEmits } from 'reka-ui'
import type { AppConfig } from '@nuxt/schema'
import type { RouteLocationRaw } from '#vue-router'
import _appConfig from '#build/app.config'
import theme from '#build/ui/pagination'
import { tv } from '../utils/tv'
@@ -77,7 +78,7 @@ export interface PaginationProps extends Partial<Pick<PaginationRootProps, 'defa
* A function to render page controls as links.
* @param page The page number to navigate to.
*/
to?: (page: number) => ButtonProps['to']
to?: (page: number) => RouteLocationRaw
class?: any
ui?: Partial<typeof pagination.slots>
}

View File

@@ -74,7 +74,7 @@ const props = withDefaults(defineProps<TextareaProps>(), {
defineSlots<TextareaSlots>()
const emits = defineEmits<TextareaEmits>()
const [modelValue, modelModifiers] = defineModel<string | number | null>()
const [modelValue, modelModifiers] = defineModel<string | number>()
const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<TextareaProps>(props, { deferInputValidation: true })
@@ -94,19 +94,15 @@ function autoFocus() {
}
// Custom function to handle the v-model properties
function updateInput(value: string | null) {
function updateInput(value: string) {
if (modelModifiers.trim) {
value = value?.trim() ?? null
value = value.trim()
}
if (modelModifiers.number) {
value = looseToNumber(value)
}
if (modelModifiers.nullify) {
value ||= null
}
modelValue.value = value
emitFormInput()
}

View File

@@ -1,13 +1,13 @@
import { defu } from 'defu'
import type { Locale, Direction } from '../types/locale'
import type { Locale, Direction, Messages } from '../types/locale'
interface DefineLocaleOptions<M> {
interface DefineLocaleOptions {
name: string
code: string
dir?: Direction
messages: M
messages: Messages
}
export function defineLocale<M>(options: DefineLocaleOptions<M>): Locale<M> {
return defu<DefineLocaleOptions<M>, [{ dir: Direction }]>(options, { dir: 'ltr' })
export function defineLocale(options: DefineLocaleOptions): Locale {
return defu<DefineLocaleOptions, [{ dir: Direction }]>(options, { dir: 'ltr' })
}

View File

@@ -1,16 +1,16 @@
import { computed, inject, toRef } from 'vue'
import { computed, inject, ref } from 'vue'
import type { InjectionKey, Ref } from 'vue'
import { createSharedComposable } from '@vueuse/core'
import type { Locale, Messages } from '../types/locale'
import type { Locale } from '../types/locale'
import { buildLocaleContext } from '../utils/locale'
import en from '../locale/en'
import { createSharedComposable } from '@vueuse/core'
export const localeContextInjectionKey: InjectionKey<Ref<Locale<unknown> | undefined>> = Symbol('nuxt-ui.locale-context')
export const localeContextInjectionKey: InjectionKey<Ref<Locale | undefined>> = Symbol('nuxt-ui.locale-context')
const _useLocale = (localeOverrides?: Ref<Locale<Messages> | undefined>) => {
const locale = localeOverrides || toRef(inject<Locale<Messages>>(localeContextInjectionKey))
const _useLocale = (localeOverrides?: Ref<Locale | undefined>) => {
const locale = localeOverrides || inject(localeContextInjectionKey, ref())!
return buildLocaleContext<Messages>(computed(() => locale.value || en))
return buildLocaleContext(computed(() => locale.value || en))
}
export const useLocale = createSharedComposable(_useLocale)

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'العربية',
code: 'ar',
dir: 'rtl',

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Azərbaycanca',
code: 'az',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'বাংলা',
code: 'bn',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Čeština',
code: 'cs',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Danish',
code: 'da',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Deutsch',
code: 'de',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Ελληνικά',
code: 'el',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'English',
code: 'en',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Español',
code: 'es',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Eesti',
code: 'et',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'فارسی',
code: 'fa-IR',
dir: 'rtl',

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Suomeksi',
code: 'fi',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Français',
code: 'fr',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Hebrew',
code: 'he',
dir: 'rtl',

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Hindi',
code: 'hi',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Magyar',
code: 'hu',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Indonesia',
code: 'id',
messages: {

View File

@@ -5,15 +5,13 @@ export { default as cs } from './cs'
export { default as da } from './da'
export { default as de } from './de'
export { default as el } from './el'
export { default as et } from './et'
export { default as en } from './en'
export { default as es } from './es'
export { default as et } from './et'
export { default as fa_ir } from './fa_ir'
export { default as fi } from './fi'
export { default as fr } from './fr'
export { default as he } from './he'
export { default as hi } from './hi'
export { default as hu } from './hu'
export { default as id } from './id'
export { default as it } from './it'
export { default as ja } from './ja'
@@ -33,3 +31,4 @@ export { default as uk } from './uk'
export { default as vi } from './vi'
export { default as zh_cn } from './zh_cn'
export { default as zh_tw } from './zh_tw'
export { default as he } from './he'

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Italiano',
code: 'it',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: '日本語',
code: 'ja',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'ភាសាខ្មែរ',
code: 'km',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: '한국어',
code: 'ko',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Norsk Bokmål',
code: 'nb-NO',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Nederlands',
code: 'nl',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Polski',
code: 'pl',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Português',
code: 'pt',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Português (Brasil)',
code: 'pt-BR',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Русский',
code: 'ru',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Slovenčina',
code: 'sk',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Svenska',
code: 'sv',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'ไทย',
code: 'th',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Türkçe',
code: 'tr',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Українська',
code: 'uk',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: 'Tiếng Việt',
code: 'vi',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: '简体中文',
code: 'zh-CN',
messages: {

View File

@@ -1,7 +1,6 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
export default defineLocale({
name: '繁體中文',
code: 'zh-TW',
messages: {

View File

@@ -55,7 +55,5 @@ export default defineNuxtPlugin(() => {
}]
}
if (!nuxtApp.isVue) {
useHead(headData)
}
useHead(headData)
})

View File

@@ -36,7 +36,7 @@ export type FormSchema<T extends object> =
export type FormInputEvents = 'input' | 'blur' | 'change' | 'focus'
export interface FormError<P extends string = string> {
name?: P
name: P
message: string
}

View File

@@ -50,9 +50,9 @@ export type Messages = {
export type Direction = 'ltr' | 'rtl'
export type Locale<M> = {
export type Locale = {
name: string
code: string
dir: Direction
messages: M
messages: Messages
}

View File

@@ -6,19 +6,19 @@ import { get } from './index'
export type TranslatorOption = Record<string, string | number>
export type Translator = (path: string, option?: TranslatorOption) => string
export type LocaleContext<M> = {
locale: Ref<Locale<M>>
export type LocaleContext = {
locale: Ref<Locale>
lang: Ref<string>
dir: Ref<Direction>
code: Ref<string>
t: Translator
}
export function buildTranslator<M>(locale: MaybeRef<Locale<M>>): Translator {
export function buildTranslator(locale: MaybeRef<Locale>): Translator {
return (path, option) => translate(path, option, unref(locale))
}
export function translate<M>(path: string, option: undefined | TranslatorOption, locale: Locale<M>): string {
export function translate(path: string, option: undefined | TranslatorOption, locale: Locale): string {
const prop: string = get(locale, `messages.${path}`, path)
return prop.replace(
@@ -27,11 +27,11 @@ export function translate<M>(path: string, option: undefined | TranslatorOption,
)
}
export function buildLocaleContext<M>(locale: MaybeRef<Locale<M>>): LocaleContext<M> {
export function buildLocaleContext(locale: MaybeRef<Locale>): LocaleContext {
const lang = computed(() => unref(locale).name)
const code = computed(() => unref(locale).code)
const dir = computed(() => unref(locale).dir)
const localeRef = isRef(locale) ? locale : ref(locale) as Ref<Locale<M>>
const localeRef = isRef(locale) ? locale : ref(locale)
return {
lang,

View File

@@ -1,9 +1,8 @@
import { createHead } from '@unhead/vue/client'
import { createHead, setHeadInjectionHandler } from '@unhead/vue'
import type { Plugin } from 'vue'
export default {
install(app) {
const head = createHead()
app.use(head)
install() {
setHeadInjectionHandler(() => createHead())
}
} satisfies Plugin

View File

@@ -6,10 +6,89 @@ import type { NuxtApp } from '#app'
import { useColorMode as useColorModeVueUse } from '@vueuse/core'
export { useHead } from '@unhead/vue'
export { useRoute, useRouter } from 'vue-router'
// Create stub implementations for vue-router
export const useRouteStub = () => ({
path: '',
name: null,
params: {},
query: {},
hash: '',
fullPath: '',
matched: [],
meta: {},
redirectedFrom: undefined
})
export const useRouterStub = () => ({
push: () => Promise.resolve(),
replace: () => Promise.resolve(),
go: () => Promise.resolve(),
back: () => Promise.resolve(),
forward: () => Promise.resolve(),
beforeEach: () => () => {},
afterEach: () => () => {},
getRoutes: () => [],
hasRoute: () => false,
currentRoute: ref({})
})
// Create a module-level cache for the imported modules
const moduleCache: Record<string, any> = {}
// Function to dynamically import a module and cache the result
function lazyImport(moduleName: string) {
return () => {
if (!moduleCache[moduleName]) {
moduleCache[moduleName] = import(/* @vite-ignore */ moduleName).catch(() => ({}))
}
return moduleCache[moduleName]
}
}
// Lazy import vue-router
const importVueRouter = lazyImport('vue-router')
// Create wrapper functions that will dynamically import or use stubs
export function useRoute() {
// Try to get the real implementation
const vueRouterModule = moduleCache['vue-router']
if (vueRouterModule && vueRouterModule.useRoute) {
return vueRouterModule.useRoute()
}
// If not available yet, try to import it
importVueRouter().then((module: any) => {
if (module && module.useRoute) {
// Module loaded successfully, but it's too late for this call
// Future calls will use the cached module
}
})
// Fall back to stub for this call
return useRouteStub()
}
export function useRouter() {
// Try to get the real implementation
const vueRouterModule = moduleCache['vue-router']
if (vueRouterModule && vueRouterModule.useRouter) {
return vueRouterModule.useRouter()
}
// If not available yet, try to import it
importVueRouter().then((module: any) => {
if (module && module.useRouter) {
// Module loaded successfully, but it's too late for this call
// Future calls will use the cached module
}
})
// Fall back to stub for this call
return useRouterStub()
}
export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale'
export const useColorMode = () => {
@@ -61,7 +140,6 @@ export const useState = <T>(key: string, init: () => T): Ref<T> => {
export function useNuxtApp() {
return {
isHydrating: true,
isVue: true,
payload: { serverRendered: false }
}
}

View File

@@ -122,10 +122,6 @@ type AppConfigUI = {
declare module '@nuxt/schema' {
interface AppConfigInput {
/**
* Nuxt UI theme configuration
* @see https://ui3.nuxt.dev/getting-started/theme#customize-theme
*/
ui?: AppConfigUI
}
}

View File

@@ -52,8 +52,7 @@ describe('Input', () => {
it.each([
['with .trim modifier', { props: { modelModifiers: { trim: true } } }, { input: 'input ', expected: 'input' }],
['with .number modifier', { props: { modelModifiers: { number: true } } }, { input: '42', expected: 42 }],
['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }],
['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }]
['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }]
])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => {
const wrapper = mount(Input, {
...options

View File

@@ -35,8 +35,7 @@ describe('Textarea', () => {
it.each([
['with .trim modifier', { props: { modelModifiers: { trim: true } } }, { input: 'input ', expected: 'input' }],
['with .number modifier', { props: { modelModifiers: { number: true } } }, { input: '42', expected: 42 }],
['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }],
['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }]
['with .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }]
])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => {
const wrapper = mount(Textarea, {
...options

View File

@@ -252,13 +252,13 @@ exports[`CommandPalette > renders with defaultValue correctly 1`] = `
exports[`CommandPalette > renders with disabled correctly 1`] = `
"<div dir="ltr" data-disabled="" class="flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-border)">
<div class="relative inline-flex items-center [&amp;>input]:h-12"><input type="text" placeholder="Type a command or search..." class="w-full rounded-[calc(var(--ui-radius)*1.5)] border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors px-3 py-2 text-sm gap-2 text-(--ui-text-highlighted) bg-transparent ps-10" disabled="" autocomplete="off" data-disabled="" aria-disabled="true" value=""><span class="absolute inset-y-0 start-0 flex items-center ps-3"><span class="iconify i-lucide:search shrink-0 text-(--ui-text-dimmed) size-5" aria-hidden="true"></span></span>
<div class="relative inline-flex items-center [&amp;>input]:h-12"><input type="text" placeholder="Type a command or search..." class="w-full rounded-[calc(var(--ui-radius)*1.5)] border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors px-3 py-2 text-sm gap-2 text-(--ui-text-highlighted) bg-transparent ps-10" disabled="" autocomplete="off" data-disabled="" aria-disabled="true" value="" aria-activedescendant="reka-listbox-item-v-0-0-1"><span class="absolute inset-y-0 start-0 flex items-center ps-3"><span class="iconify i-lucide:search shrink-0 text-(--ui-text-dimmed) size-5" aria-hidden="true"></span></span>
<!--v-if-->
</div>
<div role="listbox" aria-orientation="vertical" aria-multiselectable="false" data-orientation="vertical" class="relative overflow-hidden flex flex-col">
<div class="relative divide-y divide-(--ui-border) scroll-py-1 overflow-y-auto flex-1 focus:outline-none">
<div role="group" aria-labelledby="reka-listbox-group-v-0-0-0" class="p-1 isolate">
<!--v-if--><button type="button" id="reka-listbox-item-v-0-0-1" role="option" tabindex="-1" aria-selected="false" data-disabled="" data-state="unchecked" data-reka-collection-item="" class="group relative w-full flex items-center gap-2 px-2 py-1.5 text-sm select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text-highlighted) before:bg-(--ui-bg-elevated)"><span class="iconify i-lucide:file-plus shrink-0 size-5 text-(--ui-text)" aria-hidden="true"></span><span class="truncate space-x-1 rtl:space-x-reverse text-(--ui-text-dimmed)"><!--v-if--><span class="text-(--ui-text-highlighted) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Add new file</span><span class="text-(--ui-text-dimmed) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Create a new file in the current directory or workspace.</span></span><span class="ms-auto inline-flex gap-1.5 items-center"><span class="hidden lg:inline-flex items-center shrink-0 gap-0.5"><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">⊞</kbd><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">N</kbd></span>
<!--v-if--><button type="button" id="reka-listbox-item-v-0-0-1" role="option" tabindex="-1" aria-selected="false" data-disabled="" data-state="unchecked" data-reka-collection-item="" class="group relative w-full flex items-center gap-2 px-2 py-1.5 text-sm select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text-highlighted) before:bg-(--ui-bg-elevated)" data-highlighted=""><span class="iconify i-lucide:file-plus shrink-0 size-5 text-(--ui-text)" aria-hidden="true"></span><span class="truncate space-x-1 rtl:space-x-reverse text-(--ui-text-dimmed)"><!--v-if--><span class="text-(--ui-text-highlighted) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Add new file</span><span class="text-(--ui-text-dimmed) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Create a new file in the current directory or workspace.</span></span><span class="ms-auto inline-flex gap-1.5 items-center"><span class="hidden lg:inline-flex items-center shrink-0 gap-0.5"><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">⊞</kbd><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">N</kbd></span>
<!----></span>
</button><button type="button" id="reka-listbox-item-v-0-0-2" role="option" tabindex="-1" aria-selected="false" data-disabled="" data-state="unchecked" data-reka-collection-item="" class="group relative w-full flex items-center gap-2 px-2 py-1.5 text-sm select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors"><span class="iconify i-lucide:folder-plus shrink-0 size-5 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors" aria-hidden="true"></span><span class="truncate space-x-1 rtl:space-x-reverse text-(--ui-text-dimmed)"><!--v-if--><span class="text-(--ui-text-highlighted) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Add new folder</span><span class="text-(--ui-text-dimmed) [&amp;>mark]:text-(--ui-bg) [&amp;>mark]:bg-(--ui-primary)">Create a new folder in the current directory or workspace.</span></span><span class="ms-auto inline-flex gap-1.5 items-center"><span class="hidden lg:inline-flex items-center shrink-0 gap-0.5"><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">⊞</kbd><kbd class="inline-flex items-center justify-center px-1 rounded-(--ui-radius) font-medium font-sans bg-(--ui-bg) text-(--ui-text-highlighted) ring ring-inset ring-(--ui-border-accented) h-5 min-w-[20px] text-[11px]">F</kbd></span>
<!----></span>

View File

@@ -2,6 +2,6 @@
exports[`Container > renders with as correctly 1`] = `"<article class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8"></article>"`;
exports[`Container > renders with class correctly 1`] = `"<div class="mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
exports[`Container > renders with class correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
exports[`Container > renders with default slot correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8">Default slot</div>"`;

View File

@@ -2,6 +2,6 @@
exports[`Container > renders with as correctly 1`] = `"<article class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8"></article>"`;
exports[`Container > renders with class correctly 1`] = `"<div class="mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
exports[`Container > renders with class correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
exports[`Container > renders with default slot correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8">Default slot</div>"`;

View File

@@ -223,7 +223,7 @@ exports[`InputMenu > renders with defaultValue correctly 1`] = `
`;
exports[`InputMenu > renders with disabled correctly 1`] = `
"<div dir="ltr" data-disabled="" class="relative inline-flex items-center" style="pointer-events: auto;"><input disabled="" data-disabled="" aria-disabled="true" type="text" aria-expanded="true" aria-controls="" aria-autocomplete="list" role="combobox" autocomplete="false" class="rounded-[calc(var(--ui-radius)*1.5)] transition-colors px-2.5 py-1.5 text-sm gap-1.5 text-(--ui-text-highlighted) bg-(--ui-bg) ring ring-inset ring-(--ui-border-accented) w-full border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-primary) pe-9" value="">
"<div dir="ltr" data-disabled="" class="relative inline-flex items-center" style="pointer-events: auto;"><input disabled="" data-disabled="" aria-disabled="true" type="text" aria-expanded="true" aria-controls="" aria-autocomplete="list" role="combobox" autocomplete="false" class="rounded-[calc(var(--ui-radius)*1.5)] transition-colors px-2.5 py-1.5 text-sm gap-1.5 text-(--ui-text-highlighted) bg-(--ui-bg) ring ring-inset ring-(--ui-border-accented) w-full border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-primary) pe-9" value="" aria-activedescendant="reka-combobox-item-v-0-0-3">
<!--v-if--><button disabled="" type="button" tabindex="-1" aria-label="Show popup" aria-haspopup="listbox" aria-expanded="true" aria-controls="" data-state="open" data-disabled="" aria-disabled="true" class="group absolute inset-y-0 end-0 flex items-center disabled:cursor-not-allowed disabled:opacity-75 pe-2.5"><span class="iconify i-lucide:chevron-down shrink-0 text-(--ui-text-dimmed) size-5" aria-hidden="true"></span></button>
<!--teleport start-->
<div data-reka-popper-content-wrapper="" style="position: fixed; left: 0px; top: 0px; transform: translate(0, -200%); min-width: max-content;">
@@ -232,7 +232,7 @@ exports[`InputMenu > renders with disabled correctly 1`] = `
<div class="divide-y divide-(--ui-border) scroll-py-1" data-reka-combobox-viewport="" role="presentation" style="position: relative; overflow: auto; flex-grow: 1; flex-shrink: 1; flex-basis: 0%;">
<!--v-if-->
<div role="group" aria-labelledby="" id="reka-combobox-group-v-0-0-1" class="p-1 isolate">
<div id="reka-combobox-item-v-0-0-3" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-help shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Backlog</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-3" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item="" data-highlighted=""><span class="iconify i-lucide:circle-help shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Backlog</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-5" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-plus shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Todo</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-7" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-arrow-up shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">In Progress</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-9" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-check shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Done</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>

View File

@@ -270,7 +270,7 @@ exports[`SelectMenu > renders with disabled correctly 1`] = `
<div data-reka-popper-content-wrapper="" style="position: fixed; left: 0px; top: 0px; transform: translate(0, -200%); min-width: max-content;">
<div position="popper" id="reka-combobox-content-v-0-0-0" data-state="open" style="display: flex; flex-direction: column; box-sizing: border-box; --reka-combobox-content-transform-origin: var(--reka-popper-transform-origin); --reka-combobox-content-available-width: var(--reka-popper-available-width); --reka-combobox-content-available-height: var(--reka-popper-available-height); --reka-combobox-trigger-width: var(--reka-popper-anchor-width); --reka-combobox-trigger-height: var(--reka-popper-anchor-height); animation: none; outline-color: none; outline-style: none; outline-width: initial;" data-dismissable-layer="" role="listbox" aria-orientation="vertical" aria-multiselectable="false" data-orientation="vertical" class="max-h-60 w-(--reka-popper-anchor-width) bg-(--ui-bg) shadow-lg rounded-[calc(var(--ui-radius)*1.5)] ring ring-(--ui-border) overflow-hidden data-[state=open]:animate-[scale-in_100ms_ease-out] data-[state=closed]:animate-[scale-out_100ms_ease-in] pointer-events-auto" data-side="bottom" data-align="center">
<div tabindex="-1" class="flex flex-col min-h-0">
<div class="relative inline-flex items-center border-b border-(--ui-border)"><input type="text" placeholder="Search..." class="w-full rounded-[calc(var(--ui-radius)*1.5)] border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors px-2.5 py-1.5 text-sm gap-1.5 text-(--ui-text-highlighted) bg-transparent" disabled="" autocomplete="off" data-disabled="" aria-disabled="true" aria-expanded="true" aria-controls="reka-combobox-content-v-0-0-0" aria-autocomplete="list" role="combobox" value="">
<div class="relative inline-flex items-center border-b border-(--ui-border)"><input type="text" placeholder="Search..." class="w-full rounded-[calc(var(--ui-radius)*1.5)] border-0 placeholder:text-(--ui-text-dimmed) focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors px-2.5 py-1.5 text-sm gap-1.5 text-(--ui-text-highlighted) bg-transparent" disabled="" autocomplete="off" data-disabled="" aria-disabled="true" aria-expanded="true" aria-controls="reka-combobox-content-v-0-0-0" aria-autocomplete="list" role="combobox" value="" aria-activedescendant="reka-combobox-item-v-0-0-3">
<!--v-if-->
<!--v-if-->
</div>
@@ -278,7 +278,7 @@ exports[`SelectMenu > renders with disabled correctly 1`] = `
<div class="divide-y divide-(--ui-border) scroll-py-1" data-reka-combobox-viewport="" role="presentation" style="position: relative; overflow: auto; flex-grow: 1; flex-shrink: 1; flex-basis: 0%;">
<!--v-if-->
<div role="group" aria-labelledby="" id="reka-combobox-group-v-0-0-1" class="p-1 isolate">
<div id="reka-combobox-item-v-0-0-3" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-help shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Backlog</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-3" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item="" data-highlighted=""><span class="iconify i-lucide:circle-help shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Backlog</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-5" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-plus shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Todo</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-7" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-arrow-up shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">In Progress</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>
<div id="reka-combobox-item-v-0-0-9" role="option" tabindex="-1" aria-selected="false" disabled="" data-disabled="" data-state="unchecked" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-[calc(var(--ui-radius)*1.5)] data-disabled:cursor-not-allowed data-disabled:opacity-75 text-(--ui-text) data-highlighted:text-(--ui-text-highlighted) data-highlighted:before:bg-(--ui-bg-elevated)/50 transition-colors before:transition-colors p-1.5 text-sm gap-1.5" data-reka-collection-item=""><span class="iconify i-lucide:circle-check shrink-0 text-(--ui-text-dimmed) group-data-highlighted:text-(--ui-text) transition-colors size-5" aria-hidden="true"></span><span class="truncate">Done</span><span class="ms-auto inline-flex gap-1.5 items-center"><!----></span></div>

View File

@@ -33,7 +33,7 @@ exports[`Slider > renders with defaultValue correctly 1`] = `
exports[`Slider > renders with disabled correctly 1`] = `
"<span data-slider-impl="" dir="ltr" data-orientation="horizontal" style="--reka-slider-thumb-transform: translateX(-50%);" class="relative flex items-center select-none touch-none w-full opacity-75 cursor-not-allowed" aria-disabled="true" data-disabled=""><span data-disabled="" data-orientation="horizontal" class="relative bg-(--ui-bg-accented) overflow-hidden rounded-full grow h-[8px]"><span data-disabled="" data-orientation="horizontal" style="left: 0%; right: 100%;" class="absolute rounded-full bg-(--ui-primary) h-full"></span></span>
<div class="rounded-full bg-(--ui-bg) ring-2 focus-visible:outline-2 focus-visible:outline-offset-2 ring-(--ui-primary) focus-visible:outline-(--ui-primary)/50 size-4" role="slider" data-disabled="" data-orientation="horizontal" aria-valuemin="0" aria-valuemax="100" aria-orientation="horizontal" style="transform: var(--reka-slider-thumb-transform); position: absolute; left: calc(0% + 0px);" data-reka-collection-item=""></div>
<div class="rounded-full bg-(--ui-bg) ring-2 focus-visible:outline-2 focus-visible:outline-offset-2 ring-(--ui-primary) focus-visible:outline-(--ui-primary)/50 size-4" role="slider" data-disabled="" data-orientation="horizontal" aria-valuemin="0" aria-valuemax="100" aria-orientation="horizontal" style="transform: var(--reka-slider-thumb-transform); position: absolute; left: calc(0% + 0px);" data-reka-collection-item="" aria-valuenow="0"></div>
<!----></span>"
`;

View File

@@ -33,7 +33,7 @@ exports[`Slider > renders with defaultValue correctly 1`] = `
exports[`Slider > renders with disabled correctly 1`] = `
"<span data-slider-impl="" dir="ltr" data-orientation="horizontal" style="--reka-slider-thumb-transform: translateX(-50%);" class="relative flex items-center select-none touch-none w-full opacity-75 cursor-not-allowed" aria-disabled="true" data-disabled=""><span data-disabled="" data-orientation="horizontal" class="relative bg-(--ui-bg-accented) overflow-hidden rounded-full grow h-[8px]"><span data-disabled="" data-orientation="horizontal" style="left: 0%; right: 100%;" class="absolute rounded-full bg-(--ui-primary) h-full"></span></span>
<div class="rounded-full bg-(--ui-bg) ring-2 focus-visible:outline-2 focus-visible:outline-offset-2 ring-(--ui-primary) focus-visible:outline-(--ui-primary)/50 size-4" role="slider" data-disabled="" data-orientation="horizontal" aria-valuemin="0" aria-valuemax="100" aria-orientation="horizontal" style="transform: var(--reka-slider-thumb-transform); position: absolute; left: calc(0% + 0px);" data-reka-collection-item=""></div>
<div class="rounded-full bg-(--ui-bg) ring-2 focus-visible:outline-2 focus-visible:outline-offset-2 ring-(--ui-primary) focus-visible:outline-(--ui-primary)/50 size-4" role="slider" data-disabled="" data-orientation="horizontal" aria-valuemin="0" aria-valuemax="100" aria-orientation="horizontal" style="transform: var(--reka-slider-thumb-transform); position: absolute; left: calc(0% + 0px);" data-reka-collection-item="" aria-valuenow="0"></div>
<!----></span>"
`;

View File

@@ -1,12 +1,13 @@
import { fileURLToPath } from 'node:url'
import { defineVitestConfig } from '@nuxt/test-utils/config'
import { defaultExclude } from 'vitest/config'
export default defineVitestConfig({
test: {
testTimeout: 1000,
globals: true,
silent: true,
include: ['./test/components/**.spec.ts'],
exclude: [...defaultExclude, './test/vue/**.spec.ts'],
environment: 'nuxt',
environmentOptions: {
nuxt: {

View File

@@ -9,7 +9,6 @@ const vueComponents = await glob('./src/runtime/vue/components/*.vue', { absolut
export default defineConfig({
test: {
testTimeout: 1000,
environment: 'happy-dom',
silent: true,
include: ['./test/components/**.spec.ts'],