mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 20:48:12 +01:00
Compare commits
34 Commits
pr/3001
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc7bdf9247 | ||
|
|
8cbf6d2d58 | ||
|
|
881f977fe4 | ||
|
|
6e03d9c6ef | ||
|
|
5ecd2271ca | ||
|
|
556ebb0b36 | ||
|
|
3a56e3cf45 | ||
|
|
34dfe7d4b3 | ||
|
|
54468ca0f2 | ||
|
|
a9c8eb3f60 | ||
|
|
04fc367568 | ||
|
|
2b4e88d727 | ||
|
|
c713f3015d | ||
|
|
0a603e41f9 | ||
|
|
8329fedd1a | ||
|
|
e289db874d | ||
|
|
cbc5675e04 | ||
|
|
66686d2d2a | ||
|
|
e67906aa0b | ||
|
|
20fb8252f7 | ||
|
|
97c8098d4a | ||
|
|
fbc3200ec5 | ||
|
|
243f981ff4 | ||
|
|
9979a1c818 | ||
|
|
619bf0d7c9 | ||
|
|
21dbf01888 | ||
|
|
a208dedaea | ||
|
|
6120a15a99 | ||
|
|
b1552e447d | ||
|
|
36ec141c16 | ||
|
|
7940f5c0aa | ||
|
|
cfe9b2ecf3 | ||
|
|
ed7710a890 | ||
|
|
83725ac048 |
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,5 +1,34 @@
|
||||
# Changelog
|
||||
|
||||
## [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
|
||||
|
||||
@@ -275,16 +275,14 @@ 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 [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):
|
||||
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):
|
||||
|
||||
1. Install the [TeamPad Dev Chrome Extension](https://chromewebstore.google.com/detail/tempad-dev/lgoeakbaikpkihoiphamaeopmliaimpc)
|
||||
1. Install the [TemPad 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 TeamPad Dev panel)
|
||||
2. Open your Figma file with Nuxt UI components (reload the page if you don't see the TemPad Dev panel)
|
||||
|
||||
3. Install the `@nuxt` in TeamPad Dev's plugins section
|
||||
3. Install the `@nuxt` (or `@nuxt/pro` for Nuxt UI Pro) in TemPad Dev's plugins section
|
||||
|
||||
4. Select any Nuxt UI component and inspect the code it generates
|
||||
|
||||
{.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.*
|
||||
{.w-full .rounded .mb-2 .max-w-[636px]}
|
||||
|
||||
@@ -189,7 +189,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
:links="page.design_system.links"
|
||||
orientation="horizontal"
|
||||
>
|
||||
<MDC :value="page.design_system.code" />
|
||||
<MDC :value="page.design_system.code" cache-key="index-design-system-code" />
|
||||
</UPageSection>
|
||||
|
||||
<USeparator />
|
||||
@@ -201,10 +201,10 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
orientation="horizontal"
|
||||
>
|
||||
<template #description>
|
||||
<MDC :value="page.component_customization.description" />
|
||||
<MDC :value="page.component_customization.description" cache-key="index-component-customization-description" />
|
||||
</template>
|
||||
|
||||
<MDC :value="page.component_customization.code" />
|
||||
<MDC :value="page.component_customization.code" cache-key="index-component-customization-code" />
|
||||
</UPageSection>
|
||||
|
||||
<USeparator />
|
||||
|
||||
@@ -227,28 +227,17 @@ 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
|
||||
```diff [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^3.0.0-beta.3",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```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.
|
||||
::
|
||||
|
||||
@@ -315,28 +315,17 @@ 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add https://pkg.pr.new/@nuxt/ui@5385f84
|
||||
```diff [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^3.0.0-beta.3",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```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.
|
||||
::
|
||||
|
||||
@@ -439,7 +439,10 @@ This change affects the following components: `Modal`, `Popover`, `Slideover`, `
|
||||
This change affects the following components: `Modal`, `Slideover`.
|
||||
::
|
||||
|
||||
6. The `Toast` component `timeout` prop has been renamed to `duration`:
|
||||
|
||||
### Changed composables
|
||||
|
||||
1. The `useToast()` composable `timeout` prop has been renamed to `duration`:
|
||||
|
||||
```diff
|
||||
<script setup lang="ts">
|
||||
@@ -450,6 +453,79 @@ 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
|
||||
|
||||
@@ -17,6 +17,11 @@ 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]
|
||||
@@ -31,13 +36,42 @@ 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">
|
||||
const locale = defineLocale({
|
||||
import type { Messages } from '@nuxt/ui'
|
||||
|
||||
const locale = defineLocale<Messages>({
|
||||
name: 'My custom locale',
|
||||
code: 'en',
|
||||
dir: 'ltr',
|
||||
@@ -54,6 +88,35 @@ const locale = defineLocale({
|
||||
</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:
|
||||
|
||||
@@ -116,6 +179,11 @@ 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'
|
||||
@@ -130,6 +198,28 @@ 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
|
||||
@@ -138,6 +228,11 @@ 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'
|
||||
@@ -162,6 +257,38 @@ 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
|
||||
|
||||
@@ -17,6 +17,11 @@ 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]
|
||||
@@ -31,15 +36,43 @@ 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 { defineLocale } from '@nuxt/ui/composables/defineLocale'
|
||||
import type { Messages } from '@nuxt/ui'
|
||||
import { defineLocale } from '@nuxt/ui/composables/defineLocale.js'
|
||||
|
||||
const locale = defineLocale({
|
||||
const locale = defineLocale<Messages>({
|
||||
name: 'My custom locale',
|
||||
code: 'en',
|
||||
dir: 'ltr',
|
||||
@@ -56,6 +89,36 @@ const locale = defineLocale({
|
||||
</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:
|
||||
|
||||
@@ -131,6 +194,11 @@ 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'
|
||||
@@ -146,6 +214,29 @@ 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
|
||||
@@ -154,6 +245,11 @@ 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'
|
||||
@@ -181,6 +277,41 @@ 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
|
||||
|
||||
@@ -55,6 +55,7 @@ export default defineNuxtConfig({
|
||||
}]
|
||||
},
|
||||
rootAttrs: {
|
||||
// @ts-expect-error - vaul-drawer-wrapper is not typed
|
||||
'vaul-drawer-wrapper': '',
|
||||
'class': 'bg-(--ui-bg)'
|
||||
}
|
||||
|
||||
@@ -4,25 +4,25 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@iconify-json/logos": "^1.2.4",
|
||||
"@iconify-json/lucide": "^1.2.28",
|
||||
"@iconify-json/simple-icons": "^1.2.27",
|
||||
"@iconify-json/lucide": "^1.2.29",
|
||||
"@iconify-json/simple-icons": "^1.2.28",
|
||||
"@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@02b7ea0",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@a2768ed",
|
||||
"@nuxthub/core": "^0.8.18",
|
||||
"@nuxtjs/plausible": "^1.2.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"@rollup/plugin-yaml": "^4.1.2",
|
||||
"@vueuse/nuxt": "^12.8.2",
|
||||
"@vueuse/nuxt": "^13.0.0",
|
||||
"joi": "^17.13.3",
|
||||
"motion": "^12.4.10",
|
||||
"motion-v": "0.11.1",
|
||||
"nuxt": "^3.15.4",
|
||||
"motion": "^12.5.0",
|
||||
"motion-v": "0.11.3",
|
||||
"nuxt": "^3.16.0",
|
||||
"nuxt-component-meta": "^0.10.0",
|
||||
"nuxt-llms": "^0.1.0",
|
||||
"nuxt-og-image": "^4.2.0",
|
||||
"nuxt-og-image": "^5.0.2",
|
||||
"prettier": "^3.5.3",
|
||||
"shiki-transformer-color-highlight": "^1.0.0",
|
||||
"superstruct": "^2.0.2",
|
||||
|
||||
47
package.json
47
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
|
||||
"version": "3.0.0-beta.2",
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"version": "3.0.0-beta.4",
|
||||
"packageManager": "pnpm@10.6.2",
|
||||
"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": "nuxi build docs",
|
||||
"docs:build": "NODE_OPTIONS='--max-old-space-size=8192' nuxi build docs",
|
||||
"docs:prepare": "nuxt-component-meta docs",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
@@ -81,17 +81,17 @@
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@internationalized/date": "^3.7.0",
|
||||
"@internationalized/number": "^3.6.0",
|
||||
"@nuxt/fonts": "^0.10.3",
|
||||
"@nuxt/icon": "^1.10.3",
|
||||
"@nuxt/kit": "^3.15.4",
|
||||
"@nuxt/schema": "^3.15.4",
|
||||
"@nuxt/fonts": "^0.11.0",
|
||||
"@nuxt/icon": "^1.11.0",
|
||||
"@nuxt/kit": "^3.16.0",
|
||||
"@nuxt/schema": "^3.16.0",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@tailwindcss/postcss": "^4.0.12",
|
||||
"@tailwindcss/vite": "^4.0.12",
|
||||
"@tailwindcss/postcss": "^4.0.13",
|
||||
"@tailwindcss/vite": "^4.0.13",
|
||||
"@tanstack/vue-table": "^8.21.2",
|
||||
"@unhead/vue": "^1.11.20",
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"@vueuse/integrations": "^12.8.2",
|
||||
"@unhead/vue": "^2.0.0-rc.10",
|
||||
"@vueuse/core": "^13.0.0",
|
||||
"@vueuse/integrations": "^13.0.0",
|
||||
"colortranslator": "^4.1.0",
|
||||
"consola": "^3.4.0",
|
||||
"defu": "^6.1.4",
|
||||
@@ -110,26 +110,28 @@
|
||||
"pathe": "^2.0.3",
|
||||
"reka-ui": "^2.0.2",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-variants": "^0.3.1",
|
||||
"tailwindcss": "^4.0.12",
|
||||
"tailwind-variants": "^1.0.0",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"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"
|
||||
"vaul-vue": "^0.3.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint-config": "^1.1.0",
|
||||
"@nuxt/eslint-config": "^1.2.0",
|
||||
"@nuxt/module-builder": "^0.8.4",
|
||||
"@nuxt/test-utils": "^3.17.1",
|
||||
"@nuxt/test-utils": "^3.17.2",
|
||||
"@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.21.0",
|
||||
"happy-dom": "^17.1.2",
|
||||
"eslint": "^9.22.0",
|
||||
"happy-dom": "^17.4.4",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.15.4",
|
||||
"nuxt": "^3.16.0",
|
||||
"release-it": "^18.1.2",
|
||||
"superstruct": "^2.0.2",
|
||||
"valibot": "^0.42.1",
|
||||
@@ -146,12 +148,9 @@
|
||||
"@nuxt/ui": "workspace:*",
|
||||
"chokidar": "3.6.0",
|
||||
"debug": "4.3.7",
|
||||
"happy-dom": "17.1.2",
|
||||
"rollup": "4.32.1",
|
||||
"rollup": "4.34.9",
|
||||
"typescript": "5.6.3",
|
||||
"unimport": "3.14.5",
|
||||
"unplugin": "^2.2.0",
|
||||
"vue": "3.5.13",
|
||||
"vue-tsc": "2.2.0"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
<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</title>
|
||||
<title>Nuxt UI - Vue Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" class="isolate"></div>
|
||||
|
||||
8
playground-vue/public/logo.svg
Normal file
8
playground-vue/public/logo.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 316 B |
@@ -8,10 +8,10 @@
|
||||
"generate": "nuxi generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify-json/lucide": "^1.2.28",
|
||||
"@iconify-json/simple-icons": "^1.2.27",
|
||||
"@iconify-json/lucide": "^1.2.29",
|
||||
"@iconify-json/simple-icons": "^1.2.28",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxthub/core": "^0.8.18",
|
||||
"nuxt": "^3.15.4"
|
||||
"nuxt": "^3.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
3418
pnpm-lock.yaml
generated
3418
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -6,10 +6,10 @@
|
||||
"enabled": true
|
||||
},
|
||||
"ignoreDeps": [
|
||||
"happy-dom",
|
||||
"valibot30",
|
||||
"valibot31",
|
||||
"typescript",
|
||||
"vaul-vue",
|
||||
"vue-tsc"
|
||||
],
|
||||
"baseBranches": ["dev", "v3"],
|
||||
|
||||
@@ -53,7 +53,7 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
name: 'ui',
|
||||
configKey: 'ui',
|
||||
compatibility: {
|
||||
nuxt: '>=3.13.1'
|
||||
nuxt: '>=3.16.0'
|
||||
},
|
||||
docs: 'https://ui3.nuxt.dev/getting-started/installation/nuxt'
|
||||
},
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { ConfigProviderProps, TooltipProviderProps } from 'reka-ui'
|
||||
import { localeContextInjectionKey } from '../composables/useLocale'
|
||||
import type { ToasterProps, Locale } from '../types'
|
||||
import type { ToasterProps, Locale, Messages } from '../types'
|
||||
|
||||
export interface AppProps extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
|
||||
export interface AppProps<T extends Messages = Messages> extends Omit<ConfigProviderProps, 'useId' | 'dir' | 'locale'> {
|
||||
tooltip?: TooltipProviderProps
|
||||
toaster?: ToasterProps | null
|
||||
locale?: Locale
|
||||
locale?: Locale<T>
|
||||
}
|
||||
|
||||
export interface AppSlots {
|
||||
@@ -18,14 +17,15 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" generic="T extends Messages = Messages">
|
||||
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>()
|
||||
const props = defineProps<AppProps<T>>()
|
||||
defineSlots<AppSlots>()
|
||||
|
||||
const configProviderProps = useForwardProps(reactivePick(props, 'scrollBody'))
|
||||
|
||||
@@ -60,6 +60,7 @@ 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,
|
||||
|
||||
@@ -29,7 +29,7 @@ export interface FormEmits<T extends object> {
|
||||
}
|
||||
|
||||
export interface FormSlots {
|
||||
default(props?: {}): any
|
||||
default(props?: { errors: FormError[] }): 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)) {
|
||||
} else if (props.validateOn?.includes(event.type) && !loading.value) {
|
||||
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: inputs.value[err.name]?.id
|
||||
id: err?.name ? inputs.value[err.name]?.id : undefined
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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 />
|
||||
<slot :errors="errors" />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
@@ -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 === props.name || (props.errorPattern && error.name.match(props.errorPattern)))?.message)
|
||||
const error = computed(() => props.error || formErrors?.value?.find(error => error.name && (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.
|
||||
|
||||
@@ -82,7 +82,7 @@ const props = withDefaults(defineProps<InputProps>(), {
|
||||
const emits = defineEmits<InputEmits>()
|
||||
const slots = defineSlots<InputSlots>()
|
||||
|
||||
const [modelValue, modelModifiers] = defineModel<string | number>()
|
||||
const [modelValue, modelModifiers] = defineModel<string | number | null>()
|
||||
|
||||
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,15 +111,19 @@ function autoFocus() {
|
||||
}
|
||||
|
||||
// Custom function to handle the v-model properties
|
||||
function updateInput(value: string) {
|
||||
function updateInput(value: string | null) {
|
||||
if (modelModifiers.trim) {
|
||||
value = value.trim()
|
||||
value = value?.trim() ?? null
|
||||
}
|
||||
|
||||
if (modelModifiers.number || props.type === 'number') {
|
||||
value = looseToNumber(value)
|
||||
}
|
||||
|
||||
if (modelModifiers.nullify) {
|
||||
value ||= null
|
||||
}
|
||||
|
||||
modelValue.value = value
|
||||
emitFormInput()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { LinkProps } from '../types'
|
||||
|
||||
export interface LinkBaseProps {
|
||||
as?: string
|
||||
type?: string
|
||||
@@ -6,8 +8,8 @@ export interface LinkBaseProps {
|
||||
onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
|
||||
href?: string
|
||||
navigate?: (e: MouseEvent) => void
|
||||
rel?: string
|
||||
target?: string
|
||||
target?: LinkProps['target']
|
||||
rel?: LinkProps['rel']
|
||||
isExternal?: boolean
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<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'
|
||||
@@ -78,7 +77,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) => RouteLocationRaw
|
||||
to?: (page: number) => ButtonProps['to']
|
||||
class?: any
|
||||
ui?: Partial<typeof pagination.slots>
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ const props = withDefaults(defineProps<TextareaProps>(), {
|
||||
defineSlots<TextareaSlots>()
|
||||
const emits = defineEmits<TextareaEmits>()
|
||||
|
||||
const [modelValue, modelModifiers] = defineModel<string | number>()
|
||||
const [modelValue, modelModifiers] = defineModel<string | number | null>()
|
||||
|
||||
const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<TextareaProps>(props, { deferInputValidation: true })
|
||||
|
||||
@@ -94,15 +94,19 @@ function autoFocus() {
|
||||
}
|
||||
|
||||
// Custom function to handle the v-model properties
|
||||
function updateInput(value: string) {
|
||||
function updateInput(value: string | null) {
|
||||
if (modelModifiers.trim) {
|
||||
value = value.trim()
|
||||
value = value?.trim() ?? null
|
||||
}
|
||||
|
||||
if (modelModifiers.number) {
|
||||
value = looseToNumber(value)
|
||||
}
|
||||
|
||||
if (modelModifiers.nullify) {
|
||||
value ||= null
|
||||
}
|
||||
|
||||
modelValue.value = value
|
||||
emitFormInput()
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { defu } from 'defu'
|
||||
import type { Locale, Direction, Messages } from '../types/locale'
|
||||
import type { Locale, Direction } from '../types/locale'
|
||||
|
||||
interface DefineLocaleOptions {
|
||||
interface DefineLocaleOptions<M> {
|
||||
name: string
|
||||
code: string
|
||||
dir?: Direction
|
||||
messages: Messages
|
||||
messages: M
|
||||
}
|
||||
|
||||
export function defineLocale(options: DefineLocaleOptions): Locale {
|
||||
return defu<DefineLocaleOptions, [{ dir: Direction }]>(options, { dir: 'ltr' })
|
||||
export function defineLocale<M>(options: DefineLocaleOptions<M>): Locale<M> {
|
||||
return defu<DefineLocaleOptions<M>, [{ dir: Direction }]>(options, { dir: 'ltr' })
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { computed, inject, ref } from 'vue'
|
||||
import { computed, inject, toRef } from 'vue'
|
||||
import type { InjectionKey, Ref } from 'vue'
|
||||
import type { Locale } from '../types/locale'
|
||||
import { createSharedComposable } from '@vueuse/core'
|
||||
import type { Locale, Messages } from '../types/locale'
|
||||
import { buildLocaleContext } from '../utils/locale'
|
||||
import en from '../locale/en'
|
||||
import { createSharedComposable } from '@vueuse/core'
|
||||
|
||||
export const localeContextInjectionKey: InjectionKey<Ref<Locale | undefined>> = Symbol('nuxt-ui.locale-context')
|
||||
export const localeContextInjectionKey: InjectionKey<Ref<Locale<unknown> | undefined>> = Symbol('nuxt-ui.locale-context')
|
||||
|
||||
const _useLocale = (localeOverrides?: Ref<Locale | undefined>) => {
|
||||
const locale = localeOverrides || inject(localeContextInjectionKey, ref())!
|
||||
const _useLocale = (localeOverrides?: Ref<Locale<Messages> | undefined>) => {
|
||||
const locale = localeOverrides || toRef(inject<Locale<Messages>>(localeContextInjectionKey))
|
||||
|
||||
return buildLocaleContext(computed(() => locale.value || en))
|
||||
return buildLocaleContext<Messages>(computed(() => locale.value || en))
|
||||
}
|
||||
|
||||
export const useLocale = createSharedComposable(_useLocale)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'العربية',
|
||||
code: 'ar',
|
||||
dir: 'rtl',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Azərbaycanca',
|
||||
code: 'az',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'বাংলা',
|
||||
code: 'bn',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Čeština',
|
||||
code: 'cs',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Danish',
|
||||
code: 'da',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Deutsch',
|
||||
code: 'de',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Ελληνικά',
|
||||
code: 'el',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'English',
|
||||
code: 'en',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Español',
|
||||
code: 'es',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Eesti',
|
||||
code: 'et',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'فارسی',
|
||||
code: 'fa-IR',
|
||||
dir: 'rtl',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Suomeksi',
|
||||
code: 'fi',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Français',
|
||||
code: 'fr',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Hebrew',
|
||||
code: 'he',
|
||||
dir: 'rtl',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Hindi',
|
||||
code: 'hi',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Magyar',
|
||||
code: 'hu',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Indonesia',
|
||||
code: 'id',
|
||||
messages: {
|
||||
|
||||
@@ -5,13 +5,15 @@ 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'
|
||||
@@ -31,4 +33,3 @@ 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'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Italiano',
|
||||
code: 'it',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: '日本語',
|
||||
code: 'ja',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'ភាសាខ្មែរ',
|
||||
code: 'km',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: '한국어',
|
||||
code: 'ko',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Norsk Bokmål',
|
||||
code: 'nb-NO',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Nederlands',
|
||||
code: 'nl',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Polski',
|
||||
code: 'pl',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Português',
|
||||
code: 'pt',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Português (Brasil)',
|
||||
code: 'pt-BR',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Русский',
|
||||
code: 'ru',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Slovenčina',
|
||||
code: 'sk',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Svenska',
|
||||
code: 'sv',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'ไทย',
|
||||
code: 'th',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Türkçe',
|
||||
code: 'tr',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Українська',
|
||||
code: 'uk',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Tiếng Việt',
|
||||
code: 'vi',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: '简体中文',
|
||||
code: 'zh-CN',
|
||||
messages: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale({
|
||||
export default defineLocale<Messages>({
|
||||
name: '繁體中文',
|
||||
code: 'zh-TW',
|
||||
messages: {
|
||||
|
||||
@@ -55,5 +55,7 @@ export default defineNuxtPlugin(() => {
|
||||
}]
|
||||
}
|
||||
|
||||
useHead(headData)
|
||||
if (!nuxtApp.isVue) {
|
||||
useHead(headData)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,9 @@ export type Messages = {
|
||||
|
||||
export type Direction = 'ltr' | 'rtl'
|
||||
|
||||
export type Locale = {
|
||||
export type Locale<M> = {
|
||||
name: string
|
||||
code: string
|
||||
dir: Direction
|
||||
messages: Messages
|
||||
messages: M
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
locale: Ref<Locale>
|
||||
export type LocaleContext<M> = {
|
||||
locale: Ref<Locale<M>>
|
||||
lang: Ref<string>
|
||||
dir: Ref<Direction>
|
||||
code: Ref<string>
|
||||
t: Translator
|
||||
}
|
||||
|
||||
export function buildTranslator(locale: MaybeRef<Locale>): Translator {
|
||||
export function buildTranslator<M>(locale: MaybeRef<Locale<M>>): Translator {
|
||||
return (path, option) => translate(path, option, unref(locale))
|
||||
}
|
||||
|
||||
export function translate(path: string, option: undefined | TranslatorOption, locale: Locale): string {
|
||||
export function translate<M>(path: string, option: undefined | TranslatorOption, locale: Locale<M>): string {
|
||||
const prop: string = get(locale, `messages.${path}`, path)
|
||||
|
||||
return prop.replace(
|
||||
@@ -27,11 +27,11 @@ export function translate(path: string, option: undefined | TranslatorOption, lo
|
||||
)
|
||||
}
|
||||
|
||||
export function buildLocaleContext(locale: MaybeRef<Locale>): LocaleContext {
|
||||
export function buildLocaleContext<M>(locale: MaybeRef<Locale<M>>): LocaleContext<M> {
|
||||
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)
|
||||
const localeRef = isRef(locale) ? locale : ref(locale) as Ref<Locale<M>>
|
||||
|
||||
return {
|
||||
lang,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { createHead, setHeadInjectionHandler } from '@unhead/vue'
|
||||
import { createHead } from '@unhead/vue/client'
|
||||
import type { Plugin } from 'vue'
|
||||
|
||||
export default {
|
||||
install() {
|
||||
setHeadInjectionHandler(() => createHead())
|
||||
install(app) {
|
||||
const head = createHead()
|
||||
app.use(head)
|
||||
}
|
||||
} satisfies Plugin
|
||||
|
||||
@@ -9,6 +9,7 @@ export { useHead } from '@unhead/vue'
|
||||
export { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export { defineShortcuts } from '../composables/defineShortcuts'
|
||||
export { defineLocale } from '../composables/defineLocale'
|
||||
export { useLocale } from '../composables/useLocale'
|
||||
|
||||
export const useColorMode = () => {
|
||||
@@ -60,6 +61,7 @@ export const useState = <T>(key: string, init: () => T): Ref<T> => {
|
||||
export function useNuxtApp() {
|
||||
return {
|
||||
isHydrating: true,
|
||||
isVue: true,
|
||||
payload: { serverRendered: false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,10 @@ type AppConfigUI = {
|
||||
|
||||
declare module '@nuxt/schema' {
|
||||
interface AppConfigInput {
|
||||
/**
|
||||
* Nuxt UI theme configuration
|
||||
* @see https://ui3.nuxt.dev/getting-started/theme#customize-theme
|
||||
*/
|
||||
ui?: AppConfigUI
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,8 @@ 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 .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }],
|
||||
['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }]
|
||||
])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => {
|
||||
const wrapper = mount(Input, {
|
||||
...options
|
||||
|
||||
@@ -35,7 +35,8 @@ 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 .lazy modifier', { props: { modelModifiers: { lazy: true } } }, { input: 'input', expected: 'input' }],
|
||||
['with .nullify modifier', { props: { modelModifiers: { nullify: true } } }, { input: '', expected: null }]
|
||||
])('%s works', async (_nameOrHtml: string, options: { props?: any, slots?: any }, spec: { input: any, expected: any }) => {
|
||||
const wrapper = mount(Textarea, {
|
||||
...options
|
||||
|
||||
@@ -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 [&>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>
|
||||
<div class="relative inline-flex items-center [&>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>
|
||||
<!--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)" 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) [&>mark]:text-(--ui-bg) [&>mark]:bg-(--ui-primary)">Add new file</span><span class="text-(--ui-text-dimmed) [&>mark]:text-(--ui-bg) [&>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)"><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) [&>mark]:text-(--ui-bg) [&>mark]:bg-(--ui-primary)">Add new file</span><span class="text-(--ui-text-dimmed) [&>mark]:text-(--ui-bg) [&>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) [&>mark]:text-(--ui-bg) [&>mark]:bg-(--ui-primary)">Add new folder</span><span class="text-(--ui-text-dimmed) [&>mark]:text-(--ui-bg) [&>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>
|
||||
|
||||
@@ -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="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
|
||||
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 default slot correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8">Default slot</div>"`;
|
||||
|
||||
@@ -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="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl"></div>"`;
|
||||
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 default slot correctly 1`] = `"<div class="max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8">Default slot</div>"`;
|
||||
|
||||
@@ -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="" aria-activedescendant="reka-combobox-item-v-0-0-3">
|
||||
"<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="">
|
||||
<!--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="" 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-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-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>
|
||||
|
||||
@@ -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="" aria-activedescendant="reka-combobox-item-v-0-0-3">
|
||||
<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="">
|
||||
<!--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="" 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-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-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>
|
||||
|
||||
@@ -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="" aria-valuenow="0"></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=""></div>
|
||||
<!----></span>"
|
||||
`;
|
||||
|
||||
|
||||
@@ -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="" aria-valuenow="0"></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=""></div>
|
||||
<!----></span>"
|
||||
`;
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
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,
|
||||
exclude: [...defaultExclude, './test/vue/**.spec.ts'],
|
||||
include: ['./test/components/**.spec.ts'],
|
||||
environment: 'nuxt',
|
||||
environmentOptions: {
|
||||
nuxt: {
|
||||
|
||||
@@ -9,6 +9,7 @@ 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'],
|
||||
|
||||
Reference in New Issue
Block a user