mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 12:39:35 +01:00
Compare commits
5 Commits
v2
...
issue-1057
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21939ed333 | ||
|
|
5a414eb55a | ||
|
|
3a5960fb58 | ||
|
|
a78203ce49 | ||
|
|
592da565fe |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -1 +0,0 @@
|
||||
* @benjamincanac
|
||||
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://ui2.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://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
|
||||
15
.github/ISSUE_TEMPLATE/bug-v3.yml
vendored
15
.github/ISSUE_TEMPLATE/bug-v3.yml
vendored
@@ -5,8 +5,8 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
> [!IMPORTANT]
|
||||
> As Nuxt UI v3 is currently in alpha, we recommend thorough testing before using it in production environments. We're actively working on stabilization and welcome feedback from early adopters to improve the library.
|
||||
> [!IMPORTANT]
|
||||
> As Nuxt UI v3 is currently in alpha, we recommend thorough testing before using it in production environments. We're actively working on stabilization and welcome feedback from early adopters to improve the library.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
@@ -29,20 +29,11 @@ body:
|
||||
- Build Modules: `-`
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: package
|
||||
attributes:
|
||||
label: Is this bug related to Nuxt or Vue?
|
||||
options:
|
||||
- Nuxt
|
||||
- Vue
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
placeholder: v3.0.0-alpha.x
|
||||
placeholder: v3.0.0-alpha.5
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
4
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -5,14 +5,14 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
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).
|
||||
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).
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: For what version of Nuxt UI are you suggesting this?
|
||||
options:
|
||||
- v2.x
|
||||
- v3.0.0-alpha.x
|
||||
- v3-alpha
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/question.yml
vendored
4
.github/ISSUE_TEMPLATE/question.yml
vendored
@@ -5,14 +5,14 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
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).
|
||||
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).
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: For what version of Nuxt UI are you asking this question?
|
||||
options:
|
||||
- v2.x
|
||||
- v3.0.0-alpha.x
|
||||
- v3-alpha
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
name: module
|
||||
name: ci-dev
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v2
|
||||
- dev
|
||||
pull_request:
|
||||
branches:
|
||||
- v2
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
build:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
permissions:
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
node: [20]
|
||||
|
||||
env:
|
||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||
@@ -37,6 +37,16 @@ jobs:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Filter changes
|
||||
uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- 'src/**'
|
||||
- 'package.json'
|
||||
- 'pnpm-lock.yaml'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
@@ -55,5 +65,8 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm run test run
|
||||
|
||||
- name: Publish
|
||||
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
|
||||
- name: Release Edge
|
||||
if: github.event_name == 'push' && steps.changes.outputs.src == 'true'
|
||||
run: ./scripts/release-edge.sh
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
|
||||
@@ -1,18 +1,18 @@
|
||||
name: release
|
||||
name: ci-main
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v2*'
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||
node: [22]
|
||||
node: [20]
|
||||
|
||||
env:
|
||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||
@@ -48,7 +48,14 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm run test run
|
||||
|
||||
- name: Publish
|
||||
- name: Version Check
|
||||
id: check
|
||||
uses: EndBug/version-check@v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Release
|
||||
if: github.event_name == 'push' && steps.check.outputs.changed == 'true'
|
||||
run: ./scripts/release.sh
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
23
.github/workflows/stale.yml
vendored
Normal file
23
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: stale
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
exempt-issue-labels: triage,v3
|
||||
stale-issue-message: 'This issue is stale because it has been open for 30 days with no activity.'
|
||||
stale-issue-label: stale
|
||||
stale-pr-label: stale
|
||||
days-before-stale: 30
|
||||
days-before-close: -1
|
||||
80
CHANGELOG.md
80
CHANGELOG.md
@@ -1,85 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [2.22.1](https://github.com/nuxt/ui/compare/v2.22.0...v2.22.1) (2025-07-16)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Badge/Button:** support numeric zero as visible label ([#4116](https://github.com/nuxt/ui/issues/4116)) ([2971a31](https://github.com/nuxt/ui/commit/2971a3124299e927ddb506bb0fc61b906aa0cfeb))
|
||||
|
||||
## [2.22.0](https://github.com/nuxt/ui/compare/v2.21.1...v2.22.0) (2025-04-22)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Form:** drop explicit support for `zod` and `valibot` (#3618)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Link:** properly pick all `aria-*` & `data-*` attrs ([2bef1e2](https://github.com/nuxt/ui/commit/2bef1e26c6dfd5ee81b11f6da76e257861fc0bef)), closes [#3007](https://github.com/nuxt/ui/issues/3007)
|
||||
* **Table:** checkbox still emit `[@select](https://github.com/select)` event ([#3269](https://github.com/nuxt/ui/issues/3269)) ([c0e14d0](https://github.com/nuxt/ui/commit/c0e14d006ea39965e805adbf9698f5cb95e7c965))
|
||||
* **Table:** remove type annotation in template ([4e96dcc](https://github.com/nuxt/ui/commit/4e96dcca4213bbb56f1dd465ad7d47374e83bc9a)), closes [#3146](https://github.com/nuxt/ui/issues/3146)
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **Form:** drop explicit support for `zod` and `valibot` ([#3618](https://github.com/nuxt/ui/issues/3618)) ([ee37362](https://github.com/nuxt/ui/commit/ee373629d5a9800921301dcbab309f884eaf83fb))
|
||||
|
||||
## [2.21.1](https://github.com/nuxt/ui/compare/v2.21.0...v2.21.1) (2025-03-08)
|
||||
|
||||
### Features
|
||||
|
||||
* **Form:** add standard schema support ([#2880](https://github.com/nuxt/ui/issues/2880)) ([9c36d37](https://github.com/nuxt/ui/commit/9c36d37b847468d1cbd76eea38ac00cbc22549ca))
|
||||
* **module:** add `colorMode` option ([d2ceead](https://github.com/nuxt/ui/commit/d2ceeadae796254128697d94a3e317234bc2ecda)), closes [#3143](https://github.com/nuxt/ui/issues/3143)
|
||||
* **SelectMenu:** add inputTargetForm prop to handle input validation ([#3107](https://github.com/nuxt/ui/issues/3107)) ([feb716c](https://github.com/nuxt/ui/commit/feb716c941f1e7315009b53861a4dc0c2f233052))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Alert/Notification:** allow description ui override ([125a281](https://github.com/nuxt/ui/commit/125a28190b1a83e2456457e7a4ec618384b2446c)), closes [#2554](https://github.com/nuxt/ui/issues/2554)
|
||||
* **Table:** revert [#2600](https://github.com/nuxt/ui/issues/2600) to fix excessive column data slot re-renders ([#3375](https://github.com/nuxt/ui/issues/3375)) ([23d9b51](https://github.com/nuxt/ui/commit/23d9b51a5861f5d1f32f68a3141a600655a0598a))
|
||||
|
||||
## [2.21.0](https://github.com/nuxt/ui/compare/v2.20.0...v2.21.0) (2025-01-14)
|
||||
|
||||
### Features
|
||||
|
||||
* **module:** handle `tailwindMerge` config from `app.config` ([#2902](https://github.com/nuxt/ui/issues/2902)) ([ea15e21](https://github.com/nuxt/ui/commit/ea15e21cdcba00e21302415829113e8c6def8a6e))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Table:** `v-model` causing first column missing ([#2890](https://github.com/nuxt/ui/issues/2890)) ([d573fb6](https://github.com/nuxt/ui/commit/d573fb636f7f749ce95b93c5fb1ae2a053eeeeb0))
|
||||
* **Table:** remove `[@select](https://github.com/select)` event on checkbox ([#3042](https://github.com/nuxt/ui/issues/3042)) ([d9d4f19](https://github.com/nuxt/ui/commit/d9d4f1915aac586ae1abf3ebe67ca9aff65b9be0))
|
||||
* **tailwind:** use mjs template ([#2945](https://github.com/nuxt/ui/issues/2945)) ([8cf9f27](https://github.com/nuxt/ui/commit/8cf9f27d537bad5ffe4e136f52ff71548a451c5f))
|
||||
|
||||
## [2.20.0](https://github.com/nuxt/ui/compare/v2.19.2...v2.20.0) (2024-12-09)
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **Form:** resolve async validation in yup & issue directly mutate state (#2701)
|
||||
|
||||
### Features
|
||||
|
||||
* **Accordion:** add `close` event ([#2750](https://github.com/nuxt/ui/issues/2750)) ([419a24f](https://github.com/nuxt/ui/commit/419a24f7034cefda2c6669f3c26742552e500f63))
|
||||
* **Badge:** handle `icon` prop ([#2594](https://github.com/nuxt/ui/issues/2594)) ([0d1a76e](https://github.com/nuxt/ui/commit/0d1a76e3c69e08534abb295b96548e67cfbea00c))
|
||||
* **InputMenu/SelectMenu:** add support for `dot notation` in `by` prop ([#2607](https://github.com/nuxt/ui/issues/2607)) ([53df9d9](https://github.com/nuxt/ui/commit/53df9d9a8cd6850803bdafc7ef6efe4e7404d334))
|
||||
* **Link:** allow partial query match for `activeClass` ([#2663](https://github.com/nuxt/ui/issues/2663)) ([03e24f4](https://github.com/nuxt/ui/commit/03e24f45836bdddd94b30cbaecc2288a78b56b0b))
|
||||
* **Notification:** add `pauseTimeoutOnHover` prop ([#2661](https://github.com/nuxt/ui/issues/2661)) ([11b8c3d](https://github.com/nuxt/ui/commit/11b8c3d9db1ec62b1c3557703c7ab5c99cb42df5))
|
||||
* **Table:** add contextmenu handling to table rows ([#2283](https://github.com/nuxt/ui/issues/2283)) ([c9e6256](https://github.com/nuxt/ui/commit/c9e6256e7f2c06da8bfda13700f56f6994e76eab))
|
||||
* **Table:** add custom `[@select](https://github.com/select):all` event ([#2581](https://github.com/nuxt/ui/issues/2581)) ([ac323c4](https://github.com/nuxt/ui/commit/ac323c4cccd930f2cd8c1f54b325bd509acd40bf))
|
||||
* **Table:** allow dynamically render `checkbox` ([#2549](https://github.com/nuxt/ui/issues/2549)) ([d6daf46](https://github.com/nuxt/ui/commit/d6daf466ace42b828151c45b18cd47179e85d66d))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **AvatarGroup/ButtonGroup/MeterGroup:** allow deeply partial `ui` config ([#2542](https://github.com/nuxt/ui/issues/2542)) ([bf58086](https://github.com/nuxt/ui/commit/bf580863af11d6a1a4c6c6774b44ec37b082e933))
|
||||
* **Carousel:** wrong `ui` type with `strategy` ([07ef771](https://github.com/nuxt/ui/commit/07ef771b17c72e275508a273371454a5e8a62257))
|
||||
* **components:** replace `as const` with correct type in config ([#2652](https://github.com/nuxt/ui/issues/2652)) ([51c8b8e](https://github.com/nuxt/ui/commit/51c8b8e3e59d7eceff72625650a199fcf7c6feca))
|
||||
* **date-picker:** undefined `dayIndex` ([#2545](https://github.com/nuxt/ui/issues/2545)) ([ce955d2](https://github.com/nuxt/ui/commit/ce955d24f1dfd222e87ce88428c0612c3f13cd50))
|
||||
* **Form:** resolve async validation in yup & issue directly mutate state ([#2701](https://github.com/nuxt/ui/issues/2701)) ([f3632dd](https://github.com/nuxt/ui/commit/f3632ddee511f0fccb24d4fc37403421e84ffdae))
|
||||
* **Form:** use parsed value from `joi` instead of original state ([#2587](https://github.com/nuxt/ui/issues/2587)) ([acecff4](https://github.com/nuxt/ui/commit/acecff40ec0156e45b4934c5d10c4dfa7c135f8e))
|
||||
* **InputMenu/SelectMenu:** use `by` prop to compare objects & support dot notation in `value-attribute` ([#2566](https://github.com/nuxt/ui/issues/2566)) ([7154254](https://github.com/nuxt/ui/commit/7154254ac22830f651ec200f7f3af2f5577f2de0))
|
||||
* **Link:** `exactQuery` prop type ([#2781](https://github.com/nuxt/ui/issues/2781)) ([4cde571](https://github.com/nuxt/ui/commit/4cde571e387775a9b12759f6f8c99117c84cbcff))
|
||||
* **Notification:** element renders even when no `notification` is present ([#2561](https://github.com/nuxt/ui/issues/2561)) ([d4e408c](https://github.com/nuxt/ui/commit/d4e408cfd8e2ef26021519f2f30f57e9120e1939))
|
||||
* **Table:** data outdated when rows change ([#2600](https://github.com/nuxt/ui/issues/2600)) ([b23f2de](https://github.com/nuxt/ui/commit/b23f2decfc9607555a315d0d087d0a042f03a938))
|
||||
* **Table:** missing type on props `loadingState` ([#2551](https://github.com/nuxt/ui/issues/2551)) ([6e66990](https://github.com/nuxt/ui/commit/6e66990372ef6bd7c109a64c753d9b50e96a450b))
|
||||
* **Table:** prevent `onClick` while blocking element ([#2592](https://github.com/nuxt/ui/issues/2592)) ([9703786](https://github.com/nuxt/ui/commit/97037864b39749db228fa5f51981f19e4a9c29dd))
|
||||
* **types:** improve `DeepPartial` type for App Config ([#2621](https://github.com/nuxt/ui/issues/2621)) ([976b03f](https://github.com/nuxt/ui/commit/976b03f241ef9626a6338685e43c844a8b3953fd))
|
||||
|
||||
## [2.19.2](https://github.com/nuxt/ui/compare/v2.19.1...v2.19.2) (2024-11-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
33
README.md
33
README.md
@@ -1,4 +1,4 @@
|
||||
[](https://ui2.nuxt.com)
|
||||
[](https://ui.nuxt.com)
|
||||
|
||||
# Nuxt UI
|
||||
|
||||
@@ -22,32 +22,27 @@ Its goal is to provide everything related to UI when building a Nuxt app. This i
|
||||
- Fully typed
|
||||
- [Figma Kit](https://www.figma.com/community/file/1436401057300493073)
|
||||
|
||||
Read more on [ui2.nuxt.com](https://ui2.nuxt.com)
|
||||
Read more on [ui.nuxt.com](https://ui.nuxt.com)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install @nuxt/ui@2
|
||||
# yarn
|
||||
yarn add @nuxt/ui@2
|
||||
# pnpm
|
||||
pnpm add @nuxt/ui@2
|
||||
# bun
|
||||
bun add @nuxt/ui@2
|
||||
npx nuxi@latest module add ui
|
||||
```
|
||||
|
||||
Next, register the `@nuxt/ui` module in your `nuxt.config.ts`:
|
||||
If you want latest updates, please use `@nuxt/ui-edge` in your `package.json`:
|
||||
|
||||
```ts
|
||||
export default defineNuxtConfig({
|
||||
modules: ['@nuxt/ui']
|
||||
})
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit https://ui2.nuxt.com to explore the documentation.
|
||||
Visit https://ui.nuxt.com to explore the documentation.
|
||||
|
||||
## Credits
|
||||
|
||||
@@ -64,15 +59,15 @@ Visit https://ui2.nuxt.com to explore the documentation.
|
||||
Thank you for considering contributing to Nuxt UI. Here are a few ways you can get involved:
|
||||
|
||||
- Reporting Bugs: If you come across any bugs or issues, please check out the reporting bugs guide to learn how to submit a bug report.
|
||||
- Suggestions: Have any thoughts to enhance Nuxt UI? We'd love to hear them! Check out the [contribution guide](https://ui2.nuxt.com/getting-started/contributing) to share your suggestions.
|
||||
- Suggestions: Have any thoughts to enhance Nuxt UI? We'd love to hear them! Check out the [contribution guide](https://ui.nuxt.com/getting-started/contributing) to share your suggestions.
|
||||
|
||||
## Local Development
|
||||
|
||||
Follow the docs to [Set up your local development environment](https://ui2.nuxt.com/getting-started/contributing#_2-local-development-setup) and contribute.
|
||||
Follow the docs to [Set up your local development environment](https://ui.nuxt.com/getting-started/contributing#_2-local-development-setup) and contribute.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/v2/LICENSE.md).
|
||||
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/dev/LICENSE.md).
|
||||
|
||||
<!-- Badges -->
|
||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||
|
||||
@@ -91,7 +91,7 @@ useHead({
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
||||
{ rel: 'canonical', href: `https://ui2.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||
],
|
||||
htmlAttrs: {
|
||||
lang: 'en'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
const id = 'nuxt-ui-banner-4'
|
||||
const to = 'https://ui.nuxt.com'
|
||||
const id = 'nuxt-ui-banner-2'
|
||||
const to = 'https://ui3.nuxt.dev'
|
||||
|
||||
const hideBanner = () => {
|
||||
localStorage.setItem(id, 'true')
|
||||
@@ -30,6 +30,7 @@ if (import.meta.server) {
|
||||
:to="to"
|
||||
target="_blank"
|
||||
class="focus:outline-none"
|
||||
aria-label="Nuxt UI Pro pricing"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span class="absolute inset-0 " aria-hidden="true" />
|
||||
@@ -39,19 +40,19 @@ if (import.meta.server) {
|
||||
<div class="lg:flex-1 hidden lg:flex items-center" />
|
||||
|
||||
<p class="text-sm font-medium text-white dark:text-gray-900 truncate">
|
||||
<UIcon name="i-lucide-rocket" class="size-5 align-top flex-shrink-0 pointer-events-none mr-1.5" />
|
||||
<span class="font-bold">Nuxt UI v3</span> is officially released!
|
||||
<UIcon name="i-heroicons-rocket-launch" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
|
||||
<span class="font-semibold">Nuxt UI v3-alpha</span> has been released!
|
||||
</p>
|
||||
|
||||
<!-- <UButton
|
||||
:to="to"
|
||||
<UButton
|
||||
to="https://ui3.nuxt.dev"
|
||||
target="_blank"
|
||||
label="Buy now"
|
||||
label="Try it out"
|
||||
color="black"
|
||||
variant="solid"
|
||||
size="2xs"
|
||||
trailing-icon="i-heroicons-arrow-right-20-solid"
|
||||
/> -->
|
||||
/>
|
||||
|
||||
<div class="flex items-center justify-end lg:flex-1">
|
||||
<button
|
||||
|
||||
@@ -10,34 +10,12 @@
|
||||
}"
|
||||
>
|
||||
<template #left>
|
||||
<NuxtLink to="/" class="flex items-end gap-2 text-xl text-gray-900 dark:text-white min-w-0 shrink-0" aria-label="Nuxt UI">
|
||||
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-gray-900 dark:text-white min-w-0" aria-label="Nuxt UI">
|
||||
<LogoPro v-if="$route.path.startsWith('/pro')" class="w-auto h-6 shrink-0" />
|
||||
<Logo v-else class="w-auto h-6 shrink-0" />
|
||||
</NuxtLink>
|
||||
|
||||
<UDropdown
|
||||
:items="[[{ label: $route.path.startsWith('/pro') ? `v${pkg.version.split('-')[0]}` : `v${config.version}`, class: 'text-primary-500 dark:text-primary-400' }, { label: 'v3.x', to: 'https://ui.nuxt.com' }]]"
|
||||
:popper="{ strategy: 'absolute', offsetDistance: 11, placement: 'bottom-start' }"
|
||||
:ui="{
|
||||
background: 'dark:bg-gray-900',
|
||||
ring: 'dark:ring-gray-800',
|
||||
width: 'w-auto',
|
||||
item: {
|
||||
padding: 'p-1',
|
||||
size: 'text-xs',
|
||||
active: 'dark:bg-gray-800/50'
|
||||
}
|
||||
}"
|
||||
>
|
||||
<UButton
|
||||
:label="$route.path.startsWith('/pro') ? `v${pkg.version.split('-')[0]}` : `v${config.version}`"
|
||||
trailing-icon="i-lucide-chevron-down"
|
||||
variant="outline"
|
||||
size="2xs"
|
||||
truncate
|
||||
class="-mb-[6px] font-semibold rounded-full truncate ring-primary-500/25 dark:ring-primary-400/25 bg-primary-500/10 dark:bg-primary-400/10 hover:bg-primary-500/15 dark:hover:bg-primary-400/15 transition-colors"
|
||||
/>
|
||||
</UDropdown>
|
||||
<UBadge :label="$route.path.startsWith('/pro') ? `v${pkg.version.split('-')[0]}` : `v${config.version}`" variant="subtle" size="xs" class="-mb-[2px] rounded font-semibold truncate hidden sm:inline-flex" />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
@@ -47,10 +25,10 @@
|
||||
<UContentSearchButton :label="null" />
|
||||
</UTooltip>
|
||||
|
||||
<UColorModeButton class="hidden lg:inline-flex" />
|
||||
<UColorModeButton />
|
||||
|
||||
<UButton
|
||||
to="https://github.com/nuxt/ui/tree/v2"
|
||||
to="https://github.com/nuxt/ui"
|
||||
target="_blank"
|
||||
icon="i-simple-icons-github"
|
||||
aria-label="GitHub"
|
||||
|
||||
@@ -9,7 +9,7 @@ onMounted(() => {
|
||||
if (carbonads.value) {
|
||||
const script = document.createElement('script')
|
||||
script.setAttribute('type', 'text/javascript')
|
||||
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CW7IC53I&placement=ui2nuxtcom')
|
||||
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CWYIVK3E&placement=uinuxtcom')
|
||||
script.setAttribute('id', '_carbonads_js')
|
||||
carbonads.value.appendChild(script)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ const ui = {
|
||||
inactive: 'text-gray-400 dark:text-gray-500'
|
||||
},
|
||||
avatar: {
|
||||
size: '2xs'
|
||||
size: '2xs' as const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { sub, format, isSameDay } from 'date-fns'
|
||||
import type { Duration } from 'date-fns'
|
||||
import { sub, format, isSameDay, type Duration } from 'date-fns'
|
||||
|
||||
const ranges = [
|
||||
{ label: 'Last 7 days', duration: { days: 7 } },
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { object, string, nonempty } from 'superstruct'
|
||||
import type { Infer } from 'superstruct'
|
||||
import { object, string, nonempty, type Infer } from 'superstruct'
|
||||
import type { FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const schema = object({
|
||||
|
||||
@@ -21,7 +21,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { object, string } from 'yup'
|
||||
import type { InferType } from 'yup'
|
||||
import { object, string, type InferType } from 'yup'
|
||||
import type { FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const schema = object({
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<UInput
|
||||
v-model="name"
|
||||
:maxlength="maxLength"
|
||||
>
|
||||
<template #trailing>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">{{ name.length }}/{{ maxLength }}</span>
|
||||
</template>
|
||||
</UInput>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const name = ref('')
|
||||
const maxLength = 10
|
||||
</script>
|
||||
102
docs/components/content/examples/SelectMenuExampleClearable.vue
Normal file
102
docs/components/content/examples/SelectMenuExampleClearable.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<script setup lang="ts">
|
||||
const options = ref([
|
||||
{ id: 1, name: 'bug', color: 'd73a4a' },
|
||||
{ id: 2, name: 'documentation', color: '0075ca' },
|
||||
{ id: 3, name: 'duplicate', color: 'cfd3d7' },
|
||||
{ id: 4, name: 'enhancement', color: 'a2eeef' },
|
||||
{ id: 5, name: 'good first issue', color: '7057ff' },
|
||||
{ id: 6, name: 'help wanted', color: '008672' },
|
||||
{ id: 7, name: 'invalid', color: 'e4e669' },
|
||||
{ id: 8, name: 'question', color: 'd876e3' },
|
||||
{ id: 9, name: 'wontfix', color: 'ffffff' }
|
||||
])
|
||||
|
||||
const selected = ref([])
|
||||
|
||||
const labels = computed({
|
||||
get: () => selected.value,
|
||||
set: async (labels) => {
|
||||
const promises = labels.map(async (label) => {
|
||||
if (label.id) {
|
||||
return label
|
||||
}
|
||||
|
||||
// In a real app, you would make an API call to create the label
|
||||
const response = {
|
||||
id: options.value.length + 1,
|
||||
name: label.name,
|
||||
color: generateColorFromString(label.name)
|
||||
}
|
||||
|
||||
options.value.push(response)
|
||||
|
||||
return response
|
||||
})
|
||||
|
||||
selected.value = await Promise.all(promises)
|
||||
}
|
||||
})
|
||||
|
||||
function hashCode(str) {
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
function intToRGB(i) {
|
||||
const c = (i & 0x00FFFFFF)
|
||||
.toString(16)
|
||||
.toUpperCase()
|
||||
|
||||
return '00000'.substring(0, 6 - c.length) + c
|
||||
}
|
||||
|
||||
function generateColorFromString(str) {
|
||||
return intToRGB(hashCode(str))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu
|
||||
v-model="labels"
|
||||
by="id"
|
||||
name="labels"
|
||||
:options="options"
|
||||
option-attribute="name"
|
||||
clearable
|
||||
multiple
|
||||
searchable
|
||||
creatable
|
||||
>
|
||||
<template #label>
|
||||
<template v-if="labels.length">
|
||||
<span class="flex items-center -space-x-1">
|
||||
<span v-for="label of labels" :key="label.id" class="flex-shrink-0 w-2 h-2 mt-px rounded-full" :style="{ background: `#${label.color}` }" />
|
||||
</span>
|
||||
<span>{{ labels.length }} label{{ labels.length > 1 ? 's' : '' }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-500 dark:text-gray-400 truncate">Select labels</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full"
|
||||
:style="{ background: `#${option.color}` }"
|
||||
/>
|
||||
<span class="truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
|
||||
<template #option-create="{ option }">
|
||||
<span class="flex-shrink-0">New label:</span>
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full -mx-1"
|
||||
:style="{ background: `#${generateColorFromString(option.name)}` }"
|
||||
/>
|
||||
<span class="block truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -0,0 +1,105 @@
|
||||
<script setup lang="ts">
|
||||
const options = ref([
|
||||
{ id: 1, name: 'bug', color: 'd73a4a' },
|
||||
{ id: 2, name: 'documentation', color: '0075ca' },
|
||||
{ id: 3, name: 'duplicate', color: 'cfd3d7' },
|
||||
{ id: 4, name: 'enhancement', color: 'a2eeef' },
|
||||
{ id: 5, name: 'good first issue', color: '7057ff' },
|
||||
{ id: 6, name: 'help wanted', color: '008672' },
|
||||
{ id: 7, name: 'invalid', color: 'e4e669' },
|
||||
{ id: 8, name: 'question', color: 'd876e3' },
|
||||
{ id: 9, name: 'wontfix', color: 'ffffff' }
|
||||
])
|
||||
|
||||
const selected = ref([])
|
||||
|
||||
const labels = computed({
|
||||
get: () => selected.value,
|
||||
set: async (labels) => {
|
||||
const promises = labels.map(async (label) => {
|
||||
if (label.id) {
|
||||
return label
|
||||
}
|
||||
|
||||
// In a real app, you would make an API call to create the label
|
||||
const response = {
|
||||
id: options.value.length + 1,
|
||||
name: label.name,
|
||||
color: generateColorFromString(label.name)
|
||||
}
|
||||
|
||||
options.value.push(response)
|
||||
|
||||
return response
|
||||
})
|
||||
|
||||
selected.value = await Promise.all(promises)
|
||||
}
|
||||
})
|
||||
|
||||
function hashCode(str) {
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
function intToRGB(i) {
|
||||
const c = (i & 0x00FFFFFF)
|
||||
.toString(16)
|
||||
.toUpperCase()
|
||||
|
||||
return '00000'.substring(0, 6 - c.length) + c
|
||||
}
|
||||
|
||||
function generateColorFromString(str) {
|
||||
return intToRGB(hashCode(str))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<USelectMenu
|
||||
v-model="labels"
|
||||
by="id"
|
||||
name="labels"
|
||||
:options="options"
|
||||
option-attribute="name"
|
||||
clearable
|
||||
multiple
|
||||
searchable
|
||||
creatable
|
||||
>
|
||||
<template #label>
|
||||
<template v-if="labels.length">
|
||||
<span class="flex items-center -space-x-1">
|
||||
<span v-for="label of labels" :key="label.id" class="flex-shrink-0 w-2 h-2 mt-px rounded-full" :style="{ background: `#${label.color}` }" />
|
||||
</span>
|
||||
<span>{{ labels.length }} label{{ labels.length > 1 ? 's' : '' }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="text-gray-500 dark:text-gray-400 truncate">Select labels</span>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full"
|
||||
:style="{ background: `#${option.color}` }"
|
||||
/>
|
||||
<span class="truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
|
||||
<template #option-create="{ option }">
|
||||
<span class="flex-shrink-0">New label:</span>
|
||||
<span
|
||||
class="flex-shrink-0 w-2 h-2 mt-px rounded-full -mx-1"
|
||||
:style="{ background: `#${generateColorFromString(option.name)}` }"
|
||||
/>
|
||||
<span class="block truncate">{{ option.name }}</span>
|
||||
</template>
|
||||
<template #clearable="{ onClear }">
|
||||
<UButton icon="i-heroicons-trash-20-solid" size="xs" class="text-gray-400 dark:text-gray-500" variant="ghost" @click.capture.stop="onClear" />
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
@@ -31,7 +31,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ULandingGrid ref="section" class="lg:grid-cols-10 lg:gap-8 overflow-hidden p-1">
|
||||
<ULandingGrid ref="section" class="lg:grid-cols-10 lg:gap-8 overflow-hidden p-px">
|
||||
<div :ref="(el) => (refs[1] = el)" class="col-span-8 flex items-center animate-top">
|
||||
<RangeExample />
|
||||
</div>
|
||||
|
||||
@@ -7,29 +7,13 @@ description: 'Learn how to install and configure Nuxt UI in your application.'
|
||||
|
||||
### Add to a Nuxt project
|
||||
|
||||
1. Install the `@nuxt/ui` dependency in your project:
|
||||
1. Add `@nuxt/ui` module to your project:
|
||||
|
||||
::code-group
|
||||
|
||||
```bash [pnpm]
|
||||
pnpm add @nuxt/ui@2
|
||||
```bash
|
||||
npx nuxi@latest module add ui
|
||||
```
|
||||
|
||||
```bash [yarn]
|
||||
yarn add @nuxt/ui@2
|
||||
```
|
||||
|
||||
```bash [npm]
|
||||
npm install @nuxt/ui@2
|
||||
```
|
||||
|
||||
```bash [bun]
|
||||
bun add @nuxt/ui@2
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
2. Register the `@nuxt/ui` module in your `nuxt.config.ts`:
|
||||
2. Add it to the `modules` section in your `nuxt.config.ts`:
|
||||
|
||||
```ts [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
@@ -45,7 +29,7 @@ That's it! You can now use all the components and composables in your Nuxt app
|
||||
The Nuxt Starter template is available from the `nuxi init` command.
|
||||
|
||||
```bash
|
||||
npx nuxi@latest init -t ui2
|
||||
npx nuxi@latest init -t ui
|
||||
```
|
||||
|
||||
Please check [nuxt/starter](https://github.com/nuxt/starter/tree/ui) for details.
|
||||
@@ -110,7 +94,7 @@ You can read more about this in the [Theming](/getting-started/theming#dark-mode
|
||||
|
||||
## TypeScript
|
||||
|
||||
This module is written in TypeScript and provides typings for all the components and composables. You can look at the [source code](https://github.com/nuxt/ui/tree/v2/src/runtime/types) to see all the available types.
|
||||
This module is written in TypeScript and provides typings for all the components and composables. You can look at the [source code](https://github.com/nuxt/ui/tree/dev/src/runtime/types) to see all the available types.
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb" to="https://nuxt.com/docs/guide/concepts/typescript" target="_blank"}
|
||||
You can read more about TypeScript on the official Nuxt documentation.
|
||||
@@ -246,7 +230,7 @@ You can also add the following to your `.vscode/settings.json` to enable Intelli
|
||||
| `prefix` | `u` | Define the prefix of the imported components. |
|
||||
| `global` | `false` | Expose components globally. |
|
||||
| `safelistColors` | `['primary']` | Force safelisting of colors to need be purged. |
|
||||
| `disableGlobalStyles` | `false` | Disable [global CSS styles](https://github.com/nuxt/ui/blob/v2/src/runtime/ui.css) injected by the module. |
|
||||
| `disableGlobalStyles` | `false` | Disable [global CSS styles](https://github.com/nuxt/ui/blob/dev/src/runtime/ui.css) injected by the module. |
|
||||
|
||||
Configure options in your `nuxt.config.ts` as such:
|
||||
|
||||
@@ -259,21 +243,19 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
## Continuous Releases
|
||||
## Edge
|
||||
|
||||
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.
|
||||
To use the latest updates pushed on the [`dev`](https://github.com/nuxt/ui/tree/dev) branch, you can use `@nuxt/ui-edge`.
|
||||
|
||||
Preview releases are automatically generated for every commit to the `dev` branch and pull requests targeting the `dev` branch. To use it into your project, replace the version in your `package.json` with the commit hash or pull request number.
|
||||
Update your `package.json` to the following:
|
||||
|
||||
```diff [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^2.21.0",
|
||||
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@bf1c9e7",
|
||||
"devDependencies": {
|
||||
- "@nuxt/ui": "^2.11.0"
|
||||
+ "@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::note
|
||||
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
|
||||
::
|
||||
Then run `pnpm install`, `yarn install` or `npm install`.
|
||||
|
||||
@@ -25,7 +25,7 @@ Try to change the `primary` and `gray` colors by clicking on the :u-icon{name="i
|
||||
|
||||
As this module uses Tailwind CSS under the hood, you can use any of the [Tailwind CSS colors](https://tailwindcss.com/docs/customizing-colors#color-palette-reference) or your own custom colors or groups, such as `brand.primary`. By default, the `primary` color is `green` and the `gray` color is `cool`.
|
||||
|
||||
When [using custom colors](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [adding additional colors](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) through the `extend` key in your `tailwind.config.ts`, you'll need to make sure to define all the shades from `50` to `950` as most of them are used in the components config defined in [`ui.config/`](https://github.com/nuxt/ui/tree/v2/src/runtime/ui.config) directory. You can [generate your colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) using tools such as https://uicolors.app/ for example.
|
||||
When [using custom colors](https://tailwindcss.com/docs/customizing-colors#using-custom-colors) or [adding additional colors](https://tailwindcss.com/docs/customizing-colors#adding-additional-colors) through the `extend` key in your `tailwind.config.ts`, you'll need to make sure to define all the shades from `50` to `950` as most of them are used in the components config defined in [`ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config) directory. You can [generate your colors](https://tailwindcss.com/docs/customizing-colors#generating-colors) using tools such as https://uicolors.app/ for example.
|
||||
|
||||
```ts [tailwind.config.ts]
|
||||
import type { Config } from 'tailwindcss'
|
||||
@@ -118,7 +118,7 @@ export default defineAppConfig({
|
||||
})
|
||||
```
|
||||
|
||||
The available options for each component should auto-complete, and you can review the defaults for each component using your IDE's function such as `Cmd`+`Click` (these files can be found in [`src/runtime/ui.config/`](https://github.com/nuxt/ui/tree/v2/src/runtime/ui.config)).
|
||||
The available options for each component should auto-complete, and you can review the defaults for each component using your IDE's function such as `Cmd`+`Click` (these files can be found in [`src/runtime/ui.config/`](https://github.com/nuxt/ui/tree/dev/src/runtime/ui.config)).
|
||||
|
||||
Thanks to [tailwind-merge](https://github.com/dcastil/tailwind-merge), the `app.config.ts` is smartly merged with the default config. This means you don't have to rewrite everything.
|
||||
|
||||
@@ -221,52 +221,6 @@ export default defineAppConfig({
|
||||
})
|
||||
```
|
||||
|
||||
### Extend Tailwind Merge
|
||||
|
||||
Tailwind Merge is a library that allows you to efficiently merge Tailwind CSS classes. It is used by this module to merge the classes from the `ui` prop, the `class` attribute, and the default classes.
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb" to="https://github.com/dcastil/tailwind-merge" target="_blank"}
|
||||
Learn more about Tailwind Merge.
|
||||
::
|
||||
|
||||
By default, Tailwind Merge doesn't handle custom Tailwind CSS configuration like custom colors, spacing, or other utilities you may have defined. You'll need to extend it to handle your custom configuration.
|
||||
|
||||
You can extend Tailwind Merge by using the `tailwindMerge` option in your `app.config.ts`:
|
||||
|
||||
::code-group
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
tailwindMerge: {
|
||||
extend: {
|
||||
theme: {
|
||||
spacing: ['sm', 'md', 'lg', 'xl', '2xl']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```ts [tailwind.config.ts]
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
export default <Partial<Config>>{
|
||||
theme: {
|
||||
extend: {
|
||||
spacing: {
|
||||
sm: '0.5rem',
|
||||
md: '1rem',
|
||||
lg: '1.5rem',
|
||||
xl: '2rem',
|
||||
'2xl': '2.5rem'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
::
|
||||
|
||||
## Dark mode
|
||||
|
||||
All the components are styled with dark mode in mind.
|
||||
@@ -389,12 +343,6 @@ export default defineAppConfig({
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
},
|
||||
inputMenu: {
|
||||
default: {
|
||||
selectedIcon: 'i-octicon-check-24',
|
||||
trailingIcon: 'i-octicon-chevron-down-24'
|
||||
}
|
||||
},
|
||||
select: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24',
|
||||
@@ -430,9 +378,6 @@ export default defineAppConfig({
|
||||
sortButton: {
|
||||
icon: 'i-octicon-arrow-switch-24'
|
||||
},
|
||||
expandButton: {
|
||||
icon: 'i-octicon-chevron-down-24'
|
||||
},
|
||||
loadingState: {
|
||||
icon: 'i-octicon-sync-24'
|
||||
},
|
||||
@@ -466,21 +411,6 @@ export default defineAppConfig({
|
||||
default: {
|
||||
divider: 'i-octicon-chevron-right-24'
|
||||
}
|
||||
},
|
||||
carousel: {
|
||||
default: {
|
||||
prevButton: {
|
||||
icon: 'i-octicon-chevron-left-24'
|
||||
},
|
||||
nextButton: {
|
||||
icon: 'i-octicon-chevron-right-24'
|
||||
}
|
||||
}
|
||||
},
|
||||
toggle: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -49,22 +49,18 @@ defineShortcuts({
|
||||
Shortcuts keys are written as the literal keyboard key value. Combinations are made with `_` separator. Chained shortcuts are made with `-` separator.
|
||||
|
||||
Modifiers are also available:
|
||||
| Modifier | Description |
|
||||
|----------|-------------|
|
||||
| `meta` | Acts as `Command (⌘)` on macOS and `Control (Ctrl)` on Windows/Linux. |
|
||||
| `ctrl` | Represents the `Control (Ctrl)` key across all operating systems. |
|
||||
| `shift` | Represents the `Shift` key, only needed for alphabetic keys (e.g., `shift_e`). |
|
||||
- `meta`: acts as `Command` for MacOS and `Control` for others
|
||||
- `ctrl`: acts as `Control`
|
||||
- `shift`: acts as `Shift` and is only necessary for alphabetic keys
|
||||
|
||||
Examples of keys:
|
||||
| Shortcut Key | Action |
|
||||
|---------------|--------|
|
||||
| `escape` | Triggers when `Esc` is pressed |
|
||||
| `meta_k` | `⌘ + K` on Mac, `Ctrl + K` on Windows/Linux |
|
||||
| `ctrl_k` | Triggers `Ctrl + K` on all OS |
|
||||
| `shift_e` | Triggers `Shift + E` on all OS |
|
||||
| `?` | Triggers `?` (Shift + `/` on US Mac keyboards) |
|
||||
| `g-d` | Triggers when `g` then `d` are pressed within 800ms |
|
||||
| `arrowleft` | Triggers when `←` is pressed (also: `arrowright`, `arrowup`, `arrowdown`) |
|
||||
- `escape`: will trigger by hitting `Esc`
|
||||
- `meta_k`: will trigger by hitting `⌘` and `K` at the same time on MacOS, and `Ctrl` and `K` on Windows and Linux
|
||||
- `ctrl_k`: will trigger by hitting `Ctrl` and `K` at the same time on MacOS, Windows and Linux
|
||||
- `shift_e`: will trigger by hitting `Shift` and `E` at the same time on MacOS, Windows and Linux
|
||||
- `?`: will trigger by hitting `?` on some keyboard layouts, or for example `Shift` and `/`, which results in `?` on US Mac keyboards
|
||||
- `g-d`: will trigger by hitting `g` then `d` with a maximum delay of 800ms by default
|
||||
- `arrowleft`: will trigger by hitting `←` (also: `arrowright`, `arrowup`, `arrowdown`)
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
For a complete list of available shortcut keys, refer to the [`KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values) API docs. Note the `KeyboardEvent.key` has to be written in lowercase.
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/disclosure'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Accordion.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display an alert element to draw attention.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Alert.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Alert.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display an image that represents a resource or a group of resources
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Avatar.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Avatar.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a short text to represent a status or a category.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Badge.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Badge.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -141,74 +141,6 @@ Badge
|
||||
You can customize the whole [preset](#preset) by using the `ui` prop.
|
||||
::
|
||||
|
||||
### Icon
|
||||
|
||||
Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
|
||||
|
||||
Use the `leading` and `trailing` props to set the icon position or the `leading-icon` and `trailing-icon` props to set a different icon for each position.
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
icon: 'i-heroicons-rocket-launch'
|
||||
size: 'sm'
|
||||
color: 'primary'
|
||||
variant: 'solid'
|
||||
label: Badge
|
||||
trailing: false
|
||||
options:
|
||||
- name: variant
|
||||
restriction: only
|
||||
values:
|
||||
- solid
|
||||
excludedProps:
|
||||
- icon
|
||||
- label
|
||||
---
|
||||
::
|
||||
|
||||
## Slots
|
||||
|
||||
### `leading`
|
||||
|
||||
Use the `#leading` slot to set the content of the leading icon.
|
||||
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" />
|
||||
baseProps:
|
||||
color: 'gray'
|
||||
props:
|
||||
label: Badge
|
||||
color: 'gray'
|
||||
excludedProps:
|
||||
- color
|
||||
---
|
||||
|
||||
#leading
|
||||
:u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs"}
|
||||
::
|
||||
|
||||
### `trailing`
|
||||
|
||||
Use the `#trailing` slot to set the content of the trailing icon.
|
||||
|
||||
::component-card
|
||||
---
|
||||
slots:
|
||||
trailing: <UIcon name="i-heroicons-rocket-launch" class="w-4 h-4" />
|
||||
props:
|
||||
label: Badge
|
||||
color: 'gray'
|
||||
excludedProps:
|
||||
- color
|
||||
---
|
||||
|
||||
#trailing
|
||||
:u-icon{name="i-heroicons-rocket-launch" class="w-4 h-4"}
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -4,7 +4,7 @@ description: A list of links that indicate the current page's location within a
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/Breadcrumb.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Breadcrumb.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Create a button with icon or link capabilities.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Button.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Button.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a card for content with a header, body and footer.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Card.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Card.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display images or content in a scrollable area.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Carousel.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Carousel.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a checkbox field.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Checkbox.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Checkbox.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a chip indicator on any component.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Chip.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Chip.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -7,7 +7,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/combobox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/CommandPalette.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -274,7 +274,7 @@ hiddenCode: true
|
||||
---
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/CommandPaletteExampleThemeAlgolia.vue#L23" target="_blank"}
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/CommandPaletteExampleThemeAlgolia.vue#L23" target="_blank"}
|
||||
Take a look at the component!
|
||||
::
|
||||
|
||||
@@ -290,6 +290,6 @@ hiddenCode: true
|
||||
---
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/CommandPaletteExampleThemeRaycast.vue#L30" target="_blank"}
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/CommandPaletteExampleThemeRaycast.vue#L30" target="_blank"}
|
||||
Take a look at the component!
|
||||
::
|
||||
|
||||
@@ -3,7 +3,7 @@ description: A container lets you center and constrain the width of your content
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Container.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Container.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a menu that appears on right click.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/ContextMenu.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/ContextMenu.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a separator between content.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Divider.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Divider.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: https://headlessui.com/v1/vue/menu
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Dropdown.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a label and additional informations around a form element.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/FormGroup.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/FormGroup.vue
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Collect and validate form data.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Form.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Form.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -14,7 +14,7 @@ It works with the [FormGroup](/components/form-group) component to display error
|
||||
|
||||
The form component requires two props:
|
||||
- `state` - a reactive object holding the form's state.
|
||||
- `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).
|
||||
- `schema` - a schema object from a validation library like [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod), [Joi](https://github.com/hapijs/joi), [Valibot](https://github.com/fabian-hiller/valibot) or [Superstruct](https://github.com/ianstormtaylor/superstruct).
|
||||
|
||||
::callout{icon="i-heroicons-light-bulb"}
|
||||
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
||||
@@ -190,7 +190,7 @@ hiddenCode: true
|
||||
---
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/FormExampleElements.vue" target="_blank"}
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/FormExampleElements.vue" target="_blank"}
|
||||
Take a look at the component!
|
||||
::
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a list of horizontal links.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/HorizontalNavigation.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/HorizontalNavigation.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -7,7 +7,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/combobox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/InputMenu.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display an input field.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Input.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Input.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -142,7 +142,7 @@ props:
|
||||
|
||||
### Loading
|
||||
|
||||
Use the `loading` prop to show a loading icon in the Input.
|
||||
Use the `loading` prop to show a loading icon and disable the Input.
|
||||
|
||||
Use the `loading-icon` prop to set a different icon or change it globally in `ui.input.default.loadingIcon`. Defaults to `i-heroicons-arrow-path-20-solid`.
|
||||
|
||||
@@ -173,13 +173,6 @@ baseProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Limit
|
||||
|
||||
Use the `maxlength` prop to limit the length of the Input.
|
||||
|
||||
:component-example{component="input-example-max-length"}
|
||||
|
||||
|
||||
## Slots
|
||||
|
||||
### `leading`
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a keyboard key in a text block.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Kbd.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Kbd.vue
|
||||
navigation:
|
||||
title: 'Kbd'
|
||||
---
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Render a NuxtLink but with superpowers.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Link.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Link.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -14,7 +14,6 @@ The Link component is a wrapper around [`<NuxtLink>`](https://nuxt.com/docs/api/
|
||||
- `inactive-class` prop to set a class when the link is inactive, `active-class` is used when active.
|
||||
- `exact` prop to style with `active-class` when the link is active and the route is exactly the same as the current route.
|
||||
- `exact-query` and `exact-hash` props to style with `active-class` when the link is active and the query or hash is exactly the same as the current query or hash.
|
||||
- use `exact-query="partial"` to style with `active-class` when the link is active and the query partially match the current query.
|
||||
|
||||
The incentive behind this is to provide the same API as NuxtLink back in Nuxt 2 / Vue 2. You can read more about it in the Vue Router [migration from Vue 2](https://router.vuejs.org/guide/migration/#removal-of-the-exact-prop-in-router-link) guide.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a gauge meter that fills or depletes.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Meter.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Meter.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/dialog'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/Modal.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Modal.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a toast notification in your app.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/Notification.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Notification.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -137,9 +137,9 @@ excludedProps:
|
||||
|
||||
### Timeout
|
||||
|
||||
Use the `timeout` prop to configure how long the Notification will remain. The default value is `5000`, set it to `0` to disable the timeout. The `pauseTimeoutOnHover` prop (`true` by default) controls whether hovering the notification should pause the timeout.
|
||||
Use the `timeout` prop to configure how long the Notification will remain. The default value is `5000`, set it to `0` to disable the timeout.
|
||||
|
||||
You will see a progress bar at the bottom of the Notification which will indicate the remaining time. When hovering the Notification, the progress bar will be paused if `pauseTimeoutOnHover` is enabled; otherwise, it won't stop.
|
||||
You will see a progress bar at the bottom of the Notification which will indicate the remaining time. When hovering the Notification, the progress bar will be paused.
|
||||
|
||||
::component-card
|
||||
---
|
||||
@@ -149,7 +149,6 @@ baseProps:
|
||||
description: 'This is a notification.'
|
||||
props:
|
||||
timeout: 60000
|
||||
pauseTimeoutOnHover: true
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Add a pagination to handle pages.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/Pagination.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Pagination.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/popover'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/Popover.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Popover.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Show a horizontal bar to indicate task progression.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Progress.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Progress.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a set of radio buttons.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/RadioGroup.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/RadioGroup.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a range field
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Range.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Range.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -7,7 +7,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/listbox'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/SelectMenu.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/SelectMenu.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -156,7 +156,38 @@ Use the `searchableLazy` prop to control the immediacy of data requests.
|
||||
---
|
||||
component: 'select-menu-example-search-async'
|
||||
componentProps:
|
||||
class: 'w-full lg:w-48'
|
||||
class: 'w-full lg:w-48'
|
||||
---
|
||||
::
|
||||
|
||||
## Clearable
|
||||
The `clearable` prop allows users to easily remove their selected option(s) with a clear button.
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'select-menu-example-clearable'
|
||||
componentProps:
|
||||
class: 'w-full lg:w-52'
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
### Customization
|
||||
#### Slot Props
|
||||
The slot provides four key props:
|
||||
|
||||
| Prop | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `selected` | `Object` | The currently selected value/item in the component |
|
||||
| `disabled` | `Boolean` | Whether the component is in a disabled state |
|
||||
| `loading` | `Boolean` | Whether the component is in a loading state |
|
||||
| `onClear` | `Function` | Callback function to clear the selected value when the clear button is clicked |
|
||||
|
||||
::component-example
|
||||
---
|
||||
component: 'select-menu-example-clearable-customization'
|
||||
componentProps:
|
||||
class: 'w-full lg:w-52'
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a select field.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Select.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Select.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a placeholder while content is loading.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Skeleton.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Skeleton.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/dialog'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/Slideover.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Slideover.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Display data in a table.'
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/data/Table.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/data/Table.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
@@ -62,7 +62,7 @@ extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-columns-selectable'
|
||||
componentProps:
|
||||
class: 'flex-1 flex-col overflow-hidden min-h-[230px]'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -311,9 +311,9 @@ const onUpdateSelection = (selectedRows: any[]) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTable
|
||||
v-model="selected"
|
||||
:rows="people"
|
||||
<UTable
|
||||
v-model="selected"
|
||||
:rows="people"
|
||||
@select:all="onHandleSelectAll"
|
||||
@update:modelValue="onUpdateSelection"
|
||||
/>
|
||||
@@ -346,7 +346,7 @@ componentProps:
|
||||
|
||||
### Contextmenu
|
||||
|
||||
Use the `contextmenu` listener on your Table to make the rows right-clickable. The function will receive the original event as the first argument and the row as the second argument.
|
||||
Use the `contextmenu` listener on your Table to make the rows righ-clickable. The function will receive the original event as the first argument and the row as the second argument.
|
||||
|
||||
You can use this to open a [ContextMenu](/components/context-menu) for that row.
|
||||
|
||||
@@ -598,7 +598,7 @@ This slot allows you to customize the checkbox appearance in the table header fo
|
||||
#### Usage
|
||||
```vue
|
||||
<template>
|
||||
<UTable v-model="selectable">
|
||||
<UTable v-model="selectable">
|
||||
<template #select-header="{ checked, change, indeterminate }">
|
||||
<!-- Place your custom component here -->
|
||||
</template>
|
||||
@@ -620,7 +620,7 @@ This slot allows you to customize the checkbox appearance in the table header fo
|
||||
<UTable>
|
||||
<!-- Header checkbox customization -->
|
||||
<template #select-header="{ indeterminate, checked, change }">
|
||||
<input
|
||||
<input
|
||||
type="checkbox"
|
||||
:indeterminate="indeterminate"
|
||||
:checked="checked"
|
||||
@@ -658,7 +658,7 @@ This slot allows you to customize the checkbox appearance for each row in the ta
|
||||
<UTable>
|
||||
<!-- Row checkbox customization -->
|
||||
<template #select-data="{ checked, change }">
|
||||
<input
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="checked"
|
||||
@change="e => change(e.target.checked)"
|
||||
@@ -769,6 +769,6 @@ hiddenCode: true
|
||||
---
|
||||
::
|
||||
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/TableExampleAdvanced.vue" target="_blank"}
|
||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/TableExampleAdvanced.vue" target="_blank"}
|
||||
Take a look at the component!
|
||||
::
|
||||
|
||||
@@ -3,7 +3,7 @@ description: A set of tab panels that are displayed one at a time.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/Tabs.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Tabs.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display a textarea field.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Textarea.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Textarea.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -6,7 +6,7 @@ links:
|
||||
to: 'https://headlessui.com/v1/vue/switch'
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Toggle.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Toggle.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Display content that appears on hover next to an element.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/Tooltip.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Tooltip.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -4,7 +4,7 @@ description: Display a list of vertical links.
|
||||
links:
|
||||
- label: GitHub
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/VerticalNavigation.vue
|
||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/VerticalNavigation.vue
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -3,7 +3,7 @@ title: '<span class="text-primary">Nuxt UI</span> Releases'
|
||||
head.title: Releases
|
||||
description: Follow the latest releases and updates happening on the nuxt/ui repository.
|
||||
links:
|
||||
- label: Get started
|
||||
- label: Get Started
|
||||
trailingIcon: i-heroicons-arrow-right-20-solid
|
||||
to: /getting-started
|
||||
size: md
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
<div>
|
||||
<NuxtLoadingIndicator />
|
||||
|
||||
<Banner />
|
||||
|
||||
<Header :links="links" />
|
||||
|
||||
<UContainer>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default defineNuxtConfig({
|
||||
]
|
||||
: [
|
||||
'@nuxt/ui-pro',
|
||||
process.env.NUXT_GITHUB_TOKEN && ['github:nuxt/ui-pro/.docs#v1', { giget: { auth: process.env.NUXT_GITHUB_TOKEN } }]
|
||||
process.env.NUXT_GITHUB_TOKEN && ['github:nuxt/ui-pro/.docs#dev', { giget: { auth: process.env.NUXT_GITHUB_TOKEN } }]
|
||||
].filter(Boolean),
|
||||
|
||||
modules: [
|
||||
@@ -26,11 +26,13 @@ export default defineNuxtConfig({
|
||||
module,
|
||||
'@nuxtjs/plausible',
|
||||
'@vueuse/nuxt',
|
||||
'nuxt-component-meta'
|
||||
'nuxt-component-meta',
|
||||
'nuxt-cloudflare-analytics',
|
||||
'modules/content-examples-code'
|
||||
],
|
||||
|
||||
site: {
|
||||
url: 'https://ui2.nuxt.com'
|
||||
url: 'https://ui.nuxt.com'
|
||||
},
|
||||
|
||||
content: {
|
||||
@@ -52,7 +54,7 @@ export default defineNuxtConfig({
|
||||
prefix: '/pro',
|
||||
driver: 'github',
|
||||
repo: 'nuxt/ui-pro',
|
||||
branch: 'v1',
|
||||
branch: 'dev',
|
||||
dir: '.docs/content/pro',
|
||||
token: process.env.NUXT_GITHUB_TOKEN || ''
|
||||
}
|
||||
@@ -93,11 +95,6 @@ export default defineNuxtConfig({
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
include: ['date-fns']
|
||||
},
|
||||
server: {
|
||||
fs: {
|
||||
allow: process.env.NUXT_UI_PRO_PATH ? [resolve(process.env.NUXT_UI_PRO_PATH)] : undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -118,6 +115,11 @@ export default defineNuxtConfig({
|
||||
}
|
||||
},
|
||||
|
||||
cloudflareAnalytics: {
|
||||
token: '1e2b0c5e9a214f0390b9b94e043d8d4c',
|
||||
scriptPath: false
|
||||
},
|
||||
|
||||
componentMeta: {
|
||||
exclude: [
|
||||
'@nuxt/content',
|
||||
|
||||
@@ -3,28 +3,28 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@iconify-json/heroicons": "^1.2.2",
|
||||
"@iconify-json/lucide": "^1.2.57",
|
||||
"@iconify-json/simple-icons": "^1.2.44",
|
||||
"@iconify-json/vscode-icons": "^1.2.23",
|
||||
"@iconify-json/heroicons": "^1.2.1",
|
||||
"@iconify-json/simple-icons": "^1.2.11",
|
||||
"@iconify-json/vscode-icons": "^1.2.2",
|
||||
"@nuxt/content": "^2.13.4",
|
||||
"@nuxt/fonts": "^0.11.4",
|
||||
"@nuxt/image": "^1.10.0",
|
||||
"@nuxt/fonts": "^0.10.2",
|
||||
"@nuxt/image": "^1.8.1",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@fdb0248",
|
||||
"@nuxtjs/plausible": "^1.2.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"@vueuse/nuxt": "^13.5.0",
|
||||
"@nuxt/ui-pro": "^1.5.0",
|
||||
"@nuxtjs/plausible": "^1.0.3",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"@vueuse/nuxt": "^11.2.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^4.0.1",
|
||||
"nuxt-component-meta": "^0.12.1",
|
||||
"nuxt-og-image": "^5.1.9",
|
||||
"prettier": "^3.6.2",
|
||||
"ufo": "^1.6.1",
|
||||
"nuxt": "^3.14.159",
|
||||
"nuxt-cloudflare-analytics": "^1.0.8",
|
||||
"nuxt-component-meta": "^0.9.0",
|
||||
"nuxt-og-image": "^3.0.8",
|
||||
"prettier": "^3.3.3",
|
||||
"ufo": "^1.5.4",
|
||||
"v-calendar": "^3.1.2",
|
||||
"valibot": "^1.1.0",
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^4.0.5"
|
||||
"valibot": "^0.42.1",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ defineOgImageComponent('Docs', {
|
||||
const communityLinks = computed(() => [{
|
||||
icon: 'i-heroicons-pencil-square',
|
||||
label: 'Edit this page',
|
||||
to: `https://github.com/nuxt/ui/edit/v2/docs/content/${page?.value?._file}`,
|
||||
to: `https://github.com/nuxt/ui/edit/dev/docs/content/${page?.value?._file}`,
|
||||
target: '_blank'
|
||||
}, {
|
||||
icon: 'i-heroicons-star',
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get started" size="lg" to="/getting-started/installation" />
|
||||
<UButton label="Explore components" trailing-icon="i-heroicons-arrow-right-20-solid" color="gray" size="lg" to="/components/button" />
|
||||
<UButton label="Get Started" trailing-icon="i-heroicons-arrow-right-20-solid" size="lg" to="/getting-started/installation" />
|
||||
|
||||
<!-- <UInput
|
||||
<UInput
|
||||
v-model="source"
|
||||
color="gray"
|
||||
readonly
|
||||
@@ -48,7 +47,7 @@
|
||||
@click="copy(source)"
|
||||
/>
|
||||
</template>
|
||||
</UInput> -->
|
||||
</UInput>
|
||||
</template>
|
||||
|
||||
<ClientOnly>
|
||||
@@ -193,16 +192,16 @@
|
||||
</div>
|
||||
</ULandingHero>
|
||||
|
||||
<!-- <ULandingSection v-for="(section, index) in page.pro.sections" :key="index" v-bind="section" class="!pt-0">
|
||||
<ULandingSection v-for="(section, index) in page.pro.sections" :key="index" v-bind="section" class="!pt-0">
|
||||
<MDC
|
||||
v-if="section.code"
|
||||
:value="section.code"
|
||||
tag="pre"
|
||||
class="prose prose-primary dark:prose-invert max-w-none"
|
||||
/>
|
||||
</ULandingSection> -->
|
||||
</ULandingSection>
|
||||
|
||||
<!-- <div ref="sectionRef" :style="{ '--y': `${y}px`, '--inc': `${inc}px` }" class="_screen_xl">
|
||||
<div ref="sectionRef" :style="{ '--y': `${y}px`, '--inc': `${inc}px` }" class="_screen_xl">
|
||||
<ULandingSection class="sticky h-screen top-0 flex !pb-16" :ui="{ container: 'flex-1 sm:gap-y-12' }">
|
||||
<template #title>
|
||||
<Transition name="fade" mode="out-in">
|
||||
@@ -282,6 +281,8 @@
|
||||
<template #page-body>
|
||||
<div class="-mt-8 prose prose-primary prose-sm dark:prose-invert max-w-none">
|
||||
<MDC :value="md" tag="div" />
|
||||
|
||||
<!-- <hr class="border-gray-800/10 dark:border-gray-200/10 !mt-5"> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -324,7 +325,7 @@
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get started" icon="i-heroicons-rocket-launch" size="md" />
|
||||
<UButton label="Get Started" icon="i-heroicons-rocket-launch" size="md" />
|
||||
|
||||
<UInput
|
||||
model-value="npm i @nuxt/ui"
|
||||
@@ -373,9 +374,9 @@
|
||||
</ULandingSection>
|
||||
|
||||
<div class="h-[calc(var(--inc)*42)]" />
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="_not_screen_xl">
|
||||
<div class="_not_screen_xl">
|
||||
<ULandingSection>
|
||||
<template #title>
|
||||
<span v-html="page.pro.landing?.title" />
|
||||
@@ -402,15 +403,15 @@
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.ogg" type="video/ogg">
|
||||
</video>
|
||||
</ULandingSection>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { NavItem } from '@nuxt/content'
|
||||
import { useElementBounding, useWindowScroll, breakpointsTailwind, useBreakpoints } from '@vueuse/core'
|
||||
// import type { HomeProBlock } from '~/types'
|
||||
import type { ParsedContent, NavItem } from '@nuxt/content'
|
||||
import { useElementBounding, useWindowScroll, useElementSize, breakpointsTailwind, useBreakpoints } from '@vueuse/core'
|
||||
import type { HomeProBlock } from '~/types'
|
||||
|
||||
const { data: page } = await useAsyncData('index', () => queryContent('/').findOne())
|
||||
const { data: module } = await useFetch<{
|
||||
@@ -422,7 +423,6 @@ const { data: module } = await useFetch<{
|
||||
username: string
|
||||
}[]
|
||||
}>('https://api.nuxt.com/modules/ui', {
|
||||
key: 'stats',
|
||||
transform: ({ stats, contributors }) => ({ stats, contributors })
|
||||
})
|
||||
|
||||
@@ -434,321 +434,321 @@ useSeoMeta({
|
||||
ogTitle: page.value.title,
|
||||
description: page.value.description,
|
||||
ogDescription: page.value.description,
|
||||
ogImage: 'https://ui2.nuxt.com/social-card.png',
|
||||
twitterImage: 'https://ui2.nuxt.com/social-card.png'
|
||||
ogImage: 'https://ui.nuxt.com/social-card.png',
|
||||
twitterImage: 'https://ui.nuxt.com/social-card.png'
|
||||
})
|
||||
|
||||
// const source = ref('npx nuxi@latest module add ui')
|
||||
const source = ref('npx nuxi@latest module add ui')
|
||||
const sectionRef = ref()
|
||||
// const demoRef = ref(null)
|
||||
const demoRef = ref(null)
|
||||
const start = ref(0)
|
||||
|
||||
// const { $ui } = useNuxtApp()
|
||||
// const { height } = useElementSize(demoRef)
|
||||
const { $ui } = useNuxtApp()
|
||||
const { height } = useElementSize(demoRef)
|
||||
const { top } = useElementBounding(sectionRef)
|
||||
const { y } = useWindowScroll()
|
||||
const config = useRuntimeConfig().public
|
||||
// const { copy, copied } = useClipboard({ source })
|
||||
const { copy, copied } = useClipboard({ source })
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
|
||||
const lgAndLarger = breakpoints.greaterOrEqual('lg')
|
||||
|
||||
const { format } = Intl.NumberFormat('en', { notation: 'compact' })
|
||||
|
||||
// const steps = {
|
||||
// header: 0,
|
||||
// footer: 5,
|
||||
// landing: 10,
|
||||
// docs: 27
|
||||
// }
|
||||
const steps = {
|
||||
header: 0,
|
||||
footer: 5,
|
||||
landing: 10,
|
||||
docs: 27
|
||||
}
|
||||
|
||||
// Computed
|
||||
|
||||
// const inc = computed(() => (height.value - 32 - 64 - 32 - 32) / 4)
|
||||
const inc = computed(() => (height.value - 32 - 64 - 32 - 32) / 4)
|
||||
|
||||
// const landingBlocks = computed(() => isAfterStep(steps.landing) && isBeforeStep(steps.docs)
|
||||
// ? [{
|
||||
// class: 'inset-x-0 top-20 bottom-20 overflow-hidden',
|
||||
// inactive: true,
|
||||
// children: [{
|
||||
// name: 'ULandingHero',
|
||||
// to: '/pro/components/landing-hero',
|
||||
// class: [
|
||||
// 'inset-4',
|
||||
// isAfterStep(steps.landing + 2) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
|
||||
// ].filter(Boolean).join(' '),
|
||||
// style: {
|
||||
// '--step-y': `${getStepY(steps.landing + 2)}px`
|
||||
// },
|
||||
// inactive: isAfterStep(steps.landing + 1),
|
||||
// children: [{
|
||||
// slot: 'landing-hero',
|
||||
// class: 'inset-4'
|
||||
// }]
|
||||
// }, isAfterStep(steps.landing + 2) && {
|
||||
// name: 'ULandingSection',
|
||||
// to: '/pro/components/landing-section',
|
||||
// class: [
|
||||
// 'inset-4',
|
||||
// isBeforeStep(steps.landing + 6) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]',
|
||||
// isAfterStep(steps.landing + 10) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
|
||||
// ].filter(Boolean).join(' '),
|
||||
// style: {
|
||||
// '--height': (inc.value * 4) + 'px',
|
||||
// '--step-y': `${getStepY(steps.landing + 10)}px`,
|
||||
// '--prev-step-y': `${getStepY(steps.landing + 2)}px`
|
||||
// },
|
||||
// inactive: isAfterStep(steps.landing + 7),
|
||||
// children: [{
|
||||
// slot: 'landing-section',
|
||||
// class: 'inset-x-4 top-16'
|
||||
// }, {
|
||||
// name: 'ULandingGrid',
|
||||
// to: '/pro/components/landing-grid',
|
||||
// class: ['inset-x-4 bottom-4 top-48', isAfterStep(steps.landing + 8) && 'grid grid-cols-4 gap-4 p-4'].filter(Boolean).join(' '),
|
||||
// inactive: isAfterStep(steps.landing + 8),
|
||||
// children: [isAfterStep(steps.landing + 9)
|
||||
// ? {
|
||||
// slot: 'landing-card-1',
|
||||
// class: '!relative'
|
||||
// }
|
||||
// : {
|
||||
// name: 'ULandingCard',
|
||||
// to: '/pro/components/landing-card',
|
||||
// class: '!relative h-full',
|
||||
// inactive: false
|
||||
// }, isAfterStep(steps.landing + 9)
|
||||
// ? {
|
||||
// slot: 'landing-card-2',
|
||||
// class: '!relative h-full'
|
||||
// }
|
||||
// : {
|
||||
// name: 'ULandingCard',
|
||||
// to: '/pro/components/landing-card',
|
||||
// class: '!relative h-full',
|
||||
// inactive: false
|
||||
// }, isAfterStep(steps.landing + 9)
|
||||
// ? {
|
||||
// slot: 'landing-card-3',
|
||||
// class: '!relative h-full'
|
||||
// }
|
||||
// : {
|
||||
// name: 'ULandingCard',
|
||||
// to: '/pro/components/landing-card',
|
||||
// class: '!relative h-full',
|
||||
// inactive: false
|
||||
// }, isAfterStep(steps.landing + 9)
|
||||
// ? {
|
||||
// slot: 'landing-card-4',
|
||||
// class: '!relative h-full'
|
||||
// }
|
||||
// : {
|
||||
// name: 'ULandingCard',
|
||||
// to: '/pro/components/landing-card',
|
||||
// class: '!relative h-full',
|
||||
// inactive: false
|
||||
// }]
|
||||
// }]
|
||||
// }, isAfterStep(steps.landing + 10) && {
|
||||
// name: 'ULandingSection',
|
||||
// to: '/pro/components/landing-section',
|
||||
// class: [
|
||||
// 'inset-4',
|
||||
// isBeforeStep(steps.landing + 14) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]'
|
||||
// ].filter(Boolean).join(' '),
|
||||
// style: {
|
||||
// '--height': (inc.value * 4) + 'px',
|
||||
// '--step-y': `${getStepY(steps.landing + 18)}px`,
|
||||
// '--prev-step-y': `${getStepY(steps.landing + 10)}px`
|
||||
// },
|
||||
// inactive: isAfterStep(steps.landing + 15),
|
||||
// children: [{
|
||||
// name: 'ULandingCTA',
|
||||
// class: 'inset-4',
|
||||
// inactive: isAfterStep(steps.landing + 16),
|
||||
// children: [{
|
||||
// slot: 'landing-cta',
|
||||
// class: 'inset-0'
|
||||
// }]
|
||||
// }]
|
||||
// }].filter(Boolean)
|
||||
// }]
|
||||
// : [])
|
||||
const landingBlocks = computed(() => isAfterStep(steps.landing) && isBeforeStep(steps.docs)
|
||||
? [{
|
||||
class: 'inset-x-0 top-20 bottom-20 overflow-hidden',
|
||||
inactive: true,
|
||||
children: [{
|
||||
name: 'ULandingHero',
|
||||
to: '/pro/components/landing-hero',
|
||||
class: [
|
||||
'inset-4',
|
||||
isAfterStep(steps.landing + 2) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
|
||||
].filter(Boolean).join(' '),
|
||||
style: {
|
||||
'--step-y': `${getStepY(steps.landing + 2)}px`
|
||||
},
|
||||
inactive: isAfterStep(steps.landing + 1),
|
||||
children: [{
|
||||
slot: 'landing-hero',
|
||||
class: 'inset-4'
|
||||
}]
|
||||
}, isAfterStep(steps.landing + 2) && {
|
||||
name: 'ULandingSection',
|
||||
to: '/pro/components/landing-section',
|
||||
class: [
|
||||
'inset-4',
|
||||
isBeforeStep(steps.landing + 6) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]',
|
||||
isAfterStep(steps.landing + 10) && '-top-[calc(var(--y)-var(--step-y)-1rem)] bottom-[calc(var(--y)-var(--step-y)+1rem)]'
|
||||
].filter(Boolean).join(' '),
|
||||
style: {
|
||||
'--height': (inc.value * 4) + 'px',
|
||||
'--step-y': `${getStepY(steps.landing + 10)}px`,
|
||||
'--prev-step-y': `${getStepY(steps.landing + 2)}px`
|
||||
},
|
||||
inactive: isAfterStep(steps.landing + 7),
|
||||
children: [{
|
||||
slot: 'landing-section',
|
||||
class: 'inset-x-4 top-16'
|
||||
}, {
|
||||
name: 'ULandingGrid',
|
||||
to: '/pro/components/landing-grid',
|
||||
class: ['inset-x-4 bottom-4 top-48', isAfterStep(steps.landing + 8) && 'grid grid-cols-4 gap-4 p-4'].filter(Boolean).join(' '),
|
||||
inactive: isAfterStep(steps.landing + 8),
|
||||
children: [isAfterStep(steps.landing + 9)
|
||||
? {
|
||||
slot: 'landing-card-1',
|
||||
class: '!relative'
|
||||
}
|
||||
: {
|
||||
name: 'ULandingCard',
|
||||
to: '/pro/components/landing-card',
|
||||
class: '!relative h-full',
|
||||
inactive: false
|
||||
}, isAfterStep(steps.landing + 9)
|
||||
? {
|
||||
slot: 'landing-card-2',
|
||||
class: '!relative h-full'
|
||||
}
|
||||
: {
|
||||
name: 'ULandingCard',
|
||||
to: '/pro/components/landing-card',
|
||||
class: '!relative h-full',
|
||||
inactive: false
|
||||
}, isAfterStep(steps.landing + 9)
|
||||
? {
|
||||
slot: 'landing-card-3',
|
||||
class: '!relative h-full'
|
||||
}
|
||||
: {
|
||||
name: 'ULandingCard',
|
||||
to: '/pro/components/landing-card',
|
||||
class: '!relative h-full',
|
||||
inactive: false
|
||||
}, isAfterStep(steps.landing + 9)
|
||||
? {
|
||||
slot: 'landing-card-4',
|
||||
class: '!relative h-full'
|
||||
}
|
||||
: {
|
||||
name: 'ULandingCard',
|
||||
to: '/pro/components/landing-card',
|
||||
class: '!relative h-full',
|
||||
inactive: false
|
||||
}]
|
||||
}]
|
||||
}, isAfterStep(steps.landing + 10) && {
|
||||
name: 'ULandingSection',
|
||||
to: '/pro/components/landing-section',
|
||||
class: [
|
||||
'inset-4',
|
||||
isBeforeStep(steps.landing + 14) && '-top-[calc(var(--y)-var(--prev-step-y)-var(--height)-1rem)] bottom-[calc(var(--y)-var(--prev-step-y)-var(--height)+1rem)]'
|
||||
].filter(Boolean).join(' '),
|
||||
style: {
|
||||
'--height': (inc.value * 4) + 'px',
|
||||
'--step-y': `${getStepY(steps.landing + 18)}px`,
|
||||
'--prev-step-y': `${getStepY(steps.landing + 10)}px`
|
||||
},
|
||||
inactive: isAfterStep(steps.landing + 15),
|
||||
children: [{
|
||||
name: 'ULandingCTA',
|
||||
class: 'inset-4',
|
||||
inactive: isAfterStep(steps.landing + 16),
|
||||
children: [{
|
||||
slot: 'landing-cta',
|
||||
class: 'inset-0'
|
||||
}]
|
||||
}]
|
||||
}].filter(Boolean)
|
||||
}]
|
||||
: [])
|
||||
|
||||
// const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
|
||||
// name: 'UPage',
|
||||
// to: '/pro/components/page',
|
||||
// class: 'inset-x-0 top-20 bottom-20',
|
||||
// inactive: isAfterStep(steps.docs + 1),
|
||||
// children: [isAfterStep(steps.docs + 2)
|
||||
// ? {
|
||||
// name: 'UAside',
|
||||
// to: '/pro/components/aside',
|
||||
// class: 'left-4 inset-y-4 w-64',
|
||||
// inactive: isAfterStep(steps.docs + 3),
|
||||
// children: [isAfterStep(steps.docs + 4)
|
||||
// ? {
|
||||
// slot: 'aside-top',
|
||||
// class: 'inset-x-4 top-4'
|
||||
// }
|
||||
// : {
|
||||
// name: '#top',
|
||||
// class: 'inset-x-4 top-4 h-9'
|
||||
// }, isAfterStep(steps.docs + 5)
|
||||
// ? {
|
||||
// name: 'UNavigationTree',
|
||||
// to: '/pro/components/navigation-tree',
|
||||
// class: ['inset-x-4 top-[4.25rem] bottom-4', isAfterStep(steps.docs + 6) && '!bg-transparent !border-0'].join(' '),
|
||||
// inactive: isAfterStep(steps.docs + 6),
|
||||
// children: [{
|
||||
// slot: 'aside-default',
|
||||
// class: 'inset-0'
|
||||
// }]
|
||||
// }
|
||||
// : {
|
||||
// name: '#default',
|
||||
// class: 'inset-x-4 top-[4.25rem] bottom-4'
|
||||
// }]
|
||||
// }
|
||||
// : {
|
||||
// name: '#left',
|
||||
// class: 'left-4 inset-y-4 w-64'
|
||||
// }, isAfterStep(steps.docs + 7)
|
||||
// ? {
|
||||
// name: 'UPage',
|
||||
// to: '/pro/components/page',
|
||||
// class: 'left-72 right-4 inset-y-4',
|
||||
// inactive: isAfterStep(steps.docs + 8),
|
||||
// children: [...(isAfterStep(steps.docs + 9)
|
||||
// ? [{
|
||||
// name: 'UPageHeader',
|
||||
// to: '/pro/components/page-header',
|
||||
// class: 'top-4 left-4 right-72 h-32',
|
||||
// inactive: isAfterStep(steps.docs + 10),
|
||||
// children: [{
|
||||
// slot: 'page-header',
|
||||
// class: 'inset-4 justify-start'
|
||||
// }]
|
||||
// }, {
|
||||
// name: 'UPageBody',
|
||||
// to: '/pro/components/page-body',
|
||||
// class: 'top-40 left-4 right-72 bottom-4 overflow-y-auto',
|
||||
// inactive: isAfterStep(steps.docs + 11),
|
||||
// children: [{
|
||||
// slot: 'page-body',
|
||||
// class: 'inset-x-4 top-4 justify-start'
|
||||
// }, isAfterStep(steps.docs + 12)
|
||||
// ? {
|
||||
// slot: 'content-surround',
|
||||
// class: 'bottom-4 inset-x-4 h-28'
|
||||
// }
|
||||
// : {
|
||||
// name: 'UContentSurround',
|
||||
// to: '/pro/components/content-surround',
|
||||
// class: 'bottom-4 inset-x-4 h-28',
|
||||
// inactive: false
|
||||
// }]
|
||||
// }]
|
||||
// : [{
|
||||
// name: '#default',
|
||||
// class: 'left-4 right-72 inset-y-4'
|
||||
// }]), isAfterStep(steps.docs + 13)
|
||||
// ? {
|
||||
// name: 'UContentToc',
|
||||
// to: '/pro/components/content-toc',
|
||||
// class: 'right-4 inset-y-4 w-64',
|
||||
// inactive: isAfterStep(steps.docs + 14),
|
||||
// children: [{
|
||||
// slot: 'content-toc',
|
||||
// class: 'inset-4 overflow-y-auto'
|
||||
// }]
|
||||
// }
|
||||
// : {
|
||||
// name: '#right',
|
||||
// class: 'right-4 inset-y-4 w-64'
|
||||
// }]
|
||||
// }
|
||||
// : {
|
||||
// name: '#default',
|
||||
// class: 'left-72 right-4 inset-y-4'
|
||||
// }]
|
||||
// }].filter(Boolean))
|
||||
const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
|
||||
name: 'UPage',
|
||||
to: '/pro/components/page',
|
||||
class: 'inset-x-0 top-20 bottom-20',
|
||||
inactive: isAfterStep(steps.docs + 1),
|
||||
children: [isAfterStep(steps.docs + 2)
|
||||
? {
|
||||
name: 'UAside',
|
||||
to: '/pro/components/aside',
|
||||
class: 'left-4 inset-y-4 w-64',
|
||||
inactive: isAfterStep(steps.docs + 3),
|
||||
children: [isAfterStep(steps.docs + 4)
|
||||
? {
|
||||
slot: 'aside-top',
|
||||
class: 'inset-x-4 top-4'
|
||||
}
|
||||
: {
|
||||
name: '#top',
|
||||
class: 'inset-x-4 top-4 h-9'
|
||||
}, isAfterStep(steps.docs + 5)
|
||||
? {
|
||||
name: 'UNavigationTree',
|
||||
to: '/pro/components/navigation-tree',
|
||||
class: ['inset-x-4 top-[4.25rem] bottom-4', isAfterStep(steps.docs + 6) && '!bg-transparent !border-0'].join(' '),
|
||||
inactive: isAfterStep(steps.docs + 6),
|
||||
children: [{
|
||||
slot: 'aside-default',
|
||||
class: 'inset-0'
|
||||
}]
|
||||
}
|
||||
: {
|
||||
name: '#default',
|
||||
class: 'inset-x-4 top-[4.25rem] bottom-4'
|
||||
}]
|
||||
}
|
||||
: {
|
||||
name: '#left',
|
||||
class: 'left-4 inset-y-4 w-64'
|
||||
}, isAfterStep(steps.docs + 7)
|
||||
? {
|
||||
name: 'UPage',
|
||||
to: '/pro/components/page',
|
||||
class: 'left-72 right-4 inset-y-4',
|
||||
inactive: isAfterStep(steps.docs + 8),
|
||||
children: [...(isAfterStep(steps.docs + 9)
|
||||
? [{
|
||||
name: 'UPageHeader',
|
||||
to: '/pro/components/page-header',
|
||||
class: 'top-4 left-4 right-72 h-32',
|
||||
inactive: isAfterStep(steps.docs + 10),
|
||||
children: [{
|
||||
slot: 'page-header',
|
||||
class: 'inset-4 justify-start'
|
||||
}]
|
||||
}, {
|
||||
name: 'UPageBody',
|
||||
to: '/pro/components/page-body',
|
||||
class: 'top-40 left-4 right-72 bottom-4 overflow-y-auto',
|
||||
inactive: isAfterStep(steps.docs + 11),
|
||||
children: [{
|
||||
slot: 'page-body',
|
||||
class: 'inset-x-4 top-4 justify-start'
|
||||
}, isAfterStep(steps.docs + 12)
|
||||
? {
|
||||
slot: 'content-surround',
|
||||
class: 'bottom-4 inset-x-4 h-28'
|
||||
}
|
||||
: {
|
||||
name: 'UContentSurround',
|
||||
to: '/pro/components/content-surround',
|
||||
class: 'bottom-4 inset-x-4 h-28',
|
||||
inactive: false
|
||||
}]
|
||||
}]
|
||||
: [{
|
||||
name: '#default',
|
||||
class: 'left-4 right-72 inset-y-4'
|
||||
}]), isAfterStep(steps.docs + 13)
|
||||
? {
|
||||
name: 'UContentToc',
|
||||
to: '/pro/components/content-toc',
|
||||
class: 'right-4 inset-y-4 w-64',
|
||||
inactive: isAfterStep(steps.docs + 14),
|
||||
children: [{
|
||||
slot: 'content-toc',
|
||||
class: 'inset-4 overflow-y-auto'
|
||||
}]
|
||||
}
|
||||
: {
|
||||
name: '#right',
|
||||
class: 'right-4 inset-y-4 w-64'
|
||||
}]
|
||||
}
|
||||
: {
|
||||
name: '#default',
|
||||
class: 'left-72 right-4 inset-y-4'
|
||||
}]
|
||||
}].filter(Boolean))
|
||||
|
||||
// const blocks = computed(() => [isAfterStep(steps.header) && {
|
||||
// name: 'UHeader',
|
||||
// to: '/pro/components/header',
|
||||
// class: 'h-16 inset-x-0 top-0',
|
||||
// inactive: isAfterStep(steps.header + 1),
|
||||
// children: [isAfterStep(steps.header + 2)
|
||||
// ? {
|
||||
// slot: 'header-left',
|
||||
// class: 'left-4 top-4'
|
||||
// }
|
||||
// : {
|
||||
// name: '#left',
|
||||
// class: 'left-4 inset-y-4 w-64'
|
||||
// }, isAfterStep(steps.header + 3)
|
||||
// ? {
|
||||
// slot: 'header-center',
|
||||
// class: 'inset-x-72 top-5'
|
||||
// }
|
||||
// : {
|
||||
// name: '#center',
|
||||
// class: 'inset-x-72 inset-y-4'
|
||||
// }, isAfterStep(steps.header + 4)
|
||||
// ? {
|
||||
// slot: 'header-right',
|
||||
// class: 'right-4 top-4'
|
||||
// }
|
||||
// : {
|
||||
// name: '#right',
|
||||
// class: 'right-4 inset-y-4 w-64'
|
||||
// }]
|
||||
// }, isAfterStep(steps.footer) && {
|
||||
// name: 'UFooter',
|
||||
// to: '/pro/components/footer',
|
||||
// class: 'h-16 inset-x-0 bottom-0',
|
||||
// inactive: isAfterStep(steps.footer + 1),
|
||||
// children: [isAfterStep(steps.footer + 2)
|
||||
// ? {
|
||||
// slot: 'footer-left',
|
||||
// class: 'left-4 bottom-5'
|
||||
// }
|
||||
// : {
|
||||
// name: '#left',
|
||||
// class: 'left-4 inset-y-4 w-64'
|
||||
// }, isAfterStep(steps.footer + 3)
|
||||
// ? {
|
||||
// slot: 'footer-center',
|
||||
// class: 'inset-x-72 bottom-5'
|
||||
// }
|
||||
// : {
|
||||
// name: '#center',
|
||||
// class: 'inset-x-72 inset-y-4'
|
||||
// }, isAfterStep(steps.footer + 4)
|
||||
// ? {
|
||||
// slot: 'footer-right',
|
||||
// class: 'right-4 bottom-4'
|
||||
// }
|
||||
// : {
|
||||
// name: '#right',
|
||||
// class: 'right-4 inset-y-4 w-64'
|
||||
// }]
|
||||
// }, ...landingBlocks.value, ...docsBlocks.value].filter(Boolean))
|
||||
const blocks = computed(() => [isAfterStep(steps.header) && {
|
||||
name: 'UHeader',
|
||||
to: '/pro/components/header',
|
||||
class: 'h-16 inset-x-0 top-0',
|
||||
inactive: isAfterStep(steps.header + 1),
|
||||
children: [isAfterStep(steps.header + 2)
|
||||
? {
|
||||
slot: 'header-left',
|
||||
class: 'left-4 top-4'
|
||||
}
|
||||
: {
|
||||
name: '#left',
|
||||
class: 'left-4 inset-y-4 w-64'
|
||||
}, isAfterStep(steps.header + 3)
|
||||
? {
|
||||
slot: 'header-center',
|
||||
class: 'inset-x-72 top-5'
|
||||
}
|
||||
: {
|
||||
name: '#center',
|
||||
class: 'inset-x-72 inset-y-4'
|
||||
}, isAfterStep(steps.header + 4)
|
||||
? {
|
||||
slot: 'header-right',
|
||||
class: 'right-4 top-4'
|
||||
}
|
||||
: {
|
||||
name: '#right',
|
||||
class: 'right-4 inset-y-4 w-64'
|
||||
}]
|
||||
}, isAfterStep(steps.footer) && {
|
||||
name: 'UFooter',
|
||||
to: '/pro/components/footer',
|
||||
class: 'h-16 inset-x-0 bottom-0',
|
||||
inactive: isAfterStep(steps.footer + 1),
|
||||
children: [isAfterStep(steps.footer + 2)
|
||||
? {
|
||||
slot: 'footer-left',
|
||||
class: 'left-4 bottom-5'
|
||||
}
|
||||
: {
|
||||
name: '#left',
|
||||
class: 'left-4 inset-y-4 w-64'
|
||||
}, isAfterStep(steps.footer + 3)
|
||||
? {
|
||||
slot: 'footer-center',
|
||||
class: 'inset-x-72 bottom-5'
|
||||
}
|
||||
: {
|
||||
name: '#center',
|
||||
class: 'inset-x-72 inset-y-4'
|
||||
}, isAfterStep(steps.footer + 4)
|
||||
? {
|
||||
slot: 'footer-right',
|
||||
class: 'right-4 bottom-4'
|
||||
}
|
||||
: {
|
||||
name: '#right',
|
||||
class: 'right-4 inset-y-4 w-64'
|
||||
}]
|
||||
}, ...landingBlocks.value, ...docsBlocks.value].filter(Boolean))
|
||||
|
||||
// Methods
|
||||
|
||||
// function isBeforeStep(i = 0) {
|
||||
// return y.value < (start.value + (i * inc.value))
|
||||
// }
|
||||
function isBeforeStep(i = 0) {
|
||||
return y.value < (start.value + (i * inc.value))
|
||||
}
|
||||
|
||||
// function isAfterStep(i = 0) {
|
||||
// return y.value >= (start.value + (i * inc.value))
|
||||
// }
|
||||
function isAfterStep(i = 0) {
|
||||
return y.value >= (start.value + (i * inc.value))
|
||||
}
|
||||
|
||||
// function getStepY(step: number) {
|
||||
// return start.value + (step * inc.value)
|
||||
// }
|
||||
function getStepY(step: number) {
|
||||
return start.value + (step * inc.value)
|
||||
}
|
||||
|
||||
// Hooks
|
||||
|
||||
@@ -760,94 +760,94 @@ onMounted(() => {
|
||||
|
||||
// Slots Data
|
||||
|
||||
// const headerLinks = [{
|
||||
// label: 'Documentation',
|
||||
// active: true
|
||||
// }, {
|
||||
// label: 'Playground'
|
||||
// }, {
|
||||
// label: 'Roadmap'
|
||||
// }, {
|
||||
// label: 'Pro'
|
||||
// }]
|
||||
const headerLinks = [{
|
||||
label: 'Documentation',
|
||||
active: true
|
||||
}, {
|
||||
label: 'Playground'
|
||||
}, {
|
||||
label: 'Roadmap'
|
||||
}, {
|
||||
label: 'Pro'
|
||||
}]
|
||||
|
||||
// const navigationLinks = [{
|
||||
// label: 'Getting Started',
|
||||
// children: [{
|
||||
// label: 'Introduction'
|
||||
// }, {
|
||||
// label: 'Installation',
|
||||
// active: true
|
||||
// }, {
|
||||
// label: 'Theming'
|
||||
// }, {
|
||||
// label: 'Shortcuts'
|
||||
// }, {
|
||||
// label: 'Examples'
|
||||
// }, {
|
||||
// label: 'Roadmap'
|
||||
// }]
|
||||
// }, {
|
||||
// label: 'Elements',
|
||||
// children: [{
|
||||
// label: 'Alert'
|
||||
// }, {
|
||||
// label: 'Avatar'
|
||||
// }, {
|
||||
// label: 'Badge'
|
||||
// }, {
|
||||
// label: 'Button'
|
||||
// }]
|
||||
// }]
|
||||
const navigationLinks = [{
|
||||
label: 'Getting Started',
|
||||
children: [{
|
||||
label: 'Introduction'
|
||||
}, {
|
||||
label: 'Installation',
|
||||
active: true
|
||||
}, {
|
||||
label: 'Theming'
|
||||
}, {
|
||||
label: 'Shortcuts'
|
||||
}, {
|
||||
label: 'Examples'
|
||||
}, {
|
||||
label: 'Roadmap'
|
||||
}]
|
||||
}, {
|
||||
label: 'Elements',
|
||||
children: [{
|
||||
label: 'Alert'
|
||||
}, {
|
||||
label: 'Avatar'
|
||||
}, {
|
||||
label: 'Badge'
|
||||
}, {
|
||||
label: 'Button'
|
||||
}]
|
||||
}]
|
||||
|
||||
// const surround = [{
|
||||
// title: 'Introduction',
|
||||
// description: 'Fully styled and customizable components for Nuxt.',
|
||||
// _path: '/'
|
||||
// }, {
|
||||
// title: 'Theming',
|
||||
// description: 'Learn how to customize the look and feel of the components.',
|
||||
// _path: '/'
|
||||
// }]
|
||||
const surround = [{
|
||||
title: 'Introduction',
|
||||
description: 'Fully styled and customizable components for Nuxt.',
|
||||
_path: '/'
|
||||
}, {
|
||||
title: 'Theming',
|
||||
description: 'Learn how to customize the look and feel of the components.',
|
||||
_path: '/'
|
||||
}]
|
||||
|
||||
// const md = `
|
||||
// ## Edge
|
||||
const md = `
|
||||
## Edge
|
||||
|
||||
// To use the latest updates pushed on the [\`dev\`](https://github.com/nuxt/ui/tree/v2) branch, you can use \`@nuxt/ui-edge\`.
|
||||
// `
|
||||
To use the latest updates pushed on the [\`dev\`](https://github.com/nuxt/ui/tree/dev) branch, you can use \`@nuxt/ui-edge\`.
|
||||
`
|
||||
|
||||
// const toc = [{
|
||||
// id: 'quick-start',
|
||||
// depth: 2,
|
||||
// text: 'Quick Start'
|
||||
// }, {
|
||||
// id: 'intellisense',
|
||||
// depth: 2,
|
||||
// text: 'IntelliSense'
|
||||
// }, {
|
||||
// id: 'options',
|
||||
// depth: 2,
|
||||
// text: 'Options'
|
||||
// }, {
|
||||
// id: 'edge',
|
||||
// depth: 2,
|
||||
// text: 'Edge'
|
||||
// }]
|
||||
const toc = [{
|
||||
id: 'quick-start',
|
||||
depth: 2,
|
||||
text: 'Quick Start'
|
||||
}, {
|
||||
id: 'intellisense',
|
||||
depth: 2,
|
||||
text: 'IntelliSense'
|
||||
}, {
|
||||
id: 'options',
|
||||
depth: 2,
|
||||
text: 'Options'
|
||||
}, {
|
||||
id: 'edge',
|
||||
depth: 2,
|
||||
text: 'Edge'
|
||||
}]
|
||||
|
||||
// const communityLinks = [{
|
||||
// icon: 'i-heroicons-pencil-square',
|
||||
// label: 'Edit this page'
|
||||
// }, {
|
||||
// icon: 'i-heroicons-star',
|
||||
// label: 'Star on GitHub',
|
||||
// to: 'https://github.com/nuxt/ui',
|
||||
// target: '_blank'
|
||||
// }, {
|
||||
// icon: 'i-heroicons-book-open',
|
||||
// label: 'Nuxt documentation',
|
||||
// to: 'https://nuxt.com',
|
||||
// target: '_blank'
|
||||
// }]
|
||||
const communityLinks = [{
|
||||
icon: 'i-heroicons-pencil-square',
|
||||
label: 'Edit this page'
|
||||
}, {
|
||||
icon: 'i-heroicons-star',
|
||||
label: 'Star on GitHub',
|
||||
to: 'https://github.com/nuxt/ui',
|
||||
target: '_blank'
|
||||
}, {
|
||||
icon: 'i-heroicons-book-open',
|
||||
label: 'Nuxt documentation',
|
||||
to: 'https://nuxt.com',
|
||||
target: '_blank'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
|
||||
@@ -41,8 +41,8 @@ if (!page.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||
}
|
||||
|
||||
const { data: releases } = await useFetch('/api/releases.json', { key: 'releases-list' })
|
||||
const { data: pulls } = await useLazyFetch('/api/pulls.json', { default: () => [], key: 'pulls-list' })
|
||||
const { data: releases } = await useFetch('/api/releases.json')
|
||||
const { data: pulls } = await useLazyFetch('/api/pulls.json', { default: () => [] })
|
||||
|
||||
const dates = computed(() => {
|
||||
const first = releases.value[releases.value.length - 1]
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
user-agent: *
|
||||
user-agent: *
|
||||
disallow: /dev/*
|
||||
|
||||
117
package.json
117
package.json
@@ -1,29 +1,20 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
|
||||
"version": "2.22.1",
|
||||
"packageManager": "pnpm@10.13.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/ui.git"
|
||||
},
|
||||
"homepage": "https://ui2.nuxt.com",
|
||||
"version": "2.19.2",
|
||||
"packageManager": "pnpm@9.12.3",
|
||||
"repository": "nuxt/ui",
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/module.d.mts",
|
||||
"import": "./dist/module.mjs"
|
||||
"import": "./dist/module.mjs",
|
||||
"require": "./dist/module.cjs"
|
||||
}
|
||||
},
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
".": [
|
||||
"./dist/module.d.mts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"main": "./dist/module.mjs",
|
||||
"main": "./dist/module.cjs",
|
||||
"types": "./dist/types.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
@@ -41,78 +32,56 @@
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/tailwindcss": "^0.2.2",
|
||||
"@headlessui/tailwindcss": "^0.2.1",
|
||||
"@headlessui/vue": "^1.7.23",
|
||||
"@iconify-json/heroicons": "^1.2.2",
|
||||
"@nuxt/icon": "^1.15.0",
|
||||
"@nuxt/kit": "^4.0.1",
|
||||
"@iconify-json/heroicons": "^1.2.1",
|
||||
"@nuxt/icon": "^1.7.2",
|
||||
"@nuxt/kit": "^3.14.159",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
"@nuxtjs/tailwindcss": "^6.12.2",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"@vueuse/integrations": "^13.5.0",
|
||||
"@vueuse/math": "^13.5.0",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@vueuse/core": "^11.2.0",
|
||||
"@vueuse/integrations": "^11.2.0",
|
||||
"@vueuse/math": "^11.2.0",
|
||||
"defu": "^6.1.4",
|
||||
"fuse.js": "^7.1.0",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"fuse.js": "^7.0.0",
|
||||
"ohash": "^1.1.4",
|
||||
"pathe": "^1.1.2",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss": "^3.4.17"
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss": "^3.4.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint-config": "^1.6.0",
|
||||
"@nuxt/module-builder": "^1.0.1",
|
||||
"@nuxt/test-utils": "^3.19.2",
|
||||
"@release-it/conventional-changelog": "^10.0.1",
|
||||
"@nuxt/eslint-config": "^0.6.1",
|
||||
"@nuxt/module-builder": "^0.8.4",
|
||||
"@nuxt/test-utils": "^3.14.4",
|
||||
"@release-it/conventional-changelog": "^9.0.2",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"eslint": "^9.31.0",
|
||||
"happy-dom": "^18.0.1",
|
||||
"nuxt": "^4.0.1",
|
||||
"release-it": "^19.0.4",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.2.4",
|
||||
"eslint": "^9.14.0",
|
||||
"happy-dom": "^14.12.3",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.14.159",
|
||||
"release-it": "^17.10.0",
|
||||
"superstruct": "^2.0.2",
|
||||
"unbuild": "^2.0.0",
|
||||
"valibot": "^0.42.1",
|
||||
"valibot30": "npm:valibot@0.30.0",
|
||||
"valibot31": "npm:valibot@0.31.0",
|
||||
"vitest": "^2.1.4",
|
||||
"vitest-environment-nuxt": "^1.0.1",
|
||||
"vue-tsc": "^3.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"joi": "^17.13.0",
|
||||
"superstruct": "^2.0.0",
|
||||
"valibot": "^1.0.0",
|
||||
"yup": "^1.6.0",
|
||||
"zod": "^3.24.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"joi": {
|
||||
"optional": true
|
||||
},
|
||||
"valibot": {
|
||||
"optional": true
|
||||
},
|
||||
"superstruct": {
|
||||
"optional": true
|
||||
},
|
||||
"yup": {
|
||||
"optional": true
|
||||
},
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
"vue-tsc": "^2.1.10",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"resolutions": {
|
||||
"@nuxt/ui": "workspace:*",
|
||||
"@nuxt/content": "2.13.2",
|
||||
"@nuxtjs/mdc": "0.9.0",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"@vueuse/integrations": "^13.5.0",
|
||||
"@vueuse/math": "^13.5.0",
|
||||
"@vueuse/nuxt": "13.1.0",
|
||||
"unimport": "4.1.1",
|
||||
"chokidar": "3.6.0"
|
||||
"nuxt": "3.13.2",
|
||||
"@nuxt/kit": "3.13.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "latest",
|
||||
"nuxt": "^4.0.1"
|
||||
"nuxt": "^3.14.159"
|
||||
}
|
||||
}
|
||||
|
||||
12910
pnpm-lock.yaml
generated
12910
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,4 @@
|
||||
packages:
|
||||
- ./
|
||||
- docs
|
||||
- playground
|
||||
|
||||
ignoredBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- esbuild
|
||||
- sharp
|
||||
- vue-demi
|
||||
- "./"
|
||||
- "docs"
|
||||
- "playground"
|
||||
|
||||
@@ -5,7 +5,12 @@
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true
|
||||
},
|
||||
"baseBranches": ["v2", "v3"],
|
||||
"ignoreDeps": [
|
||||
"happy-dom",
|
||||
"valibot30",
|
||||
"valibot31"
|
||||
],
|
||||
"baseBranches": ["dev", "v3"],
|
||||
"packageRules": [{
|
||||
"matchBaseBranches": ["v3"],
|
||||
"labels": ["v3"]
|
||||
@@ -19,6 +24,5 @@
|
||||
}, {
|
||||
"matchDepTypes": ["resolutions"],
|
||||
"enabled": false
|
||||
}],
|
||||
"postUpdateOptions": ["pnpmDedupe"]
|
||||
}]
|
||||
}
|
||||
|
||||
36
scripts/bump-edge.ts
Normal file
36
scripts/bump-edge.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import { execSync } from 'node:child_process'
|
||||
|
||||
async function loadPackage(dir: string) {
|
||||
const pkgPath = resolve(dir, 'package.json')
|
||||
|
||||
const data = JSON.parse(await fsp.readFile(pkgPath, 'utf-8').catch(() => '{}'))
|
||||
|
||||
const save = () => fsp.writeFile(pkgPath, JSON.stringify(data, null, 2) + '\n')
|
||||
|
||||
return {
|
||||
dir,
|
||||
data,
|
||||
save
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const pkg = await loadPackage(process.cwd())
|
||||
|
||||
const commit = execSync('git rev-parse --short HEAD').toString('utf-8').trim()
|
||||
|
||||
const date = Math.round(Date.now() / (1000 * 60))
|
||||
|
||||
pkg.data.name = `${pkg.data.name}-edge`
|
||||
|
||||
pkg.data.version = `${pkg.data.version}-${date}.${commit}`
|
||||
|
||||
pkg.save()
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
19
scripts/release-edge.sh
Executable file
19
scripts/release-edge.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Restore all git changes
|
||||
git restore -s@ -SW -- .
|
||||
|
||||
# Bump versions to edge
|
||||
pnpm jiti ./scripts/bump-edge
|
||||
|
||||
# Update token
|
||||
if [[ ! -z ${NODE_AUTH_TOKEN} ]] ; then
|
||||
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc
|
||||
echo "registry=https://registry.npmjs.org/" >> ~/.npmrc
|
||||
echo "always-auth=true" >> ~/.npmrc
|
||||
npm whoami
|
||||
fi
|
||||
|
||||
# Release package
|
||||
echo "Publishing @nuxt/ui"
|
||||
npm publish -q --access public
|
||||
@@ -13,4 +13,4 @@ fi
|
||||
|
||||
# Release package
|
||||
echo "Publishing @nuxt/ui"
|
||||
npm publish --access public --no-tag
|
||||
npm publish -q --access public
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit'
|
||||
import type { ConfigExtension, DefaultClassGroupIds, DefaultThemeGroupIds } from 'tailwind-merge'
|
||||
import { name, version } from '../package.json'
|
||||
import createTemplates from './templates'
|
||||
import type * as config from './runtime/ui.config'
|
||||
@@ -21,7 +20,6 @@ type UI = {
|
||||
gray?: string
|
||||
colors?: string[]
|
||||
strategy?: Strategy
|
||||
tailwindMerge?: ConfigExtension<DefaultClassGroupIds, DefaultThemeGroupIds>
|
||||
[key: string]: any
|
||||
} & DeepPartial<typeof config, string | number | boolean>
|
||||
|
||||
@@ -43,11 +41,6 @@ export interface ModuleOptions {
|
||||
*/
|
||||
global?: boolean
|
||||
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
colorMode?: boolean
|
||||
|
||||
safelistColors?: string[]
|
||||
/**
|
||||
* Disables the global css styles added by the module.
|
||||
@@ -66,7 +59,6 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
},
|
||||
defaults: {
|
||||
prefix: 'U',
|
||||
colorMode: true,
|
||||
safelistColors: ['primary'],
|
||||
disableGlobalStyles: false
|
||||
},
|
||||
@@ -89,9 +81,7 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
// Modules
|
||||
|
||||
await installModule('@nuxt/icon')
|
||||
if (options.colorMode) {
|
||||
await installModule('@nuxtjs/color-mode', { classSuffix: '' })
|
||||
}
|
||||
await installModule('@nuxtjs/color-mode', { classSuffix: '' })
|
||||
await installTailwind(options, nuxt, resolve)
|
||||
|
||||
// Plugins
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
:class="[ui.th.base, ui.th.padding, ui.th.color, ui.th.font, ui.th.size, column.key === 'select' && ui.checkbox.padding, column.class]"
|
||||
:aria-sort="getAriaSort(column)"
|
||||
>
|
||||
<slot v-if="!singleSelect && modelValue && column.key === 'select'" name="select-header" :indeterminate="indeterminate" :checked="isAllRowChecked" :change="onChange">
|
||||
<slot v-if="!singleSelect && modelValue && (column.key === 'select' || shouldRenderColumnInFirstPlace(index, 'select'))" name="select-header" :indeterminate="indeterminate" :checked="isAllRowChecked" :change="onChange">
|
||||
<UCheckbox
|
||||
:model-value="isAllRowChecked"
|
||||
:indeterminate="indeterminate"
|
||||
@@ -93,19 +93,19 @@
|
||||
/>
|
||||
</td>
|
||||
<td v-for="(column, subIndex) in columns" :key="subIndex" :class="[ui.td.base, ui.td.padding, ui.td.color, ui.td.font, ui.td.size, column?.rowClass, row[column.key]?.class, column.key === 'select' && ui.checkbox.padding]">
|
||||
<!-- This is a workaround: Since the @change event doesn't bubble up naturally, we need to wrap it in another element and use @click.capture.stop to simulate event bubbling behavior -->
|
||||
<span v-if="modelValue && column.key === 'select' " @click.capture.stop="() => {}">
|
||||
<slot name="select-data" :checked="isSelected(row)" :change="(ev: boolean) => onChangeCheckbox(ev, row)">
|
||||
<UCheckbox
|
||||
:model-value="isSelected(row)"
|
||||
v-bind="ui.default.checkbox"
|
||||
aria-label="Select row"
|
||||
@change="onChangeCheckbox($event, row)"
|
||||
/>
|
||||
</slot>
|
||||
</span>
|
||||
<slot v-if="modelValue && (column.key === 'select' || shouldRenderColumnInFirstPlace(subIndex, 'select')) " name="select-data" :checked="isSelected(row)" :change="(ev: boolean) => onChangeCheckbox(ev, row)">
|
||||
<UCheckbox
|
||||
:model-value="isSelected(row)"
|
||||
v-bind="ui.default.checkbox"
|
||||
aria-label="Select row"
|
||||
@change="onChangeCheckbox($event, row)"
|
||||
@click.capture.stop="() => onSelect(row)"
|
||||
/>
|
||||
</slot>
|
||||
|
||||
<slot
|
||||
v-else
|
||||
:key="retriggerSlot"
|
||||
:name="`${column.key}-data`"
|
||||
:column="column"
|
||||
:row="row"
|
||||
@@ -133,18 +133,18 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, toRaw, toRef } from 'vue'
|
||||
import { computed, defineComponent, ref, toRaw, toRef, watch } from 'vue'
|
||||
import type { PropType, AriaAttributes } from 'vue'
|
||||
import { upperFirst } from 'scule'
|
||||
import { defu } from 'defu'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { isEqual } from 'ohash/utils'
|
||||
import { isEqual } from 'ohash'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import UProgress from '../elements/Progress.vue'
|
||||
import UCheckbox from '../forms/Checkbox.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { get, mergeConfig } from '../../utils'
|
||||
import { mergeConfig, get } from '../../utils'
|
||||
import type { TableRow, TableColumn, Strategy, Button, ProgressColor, ProgressAnimation, DeepPartial, Expanded } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
@@ -274,30 +274,7 @@ export default defineComponent({
|
||||
setup(props, { emit, attrs: $attrs }) {
|
||||
const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))
|
||||
|
||||
const columns = computed(() => {
|
||||
const defaultColumns = props.columns ?? (
|
||||
Object.keys(props.rows[0]).map(key => ({
|
||||
key,
|
||||
label: upperFirst(key),
|
||||
sortable: false,
|
||||
class: undefined,
|
||||
sort: defaultSort
|
||||
}))
|
||||
) as TableColumn[]
|
||||
|
||||
const hasColumnSelect = defaultColumns.find(v => v.key === 'select')
|
||||
|
||||
if (hasColumnSelect || !props.modelValue) {
|
||||
return defaultColumns
|
||||
}
|
||||
|
||||
return [{
|
||||
key: 'select',
|
||||
sortable: false,
|
||||
class: undefined,
|
||||
sort: defaultSort
|
||||
}, ...defaultColumns]
|
||||
})
|
||||
const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map(key => ({ key, label: upperFirst(key), sortable: false, class: undefined, sort: defaultSort }) as TableColumn))
|
||||
|
||||
const sort = useVModel(props, 'sort', emit, { passive: true, defaultValue: defu({}, props.sort, { column: null, direction: 'asc' }) })
|
||||
const expand = useVModel(props, 'expand', emit, {
|
||||
@@ -308,6 +285,8 @@ export default defineComponent({
|
||||
})
|
||||
})
|
||||
|
||||
const retriggerSlot = ref(null)
|
||||
|
||||
const savedSort = { column: sort.value.column, direction: null }
|
||||
|
||||
const rows = computed(() => {
|
||||
@@ -443,7 +422,8 @@ export default defineComponent({
|
||||
if (checked) {
|
||||
selected.value = props.singleSelect ? [row] : [...selected.value, row]
|
||||
} else {
|
||||
selected.value = selected.value.filter(value => !compare(toRaw(value), toRaw(row)))
|
||||
const index = selected.value.findIndex(item => compare(item, row))
|
||||
selected.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +435,13 @@ export default defineComponent({
|
||||
return expand.value?.openedRows ? expand.value.openedRows.some(openedRow => compare(openedRow, row)) : false
|
||||
}
|
||||
|
||||
function shouldRenderColumnInFirstPlace(index: number, key: string) {
|
||||
if (!props.columns) {
|
||||
return index === 0
|
||||
}
|
||||
return index === 0 && !props.columns.find(col => col.key === key)
|
||||
}
|
||||
|
||||
function toggleOpened(row: TableRow) {
|
||||
expand.value = {
|
||||
openedRows: isExpanded(row) ? expand.value.openedRows.filter(v => !compare(v, row)) : props.multipleExpand ? [...expand.value.openedRows, row] : [row],
|
||||
@@ -482,6 +469,12 @@ export default defineComponent({
|
||||
return undefined
|
||||
}
|
||||
|
||||
watch(rows, () => {
|
||||
retriggerSlot.value = new Date()
|
||||
}, {
|
||||
deep: true
|
||||
})
|
||||
|
||||
return {
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
@@ -508,7 +501,9 @@ export default defineComponent({
|
||||
getRowData,
|
||||
toggleOpened,
|
||||
getAriaSort,
|
||||
isExpanded
|
||||
isExpanded,
|
||||
shouldRenderColumnInFirstPlace,
|
||||
retriggerSlot
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -126,7 +126,7 @@ export default defineComponent({
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
emits: ['open', 'close'],
|
||||
emits: ['open'],
|
||||
setup(props, { emit }) {
|
||||
const { ui, attrs } = useUI('accordion', toRef(props, 'ui'), config, toRef(props, 'class'))
|
||||
|
||||
@@ -142,8 +142,6 @@ export default defineComponent({
|
||||
|
||||
if (!isOpenBefore && isOpenAfter) {
|
||||
emit('open', index)
|
||||
} else if (isOpenBefore && !isOpenAfter) {
|
||||
emit('close', index)
|
||||
}
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{{ title }}
|
||||
</slot>
|
||||
</p>
|
||||
<div v-if="description || $slots.description" :class="twMerge(ui.description, !title && !$slots.title && ui.descriptionOnly)">
|
||||
<div v-if="description || $slots.description" :class="twMerge(ui.description, !title && !$slots.title && 'mt-0 leading-5')">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
@@ -42,13 +42,13 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import type { Avatar, Button, AlertColor, AlertVariant, AlertAction, Strategy, DeepPartial } from '../../types/index'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { alert } from '#ui/ui.config'
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, toRef, watch } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { AvatarSize, AvatarChipColor, AvatarChipPosition, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { getSlotsChildren, mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import type { AvatarSize, DeepPartial, Strategy } from '../../types/index'
|
||||
import UAvatar from './Avatar.vue'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -1,28 +1,15 @@
|
||||
<template>
|
||||
<span :class="badgeClass" v-bind="attrs">
|
||||
<slot name="leading">
|
||||
<UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="leadingIconClass" aria-hidden="true" />
|
||||
</slot>
|
||||
|
||||
<slot>
|
||||
<span v-if="label !== undefined && label !== null">
|
||||
{{ label }}
|
||||
</span>
|
||||
</slot>
|
||||
|
||||
<slot name="trailing">
|
||||
<UIcon v-if="isTrailing && trailingIconName" :name="trailingIconName" :class="trailingIconClass" aria-hidden="true" />
|
||||
</slot>
|
||||
<slot>{{ label }}</slot>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { BadgeColor, BadgeSize, BadgeVariant, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
@@ -32,9 +19,6 @@ import { badge } from '#ui/ui.config'
|
||||
const config = mergeConfig<typeof badge>(appConfig.ui.strategy, appConfig.ui.badge, badge)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
UIcon
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
size: {
|
||||
@@ -65,26 +49,6 @@ export default defineComponent({
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
leadingIcon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
trailingIcon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
trailing: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
leading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
class: {
|
||||
type: [String, Object, Array] as PropType<any>,
|
||||
default: () => ''
|
||||
@@ -99,14 +63,6 @@ export default defineComponent({
|
||||
|
||||
const { size, rounded } = useInjectButtonGroup({ ui, props })
|
||||
|
||||
const isLeading = computed(() => {
|
||||
return (props.icon && props.leading) || (props.icon && !props.trailing) || !props.trailing || props.leadingIcon
|
||||
})
|
||||
|
||||
const isTrailing = computed(() => {
|
||||
return (props.icon && props.trailing) || props.trailing || props.trailingIcon
|
||||
})
|
||||
|
||||
const badgeClass = computed(() => {
|
||||
const variant = ui.value.color?.[props.color as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
||||
|
||||
@@ -115,42 +71,13 @@ export default defineComponent({
|
||||
ui.value.font,
|
||||
rounded.value,
|
||||
ui.value.size[size.value],
|
||||
ui.value.gap[size.value],
|
||||
variant?.replaceAll('{color}', props.color)
|
||||
), props.class)
|
||||
})
|
||||
|
||||
const leadingIconName = computed(() => {
|
||||
return props.leadingIcon || props.icon
|
||||
})
|
||||
|
||||
const trailingIconName = computed(() => {
|
||||
return props.trailingIcon || props.icon
|
||||
})
|
||||
|
||||
const leadingIconClass = computed(() => {
|
||||
return twJoin(
|
||||
ui.value.icon.base,
|
||||
ui.value.icon.size[size.value]
|
||||
)
|
||||
})
|
||||
|
||||
const trailingIconClass = computed(() => {
|
||||
return twJoin(
|
||||
ui.value.icon.base,
|
||||
ui.value.icon.size[size.value]
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
attrs,
|
||||
isLeading,
|
||||
isTrailing,
|
||||
badgeClass,
|
||||
leadingIconName,
|
||||
trailingIconName,
|
||||
leadingIconClass,
|
||||
trailingIconClass
|
||||
badgeClass
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</slot>
|
||||
|
||||
<slot>
|
||||
<span v-if="label !== undefined && label !== null" :class="[truncate ? ui.truncate : '']">
|
||||
<span v-if="label" :class="[truncate ? ui.truncate : '']">
|
||||
{{ label }}
|
||||
</span>
|
||||
</slot>
|
||||
@@ -19,11 +19,11 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, toRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import ULink from '../elements/Link.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { getNuxtLinkProps, mergeConfig, nuxtLinkProps, twMerge } from '../../utils'
|
||||
import { mergeConfig, nuxtLinkProps, getNuxtLinkProps } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { ButtonColor, ButtonSize, ButtonVariant, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { h, computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { getSlotsChildren, mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import { useProvideButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { ButtonSize, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -58,8 +58,9 @@
|
||||
<script lang="ts">
|
||||
import { ref, toRef, computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { useScroll, useResizeObserver, useElementSize } from '@vueuse/core'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import type { Strategy, Button, DeepPartial } from '../../types/index'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
@@ -105,7 +106,7 @@ export default defineComponent({
|
||||
default: () => ''
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<DeepPartial<typeof config> & { strategy?: Strategy }>,
|
||||
type: Object as PropType<DeepPartial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
|
||||
@@ -60,13 +60,13 @@ import { defineComponent, ref, computed, watch, toRef, onMounted, resolveCompone
|
||||
import type { PropType } from 'vue'
|
||||
import { Menu as HMenu, MenuButton as HMenuButton, MenuItems as HMenuItems, MenuItem as HMenuItem, provideUseId } from '@headlessui/vue'
|
||||
import { defu } from 'defu'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UKbd from '../elements/Kbd.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { getNuxtLinkProps, mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig, getNuxtLinkProps } from '../../utils'
|
||||
import type { DeepPartial, DropdownItem, PopperOptions, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<script lang="ts">
|
||||
import { toRef, defineComponent, computed } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { DeepPartial, KbdSize, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -32,9 +32,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { isEqual, diff } from 'ohash/utils'
|
||||
import { isEqual } from 'ohash'
|
||||
import { defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { nuxtLinkProps } from '../../utils'
|
||||
|
||||
export default defineComponent({
|
||||
@@ -62,7 +61,7 @@ export default defineComponent({
|
||||
default: false
|
||||
},
|
||||
exactQuery: {
|
||||
type: [Boolean, String] as PropType<boolean | 'partial'>,
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
exactHash: {
|
||||
@@ -75,25 +74,9 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
function isPartiallyEqual(item1: any, item2: any) {
|
||||
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
|
||||
if (q.type === 'added') {
|
||||
filtered.add(q.key)
|
||||
}
|
||||
return filtered
|
||||
}, new Set<string>())
|
||||
|
||||
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
|
||||
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
|
||||
|
||||
return isEqual(item1Filtered, item2Filtered)
|
||||
}
|
||||
|
||||
function resolveLinkClass(route, $route, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }) {
|
||||
if (props.exactQuery === 'partial') {
|
||||
if (!isPartiallyEqual(route.query, $route.query)) return props.inactiveClass
|
||||
} else if (props.exactQuery === true) {
|
||||
if (!isEqual(route.query, $route.query)) return props.inactiveClass
|
||||
if (props.exactQuery && !isEqual(route.query, $route.query)) {
|
||||
return props.inactiveClass
|
||||
}
|
||||
if (props.exactHash && route.hash !== $route.hash) {
|
||||
return props.inactiveClass
|
||||
|
||||
@@ -46,6 +46,10 @@ export default defineComponent({
|
||||
UIcon
|
||||
},
|
||||
inheritAttrs: false,
|
||||
slots: Object as SlotsType<{
|
||||
indicator?: { percent: number, value: number }
|
||||
label?: { percent: number, value: number }
|
||||
}>,
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
@@ -94,10 +98,6 @@ export default defineComponent({
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
slots: Object as SlotsType<{
|
||||
indicator?: { percent: number, value: number }
|
||||
label?: { percent: number, value: number }
|
||||
}>,
|
||||
setup(props) {
|
||||
const { ui, attrs } = useUI('meter', toRef(props, 'ui'), config, toRef(props, 'class'))
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { ComputedRef, VNode, SlotsType, PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { getSlotsChildren, mergeConfig } from '../../utils'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import type { DeepPartial, Strategy, MeterSize } from '../../types/index'
|
||||
import type Meter from './Meter.vue'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { provide, ref, defineComponent, onUnmounted, onMounted, readonly } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { provide, ref, type PropType, defineComponent, onUnmounted, onMounted, readonly } from 'vue'
|
||||
import { useEventBus } from '@vueuse/core'
|
||||
import type { ZodSchema } from 'zod'
|
||||
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
|
||||
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
||||
import type { BaseSchema as ValibotSchema30, BaseSchemaAsync as ValibotSchemaAsync30 } from 'valibot30'
|
||||
import type { GenericSchema as ValibotSchema31, GenericSchemaAsync as ValibotSchemaAsync31, SafeParser as ValibotSafeParser31, SafeParserAsync as ValibotSafeParserAsync31 } from 'valibot31'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { Struct } from 'superstruct'
|
||||
import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEvent, Form, ValidateReturnSchema } from '../../types/form'
|
||||
import { useId } from '#imports'
|
||||
@@ -23,10 +25,14 @@ class FormException extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
type Schema = PropType<StandardSchemaV1>
|
||||
type Schema = PropType<ZodSchema>
|
||||
| PropType<YupObjectSchema<any>>
|
||||
| PropType<Struct<any, any>>
|
||||
| PropType<JoiSchema>
|
||||
| PropType<ValibotSchema30 | ValibotSchemaAsync30>
|
||||
| PropType<ValibotSchema31 | ValibotSchemaAsync31>
|
||||
| PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>>
|
||||
| PropType<ValibotSchema | ValibotSchemaAsync>
|
||||
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -54,8 +60,6 @@ export default defineComponent({
|
||||
const formId = useId()
|
||||
const bus = useEventBus<FormEvent>(`form-${formId}`)
|
||||
|
||||
const parsedValue = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
bus.on(async (event) => {
|
||||
if (event.type !== 'submit' && props.validateOn?.includes(event.type)) {
|
||||
@@ -83,7 +87,7 @@ export default defineComponent({
|
||||
if (errors) {
|
||||
errs = errs.concat(errors)
|
||||
} else {
|
||||
parsedValue.value = result
|
||||
Object.assign(props.state, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +130,7 @@ export default defineComponent({
|
||||
if (props.validateOn?.includes('submit')) {
|
||||
await validate()
|
||||
}
|
||||
event.data = props.schema ? parsedValue.value : props.state
|
||||
event.data = props.state
|
||||
emit('submit', event)
|
||||
} catch (error) {
|
||||
if (!(error instanceof FormException)) {
|
||||
@@ -206,18 +210,26 @@ function isJoiError(error: any): error is JoiError {
|
||||
return error.isJoi === true
|
||||
}
|
||||
|
||||
export function isStandardSchema(schema: any): schema is StandardSchemaV1 {
|
||||
return '~standard' in schema
|
||||
function isValibotSchema(schema: any): schema is ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
|
||||
return '_parse' in schema || '_run' in schema || (typeof schema === 'function' && 'schema' in schema)
|
||||
}
|
||||
|
||||
export async function validateStandardSchema(
|
||||
function isZodSchema(schema: any): schema is ZodSchema {
|
||||
return schema.parse !== undefined
|
||||
}
|
||||
|
||||
async function validateValibotSchema(
|
||||
state: any,
|
||||
schema: StandardSchemaV1
|
||||
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
||||
): Promise<ValidateReturnSchema<typeof state>> {
|
||||
const result = await schema['~standard'].validate(state)
|
||||
const result = await ('_parse' in schema ? schema._parse(state) : '_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state))
|
||||
|
||||
if (!result.issues || result.issues.length === 0) {
|
||||
const output = ('value' in result ? result.value : null)
|
||||
const output = ('output' in result
|
||||
? result.output
|
||||
: 'value' in result
|
||||
? result.value
|
||||
: null)
|
||||
return {
|
||||
errors: null,
|
||||
result: output
|
||||
@@ -225,7 +237,7 @@ export async function validateStandardSchema(
|
||||
}
|
||||
|
||||
const errors = result.issues.map(issue => ({
|
||||
path: issue.path?.map(item => typeof item === 'object' ? item.key : item).join('.') || '',
|
||||
path: issue.path?.map(item => item.key).join('.') || '',
|
||||
message: issue.message
|
||||
}))
|
||||
|
||||
@@ -262,6 +274,28 @@ async function validateJoiSchema(
|
||||
}
|
||||
}
|
||||
|
||||
async function validateZodSchema(
|
||||
state: any,
|
||||
schema: ZodSchema
|
||||
): Promise<ValidateReturnSchema<typeof state>> {
|
||||
const result = await schema.safeParseAsync(state)
|
||||
if (result.success === false) {
|
||||
const errors = result.error.issues.map(issue => ({
|
||||
path: issue.path.join('.'),
|
||||
message: issue.message
|
||||
}))
|
||||
|
||||
return {
|
||||
errors,
|
||||
result: null
|
||||
}
|
||||
}
|
||||
return {
|
||||
result: result.data,
|
||||
errors: null
|
||||
}
|
||||
}
|
||||
|
||||
async function validateSuperstructSchema(state: any, schema: Struct<any, any>): Promise<ValidateReturnSchema<typeof state>> {
|
||||
const [err, result] = schema.validate(state)
|
||||
if (err) {
|
||||
@@ -287,7 +321,7 @@ async function validateYupSchema(
|
||||
schema: YupObjectSchema<any>
|
||||
): Promise<ValidateReturnSchema<typeof state>> {
|
||||
try {
|
||||
const result = await schema.validate(state, { abortEarly: false })
|
||||
const result = schema.validateSync(state, { abortEarly: false })
|
||||
return {
|
||||
errors: null,
|
||||
result
|
||||
@@ -310,10 +344,12 @@ async function validateYupSchema(
|
||||
}
|
||||
|
||||
function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> {
|
||||
if (isStandardSchema(schema)) {
|
||||
return validateStandardSchema(state, schema)
|
||||
if (isZodSchema(schema)) {
|
||||
return validateZodSchema(state, schema)
|
||||
} else if (isJoiSchema(schema)) {
|
||||
return validateJoiSchema(state, schema)
|
||||
} else if (isValibotSchema(schema)) {
|
||||
return validateValibotSchema(state, schema)
|
||||
} else if (isYupSchema(schema)) {
|
||||
return validateYupSchema(state, schema)
|
||||
} else if (isSuperStructSchema(schema)) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user