mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-18 14:08:06 +01:00
Compare commits
304 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13be8f1c83 | ||
|
|
48f68de4ca | ||
|
|
13bd3f3804 | ||
|
|
65735e787f | ||
|
|
6b971b8e6c | ||
|
|
1598d8fc72 | ||
|
|
2176e30113 | ||
|
|
1f3e9789fe | ||
|
|
b797690483 | ||
|
|
f7303d5c94 | ||
|
|
346031f279 | ||
|
|
dae6d77cf2 | ||
|
|
c1d5bcc1ac | ||
|
|
1bc44f8594 | ||
|
|
9ee68d20fc | ||
|
|
d5f50be354 | ||
|
|
03ab56c9bd | ||
|
|
9985fd5af4 | ||
|
|
fb2a835a78 | ||
|
|
2d5100044b | ||
|
|
7903d2adc2 | ||
|
|
cd9ee1ff99 | ||
|
|
29208f1877 | ||
|
|
f9f505b0c0 | ||
|
|
7361914715 | ||
|
|
88923bb678 | ||
|
|
212154d0d0 | ||
|
|
b9037e166f | ||
|
|
58fc563d63 | ||
|
|
11569bc7e0 | ||
|
|
1934063763 | ||
|
|
b6de20104f | ||
|
|
2971a31242 | ||
|
|
30068da217 | ||
|
|
44734f717e | ||
|
|
77cc1f3670 | ||
|
|
e55a27a503 | ||
|
|
45f5e628ea | ||
|
|
e47bba9a05 | ||
|
|
fcbedd1244 | ||
|
|
3a964d5a4b | ||
|
|
b7c9c83dfa | ||
|
|
43ee099fbe | ||
|
|
4bc9878ef4 | ||
|
|
bb8d7aa48e | ||
|
|
8c727f21d7 | ||
|
|
48fabbcdeb | ||
|
|
c46b952022 | ||
|
|
c0e14d006e | ||
|
|
a58efd23aa | ||
|
|
ec2b51b59e | ||
|
|
e2dc287dbb | ||
|
|
dbe8b34b6e | ||
|
|
091725f940 | ||
|
|
c21fbe5ec6 | ||
|
|
cff1282f30 | ||
|
|
86a7da03b1 | ||
|
|
252189de0a | ||
|
|
4451768415 | ||
|
|
8e67cab77a | ||
|
|
d113c31844 | ||
|
|
18e4b4ff4e | ||
|
|
1c8ec1d857 | ||
|
|
d7872a149c | ||
|
|
9104a4d54d | ||
|
|
0506c0cc6a | ||
|
|
2bef1e26c6 | ||
|
|
02694db29c | ||
|
|
b8a7a47620 | ||
|
|
bd732d3b34 | ||
|
|
93406d26b8 | ||
|
|
b034a5679c | ||
|
|
c7b1fc32ad | ||
|
|
3b0dbfe473 | ||
|
|
1454149c97 | ||
|
|
5af04bad5f | ||
|
|
f242c7243e | ||
|
|
5a864e8d6f | ||
|
|
ee373629d5 | ||
|
|
63b5f2bc2f | ||
|
|
4e96dcca42 | ||
|
|
b131b1168b | ||
|
|
3c849b98a6 | ||
|
|
714e0ff250 | ||
|
|
74c77f9bac | ||
|
|
54fda9eef8 | ||
|
|
c3567a34a4 | ||
|
|
d210d18a2f | ||
|
|
7aeecea599 | ||
|
|
70e889813c | ||
|
|
2b9696f4d3 | ||
|
|
188184b674 | ||
|
|
b0d1da8dc2 | ||
|
|
fec5f3f3ce | ||
|
|
05509b7ed1 | ||
|
|
88b17cd93c | ||
|
|
0eca0fd201 | ||
|
|
420fcb003a | ||
|
|
f607140941 | ||
|
|
40da32588d | ||
|
|
264373b499 | ||
|
|
bb70218568 | ||
|
|
402f508e7d | ||
|
|
0d69747c9d | ||
|
|
760eb467be | ||
|
|
b830f63c89 | ||
|
|
71dac5e5b0 | ||
|
|
7b81bfa1ae | ||
|
|
bf1c9e7c94 | ||
|
|
23d9b51a58 | ||
|
|
2e6ba71e89 | ||
|
|
ea4007c62d | ||
|
|
69d6997210 | ||
|
|
6565472570 | ||
|
|
ee408e522e | ||
|
|
461e6173a9 | ||
|
|
b824f0682e | ||
|
|
7ce6af4870 | ||
|
|
b4cc9a5ab4 | ||
|
|
06eceff68b | ||
|
|
40f3e3b486 | ||
|
|
a5458765dc | ||
|
|
ac574b239b | ||
|
|
feb716c941 | ||
|
|
15da5cf71e | ||
|
|
125a28190b | ||
|
|
569fa7619b | ||
|
|
0ff2448655 | ||
|
|
a6c3daa363 | ||
|
|
e16eeee8c1 | ||
|
|
53ac62eae5 | ||
|
|
9c36d37b84 | ||
|
|
0462edb84e | ||
|
|
91e77bb09c | ||
|
|
84e35d1a79 | ||
|
|
28f29e98b8 | ||
|
|
81d7ca0cd1 | ||
|
|
89d3766835 | ||
|
|
9104213d35 | ||
|
|
d699558e38 | ||
|
|
7cbc3913d9 | ||
|
|
d2ceeadae7 | ||
|
|
c7f64b64c7 | ||
|
|
72ab47e77d | ||
|
|
5b187d6fbd | ||
|
|
f9e61fc422 | ||
|
|
1291e95e1c | ||
|
|
f943203770 | ||
|
|
f2d387622a | ||
|
|
b02dc4d5b7 | ||
|
|
6dddadc370 | ||
|
|
d89ecce472 | ||
|
|
efb74668bd | ||
|
|
e065734d58 | ||
|
|
0c5bea5f11 | ||
|
|
f6d4dd3b88 | ||
|
|
d9d4f1915a | ||
|
|
c70d29702e | ||
|
|
a0d8935f64 | ||
|
|
04aefcf81f | ||
|
|
e68b9795be | ||
|
|
b8c8718560 | ||
|
|
2a33a8171d | ||
|
|
23cfc046e7 | ||
|
|
e68cb53ab6 | ||
|
|
109b857472 | ||
|
|
ea15e21cdc | ||
|
|
b7153cd879 | ||
|
|
5047d448ed | ||
|
|
a0fee0fa73 | ||
|
|
b762d29220 | ||
|
|
98c19be71a | ||
|
|
8cf9f27d53 | ||
|
|
c0455c831f | ||
|
|
0360ea7a3c | ||
|
|
711539f3ce | ||
|
|
80d6d89467 | ||
|
|
d573fb636f | ||
|
|
1d08d319a7 | ||
|
|
b654c93e93 | ||
|
|
b7e04db645 | ||
|
|
e6034a2765 | ||
|
|
a8c38224c6 | ||
|
|
a9ef6406ea | ||
|
|
96e846ddee | ||
|
|
16dbc1b536 | ||
|
|
c6b2ae45e5 | ||
|
|
547c657ee7 | ||
|
|
b16b434041 | ||
|
|
fb12323304 | ||
|
|
0a404615ff | ||
|
|
cbf0f22efd | ||
|
|
4cde571e38 | ||
|
|
023497d144 | ||
|
|
56d4ca3b74 | ||
|
|
11b8c3d9db | ||
|
|
419a24f703 | ||
|
|
854bb81295 | ||
|
|
bf8e3954a4 | ||
|
|
637ec4d27b | ||
|
|
f3632ddee5 | ||
|
|
dbd2aed20b | ||
|
|
51c8b8e3e5 | ||
|
|
588a908358 | ||
|
|
d692a81b1e | ||
|
|
ec98d415b4 | ||
|
|
c80d2e6c12 | ||
|
|
ce61a2b6db | ||
|
|
eee5bb9939 | ||
|
|
d3804157ec | ||
|
|
03e24f4583 | ||
|
|
d0e626c551 | ||
|
|
670d8bfbac | ||
|
|
64b703df8d | ||
|
|
976b03f241 | ||
|
|
35e3b8c720 | ||
|
|
07ef771b17 | ||
|
|
5c75b5c490 | ||
|
|
53df9d9a8c | ||
|
|
0d1a76e3c6 | ||
|
|
b2ed4662af | ||
|
|
423c48879d | ||
|
|
acecff40ec | ||
|
|
1fd5fac295 | ||
|
|
b23f2decfc | ||
|
|
7154254ac2 | ||
|
|
49f85d55c5 | ||
|
|
97037864b3 | ||
|
|
0abccabc26 | ||
|
|
ac323c4ccc | ||
|
|
d4e408cfd8 | ||
|
|
f3bf69c233 | ||
|
|
d6daf466ac | ||
|
|
6e66990372 | ||
|
|
56e28d80db | ||
|
|
24e61ccc8b | ||
|
|
c9e6256e7f | ||
|
|
ce955d24f1 | ||
|
|
bf580863af | ||
|
|
f38a217032 | ||
|
|
717a027bad | ||
|
|
159acd664c | ||
|
|
212f7df35b | ||
|
|
d0d37a06d2 | ||
|
|
cb6f5f2d71 | ||
|
|
22da1a839a | ||
|
|
c5f76a25db | ||
|
|
ceecb60c3b | ||
|
|
23971efdb0 | ||
|
|
1a94b55caa | ||
|
|
c71fdc8795 | ||
|
|
6844f7bbd9 | ||
|
|
1acd01a440 | ||
|
|
0b2a3989a2 | ||
|
|
5f8d645231 | ||
|
|
2cc838ea8b | ||
|
|
2e41e3f238 | ||
|
|
7cb8218ed5 | ||
|
|
ddf67a060b | ||
|
|
54e713d31a | ||
|
|
09e232ed05 | ||
|
|
1d455b092d | ||
|
|
13957ba206 | ||
|
|
ff1806143c | ||
|
|
b6ed1c59ff | ||
|
|
424efe783e | ||
|
|
c3cd3c9940 | ||
|
|
8ab4a14394 | ||
|
|
25378df1d8 | ||
|
|
070d2f89b6 | ||
|
|
8e413f0681 | ||
|
|
03ac697167 | ||
|
|
c6a9b499e3 | ||
|
|
cae4f0c4a8 | ||
|
|
b29fcd2650 | ||
|
|
3671b2fbbe | ||
|
|
2577eb2780 | ||
|
|
3d1be39221 | ||
|
|
49e04389fa | ||
|
|
ee364318d1 | ||
|
|
b14afbebe9 | ||
|
|
4bf81be364 | ||
|
|
7846ca35b5 | ||
|
|
b72d3434e9 | ||
|
|
20fb46a3ba | ||
|
|
1b7e36cf70 | ||
|
|
3768cd9803 | ||
|
|
3d0bba2e83 | ||
|
|
494e73932b | ||
|
|
38200aa392 | ||
|
|
19b01f43f1 | ||
|
|
c36964b5ea | ||
|
|
4de8f2e2f7 | ||
|
|
3cf19ea5af | ||
|
|
9dd7e615e9 | ||
|
|
33b9a445c4 | ||
|
|
46cec7ecd1 | ||
|
|
f8e2c94375 | ||
|
|
71e0492179 | ||
|
|
3cda6c6478 | ||
|
|
428ee44fc0 | ||
|
|
c68ba76fd0 | ||
|
|
dd0d0551be | ||
|
|
3efcf3026a |
@@ -1,14 +0,0 @@
|
|||||||
node_modules
|
|
||||||
dist
|
|
||||||
.nuxt
|
|
||||||
coverage
|
|
||||||
*.log*
|
|
||||||
.DS_Store
|
|
||||||
.code
|
|
||||||
*.iml
|
|
||||||
package-lock.json
|
|
||||||
templates/*
|
|
||||||
sw.js
|
|
||||||
|
|
||||||
# Templates
|
|
||||||
src/templates
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
extends: ['@nuxt/eslint-config'],
|
|
||||||
rules: {
|
|
||||||
// General
|
|
||||||
semi: ['error', 'never'],
|
|
||||||
quotes: ['error', 'single'],
|
|
||||||
'comma-dangle': ['error', 'never'],
|
|
||||||
'comma-spacing': ['error', { before: false, after: true }],
|
|
||||||
'keyword-spacing': ['error', { before: true, after: true }],
|
|
||||||
'space-before-function-paren': ['error', 'always'],
|
|
||||||
'object-curly-spacing': ['error', 'always'],
|
|
||||||
'arrow-spacing': ['error', { before: true, after: true }],
|
|
||||||
'key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
|
|
||||||
'space-before-blocks': ['error', 'always'],
|
|
||||||
'space-infix-ops': ['error', { int32Hint: false }],
|
|
||||||
'no-multi-spaces': ['error', { ignoreEOLComments: true }],
|
|
||||||
'no-trailing-spaces': ['error'],
|
|
||||||
|
|
||||||
// Typescript
|
|
||||||
'@typescript-eslint/type-annotation-spacing': 'error',
|
|
||||||
|
|
||||||
// Vuejs
|
|
||||||
'vue/multi-word-component-names': 0,
|
|
||||||
'vue/html-indent': ['error', 2],
|
|
||||||
'vue/comma-spacing': ['error', { before: false, after: true }],
|
|
||||||
'vue/script-indent': ['error', 2, { baseIndent: 0 }],
|
|
||||||
'vue/keyword-spacing': ['error', { before: true, after: true }],
|
|
||||||
'vue/object-curly-spacing': ['error', 'always'],
|
|
||||||
'vue/key-spacing': ['error', { beforeColon: false, afterColon: true, mode: 'strict' }],
|
|
||||||
'vue/arrow-spacing': ['error', { before: true, after: true }],
|
|
||||||
'vue/array-bracket-spacing': ['error', 'never'],
|
|
||||||
'vue/block-spacing': ['error', 'always'],
|
|
||||||
'vue/brace-style': ['error', 'stroustrup', { allowSingleLine: true }],
|
|
||||||
'vue/space-infix-ops': ['error', { int32Hint: false }],
|
|
||||||
'vue/max-attributes-per-line': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
singleline: {
|
|
||||||
max: 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'vue/padding-line-between-blocks': ['error', 'always']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @benjamincanac
|
||||||
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -5,7 +5,7 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
Before reporting a bug, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: env
|
id: env
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/bug-v3.yml
vendored
11
.github/ISSUE_TEMPLATE/bug-v3.yml
vendored
@@ -29,11 +29,20 @@ body:
|
|||||||
- Build Modules: `-`
|
- Build Modules: `-`
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: package
|
||||||
|
attributes:
|
||||||
|
label: Is this bug related to Nuxt or Vue?
|
||||||
|
options:
|
||||||
|
- Nuxt
|
||||||
|
- Vue
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: version
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
label: Version
|
label: Version
|
||||||
placeholder: v3.0.0-alpha.5
|
placeholder: v3.0.0-alpha.x
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
11
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -5,7 +5,16 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
Before requesting a feature, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
Before requesting a feature, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: For what version of Nuxt UI are you suggesting this?
|
||||||
|
options:
|
||||||
|
- v2.x
|
||||||
|
- v3.0.0-alpha.x
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/question.yml
vendored
11
.github/ISSUE_TEMPLATE/question.yml
vendored
@@ -5,7 +5,16 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
Before asking a question, please make sure that you have read through our [documentation](https://ui.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
Before asking a question, please make sure that you have read through our [documentation](https://ui2.nuxt.com) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
|
||||||
|
- type: dropdown
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: For what version of Nuxt UI are you asking this question?
|
||||||
|
options:
|
||||||
|
- v2.x
|
||||||
|
- v3.0.0-alpha.x
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
name: ci-dev
|
name: module
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- v2
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
- v2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||||
node: [20]
|
node: [22]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||||
@@ -37,16 +37,6 @@ jobs:
|
|||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Filter changes
|
|
||||||
uses: dorny/paths-filter@v3
|
|
||||||
id: changes
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
src:
|
|
||||||
- 'src/**'
|
|
||||||
- 'package.json'
|
|
||||||
- 'pnpm-lock.yaml'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
@@ -65,8 +55,5 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm run test run
|
run: pnpm run test run
|
||||||
|
|
||||||
- name: Release Edge
|
- name: Publish
|
||||||
if: github.event_name == 'push' && steps.changes.outputs.src == 'true'
|
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
|
||||||
run: ./scripts/release-edge.sh
|
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
|
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
name: ci-main
|
name: release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
tags:
|
||||||
- main
|
- 'v2*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
publish:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest] # macos-latest, windows-latest
|
os: [ubuntu-latest] # macos-latest, windows-latest
|
||||||
node: [20]
|
node: [22]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
|
||||||
@@ -48,14 +48,7 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: pnpm run test run
|
run: pnpm run test run
|
||||||
|
|
||||||
- name: Version Check
|
- name: Publish
|
||||||
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
|
run: ./scripts/release.sh
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||||
23
.github/workflows/stale.yml
vendored
23
.github/workflows/stale.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
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
|
|
||||||
122
CHANGELOG.md
122
CHANGELOG.md
@@ -1,5 +1,127 @@
|
|||||||
# Changelog
|
# 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
|
||||||
|
|
||||||
|
* **Button:** put back `target` override ([212f7df](https://github.com/nuxt/ui/commit/212f7df35b9f81d189e1ee3e34f6fd2234cf52fe))
|
||||||
|
|
||||||
|
## [2.19.1](https://github.com/nuxt/ui/compare/v2.19.0...v2.19.1) (2024-11-05)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **InputMenu/SelectMenu:** regex breaks build ([cb6f5f2](https://github.com/nuxt/ui/commit/cb6f5f2d71ea8bb526a8f958daec8e9871469b63))
|
||||||
|
|
||||||
|
## [2.19.0](https://github.com/nuxt/ui/compare/v2.18.7...v2.19.0) (2024-11-05)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Form:** add `superstruct` validation ([#2357](https://github.com/nuxt/ui/issues/2357)) ([3cda6c6](https://github.com/nuxt/ui/commit/3cda6c6478d5284a3ffcb973270831601e8e5657))
|
||||||
|
* **Form:** apply transformations ([#2460](https://github.com/nuxt/ui/issues/2460)) ([ceecb60](https://github.com/nuxt/ui/commit/ceecb60c3bbd5507b1f54faed001818639d9269c))
|
||||||
|
* **Input/Textarea:** nullify model modifier ([#2309](https://github.com/nuxt/ui/issues/2309)) ([9dd7e61](https://github.com/nuxt/ui/commit/9dd7e615e97b6bf3c4c4096edd35a86ca3cfd53c))
|
||||||
|
* **InputMenu:** allows to customize labels ([#2295](https://github.com/nuxt/ui/issues/2295)) ([ddf67a0](https://github.com/nuxt/ui/commit/ddf67a060ba659f102673eff31eb2e30231c2d93))
|
||||||
|
* **Pagination:** improve slot props ([#2522](https://github.com/nuxt/ui/issues/2522)) ([c71fdc8](https://github.com/nuxt/ui/commit/c71fdc8795812bed779ab247451efd3db031e4cd))
|
||||||
|
* **SelectMenu:** allows to customize labels ([#2266](https://github.com/nuxt/ui/issues/2266)) ([54e713d](https://github.com/nuxt/ui/commit/54e713d31ae0b80b0f69dd507f71387100204ac3))
|
||||||
|
* **Table:** improve `expanded` row ([#2485](https://github.com/nuxt/ui/issues/2485)) ([1acd01a](https://github.com/nuxt/ui/commit/1acd01a440db7a7fa765189d8bde424ade9074e9))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **Accordion:** improve `items` type ([#2487](https://github.com/nuxt/ui/issues/2487)) ([25378df](https://github.com/nuxt/ui/commit/25378df1d894546c4b08eb43a58b02b40ab9649b))
|
||||||
|
* **Button:** wrong `to` type ([8ab4a14](https://github.com/nuxt/ui/commit/8ab4a14394e0890b33a610e6491d891e89386959)), closes [#1253](https://github.com/nuxt/ui/issues/1253)
|
||||||
|
* **Divider:** default `type` from app config ([7846ca3](https://github.com/nuxt/ui/commit/7846ca35b5332a9e70f9990059f6041d60770e79)), closes [nuxt/ui#2398](https://github.com/nuxt/ui/issues/2398)
|
||||||
|
* **HorizontalNavigation/VerticalNavigation:** handle `badge` in RTL mode ([#2420](https://github.com/nuxt/ui/issues/2420)) ([4bf81be](https://github.com/nuxt/ui/commit/4bf81be36463bf280f31099c97a751e65240dcf5))
|
||||||
|
* **InputMenu/SelectMenu:** allow access nested object in `option-attribute` ([#2465](https://github.com/nuxt/ui/issues/2465)) ([ff18061](https://github.com/nuxt/ui/commit/ff1806143c45a7d83b00e78bec979a8f412a2827))
|
||||||
|
* **InputMenu/SelectMenu:** escape regexp before search ([c68ba76](https://github.com/nuxt/ui/commit/c68ba76fd0eebf411ccd5f047ee9a01b8ec5f5de)), closes [nuxt/ui#2308](https://github.com/nuxt/ui/issues/2308)
|
||||||
|
* **InputMenu/SelectMenu:** prevent unnecessary updates when modelValue is unchanged ([#2507](https://github.com/nuxt/ui/issues/2507)) ([1a94b55](https://github.com/nuxt/ui/commit/1a94b55caac91685f518ae4c24ca8dcbee827f86))
|
||||||
|
* **module:** missing types in `ui` config ([#2467](https://github.com/nuxt/ui/issues/2467)) ([23971ef](https://github.com/nuxt/ui/commit/23971efdb007701352ce58412db597cd95b9996b))
|
||||||
|
* **Progress:** handle `carousel` and `carousel-inverse` animations in RTL mode ([#2400](https://github.com/nuxt/ui/issues/2400)) ([20fb46a](https://github.com/nuxt/ui/commit/20fb46a3ba8d74fcaa1407b23d65b117cc9d6802))
|
||||||
|
* **RadioGroup:** rendering empty slots ([#2456](https://github.com/nuxt/ui/issues/2456)) ([b6ed1c5](https://github.com/nuxt/ui/commit/b6ed1c59ffe8c8aaac78a34d8559ca793bb92eaa))
|
||||||
|
* **Table:** `checkbox` not checked while using props by ([#2401](https://github.com/nuxt/ui/issues/2401)) ([1b7e36c](https://github.com/nuxt/ui/commit/1b7e36cf70a7252915c58657bc878cb29c719a7f))
|
||||||
|
* **Table:** `indeterminate` checkbox with pagination ([#2439](https://github.com/nuxt/ui/issues/2439)) ([070d2f8](https://github.com/nuxt/ui/commit/070d2f89b6d1cb9c236eeb779cb3918ed5770434))
|
||||||
|
* **Table:** export `TableRow` and `TableColumn` types ([c36964b](https://github.com/nuxt/ui/commit/c36964b5eacbd61a661f02953f0297a390fd1d34)), closes [nuxt/ui#2373](https://github.com/nuxt/ui/issues/2373)
|
||||||
|
* **Table:** handle dot nation with `by` prop ([#2413](https://github.com/nuxt/ui/issues/2413)) ([b72d343](https://github.com/nuxt/ui/commit/b72d3434e9ab024e8622611d32b5a4467c8364b9))
|
||||||
|
* **Tabs:** allow `aria-label` on items ([3cf19ea](https://github.com/nuxt/ui/commit/3cf19ea5afcf97ef226d8be231d3b297c5f23b9f)), closes [nuxt/ui#1934](https://github.com/nuxt/ui/issues/1934)
|
||||||
|
|
||||||
## [2.18.7](https://github.com/nuxt/ui/compare/v2.18.6...v2.18.7) (2024-10-09)
|
## [2.18.7](https://github.com/nuxt/ui/compare/v2.18.6...v2.18.7) (2024-10-09)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -1,4 +1,4 @@
|
|||||||
[](https://ui.nuxt.com)
|
[](https://ui2.nuxt.com)
|
||||||
|
|
||||||
# Nuxt UI
|
# Nuxt UI
|
||||||
|
|
||||||
@@ -20,29 +20,34 @@ Its goal is to provide everything related to UI when building a Nuxt app. This i
|
|||||||
- Keyboard shortcuts
|
- Keyboard shortcuts
|
||||||
- Bundled icons
|
- Bundled icons
|
||||||
- Fully typed
|
- Fully typed
|
||||||
- [Figma Kit](https://www.figma.com/community/file/1288455405058138934)
|
- [Figma Kit](https://www.figma.com/community/file/1436401057300493073)
|
||||||
|
|
||||||
Read more on [ui.nuxt.com](https://ui.nuxt.com)
|
Read more on [ui2.nuxt.com](https://ui2.nuxt.com)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx nuxi@latest module add ui
|
# npm
|
||||||
|
npm install @nuxt/ui@2
|
||||||
|
# yarn
|
||||||
|
yarn add @nuxt/ui@2
|
||||||
|
# pnpm
|
||||||
|
pnpm add @nuxt/ui@2
|
||||||
|
# bun
|
||||||
|
bun add @nuxt/ui@2
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want latest updates, please use `@nuxt/ui-edge` in your `package.json`:
|
Next, register the `@nuxt/ui` module in your `nuxt.config.ts`:
|
||||||
|
|
||||||
```json
|
```ts
|
||||||
{
|
export default defineNuxtConfig({
|
||||||
"devDependencies": {
|
modules: ['@nuxt/ui']
|
||||||
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Visit https://ui.nuxt.com to explore the documentation.
|
Visit https://ui2.nuxt.com to explore the documentation.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
@@ -59,15 +64,15 @@ Visit https://ui.nuxt.com to explore the documentation.
|
|||||||
Thank you for considering contributing to Nuxt UI. Here are a few ways you can get involved:
|
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.
|
- 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://ui.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://ui2.nuxt.com/getting-started/contributing) to share your suggestions.
|
||||||
|
|
||||||
## Local Development
|
## Local Development
|
||||||
|
|
||||||
Follow the docs to [Set up your local development environment](https://ui.nuxt.com/getting-started/contributing#_2-local-development-setup) and contribute.
|
Follow the docs to [Set up your local development environment](https://ui2.nuxt.com/getting-started/contributing#_2-local-development-setup) and contribute.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/dev/LICENSE.md).
|
Licensed under the [MIT license](https://github.com/nuxt/ui/blob/v2/LICENSE.md).
|
||||||
|
|
||||||
<!-- Badges -->
|
<!-- Badges -->
|
||||||
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
[npm-version-src]: https://img.shields.io/npm/v/@nuxt/ui/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
||||||
|
|||||||
34
docs/app.vue
34
docs/app.vue
@@ -3,7 +3,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<NuxtLoadingIndicator />
|
<NuxtLoadingIndicator />
|
||||||
|
|
||||||
<!-- <Banner v-if="!$route.path.startsWith('/examples')" /> -->
|
<Banner v-if="!$route.path.startsWith('/examples')" />
|
||||||
|
|
||||||
<Header v-if="!$route.path.startsWith('/examples')" :links="links" />
|
<Header v-if="!$route.path.startsWith('/examples')" :links="links" />
|
||||||
|
|
||||||
@@ -50,20 +50,22 @@ const links = computed(() => {
|
|||||||
icon: 'i-heroicons-book-open',
|
icon: 'i-heroicons-book-open',
|
||||||
to: '/getting-started',
|
to: '/getting-started',
|
||||||
active: route.path.startsWith('/getting-started') || route.path.startsWith('/components')
|
active: route.path.startsWith('/getting-started') || route.path.startsWith('/components')
|
||||||
}, ...(navigation.value.find(item => item._path === '/pro') ? [{
|
}, ...(navigation.value.find(item => item._path === '/pro')
|
||||||
label: 'Pro',
|
? [{
|
||||||
icon: 'i-heroicons-square-3-stack-3d',
|
label: 'Pro',
|
||||||
to: '/pro',
|
icon: 'i-heroicons-square-3-stack-3d',
|
||||||
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
|
to: '/pro',
|
||||||
}, {
|
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
|
||||||
label: 'Pricing',
|
}, {
|
||||||
icon: 'i-heroicons-ticket',
|
label: 'Pricing',
|
||||||
to: '/pro/pricing'
|
icon: 'i-heroicons-ticket',
|
||||||
}, {
|
to: '/pro/pricing'
|
||||||
label: 'Templates',
|
}, {
|
||||||
icon: 'i-heroicons-computer-desktop',
|
label: 'Templates',
|
||||||
to: '/pro/templates'
|
icon: 'i-heroicons-computer-desktop',
|
||||||
}] : []), {
|
to: '/pro/templates'
|
||||||
|
}]
|
||||||
|
: []), {
|
||||||
label: 'Releases',
|
label: 'Releases',
|
||||||
icon: 'i-heroicons-rocket-launch',
|
icon: 'i-heroicons-rocket-launch',
|
||||||
to: '/releases'
|
to: '/releases'
|
||||||
@@ -89,7 +91,7 @@ useHead({
|
|||||||
],
|
],
|
||||||
link: [
|
link: [
|
||||||
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
|
||||||
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
|
{ rel: 'canonical', href: `https://ui2.nuxt.com${withoutTrailingSlash(route.path)}` }
|
||||||
],
|
],
|
||||||
htmlAttrs: {
|
htmlAttrs: {
|
||||||
lang: 'en'
|
lang: 'en'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const id = 'nuxt-ui-banner-1'
|
const id = 'nuxt-ui-banner-4'
|
||||||
const to = '/pro/pricing'
|
const to = 'https://ui.nuxt.com'
|
||||||
|
|
||||||
const hideBanner = () => {
|
const hideBanner = () => {
|
||||||
localStorage.setItem(id, 'true')
|
localStorage.setItem(id, 'true')
|
||||||
@@ -25,7 +25,13 @@ if (import.meta.server) {
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
|
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
|
||||||
<UContainer class="py-2">
|
<UContainer class="py-2">
|
||||||
<NuxtLink v-if="to" :to="to" class="focus:outline-none" aria-label="Nuxt UI Pro pricing" tabindex="-1">
|
<NuxtLink
|
||||||
|
v-if="to"
|
||||||
|
:to="to"
|
||||||
|
target="_blank"
|
||||||
|
class="focus:outline-none"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
<span class="absolute inset-0 " aria-hidden="true" />
|
<span class="absolute inset-0 " aria-hidden="true" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
@@ -33,10 +39,20 @@ if (import.meta.server) {
|
|||||||
<div class="lg:flex-1 hidden lg:flex items-center" />
|
<div class="lg:flex-1 hidden lg:flex items-center" />
|
||||||
|
|
||||||
<p class="text-sm font-medium text-white dark:text-gray-900 truncate">
|
<p class="text-sm font-medium text-white dark:text-gray-900 truncate">
|
||||||
<UIcon name="i-heroicons-rocket-launch" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
|
<UIcon name="i-lucide-rocket" class="size-5 align-top flex-shrink-0 pointer-events-none mr-1.5" />
|
||||||
<span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components!
|
<span class="font-bold">Nuxt UI v3</span> is officially released!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- <UButton
|
||||||
|
:to="to"
|
||||||
|
target="_blank"
|
||||||
|
label="Buy now"
|
||||||
|
color="black"
|
||||||
|
variant="solid"
|
||||||
|
size="2xs"
|
||||||
|
trailing-icon="i-heroicons-arrow-right-20-solid"
|
||||||
|
/> -->
|
||||||
|
|
||||||
<div class="flex items-center justify-end lg:flex-1">
|
<div class="flex items-center justify-end lg:flex-1">
|
||||||
<button
|
<button
|
||||||
class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
|
class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const { $ui } = useNuxtApp()
|
|||||||
const links = [{
|
const links = [{
|
||||||
icon: 'i-simple-icons-figma',
|
icon: 'i-simple-icons-figma',
|
||||||
label: 'Figma Kit',
|
label: 'Figma Kit',
|
||||||
to: 'https://www.figma.com/community/file/1288455405058138934',
|
to: 'https://www.figma.com/community/file/1436401057300493073',
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
}, {
|
}, {
|
||||||
label: 'Playground',
|
label: 'Playground',
|
||||||
|
|||||||
@@ -10,12 +10,34 @@
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #left>
|
<template #left>
|
||||||
<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">
|
<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">
|
||||||
<LogoPro v-if="$route.path.startsWith('/pro')" class="w-auto h-6 shrink-0" />
|
<LogoPro v-if="$route.path.startsWith('/pro')" class="w-auto h-6 shrink-0" />
|
||||||
<Logo v-else class="w-auto h-6 shrink-0" />
|
<Logo v-else class="w-auto h-6 shrink-0" />
|
||||||
|
|
||||||
<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>
|
</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>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #right>
|
<template #right>
|
||||||
@@ -25,10 +47,10 @@
|
|||||||
<UContentSearchButton :label="null" />
|
<UContentSearchButton :label="null" />
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
|
|
||||||
<UColorModeButton />
|
<UColorModeButton class="hidden lg:inline-flex" />
|
||||||
|
|
||||||
<UButton
|
<UButton
|
||||||
to="https://github.com/nuxt/ui"
|
to="https://github.com/nuxt/ui/tree/v2"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
icon="i-simple-icons-github"
|
icon="i-simple-icons-github"
|
||||||
aria-label="GitHub"
|
aria-label="GitHub"
|
||||||
@@ -48,8 +70,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { NavItem } from '@nuxt/content'
|
import type { NavItem } from '@nuxt/content'
|
||||||
import type { HeaderLink } from '#ui-pro/types'
|
|
||||||
import pkg from '@nuxt/ui-pro/package.json'
|
import pkg from '@nuxt/ui-pro/package.json'
|
||||||
|
import type { HeaderLink } from '#ui-pro/types'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
links: HeaderLink[]
|
links: HeaderLink[]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ onMounted(() => {
|
|||||||
if (carbonads.value) {
|
if (carbonads.value) {
|
||||||
const script = document.createElement('script')
|
const script = document.createElement('script')
|
||||||
script.setAttribute('type', 'text/javascript')
|
script.setAttribute('type', 'text/javascript')
|
||||||
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CWYIVK3E&placement=uinuxtcom')
|
script.setAttribute('src', 'https://cdn.carbonads.com/carbon.js?serve=CW7IC53I&placement=ui2nuxtcom')
|
||||||
script.setAttribute('id', '_carbonads_js')
|
script.setAttribute('id', '_carbonads_js')
|
||||||
carbonads.value.appendChild(script)
|
carbonads.value.appendChild(script)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ const colorMode = useColorMode()
|
|||||||
|
|
||||||
const primaryColors = computed(() => appConfig.ui.colors.filter(color => color !== 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
const primaryColors = computed(() => appConfig.ui.colors.filter(color => color !== 'primary').map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||||
const primary = computed({
|
const primary = computed({
|
||||||
get () {
|
get() {
|
||||||
return primaryColors.value.find(option => option.value === appConfig.ui.primary)
|
return primaryColors.value.find(option => option.value === appConfig.ui.primary)
|
||||||
},
|
},
|
||||||
set (option) {
|
set(option) {
|
||||||
appConfig.ui.primary = option.value
|
appConfig.ui.primary = option.value
|
||||||
|
|
||||||
window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.primary)
|
window.localStorage.setItem('nuxt-ui-primary', appConfig.ui.primary)
|
||||||
@@ -44,10 +44,10 @@ const primary = computed({
|
|||||||
|
|
||||||
const grayColors = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
const grayColors = computed(() => ['slate', 'cool', 'zinc', 'neutral', 'stone'].map(color => ({ value: color, text: color, hex: colors[color][colorMode.value === 'dark' ? 400 : 500] })))
|
||||||
const gray = computed({
|
const gray = computed({
|
||||||
get () {
|
get() {
|
||||||
return grayColors.value.find(option => option.value === appConfig.ui.gray)
|
return grayColors.value.find(option => option.value === appConfig.ui.gray)
|
||||||
},
|
},
|
||||||
set (option) {
|
set(option) {
|
||||||
appConfig.ui.gray = option.value
|
appConfig.ui.gray = option.value
|
||||||
|
|
||||||
window.localStorage.setItem('nuxt-ui-gray', appConfig.ui.gray)
|
window.localStorage.setItem('nuxt-ui-gray', appConfig.ui.gray)
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{ color: { value: string, hex: string }, selected: { value: string} }>()
|
defineProps<{ color: { value: string, hex: string }, selected: { value: string } }>()
|
||||||
defineEmits(['select'])
|
defineEmits(['select'])
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
const colorMode = useColorMode()
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
const isDark = computed({
|
const isDark = computed({
|
||||||
get () {
|
get() {
|
||||||
return colorMode.value === 'dark'
|
return colorMode.value === 'dark'
|
||||||
},
|
},
|
||||||
set () {
|
set() {
|
||||||
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -51,11 +51,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { transformContent } from '@nuxt/content/transformers'
|
|
||||||
import { upperFirst, camelCase, kebabCase } from 'scule'
|
import { upperFirst, camelCase, kebabCase } from 'scule'
|
||||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-dupe-keys
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
slug: {
|
slug: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -90,7 +88,7 @@ const props = defineProps({
|
|||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Array as PropType<{ name: string; values: string[]; restriction: 'expected' | 'included' | 'excluded' | 'only' }[]>,
|
type: Array as PropType<{ name: string, values: string[], restriction: 'expected' | 'included' | 'excluded' | 'only' }[]>,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
backgroundClass: {
|
backgroundClass: {
|
||||||
@@ -115,7 +113,6 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-dupe-keys
|
|
||||||
const baseProps = reactive({ ...props.baseProps })
|
const baseProps = reactive({ ...props.baseProps })
|
||||||
const componentProps = reactive({ ...props.props })
|
const componentProps = reactive({ ...props.props })
|
||||||
|
|
||||||
@@ -159,13 +156,13 @@ const generateOptions = (key: string, schema: { kind: string, schema: [], type:
|
|||||||
const schemaOptions = Object.values(schema?.schema || {})
|
const schemaOptions = Object.values(schema?.schema || {})
|
||||||
|
|
||||||
if (key.toLowerCase() === 'size' && schemaOptions?.length > 0) {
|
if (key.toLowerCase() === 'size' && schemaOptions?.length > 0) {
|
||||||
const baseSizeOrder = { 'xs': 1, 'sm': 2, 'md': 3, 'lg': 4, 'xl': 5 }
|
const baseSizeOrder = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }
|
||||||
schemaOptions.sort((a: string, b: string) => {
|
schemaOptions.sort((a: string, b: string) => {
|
||||||
const aBase = a.match(/[a-zA-Z]+/)[0].toLowerCase()
|
const aBase = a.match(/[a-z]+/i)[0].toLowerCase()
|
||||||
const bBase = b.match(/[a-zA-Z]+/)[0].toLowerCase()
|
const bBase = b.match(/[a-z]+/i)[0].toLowerCase()
|
||||||
|
|
||||||
const aNum = parseInt(a.match(/\d+/)?.[0]) || 1
|
const aNum = Number.parseInt(a.match(/\d+/)?.[0]) || 1
|
||||||
const bNum = parseInt(b.match(/\d+/)?.[0]) || 1
|
const bNum = Number.parseInt(b.match(/\d+/)?.[0]) || 1
|
||||||
|
|
||||||
if (aBase === bBase) {
|
if (aBase === bBase) {
|
||||||
return aBase === 'xs' ? bNum - aNum : aNum - bNum
|
return aBase === 'xs' ? bNum - aNum : aNum - bNum
|
||||||
@@ -215,7 +212,6 @@ const propsToSelect = computed(() => Object.keys(componentProps).map((key) => {
|
|||||||
}
|
}
|
||||||
}).filter(Boolean))
|
}).filter(Boolean))
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-dupe-keys
|
|
||||||
const code = computed(() => {
|
const code = computed(() => {
|
||||||
let code = `\`\`\`html
|
let code = `\`\`\`html
|
||||||
<template>
|
<template>
|
||||||
@@ -254,7 +250,7 @@ const code = computed(() => {
|
|||||||
return code
|
return code
|
||||||
})
|
})
|
||||||
|
|
||||||
function renderObject (obj: any) {
|
function renderObject(obj: any) {
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
return `[${obj.map(renderObject).join(', ')}]`
|
return `[${obj.map(renderObject).join(', ')}]`
|
||||||
}
|
}
|
||||||
@@ -270,27 +266,28 @@ function renderObject (obj: any) {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: ast } = await useAsyncData(
|
const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`, async () => {
|
||||||
`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`,
|
let formatted = ''
|
||||||
async () => {
|
try {
|
||||||
let formatted = ''
|
// @ts-ignore
|
||||||
try {
|
formatted = await $prettier.format(code.value, {
|
||||||
formatted = await $prettier.format(code.value) || code.value
|
trailingComma: 'none',
|
||||||
} catch (error) {
|
semi: false,
|
||||||
formatted = code.value
|
singleQuote: true
|
||||||
}
|
|
||||||
|
|
||||||
return transformContent('content:_markdown.md', formatted, {
|
|
||||||
markdown: {
|
|
||||||
highlight: {
|
|
||||||
highlighter,
|
|
||||||
theme: {
|
|
||||||
light: 'material-theme-lighter',
|
|
||||||
default: 'material-theme',
|
|
||||||
dark: 'material-theme-palenight'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}, { watch: [code] })
|
} catch {
|
||||||
|
formatted = code.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseMarkdown(formatted, {
|
||||||
|
highlight: {
|
||||||
|
highlighter,
|
||||||
|
theme: {
|
||||||
|
light: 'material-theme-lighter',
|
||||||
|
default: 'material-theme',
|
||||||
|
dark: 'material-theme-palenight'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, { watch: [code] })
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0">
|
<div class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0">
|
||||||
<div
|
<div v-if="hasPreview" class="flex border border-gray-200 dark:border-gray-700 relative rounded-t-md" :class="[{ 'p-4': padding, 'rounded-b-md': !hasCode, 'border-b-0': hasCode, 'not-prose': !prose }, backgroundClass, extraClass]">
|
||||||
v-if="hasPreview"
|
|
||||||
class="flex border border-gray-200 dark:border-gray-700 relative rounded-t-md"
|
|
||||||
:class="[{ 'p-4': padding, 'rounded-b-md': !hasCode, 'border-b-0': hasCode, 'not-prose': !prose }, backgroundClass, extraClass]"
|
|
||||||
>
|
|
||||||
<template v-if="component">
|
<template v-if="component">
|
||||||
<iframe v-if="iframe" :src="`/examples/${component}`" v-bind="iframeProps" :class="backgroundClass" class="w-full" />
|
<iframe v-if="iframe" :src="`/examples/${component}`" v-bind="iframeProps" :class="backgroundClass" class="w-full" />
|
||||||
<component :is="camelName" v-else v-bind="componentProps" :class="componentClass" />
|
<component :is="camelName" v-else v-bind="componentProps" :class="componentClass" />
|
||||||
@@ -22,7 +18,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { camelCase } from 'scule'
|
import { camelCase } from 'scule'
|
||||||
import { fetchContentExampleCode } from '~/composables/useContentExamplesCode'
|
import { fetchContentExampleCode } from '~/composables/useContentExamplesCode'
|
||||||
import { transformContent } from '@nuxt/content/transformers'
|
|
||||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -86,15 +81,13 @@ const highlighter = useShikiHighlighter()
|
|||||||
const hasCode = computed(() => !props.hiddenCode && (data?.code || instance.slots.code))
|
const hasCode = computed(() => !props.hiddenCode && (data?.code || instance.slots.code))
|
||||||
const hasPreview = computed(() => !props.hiddenPreview && (props.component || instance.slots.default))
|
const hasPreview = computed(() => !props.hiddenPreview && (props.component || instance.slots.default))
|
||||||
|
|
||||||
const { data: ast } = await useAsyncData(`content-example-${camelName}-ast`, () => transformContent('content:_markdown.md', `\`\`\`vue\n${data?.code ?? ''}\n\`\`\``, {
|
const { data: ast } = await useAsyncData(`content-example-${camelName}-ast`, () => parseMarkdown(`\`\`\`vue\n${data?.code ?? ''}\n\`\`\``, {
|
||||||
markdown: {
|
highlight: {
|
||||||
highlight: {
|
highlighter,
|
||||||
highlighter,
|
theme: {
|
||||||
theme: {
|
light: 'material-theme-lighter',
|
||||||
light: 'material-theme-lighter',
|
default: 'material-theme',
|
||||||
default: 'material-theme',
|
dark: 'material-theme-palenight'
|
||||||
dark: 'material-theme-palenight'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -3,11 +3,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { transformContent } from '@nuxt/content/transformers'
|
|
||||||
import { upperFirst, camelCase } from 'scule'
|
import { upperFirst, camelCase } from 'scule'
|
||||||
import json5 from 'json5'
|
import json5 from 'json5'
|
||||||
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
|
||||||
import * as config from '#ui/ui.config'
|
import * as config from '#ui/ui.config'
|
||||||
|
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
slug: {
|
slug: {
|
||||||
@@ -18,26 +17,24 @@ const props = defineProps({
|
|||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const highlighter = useShikiHighlighter()
|
const highlighter = useShikiHighlighter()
|
||||||
// eslint-disable-next-line vue/no-dupe-keys
|
|
||||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||||
const camelName = camelCase(slug)
|
const camelName = camelCase(slug)
|
||||||
const name = `U${upperFirst(camelName)}`
|
const name = `U${upperFirst(camelName)}`
|
||||||
|
|
||||||
const preset = config[camelName]
|
const preset = config[camelName]
|
||||||
|
|
||||||
const { data: ast } = await useAsyncData(`${name}-preset`, () => transformContent('content:_markdown.md', `
|
const { data: ast } = await useAsyncData(`${name}-preset`, () => parseMarkdown(`
|
||||||
\`\`\`yml
|
\`\`\`yml
|
||||||
${json5.stringify(preset, null, 2)}
|
${json5.stringify(preset, null, 2).replace(/,([ |\t\n]+[}|\])])/g, '$1')}
|
||||||
\`\`\`\
|
\`\`\`\
|
||||||
`, {
|
`, {
|
||||||
markdown: {
|
highlight: {
|
||||||
highlight: {
|
highlighter,
|
||||||
highlighter,
|
theme: {
|
||||||
theme: {
|
light: 'material-theme-lighter',
|
||||||
light: 'material-theme-lighter',
|
default: 'material-theme',
|
||||||
default: 'material-theme',
|
dark: 'material-theme-palenight'
|
||||||
dark: 'material-theme-palenight'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function startsWithCapital (word) {
|
function startsWithCapital(word) {
|
||||||
if (word.charAt(0).startsWith('"')) {
|
if (word.charAt(0).startsWith('"')) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const links = [{
|
|||||||
<UBreadcrumb :links="links" :divider="null" :ui="{ ol: 'gap-x-3' }">
|
<UBreadcrumb :links="links" :divider="null" :ui="{ ol: 'gap-x-3' }">
|
||||||
<template #icon="{ link, index, isActive }">
|
<template #icon="{ link, index, isActive }">
|
||||||
<UAvatar
|
<UAvatar
|
||||||
:alt="(index + 1 ).toString()"
|
:alt="(index + 1).toString()"
|
||||||
:ui="{
|
:ui="{
|
||||||
background: isActive ? 'bg-primary-500 dark:bg-primary-400' : undefined,
|
background: isActive ? 'bg-primary-500 dark:bg-primary-400' : undefined,
|
||||||
placeholder: isActive ? 'text-white dark:text-gray-900' : !!link.to ? 'group-hover:text-gray-700 dark:group-hover:text-gray-200' : ''
|
placeholder: isActive ? 'text-white dark:text-gray-900' : !!link.to ? 'group-hover:text-gray-700 dark:group-hover:text-gray-200' : ''
|
||||||
|
|||||||
@@ -18,19 +18,21 @@ const actions = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const groups = computed(() =>
|
const groups = computed(() =>
|
||||||
[commandPaletteRef.value?.query ? {
|
[commandPaletteRef.value?.query
|
||||||
key: 'users',
|
? {
|
||||||
commands: users
|
key: 'users',
|
||||||
} : {
|
commands: users
|
||||||
key: 'recent',
|
}
|
||||||
label: 'Recent searches',
|
: {
|
||||||
commands: users.slice(0, 1)
|
key: 'recent',
|
||||||
}, {
|
label: 'Recent searches',
|
||||||
|
commands: users.slice(0, 1)
|
||||||
|
}, {
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
commands: actions
|
commands: actions
|
||||||
}].filter(Boolean))
|
}].filter(Boolean))
|
||||||
|
|
||||||
function onSelect (option) {
|
function onSelect(option) {
|
||||||
if (option.click) {
|
if (option.click) {
|
||||||
option.click()
|
option.click()
|
||||||
} else if (option.to) {
|
} else if (option.to) {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const ui = {
|
|||||||
:autoselect="false"
|
:autoselect="false"
|
||||||
command-attribute="title"
|
command-attribute="title"
|
||||||
:fuse="{
|
:fuse="{
|
||||||
fuseOptions: { keys: ['title', 'category'] },
|
fuseOptions: { keys: ['title', 'category'] }
|
||||||
}"
|
}"
|
||||||
placeholder="Search docs"
|
placeholder="Search docs"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const ui = {
|
|||||||
inactive: 'text-gray-400 dark:text-gray-500'
|
inactive: 'text-gray-400 dark:text-gray-500'
|
||||||
},
|
},
|
||||||
avatar: {
|
avatar: {
|
||||||
size: '2xs' as const
|
size: '2xs'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
|
|||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||||
|
|
||||||
function onContextMenu () {
|
function onContextMenu() {
|
||||||
const top = unref(y) - unref(windowY)
|
const top = unref(y) - unref(windowY)
|
||||||
const left = unref(x)
|
const left = unref(x)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
|
|||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||||
|
|
||||||
function onContextMenu () {
|
function onContextMenu() {
|
||||||
const top = unref(y) - unref(windowY)
|
const top = unref(y) - unref(windowY)
|
||||||
const left = unref(x)
|
const left = unref(x)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
|
|||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||||
|
|
||||||
function onContextMenu () {
|
function onContextMenu() {
|
||||||
const top = unref(y) - unref(windowY)
|
const top = unref(y) - unref(windowY)
|
||||||
const left = unref(x)
|
const left = unref(x)
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { y: windowY } = useWindowScroll()
|
|||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||||
|
|
||||||
function onContextMenu () {
|
function onContextMenu() {
|
||||||
const top = unref(y) - unref(windowY)
|
const top = unref(y) - unref(windowY)
|
||||||
const left = unref(x)
|
const left = unref(x)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { sub, format, isSameDay, type Duration } from 'date-fns'
|
import { sub, format, isSameDay } from 'date-fns'
|
||||||
|
import type { Duration } from 'date-fns'
|
||||||
|
|
||||||
const ranges = [
|
const ranges = [
|
||||||
{ label: 'Last 7 days', duration: { days: 7 } },
|
{ label: 'Last 7 days', duration: { days: 7 } },
|
||||||
@@ -11,11 +12,11 @@ const ranges = [
|
|||||||
]
|
]
|
||||||
const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() })
|
const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() })
|
||||||
|
|
||||||
function isRangeSelected (duration: Duration) {
|
function isRangeSelected(duration: Duration) {
|
||||||
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
|
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectRange (duration: Duration) {
|
function selectRange(duration: Duration) {
|
||||||
selected.value = { start: sub(new Date(), duration), end: new Date() }
|
selected.value = { start: sub(new Date(), duration), end: new Date() }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const validate = (state: any): FormError[] => {
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<any>) {
|
async function onSubmit(event: FormSubmitEvent<any>) {
|
||||||
// Do something with data
|
// Do something with data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ type Schema = z.infer<typeof schema>
|
|||||||
|
|
||||||
const form = ref()
|
const form = ref()
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<Schema>) {
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||||
// Do something with event.data
|
// Do something with event.data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const state = reactive({
|
|||||||
password: undefined
|
password: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<any>) {
|
async function onSubmit(event: FormSubmitEvent<any>) {
|
||||||
// Do something with event.data
|
// Do something with event.data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ const validate = (state: any): FormError[] => {
|
|||||||
return errors
|
return errors
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<any>) {
|
async function onSubmit(event: FormSubmitEvent<any>) {
|
||||||
// Do something with data
|
// Do something with data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onError (event: FormErrorEvent) {
|
async function onError(event: FormErrorEvent) {
|
||||||
const element = document.getElementById(event.errors[0].id)
|
const element = document.getElementById(event.errors[0].id)
|
||||||
element?.focus()
|
element?.focus()
|
||||||
element?.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
element?.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
||||||
|
|||||||
37
docs/components/content/examples/FormExampleSuperstruct.vue
Normal file
37
docs/components/content/examples/FormExampleSuperstruct.vue
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { object, string, nonempty } from 'superstruct'
|
||||||
|
import type { Infer } from 'superstruct'
|
||||||
|
import type { FormSubmitEvent } from '#ui/types'
|
||||||
|
|
||||||
|
const schema = object({
|
||||||
|
email: nonempty(string()),
|
||||||
|
password: nonempty(string())
|
||||||
|
})
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
email: '',
|
||||||
|
password: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
type Schema = Infer<typeof schema>
|
||||||
|
|
||||||
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||||
|
console.log(event.data)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||||
|
<UFormGroup label="Email" name="email">
|
||||||
|
<UInput v-model="state.email" />
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<UFormGroup label="Password" name="password">
|
||||||
|
<UInput v-model="state.password" type="password" />
|
||||||
|
</UFormGroup>
|
||||||
|
|
||||||
|
<UButton type="submit">
|
||||||
|
Submit
|
||||||
|
</UButton>
|
||||||
|
</UForm>
|
||||||
|
</template>
|
||||||
@@ -14,14 +14,14 @@ const state = reactive({
|
|||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<Schema>) {
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||||
// Do something with event.data
|
// Do something with event.data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||||
<UFormGroup label="Email" name="email">
|
<UFormGroup label="Email" name="email">
|
||||||
<UInput v-model="state.email" />
|
<UInput v-model="state.email" />
|
||||||
</UFormGroup>
|
</UFormGroup>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { object, string, type InferType } from 'yup'
|
import { object, string } from 'yup'
|
||||||
|
import type { InferType } from 'yup'
|
||||||
import type { FormSubmitEvent } from '#ui/types'
|
import type { FormSubmitEvent } from '#ui/types'
|
||||||
|
|
||||||
const schema = object({
|
const schema = object({
|
||||||
@@ -16,7 +17,7 @@ const state = reactive({
|
|||||||
password: undefined
|
password: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<Schema>) {
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||||
// Do something with event.data
|
// Do something with event.data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const state = reactive({
|
|||||||
password: undefined
|
password: undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
async function onSubmit (event: FormSubmitEvent<Schema>) {
|
async function onSubmit(event: FormSubmitEvent<Schema>) {
|
||||||
// Do something with data
|
// Do something with data
|
||||||
console.log(event.data)
|
console.log(event.data)
|
||||||
}
|
}
|
||||||
|
|||||||
15
docs/components/content/examples/InputExampleMaxLength.vue
Normal file
15
docs/components/content/examples/InputExampleMaxLength.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<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>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const selected = ref()
|
const selected = ref()
|
||||||
|
|
||||||
async function search (q: string) {
|
async function search(q: string) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['success'])
|
const emit = defineEmits(['success'])
|
||||||
|
|
||||||
function onSuccess () {
|
function onSuccess() {
|
||||||
emit('success')
|
emit('success')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ const toast = useToast()
|
|||||||
const modal = useModal()
|
const modal = useModal()
|
||||||
const count = ref(0)
|
const count = ref(0)
|
||||||
|
|
||||||
function openModal () {
|
function openModal() {
|
||||||
count.value += 1
|
count.value += 1
|
||||||
modal.open(ModalExampleComponent, {
|
modal.open(ModalExampleComponent, {
|
||||||
count: count.value,
|
count: count.value,
|
||||||
onSuccess () {
|
onSuccess() {
|
||||||
toast.add({
|
toast.add({
|
||||||
title: 'Success !',
|
title: 'Success !',
|
||||||
id: 'modal-success'
|
id: 'modal-success'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
function onCallback () {
|
function onCallback() {
|
||||||
alert('Notification expired!')
|
alert('Notification expired!')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
function onClick () {
|
function onClick() {
|
||||||
alert('Clicked!')
|
alert('Clicked!')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,15 +5,29 @@ const items = ref(Array(55))
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
|
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
|
||||||
<template #first="{ onClick }">
|
<template #first="{ onClick, canGoFirst }">
|
||||||
<UTooltip text="First page">
|
<UTooltip text="First page">
|
||||||
<UButton icon="i-heroicons-arrow-uturn-left" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:first-child]:rotate-180 me-2" @click="onClick" />
|
<UButton
|
||||||
|
icon="i-heroicons-arrow-uturn-left"
|
||||||
|
color="primary"
|
||||||
|
:ui="{ rounded: 'rounded-full' }"
|
||||||
|
class="rtl:[&_span:first-child]:rotate-180 me-2"
|
||||||
|
:disabled="!canGoFirst"
|
||||||
|
@click="onClick"
|
||||||
|
/>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #last="{ onClick }">
|
<template #last="{ onClick, canGoLast }">
|
||||||
<UTooltip text="Last page">
|
<UTooltip text="Last page">
|
||||||
<UButton icon="i-heroicons-arrow-uturn-right-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:last-child]:rotate-180 ms-2" @click="onClick" />
|
<UButton
|
||||||
|
icon="i-heroicons-arrow-uturn-right-20-solid"
|
||||||
|
color="primary"
|
||||||
|
:ui="{ rounded: 'rounded-full' }"
|
||||||
|
class="rtl:[&_span:last-child]:rotate-180 ms-2"
|
||||||
|
:disabled="!canGoLast"
|
||||||
|
@click="onClick"
|
||||||
|
/>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
</UPagination>
|
</UPagination>
|
||||||
|
|||||||
@@ -5,15 +5,29 @@ const items = ref(Array(55))
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
|
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
|
||||||
<template #prev="{ onClick }">
|
<template #prev="{ onClick, canGoPrev }">
|
||||||
<UTooltip text="Previous page">
|
<UTooltip text="Previous page">
|
||||||
<UButton icon="i-heroicons-arrow-small-left-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:first-child]:rotate-180 me-2" @click="onClick" />
|
<UButton
|
||||||
|
icon="i-heroicons-arrow-small-left-20-solid"
|
||||||
|
color="primary"
|
||||||
|
:ui="{ rounded: 'rounded-full' }"
|
||||||
|
class="rtl:[&_span:first-child]:rotate-180 me-2"
|
||||||
|
:disabled="!canGoPrev"
|
||||||
|
@click="onClick"
|
||||||
|
/>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #next="{ onClick }">
|
<template #next="{ onClick, canGoNext }">
|
||||||
<UTooltip text="Next page">
|
<UTooltip text="Next page">
|
||||||
<UButton icon="i-heroicons-arrow-small-right-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:last-child]:rotate-180 ms-2" @click="onClick" />
|
<UButton
|
||||||
|
icon="i-heroicons-arrow-small-right-20-solid"
|
||||||
|
color="primary"
|
||||||
|
:ui="{ rounded: 'rounded-full' }"
|
||||||
|
class="rtl:[&_span:last-child]:rotate-180 ms-2"
|
||||||
|
:disabled="!canGoNext"
|
||||||
|
@click="onClick"
|
||||||
|
/>
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
</UPagination>
|
</UPagination>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const items = ref(Array(50))
|
|||||||
:to="(page: number) => ({
|
:to="(page: number) => ({
|
||||||
query: { page },
|
query: { page },
|
||||||
// Hash is specified here to prevent the page from scrolling to the top
|
// Hash is specified here to prevent the page from scrolling to the top
|
||||||
hash: '#links',
|
hash: '#links'
|
||||||
})"
|
})"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ const temp = ref(35)
|
|||||||
|
|
||||||
const color = computed(() => {
|
const color = computed(() => {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case temp.value < 10: return 'blue'
|
case temp.value < 10: return 'blue'
|
||||||
case temp.value < 20: return 'amber'
|
case temp.value < 20: return 'amber'
|
||||||
case temp.value < 30: return 'orange'
|
case temp.value < 30: return 'orange'
|
||||||
default: return 'red'
|
default: return 'red'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const labels = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function hashCode (str) {
|
function hashCode(str) {
|
||||||
let hash = 0
|
let hash = 0
|
||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||||
@@ -45,7 +45,7 @@ function hashCode (str) {
|
|||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
function intToRGB (i) {
|
function intToRGB(i) {
|
||||||
const c = (i & 0x00FFFFFF)
|
const c = (i & 0x00FFFFFF)
|
||||||
.toString(16)
|
.toString(16)
|
||||||
.toUpperCase()
|
.toUpperCase()
|
||||||
@@ -53,7 +53,7 @@ function intToRGB (i) {
|
|||||||
return '00000'.substring(0, 6 - c.length) + c
|
return '00000'.substring(0, 6 - c.length) + c
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateColorFromString (str) {
|
function generateColorFromString(str) {
|
||||||
return intToRGB(hashCode(str))
|
return intToRGB(hashCode(str))
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const labels = computed({
|
|||||||
|
|
||||||
const showCreateOption = (query, results) => {
|
const showCreateOption = (query, results) => {
|
||||||
const lowercaseQuery = String.prototype.toLowerCase.apply(query || '')
|
const lowercaseQuery = String.prototype.toLowerCase.apply(query || '')
|
||||||
return lowercaseQuery.length >= 3 && !results.find(option => {
|
return lowercaseQuery.length >= 3 && !results.find((option) => {
|
||||||
return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery
|
return String.prototype.toLowerCase.apply(option['name'] || '') === lowercaseQuery
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const selected = ref([])
|
const selected = ref([])
|
||||||
|
|
||||||
async function search (q: string) {
|
async function search(q: string) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
const users: any[] = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
count: {
|
count: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -8,7 +7,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
close: [];
|
close: []
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { SlideoverExampleComponent } from '#components'
|
|||||||
|
|
||||||
const slideover = useSlideover()
|
const slideover = useSlideover()
|
||||||
const count = ref(0)
|
const count = ref(0)
|
||||||
function openSlideover () {
|
function openSlideover() {
|
||||||
count.value += 1
|
count.value += 1
|
||||||
slideover.open(SlideoverExampleComponent, {
|
slideover.open(SlideoverExampleComponent, {
|
||||||
count: count.value,
|
count: count.value,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// Columns
|
// Columns
|
||||||
const columns = [{
|
const columns = [{
|
||||||
|
key: 'select',
|
||||||
|
class: 'w-2'
|
||||||
|
}, {
|
||||||
key: 'id',
|
key: 'id',
|
||||||
label: '#',
|
label: '#',
|
||||||
sortable: true
|
sortable: true
|
||||||
@@ -19,13 +22,14 @@ const columns = [{
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
const selectedColumns = ref(columns)
|
const selectedColumns = ref(columns)
|
||||||
const columnsTable = computed(() => columns.filter((column) => selectedColumns.value.includes(column)))
|
const columnsTable = computed(() => columns.filter(column => selectedColumns.value.includes(column)))
|
||||||
|
const excludeSelectColumn = computed(() => columns.filter(v => v.key !== 'select'))
|
||||||
|
|
||||||
// Selected Rows
|
// Selected Rows
|
||||||
const selectedRows = ref([])
|
const selectedRows = ref([])
|
||||||
|
|
||||||
function select (row) {
|
function select(row) {
|
||||||
const index = selectedRows.value.findIndex((item) => item.id === row.id)
|
const index = selectedRows.value.findIndex(item => item.id === row.id)
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
selectedRows.value.push(row)
|
selectedRows.value.push(row)
|
||||||
} else {
|
} else {
|
||||||
@@ -92,10 +96,10 @@ const { data: todos, status } = await useLazyAsyncData<{
|
|||||||
}[]>('todos', () => ($fetch as any)(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
|
}[]>('todos', () => ($fetch as any)(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
|
||||||
query: {
|
query: {
|
||||||
q: search.value,
|
q: search.value,
|
||||||
'_page': page.value,
|
_page: page.value,
|
||||||
'_limit': pageCount.value,
|
_limit: pageCount.value,
|
||||||
'_sort': sort.value.column,
|
_sort: sort.value.column,
|
||||||
'_order': sort.value.direction
|
_order: sort.value.direction
|
||||||
}
|
}
|
||||||
}), {
|
}), {
|
||||||
default: () => [],
|
default: () => [],
|
||||||
@@ -153,7 +157,7 @@ const { data: todos, status } = await useLazyAsyncData<{
|
|||||||
</UButton>
|
</UButton>
|
||||||
</UDropdown>
|
</UDropdown>
|
||||||
|
|
||||||
<USelectMenu v-model="selectedColumns" :options="columns" multiple>
|
<USelectMenu v-model="selectedColumns" :options="excludeSelectColumn" multiple>
|
||||||
<UButton
|
<UButton
|
||||||
icon="i-heroicons-view-columns"
|
icon="i-heroicons-view-columns"
|
||||||
color="gray"
|
color="gray"
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ const people = [{
|
|||||||
role: 'Owner'
|
role: 'Owner'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
function select (row) {
|
function select(row) {
|
||||||
const index = selected.value.findIndex((item) => item.id === row.id)
|
const index = selected.value.findIndex(item => item.id === row.id)
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
selected.value.push(row)
|
selected.value.push(row)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
66
docs/components/content/examples/TableExampleContextmenu.vue
Normal file
66
docs/components/content/examples/TableExampleContextmenu.vue
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const people = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'Lindsay Walton',
|
||||||
|
title: 'Front-end Developer',
|
||||||
|
email: 'lindsay.walton@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'Courtney Henry',
|
||||||
|
title: 'Designer',
|
||||||
|
email: 'courtney.henry@example.com',
|
||||||
|
role: 'Admin'
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
name: 'Tom Cook',
|
||||||
|
title: 'Director of Product',
|
||||||
|
email: 'tom.cook@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
name: 'Whitney Francis',
|
||||||
|
title: 'Copywriter',
|
||||||
|
email: 'whitney.francis@example.com',
|
||||||
|
role: 'Admin'
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: 'Leonard Krasner',
|
||||||
|
title: 'Senior Designer',
|
||||||
|
email: 'leonard.krasner@example.com',
|
||||||
|
role: 'Owner'
|
||||||
|
}]
|
||||||
|
|
||||||
|
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||||
|
const contextMenuRow = ref()
|
||||||
|
|
||||||
|
function contextmenu(event: MouseEvent, row: any) {
|
||||||
|
// Prevent the default context menu
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
virtualElement.value.getBoundingClientRect = () => ({
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
top: event.clientY,
|
||||||
|
left: event.clientX
|
||||||
|
})
|
||||||
|
|
||||||
|
contextMenuRow.value = row
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<UTable :rows="people" @contextmenu.stop="contextmenu" />
|
||||||
|
|
||||||
|
<UContextMenu
|
||||||
|
:virtual-element="virtualElement"
|
||||||
|
:model-value="!!contextMenuRow"
|
||||||
|
@update:model-value="contextMenuRow = null"
|
||||||
|
>
|
||||||
|
<div class="p-4">
|
||||||
|
{{ contextMenuRow.id }} - {{ contextMenuRow.name }}
|
||||||
|
</div>
|
||||||
|
</UContextMenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<script setup>
|
||||||
|
const people = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'Lindsay Walton',
|
||||||
|
title: 'Front-end Developer',
|
||||||
|
email: 'lindsay.walton@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'Courtney Henry',
|
||||||
|
title: 'Designer',
|
||||||
|
email: 'courtney.henry@example.com',
|
||||||
|
role: 'Admin',
|
||||||
|
disabledExpand: true
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
name: 'Tom Cook',
|
||||||
|
title: 'Director of Product',
|
||||||
|
email: 'tom.cook@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
name: 'Whitney Francis',
|
||||||
|
title: 'Copywriter',
|
||||||
|
email: 'whitney.francis@example.com',
|
||||||
|
role: 'Admin',
|
||||||
|
disabledExpand: true
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: 'Leonard Krasner',
|
||||||
|
title: 'Senior Designer',
|
||||||
|
email: 'leonard.krasner@example.com',
|
||||||
|
role: 'Owner'
|
||||||
|
}, {
|
||||||
|
id: 6,
|
||||||
|
name: 'Floyd Miles',
|
||||||
|
title: 'Principal Designer',
|
||||||
|
email: 'floyd.miles@example.com',
|
||||||
|
role: 'Member',
|
||||||
|
disabledExpand: true
|
||||||
|
}]
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
label: 'Name',
|
||||||
|
key: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'title',
|
||||||
|
key: 'title'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Email',
|
||||||
|
key: 'email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'role',
|
||||||
|
key: 'role'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const expand = ref({
|
||||||
|
openedRows: [],
|
||||||
|
row: null
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UTable v-model:expand="expand" :rows="people" :columns="columns">
|
||||||
|
<template #expand="{ row }">
|
||||||
|
<div class="p-4">
|
||||||
|
<pre>{{ row }}</pre>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UTable>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const people = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'Lindsay Walton',
|
||||||
|
title: 'Front-end Developer',
|
||||||
|
email: 'lindsay.walton@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'Courtney Henry',
|
||||||
|
title: 'Designer',
|
||||||
|
email: 'courtney.henry@example.com',
|
||||||
|
role: 'Admin'
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
name: 'Tom Cook',
|
||||||
|
title: 'Director of Product',
|
||||||
|
email: 'tom.cook@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
name: 'Whitney Francis',
|
||||||
|
title: 'Copywriter',
|
||||||
|
email: 'whitney.francis@example.com',
|
||||||
|
role: 'Admin'
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: 'Leonard Krasner',
|
||||||
|
title: 'Senior Designer',
|
||||||
|
email: 'leonard.krasner@example.com',
|
||||||
|
role: 'Owner'
|
||||||
|
}, {
|
||||||
|
id: 6,
|
||||||
|
name: 'Floyd Miles',
|
||||||
|
title: 'Principal Designer',
|
||||||
|
email: 'floyd.miles@example.com',
|
||||||
|
role: 'Member'
|
||||||
|
}]
|
||||||
|
|
||||||
|
const selected = ref([people[1]])
|
||||||
|
|
||||||
|
const columns = [{
|
||||||
|
key: 'id',
|
||||||
|
label: 'ID'
|
||||||
|
}, {
|
||||||
|
key: 'name',
|
||||||
|
label: 'User name'
|
||||||
|
}, {
|
||||||
|
key: 'title',
|
||||||
|
label: 'Job position'
|
||||||
|
}, {
|
||||||
|
key: 'email',
|
||||||
|
label: 'Email'
|
||||||
|
}, {
|
||||||
|
key: 'role'
|
||||||
|
}, {
|
||||||
|
key: 'select',
|
||||||
|
class: 'w-2'
|
||||||
|
}]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UTable v-model="selected" :rows="people" :columns="columns" />
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<script setup lang='ts'>
|
||||||
|
const people = [{
|
||||||
|
id: 1,
|
||||||
|
name: 'Lindsay Walton',
|
||||||
|
title: 'Front-end Developer',
|
||||||
|
email: 'lindsay.walton@example.com',
|
||||||
|
role: 'Member',
|
||||||
|
hasExpand: false
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
name: 'Courtney Henry',
|
||||||
|
title: 'Designer',
|
||||||
|
email: 'courtney.henry@example.com',
|
||||||
|
role: 'Admin',
|
||||||
|
hasExpand: true
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
name: 'Tom Cook',
|
||||||
|
title: 'Director of Product',
|
||||||
|
email: 'tom.cook@example.com',
|
||||||
|
role: 'Member',
|
||||||
|
hasExpand: false
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
name: 'Whitney Francis',
|
||||||
|
title: 'Copywriter',
|
||||||
|
email: 'whitney.francis@example.com',
|
||||||
|
role: 'Admin',
|
||||||
|
hasExpand: true
|
||||||
|
}, {
|
||||||
|
id: 5,
|
||||||
|
name: 'Leonard Krasner',
|
||||||
|
title: 'Senior Designer',
|
||||||
|
email: 'leonard.krasner@example.com',
|
||||||
|
role: 'Owner',
|
||||||
|
hasExpand: false
|
||||||
|
}, {
|
||||||
|
id: 6,
|
||||||
|
name: 'Floyd Miles',
|
||||||
|
title: 'Principal Designer',
|
||||||
|
email: 'floyd.miles@example.com',
|
||||||
|
role: 'Member',
|
||||||
|
hasExpand: true
|
||||||
|
}]
|
||||||
|
|
||||||
|
const expand = ref({
|
||||||
|
openedRows: [people.find(v => v.hasExpand)],
|
||||||
|
row: {}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UTable v-model:expand="expand" :rows="people">
|
||||||
|
<template #expand="{ row }">
|
||||||
|
<div class="p-4">
|
||||||
|
<pre>{{ row }}</pre>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #expand-action="{ row, isExpanded, toggle }">
|
||||||
|
<UButton v-if="row.hasExpand" @click="toggle">
|
||||||
|
{{ isExpanded ? 'collapse' : 'expand' }}
|
||||||
|
</UButton>
|
||||||
|
</template>
|
||||||
|
</UTable>
|
||||||
|
</template>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<script setup>
|
<script setup lang='ts'>
|
||||||
const people = [{
|
const people = [{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Lindsay Walton',
|
name: 'Lindsay Walton',
|
||||||
@@ -36,10 +36,15 @@ const people = [{
|
|||||||
email: 'floyd.miles@example.com',
|
email: 'floyd.miles@example.com',
|
||||||
role: 'Member'
|
role: 'Member'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
const expand = ref({
|
||||||
|
openedRows: [people[0]],
|
||||||
|
row: {}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UTable :rows="people">
|
<UTable v-model:expand="expand" :rows="people">
|
||||||
<template #expand="{ row }">
|
<template #expand="{ row }">
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<pre>{{ row }}</pre>
|
<pre>{{ row }}</pre>
|
||||||
|
|||||||
@@ -34,53 +34,55 @@ const pending = ref(true)
|
|||||||
/* https://codepen.io/jenning/pen/YzNmzaV */
|
/* https://codepen.io/jenning/pen/YzNmzaV */
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
--color: rgb(var(--color-primary-400));
|
--color: rgb(var(--color-primary-400));
|
||||||
--size-mid: 6vmin;
|
--size-mid: 6vmin;
|
||||||
--size-dot: 1.5vmin;
|
--size-dot: 1.5vmin;
|
||||||
--size-bar: 0.4vmin;
|
--size-bar: 0.4vmin;
|
||||||
--size-square: 3vmin;
|
--size-square: 3vmin;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader::before,
|
.loader::before,
|
||||||
.loader::after {
|
.loader::after {
|
||||||
content: '';
|
content: '';
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
loader --6
|
loader --6
|
||||||
**/
|
**/
|
||||||
.loader.--6::before {
|
.loader.--6::before {
|
||||||
width: var(--size-square);
|
width: var(--size-square);
|
||||||
height: var(--size-square);
|
height: var(--size-square);
|
||||||
background-color: var(--color);
|
background-color: var(--color);
|
||||||
top: calc(50% - var(--size-square));
|
top: calc(50% - var(--size-square));
|
||||||
left: calc(50% - var(--size-square));
|
left: calc(50% - var(--size-square));
|
||||||
animation: loader-6 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite;
|
animation: loader-6 2.4s cubic-bezier(0, 0, 0.24, 1.21) infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes loader-6 {
|
@keyframes loader-6 {
|
||||||
0%, 100% {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
25% {
|
0%,
|
||||||
transform: translateX(100%);
|
100% {
|
||||||
}
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
50% {
|
25% {
|
||||||
transform: translateX(100%) translateY(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
75% {
|
50% {
|
||||||
transform: translateY(100%);
|
transform: translateX(100%) translateY(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75% {
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const people = [{
|
|||||||
role: 'Member'
|
role: 'Member'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
const items = (row) => [
|
const items = row => [
|
||||||
[{
|
[{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
icon: 'i-heroicons-pencil-square-20-solid',
|
icon: 'i-heroicons-pencil-square-20-solid',
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const items = [{
|
|||||||
content: 'Finally, this is the content for Tab3'
|
content: 'Finally, this is the content for Tab3'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
function onChange (index) {
|
function onChange(index) {
|
||||||
const item = items[index]
|
const item = items[index]
|
||||||
|
|
||||||
alert(`${item.label} was clicked!`)
|
alert(`${item.label} was clicked!`)
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ const items = [{
|
|||||||
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
|
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
|
||||||
const passwordForm = reactive({ currentPassword: '', newPassword: '' })
|
const passwordForm = reactive({ currentPassword: '', newPassword: '' })
|
||||||
|
|
||||||
function onSubmitAccount () {
|
function onSubmitAccount() {
|
||||||
console.log('Submitted form:', accountForm)
|
console.log('Submitted form:', accountForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmitPassword () {
|
function onSubmitPassword() {
|
||||||
console.log('Submitted form:', passwordForm)
|
console.log('Submitted form:', passwordForm)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const items = [{
|
|||||||
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
|
const accountForm = reactive({ name: 'Benjamin', username: 'benjamincanac' })
|
||||||
const passwordForm = reactive({ currentPassword: '', newPassword: '' })
|
const passwordForm = reactive({ currentPassword: '', newPassword: '' })
|
||||||
|
|
||||||
function onSubmit (form) {
|
function onSubmit(form) {
|
||||||
console.log('Submitted form:', form)
|
console.log('Submitted form:', form)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -17,15 +17,15 @@ const route = useRoute()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const selected = computed({
|
const selected = computed({
|
||||||
get () {
|
get() {
|
||||||
const index = items.findIndex((item) => item.label === route.query.tab)
|
const index = items.findIndex(item => item.label === route.query.tab)
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return index
|
return index
|
||||||
},
|
},
|
||||||
set (value) {
|
set(value) {
|
||||||
// Hash is specified here to prevent the page from scrolling to the top
|
// Hash is specified here to prevent the page from scrolling to the top
|
||||||
router.replace({ query: { tab: items[value].label }, hash: '#control-the-selected-index' })
|
router.replace({ query: { tab: items[value].label }, hash: '#control-the-selected-index' })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useBreakpoints, breakpointsTailwind } from '@vueuse/core'
|
|
||||||
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
||||||
@@ -26,22 +25,34 @@ const date = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
|
||||||
|
|
||||||
const smallerThanSm = breakpoints.smaller('sm')
|
|
||||||
|
|
||||||
const attrs = {
|
const attrs = {
|
||||||
transparent: true,
|
'transparent': true,
|
||||||
borderless: true,
|
'borderless': true,
|
||||||
color: 'primary',
|
'color': 'primary',
|
||||||
'is-dark': { selector: 'html', darkClass: 'dark' },
|
'is-dark': { selector: 'html', darkClass: 'dark' },
|
||||||
'first-day-of-week': 2
|
'first-day-of-week': 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDayClick(_: any, event: MouseEvent): void {
|
||||||
|
const target = event.target as HTMLElement
|
||||||
|
target.blur()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VCalendarDatePicker v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end" v-model.range="date" :columns="smallerThanSm ? 1 : 2" :rows="smallerThanSm ? 2 : 1" v-bind="{ ...attrs, ...$attrs }" />
|
<VCalendarDatePicker
|
||||||
<VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" />
|
v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end"
|
||||||
|
v-model.range="date"
|
||||||
|
:columns="2"
|
||||||
|
v-bind="{ ...attrs, ...$attrs }"
|
||||||
|
@dayclick="onDayClick"
|
||||||
|
/>
|
||||||
|
<VCalendarDatePicker
|
||||||
|
v-else
|
||||||
|
v-model="date"
|
||||||
|
v-bind="{ ...attrs, ...$attrs }"
|
||||||
|
@dayclick="onDayClick"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ULandingGrid ref="section" class="lg:grid-cols-10 lg:gap-8 overflow-hidden p-px">
|
<ULandingGrid ref="section" class="lg:grid-cols-10 lg:gap-8 overflow-hidden p-1">
|
||||||
<div :ref="(el) => (refs[1] = el)" class="col-span-8 flex items-center animate-top">
|
<div :ref="(el) => (refs[1] = el)" class="col-span-8 flex items-center animate-top">
|
||||||
<RangeExample />
|
<RangeExample />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
v-else
|
v-else
|
||||||
class="font-semibold flex flex-col gap-1 text-center"
|
class="font-semibold flex flex-col gap-1 text-center"
|
||||||
:class="[
|
:class="[
|
||||||
!block.slot && (block.inactive || block.inactive === undefined ? 'text-gray-900 dark:text-white' : 'text-white dark:text-gray-900'),
|
!block.slot && (block.inactive || block.inactive === undefined ? 'text-gray-900 dark:text-white' : 'text-white dark:text-gray-900')
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ block.name }}
|
{{ block.name }}
|
||||||
|
|||||||
@@ -36,21 +36,22 @@ const cols = ref(0)
|
|||||||
|
|
||||||
const { width, height } = useElementSize(el)
|
const { width, height } = useElementSize(el)
|
||||||
|
|
||||||
function createGrid () {
|
function createGrid() {
|
||||||
grid.value = []
|
grid.value = []
|
||||||
|
|
||||||
for (let i = 0; i <= rows.value; i++) {
|
for (let i = 0; i <= rows.value; i++) {
|
||||||
|
// eslint-disable-next-line unicorn/no-new-array
|
||||||
grid.value.push(new Array(cols.value).fill(null))
|
grid.value.push(new Array(cols.value).fill(null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewCell () {
|
function createNewCell() {
|
||||||
const x = Math.floor(Math.random() * cols.value)
|
const x = Math.floor(Math.random() * cols.value)
|
||||||
|
|
||||||
grid.value[0][x] = true
|
grid.value[0][x] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveCellsDown () {
|
function moveCellsDown() {
|
||||||
for (let row = rows.value - 1; row >= 0; row--) {
|
for (let row = rows.value - 1; row >= 0; row--) {
|
||||||
for (let col = 0; col < cols.value; col++) {
|
for (let col = 0; col < cols.value; col++) {
|
||||||
if (grid.value[row][col] !== null && grid.value[row + 1][col] === null) {
|
if (grid.value[row][col] !== null && grid.value[row + 1][col] === null) {
|
||||||
@@ -69,11 +70,11 @@ function moveCellsDown () {
|
|||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeCell (row, col) {
|
function removeCell(row, col) {
|
||||||
grid.value[row][col] = null
|
grid.value[row][col] = null
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcGrid () {
|
function calcGrid() {
|
||||||
const base = Math.ceil(width.value / 60)
|
const base = Math.ceil(width.value / 60)
|
||||||
const cell = width.value / base
|
const cell = width.value / base
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
const useComponentsMetaState = () => useState('components-meta', () => ({}))
|
const useComponentsMetaState = () => useState('components-meta', () => ({}))
|
||||||
|
|
||||||
export async function fetchComponentMeta (name: string) {
|
export async function fetchComponentMeta(name: string) {
|
||||||
const state = useComponentsMetaState()
|
const state = useComponentsMetaState()
|
||||||
|
|
||||||
if (state.value[name]?.then) {
|
if (state.value[name]?.then) {
|
||||||
await state.value[name]
|
await state.value[name]
|
||||||
return state.value[name]
|
return state.value[name]
|
||||||
}
|
}
|
||||||
if (state.value[name]) { return state.value[name] }
|
if (state.value[name]) {
|
||||||
|
return state.value[name]
|
||||||
|
}
|
||||||
|
|
||||||
// Store promise to avoid multiple calls
|
// Store promise to avoid multiple calls
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const useContentExamplesCodeState = () => useState('content-examples-code', () => ({}))
|
const useContentExamplesCodeState = () => useState('content-examples-code', () => ({}))
|
||||||
|
|
||||||
export async function fetchContentExampleCode (name?: string) {
|
export async function fetchContentExampleCode(name?: string) {
|
||||||
if (!name) return
|
if (!name) return
|
||||||
const state = useContentExamplesCodeState()
|
const state = useContentExamplesCodeState()
|
||||||
|
|
||||||
@@ -8,7 +8,9 @@ export async function fetchContentExampleCode (name?: string) {
|
|||||||
await state.value[name]
|
await state.value[name]
|
||||||
return state.value[name]
|
return state.value[name]
|
||||||
}
|
}
|
||||||
if (state.value[name]) { return state.value[name] }
|
if (state.value[name]) {
|
||||||
|
return state.value[name]
|
||||||
|
}
|
||||||
|
|
||||||
// add to nitro prerender
|
// add to nitro prerender
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ Its goal is to provide everything related to UI when building a Nuxt app. This i
|
|||||||
- Keyboard shortcuts
|
- Keyboard shortcuts
|
||||||
- Bundled icons
|
- Bundled icons
|
||||||
- Fully typed
|
- Fully typed
|
||||||
- [Figma Kit](https://www.figma.com/community/file/1288455405058138934)
|
- [Figma Kit](https://www.figma.com/community/file/1436401057300493073)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,29 @@ description: 'Learn how to install and configure Nuxt UI in your application.'
|
|||||||
|
|
||||||
### Add to a Nuxt project
|
### Add to a Nuxt project
|
||||||
|
|
||||||
1. Add `@nuxt/ui` module to your project:
|
1. Install the `@nuxt/ui` dependency in your project:
|
||||||
|
|
||||||
```bash
|
::code-group
|
||||||
npx nuxi@latest module add ui
|
|
||||||
|
```bash [pnpm]
|
||||||
|
pnpm add @nuxt/ui@2
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Add it to the `modules` section in your `nuxt.config.ts`:
|
```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`:
|
||||||
|
|
||||||
```ts [nuxt.config.ts]
|
```ts [nuxt.config.ts]
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
@@ -29,7 +45,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.
|
The Nuxt Starter template is available from the `nuxi init` command.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx nuxi@latest init -t ui
|
npx nuxi@latest init -t ui2
|
||||||
```
|
```
|
||||||
|
|
||||||
Please check [nuxt/starter](https://github.com/nuxt/starter/tree/ui) for details.
|
Please check [nuxt/starter](https://github.com/nuxt/starter/tree/ui) for details.
|
||||||
@@ -94,7 +110,7 @@ You can read more about this in the [Theming](/getting-started/theming#dark-mode
|
|||||||
|
|
||||||
## TypeScript
|
## 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/dev/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/v2/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"}
|
::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.
|
You can read more about TypeScript on the official Nuxt documentation.
|
||||||
@@ -230,7 +246,7 @@ You can also add the following to your `.vscode/settings.json` to enable Intelli
|
|||||||
| `prefix` | `u` | Define the prefix of the imported components. |
|
| `prefix` | `u` | Define the prefix of the imported components. |
|
||||||
| `global` | `false` | Expose components globally. |
|
| `global` | `false` | Expose components globally. |
|
||||||
| `safelistColors` | `['primary']` | Force safelisting of colors to need be purged. |
|
| `safelistColors` | `['primary']` | Force safelisting of colors to need be purged. |
|
||||||
| `disableGlobalStyles` | `false` | Disable [global CSS styles](https://github.com/nuxt/ui/blob/dev/src/runtime/ui.css) injected by the module. |
|
| `disableGlobalStyles` | `false` | Disable [global CSS styles](https://github.com/nuxt/ui/blob/v2/src/runtime/ui.css) injected by the module. |
|
||||||
|
|
||||||
Configure options in your `nuxt.config.ts` as such:
|
Configure options in your `nuxt.config.ts` as such:
|
||||||
|
|
||||||
@@ -243,19 +259,21 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Edge
|
## Continuous Releases
|
||||||
|
|
||||||
To use the latest updates pushed on the [`dev`](https://github.com/nuxt/ui/tree/dev) branch, you can use `@nuxt/ui-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.
|
||||||
|
|
||||||
Update your `package.json` to the following:
|
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.
|
||||||
|
|
||||||
```diff [package.json]
|
```diff [package.json]
|
||||||
{
|
{
|
||||||
"devDependencies": {
|
"dependencies": {
|
||||||
- "@nuxt/ui": "^2.11.0"
|
- "@nuxt/ui": "^2.21.0",
|
||||||
+ "@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
+ "@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@bf1c9e7",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run `pnpm install`, `yarn install` or `npm install`.
|
::note
|
||||||
|
**pkg.pr.new** will automatically comment on PRs with the installation URL, making it easy to test changes.
|
||||||
|
::
|
||||||
|
|||||||
@@ -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`.
|
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/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.
|
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.
|
||||||
|
|
||||||
```ts [tailwind.config.ts]
|
```ts [tailwind.config.ts]
|
||||||
import type { Config } from 'tailwindcss'
|
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/dev/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/v2/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.
|
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,6 +221,52 @@ 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
|
## Dark mode
|
||||||
|
|
||||||
All the components are styled with dark mode in mind.
|
All the components are styled with dark mode in mind.
|
||||||
@@ -343,6 +389,12 @@ export default defineAppConfig({
|
|||||||
loadingIcon: 'i-octicon-sync-24'
|
loadingIcon: 'i-octicon-sync-24'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
inputMenu: {
|
||||||
|
default: {
|
||||||
|
selectedIcon: 'i-octicon-check-24',
|
||||||
|
trailingIcon: 'i-octicon-chevron-down-24'
|
||||||
|
}
|
||||||
|
},
|
||||||
select: {
|
select: {
|
||||||
default: {
|
default: {
|
||||||
loadingIcon: 'i-octicon-sync-24',
|
loadingIcon: 'i-octicon-sync-24',
|
||||||
@@ -378,6 +430,9 @@ export default defineAppConfig({
|
|||||||
sortButton: {
|
sortButton: {
|
||||||
icon: 'i-octicon-arrow-switch-24'
|
icon: 'i-octicon-arrow-switch-24'
|
||||||
},
|
},
|
||||||
|
expandButton: {
|
||||||
|
icon: 'i-octicon-chevron-down-24'
|
||||||
|
},
|
||||||
loadingState: {
|
loadingState: {
|
||||||
icon: 'i-octicon-sync-24'
|
icon: 'i-octicon-sync-24'
|
||||||
},
|
},
|
||||||
@@ -411,6 +466,21 @@ export default defineAppConfig({
|
|||||||
default: {
|
default: {
|
||||||
divider: 'i-octicon-chevron-right-24'
|
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,18 +49,22 @@ defineShortcuts({
|
|||||||
Shortcuts keys are written as the literal keyboard key value. Combinations are made with `_` separator. Chained shortcuts are made with `-` separator.
|
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:
|
Modifiers are also available:
|
||||||
- `meta`: acts as `Command` for MacOS and `Control` for others
|
| Modifier | Description |
|
||||||
- `ctrl`: acts as `Control`
|
|----------|-------------|
|
||||||
- `shift`: acts as `Shift` and is only necessary for alphabetic keys
|
| `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`). |
|
||||||
|
|
||||||
Examples of keys:
|
Examples of keys:
|
||||||
- `escape`: will trigger by hitting `Esc`
|
| Shortcut Key | Action |
|
||||||
- `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
|
| `escape` | Triggers when `Esc` is pressed |
|
||||||
- `shift_e`: will trigger by hitting `Shift` and `E` at the same time on MacOS, Windows and Linux
|
| `meta_k` | `⌘ + K` on Mac, `Ctrl + K` on Windows/Linux |
|
||||||
- `?`: will trigger by hitting `?` on some keyboard layouts, or for example `Shift` and `/`, which results in `?` on US Mac keyboards
|
| `ctrl_k` | Triggers `Ctrl + K` on all OS |
|
||||||
- `g-d`: will trigger by hitting `g` then `d` with a maximum delay of 800ms by default
|
| `shift_e` | Triggers `Shift + E` on all OS |
|
||||||
- `arrowleft`: will trigger by hitting `←` (also: `arrowright`, `arrowup`, `arrowdown`)
|
| `?` | 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`) |
|
||||||
|
|
||||||
::callout{icon="i-heroicons-light-bulb"}
|
::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.
|
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'
|
to: 'https://headlessui.com/v1/vue/disclosure'
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Accordion.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display an alert element to draw attention.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Alert.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Alert.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display an image that represents a resource or a group of resources
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Avatar.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Avatar.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display a short text to represent a status or a category.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Badge.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Badge.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -141,6 +141,74 @@ Badge
|
|||||||
You can customize the whole [preset](#preset) by using the `ui` prop.
|
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
|
## Props
|
||||||
|
|
||||||
:component-props
|
:component-props
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: A list of links that indicate the current page's location within a
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Breadcrumb.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/Breadcrumb.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Create a button with icon or link capabilities.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Button.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Button.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display a card for content with a header, body and footer.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Card.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Card.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display images or content in a scrollable area.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Carousel.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Carousel.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display a checkbox field.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Checkbox.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Checkbox.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -87,7 +87,7 @@ slots:
|
|||||||
[Label]{.italic}
|
[Label]{.italic}
|
||||||
::
|
::
|
||||||
|
|
||||||
### `help` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
### `help`
|
||||||
|
|
||||||
Like the `#label` slot, use the `#help` slot to override the content of the help text.
|
Like the `#label` slot, use the `#help` slot to override the content of the help text.
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display a chip indicator on any component.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Chip.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Chip.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ links:
|
|||||||
to: 'https://headlessui.com/v1/vue/combobox'
|
to: 'https://headlessui.com/v1/vue/combobox'
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/CommandPalette.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -274,7 +274,7 @@ hiddenCode: true
|
|||||||
---
|
---
|
||||||
::
|
::
|
||||||
|
|
||||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/CommandPaletteExampleThemeAlgolia.vue#L23" target="_blank"}
|
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/CommandPaletteExampleThemeAlgolia.vue#L23" target="_blank"}
|
||||||
Take a look at the component!
|
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/dev/docs/components/content/examples/CommandPaletteExampleThemeRaycast.vue#L30" target="_blank"}
|
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/CommandPaletteExampleThemeRaycast.vue#L30" target="_blank"}
|
||||||
Take a look at the component!
|
Take a look at the component!
|
||||||
::
|
::
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: A container lets you center and constrain the width of your content
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Container.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Container.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: Display a menu that appears on right click.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/ContextMenu.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/overlays/ContextMenu.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -38,9 +38,14 @@ The following example is styled based on the `primary` and `gray` colors and sup
|
|||||||
```vue [components/DatePicker.vue]
|
```vue [components/DatePicker.vue]
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
import { DatePicker as VCalendarDatePicker } from 'v-calendar'
|
||||||
|
// @ts-ignore
|
||||||
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
|
||||||
import 'v-calendar/dist/style.css'
|
import 'v-calendar/dist/style.css'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false
|
||||||
|
})
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [Date, Object] as PropType<DatePickerDate | DatePickerRangeObject | null>,
|
type: [Date, Object] as PropType<DatePickerDate | DatePickerRangeObject | null>,
|
||||||
@@ -59,17 +64,33 @@ const date = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const attrs = {
|
const attrs = {
|
||||||
transparent: true,
|
'transparent': true,
|
||||||
borderless: true,
|
'borderless': true,
|
||||||
color: 'primary',
|
'color': 'primary',
|
||||||
'is-dark': { selector: 'html', darkClass: 'dark' },
|
'is-dark': { selector: 'html', darkClass: 'dark' },
|
||||||
'first-day-of-week': 2,
|
'first-day-of-week': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDayClick(_: any, event: MouseEvent): void {
|
||||||
|
const target = event.target as HTMLElement
|
||||||
|
target.blur()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VCalendarDatePicker v-if="date && (typeof date === 'object')" v-model.range="date" :columns="2" v-bind="{ ...attrs, ...$attrs }" />
|
<VCalendarDatePicker
|
||||||
<VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" />
|
v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end"
|
||||||
|
v-model.range="date"
|
||||||
|
:columns="2"
|
||||||
|
v-bind="{ ...attrs, ...$attrs }"
|
||||||
|
@dayclick="onDayClick"
|
||||||
|
/>
|
||||||
|
<VCalendarDatePicker
|
||||||
|
v-else
|
||||||
|
v-model="date"
|
||||||
|
v-bind="{ ...attrs, ...$attrs }"
|
||||||
|
@dayclick="onDayClick"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: Display a separator between content.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/layout/Divider.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/layout/Divider.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ links:
|
|||||||
to: https://headlessui.com/v1/vue/menu
|
to: https://headlessui.com/v1/vue/menu
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/elements/Dropdown.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: Display a label and additional informations around a form element.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/FormGroup.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/FormGroup.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ description: Collect and validate form data.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Form.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/Form.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Use the Form component to validate form data using schema libraries such as [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 your own validation logic.
|
Use the Form component to validate form data using schema libraries such as [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), [Superstruct](https://github.com/ianstormtaylor/superstruct), or your own validation logic.
|
||||||
|
|
||||||
It works with the [FormGroup](/components/form-group) component to display error messages around form elements automatically.
|
It works with the [FormGroup](/components/form-group) component to display error messages around form elements automatically.
|
||||||
|
|
||||||
The form component requires two props:
|
The form component requires two props:
|
||||||
- `state` - a reactive object holding the form's state.
|
- `state` - a reactive object holding the form's state.
|
||||||
- `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) or [Valibot](https://github.com/fabian-hiller/valibot).
|
- `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).
|
||||||
|
|
||||||
::callout{icon="i-heroicons-light-bulb"}
|
::callout{icon="i-heroicons-light-bulb"}
|
||||||
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
Note that **no validation library is included** by default, so ensure you **install the one you need**.
|
||||||
@@ -52,6 +52,13 @@ Note that **no validation library is included** by default, so ensure you **inst
|
|||||||
class: 'w-60'
|
class: 'w-60'
|
||||||
---
|
---
|
||||||
::
|
::
|
||||||
|
::component-example{label="Superstruct"}
|
||||||
|
---
|
||||||
|
component: 'form-example-superstruct'
|
||||||
|
componentProps:
|
||||||
|
class: 'w-60'
|
||||||
|
---
|
||||||
|
::
|
||||||
::
|
::
|
||||||
|
|
||||||
## Custom validation
|
## Custom validation
|
||||||
@@ -183,7 +190,7 @@ hiddenCode: true
|
|||||||
---
|
---
|
||||||
::
|
::
|
||||||
|
|
||||||
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/dev/docs/components/content/examples/FormExampleElements.vue" target="_blank"}
|
::callout{icon="i-simple-icons-github" to="https://github.com/nuxt/ui/blob/v2/docs/components/content/examples/FormExampleElements.vue" target="_blank"}
|
||||||
Take a look at the component!
|
Take a look at the component!
|
||||||
::
|
::
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ description: Display a list of horizontal links.
|
|||||||
links:
|
links:
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/HorizontalNavigation.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/navigation/HorizontalNavigation.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ links:
|
|||||||
to: 'https://headlessui.com/v1/vue/combobox'
|
to: 'https://headlessui.com/v1/vue/combobox'
|
||||||
- label: GitHub
|
- label: GitHub
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
|
to: https://github.com/nuxt/ui/blob/v2/src/runtime/components/forms/InputMenu.vue
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -32,7 +32,7 @@ This component does not support multiple values. Use the [SelectMenu](/component
|
|||||||
|
|
||||||
### Objects
|
### Objects
|
||||||
|
|
||||||
You can pass an array of objects to `options` and either compare on the whole object or use the `by` prop to compare on a specific key. You can configure which field will be used to display the label through the `option-attribute` prop that defaults to `label`.
|
You can pass an array of objects to `options` and either compare on the whole object or use the `by` prop to compare on a specific key. You can configure which field will be used to display the label through the `option-attribute` prop that defaults to `label`. Additionally, you can use dot notation (e.g., `user.name`) to access nested object properties.
|
||||||
|
|
||||||
::component-example
|
::component-example
|
||||||
---
|
---
|
||||||
@@ -174,6 +174,8 @@ componentProps:
|
|||||||
|
|
||||||
Use the `#option-empty` slot to customize the content displayed when the `searchable` prop is `true` and there is no options. You will have access to the `query` property in the slot scope.
|
Use the `#option-empty` slot to customize the content displayed when the `searchable` prop is `true` and there is no options. You will have access to the `query` property in the slot scope.
|
||||||
|
|
||||||
|
You can also configure this globally through the `ui.inputMenu.default.optionEmpty.label` config. The token `{query}` will be replaced by `query` property. Defaults to `No results for "{query}".`.
|
||||||
|
|
||||||
::component-example
|
::component-example
|
||||||
---
|
---
|
||||||
component: 'input-menu-example-option-empty-slot'
|
component: 'input-menu-example-option-empty-slot'
|
||||||
@@ -186,6 +188,8 @@ componentProps:
|
|||||||
|
|
||||||
Use the `#empty` slot to customize the content displayed when there is no options. Defaults to `No options.`.
|
Use the `#empty` slot to customize the content displayed when there is no options. Defaults to `No options.`.
|
||||||
|
|
||||||
|
You can also configure this globally through the `ui.inputMenu.default.empty.label` config. Defaults to `No options.`.
|
||||||
|
|
||||||
::component-example
|
::component-example
|
||||||
---
|
---
|
||||||
component: 'input-menu-example-empty-slot'
|
component: 'input-menu-example-empty-slot'
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user