mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 12:39:35 +01:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05ab54d03a | ||
|
|
db83df5f5e | ||
|
|
a5168666b7 | ||
|
|
f30d45c79a | ||
|
|
31be5f656e | ||
|
|
0ef5f3b77b | ||
|
|
a0fec4e467 | ||
|
|
f401766e26 | ||
|
|
70f469b868 | ||
|
|
f92df1f661 | ||
|
|
16edbdf1f0 | ||
|
|
fe0bd83d11 | ||
|
|
8a26de230b | ||
|
|
65a6861b54 | ||
|
|
ecff9abc72 | ||
|
|
06bc7d3028 | ||
|
|
b2034ccc91 | ||
|
|
53cf1b4c14 | ||
|
|
0229b0fd46 | ||
|
|
302e04bd77 | ||
|
|
126ba2326f | ||
|
|
dfc27514ec | ||
|
|
26321c4857 | ||
|
|
5dec0e16e2 | ||
|
|
f4c417d9ef | ||
|
|
9046b9d679 | ||
|
|
99df056cad | ||
|
|
08bebcae48 | ||
|
|
764c41a0c6 | ||
|
|
2abcc24018 | ||
|
|
67f90f5f26 | ||
|
|
024fccf8bb | ||
|
|
edb0f0afc6 | ||
|
|
fd160339a6 | ||
|
|
2a023b9060 | ||
|
|
ab52830dc8 | ||
|
|
9a4bb34d7d | ||
|
|
02184b016a | ||
|
|
57efc78a3b | ||
|
|
dec2730aae | ||
|
|
c8ca604bdf | ||
|
|
ef86108f14 | ||
|
|
a1caac47c5 | ||
|
|
fad715d8df | ||
|
|
b0d0d926ab | ||
|
|
a8e6b74e38 | ||
|
|
177fb79cb4 | ||
|
|
175c7027a3 | ||
|
|
cc504b8a4b | ||
|
|
0897e9ef05 | ||
|
|
6588ae8669 | ||
|
|
0b41cebee4 | ||
|
|
e80cc1592f | ||
|
|
5d52af6292 | ||
|
|
5e62493321 | ||
|
|
37f8619c1a | ||
|
|
5376a835f7 | ||
|
|
f2ba755ba5 | ||
|
|
c8d712747f | ||
|
|
816cf50b37 | ||
|
|
3c60f70cab | ||
|
|
05758fa915 | ||
|
|
ce4b229264 | ||
|
|
09b4e9e282 | ||
|
|
50d68a636c | ||
|
|
7646c95c73 | ||
|
|
4c30baffe0 | ||
|
|
0b411936c4 | ||
|
|
047582c246 | ||
|
|
b00f1206f6 | ||
|
|
9ba5cfe70c | ||
|
|
ee9aca33fd | ||
|
|
8d29e50340 | ||
|
|
0ad18d0a7a |
4
.github/ISSUE_TEMPLATE/bug-report-v3.yml
vendored
4
.github/ISSUE_TEMPLATE/bug-report-v3.yml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before reporting a bug, please make sure that you have read through our [v3 documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
Before reporting a bug, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
@@ -37,7 +37,7 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
placeholder: v3.0.0-alpha.x
|
||||
placeholder: v3.0.0
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
Before reporting a bug, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
|
||||
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before requesting a feature, please make sure that you have read through our [v3 documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
Before requesting a feature, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before requesting a feature, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
Before requesting a feature, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/question-v3.yml
vendored
2
.github/ISSUE_TEMPLATE/question-v3.yml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before asking a question, please make sure that you have read through our [v3 documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
Before asking a question, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/question.yml
vendored
2
.github/ISSUE_TEMPLATE/question.yml
vendored
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before asking a question, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
Before asking a question, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
||||
142
.github/workflows/module.yml
vendored
142
.github/workflows/module.yml
vendored
@@ -63,3 +63,145 @@ jobs:
|
||||
|
||||
- name: Publish
|
||||
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
|
||||
|
||||
starter-nuxt:
|
||||
needs: build
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: nuxtlabs/nuxt-ui-starter
|
||||
|
||||
- name: Store commit SHA
|
||||
run: |
|
||||
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
|
||||
- name: Install latest nuxt/ui
|
||||
run: pnpm install https://pkg.pr.new/@nuxt/ui@${{ env.COMMIT_SHA }} --lockfile-only
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Typecheck
|
||||
run: pnpm run typecheck
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
starter-vue:
|
||||
needs: build
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: nuxtlabs/nuxt-ui-vue-starter
|
||||
|
||||
- name: Store commit SHA
|
||||
run: |
|
||||
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
|
||||
- name: Install latest nuxt/ui
|
||||
run: pnpm install https://pkg.pr.new/@nuxt/ui@${{ env.COMMIT_SHA }} --lockfile-only
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Typecheck
|
||||
run: pnpm run typecheck
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
# nuxt-ui-pro:
|
||||
# needs: build
|
||||
|
||||
# runs-on: ${{ matrix.os }}
|
||||
|
||||
# permissions:
|
||||
# contents: read
|
||||
# pull-requests: read
|
||||
|
||||
# strategy:
|
||||
# matrix:
|
||||
# os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
# node: [22]
|
||||
|
||||
# env:
|
||||
# NUXT_UI_PRO_LICENSE: ${{ secrets.NUXT_UI_PRO_LICENSE }}
|
||||
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v4
|
||||
# with:
|
||||
# repository: nuxt/ui-pro
|
||||
# token: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||
|
||||
# - name: Store commit SHA
|
||||
# run: |
|
||||
# echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
|
||||
|
||||
# - name: Install pnpm
|
||||
# uses: pnpm/action-setup@v4
|
||||
|
||||
# - name: Install node
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: 22
|
||||
# cache: pnpm
|
||||
|
||||
# - name: Install latest nuxt/ui
|
||||
# run: pnpm install https://pkg.pr.new/@nuxt/ui@${{ env.COMMIT_SHA }} --lockfile-only
|
||||
|
||||
# - name: Install dependencies
|
||||
# run: pnpm install
|
||||
|
||||
# - name: Prepare
|
||||
# run: pnpm run dev:prepare
|
||||
|
||||
# - name: Typecheck
|
||||
# run: pnpm run typecheck
|
||||
|
||||
# - name: Build
|
||||
# run: pnpm run build
|
||||
|
||||
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,5 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## [3.0.1](https://github.com/nuxt/ui/compare/v3.0.0...v3.0.1) (2025-03-21)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Form:** drop explicit support for `zod` and `valibot` (#3617)
|
||||
|
||||
### Features
|
||||
|
||||
* **components:** handle events in `content` prop ([5dec0e1](https://github.com/nuxt/ui/commit/5dec0e16e28549b8833aaab17a87fada63d6598c))
|
||||
* **locale:** add Catalan language ([#3550](https://github.com/nuxt/ui/issues/3550)) ([53cf1b4](https://github.com/nuxt/ui/commit/53cf1b4c14a2a0e076e1e77688852e6bd0a28a74))
|
||||
* **locale:** add Central Kurdish language ([#3566](https://github.com/nuxt/ui/issues/3566)) ([b2034cc](https://github.com/nuxt/ui/commit/b2034ccc91eec6a2842c6f83d159e5aa6fd5f2fd))
|
||||
* **locale:** add Romanian language ([#3587](https://github.com/nuxt/ui/issues/3587)) ([0229b0f](https://github.com/nuxt/ui/commit/0229b0fd4644a97db7eb3154c3c87a26634dcfbb))
|
||||
* **locale:** add Urdu language ([#3611](https://github.com/nuxt/ui/issues/3611)) ([126ba23](https://github.com/nuxt/ui/commit/126ba2326f8153e155e1013db92c6ee417117610))
|
||||
* **locale:** add Uzbek language ([#3548](https://github.com/nuxt/ui/issues/3548)) ([302e04b](https://github.com/nuxt/ui/commit/302e04bd77ae8b165046b264c8d23626e92f8fb5))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Calendar:** grey out days outside of displayed month ([#3639](https://github.com/nuxt/ui/issues/3639)) ([a516866](https://github.com/nuxt/ui/commit/a5168666b7dff08e714d57f497737e7a670f457c))
|
||||
* **ContextMenu/DropdownMenu:** remove `any` from `proxySlots` ([#3623](https://github.com/nuxt/ui/issues/3623)) ([764c41a](https://github.com/nuxt/ui/commit/764c41a0c60dd1c12d39a86af9f5f11b9e6cdc8c))
|
||||
* **Modal/Slideover/Toast:** prevent unnecessary close instantiation ([f4c417d](https://github.com/nuxt/ui/commit/f4c417d9ef5409b52084bdf9d8cbccee3139709f))
|
||||
* **module:** handle tailwindcss import without `theme(static)` ([#3630](https://github.com/nuxt/ui/issues/3630)) ([ecff9ab](https://github.com/nuxt/ui/commit/ecff9abc720bdda3a279d5bcfb7b477ff885f2e4))
|
||||
* **module:** mark functions used in exports as pure ([#3604](https://github.com/nuxt/ui/issues/3604)) ([57efc78](https://github.com/nuxt/ui/commit/57efc78a3b3fa4a54bcd13df47d570a18fba2bc4))
|
||||
* **RadioGroup:** handle `disabled` on items ([fe0bd83](https://github.com/nuxt/ui/commit/fe0bd83d11b0dfa53b58d423bc917f8e21d73444)), closes [nuxt/ui-pro#911](https://github.com/nuxt/ui-pro/issues/911)
|
||||
* **Table:** allow links to be opened when [@select](https://github.com/select) is used ([#3580](https://github.com/nuxt/ui/issues/3580)) ([e80cc15](https://github.com/nuxt/ui/commit/e80cc1592fb244dd7692486a4c1ca5b1c2008112))
|
||||
* **types:** add missing export for Icon ([#3568](https://github.com/nuxt/ui/issues/3568)) ([5e62493](https://github.com/nuxt/ui/commit/5e624933216db95cbfd1b8034b2eb0f13846ae55))
|
||||
* **unplugin:** include `@compodium/examples` in auto-imports paths ([#3585](https://github.com/nuxt/ui/issues/3585)) ([cc504b8](https://github.com/nuxt/ui/commit/cc504b8a4b69dd76b49659d5c206ef23dcb9e475))
|
||||
* **useLocale:** unique symbol to use in `@nuxt/ui-pro` ([#3603](https://github.com/nuxt/ui/issues/3603)) ([dec2730](https://github.com/nuxt/ui/commit/dec2730aaea1327434837cfa022ea04056757cbf))
|
||||
* **vue:** missing unhead context ([#3589](https://github.com/nuxt/ui/issues/3589)) ([0897e9e](https://github.com/nuxt/ui/commit/0897e9ef05fbee4f021f317bb7c2d0b7007f1b75))
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **Form:** drop explicit support for `zod` and `valibot` ([#3617](https://github.com/nuxt/ui/issues/3617)) ([9a4bb34](https://github.com/nuxt/ui/commit/9a4bb34d7d14add0a3199103f4b583e8307d1d6d))
|
||||
|
||||
## [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)
|
||||
|
||||
22
README.md
22
README.md
@@ -11,31 +11,31 @@
|
||||
[![License][license-src]][license-href]
|
||||
[![Nuxt][nuxt-src]][nuxt-href]
|
||||
|
||||
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.
|
||||
Nuxt UI harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Tailwind CSS](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.
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit https://ui3.nuxt.dev to explore the documentation.
|
||||
Visit https://ui.nuxt.com to explore the documentation.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui@next
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui@next
|
||||
yarn add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui@next
|
||||
npm install @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui@next
|
||||
bun add @nuxt/ui
|
||||
```
|
||||
|
||||
### Nuxt
|
||||
@@ -51,11 +51,11 @@ export default defineNuxtConfig({
|
||||
2. Import Tailwind CSS and Nuxt UI in your CSS:
|
||||
|
||||
```css [assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
```
|
||||
|
||||
Learn more in the [installation guide](https://ui3.nuxt.dev/getting-started/installation/nuxt).
|
||||
Learn more in the [installation guide](https://ui.nuxt.com/getting-started/installation/nuxt).
|
||||
|
||||
### Vue
|
||||
|
||||
@@ -98,11 +98,11 @@ app.mount('#app')
|
||||
3. Import Tailwind CSS and Nuxt UI in your CSS:
|
||||
|
||||
```css [assets/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
```
|
||||
|
||||
Learn more in the [installation guide](https://ui3.nuxt.dev/getting-started/installation/vue).
|
||||
Learn more in the [installation guide](https://ui.nuxt.com/getting-started/installation/vue).
|
||||
|
||||
## Credits
|
||||
|
||||
@@ -119,7 +119,7 @@ Learn more in the [installation guide](https://ui3.nuxt.dev/getting-started/inst
|
||||
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/v3/LICENSE.md).
|
||||
|
||||
<!-- Badges -->
|
||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/next.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
[npm-version-href]: https://npmjs.com/package/@nuxt/ui
|
||||
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/@nuxt/ui.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"citty": "^0.1.6",
|
||||
"consola": "^3.4.0",
|
||||
"consola": "^3.4.2",
|
||||
"pathe": "^2.0.3",
|
||||
"scule": "^1.3.0"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
// import { withoutTrailingSlash } from 'ufo'
|
||||
import { withoutTrailingSlash } from 'ufo'
|
||||
import colors from 'tailwindcss/colors'
|
||||
// import { debounce } from 'perfect-debounce'
|
||||
|
||||
const route = useRoute()
|
||||
const appConfig = useAppConfig()
|
||||
@@ -12,16 +11,6 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
|
||||
server: false
|
||||
})
|
||||
|
||||
const searchTerm = ref('')
|
||||
|
||||
// watch(searchTerm, debounce((query: string) => {
|
||||
// if (!query) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// useTrackEvent('Search', { props: { query: `${query} - ${searchTerm.value?.commandPaletteRef.results.length} results` } })
|
||||
// }, 500))
|
||||
|
||||
const links = useLinks()
|
||||
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
|
||||
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
|
||||
@@ -33,8 +22,8 @@ useHead({
|
||||
{ key: 'theme-color', name: 'theme-color', content: color }
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
|
||||
// { rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
||||
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||
],
|
||||
style: [
|
||||
{ innerHTML: radius, id: 'nuxt-ui-radius', tagPriority: -2 },
|
||||
@@ -61,7 +50,7 @@ provide('navigation', mappedNavigation)
|
||||
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
|
||||
|
||||
<template v-if="!route.path.startsWith('/examples')">
|
||||
<!-- <Banner /> -->
|
||||
<Banner />
|
||||
|
||||
<Header :links="links" />
|
||||
</template>
|
||||
@@ -75,7 +64,6 @@ provide('navigation', mappedNavigation)
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUContentSearch
|
||||
v-model:search-term="searchTerm"
|
||||
:files="files"
|
||||
:groups="[{
|
||||
id: 'framework',
|
||||
@@ -95,5 +83,5 @@ provide('navigation', mappedNavigation)
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* Safelist (do not remove): [&>div]:*:my-0 [&>div]:*:w-full h-64 !px-0 !py-0 !pt-0 !pb-0 !p-0 !justify-start !min-h-96 h-136 */
|
||||
/* Safelist (do not remove): [&>div]:*:my-0 [&>div]:*:w-full h-64 !px-0 !py-0 !pt-0 !pb-0 !p-0 !justify-start !justify-end !min-h-96 h-136 */
|
||||
</style>
|
||||
|
||||
50
docs/app/components/AdsCarbon.vue
Normal file
50
docs/app/components/AdsCarbon.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
const el = ref<HTMLDivElement | null>(null)
|
||||
|
||||
onMounted(() => {
|
||||
if (!el.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const script = document.createElement('script')
|
||||
script.setAttribute('type', 'text/javascript')
|
||||
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CWYIVK3E&placement=uinuxtcom')
|
||||
script.setAttribute('id', '_carbonads_js')
|
||||
|
||||
el.value?.appendChild(script)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="el" class="carbon" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@reference "../assets/css/main.css";
|
||||
|
||||
.carbon :deep(#carbonads) {
|
||||
@apply relative border border-(--ui-border) rounded-[calc(var(--ui-radius)*1.5)] hover:bg-(--ui-bg-elevated)/50 w-full transition-colors min-h-[220px] p-2;
|
||||
|
||||
.carbon-img {
|
||||
@apply flex justify-center w-full;
|
||||
|
||||
& > img {
|
||||
@apply !max-w-full w-full rounded-(--ui-radius);
|
||||
}
|
||||
}
|
||||
|
||||
.carbon-text {
|
||||
@apply text-sm text-(--ui-text-muted) transition-colors text-center text-pretty flex pt-2;
|
||||
}
|
||||
|
||||
.carbon-poweredby {
|
||||
@apply block text-[10px] text-center text-(--ui-text-dimmed) pt-2;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.carbon-text {
|
||||
@apply text-(--ui-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,18 @@
|
||||
<template>
|
||||
<UBanner icon="i-lucide-construction" :actions="[{ label: 'Go to Nuxt UI v2', to: 'https://ui.nuxt.com', trailingIcon: 'i-lucide-arrow-right' }]" :close="false">
|
||||
<UBanner
|
||||
id="ui3-launch"
|
||||
icon="i-lucide-rocket"
|
||||
:actions="[
|
||||
{
|
||||
label: 'Discover Nuxt UI Pro',
|
||||
to: '/pro/pricing',
|
||||
trailingIcon: 'i-lucide-arrow-right'
|
||||
}
|
||||
]"
|
||||
close
|
||||
>
|
||||
<template #title>
|
||||
You're looking at the documentation for <span class="font-semibold">Nuxt UI v3</span>!
|
||||
<span class="font-semibold">Nuxt UI v3</span> is officially released.
|
||||
</template>
|
||||
</UBanner>
|
||||
</template>
|
||||
|
||||
51
docs/app/components/Countdown.vue
Normal file
51
docs/app/components/Countdown.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
const endDate = new Date('2025-03-14T23:59:59Z')
|
||||
const second = 1000
|
||||
const minute = second * 60
|
||||
const hour = minute * 60
|
||||
const day = hour * 24
|
||||
|
||||
function getCountdown() {
|
||||
const distance = Math.floor((endDate.getTime() - Date.now()))
|
||||
return {
|
||||
day: Math.floor(distance / day),
|
||||
hour: Math.floor((distance % (day)) / (hour)),
|
||||
minute: Math.floor((distance % (hour)) / (minute)),
|
||||
second: Math.floor((distance % (minute)) / (second)),
|
||||
distance
|
||||
}
|
||||
}
|
||||
const countdown = ref(getCountdown())
|
||||
let interval: any
|
||||
if (countdown.value.distance > 0) {
|
||||
onMounted(() => {
|
||||
interval = setInterval(() => {
|
||||
countdown.value = getCountdown()
|
||||
if (countdown.value.distance <= 0) {
|
||||
clearInterval(interval)
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
const plural = (value: number) => (value === 1 ? '' : 's')
|
||||
const double = (value: number) => (value < 10 ? `0${value}` : value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p class="font-semibold text-gray-900 dark:text-white text-sm mb-3">
|
||||
Nuxt UI v3 launch offer ends in:
|
||||
</p>
|
||||
|
||||
<div class="flex items-center justify-center gap-2 text-center">
|
||||
<template v-for="(value, key) in countdown" :key="key">
|
||||
<div v-if="key !== 'distance'" class="flex flex-col items-center gap-2">
|
||||
<UBadge color="primary" class="w-14 h-14 font-bold text-2xl flex items-center justify-center tabular-nums" variant="subtle">
|
||||
{{ double(value) }}
|
||||
</UBadge>
|
||||
<span class="text-[10px] font-semibold text-gray-900 dark:text-white tracking-wide tabular-nums uppercase">{{ key }}{{ plural(value) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -41,7 +41,7 @@ const mobileLinks = computed(() => props.links.map(link => ({ ...link, defaultOp
|
||||
<UDropdownMenu
|
||||
v-slot="{ open }"
|
||||
:modal="false"
|
||||
:items="[{ label: `v${config.version}`, active: true, color: 'primary', checked: true, type: 'checkbox' }, { label: module === 'ui-pro' ? 'v1.5' : 'v2.19', to: module === 'ui-pro' ? 'https://ui.nuxt.com/pro' : 'https://ui.nuxt.com' }]"
|
||||
:items="[{ label: `v${config.version}`, active: true, color: 'primary', checked: true, type: 'checkbox' }, { label: module === 'ui-pro' ? 'v1.7.1' : 'v2.21.1', to: module === 'ui-pro' ? 'https://ui2.nuxt.com/pro' : 'https://ui2.nuxt.com' }]"
|
||||
:ui="{ content: 'w-(--reka-dropdown-menu-trigger-width) min-w-0' }"
|
||||
size="xs"
|
||||
>
|
||||
@@ -82,7 +82,7 @@ const mobileLinks = computed(() => props.links.map(link => ({ ...link, defaultOp
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<UNavigationMenu orientation="vertical" :items="mobileLinks" class="-mx-2.5" default-open />
|
||||
<UNavigationMenu orientation="vertical" :items="mobileLinks" class="-mx-2.5" />
|
||||
|
||||
<USeparator type="dashed" class="mt-4 mb-6" />
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { kebabCase } from 'scule'
|
||||
|
||||
interface Star {
|
||||
x: number
|
||||
y: number
|
||||
@@ -22,6 +24,8 @@ const props = withDefaults(defineProps<{
|
||||
speed: 'normal'
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
// Generate random stars
|
||||
const generateStars = (count: number): Star[] => {
|
||||
return Array.from({ length: count }, () => {
|
||||
@@ -35,7 +39,7 @@ const generateStars = (count: number): Star[] => {
|
||||
}
|
||||
|
||||
// Generate all stars
|
||||
const stars = ref<Star[]>(generateStars(props.starCount))
|
||||
const stars = useState<Star[]>(`${kebabCase(route.path)}-sky`, () => generateStars(props.starCount))
|
||||
|
||||
// Compute twinkle animation duration based on speed
|
||||
const twinkleDuration = computed(() => {
|
||||
@@ -50,22 +54,20 @@ const twinkleDuration = computed(() => {
|
||||
|
||||
<template>
|
||||
<div class="absolute pointer-events-none z-[-1] inset-y-0 left-4 right-4 lg:right-[50%] overflow-hidden">
|
||||
<ClientOnly>
|
||||
<div
|
||||
v-for="star in stars"
|
||||
:key="star.id"
|
||||
class="star absolute"
|
||||
:style="{
|
||||
'left': `${star.x}%`,
|
||||
'top': `${star.y}%`,
|
||||
'transform': 'translate(-50%, -50%)',
|
||||
'--star-size': `${star.size}px`,
|
||||
'--star-color': color,
|
||||
'--twinkle-delay': `${star.twinkleDelay}s`,
|
||||
'--twinkle-duration': twinkleDuration
|
||||
}"
|
||||
/>
|
||||
</ClientOnly>
|
||||
<div
|
||||
v-for="star in stars"
|
||||
:key="star.id"
|
||||
class="star absolute"
|
||||
:style="{
|
||||
'left': `${star.x}%`,
|
||||
'top': `${star.y}%`,
|
||||
'transform': 'translate(-50%, -50%)',
|
||||
'--star-size': `${star.size}px`,
|
||||
'--star-color': color,
|
||||
'--twinkle-delay': `${star.twinkleDelay}s`,
|
||||
'--twinkle-duration': twinkleDuration
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { kebabCase } from 'scule'
|
||||
|
||||
interface Star {
|
||||
x: number
|
||||
y: number
|
||||
size: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
starCount?: number
|
||||
color?: string
|
||||
@@ -14,8 +22,10 @@ const props = withDefaults(defineProps<{
|
||||
})
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
// Generate random star positions and sizes
|
||||
const generateStars = (count: number) => {
|
||||
const generateStars = (count: number): Star[] => {
|
||||
return Array.from({ length: count }, () => ({
|
||||
x: Math.floor(Math.random() * 2000),
|
||||
y: Math.floor(Math.random() * 2000),
|
||||
@@ -25,52 +35,58 @@ const generateStars = (count: number) => {
|
||||
}))
|
||||
}
|
||||
|
||||
// Compute star layers with different speeds and opacities
|
||||
const starLayers = computed(() => {
|
||||
const speedMap = {
|
||||
slow: { duration: 200, opacity: 0.5 },
|
||||
normal: { duration: 150, opacity: 0.75 },
|
||||
fast: { duration: 100, opacity: 1 }
|
||||
}
|
||||
// Define speed configurations once
|
||||
const speedMap = {
|
||||
slow: { duration: 200, opacity: 0.5, ratio: 0.3 },
|
||||
normal: { duration: 150, opacity: 0.75, ratio: 0.3 },
|
||||
fast: { duration: 100, opacity: 1, ratio: 0.4 }
|
||||
}
|
||||
|
||||
return [
|
||||
{ stars: generateStars(props.starCount), ...speedMap.fast },
|
||||
{ stars: generateStars(Math.floor(props.starCount * 0.6)), ...speedMap.normal },
|
||||
{ stars: generateStars(Math.floor(props.starCount * 0.3)), ...speedMap.slow }
|
||||
]
|
||||
// Use a more efficient approach to generate and store stars
|
||||
const stars = useState<{ slow: Star[], normal: Star[], fast: Star[] }>(`${kebabCase(route.path)}-stars`, () => {
|
||||
return {
|
||||
slow: generateStars(Math.floor(props.starCount * speedMap.slow.ratio)),
|
||||
normal: generateStars(Math.floor(props.starCount * speedMap.normal.ratio)),
|
||||
fast: generateStars(Math.floor(props.starCount * speedMap.fast.ratio))
|
||||
}
|
||||
})
|
||||
|
||||
// Compute star layers with different speeds and opacities
|
||||
const starLayers = computed(() => [
|
||||
{ stars: stars.value.fast, ...speedMap.fast },
|
||||
{ stars: stars.value.normal, ...speedMap.normal },
|
||||
{ stars: stars.value.slow, ...speedMap.slow }
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="absolute pointer-events-none z-[-1] inset-y-0 inset-x-5 sm:inset-x-7 lg:inset-x-9 overflow-hidden">
|
||||
<ClientOnly>
|
||||
<div class="stars size-full absolute inset-x-0 top-0">
|
||||
<div class="stars size-full absolute inset-x-0 top-0">
|
||||
<div
|
||||
v-for="(layer, index) in starLayers"
|
||||
:key="index"
|
||||
class="star-layer"
|
||||
:style="{
|
||||
'--star-duration': `${layer.duration}s`,
|
||||
'--star-opacity': layer.opacity,
|
||||
'--star-color': color
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-for="(layer, index) in starLayers"
|
||||
:key="index"
|
||||
class="star-layer"
|
||||
v-for="(star, starIndex) in layer.stars"
|
||||
:key="starIndex"
|
||||
class="star absolute rounded-full"
|
||||
:style="{
|
||||
'--star-duration': `${layer.duration}s`,
|
||||
'--star-opacity': layer.opacity,
|
||||
'--star-color': color
|
||||
left: `${star.x}px`,
|
||||
top: `${star.y}px`,
|
||||
width: `${star.size}px`,
|
||||
height: `${star.size}px`,
|
||||
backgroundColor: 'var(--star-color)',
|
||||
opacity: 'var(--star-opacity)'
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-for="(star, starIndex) in layer.stars"
|
||||
:key="starIndex"
|
||||
class="star absolute rounded-full"
|
||||
:style="{
|
||||
left: `${star.x}px`,
|
||||
top: `${star.y}px`,
|
||||
width: `${star.size}px`,
|
||||
height: `${star.size}px`,
|
||||
backgroundColor: 'var(--star-color)',
|
||||
opacity: 'var(--star-opacity)'
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@ function getEmojiFlag(locale: string): string {
|
||||
const languageToCountry: Record<string, string> = {
|
||||
ar: 'sa', // Arabic -> Saudi Arabia
|
||||
bn: 'bd', // Bengali -> Bangladesh
|
||||
ca: 'es', // Catalan -> Spain
|
||||
cs: 'cz', // Czech -> Czech Republic (note: modern country code is actually 'cz')
|
||||
ckb: 'iq', // Central Kurdish -> Iraq
|
||||
da: 'dk', // Danish -> Denmark
|
||||
el: 'gr', // Greek -> Greece
|
||||
et: 'ee', // Estonian -> Estonia
|
||||
@@ -24,6 +26,7 @@ function getEmojiFlag(locale: string): string {
|
||||
nb: 'no', // Norwegian Bokmål -> Norway
|
||||
sv: 'se', // Swedish -> Sweden
|
||||
uk: 'ua', // Ukrainian -> Ukraine
|
||||
ur: 'pk', // Urdu -> Pakistan
|
||||
vi: 'vn' // Vietnamese -> Vietnam
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UFormField label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormField>
|
||||
|
||||
@@ -3,7 +3,7 @@ withDefaults(defineProps<{
|
||||
title: string
|
||||
description: string
|
||||
component: string
|
||||
module: string
|
||||
module?: string
|
||||
}>(), {
|
||||
module: ''
|
||||
})
|
||||
|
||||
@@ -3,8 +3,8 @@ withDefaults(defineProps<{
|
||||
title: string
|
||||
description: string
|
||||
headline: string
|
||||
framework: string
|
||||
module: string
|
||||
framework?: string
|
||||
module?: string
|
||||
}>(), {
|
||||
framework: 'nuxt',
|
||||
module: ''
|
||||
|
||||
@@ -81,7 +81,6 @@ function setBlackAsPrimary(value: boolean) {
|
||||
|
||||
<div class="grid grid-cols-3 gap-1 -mx-2">
|
||||
<ThemePickerButton
|
||||
chip="primary"
|
||||
label="Black"
|
||||
:selected="appConfig.theme.blackAsPrimary"
|
||||
@click="setBlackAsPrimary(true)"
|
||||
@@ -90,6 +89,7 @@ function setBlackAsPrimary(value: boolean) {
|
||||
<span class="inline-block w-2 h-2 rounded-full bg-black dark:bg-white" />
|
||||
</template>
|
||||
</ThemePickerButton>
|
||||
|
||||
<ThemePickerButton
|
||||
v-for="color in primaryColors"
|
||||
:key="color"
|
||||
|
||||
@@ -5,6 +5,10 @@ defineProps<{
|
||||
chip?: string
|
||||
selected?: boolean
|
||||
}>()
|
||||
|
||||
const slots = defineSlots<{
|
||||
leading: () => any
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -17,7 +21,7 @@ defineProps<{
|
||||
class="capitalize ring-(--ui-border) rounded-[calc(var(--ui-radius))] text-[11px]"
|
||||
:class="[selected ? 'bg-(--ui-bg-elevated)' : 'hover:bg-(--ui-bg-elevated)/50']"
|
||||
>
|
||||
<template v-if="chip" #leading>
|
||||
<template v-if="chip || !!slots.leading" #leading>
|
||||
<slot name="leading">
|
||||
<span
|
||||
class="inline-block size-2 rounded-full"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import colors from 'tailwindcss/colors'
|
||||
// import { debounce } from 'perfect-debounce'
|
||||
import type { NuxtError } from '#app'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -15,16 +14,6 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
|
||||
server: false
|
||||
})
|
||||
|
||||
const searchTerm = ref('')
|
||||
|
||||
// watch(searchTerm, debounce((query: string) => {
|
||||
// if (!query) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// useTrackEvent('Search', { props: { query: `${query} - ${searchTerm.value?.commandPaletteRef.results.length} results` } })
|
||||
// }, 500))
|
||||
|
||||
const links = useLinks()
|
||||
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
|
||||
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
|
||||
@@ -48,7 +37,7 @@ useHead({
|
||||
})
|
||||
|
||||
useSeoMeta({
|
||||
titleTemplate: '%s - Nuxt UI v3',
|
||||
titleTemplate: '%s - Nuxt UI',
|
||||
title: String(props.error.statusCode)
|
||||
})
|
||||
|
||||
@@ -67,17 +56,16 @@ provide('navigation', mappedNavigation)
|
||||
<UApp>
|
||||
<NuxtLoadingIndicator color="#FFF" />
|
||||
|
||||
<!-- <Banner /> -->
|
||||
<Banner />
|
||||
|
||||
<Header :links="links" />
|
||||
|
||||
<UError :error="error" />
|
||||
|
||||
<!-- <Footer /> -->
|
||||
<Footer />
|
||||
|
||||
<ClientOnly>
|
||||
<LazyUContentSearch
|
||||
v-model:search-term="searchTerm"
|
||||
:files="files"
|
||||
:groups="[{
|
||||
id: 'framework',
|
||||
|
||||
@@ -97,7 +97,7 @@ design_system:
|
||||
```
|
||||
|
||||
```css [main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
:root {
|
||||
|
||||
@@ -82,6 +82,8 @@ if (route.path.startsWith('/components')) {
|
||||
})
|
||||
} else {
|
||||
defineOgImageComponent('Docs', {
|
||||
title: page.value.title,
|
||||
description: page.value.description,
|
||||
headline: breadcrumb.value?.[breadcrumb.value.length - 1]?.label || 'Nuxt UI',
|
||||
framework: page.value?.framework,
|
||||
module: page.value.module
|
||||
@@ -107,23 +109,6 @@ const communityLinks = computed(() => [{
|
||||
icon: 'i-lucide-map',
|
||||
to: '/roadmap'
|
||||
}])
|
||||
|
||||
// const resourcesLinks = [{
|
||||
// icon: 'i-simple-icons-figma',
|
||||
// label: 'Figma Kit',
|
||||
// to: 'https://www.figma.com/community/file/1288455405058138934',
|
||||
// target: '_blank'
|
||||
// }, {
|
||||
// label: 'Playground',
|
||||
// icon: 'i-simple-icons-stackblitz',
|
||||
// to: 'https://stackblitz.com/edit/nuxt-ui',
|
||||
// target: '_blank'
|
||||
// }, {
|
||||
// icon: 'i-simple-icons-nuxtdotjs',
|
||||
// label: 'Nuxt docs',
|
||||
// to: 'https://nuxt.com',
|
||||
// target: '_blank'
|
||||
// }]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -172,14 +157,9 @@ const communityLinks = computed(() => [{
|
||||
|
||||
<UPageLinks title="Community" :links="communityLinks" />
|
||||
|
||||
<!-- <USeparator type="dashed" />
|
||||
|
||||
<UPageLinks title="Resources" :links="resourcesLinks" />
|
||||
|
||||
<USeparator type="dashed" />
|
||||
|
||||
<AdsPro />
|
||||
<AdsCarbon /> -->
|
||||
<AdsCarbon />
|
||||
</template>
|
||||
</UContentToc>
|
||||
</template>
|
||||
|
||||
@@ -119,7 +119,8 @@ onMounted(() => {
|
||||
/>
|
||||
</template>
|
||||
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
</UPageHero>
|
||||
|
||||
|
||||
@@ -178,6 +178,7 @@ pricing:
|
||||
- title: Solo License
|
||||
description: Design faster with all Nuxt UI Pro components.
|
||||
price: $149
|
||||
# discount: $119
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
class: bg-(--ui-bg-elevated)/50
|
||||
@@ -199,6 +200,7 @@ pricing:
|
||||
- title: Team License
|
||||
description: Everything you need to deliver faster as a team.
|
||||
price: $349
|
||||
# discount: $279
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
class: bg-(--ui-bg-elevated)/50
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// @ts-expect-error yaml is not typed
|
||||
import page from '.figma.yml'
|
||||
import { animate } from 'motion'
|
||||
import { animate } from 'motion-v'
|
||||
import { joinURL } from 'ufo'
|
||||
|
||||
const { url } = useSiteConfig()
|
||||
@@ -233,6 +233,7 @@ onMounted(async () => {
|
||||
:title="plan.title"
|
||||
:description="plan.description"
|
||||
:price="plan.price"
|
||||
:discount="plan.discount"
|
||||
:billing-period="plan.billing_period"
|
||||
:billing-cycle="plan.billing_cycle"
|
||||
:highlight="plan.highlight"
|
||||
|
||||
@@ -76,7 +76,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
:key="feature.title"
|
||||
as-child
|
||||
:initial="{ opacity: 0, transform: 'translateX(-10px)' }"
|
||||
:in-view="{ opacity: 1, transform: 'translateX(0)' }"
|
||||
:while-in-view="{ opacity: 1, transform: 'translateX(0)' }"
|
||||
:transition="{ delay: 0.2 + 0.4 * index }"
|
||||
:in-view-options="{ once: true }"
|
||||
>
|
||||
@@ -85,7 +85,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<SkyBg />
|
||||
<LazySkyBg />
|
||||
|
||||
<div class="h-[344px] lg:h-full lg:relative w-full lg:min-h-[calc(100vh-var(--ui-header-height)-1px)] overflow-hidden">
|
||||
<UPageMarquee
|
||||
@@ -93,7 +93,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
:overlay="false"
|
||||
:ui="{
|
||||
root: '[--gap:--spacing(4)] [--duration:40s] border-(--ui-border) absolute w-full left-0 border-y lg:border-x lg:border-y-0 lg:w-[calc(50%-6px)] 2xl:w-[320px] lg:flex-col',
|
||||
content: 'lg:w-auto lg:h-full lg:flex-col lg:animate-[marquee-vertical_var(--duration)_linear_infinite] lg:rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] lg:h-[fit-content]'
|
||||
content: 'lg:w-auto lg:flex-col lg:animate-[marquee-vertical_var(--duration)_linear_infinite] lg:rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] lg:h-[fit-content]'
|
||||
}"
|
||||
>
|
||||
<ULink
|
||||
@@ -118,7 +118,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
:overlay="false"
|
||||
:ui="{
|
||||
root: '[--gap:--spacing(4)] [--duration:40s] border-(--ui-border) absolute w-full mt-[180px] left-0 border-y lg:mt-auto lg:left-auto lg:border-y-0 lg:border-x lg:w-[calc(50%-6px)] 2xl:w-[320px] lg:right-0 lg:flex-col',
|
||||
content: 'lg:w-auto lg:h-full lg:flex-col lg:animate-[marquee-vertical_var(--duration)_linear_infinite] lg:rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] lg:h-[fit-content] lg:[animation-direction:reverse]'
|
||||
content: 'lg:w-auto lg:flex-col lg:animate-[marquee-vertical_var(--duration)_linear_infinite] lg:rtl:animate-[marquee-vertical-rtl_var(--duration)_linear_infinite] lg:h-[fit-content] lg:[animation-direction:reverse]'
|
||||
}"
|
||||
>
|
||||
<ULink
|
||||
@@ -147,7 +147,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
:key="feature.title"
|
||||
as="li"
|
||||
:initial="{ opacity: 0, transform: 'translateY(10px)' }"
|
||||
:in-view="{ opacity: 1, transform: 'translateY(0)' }"
|
||||
:while-in-view="{ opacity: 1, transform: 'translateY(0)' }"
|
||||
:transition="{ delay: 0.1 * index }"
|
||||
:in-view-options="{ once: true }"
|
||||
class="flex items-start gap-x-3 relative group"
|
||||
@@ -261,7 +261,7 @@ useIntersectionObserver(contributorsRef, ([entry]) => {
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
<div class="relative h-[400px] border border-(--ui-border) bg-(--ui-bg-muted) overflow-hidden border-x-0 -mx-4 sm:-mx-6 lg:mx-0 lg:border-x w-screen lg:w-full">
|
||||
|
||||
@@ -17,7 +17,10 @@ pricing:
|
||||
title: Figma Kit Pro
|
||||
description: Get all Nuxt UI Pro components in a Figma kit to design your next application before coding. Everything you need, from wire-framing to high-fidelity web integration.
|
||||
orientation: horizontal
|
||||
price: $149 - $349
|
||||
price: $149
|
||||
# discount: $119
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
terms: Solo & Team licenses available.
|
||||
features:
|
||||
- 1700+ components & variants from Nuxt UI & UI Pro
|
||||
@@ -36,6 +39,7 @@ pricing:
|
||||
- title: Solo
|
||||
description: Tailored for indie hackers, freelancers and solo founders.
|
||||
price: $249
|
||||
# discount: $199
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
features:
|
||||
@@ -50,6 +54,7 @@ pricing:
|
||||
- title: Startup
|
||||
description: Best suited for small teams, startups and agencies.
|
||||
price: $499
|
||||
# discount: $399
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
features:
|
||||
@@ -65,6 +70,7 @@ pricing:
|
||||
- title: Organization
|
||||
description: Ideal for larger teams and organizations.
|
||||
price: $999
|
||||
# discount: $799
|
||||
billing_period: one-time payment
|
||||
billing_cycle: plus local taxes
|
||||
features:
|
||||
@@ -174,7 +180,7 @@ testimonials:
|
||||
- quote: "Nuxt UI Pro is my preferred choice for everything, from a POC to a web platform. It's ready to use out-of-the-box and assists me in crafting pixel-perfect UIs. It saves me a significant amount of time while remaining highly customizable. Give it a try, and you won't be let down."
|
||||
user:
|
||||
name: 'Estéban Soubiran'
|
||||
description: 'Web developer and UnJS member'
|
||||
description: 'Software engineer'
|
||||
to: 'https://x.com/soubiran_'
|
||||
target: _blank
|
||||
avatar:
|
||||
|
||||
@@ -71,7 +71,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<UMain>
|
||||
<UPageHero headline="License Activation" :title="title" :description="description" :ui="{ container: 'relative overflow-hidden', wrapper: 'lg:px-12', description: 'text-pretty' }">
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
|
||||
<div class="px-4 py-10 lg:border border-(--ui-border) bg-(--ui-bg)">
|
||||
|
||||
@@ -32,7 +32,7 @@ useSeoMeta({
|
||||
<MDC :value="page.hero.description" tag="span" unwrap="p" cache-key="pro-hero-description" />
|
||||
</template>
|
||||
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<Motion as-child :initial="{ height: 0 }" :animate="{ height: 'auto' }" :transition="{ delay: 0.2, duration: 1 }">
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
@@ -82,11 +82,11 @@ useSeoMeta({
|
||||
}"
|
||||
>
|
||||
<template #description>
|
||||
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.2 }">
|
||||
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :while-in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.2 }">
|
||||
<MDC :value="page.testimonial.quote" tag="span" unwrap="p" class="before:content-[open-quote] after:content-[close-quote]" cache-key="pro-testimonial-quote" />
|
||||
</Motion>
|
||||
</template>
|
||||
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.3 }">
|
||||
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :while-in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.3 }">
|
||||
<UUser
|
||||
v-bind="page.testimonial.user"
|
||||
class="justify-center"
|
||||
@@ -103,7 +103,7 @@ useSeoMeta({
|
||||
}"
|
||||
class="border-t border-(--ui-border)"
|
||||
>
|
||||
<Motion as-child :initial="{ height: 0 }" :in-view="{ height: 'auto' }" :transition="{ delay: 0.4, duration: 1 }">
|
||||
<Motion as-child :initial="{ height: 0 }" :while-in-view="{ height: 'auto' }" :transition="{ delay: 0.4, duration: 1 }">
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
</Motion>
|
||||
</UPageSection>
|
||||
@@ -196,7 +196,7 @@ useSeoMeta({
|
||||
class="overflow-hidden"
|
||||
orientation="horizontal"
|
||||
>
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<video
|
||||
class="rounded-[var(--ui-radius)] z-10"
|
||||
|
||||
@@ -27,8 +27,10 @@ useSeoMeta({
|
||||
<MDC :value="page.pricing.title" unwrap="p" cache-key="pro-pricing-title" />
|
||||
</template>
|
||||
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
|
||||
<div class="flex flex-col bg-(--ui-bg) gap-8 lg:gap-0">
|
||||
<UPricingPlan
|
||||
v-bind="page.pricing.freePlan"
|
||||
@@ -42,6 +44,7 @@ useSeoMeta({
|
||||
:title="plan.title"
|
||||
:description="plan.description"
|
||||
:price="plan.price"
|
||||
:discount="plan.discount"
|
||||
:billing-period="plan.billing_period"
|
||||
:billing-cycle="plan.billing_cycle"
|
||||
:variant="plan.highlight ? 'soft' : 'outline'"
|
||||
@@ -53,6 +56,8 @@ useSeoMeta({
|
||||
<UPricingPlan
|
||||
v-bind="page.pricing.figma"
|
||||
variant="naked"
|
||||
:billing-period="page.pricing.figma.billing_period"
|
||||
:billing-cycle="page.pricing.figma.billing_cycle"
|
||||
class="lg:rounded-none border lg:border-y-0 border-(--ui-border)"
|
||||
>
|
||||
<template #features>
|
||||
|
||||
@@ -18,7 +18,8 @@ useSeoMeta({
|
||||
<template>
|
||||
<div class="relative">
|
||||
<UPageHero :links="page.links" :ui="{ container: 'relative' }">
|
||||
<StarsBg />
|
||||
<LazyStarsBg />
|
||||
|
||||
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||
|
||||
<template #title>
|
||||
@@ -50,7 +51,7 @@ useSeoMeta({
|
||||
</template>
|
||||
|
||||
<div class="lg:border-x border-(--ui-border) h-full flex items-center lg:bg-(--ui-bg-muted)/20">
|
||||
<Motion class="flex-1" :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0px)' }" :in-view-options="{ once: true }" :transition="{ duration: 0.5, delay: 0.2 }">
|
||||
<Motion class="flex-1" :initial="{ opacity: 0, transform: 'translateY(10px)' }" :while-in-view="{ opacity: 1, transform: 'translateY(0px)' }" :in-view-options="{ once: true }" :transition="{ duration: 0.5, delay: 0.2 }">
|
||||
<UColorModeImage
|
||||
v-if="template.thumbnail"
|
||||
v-bind="template.thumbnail"
|
||||
|
||||
@@ -3,7 +3,7 @@ const title = 'Roadmap'
|
||||
const description = 'Discover our Volta board for @nuxt/ui development status.'
|
||||
|
||||
useSeoMeta({
|
||||
titleTemplate: '%s - Nuxt UI v3',
|
||||
titleTemplate: '%s - Nuxt UI',
|
||||
title,
|
||||
ogTitle: 'Nuxt UI Roadmap',
|
||||
description
|
||||
|
||||
@@ -41,16 +41,16 @@ export default defineNuxtPlugin({
|
||||
const primaryColor = localStorage.getItem('nuxt-ui-primary');
|
||||
if (primaryColor !== 'black') {
|
||||
html = html.replace(
|
||||
/(--ui-color-primary-\\d{2,3}:\\s*var\\()--color-${appConfig.ui.colors.primary}-(\\d{2,3}\\))/g,
|
||||
\`$1--color-\${primaryColor}-$2\`
|
||||
/(--ui-color-primary-\\d{2,3}:\\s*var\\(--color-)${appConfig.ui.colors.primary}(-\\d{2,3}.*?\\))/g,
|
||||
\`$1\${primaryColor}$2\`
|
||||
);
|
||||
}
|
||||
}
|
||||
if (localStorage.getItem('nuxt-ui-neutral')) {
|
||||
let neutralColor = localStorage.getItem('nuxt-ui-neutral');
|
||||
html = html.replace(
|
||||
/(--ui-color-neutral-\\d{2,3}:\\s*var\\()--color-${appConfig.ui.colors.neutral}-(\\d{2,3}\\))/g,
|
||||
\`$1--color-\${neutralColor === 'neutral' ? 'old-neutral' : neutralColor}-$2\`
|
||||
/(--ui-color-neutral-\\d{2,3}:\\s*var\\(--color-)${appConfig.ui.colors.neutral}(-\\d{2,3}.*?\\))/g,
|
||||
\`$1\${neutralColor === 'neutral' ? 'old-neutral' : neutralColor}$2\`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
---
|
||||
navigation.title: Introduction
|
||||
title: Nuxt UI v3
|
||||
description: 'A comprehensive, Nuxt-integrated UI library providing a rich set of fully-styled, accessible and highly customizable components for building modern web applications.'
|
||||
title: Introduction
|
||||
description: 'Nuxt UI harnesses the combined strengths of Reka UI, Tailwind CSS, and Tailwind Variants to offer developers an unparalleled set of tools for creating sophisticated, accessible, and highly performant user interfaces.'
|
||||
navigation.icon: i-lucide-house
|
||||
---
|
||||
|
||||
We're thrilled to introduce this major update to our UI library, bringing significant improvements and powerful new features. Nuxt UI v3 represents a leap forward in creating robust, accessible, and highly customizable user interfaces for Nuxt applications.
|
||||
|
||||
## What's New in v3?
|
||||
|
||||
<iframe width="100%" height="100%" src="https://www.youtube-nocookie.com/embed/_eQxomah-nA?si=pDSzchUBDKb2NQu7" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="aspect-ratio: 16/9;" class="rounded-[calc(var(--ui-radius)*1.5)]"></iframe>
|
||||
|
||||
### Reka UI
|
||||
@@ -24,7 +19,7 @@ This transition empowers Nuxt UI to become a more comprehensive and flexible UI
|
||||
|
||||
### Tailwind CSS v4
|
||||
|
||||
Nuxt UI v3 integrates the latest Tailwind CSS v4, bringing significant improvements:
|
||||
Nuxt UI integrates the latest Tailwind CSS v4, bringing significant improvements:
|
||||
|
||||
- **Built for performance**: Full builds in the new engine are up to 5x faster, and incremental builds are over 100x faster — and measured in microseconds.
|
||||
- **Unified toolchain**: Built-in import handling, vendor prefixing, and syntax transforms, with no additional tooling required.
|
||||
@@ -47,7 +42,7 @@ This integration unifies the styling of components, ensuring consistency and cod
|
||||
|
||||
### TypeScript Integration
|
||||
|
||||
Nuxt UI v3 offers significantly improved TypeScript integration, providing a superior developer experience:
|
||||
Nuxt UI offers significantly improved TypeScript integration, providing a superior developer experience:
|
||||
|
||||
- **Enhanced Auto-completion**:
|
||||
- Full auto-completion for component props based on your theme
|
||||
@@ -112,11 +107,7 @@ Key points to consider:
|
||||
## FAQ
|
||||
|
||||
::accordion
|
||||
::accordion-item{label="What are the main considerations when upgrading to Nuxt UI v3?"}
|
||||
The transition to v3 involves significant changes, including new component structures, updated theming approaches, and revised TypeScript definitions. We recommend a careful, incremental upgrade process, starting with thorough testing in a development environment.
|
||||
::
|
||||
|
||||
::accordion-item{label="Is Nuxt UI v3 compatible with standalone Vue projects?"}
|
||||
::accordion-item{label="Is Nuxt UI compatible with standalone Vue projects?"}
|
||||
Nuxt UI is now compatible with Vue! You can follow the [installation guide](/getting-started/installation/vue) to get started.
|
||||
::
|
||||
|
||||
@@ -124,23 +115,19 @@ Key points to consider:
|
||||
We've also rebuilt Nuxt UI Pro from scratch as v3 to match Nuxt UI version. The license you bought or will buy is valid for both Nuxt UI Pro v1 and v3, this is a **free update**. You can follow the [installation guide](/getting-started/installation/pro/nuxt) to get started.
|
||||
::
|
||||
|
||||
::accordion-item{label="Will Nuxt UI v3 work with other CSS frameworks like UnoCSS?"}
|
||||
Nuxt UI v3 is currently designed to work exclusively with Tailwind CSS. While there's interest in UnoCSS support, implementing it would require significant changes to the theme structure due to differences in class naming conventions. As a result, we don't have plans to add UnoCSS support in v3.
|
||||
::accordion-item{label="Will Nuxt UI work with other CSS frameworks like UnoCSS?"}
|
||||
Nuxt UI is currently designed to work exclusively with Tailwind CSS. While there's interest in UnoCSS support, implementing it would require significant changes to the theme structure due to differences in class naming conventions. As a result, we don't have plans to add UnoCSS support.
|
||||
::
|
||||
|
||||
::accordion-item{label="How does Nuxt UI v3 handle accessibility?"}
|
||||
Nuxt UI v3 enhances accessibility through Reka UI integration. This provides automatic ARIA attributes, keyboard navigation support, intelligent focus management, and screen reader announcements. While offering a strong foundation, proper implementation and testing in your specific use case remains crucial for full accessibility compliance. For more detailed information, refer to [Reka UI's accessibility documentation](https://reka-ui.com/docs/overview/accessibility).
|
||||
::accordion-item{label="How does Nuxt UI handle accessibility?"}
|
||||
Nuxt UI enhances accessibility through Reka UI integration. This provides automatic ARIA attributes, keyboard navigation support, intelligent focus management, and screen reader announcements. While offering a strong foundation, proper implementation and testing in your specific use case remains crucial for full accessibility compliance. For more detailed information, refer to [Reka UI's accessibility documentation](https://reka-ui.com/docs/overview/accessibility).
|
||||
::
|
||||
|
||||
::accordion-item{label="What is the testing approach for Nuxt UI v3?"}
|
||||
Nuxt UI v3 ensures reliability with 1000+ Vitest tests, covering core functionality and accessibility. This robust testing suite supports the library's stability and serves as a reference for developers.
|
||||
::
|
||||
|
||||
::accordion-item{label="Is this version stable and suitable for production use?"}
|
||||
Nuxt UI v3 is now in beta and is stable enough to be used in production. We now recommend using v3 over v2. We welcome feedback from users to help improve the library further. Feel free to report any issues you encounter on our [GitHub repository](https://github.com/nuxt/ui/issues).
|
||||
::accordion-item{label="What is the testing approach for Nuxt UI?"}
|
||||
Nuxt UI ensures reliability with 1000+ Vitest tests, covering core functionality and accessibility. This robust testing suite supports the library's stability and serves as a reference for developers.
|
||||
::
|
||||
::
|
||||
|
||||
:hr
|
||||
|
||||
We're excited about the possibilities Nuxt UI v3 brings to your projects. Explore our documentation to learn more about new features, components, and best practices for building powerful, accessible user interfaces with Nuxt UI v3.
|
||||
We're excited about the possibilities Nuxt UI v3 brings to your projects. Explore our documentation to learn more about new features, components, and best practices for building powerful, accessible user interfaces.
|
||||
|
||||
@@ -20,24 +20,24 @@ Looking for the **Vue** version?
|
||||
|
||||
::steps{level="4"}
|
||||
|
||||
#### Install the Nuxt UI v3 beta package
|
||||
#### Install the Nuxt UI package
|
||||
|
||||
::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui@next
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui@next
|
||||
yarn add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui@next
|
||||
npm install @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui@next
|
||||
bun add @nuxt/ui
|
||||
```
|
||||
|
||||
::
|
||||
@@ -59,7 +59,7 @@ export default defineNuxtConfig({
|
||||
::code-group
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
```
|
||||
|
||||
@@ -72,10 +72,6 @@ export default defineNuxtConfig({
|
||||
|
||||
::
|
||||
|
||||
::warning
|
||||
The `theme(static)` is required since [`tailwindcss@4.0.8`](https://github.com/tailwindlabs/tailwindcss/releases/tag/v4.0.8) introduced a breaking change to only expose used CSS variables.
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-visualstudiocode"}
|
||||
It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) extension for VSCode and add the following settings:
|
||||
|
||||
@@ -85,7 +81,11 @@ It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.
|
||||
},
|
||||
"editor.quickSuggestions": {
|
||||
"strings": "on"
|
||||
}
|
||||
},
|
||||
"tailwindCSS.classAttributes": ["class", "ui"],
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
|
||||
]
|
||||
```
|
||||
|
||||
::
|
||||
@@ -108,12 +108,12 @@ The `App` component provides global configurations and is required for **Toast**
|
||||
|
||||
### Use our Nuxt Starter
|
||||
|
||||
Start your project using the [nuxt/starter#ui3](https://github.com/nuxt/starter/tree/ui3) template with Nuxt UI v3 pre-configured.
|
||||
Start your project using the [nuxt/starter#ui](https://github.com/nuxt/starter/tree/ui) template with Nuxt UI pre-configured.
|
||||
|
||||
Create a new project locally by running the following command:
|
||||
|
||||
```bash [Terminal]
|
||||
npx nuxi init -t ui3 <my-app>
|
||||
npx nuxi init -t ui <my-app>
|
||||
```
|
||||
|
||||
::note
|
||||
@@ -225,15 +225,15 @@ This option adds the `transition-colors` class on components with hover or activ
|
||||
|
||||
## Continuous Releases
|
||||
|
||||
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.
|
||||
Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
|
||||
|
||||
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.
|
||||
|
||||
```diff [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^3.0.0-beta.3",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
|
||||
- "@nuxt/ui": "^3.0.0",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@4c96909",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -20,24 +20,24 @@ Looking for the **Nuxt** version?
|
||||
|
||||
::steps{level="4"}
|
||||
|
||||
#### Install the Nuxt UI v3 beta package
|
||||
#### Install the Nuxt UI package
|
||||
|
||||
::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui@next
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui@next
|
||||
yarn add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui@next
|
||||
npm install @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui@next
|
||||
bun add @nuxt/ui
|
||||
```
|
||||
|
||||
::
|
||||
@@ -102,14 +102,10 @@ app.mount('#app')
|
||||
#### Import Tailwind CSS and Nuxt UI in your CSS
|
||||
|
||||
```css [assets/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
```
|
||||
|
||||
::warning
|
||||
The `theme(static)` is required since [`tailwindcss@4.0.8`](https://github.com/tailwindlabs/tailwindcss/releases/tag/v4.0.8) introduced a breaking change to only expose used CSS variables.
|
||||
::
|
||||
|
||||
::tip
|
||||
Import the CSS file in your `main.ts`.
|
||||
|
||||
@@ -145,7 +141,11 @@ It's recommended to install the [Tailwind CSS IntelliSense](https://marketplace.
|
||||
},
|
||||
"editor.quickSuggestions": {
|
||||
"strings": "on"
|
||||
}
|
||||
},
|
||||
"tailwindCSS.classAttributes": ["class", "ui"],
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
|
||||
]
|
||||
```
|
||||
|
||||
::
|
||||
@@ -168,7 +168,7 @@ The `App` component provides global configurations and is required for **Toast**
|
||||
|
||||
### Use our Vue starter
|
||||
|
||||
Start your project using the [nuxtlabs/nuxt-ui-vue-starter](https://github.com/nuxtlabs/nuxt-ui-vue-starter) template with Nuxt UI v3 pre-configured.
|
||||
Start your project using the [nuxtlabs/nuxt-ui-vue-starter](https://github.com/nuxtlabs/nuxt-ui-vue-starter) template with Nuxt UI pre-configured.
|
||||
|
||||
Create a new project locally by running the following command:
|
||||
|
||||
@@ -313,15 +313,15 @@ This option adds the `transition-colors` class on components with hover or activ
|
||||
|
||||
## Continuous Releases
|
||||
|
||||
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.
|
||||
Nuxt UI uses [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new) for continuous preview releases, providing developers with instant access to the latest features and bug fixes without waiting for official releases.
|
||||
|
||||
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.
|
||||
|
||||
```diff [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^3.0.0-beta.3",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@83725ac",
|
||||
- "@nuxt/ui": "^3.0.0",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@4c96909",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -28,7 +28,7 @@ For a detailed walkthrough of all changes, refer to the official **Tailwind CSS
|
||||
::code-group
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
```ts [nuxt.config.ts]
|
||||
@@ -56,19 +56,19 @@ npx @tailwindcss/upgrade
|
||||
::::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui@next
|
||||
pnpm add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui@next
|
||||
yarn add @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui@next
|
||||
npm install @nuxt/ui
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui@next
|
||||
bun add @nuxt/ui
|
||||
```
|
||||
|
||||
::::
|
||||
@@ -81,19 +81,19 @@ bun add @nuxt/ui@next
|
||||
::::code-group{sync="pm"}
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui-pro@next
|
||||
pnpm add @nuxt/ui-pro
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui-pro@next
|
||||
yarn add @nuxt/ui-pro
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui-pro@next
|
||||
npm install @nuxt/ui-pro
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui-pro@next
|
||||
bun add @nuxt/ui-pro
|
||||
```
|
||||
|
||||
::::
|
||||
@@ -109,7 +109,7 @@ bun add @nuxt/ui-pro@next
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]{2}
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
```
|
||||
|
||||
@@ -119,7 +119,7 @@ bun add @nuxt/ui-pro@next
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]{2}
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
```
|
||||
|
||||
@@ -130,7 +130,7 @@ bun add @nuxt/ui-pro@next
|
||||
#ui
|
||||
|
||||
:::div
|
||||
5. Wrap you app with the [App](/components/app) component:
|
||||
5. Wrap your app with the [App](/components/app) component:
|
||||
:::
|
||||
|
||||
#ui-pro
|
||||
@@ -145,7 +145,7 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
6. Wrap you app with the [App](/components/app) component:
|
||||
6. Wrap your app with the [App](/components/app) component:
|
||||
:::
|
||||
|
||||
::
|
||||
@@ -458,8 +458,8 @@ const toast = useToast()
|
||||
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
|
||||
- Overlays can no longer be close using `modal.close()` or `slideover.close()`, rather, they close automatically: either when a `close` 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 `close` event with the desired value
|
||||
|
||||
|
||||
```diff
|
||||
@@ -496,7 +496,7 @@ const count = ref(0)
|
||||
</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:
|
||||
Closing a modal is now done through the `close` event. The `modal.open` method now returns a promise that resolves to the result of the modal whenever the modal is close:
|
||||
|
||||
```diff
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -6,7 +6,7 @@ navigation.icon: i-lucide-swatch-book
|
||||
|
||||
## Tailwind CSS
|
||||
|
||||
Nuxt UI v3 uses Tailwind CSS v4, you can read the official [upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3) to learn about all the breaking changes.
|
||||
Nuxt UI uses Tailwind CSS v4, you can read the official [upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3) to learn about all the breaking changes.
|
||||
|
||||
### `@theme`
|
||||
|
||||
@@ -17,7 +17,7 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme static {
|
||||
@@ -45,7 +45,7 @@ Tailwind CSS v4 takes a CSS-first configuration approach, you now customize your
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@theme static {
|
||||
@@ -87,7 +87,7 @@ This can be useful when writing Tailwind CSS classes in markdown files with [`@n
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@source "../../../content";
|
||||
@@ -101,7 +101,7 @@ This can be useful when writing Tailwind CSS classes in markdown files with [`@n
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@source "../../../content";
|
||||
@@ -380,7 +380,7 @@ You can change which shade is used for each color on light and dark mode:
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
:root {
|
||||
@@ -398,7 +398,7 @@ You can change which shade is used for each color on light and dark mode:
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
:root {
|
||||
@@ -434,7 +434,7 @@ You cannot set `primary: 'black'`{lang="ts-type"} in your [`vite.config.ts`](#co
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
:root {
|
||||
@@ -452,7 +452,7 @@ You cannot set `primary: 'black'`{lang="ts-type"} in your [`vite.config.ts`](#co
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
:root {
|
||||
@@ -564,7 +564,7 @@ You can customize these CSS variables to tailor the appearance of your applicati
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
:root {
|
||||
@@ -584,7 +584,7 @@ You can customize these CSS variables to tailor the appearance of your applicati
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
:root {
|
||||
@@ -625,7 +625,7 @@ You can customize the default radius value using the default Tailwind CSS variab
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
:root {
|
||||
@@ -639,7 +639,7 @@ You can customize the default radius value using the default Tailwind CSS variab
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
:root {
|
||||
@@ -670,7 +670,7 @@ You can customize the default container width using the default Tailwind CSS var
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme {
|
||||
@@ -688,7 +688,7 @@ You can customize the default container width using the default Tailwind CSS var
|
||||
:::div{class="*:!mb-0 *:!mt-2.5"}
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@theme {
|
||||
|
||||
@@ -19,7 +19,7 @@ Nuxt UI automatically registers the [`@nuxt/fonts`](https://github.com/nuxt/font
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme {
|
||||
@@ -33,7 +33,7 @@ Nuxt UI automatically registers the [`@nuxt/fonts`](https://github.com/nuxt/font
|
||||
:::div
|
||||
|
||||
```css [app/assets/css/main.css]
|
||||
@import "tailwindcss" theme(static);
|
||||
@import "tailwindcss";
|
||||
@import "@nuxt/ui-pro";
|
||||
|
||||
@theme {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
---
|
||||
title: Contribution Guide
|
||||
description: 'A comprehensive guide on contributing to Nuxt UI v3, including project structure, development workflow, and best practices.'
|
||||
description: 'A comprehensive guide on contributing to Nuxt UI, including project structure, development workflow, and best practices.'
|
||||
navigation: false
|
||||
---
|
||||
|
||||
Nuxt UI thrives thanks to its incredible community ❤️. We welcome all contributions through bug reports, pull requests, and feedback to help make this library even better.
|
||||
|
||||
::caution
|
||||
Before reporting a bug or requesting a feature, make sure that you have read through our [documentation](https://ui3.nuxt.dev/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
Before reporting a bug or requesting a feature, make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
|
||||
::
|
||||
|
||||
## Project Structure
|
||||
|
||||
@@ -166,6 +166,31 @@ slots:
|
||||
:placeholder{class="h-48 m-4"}
|
||||
::
|
||||
|
||||
### Handle Only
|
||||
|
||||
Use the `handle-only` prop to only allow the Drawer to be dragged by the handle.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
props:
|
||||
handleOnly: true
|
||||
slots:
|
||||
default: |
|
||||
|
||||
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
|
||||
|
||||
content: |
|
||||
|
||||
<Placeholder class="h-48 m-4" />
|
||||
---
|
||||
|
||||
:u-button{label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up"}
|
||||
|
||||
#content
|
||||
:placeholder{class="h-48 m-4"}
|
||||
::
|
||||
|
||||
### Overlay
|
||||
|
||||
Use the `overlay` prop to control whether the Drawer has an overlay or not. Defaults to `true`.
|
||||
@@ -193,13 +218,14 @@ slots:
|
||||
|
||||
### Scale background
|
||||
|
||||
Use the `should-scale-background` prop to scale the background when the Drawer is open, creating a visual depth effect.
|
||||
Use the `should-scale-background` prop to scale the background when the Drawer is open, creating a visual depth effect. You can set the `set-background-color-on-scale` prop to `false` to prevent changing the background color.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
props:
|
||||
shouldScaleBackground: true
|
||||
setBackgroundColorOnScale: true
|
||||
slots:
|
||||
default: |
|
||||
|
||||
@@ -217,12 +243,12 @@ slots:
|
||||
::
|
||||
|
||||
::warning
|
||||
Make sure to add the `vaul-drawer-wrapper` directive to a parent element of your app to make this work.
|
||||
Make sure to add the `data-vaul-drawer-wrapper` directive to a parent element of your app to make this work.
|
||||
|
||||
```vue [app.vue]
|
||||
<template>
|
||||
<UApp>
|
||||
<div class="bg-(--ui-bg)" vaul-drawer-wrapper>
|
||||
<div class="bg-(--ui-bg)" data-vaul-drawer-wrapper>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
@@ -235,7 +261,7 @@ Make sure to add the `vaul-drawer-wrapper` directive to a parent element of your
|
||||
export default defineNuxtConfig({
|
||||
app: {
|
||||
rootAttrs: {
|
||||
'vaul-drawer-wrapper': '',
|
||||
'data-vaul-drawer-wrapper': '',
|
||||
'class': 'bg-(--ui-bg)'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ links:
|
||||
|
||||
## Usage
|
||||
|
||||
Use the Form component to validate form data using schema libraries such as [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
|
||||
Use the Form component to validate form data using validation libraries such as [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi), [Superstruct](https://github.com/ianstormtaylor/superstruct) or your own validation logic.
|
||||
|
||||
It works with the [FormField](/components/form-field) component to display error messages around form elements automatically.
|
||||
|
||||
@@ -18,7 +18,7 @@ It works with the [FormField](/components/form-field) component to display error
|
||||
It requires two props:
|
||||
|
||||
- `state` - a reactive object holding the form's state.
|
||||
- `schema` - a schema object from a validation library like [Valibot](https://github.com/fabian-hiller/valibot), [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||
- `schema` - any [Standard Schema](https://standardschema.dev/) or a schema from [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||
|
||||
::warning
|
||||
**No validation library is included** by default, ensure you **install the one you need**.
|
||||
|
||||
@@ -8,7 +8,6 @@ links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/tree/v3/src/runtime/components/Tree.vue
|
||||
navigation.badge: New
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -34,7 +34,7 @@ export default defineNuxtConfig({
|
||||
},
|
||||
$production: {
|
||||
site: {
|
||||
url: 'https://ui3.nuxt.dev'
|
||||
url: 'https://ui.nuxt.com'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -55,8 +55,7 @@ export default defineNuxtConfig({
|
||||
}]
|
||||
},
|
||||
rootAttrs: {
|
||||
// @ts-expect-error - vaul-drawer-wrapper is not typed
|
||||
'vaul-drawer-wrapper': '',
|
||||
'data-vaul-drawer-wrapper': '',
|
||||
'class': 'bg-(--ui-bg)'
|
||||
}
|
||||
},
|
||||
@@ -91,7 +90,56 @@ export default defineNuxtConfig({
|
||||
'/getting-started/icons': { redirect: '/getting-started/icons/nuxt', prerender: false },
|
||||
'/getting-started/color-mode': { redirect: '/getting-started/color-mode/nuxt', prerender: false },
|
||||
'/getting-started/i18n': { redirect: '/getting-started/i18n/nuxt', prerender: false },
|
||||
'/composables': { redirect: '/composables/define-shortcuts', prerender: false }
|
||||
'/composables': { redirect: '/composables/define-shortcuts', prerender: false },
|
||||
// v2 redirects
|
||||
'/getting-started/theming': { redirect: { to: '/getting-started/theme', statusCode: 301 }, prerender: false },
|
||||
'/pro/getting-started/**': { redirect: { to: '/getting-started/installation/pro/nuxt', statusCode: 301 }, prerender: false },
|
||||
'/playground': { redirect: { to: '/getting-started/installation/nuxt', statusCode: 301 }, prerender: false },
|
||||
'/pro/guide/**': { redirect: { to: '/getting-started/installation/pro/nuxt', statusCode: 301 }, prerender: false },
|
||||
'/pro/prose/**': { redirect: { to: '/getting-started/typography#vue-components', statusCode: 301 }, prerender: false },
|
||||
'/components/range': { redirect: { to: '/components/slider', statusCode: 301 }, prerender: false },
|
||||
'/components/date-picker': { redirect: { to: '/components/calendar#as-a-datepicker', statusCode: 301 }, prerender: false },
|
||||
'/components/dropdown': { redirect: { to: '/components/dropdown-menu', statusCode: 301 }, prerender: false },
|
||||
'/components/notification': { redirect: { to: '/components/toast', statusCode: 301 }, prerender: false },
|
||||
'/components/vertical-navigation': { redirect: { to: '/components/navigation-menu', statusCode: 301 }, prerender: false },
|
||||
'/components/horizontal-navigation': { redirect: { to: '/components/navigation-menu', statusCode: 301 }, prerender: false },
|
||||
'/components/divider': { redirect: { to: '/components/separator', statusCode: 301 }, prerender: false },
|
||||
'/components/toggle': { redirect: { to: '/components/switch', statusCode: 301 }, prerender: false },
|
||||
'/components/form-group': { redirect: { to: '/components/form-field', statusCode: 301 }, prerender: false },
|
||||
'/pro/components': { redirect: { to: '/components', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/docs/docs-search': { redirect: { to: '/components/content-search', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/docs-search': { redirect: { to: '/components/content-search', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-hero': { redirect: { to: '/components/page-hero', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-cta': { redirect: { to: '/components/page-cta', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-card': { redirect: { to: '/components/page-card', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-section': { redirect: { to: '/components/page-section', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-faq': { redirect: { to: '/components/page-accordion', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-grid': { redirect: { to: '/components/page-grid', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-logos': { redirect: { to: '/components/page-logos', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/landing-testimonial': { redirect: { to: '/components/page-card#as-a-testimonial', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/blog-list': { redirect: { to: '/components/blog-posts', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/color-mode-toggle': { redirect: { to: '/components/color-mode-switch', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-card': { redirect: { to: '/components/page-card', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-layout': { redirect: { to: '/components/dashboard-group', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-modal': { redirect: { to: '/components/modal', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-navbar-toggle': { redirect: { to: '/components/dashboard-sidebar-toggle', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-page': { redirect: { to: '/components/dashboard-panel', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-panel-content': { redirect: { to: '/components/dashboard-panel', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-panel-handle': { redirect: { to: '/components/dashboard-resize-handle', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-section': { redirect: { to: '/components/page-card', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-sidebar-links': { redirect: { to: '/components/navigation-menu', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/dashboard-slideover': { redirect: { to: '/components/slideover', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/navigation-accordion': { redirect: { to: '/components/content-navigation', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/navigation-links': { redirect: { to: '/components/content-navigation', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/navigation-tree': { redirect: { to: '/components/content-navigation', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/page-error': { redirect: { to: '/components/error', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/footer-links': { redirect: { to: '/components/navigation-menu', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/header-links': { redirect: { to: '/components/navigation-menu', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/pricing-card': { redirect: { to: '/components/pricing-plan', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/pricing-grid': { redirect: { to: '/components/pricing-plans', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/pricing-switch': { redirect: { to: '/components/switch', statusCode: 301 }, prerender: false },
|
||||
'/pro/components/**': { redirect: { to: '/components/**', statusCode: 301 }, prerender: false },
|
||||
'/releases': { redirect: 'https://github.com/nuxt/ui/releases', prerender: false }
|
||||
},
|
||||
|
||||
future: {
|
||||
@@ -105,9 +153,10 @@ export default defineNuxtConfig({
|
||||
routes: [
|
||||
'/getting-started',
|
||||
'/api/countries.json',
|
||||
'/api/locales.json'
|
||||
'/api/locales.json',
|
||||
// '/api/releases.json',
|
||||
// '/api/pulls.json'
|
||||
'/404.html'
|
||||
],
|
||||
crawlLinks: true,
|
||||
autoSubfolderIndex: false
|
||||
@@ -128,7 +177,12 @@ export default defineNuxtConfig({
|
||||
vite: {
|
||||
plugins: [
|
||||
yaml()
|
||||
]
|
||||
],
|
||||
server: {
|
||||
fs: {
|
||||
allow: process.env.NUXT_UI_PRO_PATH ? [resolve(process.env.NUXT_UI_PRO_PATH)] : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
componentMeta: {
|
||||
@@ -170,12 +224,12 @@ export default defineNuxtConfig({
|
||||
},
|
||||
|
||||
llms: {
|
||||
domain: 'https://ui3.nuxt.dev',
|
||||
title: 'Nuxt UI v3',
|
||||
domain: 'https://ui.nuxt.com',
|
||||
title: 'Nuxt UI',
|
||||
description: 'A comprehensive, Nuxt-integrated UI library providing a rich set of fully-styled, accessible and highly customizable components for building modern web applications.',
|
||||
full: {
|
||||
title: 'Nuxt UI v3 Full Documentation',
|
||||
description: 'This is the full documentation for Nuxt UI v3. It includes all the Markdown files written with the MDC syntax.'
|
||||
title: 'Nuxt UI Full Documentation',
|
||||
description: 'This is the full documentation for Nuxt UI. It includes all the Markdown files written with the MDC syntax.'
|
||||
},
|
||||
sections: [
|
||||
{
|
||||
|
||||
@@ -4,34 +4,33 @@
|
||||
"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.31",
|
||||
"@iconify-json/simple-icons": "^1.2.29",
|
||||
"@iconify-json/vscode-icons": "^1.2.16",
|
||||
"@nuxt/content": "^3.3.0",
|
||||
"@nuxt/image": "^1.9.0",
|
||||
"@nuxt/content": "^3.4.0",
|
||||
"@nuxt/image": "^1.10.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@d96a086",
|
||||
"@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",
|
||||
"joi": "^17.13.3",
|
||||
"motion": "^12.5.0",
|
||||
"motion-v": "0.11.3",
|
||||
"nuxt": "^3.16.0",
|
||||
"motion-v": "0.13.1",
|
||||
"nuxt": "^3.16.1",
|
||||
"nuxt-component-meta": "^0.10.0",
|
||||
"nuxt-llms": "^0.1.0",
|
||||
"nuxt-og-image": "^5.0.2",
|
||||
"nuxt-og-image": "^5.0.5",
|
||||
"prettier": "^3.5.3",
|
||||
"shiki-transformer-color-highlight": "^1.0.0",
|
||||
"superstruct": "^2.0.2",
|
||||
"ufo": "^1.5.4",
|
||||
"valibot": "^0.42.1",
|
||||
"valibot": "^1.0.0",
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"wrangler": "^3.114.0"
|
||||
"wrangler": "^3.114.2"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
docs/public/pro/ad.png
Normal file
BIN
docs/public/pro/ad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
@@ -188,6 +188,7 @@ const countries: Country[] = [
|
||||
{ name: 'United Arab Emirates', code: 'AE', emoji: '🇦🇪' },
|
||||
{ name: 'United Kingdom', code: 'GB', emoji: '🇬🇧' },
|
||||
{ name: 'United States', code: 'US', emoji: '🇺🇸' },
|
||||
{ name: 'Pakistan', code: 'PK', emoji: '🇵🇰' },
|
||||
{ name: 'Uruguay', code: 'UY', emoji: '🇺🇾' },
|
||||
{ name: 'Uzbekistan', code: 'UZ', emoji: '🇺🇿' },
|
||||
{ name: 'Vanuatu', code: 'VU', emoji: '🇻🇺' },
|
||||
|
||||
34
package.json
34
package.json
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"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.1",
|
||||
"packageManager": "pnpm@10.6.5",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/ui.git"
|
||||
},
|
||||
"homepage": "https://ui3.nuxt.dev",
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
@@ -83,17 +83,17 @@
|
||||
"@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/kit": "^3.16.1",
|
||||
"@nuxt/schema": "^3.16.1",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@tailwindcss/postcss": "^4.0.13",
|
||||
"@tailwindcss/vite": "^4.0.13",
|
||||
"@tailwindcss/postcss": "^4.0.15",
|
||||
"@tailwindcss/vite": "^4.0.15",
|
||||
"@tanstack/vue-table": "^8.21.2",
|
||||
"@unhead/vue": "^2.0.0-rc.10",
|
||||
"@unhead/vue": "^2.0.0-rc.13",
|
||||
"@vueuse/core": "^13.0.0",
|
||||
"@vueuse/integrations": "^13.0.0",
|
||||
"colortranslator": "^4.1.0",
|
||||
"consola": "^3.4.0",
|
||||
"consola": "^3.4.2",
|
||||
"defu": "^6.1.4",
|
||||
"embla-carousel-auto-height": "^8.5.2",
|
||||
"embla-carousel-auto-scroll": "^8.5.2",
|
||||
@@ -108,15 +108,15 @@
|
||||
"mlly": "^1.7.4",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"reka-ui": "^2.0.2",
|
||||
"reka-ui": "^2.1.0",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-variants": "^1.0.0",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"tailwindcss": "^4.0.15",
|
||||
"tinyglobby": "^0.2.12",
|
||||
"unplugin": "^2.2.0",
|
||||
"unplugin": "^2.2.1",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vaul-vue": "^0.3.0",
|
||||
"vaul-vue": "^0.4.1",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
@@ -131,11 +131,11 @@
|
||||
"eslint": "^9.22.0",
|
||||
"happy-dom": "^17.4.4",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.16.0",
|
||||
"nuxt": "^3.16.1",
|
||||
"release-it": "^18.1.2",
|
||||
"superstruct": "^2.0.2",
|
||||
"valibot": "^0.42.1",
|
||||
"vitest": "^3.0.8",
|
||||
"valibot": "^1.0.0",
|
||||
"vitest": "^3.0.9",
|
||||
"vitest-environment-nuxt": "^1.0.1",
|
||||
"vue-tsc": "^2.2.0",
|
||||
"yup": "^1.6.1",
|
||||
@@ -150,7 +150,7 @@
|
||||
"debug": "4.3.7",
|
||||
"rollup": "4.34.9",
|
||||
"typescript": "5.6.3",
|
||||
"unplugin": "^2.2.0",
|
||||
"unplugin": "^2.2.1",
|
||||
"vue-tsc": "2.2.0"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^6.2.1",
|
||||
"vite": "^6.2.2",
|
||||
"vue-tsc": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ defineShortcuts({
|
||||
|
||||
<template>
|
||||
<UApp :toaster="(appConfig.toaster as any)">
|
||||
<div class="h-screen w-screen overflow-hidden flex min-h-0 bg-(--ui-bg)" vaul-drawer-wrapper>
|
||||
<div class="h-screen w-screen overflow-hidden flex min-h-0 bg-(--ui-bg)" data-vaul-drawer-wrapper>
|
||||
<UNavigationMenu :items="items" orientation="vertical" class="hidden lg:flex border-e border-(--ui-border) overflow-y-auto w-48 p-4" />
|
||||
<UNavigationMenu :items="items" orientation="horizontal" class="lg:hidden border-b border-(--ui-border) [&>div]:min-w-min overflow-x-auto" />
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "tailwindcss" theme(static) source("../../../..");
|
||||
@import "tailwindcss" source("../../../..");
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme static {
|
||||
|
||||
@@ -85,7 +85,7 @@ defineShortcuts({
|
||||
<template>
|
||||
<template v-if="!$route.path.startsWith('/__nuxt_ui__')">
|
||||
<UApp :toaster="appConfig.toaster">
|
||||
<div class="h-screen w-screen overflow-hidden flex flex-col lg:flex-row min-h-0 bg-(--ui-bg)" vaul-drawer-wrapper>
|
||||
<div class="h-screen w-screen overflow-hidden flex flex-col lg:flex-row min-h-0 bg-(--ui-bg)" data-vaul-drawer-wrapper>
|
||||
<UNavigationMenu :items="items" orientation="vertical" class="hidden lg:flex border-e border-(--ui-border) overflow-y-auto w-48 p-4" />
|
||||
<UNavigationMenu :items="items" orientation="horizontal" class="lg:hidden border-b border-(--ui-border) [&>div]:min-w-min overflow-x-auto" />
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "tailwindcss" theme(static) source("../../../..");
|
||||
@import "tailwindcss" source("../../../..");
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@theme static {
|
||||
|
||||
@@ -20,7 +20,7 @@ const inset = ref(false)
|
||||
</template>
|
||||
</UDrawer>
|
||||
|
||||
<UDrawer should-scale-background title="Drawer with `should-scale-background`" description="You need to add the `vaul-drawer-wrapper` directive to your content to make it work." :inset="inset">
|
||||
<UDrawer should-scale-background title="Drawer with `should-scale-background`" description="You need to add the `data-vaul-drawer-wrapper` directive to your content to make it work." :inset="inset">
|
||||
<UButton color="neutral" variant="outline" label="Open with scale" />
|
||||
|
||||
<template #body>
|
||||
@@ -28,7 +28,7 @@ const inset = ref(false)
|
||||
</template>
|
||||
</UDrawer>
|
||||
|
||||
<UDrawer title="Drawer with bottom direction" direction="bottom" :handle="false" :inset="inset">
|
||||
<UDrawer title="Drawer with bottom direction" direction="bottom" :inset="inset">
|
||||
<UButton color="neutral" variant="outline" label="Open on bottom" />
|
||||
|
||||
<template #body>
|
||||
@@ -36,7 +36,7 @@ const inset = ref(false)
|
||||
</template>
|
||||
</UDrawer>
|
||||
|
||||
<UDrawer title="Drawer with left direction" direction="left" :handle="false" :inset="inset">
|
||||
<UDrawer title="Drawer with left direction" direction="left" :inset="inset">
|
||||
<UButton color="neutral" variant="outline" label="Open on left" />
|
||||
|
||||
<template #body>
|
||||
@@ -44,7 +44,7 @@ const inset = ref(false)
|
||||
</template>
|
||||
</UDrawer>
|
||||
|
||||
<UDrawer title="Drawer with top direction" direction="top" :handle="false" :inset="inset">
|
||||
<UDrawer title="Drawer with top direction" direction="top" :inset="inset">
|
||||
<UButton color="neutral" variant="outline" label="Open on top" />
|
||||
|
||||
<template #body>
|
||||
@@ -52,7 +52,7 @@ const inset = ref(false)
|
||||
</template>
|
||||
</UDrawer>
|
||||
|
||||
<UDrawer title="Drawer with right direction" direction="right" :handle="false" :inset="inset">
|
||||
<UDrawer title="Drawer with right direction" direction="right" :inset="inset">
|
||||
<UButton color="neutral" variant="outline" label="Open on right" />
|
||||
|
||||
<template #body>
|
||||
|
||||
@@ -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.31",
|
||||
"@iconify-json/simple-icons": "^1.2.29",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxthub/core": "^0.8.18",
|
||||
"nuxt": "^3.16.0"
|
||||
"nuxt": "^3.16.1"
|
||||
}
|
||||
}
|
||||
|
||||
1369
pnpm-lock.yaml
generated
1369
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -6,10 +6,7 @@
|
||||
"enabled": true
|
||||
},
|
||||
"ignoreDeps": [
|
||||
"valibot30",
|
||||
"valibot31",
|
||||
"typescript",
|
||||
"vaul-vue",
|
||||
"vue-tsc"
|
||||
],
|
||||
"baseBranches": ["v2", "v3"],
|
||||
|
||||
@@ -9,40 +9,40 @@ export interface ModuleOptions {
|
||||
/**
|
||||
* Prefix for components
|
||||
* @defaultValue `U`
|
||||
* @link https://ui3.nuxt.dev/getting-started/installation/nuxt#prefix
|
||||
* @link https://ui.nuxt.com/getting-started/installation/nuxt#prefix
|
||||
*/
|
||||
prefix?: string
|
||||
|
||||
/**
|
||||
* Enable or disable `@nuxt/fonts` module
|
||||
* @defaultValue `true`
|
||||
* @link https://ui3.nuxt.dev/getting-started/installation/nuxt#fonts
|
||||
* @link https://ui.nuxt.com/getting-started/installation/nuxt#fonts
|
||||
*/
|
||||
fonts?: boolean
|
||||
|
||||
/**
|
||||
* Enable or disable `@nuxtjs/color-mode` module
|
||||
* @defaultValue `true`
|
||||
* @link https://ui3.nuxt.dev/getting-started/installation/nuxt#colormode
|
||||
* @link https://ui.nuxt.com/getting-started/installation/nuxt#colormode
|
||||
*/
|
||||
colorMode?: boolean
|
||||
|
||||
/**
|
||||
* Customize how the theme is generated
|
||||
* @link https://ui3.nuxt.dev/getting-started/theme
|
||||
* @link https://ui.nuxt.com/getting-started/theme
|
||||
*/
|
||||
theme?: {
|
||||
/**
|
||||
* Define the color aliases available for components
|
||||
* @defaultValue `['primary', 'secondary', 'success', 'info', 'warning', 'error']`
|
||||
* @link https://ui3.nuxt.dev/getting-started/installation/nuxt#themecolors
|
||||
* @link https://ui.nuxt.com/getting-started/installation/nuxt#themecolors
|
||||
*/
|
||||
colors?: string[]
|
||||
|
||||
/**
|
||||
* Enable or disable transitions on components
|
||||
* @defaultValue `true`
|
||||
* @link https://ui3.nuxt.dev/getting-started/installation/nuxt#themetransitions
|
||||
* @link https://ui.nuxt.com/getting-started/installation/nuxt#themetransitions
|
||||
*/
|
||||
transitions?: boolean
|
||||
}
|
||||
@@ -55,7 +55,7 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
compatibility: {
|
||||
nuxt: '>=3.16.0'
|
||||
},
|
||||
docs: 'https://ui3.nuxt.dev/getting-started/installation/nuxt'
|
||||
docs: 'https://ui.nuxt.com/getting-started/installation/nuxt'
|
||||
},
|
||||
defaults: defaultOptions,
|
||||
async setup(options, nuxt) {
|
||||
|
||||
@@ -20,7 +20,11 @@ export default function ComponentImportPlugin(options: NuxtUIOptions & { prefix:
|
||||
|
||||
const pluginOptions = defu(options.components, <ComponentsOptions>{
|
||||
dts: options.dts ?? true,
|
||||
exclude: [/[\\/]node_modules[\\/](?!\.pnpm|@nuxt\/ui)/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/],
|
||||
exclude: [
|
||||
/[\\/]node_modules[\\/](?!\.pnpm|@nuxt\/ui|@compodium\/examples)/,
|
||||
/[\\/]\.git[\\/]/,
|
||||
/[\\/]\.nuxt[\\/]/
|
||||
],
|
||||
resolvers: [
|
||||
(componentName) => {
|
||||
if (overrideNames.has(componentName))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { AccordionRootProps, AccordionRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
@@ -60,6 +61,7 @@ export type AccordionSlots<T extends { slot?: string }> = {
|
||||
content: SlotProps<T>
|
||||
body: SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends AccordionItem">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
@@ -51,6 +52,7 @@ export type BreadcrumbSlots<T extends { slot?: string }> = {
|
||||
'item-trailing': SlotProps<T>
|
||||
'separator'(props?: {}): any
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends BreadcrumbItem">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { MaybeRefOrGetter } from '@vueuse/shared'
|
||||
@@ -70,6 +71,7 @@ export type ColorPickerProps = {
|
||||
class?: any
|
||||
ui?: Partial<typeof colorPicker.slots>
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { ListboxRootProps, ListboxRootEmits } from 'reka-ui'
|
||||
import type { FuseResult } from 'fuse.js'
|
||||
@@ -130,6 +131,7 @@ export type CommandPaletteSlots<G extends { slot?: string }, T extends { slot?:
|
||||
'item-label': SlotProps<T>
|
||||
'item-trailing': SlotProps<T>
|
||||
} & DynamicSlots<G, SlotProps<T>> & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="G extends CommandPaletteGroup<T>, T extends CommandPaletteItem">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps } from 'reka-ui'
|
||||
import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps, ContextMenuContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/context-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, KbdProps, LinkProps } from '../types'
|
||||
import type { DynamicSlots, PartialString } from '../types/utils'
|
||||
import type { DynamicSlots, PartialString, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigContextMenu = _appConfig as AppConfig & { ui: { contextMenu: Partial<typeof theme> } }
|
||||
|
||||
@@ -22,7 +23,7 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custo
|
||||
icon?: string
|
||||
color?: ContextMenuVariants['color']
|
||||
avatar?: AvatarProps
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
|
||||
kbds?: KbdProps['value'][] | KbdProps[]
|
||||
/**
|
||||
* The item type.
|
||||
@@ -66,7 +67,7 @@ export interface ContextMenuProps<T> extends Omit<ContextMenuRootProps, 'dir'> {
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
/** The content of the menu. */
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
|
||||
/**
|
||||
* Render the menu in a portal.
|
||||
* @defaultValue true
|
||||
@@ -93,6 +94,7 @@ export type ContextMenuSlots<T extends { slot?: string }> = {
|
||||
'item-label': SlotProps<T>
|
||||
'item-trailing': SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends ContextMenuItem">
|
||||
@@ -112,7 +114,7 @@ const emits = defineEmits<ContextMenuEmits>()
|
||||
const slots = defineSlots<ContextMenuSlots<T>>()
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content as ContextMenuContentProps)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
|
||||
|
||||
const ui = computed(() => contextMenu({
|
||||
@@ -138,7 +140,7 @@ const ui = computed(() => contextMenu({
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData">
|
||||
<slot :name="name" v-bind="slotData" />
|
||||
</template>
|
||||
</UContextMenuContent>
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type { DrawerRootProps, DrawerRootEmits } from 'vaul-vue'
|
||||
import type { DialogContentProps } from 'reka-ui'
|
||||
import type { DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/drawer'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigDrawer = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme> } }
|
||||
|
||||
const drawer = tv({ extend: tv(theme), ...(appConfigDrawer.ui?.drawer || {}) })
|
||||
|
||||
export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'direction' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
|
||||
export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'shouldScaleBackground' | 'setBackgroundColorOnScale' | 'scrollLockTimeout' | 'fixed' | 'dismissible' | 'modal' | 'open' | 'defaultOpen' | 'nested' | 'direction' | 'noBodyStyles' | 'handleOnly' | 'preventScrollRestoration' | 'snapPoints'> {
|
||||
/**
|
||||
* The element or component this component should render as.
|
||||
* @defaultValue 'div'
|
||||
@@ -24,7 +25,7 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
|
||||
*/
|
||||
inset?: boolean
|
||||
/** The content of the drawer. */
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DialogContentEmits>>
|
||||
/**
|
||||
* Render an overlay behind the drawer.
|
||||
* @defaultValue true
|
||||
@@ -41,10 +42,9 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
|
||||
*/
|
||||
portal?: boolean
|
||||
/**
|
||||
* When `false`, the drawer will not close when clicking outside or pressing escape.
|
||||
* @defaultValue true
|
||||
* Index of a `snapPoint` from which the overlay fade should be applied. Defaults to the last snap point.
|
||||
*/
|
||||
dismissible?: boolean
|
||||
fadeFromIndex?: any
|
||||
class?: any
|
||||
ui?: Partial<typeof drawer.slots>
|
||||
}
|
||||
@@ -53,7 +53,6 @@ export interface DrawerEmits extends DrawerRootEmits {}
|
||||
|
||||
export interface DrawerSlots {
|
||||
default(props?: {}): any
|
||||
handle(props?: {}): any
|
||||
content(props?: {}): any
|
||||
header(props?: {}): any
|
||||
title(props?: {}): any
|
||||
@@ -66,19 +65,21 @@ export interface DrawerSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed, toRef } from 'vue'
|
||||
import { useForwardPropsEmits } from 'reka-ui'
|
||||
import { DrawerRoot, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription } from 'vaul-vue'
|
||||
import { DrawerRoot, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription, DrawerHandle } from 'vaul-vue'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
|
||||
const props = withDefaults(defineProps<DrawerProps>(), {
|
||||
direction: 'bottom',
|
||||
portal: true,
|
||||
overlay: true,
|
||||
handle: true
|
||||
handle: true,
|
||||
modal: true,
|
||||
dismissible: true
|
||||
})
|
||||
const emits = defineEmits<DrawerEmits>()
|
||||
const slots = defineSlots<DrawerSlots>()
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'closeThreshold', 'defaultOpen', 'dismissible', 'fadeFromIndex', 'fixed', 'modal', 'nested', 'direction', 'open', 'scrollLockTimeout', 'shouldScaleBackground', 'snapPoints'), emits)
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'closeThreshold', 'shouldScaleBackground', 'setBackgroundColorOnScale', 'scrollLockTimeout', 'fixed', 'dismissible', 'modal', 'open', 'defaultOpen', 'nested', 'direction', 'noBodyStyles', 'handleOnly', 'preventScrollRestoration', 'snapPoints', 'fadeFromIndex'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const contentEvents = {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
@@ -100,9 +101,7 @@ const ui = computed(() => drawer({
|
||||
<DrawerOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
|
||||
|
||||
<DrawerContent :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" v-on="contentEvents">
|
||||
<slot name="handle">
|
||||
<div v-if="handle" :class="ui.handle({ class: props.ui?.handle })" />
|
||||
</slot>
|
||||
<DrawerHandle v-if="handle" :class="ui.handle({ class: props.ui?.handle })" />
|
||||
|
||||
<slot name="content">
|
||||
<div :class="ui.container({ class: props.ui?.container })">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuArrowProps } from 'reka-ui'
|
||||
import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuContentEmits, DropdownMenuArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/dropdown-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, KbdProps, LinkProps } from '../types'
|
||||
import type { DynamicSlots, PartialString } from '../types/utils'
|
||||
import type { DynamicSlots, PartialString, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigDropdownMenu = _appConfig as AppConfig & { ui: { dropdownMenu: Partial<typeof theme> } }
|
||||
|
||||
@@ -22,7 +23,7 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
|
||||
icon?: string
|
||||
color?: DropdownMenuVariants['color']
|
||||
avatar?: AvatarProps
|
||||
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>
|
||||
kbds?: KbdProps['value'][] | KbdProps[]
|
||||
/**
|
||||
* The item type.
|
||||
@@ -69,7 +70,7 @@ export interface DropdownMenuProps<T> extends Omit<DropdownMenuRootProps, 'dir'>
|
||||
* The content of the menu.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
||||
*/
|
||||
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the menu.
|
||||
* @defaultValue false
|
||||
@@ -101,6 +102,7 @@ export type DropdownMenuSlots<T extends { slot?: string }> = {
|
||||
'item-label': SlotProps<T>
|
||||
'item-trailing': SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends DropdownMenuItem">
|
||||
@@ -148,7 +150,7 @@ const ui = computed(() => dropdownMenu({
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData">
|
||||
<slot :name="name" v-bind="slotData" />
|
||||
</template>
|
||||
|
||||
|
||||
@@ -12,14 +12,34 @@ const form = tv({ extend: tv(theme), ...(appConfigForm.ui?.form || {}) })
|
||||
|
||||
export interface FormProps<T extends object> {
|
||||
id?: string | number
|
||||
/** Schema to validate the form state. Supports Standard Schema objects, Yup, Joi, and Superstructs. */
|
||||
schema?: FormSchema<T>
|
||||
/** An object representing the current state of the form. */
|
||||
state: Partial<T>
|
||||
/**
|
||||
* Custom validation function to validate the form state.
|
||||
* @param state - The current state of the form.
|
||||
* @returns A promise that resolves to an array of FormError objects, or an array of FormError objects directly.
|
||||
*/
|
||||
validate?: (state: Partial<T>) => Promise<FormError[]> | FormError[]
|
||||
/**
|
||||
* The list of input events that trigger the form validation.
|
||||
* @defaultValue `['blur', 'change', 'input']`
|
||||
*/
|
||||
validateOn?: FormInputEvents[]
|
||||
/** Disable all inputs inside the form. */
|
||||
disabled?: boolean
|
||||
/**
|
||||
* Delay in milliseconds before validating the form on input events.
|
||||
* @defaultValue `300`
|
||||
*/
|
||||
validateOnInputDelay?: number
|
||||
class?: any
|
||||
/**
|
||||
* If true, schema transformations will be applied to the state on submit.
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
transform?: boolean
|
||||
class?: any
|
||||
onSubmit?: ((event: FormSubmitEvent<T>) => void | Promise<void>) | (() => void | Promise<void>)
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,12 @@ export interface FormFieldProps {
|
||||
*/
|
||||
size?: FormFieldVariants['size']
|
||||
required?: boolean
|
||||
/** If true, validation on input will be active immediately instead of waiting for a blur event. */
|
||||
eagerValidation?: boolean
|
||||
/**
|
||||
* Delay in milliseconds before validating the form on input events.
|
||||
* @defaultValue `300`
|
||||
*/
|
||||
validateOnInputDelay?: number
|
||||
class?: any
|
||||
ui?: Partial<typeof formField.slots>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script lang="ts">
|
||||
import type { InputHTMLAttributes } from 'vue'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/input-menu'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigInputMenu = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
|
||||
|
||||
@@ -81,7 +81,7 @@ export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends Ma
|
||||
* The content of the menu.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
||||
*/
|
||||
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ComboboxContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the menu.
|
||||
* @defaultValue false
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'reka-ui'
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/modal'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigModal = _appConfig as AppConfig & { ui: { modal: Partial<typeof theme> } }
|
||||
|
||||
@@ -14,7 +15,7 @@ export interface ModalProps extends DialogRootProps {
|
||||
title?: string
|
||||
description?: string
|
||||
/** The content of the modal. */
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DialogContentEmits>>
|
||||
/**
|
||||
* Render an overlay behind the modal.
|
||||
* @defaultValue true
|
||||
@@ -97,18 +98,20 @@ const appConfig = useAppConfig()
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const contentEvents = computed(() => {
|
||||
const events = {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
}
|
||||
|
||||
if (!props.dismissible) {
|
||||
return {
|
||||
pointerDownOutside: (e: Event) => e.preventDefault(),
|
||||
interactOutside: (e: Event) => e.preventDefault(),
|
||||
escapeKeyDown: (e: Event) => e.preventDefault(),
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
...events
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
}
|
||||
return events
|
||||
})
|
||||
|
||||
const ui = computed(() => modal({
|
||||
@@ -158,7 +161,7 @@ const ui = computed(() => modal({
|
||||
</DialogDescription>
|
||||
</div>
|
||||
|
||||
<DialogClose as-child>
|
||||
<DialogClose v-if="close || !!slots.close" as-child>
|
||||
<slot name="close" :ui="ui">
|
||||
<UButton
|
||||
v-if="close"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, CollapsibleRootProps } from 'reka-ui'
|
||||
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, NavigationMenuContentEmits, CollapsibleRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/navigation-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, BadgeProps, LinkProps } from '../types'
|
||||
import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString } from '../types/utils'
|
||||
import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigNavigationMenu = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
|
||||
|
||||
@@ -93,7 +94,7 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'm
|
||||
*/
|
||||
highlightColor?: NavigationMenuVariants['highlightColor']
|
||||
/** The content of the menu. */
|
||||
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<NavigationMenuContentEmits>>
|
||||
/**
|
||||
* The orientation of the content.
|
||||
* Only works when `orientation` is `horizontal`.
|
||||
@@ -125,6 +126,7 @@ export type NavigationMenuSlots<T extends { slot?: string }> = {
|
||||
'item-trailing': SlotProps<T>
|
||||
'item-content': SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<NavigationMenuItem>">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
|
||||
@@ -45,6 +46,7 @@ export type PinInputEmits = PinInputRootEmits & {
|
||||
change: [payload: Event]
|
||||
blur: [payload: Event]
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverArrowProps } from 'reka-ui'
|
||||
import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverContentEmits, PopoverArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/popover'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigPopover = _appConfig as AppConfig & { ui: { popover: Partial<typeof theme> } }
|
||||
|
||||
@@ -19,7 +20,7 @@ export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps,
|
||||
* The content of the popover.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
||||
*/
|
||||
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<PopoverContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<PopoverContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the popover.
|
||||
* @defaultValue false
|
||||
|
||||
@@ -161,8 +161,8 @@ function onUpdate(value: any) {
|
||||
<RadioGroupItem
|
||||
:id="item.id"
|
||||
:value="item.value"
|
||||
:disabled="disabled"
|
||||
:class="ui.base({ class: props.ui?.base })"
|
||||
:disabled="item.disabled"
|
||||
:class="ui.base({ class: props.ui?.base, disabled: item.disabled })"
|
||||
>
|
||||
<RadioGroupIndicator :class="ui.indicator({ class: props.ui?.indicator })" />
|
||||
</RadioGroupItem>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/select'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigSelect = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
|
||||
|
||||
@@ -64,7 +64,7 @@ export interface SelectProps<T extends MaybeArrayOfArrayItem<I>, I extends Maybe
|
||||
* The content of the menu.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
||||
*/
|
||||
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<SelectContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<SelectContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the menu.
|
||||
* @defaultValue false
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/select-menu'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
|
||||
import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey, EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigSelectMenu = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
|
||||
|
||||
@@ -72,7 +72,7 @@ export interface SelectMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends M
|
||||
* The content of the menu.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }
|
||||
*/
|
||||
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<ComboboxContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ComboboxContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the menu.
|
||||
* @defaultValue false
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'reka-ui'
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/slideover'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigSlideover = _appConfig as AppConfig & { ui: { slideover: Partial<typeof theme> } }
|
||||
|
||||
@@ -17,7 +18,7 @@ export interface SlideoverProps extends DialogRootProps {
|
||||
title?: string
|
||||
description?: string
|
||||
/** The content of the slideover. */
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DialogContentEmits>>
|
||||
/**
|
||||
* Render an overlay behind the slideover.
|
||||
* @defaultValue true
|
||||
@@ -101,18 +102,20 @@ const appConfig = useAppConfig()
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const contentEvents = computed(() => {
|
||||
const events = {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
}
|
||||
|
||||
if (!props.dismissible) {
|
||||
return {
|
||||
pointerDownOutside: (e: Event) => e.preventDefault(),
|
||||
interactOutside: (e: Event) => e.preventDefault(),
|
||||
escapeKeyDown: (e: Event) => e.preventDefault(),
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
...events
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
}
|
||||
return events
|
||||
})
|
||||
|
||||
const ui = computed(() => slideover({
|
||||
@@ -162,7 +165,7 @@ const ui = computed(() => slideover({
|
||||
</DialogDescription>
|
||||
</div>
|
||||
|
||||
<DialogClose as-child>
|
||||
<DialogClose v-if="close || !!slots.close" as-child>
|
||||
<slot name="close" :ui="ui">
|
||||
<UButton
|
||||
v-if="close"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { StepperRootProps, StepperRootEmits } from 'reka-ui'
|
||||
@@ -68,6 +69,7 @@ export type StepperSlots<T extends StepperItem> = {
|
||||
description: SlotProps<T>
|
||||
content: SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends StepperItem">
|
||||
|
||||
@@ -289,7 +289,7 @@ function handleRowSelect(row: TableRow<T>, e: Event) {
|
||||
return
|
||||
}
|
||||
const target = e.target as HTMLElement
|
||||
const isInteractive = target.closest('button')
|
||||
const isInteractive = target.closest('button') || target.closest('a')
|
||||
if (isInteractive) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { TabsRootProps, TabsRootEmits } from 'reka-ui'
|
||||
@@ -76,6 +77,7 @@ export type TabsSlots<T extends { slot?: string }> = {
|
||||
trailing: SlotProps<T>
|
||||
content: SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends TabsItem">
|
||||
|
||||
@@ -168,7 +168,7 @@ defineExpose({
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
<ToastClose as-child>
|
||||
<ToastClose v-if="close || !!slots.close" as-child>
|
||||
<slot name="close" :ui="ui">
|
||||
<UButton
|
||||
v-if="close"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { TooltipRootProps, TooltipRootEmits, TooltipContentProps, TooltipArrowProps } from 'reka-ui'
|
||||
import type { TooltipRootProps, TooltipRootEmits, TooltipContentProps, TooltipContentEmits, TooltipArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/tooltip'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { KbdProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
|
||||
const appConfigTooltip = _appConfig as AppConfig & { ui: { tooltip: Partial<typeof theme> } }
|
||||
|
||||
@@ -19,7 +20,7 @@ export interface TooltipProps extends TooltipRootProps {
|
||||
* The content of the tooltip.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
||||
*/
|
||||
content?: Omit<TooltipContentProps, 'as' | 'asChild'>
|
||||
content?: Omit<TooltipContentProps, 'as' | 'asChild'> & Partial<EmitsToProps<TooltipContentEmits>>
|
||||
/**
|
||||
* Display an arrow alongside the tooltip.
|
||||
* @defaultValue false
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { TreeRootProps, TreeRootEmits } from 'reka-ui'
|
||||
@@ -97,6 +98,7 @@ export type TreeSlots<T extends { slot?: string }> = {
|
||||
'item-label': SlotProps<T>
|
||||
'item-trailing': SlotProps<T>
|
||||
} & DynamicSlots<T, SlotProps<T>>
|
||||
|
||||
</script>
|
||||
|
||||
<script setup lang="ts" generic="T extends TreeItem, M extends boolean = false, K extends SelectItemKey<T> | undefined = undefined">
|
||||
|
||||
@@ -8,6 +8,7 @@ interface DefineLocaleOptions<M> {
|
||||
messages: M
|
||||
}
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function defineLocale<M>(options: DefineLocaleOptions<M>): Locale<M> {
|
||||
return defu<DefineLocaleOptions<M>, [{ dir: Direction }]>(options, { dir: 'ltr' })
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ export function extractShortcuts(items: any[] | any[][]) {
|
||||
return shortcuts
|
||||
}
|
||||
|
||||
/* @__NO_SIDE_EFFECTS__ */
|
||||
export function defineShortcuts(config: MaybeRef<ShortcutsConfig>, options: ShortcutsOptions = {}) {
|
||||
const chainedInputs = ref<string[]>([])
|
||||
const clearChainedInput = () => {
|
||||
|
||||
@@ -67,4 +67,4 @@ const _useKbd = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const useKbd = createSharedComposable(_useKbd)
|
||||
export const useKbd = /* @__PURE__ */ createSharedComposable(_useKbd)
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Locale, Messages } from '../types/locale'
|
||||
import { buildLocaleContext } from '../utils/locale'
|
||||
import en from '../locale/en'
|
||||
|
||||
export const localeContextInjectionKey: InjectionKey<Ref<Locale<unknown> | undefined>> = Symbol('nuxt-ui.locale-context')
|
||||
export const localeContextInjectionKey: InjectionKey<Ref<Locale<unknown> | undefined>> = Symbol.for('nuxt-ui.locale-context')
|
||||
|
||||
const _useLocale = (localeOverrides?: Ref<Locale<Messages> | undefined>) => {
|
||||
const locale = localeOverrides || toRef(inject<Locale<Messages>>(localeContextInjectionKey))
|
||||
@@ -13,4 +13,4 @@ const _useLocale = (localeOverrides?: Ref<Locale<Messages> | undefined>) => {
|
||||
return buildLocaleContext<Messages>(computed(() => locale.value || en))
|
||||
}
|
||||
|
||||
export const useLocale = createSharedComposable(_useLocale)
|
||||
export const useLocale = /* @__PURE__ */ createSharedComposable(_useLocale)
|
||||
|
||||
@@ -116,4 +116,4 @@ function _useOverlay() {
|
||||
}
|
||||
}
|
||||
|
||||
export const useOverlay = createSharedComposable(_useOverlay)
|
||||
export const useOverlay = /* @__PURE__ */ createSharedComposable(_useOverlay)
|
||||
|
||||
56
src/runtime/locale/ca.ts
Normal file
56
src/runtime/locale/ca.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Català',
|
||||
code: 'ca',
|
||||
messages: {
|
||||
inputMenu: {
|
||||
noMatch: 'No hi ha dades coincidents',
|
||||
noData: 'Sense dades',
|
||||
create: 'Crear "{label}"'
|
||||
},
|
||||
calendar: {
|
||||
prevYear: 'Any anterior',
|
||||
nextYear: 'Any següent',
|
||||
prevMonth: 'Mes anterior',
|
||||
nextMonth: 'Mes següent'
|
||||
},
|
||||
inputNumber: {
|
||||
increment: 'Incrementar',
|
||||
decrement: 'Decrementar'
|
||||
},
|
||||
commandPalette: {
|
||||
placeholder: 'Escriu una ordre o cerca...',
|
||||
noMatch: 'No hi ha dades coincidents',
|
||||
noData: 'Sense dades',
|
||||
close: 'Tancar'
|
||||
},
|
||||
selectMenu: {
|
||||
noMatch: 'No hi ha dades coincidents',
|
||||
noData: 'Sense dades',
|
||||
create: 'Crear "{label}"',
|
||||
search: 'Cerca...'
|
||||
},
|
||||
toast: {
|
||||
close: 'Tancar'
|
||||
},
|
||||
carousel: {
|
||||
prev: 'Anterior',
|
||||
next: 'Següent',
|
||||
goto: 'Anar a la diapositiva {slide}'
|
||||
},
|
||||
modal: {
|
||||
close: 'Tancar'
|
||||
},
|
||||
slideover: {
|
||||
close: 'Tancar'
|
||||
},
|
||||
alert: {
|
||||
close: 'Tancar'
|
||||
},
|
||||
table: {
|
||||
noData: 'Sense dades'
|
||||
}
|
||||
}
|
||||
})
|
||||
57
src/runtime/locale/ckb.ts
Normal file
57
src/runtime/locale/ckb.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale<Messages>({
|
||||
name: 'کوردی',
|
||||
code: 'ckb',
|
||||
dir: 'rtl',
|
||||
messages: {
|
||||
inputMenu: {
|
||||
noMatch: 'هیچ ئەنجامێک نەدۆزرایەوە',
|
||||
noData: 'هیچ داتایەک نییە',
|
||||
create: '"{label}" دروستکردنی'
|
||||
},
|
||||
calendar: {
|
||||
prevYear: 'ساڵی پێشوو',
|
||||
nextYear: 'ساڵی داهاتوو',
|
||||
prevMonth: 'مانگی پێشوو',
|
||||
nextMonth: 'مانگی داهاتوو'
|
||||
},
|
||||
inputNumber: {
|
||||
increment: 'زیادکردن',
|
||||
decrement: 'کەمکردنەوە'
|
||||
},
|
||||
commandPalette: {
|
||||
placeholder: 'فەرمانێک بنووسە یان بگەڕێ...',
|
||||
noMatch: 'هیچ ئەنجامێک نەدۆزرایەوە',
|
||||
noData: 'هیچ داتایەک نییە',
|
||||
close: 'داخستن'
|
||||
},
|
||||
selectMenu: {
|
||||
noMatch: 'هیچ ئەنجامێک نەدۆزرایەوە',
|
||||
noData: 'هیچ داتایەک نییە',
|
||||
create: '"{label}" دروستکردنی',
|
||||
search: 'گەڕان...'
|
||||
},
|
||||
toast: {
|
||||
close: 'داخستن'
|
||||
},
|
||||
carousel: {
|
||||
prev: 'پێشوو',
|
||||
next: 'داهاتوو',
|
||||
goto: 'بڕۆ بۆ سلایدی {slide}'
|
||||
},
|
||||
modal: {
|
||||
close: 'داخستن'
|
||||
},
|
||||
slideover: {
|
||||
close: 'داخستن'
|
||||
},
|
||||
alert: {
|
||||
close: 'داخستن'
|
||||
},
|
||||
table: {
|
||||
noData: 'هیچ داتایەک نییە'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,7 +1,9 @@
|
||||
export { default as ar } from './ar'
|
||||
export { default as az } from './az'
|
||||
export { default as bn } from './bn'
|
||||
export { default as ca } from './ca'
|
||||
export { default as cs } from './cs'
|
||||
export { default as ckb } from './ckb'
|
||||
export { default as da } from './da'
|
||||
export { default as de } from './de'
|
||||
export { default as el } from './el'
|
||||
@@ -24,12 +26,15 @@ export { default as nl } from './nl'
|
||||
export { default as pl } from './pl'
|
||||
export { default as pt } from './pt'
|
||||
export { default as pt_br } from './pt_br'
|
||||
export { default as ro } from './ro'
|
||||
export { default as ru } from './ru'
|
||||
export { default as sk } from './sk'
|
||||
export { default as sv } from './sv'
|
||||
export { default as th } from './th'
|
||||
export { default as tr } from './tr'
|
||||
export { default as uk } from './uk'
|
||||
export { default as ur } from './ur'
|
||||
export { default as uz } from './uz'
|
||||
export { default as vi } from './vi'
|
||||
export { default as zh_cn } from './zh_cn'
|
||||
export { default as zh_tw } from './zh_tw'
|
||||
|
||||
56
src/runtime/locale/ro.ts
Normal file
56
src/runtime/locale/ro.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Română',
|
||||
code: 'ro',
|
||||
messages: {
|
||||
inputMenu: {
|
||||
noMatch: 'Nu există date corespunzătoare',
|
||||
noData: 'Nu există date',
|
||||
create: 'Creează "{label}"'
|
||||
},
|
||||
calendar: {
|
||||
prevYear: 'Anul precedent',
|
||||
nextYear: 'Anul următor',
|
||||
prevMonth: 'Luna precedentă',
|
||||
nextMonth: 'Luna următoare'
|
||||
},
|
||||
inputNumber: {
|
||||
increment: 'Crește',
|
||||
decrement: 'Scade'
|
||||
},
|
||||
commandPalette: {
|
||||
placeholder: 'Tastează o comandă sau caută...',
|
||||
noMatch: 'Nu există date corespunzătoare',
|
||||
noData: 'Nu există date',
|
||||
close: 'Închide'
|
||||
},
|
||||
selectMenu: {
|
||||
noMatch: 'Nu există date corespunzătoare',
|
||||
noData: 'Nu există date',
|
||||
create: 'Creează "{label}"',
|
||||
search: 'Caută...'
|
||||
},
|
||||
toast: {
|
||||
close: 'Închide'
|
||||
},
|
||||
carousel: {
|
||||
prev: 'Anterior',
|
||||
next: 'Următor',
|
||||
goto: 'Mergi la diapozitivul {slide}'
|
||||
},
|
||||
modal: {
|
||||
close: 'Închide'
|
||||
},
|
||||
slideover: {
|
||||
close: 'Închide'
|
||||
},
|
||||
alert: {
|
||||
close: 'Închide'
|
||||
},
|
||||
table: {
|
||||
noData: 'Nu există date'
|
||||
}
|
||||
}
|
||||
})
|
||||
57
src/runtime/locale/ur.ts
Normal file
57
src/runtime/locale/ur.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Urdu',
|
||||
code: 'ur',
|
||||
dir: 'rtl',
|
||||
messages: {
|
||||
inputMenu: {
|
||||
noMatch: 'کوئی ملتا جلتا ڈیٹا نہیں ملا',
|
||||
noData: 'کوئی ڈیٹا نہیں',
|
||||
create: '"{label}" بنائیں'
|
||||
},
|
||||
calendar: {
|
||||
prevYear: 'پچھلا سال',
|
||||
nextYear: 'اگلا سال',
|
||||
prevMonth: 'پچھلا مہینہ',
|
||||
nextMonth: 'اگلا مہینہ'
|
||||
},
|
||||
inputNumber: {
|
||||
increment: 'اضافہ',
|
||||
decrement: 'کمی'
|
||||
},
|
||||
commandPalette: {
|
||||
placeholder: 'کمانڈ ٹائپ کریں یا تلاش کریں...',
|
||||
noMatch: 'کوئی ملتا جلتا ڈیٹا نہیں ملا',
|
||||
noData: 'کوئی ڈیٹا نہیں',
|
||||
close: 'بند کریں'
|
||||
},
|
||||
selectMenu: {
|
||||
noMatch: 'کوئی ملتا جلتا ڈیٹا نہیں ملا',
|
||||
noData: 'کوئی ڈیٹا نہیں',
|
||||
create: '"{label}" بنائیں',
|
||||
search: 'تلاش کریں...'
|
||||
},
|
||||
toast: {
|
||||
close: 'بند کریں'
|
||||
},
|
||||
carousel: {
|
||||
prev: 'پچھلا',
|
||||
next: 'اگلا',
|
||||
goto: 'سلائیڈ {slide} پر جائیں'
|
||||
},
|
||||
modal: {
|
||||
close: 'بند کریں'
|
||||
},
|
||||
slideover: {
|
||||
close: 'بند کریں'
|
||||
},
|
||||
alert: {
|
||||
close: 'بند کریں'
|
||||
},
|
||||
table: {
|
||||
noData: 'کوئی ڈیٹا نہیں'
|
||||
}
|
||||
}
|
||||
})
|
||||
56
src/runtime/locale/uz.ts
Normal file
56
src/runtime/locale/uz.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { Messages } from '../types'
|
||||
import { defineLocale } from '../composables/defineLocale'
|
||||
|
||||
export default defineLocale<Messages>({
|
||||
name: 'Oʻzbek',
|
||||
code: 'uz',
|
||||
messages: {
|
||||
inputMenu: {
|
||||
noMatch: 'Mos keluvchi natija topilmadi',
|
||||
noData: 'Maʼlumot yoʻq',
|
||||
create: '"{label}" yaratish'
|
||||
},
|
||||
calendar: {
|
||||
prevYear: 'Oldingi yil',
|
||||
nextYear: 'Keyingi yil',
|
||||
prevMonth: 'Oldingi oy',
|
||||
nextMonth: 'Keyingi oy'
|
||||
},
|
||||
inputNumber: {
|
||||
increment: 'Qoʻshish',
|
||||
decrement: 'Ayirish'
|
||||
},
|
||||
commandPalette: {
|
||||
placeholder: 'Buyruq kiriting yoki qidiring...',
|
||||
noMatch: 'Mos keluvchi natija topilmadi',
|
||||
noData: 'Maʼlumot yoʻq',
|
||||
close: 'Yopish'
|
||||
},
|
||||
selectMenu: {
|
||||
noMatch: 'Mos keluvchi natija topilmadi',
|
||||
noData: 'Maʼlumot yoʻq',
|
||||
create: '"{label}" yaratish',
|
||||
search: 'Qidirish...'
|
||||
},
|
||||
toast: {
|
||||
close: 'Yopish'
|
||||
},
|
||||
carousel: {
|
||||
prev: 'Ortga',
|
||||
next: 'Oldinga',
|
||||
goto: '{slide}-slaydga o‘tish'
|
||||
},
|
||||
modal: {
|
||||
close: 'Yopish'
|
||||
},
|
||||
slideover: {
|
||||
close: 'Yopish'
|
||||
},
|
||||
alert: {
|
||||
close: 'Yopish'
|
||||
},
|
||||
table: {
|
||||
noData: 'Maʼlumot yoʻq'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,21 +1,30 @@
|
||||
import { computed } from 'vue'
|
||||
import colors from 'tailwindcss/colors'
|
||||
import type { UseHeadInput } from '@unhead/vue/types'
|
||||
import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports'
|
||||
// FIXME: https://github.com/nuxt/module-builder/issues/141#issuecomment-2078248248
|
||||
import type {} from '#app'
|
||||
|
||||
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const
|
||||
|
||||
function getColor(color: keyof typeof colors, shade: typeof shades[number]): string {
|
||||
if (color in colors && typeof colors[color] === 'object' && shade in colors[color]) {
|
||||
return colors[color][shade] as string
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function generateShades(key: string, value: string) {
|
||||
return `${shades.map(shade => `--ui-color-${key}-${shade}: var(--color-${value === 'neutral' ? 'old-neutral' : value}-${shade}, ${getColor(value as keyof typeof colors, shade)});`).join('\n ')}`
|
||||
}
|
||||
function generateColor(key: string, shade: number) {
|
||||
return `--ui-${key}: var(--ui-color-${key}-${shade});`
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
const appConfig = useAppConfig()
|
||||
const nuxtApp = useNuxtApp()
|
||||
|
||||
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
|
||||
|
||||
function generateShades(key: string, value: string) {
|
||||
return `${shades.map(shade => `--ui-color-${key}-${shade}: var(--color-${value === 'neutral' ? 'old-neutral' : value}-${shade});`).join('\n ')}`
|
||||
}
|
||||
function generateColor(key: string, shade: number) {
|
||||
return `--ui-${key}: var(--ui-color-${key}-${shade});`
|
||||
}
|
||||
|
||||
const root = computed(() => {
|
||||
const { neutral, ...colors } = appConfig.ui.colors
|
||||
|
||||
@@ -33,12 +42,11 @@ export default defineNuxtPlugin(() => {
|
||||
})
|
||||
|
||||
// Head
|
||||
const headData: any = {
|
||||
const headData: UseHeadInput = {
|
||||
style: [{
|
||||
innerHTML: () => root.value,
|
||||
tagPriority: -2,
|
||||
id: 'nuxt-ui-colors',
|
||||
type: 'text/css'
|
||||
id: 'nuxt-ui-colors'
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -55,7 +63,5 @@ export default defineNuxtPlugin(() => {
|
||||
}]
|
||||
}
|
||||
|
||||
if (!nuxtApp.isVue) {
|
||||
useHead(headData)
|
||||
}
|
||||
useHead(headData)
|
||||
})
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
||||
import type { ComputedRef, DeepReadonly, Ref } from 'vue'
|
||||
import type { ZodSchema } from 'zod'
|
||||
import type { Schema as JoiSchema } from 'joi'
|
||||
import type { ObjectSchema as YupObjectSchema } from 'yup'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { GetObjectField } from './utils'
|
||||
import type { Struct as SuperstructSchema } from 'superstruct'
|
||||
|
||||
@@ -23,12 +21,7 @@ export interface Form<T extends object> {
|
||||
}
|
||||
|
||||
export type FormSchema<T extends object> =
|
||||
| ZodSchema
|
||||
| YupObjectSchema<T>
|
||||
| ValibotSchema
|
||||
| ValibotSchemaAsync
|
||||
| ValibotSafeParser<any, any>
|
||||
| ValibotSafeParserAsync<any, any>
|
||||
| JoiSchema<T>
|
||||
| SuperstructSchema<any, any>
|
||||
| StandardSchemaV1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user