mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 12:39:35 +01:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
17
.github/workflows/ci-dev.yml
vendored
17
.github/workflows/ci-dev.yml
vendored
@@ -37,16 +37,6 @@ jobs:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Filter changes
|
||||
uses: dorny/paths-filter@v3
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- 'src/**'
|
||||
- 'package.json'
|
||||
- 'pnpm-lock.yaml'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
@@ -65,8 +55,5 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm run test run
|
||||
|
||||
- name: Release Edge
|
||||
if: github.event_name == 'push' && steps.changes.outputs.src == 'true'
|
||||
run: ./scripts/release-edge.sh
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
|
||||
- name: Publish
|
||||
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
|
||||
|
||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## [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
|
||||
|
||||
10
README.md
10
README.md
@@ -30,16 +30,6 @@ Read more on [ui.nuxt.com](https://ui.nuxt.com)
|
||||
npx nuxi@latest module add ui
|
||||
```
|
||||
|
||||
If you want latest updates, please use `@nuxt/ui-edge` in your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit https://ui.nuxt.com to explore the documentation.
|
||||
|
||||
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>
|
||||
@@ -243,19 +243,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]
|
||||
{
|
||||
"devDependencies": {
|
||||
- "@nuxt/ui": "^2.11.0"
|
||||
+ "@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||
"dependencies": {
|
||||
- "@nuxt/ui": "^2.21.0",
|
||||
+ "@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.
|
||||
::
|
||||
|
||||
@@ -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
|
||||
|
||||
All the components are styled with dark mode in mind.
|
||||
@@ -343,6 +389,12 @@ export default defineAppConfig({
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
},
|
||||
inputMenu: {
|
||||
default: {
|
||||
selectedIcon: 'i-octicon-check-24',
|
||||
trailingIcon: 'i-octicon-chevron-down-24'
|
||||
}
|
||||
},
|
||||
select: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24',
|
||||
@@ -378,6 +430,9 @@ export default defineAppConfig({
|
||||
sortButton: {
|
||||
icon: 'i-octicon-arrow-switch-24'
|
||||
},
|
||||
expandButton: {
|
||||
icon: 'i-octicon-chevron-down-24'
|
||||
},
|
||||
loadingState: {
|
||||
icon: 'i-octicon-sync-24'
|
||||
},
|
||||
@@ -411,6 +466,21 @@ export default defineAppConfig({
|
||||
default: {
|
||||
divider: 'i-octicon-chevron-right-24'
|
||||
}
|
||||
},
|
||||
carousel: {
|
||||
default: {
|
||||
prevButton: {
|
||||
icon: 'i-octicon-chevron-left-24'
|
||||
},
|
||||
nextButton: {
|
||||
icon: 'i-octicon-chevron-right-24'
|
||||
}
|
||||
}
|
||||
},
|
||||
toggle: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -49,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.
|
||||
|
||||
Modifiers are also available:
|
||||
- `meta`: acts as `Command` for MacOS and `Control` for others
|
||||
- `ctrl`: acts as `Control`
|
||||
- `shift`: acts as `Shift` and is only necessary for alphabetic keys
|
||||
| Modifier | Description |
|
||||
|----------|-------------|
|
||||
| `meta` | Acts as `Command (⌘)` on macOS and `Control (Ctrl)` on Windows/Linux. |
|
||||
| `ctrl` | Represents the `Control (Ctrl)` key across all operating systems. |
|
||||
| `shift` | Represents the `Shift` key, only needed for alphabetic keys (e.g., `shift_e`). |
|
||||
|
||||
Examples of keys:
|
||||
- `escape`: will trigger by hitting `Esc`
|
||||
- `meta_k`: will trigger by hitting `⌘` and `K` at the same time on MacOS, and `Ctrl` and `K` on Windows and Linux
|
||||
- `ctrl_k`: will trigger by hitting `Ctrl` and `K` at the same time on MacOS, Windows and Linux
|
||||
- `shift_e`: will trigger by hitting `Shift` and `E` at the same time on MacOS, Windows and Linux
|
||||
- `?`: will trigger by hitting `?` on some keyboard layouts, or for example `Shift` and `/`, which results in `?` on US Mac keyboards
|
||||
- `g-d`: will trigger by hitting `g` then `d` with a maximum delay of 800ms by default
|
||||
- `arrowleft`: will trigger by hitting `←` (also: `arrowright`, `arrowup`, `arrowdown`)
|
||||
| Shortcut Key | Action |
|
||||
|---------------|--------|
|
||||
| `escape` | Triggers when `Esc` is pressed |
|
||||
| `meta_k` | `⌘ + K` on Mac, `Ctrl + K` on Windows/Linux |
|
||||
| `ctrl_k` | Triggers `Ctrl + K` on all OS |
|
||||
| `shift_e` | Triggers `Shift + E` on all OS |
|
||||
| `?` | Triggers `?` (Shift + `/` on US Mac keyboards) |
|
||||
| `g-d` | Triggers when `g` then `d` are pressed within 800ms |
|
||||
| `arrowleft` | Triggers when `←` is pressed (also: `arrowright`, `arrowup`, `arrowdown`) |
|
||||
|
||||
::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.
|
||||
|
||||
@@ -173,6 +173,13 @@ baseProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Limit
|
||||
|
||||
Use the `maxlength` prop to limit the length of the Input.
|
||||
|
||||
:component-example{component="input-example-max-length"}
|
||||
|
||||
|
||||
## Slots
|
||||
|
||||
### `leading`
|
||||
|
||||
@@ -3,28 +3,29 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@iconify-json/heroicons": "^1.2.1",
|
||||
"@iconify-json/simple-icons": "^1.2.14",
|
||||
"@iconify-json/vscode-icons": "^1.2.3",
|
||||
"@iconify-json/heroicons": "^1.2.2",
|
||||
"@iconify-json/lucide": "^1.2.28",
|
||||
"@iconify-json/simple-icons": "^1.2.27",
|
||||
"@iconify-json/vscode-icons": "^1.2.16",
|
||||
"@nuxt/content": "^2.13.4",
|
||||
"@nuxt/fonts": "^0.10.3",
|
||||
"@nuxt/image": "^1.8.1",
|
||||
"@nuxt/image": "^1.9.0",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "^1.5.0",
|
||||
"@nuxt/ui-pro": "^1.7.0",
|
||||
"@nuxtjs/plausible": "^1.2.0",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"@vueuse/nuxt": "^12.0.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
"@vueuse/nuxt": "^12.8.2",
|
||||
"date-fns": "^4.1.0",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.14.1592",
|
||||
"nuxt": "^3.16.0",
|
||||
"nuxt-cloudflare-analytics": "^1.0.8",
|
||||
"nuxt-component-meta": "^0.9.0",
|
||||
"nuxt-og-image": "^3.1.1",
|
||||
"prettier": "^3.4.2",
|
||||
"nuxt-component-meta": "^0.10.0",
|
||||
"nuxt-og-image": "^4.2.0",
|
||||
"prettier": "^3.5.3",
|
||||
"ufo": "^1.5.4",
|
||||
"v-calendar": "^3.1.2",
|
||||
"valibot": "^0.42.1",
|
||||
"yup": "^1.5.0",
|
||||
"zod": "^3.23.8"
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^3.24.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,6 +423,7 @@ const { data: module } = await useFetch<{
|
||||
username: string
|
||||
}[]
|
||||
}>('https://api.nuxt.com/modules/ui', {
|
||||
key: 'stats',
|
||||
transform: ({ stats, contributors }) => ({ stats, contributors })
|
||||
})
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ if (!page.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||
}
|
||||
|
||||
const { data: releases } = await useFetch('/api/releases.json')
|
||||
const { data: pulls } = await useLazyFetch('/api/pulls.json', { default: () => [] })
|
||||
const { data: releases } = await useFetch('/api/releases.json', { key: 'releases-list' })
|
||||
const { data: pulls } = await useLazyFetch('/api/pulls.json', { default: () => [], key: 'pulls-list' })
|
||||
|
||||
const dates = computed(() => {
|
||||
const first = releases.value[releases.value.length - 1]
|
||||
|
||||
57
package.json
57
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
|
||||
"version": "2.20.0",
|
||||
"packageManager": "pnpm@9.15.0",
|
||||
"version": "2.21.1",
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"repository": "nuxt/ui",
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"type": "module",
|
||||
@@ -32,57 +32,58 @@
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/tailwindcss": "^0.2.1",
|
||||
"@headlessui/tailwindcss": "^0.2.2",
|
||||
"@headlessui/vue": "^1.7.23",
|
||||
"@iconify-json/heroicons": "^1.2.1",
|
||||
"@nuxt/icon": "^1.9.1",
|
||||
"@nuxt/kit": "^3.14.1592",
|
||||
"@iconify-json/heroicons": "^1.2.2",
|
||||
"@nuxt/icon": "^1.10.3",
|
||||
"@nuxt/kit": "^3.16.0",
|
||||
"@nuxtjs/color-mode": "^3.5.2",
|
||||
"@nuxtjs/tailwindcss": "^6.12.2",
|
||||
"@nuxtjs/tailwindcss": "^6.13.1",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@vueuse/core": "^12.0.0",
|
||||
"@vueuse/integrations": "^12.0.0",
|
||||
"@vueuse/math": "^12.0.0",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"@vueuse/integrations": "^12.8.2",
|
||||
"@vueuse/math": "^12.8.2",
|
||||
"defu": "^6.1.4",
|
||||
"fuse.js": "^7.0.0",
|
||||
"ohash": "^1.1.4",
|
||||
"pathe": "^1.1.2",
|
||||
"fuse.js": "^7.1.0",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
"tailwindcss": "^3.4.16"
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss": "^3.4.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint-config": "^0.7.2",
|
||||
"@nuxt/eslint-config": "^1.1.0",
|
||||
"@nuxt/module-builder": "^0.8.4",
|
||||
"@nuxt/test-utils": "^3.15.1",
|
||||
"@release-it/conventional-changelog": "^9.0.3",
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@nuxt/test-utils": "^3.17.1",
|
||||
"@release-it/conventional-changelog": "^10.0.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"eslint": "^9.16.0",
|
||||
"happy-dom": "^14.12.3",
|
||||
"eslint": "^9.22.0",
|
||||
"happy-dom": "^17.1.8",
|
||||
"joi": "^17.13.3",
|
||||
"nuxt": "^3.14.1592",
|
||||
"release-it": "^17.10.0",
|
||||
"nuxt": "^3.16.0",
|
||||
"release-it": "^18.1.2",
|
||||
"superstruct": "^2.0.2",
|
||||
"typescript": "^5.6.3",
|
||||
"unbuild": "^2.0.0",
|
||||
"valibot": "^0.42.1",
|
||||
"valibot30": "npm:valibot@0.30.0",
|
||||
"valibot31": "npm:valibot@0.31.0",
|
||||
"vitest": "^2.1.8",
|
||||
"vitest": "^3.0.8",
|
||||
"vitest-environment-nuxt": "^1.0.1",
|
||||
"vue-tsc": "^2.1.10",
|
||||
"yup": "^1.5.0",
|
||||
"zod": "^3.23.8"
|
||||
"yup": "^1.6.1",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"@nuxt/ui": "workspace:*",
|
||||
"@nuxt/content": "2.13.2",
|
||||
"@nuxtjs/mdc": "0.9.0",
|
||||
"chokidar": "3.6.0",
|
||||
"vue-tsc": "2.1.10",
|
||||
"typescript": "5.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "latest",
|
||||
"nuxt": "^3.14.1592"
|
||||
"nuxt": "^3.16.0"
|
||||
}
|
||||
}
|
||||
|
||||
7518
pnpm-lock.yaml
generated
7518
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@
|
||||
"enabled": true
|
||||
},
|
||||
"ignoreDeps": [
|
||||
"happy-dom",
|
||||
"valibot30",
|
||||
"valibot31"
|
||||
],
|
||||
@@ -24,5 +23,6 @@
|
||||
}, {
|
||||
"matchDepTypes": ["resolutions"],
|
||||
"enabled": false
|
||||
}]
|
||||
}],
|
||||
"postUpdateOptions": ["pnpmDedupe"]
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import { execSync } from 'node:child_process'
|
||||
|
||||
async function loadPackage(dir: string) {
|
||||
const pkgPath = resolve(dir, 'package.json')
|
||||
|
||||
const data = JSON.parse(await fsp.readFile(pkgPath, 'utf-8').catch(() => '{}'))
|
||||
|
||||
const save = () => fsp.writeFile(pkgPath, JSON.stringify(data, null, 2) + '\n')
|
||||
|
||||
return {
|
||||
dir,
|
||||
data,
|
||||
save
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const pkg = await loadPackage(process.cwd())
|
||||
|
||||
const commit = execSync('git rev-parse --short HEAD').toString('utf-8').trim()
|
||||
|
||||
const date = Math.round(Date.now() / (1000 * 60))
|
||||
|
||||
pkg.data.name = `${pkg.data.name}-edge`
|
||||
|
||||
pkg.data.version = `${pkg.data.version}-${date}.${commit}`
|
||||
|
||||
pkg.save()
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Restore all git changes
|
||||
git restore -s@ -SW -- .
|
||||
|
||||
# Bump versions to edge
|
||||
pnpm jiti ./scripts/bump-edge
|
||||
|
||||
# Update token
|
||||
if [[ ! -z ${NODE_AUTH_TOKEN} ]] ; then
|
||||
echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc
|
||||
echo "registry=https://registry.npmjs.org/" >> ~/.npmrc
|
||||
echo "always-auth=true" >> ~/.npmrc
|
||||
npm whoami
|
||||
fi
|
||||
|
||||
# Release package
|
||||
echo "Publishing @nuxt/ui"
|
||||
npm publish -q --access public
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { defineNuxtModule, installModule, addComponentsDir, addImportsDir, createResolver, addPlugin } from '@nuxt/kit'
|
||||
import type { ConfigExtension, DefaultClassGroupIds, DefaultThemeGroupIds } from 'tailwind-merge'
|
||||
import { name, version } from '../package.json'
|
||||
import createTemplates from './templates'
|
||||
import type * as config from './runtime/ui.config'
|
||||
@@ -20,6 +21,7 @@ type UI = {
|
||||
gray?: string
|
||||
colors?: string[]
|
||||
strategy?: Strategy
|
||||
tailwindMerge?: ConfigExtension<DefaultClassGroupIds, DefaultThemeGroupIds>
|
||||
[key: string]: any
|
||||
} & DeepPartial<typeof config, string | number | boolean>
|
||||
|
||||
@@ -41,6 +43,11 @@ export interface ModuleOptions {
|
||||
*/
|
||||
global?: boolean
|
||||
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
colorMode?: boolean
|
||||
|
||||
safelistColors?: string[]
|
||||
/**
|
||||
* Disables the global css styles added by the module.
|
||||
@@ -59,6 +66,7 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
},
|
||||
defaults: {
|
||||
prefix: 'U',
|
||||
colorMode: true,
|
||||
safelistColors: ['primary'],
|
||||
disableGlobalStyles: false
|
||||
},
|
||||
@@ -81,7 +89,9 @@ export default defineNuxtModule<ModuleOptions>({
|
||||
// Modules
|
||||
|
||||
await installModule('@nuxt/icon')
|
||||
await installModule('@nuxtjs/color-mode', { classSuffix: '' })
|
||||
if (options.colorMode) {
|
||||
await installModule('@nuxtjs/color-mode', { classSuffix: '' })
|
||||
}
|
||||
await installTailwind(options, nuxt, resolve)
|
||||
|
||||
// Plugins
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
:class="[ui.th.base, ui.th.padding, ui.th.color, ui.th.font, ui.th.size, column.key === 'select' && ui.checkbox.padding, column.class]"
|
||||
:aria-sort="getAriaSort(column)"
|
||||
>
|
||||
<slot v-if="!singleSelect && modelValue && (column.key === 'select' || shouldRenderColumnInFirstPlace(index, 'select'))" name="select-header" :indeterminate="indeterminate" :checked="isAllRowChecked" :change="onChange">
|
||||
<slot v-if="!singleSelect && modelValue && column.key === 'select'" name="select-header" :indeterminate="indeterminate" :checked="isAllRowChecked" :change="onChange">
|
||||
<UCheckbox
|
||||
:model-value="isAllRowChecked"
|
||||
:indeterminate="indeterminate"
|
||||
@@ -93,19 +93,17 @@
|
||||
/>
|
||||
</td>
|
||||
<td v-for="(column, subIndex) in columns" :key="subIndex" :class="[ui.td.base, ui.td.padding, ui.td.color, ui.td.font, ui.td.size, column?.rowClass, row[column.key]?.class, column.key === 'select' && ui.checkbox.padding]">
|
||||
<slot v-if="modelValue && (column.key === 'select' || shouldRenderColumnInFirstPlace(subIndex, 'select')) " name="select-data" :checked="isSelected(row)" :change="(ev: boolean) => onChangeCheckbox(ev, row)">
|
||||
<slot v-if="modelValue && column.key === 'select' " name="select-data" :checked="isSelected(row)" :change="(ev: boolean) => onChangeCheckbox(ev, row)">
|
||||
<UCheckbox
|
||||
:model-value="isSelected(row)"
|
||||
v-bind="ui.default.checkbox"
|
||||
aria-label="Select row"
|
||||
@change="onChangeCheckbox($event, row)"
|
||||
@click.capture.stop="() => onSelect(row)"
|
||||
/>
|
||||
</slot>
|
||||
|
||||
<slot
|
||||
v-else
|
||||
:key="retriggerSlot"
|
||||
:name="`${column.key}-data`"
|
||||
:column="column"
|
||||
:row="row"
|
||||
@@ -133,18 +131,18 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref, toRaw, toRef, watch } from 'vue'
|
||||
import { computed, defineComponent, toRaw, toRef } from 'vue'
|
||||
import type { PropType, AriaAttributes } from 'vue'
|
||||
import { upperFirst } from 'scule'
|
||||
import { defu } from 'defu'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { isEqual } from 'ohash'
|
||||
import { isEqual } from 'ohash/utils'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import UProgress from '../elements/Progress.vue'
|
||||
import UCheckbox from '../forms/Checkbox.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, get } from '../../utils'
|
||||
import { get, mergeConfig } from '../../utils'
|
||||
import type { TableRow, TableColumn, Strategy, Button, ProgressColor, ProgressAnimation, DeepPartial, Expanded } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
@@ -274,7 +272,30 @@ export default defineComponent({
|
||||
setup(props, { emit, attrs: $attrs }) {
|
||||
const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))
|
||||
|
||||
const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map(key => ({ key, label: upperFirst(key), sortable: false, class: undefined, sort: defaultSort }) as TableColumn))
|
||||
const columns = computed(() => {
|
||||
const defaultColumns = props.columns ?? (
|
||||
Object.keys(props.rows[0]).map(key => ({
|
||||
key,
|
||||
label: upperFirst(key),
|
||||
sortable: false,
|
||||
class: undefined,
|
||||
sort: defaultSort
|
||||
}))
|
||||
) as TableColumn[]
|
||||
|
||||
const hasColumnSelect = defaultColumns.find(v => v.key === 'select')
|
||||
|
||||
if (hasColumnSelect || !props.modelValue) {
|
||||
return defaultColumns
|
||||
}
|
||||
|
||||
return [{
|
||||
key: 'select',
|
||||
sortable: false,
|
||||
class: undefined,
|
||||
sort: defaultSort
|
||||
}, ...defaultColumns]
|
||||
})
|
||||
|
||||
const sort = useVModel(props, 'sort', emit, { passive: true, defaultValue: defu({}, props.sort, { column: null, direction: 'asc' }) })
|
||||
const expand = useVModel(props, 'expand', emit, {
|
||||
@@ -285,8 +306,6 @@ export default defineComponent({
|
||||
})
|
||||
})
|
||||
|
||||
const retriggerSlot = ref(null)
|
||||
|
||||
const savedSort = { column: sort.value.column, direction: null }
|
||||
|
||||
const rows = computed(() => {
|
||||
@@ -422,8 +441,7 @@ export default defineComponent({
|
||||
if (checked) {
|
||||
selected.value = props.singleSelect ? [row] : [...selected.value, row]
|
||||
} else {
|
||||
const index = selected.value.findIndex(item => compare(item, row))
|
||||
selected.value.splice(index, 1)
|
||||
selected.value = selected.value.filter(value => !compare(toRaw(value), toRaw(row)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,13 +453,6 @@ export default defineComponent({
|
||||
return expand.value?.openedRows ? expand.value.openedRows.some(openedRow => compare(openedRow, row)) : false
|
||||
}
|
||||
|
||||
function shouldRenderColumnInFirstPlace(index: number, key: string) {
|
||||
if (!props.columns) {
|
||||
return index === 0
|
||||
}
|
||||
return index === 0 && !props.columns.find(col => col.key === key)
|
||||
}
|
||||
|
||||
function toggleOpened(row: TableRow) {
|
||||
expand.value = {
|
||||
openedRows: isExpanded(row) ? expand.value.openedRows.filter(v => !compare(v, row)) : props.multipleExpand ? [...expand.value.openedRows, row] : [row],
|
||||
@@ -469,12 +480,6 @@ export default defineComponent({
|
||||
return undefined
|
||||
}
|
||||
|
||||
watch(rows, () => {
|
||||
retriggerSlot.value = new Date()
|
||||
}, {
|
||||
deep: true
|
||||
})
|
||||
|
||||
return {
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
@@ -501,9 +506,7 @@ export default defineComponent({
|
||||
getRowData,
|
||||
toggleOpened,
|
||||
getAriaSort,
|
||||
isExpanded,
|
||||
shouldRenderColumnInFirstPlace,
|
||||
retriggerSlot
|
||||
isExpanded
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{{ title }}
|
||||
</slot>
|
||||
</p>
|
||||
<div v-if="description || $slots.description" :class="twMerge(ui.description, !title && !$slots.title && 'mt-0 leading-5')">
|
||||
<div v-if="description || $slots.description" :class="twMerge(ui.description, !title && !$slots.title && ui.descriptionOnly)">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
@@ -42,13 +42,13 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import type { Avatar, Button, AlertColor, AlertVariant, AlertAction, Strategy, DeepPartial } from '../../types/index'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { alert } from '#ui/ui.config'
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, toRef, watch } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { AvatarSize, AvatarChipColor, AvatarChipPosition, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import { getSlotsChildren, mergeConfig, twMerge } from '../../utils'
|
||||
import type { AvatarSize, DeepPartial, Strategy } from '../../types/index'
|
||||
import UAvatar from './Avatar.vue'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { BadgeColor, BadgeSize, BadgeVariant, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, toRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import ULink from '../elements/Link.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, nuxtLinkProps, getNuxtLinkProps } from '../../utils'
|
||||
import { getNuxtLinkProps, mergeConfig, nuxtLinkProps, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { ButtonColor, ButtonSize, ButtonVariant, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { h, computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import { getSlotsChildren, mergeConfig, twMerge } from '../../utils'
|
||||
import { useProvideButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { ButtonSize, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -58,9 +58,8 @@
|
||||
<script lang="ts">
|
||||
import { ref, toRef, computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { useScroll, useResizeObserver, useElementSize } from '@vueuse/core'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import type { Strategy, Button, DeepPartial } from '../../types/index'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
|
||||
@@ -60,13 +60,13 @@ import { defineComponent, ref, computed, watch, toRef, onMounted, resolveCompone
|
||||
import type { PropType } from 'vue'
|
||||
import { Menu as HMenu, MenuButton as HMenuButton, MenuItems as HMenuItems, MenuItem as HMenuItem, provideUseId } from '@headlessui/vue'
|
||||
import { defu } from 'defu'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UKbd from '../elements/Kbd.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { mergeConfig, getNuxtLinkProps } from '../../utils'
|
||||
import { getNuxtLinkProps, mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, DropdownItem, PopperOptions, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<script lang="ts">
|
||||
import { toRef, defineComponent, computed } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, KbdSize, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { isEqual, diff } from 'ohash'
|
||||
import { isEqual, diff } from 'ohash/utils'
|
||||
import { type PropType, defineComponent } from 'vue'
|
||||
import { nuxtLinkProps } from '../../utils'
|
||||
|
||||
@@ -74,14 +74,18 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
function isPartiallyEqual(item1, item2) {
|
||||
function isPartiallyEqual(item1: any, item2: any) {
|
||||
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
|
||||
if (q.type === 'added') {
|
||||
filtered.push(q.key)
|
||||
filtered.add(q.key)
|
||||
}
|
||||
return filtered
|
||||
}, [])
|
||||
return isEqual(item1, item2, { excludeKeys: key => diffedKeys.includes(key) })
|
||||
}, new Set<string>())
|
||||
|
||||
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
|
||||
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
|
||||
|
||||
return isEqual(item1Filtered, item2Filtered)
|
||||
}
|
||||
|
||||
function resolveLinkClass(route, $route, { isActive, isExactActive }: { isActive: boolean, isExactActive: boolean }) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { ComputedRef, VNode, SlotsType, PropType } from 'vue'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getSlotsChildren } from '../../utils'
|
||||
import { getSlotsChildren, mergeConfig } from '../../utils'
|
||||
import type { DeepPartial, Strategy, MeterSize } from '../../types/index'
|
||||
import type Meter from './Meter.vue'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -13,6 +13,7 @@ import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } fro
|
||||
import type { BaseSchema as ValibotSchema30, BaseSchemaAsync as ValibotSchemaAsync30 } from 'valibot30'
|
||||
import type { GenericSchema as ValibotSchema31, GenericSchemaAsync as ValibotSchemaAsync31, SafeParser as ValibotSafeParser31, SafeParserAsync as ValibotSafeParserAsync31 } from 'valibot31'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
||||
import type { Struct } from 'superstruct'
|
||||
import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEvent, Form, ValidateReturnSchema } from '../../types/form'
|
||||
import { useId } from '#imports'
|
||||
@@ -33,6 +34,7 @@ type Schema = PropType<ZodSchema>
|
||||
| PropType<ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any>>
|
||||
| PropType<ValibotSchema | ValibotSchemaAsync>
|
||||
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>> | PropType<Struct<any, any>>
|
||||
| PropType<StandardSchemaV1>
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -220,6 +222,35 @@ function isZodSchema(schema: any): schema is ZodSchema {
|
||||
return schema.parse !== undefined
|
||||
}
|
||||
|
||||
export function isStandardSchema(schema: any): schema is StandardSchemaV1 {
|
||||
return '~standard' in schema
|
||||
}
|
||||
|
||||
export async function validateStandardSchema(
|
||||
state: any,
|
||||
schema: StandardSchemaV1
|
||||
): Promise<ValidateReturnSchema<typeof state>> {
|
||||
const result = await schema['~standard'].validate(state)
|
||||
|
||||
if (!result.issues || result.issues.length === 0) {
|
||||
const output = ('value' in result ? result.value : null)
|
||||
return {
|
||||
errors: null,
|
||||
result: output
|
||||
}
|
||||
}
|
||||
|
||||
const errors = result.issues.map(issue => ({
|
||||
path: issue.path?.map(item => typeof item === 'object' ? item.key : item).join('.') || '',
|
||||
message: issue.message
|
||||
}))
|
||||
|
||||
return {
|
||||
errors,
|
||||
result: null
|
||||
}
|
||||
}
|
||||
|
||||
async function validateValibotSchema(
|
||||
state: any,
|
||||
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema31 | ValibotSchemaAsync31 | ValibotSafeParser31<any, any> | ValibotSafeParserAsync31<any, any> | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
||||
@@ -346,7 +377,9 @@ async function validateYupSchema(
|
||||
}
|
||||
|
||||
function parseSchema(state: any, schema: Schema): Promise<ValidateReturnSchema<typeof state>> {
|
||||
if (isZodSchema(schema)) {
|
||||
if (isStandardSchema(schema)) {
|
||||
return validateStandardSchema(state, schema)
|
||||
} else if (isZodSchema(schema)) {
|
||||
return validateZodSchema(state, schema)
|
||||
} else if (isJoiSchema(schema)) {
|
||||
return validateJoiSchema(state, schema)
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
<script lang="ts">
|
||||
import { ref, computed, toRef, onMounted, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { defu } from 'defu'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig, looseToNumber } from '../../utils'
|
||||
import { looseToNumber, mergeConfig, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { InputSize, InputColor, InputVariant, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -103,14 +103,14 @@ import {
|
||||
} from '@headlessui/vue'
|
||||
import { computedAsync, useDebounceFn } from '@vueuse/core'
|
||||
import { defu } from 'defu'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { isEqual } from 'ohash'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { isEqual } from 'ohash/utils'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { get, mergeConfig } from '../../utils'
|
||||
import { get, mergeConfig, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { InputSize, InputColor, InputVariant, PopperOptions, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, inject, toRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -34,7 +34,7 @@ import { computed, defineComponent, provide, toRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig, get } from '../../utils'
|
||||
import { get, mergeConfig } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
import URadio from './Radio.vue'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { RangeSize, RangeColor, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -55,11 +55,11 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType, ComputedRef } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig, get } from '../../utils'
|
||||
import { get, mergeConfig, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { SelectSize, SelectColor, SelectVariant, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
:value="modelValue"
|
||||
:required="required"
|
||||
:class="uiMenu.required"
|
||||
:form="inputTargetForm"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
>
|
||||
@@ -139,14 +140,14 @@ import {
|
||||
} from '@headlessui/vue'
|
||||
import { computedAsync, useDebounceFn } from '@vueuse/core'
|
||||
import { defu } from 'defu'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { isEqual } from 'ohash'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { isEqual } from 'ohash/utils'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { get, mergeConfig } from '../../utils'
|
||||
import { get, mergeConfig, twMerge } from '../../utils'
|
||||
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
||||
import type { SelectSize, SelectColor, SelectVariant, PopperOptions, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
@@ -314,6 +315,10 @@ export default defineComponent({
|
||||
type: Array,
|
||||
default: null
|
||||
},
|
||||
inputTargetForm: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
popper: {
|
||||
type: Object as PropType<PopperOptions>,
|
||||
default: () => ({})
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
<script lang="ts">
|
||||
import { ref, computed, toRef, watch, onMounted, nextTick, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { defu } from 'defu'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig, looseToNumber } from '../../utils'
|
||||
import { looseToNumber, mergeConfig, twMerge } from '../../utils'
|
||||
import type { TextareaSize, TextareaColor, TextareaVariant, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { Switch as HSwitch, provideUseId } from '@headlessui/vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { ToggleSize, ToggleColor, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
<script lang="ts">
|
||||
import { toRef, computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { Avatar, DeepPartial, DividerSize, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, toRef } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import ULink from '../elements/Link.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getULinkProps } from '../../utils'
|
||||
import { getULinkProps, mergeConfig, twMerge } from '../../utils'
|
||||
import type { BreadcrumbLink, DeepPartial, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -54,13 +54,13 @@
|
||||
<script lang="ts">
|
||||
import { toRef, defineComponent, computed } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UBadge from '../elements/Badge.vue'
|
||||
import ULink from '../elements/Link.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getULinkProps } from '../../utils'
|
||||
import { getULinkProps, mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, HorizontalNavigationLink, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -55,14 +55,14 @@
|
||||
<script lang="ts">
|
||||
import { toRef, defineComponent, computed } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UBadge from '../elements/Badge.vue'
|
||||
import ULink from '../elements/Link.vue'
|
||||
import UDivider from '../layout/Divider.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig, getULinkProps } from '../../utils'
|
||||
import { getULinkProps, mergeConfig, twMerge } from '../../utils'
|
||||
import type { VerticalNavigationLink, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -18,10 +18,10 @@ import type { PropType, Ref } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import type { VirtualElement } from '@popperjs/core'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, PopperOptions, Strategy } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{{ title }}
|
||||
</slot>
|
||||
</p>
|
||||
<div v-if="(description || $slots.description)" :class="twMerge(ui.description, !title && !$slots.title && 'mt-0 leading-5')">
|
||||
<div v-if="(description || $slots.description)" :class="twMerge(ui.description, !title && !$slots.title && ui.descriptionOnly)">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
@@ -45,13 +45,13 @@
|
||||
<script lang="ts">
|
||||
import { ref, computed, toRef, onMounted, onUnmounted, watch, watchEffect, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useTimer } from '../../composables/useTimer'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { Avatar, Button, NotificationColor, NotificationAction, Strategy, DeepPartial } from '../../types/index'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
<script lang="ts">
|
||||
import { computed, toRef, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { twJoin } from 'tailwind-merge'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useToast } from '../../composables/useToast'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import { mergeConfig, twMerge } from '../../utils'
|
||||
import type { DeepPartial, Notification, Strategy } from '../../types/index'
|
||||
import UNotification from './Notification.vue'
|
||||
import { useState } from '#imports'
|
||||
|
||||
@@ -5,6 +5,7 @@ export default {
|
||||
inner: 'w-0 flex-1',
|
||||
title: 'text-sm font-medium',
|
||||
description: 'mt-1 text-sm leading-4 opacity-90',
|
||||
descriptionOnly: 'mt-0 leading-5',
|
||||
actions: 'flex items-center gap-2 mt-3 flex-shrink-0',
|
||||
shadow: '',
|
||||
rounded: 'rounded-lg',
|
||||
|
||||
@@ -6,6 +6,7 @@ export default {
|
||||
inner: 'w-0 flex-1',
|
||||
title: 'text-sm font-medium text-gray-900 dark:text-white',
|
||||
description: 'mt-1 text-sm leading-4 text-gray-500 dark:text-gray-400',
|
||||
descriptionOnly: 'mt-0 leading-5',
|
||||
actions: 'flex items-center gap-2 mt-3 flex-shrink-0',
|
||||
background: 'bg-white dark:bg-gray-900',
|
||||
shadow: 'shadow-lg',
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { defu, createDefu } from 'defu'
|
||||
import { extendTailwindMerge } from 'tailwind-merge'
|
||||
import type { Strategy } from '../types/index'
|
||||
// @ts-ignore
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
const customTwMerge = extendTailwindMerge<string, string>({
|
||||
export const twMerge = extendTailwindMerge<string, string>(defu({
|
||||
extend: {
|
||||
classGroups: {
|
||||
icons: [(classPart: string) => classPart.startsWith('i-')]
|
||||
}
|
||||
}
|
||||
})
|
||||
}, appConfig.ui?.tailwindMerge))
|
||||
|
||||
const defuTwMerge = createDefu((obj, key, value, namespace) => {
|
||||
if (namespace === 'default' || namespace.startsWith('default.')) {
|
||||
@@ -28,7 +30,7 @@ const defuTwMerge = createDefu((obj, key, value, namespace) => {
|
||||
}
|
||||
if (typeof obj[key] === 'string' && typeof value === 'string' && obj[key] && value) {
|
||||
// @ts-ignore
|
||||
obj[key] = customTwMerge(obj[key], value)
|
||||
obj[key] = twMerge(obj[key], value)
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
@@ -30,21 +30,26 @@ export default function installTailwind(
|
||||
|
||||
// 2. add config template
|
||||
const configTemplate = addTemplate({
|
||||
filename: 'nuxtui-tailwind.config.cjs',
|
||||
filename: 'nuxtui-tailwind.config.mjs',
|
||||
write: true,
|
||||
getContents: ({ nuxt }) => `
|
||||
const { defaultExtractor: createDefaultExtractor } = require('tailwindcss/lib/lib/defaultExtractor.js')
|
||||
const { customSafelistExtractor, generateSafelist } = require(${JSON.stringify(resolve(runtimeDir, 'utils', 'colors'))})
|
||||
import { defaultExtractor as createDefaultExtractor } from "tailwindcss/lib/lib/defaultExtractor.js";
|
||||
import { customSafelistExtractor, generateSafelist } from ${JSON.stringify(resolve(runtimeDir, 'utils', 'colors'))};
|
||||
import formsPlugin from "@tailwindcss/forms";
|
||||
import aspectRatio from "@tailwindcss/aspect-ratio";
|
||||
import typography from "@tailwindcss/typography";
|
||||
import containerQueries from "@tailwindcss/container-queries";
|
||||
import headlessUi from "@headlessui/tailwindcss";
|
||||
|
||||
const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } })
|
||||
const defaultExtractor = createDefaultExtractor({ tailwindConfig: { separator: ':' } });
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: [
|
||||
require('@tailwindcss/forms')({ strategy: 'class' }),
|
||||
require('@tailwindcss/aspect-ratio'),
|
||||
require('@tailwindcss/typography'),
|
||||
require('@tailwindcss/container-queries'),
|
||||
require('@headlessui/tailwindcss')
|
||||
formsPlugin({ strategy: 'class' }),
|
||||
aspectRatio,
|
||||
typography,
|
||||
containerQueries,
|
||||
headlessUi
|
||||
],
|
||||
content: {
|
||||
files: [
|
||||
|
||||
Reference in New Issue
Block a user