mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 20:48:12 +01:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6736d1efd | ||
|
|
f6e695ffc8 | ||
|
|
e8898d15a6 | ||
|
|
f65aefb706 | ||
|
|
9b9ccdb59e | ||
|
|
688232215d | ||
|
|
ebfb835033 | ||
|
|
838d6c832f | ||
|
|
e7c2f7856c | ||
|
|
1d5bd89d58 | ||
|
|
6c124bb1ac | ||
|
|
49174b7628 | ||
|
|
50ad14f9df | ||
|
|
6e2678d1d8 | ||
|
|
831c560a96 | ||
|
|
06990beabf | ||
|
|
3ebff4d133 | ||
|
|
d66cfa9d7d | ||
|
|
75c0d9e31f | ||
|
|
6033872ef8 | ||
|
|
838cb7212a | ||
|
|
c8dd71c4f5 | ||
|
|
4f0d00f7a6 | ||
|
|
3b975634e8 | ||
|
|
249bbd49dc | ||
|
|
3c1602af37 | ||
|
|
e1ca6e0cde | ||
|
|
3b3bd16afe | ||
|
|
fab9cbebd8 | ||
|
|
581b470cc7 | ||
|
|
24d30cd1f3 |
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,5 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## [2.17.0](https://github.com/nuxt/ui/compare/v2.16.0...v2.17.0) (2024-06-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Alert:** add `actions` slot ([#1785](https://github.com/nuxt/ui/issues/1785)) ([c8dd71c](https://github.com/nuxt/ui/commit/c8dd71c4f5a5239811b07b50f1dc802101af07d5))
|
||||
* **Form:** update and migrate `valibot` to v0.31.0 ([#1848](https://github.com/nuxt/ui/issues/1848)) ([1d5bd89](https://github.com/nuxt/ui/commit/1d5bd89d5881163fc6dc917e138b9d8304dff6c4))
|
||||
* **Notification:** allow ring customization with `{color}` ([#1830](https://github.com/nuxt/ui/issues/1830)) ([3ebff4d](https://github.com/nuxt/ui/commit/3ebff4d133372e339e2c4c439576e9e192b29cc3))
|
||||
* **Slideover:** handle `top` and `bottom` side ([#1834](https://github.com/nuxt/ui/issues/1834)) ([50ad14f](https://github.com/nuxt/ui/commit/50ad14f9dffe4f76bef888cd10d30b417c75bca5))
|
||||
* **Tabs:** add `content` prop to avoid the render of the HTML markup ([#1831](https://github.com/nuxt/ui/issues/1831)) ([6e2678d](https://github.com/nuxt/ui/commit/6e2678d1d8a498322eb3eff909ccbba55e40a2b7))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Alert/Notification:** use `div` for description ([e8898d1](https://github.com/nuxt/ui/commit/e8898d15a667ba66e78828315e3cc4e92845cd3f)), closes [#1551](https://github.com/nuxt/ui/issues/1551)
|
||||
* **Alert:** base style not applied on icon ([#1859](https://github.com/nuxt/ui/issues/1859)) ([f65aefb](https://github.com/nuxt/ui/commit/f65aefb7067c1c64c1355b5d699129e716ef1281))
|
||||
* **Breadcrumb:** allow `aria-current` to be overrideable ([ebfb835](https://github.com/nuxt/ui/commit/ebfb8350339725c0a6f88c73f16bff01d61538c2)), closes [#1856](https://github.com/nuxt/ui/issues/1856)
|
||||
* **Carousel:** prevent mouse click when dragging ([#1781](https://github.com/nuxt/ui/issues/1781)) ([4f0d00f](https://github.com/nuxt/ui/commit/4f0d00f7a6eebf05adceaf1e7c2869ad91949cf3))
|
||||
* **CommandPalette:** hide `empty-state` when `null` ([249bbd4](https://github.com/nuxt/ui/commit/249bbd49dc8420603e8d561543d237abeb400908)), closes [#1787](https://github.com/nuxt/ui/issues/1787)
|
||||
* **Form:** maintain other errors when using `setErrors` with a path ([#1818](https://github.com/nuxt/ui/issues/1818)) ([06990be](https://github.com/nuxt/ui/commit/06990beabf67f668322b4d3fb2ec93cc4f3bdcd4))
|
||||
* **Input:** hide wrapper when type is `hidden` ([#1797](https://github.com/nuxt/ui/issues/1797)) ([e7c2f78](https://github.com/nuxt/ui/commit/e7c2f7856c05ed96f48c83d64d8e1d3f41ab58fe))
|
||||
* **Link:** typo in `exactHash` type ([581b470](https://github.com/nuxt/ui/commit/581b470cc79c2315bb2d56e02a7c134a7861c616)), closes [#1767](https://github.com/nuxt/ui/issues/1767)
|
||||
* **SelectMenu:** wrong placeholder color when `modelValue` is an empty string ([9b9ccdb](https://github.com/nuxt/ui/commit/9b9ccdb59e98fed096dd18809af646b10de46b9f)), closes [#1862](https://github.com/nuxt/ui/issues/1862)
|
||||
* **Select:** remove defaults for `value` and `text` ([6c124bb](https://github.com/nuxt/ui/commit/6c124bb1ac2fef116161da56a3a8e5f92144ce3a)), closes [#1702](https://github.com/nuxt/ui/issues/1702)
|
||||
|
||||
## [2.16.0](https://github.com/nuxt/ui/compare/v2.15.2...v2.16.0) (2024-05-07)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouse, useWindowScroll } from '@vueuse/core'
|
||||
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { string, objectAsync, email, minLength, type Input } from 'valibot'
|
||||
import * as v from 'valibot'
|
||||
import type { FormSubmitEvent } from '#ui/types'
|
||||
|
||||
const schema = objectAsync({
|
||||
email: string([email('Invalid email')]),
|
||||
password: string([minLength(8, 'Must be at least 8 characters')])
|
||||
const schema = v.object({
|
||||
email: v.pipe(v.string(), v.email('Invalid email')),
|
||||
password: v.pipe(v.string(), v.minLength(8, 'Must be at least 8 characters'))
|
||||
})
|
||||
|
||||
type Schema = Input<typeof schema>
|
||||
type Schema = v.InferOutput<typeof schema>
|
||||
|
||||
const state = reactive({
|
||||
email: '',
|
||||
@@ -21,7 +21,7 @@ async function onSubmit (event: FormSubmitEvent<Schema>) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UForm :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UForm :schema="v.safeParser(schema)" :state="state" class="space-y-4" @submit="onSubmit">
|
||||
<UFormGroup label="Email" name="email">
|
||||
<UInput v-model="state.email" />
|
||||
</UFormGroup>
|
||||
|
||||
@@ -8,6 +8,16 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -7,8 +7,22 @@ const isOpen = ref(false)
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="isOpen">
|
||||
<UCard class="flex flex-col flex-1" :ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<UCard
|
||||
class="flex flex-col flex-1"
|
||||
:ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"
|
||||
>
|
||||
<template #header>
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-8" />
|
||||
</template>
|
||||
|
||||
|
||||
@@ -8,6 +8,17 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen" :overlay="false">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -8,6 +8,17 @@ const isOpen = ref(false)
|
||||
|
||||
<USlideover v-model="isOpen" :transition="false">
|
||||
<div class="p-4 flex-1">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon="i-heroicons-x-mark-20-solid"
|
||||
class="flex sm:hidden absolute end-5 top-5 z-10"
|
||||
square
|
||||
padded
|
||||
@click="isOpen = false"
|
||||
/>
|
||||
|
||||
<Placeholder class="h-full" />
|
||||
</div>
|
||||
</USlideover>
|
||||
|
||||
@@ -175,6 +175,10 @@ Use the `#avatar` slot to customize the displayable avatar.
|
||||
|
||||
:component-example{component="alert-example-avatar"}
|
||||
|
||||
### `actions` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}
|
||||
|
||||
Use the `#actions` slot to add custom user interaction elements.
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -10,7 +10,7 @@ links:
|
||||
|
||||
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://valibot.dev/), or your own validation logic.
|
||||
|
||||
It works with the [FormGroup](/components/input) 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:
|
||||
- `state` - a reactive object holding the form's state.
|
||||
|
||||
@@ -49,7 +49,7 @@ extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-columns-selectable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -282,7 +282,7 @@ extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-searchable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
@@ -296,7 +296,7 @@ extraClass: 'overflow-hidden'
|
||||
padding: false
|
||||
component: 'table-example-paginable'
|
||||
componentProps:
|
||||
class: 'flex-1'
|
||||
class: 'flex-1 flex-col overflow-hidden'
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@ componentProps:
|
||||
---
|
||||
::
|
||||
|
||||
You can use the `content` prop and set it to `false` to avoid the rendering of the HTML content if you don't need it.
|
||||
|
||||
### Control the selected index
|
||||
|
||||
Use a `v-model` to control the selected index.
|
||||
|
||||
@@ -4,29 +4,29 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@iconify-json/heroicons": "^1.1.21",
|
||||
"@iconify-json/simple-icons": "^1.1.101",
|
||||
"@iconify-json/simple-icons": "^1.1.105",
|
||||
"@nuxt/content": "^2.12.1",
|
||||
"@nuxt/eslint-config": "^0.3.10",
|
||||
"@nuxt/eslint-config": "^0.3.13",
|
||||
"@nuxt/fonts": "^0.7.0",
|
||||
"@nuxt/image": "^1.7.0",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.1.0-28584604.9227c85",
|
||||
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.2.0-28637819.42c6d9b",
|
||||
"@nuxtjs/plausible": "^1.0.0",
|
||||
"@octokit/rest": "^20.1.1",
|
||||
"@vueuse/nuxt": "^10.9.0",
|
||||
"@vueuse/nuxt": "^10.11.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"eslint": "^8.57.0",
|
||||
"joi": "^17.13.1",
|
||||
"nuxt": "^3.11.2",
|
||||
"nuxt": "^3.12.1",
|
||||
"nuxt-cloudflare-analytics": "^1.0.8",
|
||||
"nuxt-component-meta": "^0.6.4",
|
||||
"nuxt-og-image": "^2.2.4",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier": "^3.3.2",
|
||||
"typescript": "^5.4.5",
|
||||
"ufo": "^1.5.3",
|
||||
"v-calendar": "^3.1.2",
|
||||
"valibot": "^0.30.0",
|
||||
"valibot": "^0.31.1",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.6"
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
||||
35
package.json
35
package.json
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "@nuxt/ui",
|
||||
"version": "2.16.0",
|
||||
"version": "2.17.0",
|
||||
"packageManager": "pnpm@9.1.1",
|
||||
"repository": "nuxt/ui",
|
||||
"homepage": "https://ui.nuxt.com",
|
||||
"type": "module",
|
||||
@@ -33,11 +34,11 @@
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@egoist/tailwindcss-icons": "^1.8.0",
|
||||
"@headlessui/tailwindcss": "^0.2.0",
|
||||
"@headlessui/vue": "^1.7.21",
|
||||
"@egoist/tailwindcss-icons": "^1.8.1",
|
||||
"@headlessui/tailwindcss": "^0.2.1",
|
||||
"@headlessui/vue": "^1.7.22",
|
||||
"@iconify-json/heroicons": "^1.1.21",
|
||||
"@nuxt/kit": "^3.11.2",
|
||||
"@nuxt/kit": "^3.12.1",
|
||||
"@nuxtjs/color-mode": "^3.4.1",
|
||||
"@nuxtjs/tailwindcss": "^6.12.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
@@ -45,9 +46,9 @@
|
||||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@vueuse/integrations": "^10.9.0",
|
||||
"@vueuse/math": "^10.9.0",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@vueuse/integrations": "^10.11.0",
|
||||
"@vueuse/math": "^10.11.0",
|
||||
"defu": "^6.1.4",
|
||||
"fuse.js": "^6.6.2",
|
||||
"nuxt-icon": "^0.6.10",
|
||||
@@ -55,30 +56,32 @@
|
||||
"pathe": "^1.1.2",
|
||||
"scule": "^1.3.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss": "^3.4.3"
|
||||
"tailwindcss": "^3.4.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint-config": "^0.3.10",
|
||||
"@nuxt/eslint-config": "^0.3.13",
|
||||
"@nuxt/module-builder": "^0.5.5",
|
||||
"@nuxt/test-utils": "^3.12.1",
|
||||
"@nuxt/test-utils": "^3.13.1",
|
||||
"@release-it/conventional-changelog": "^8.0.1",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"eslint": "^8.57.0",
|
||||
"happy-dom": "^14.10.1",
|
||||
"joi": "^17.13.1",
|
||||
"nuxt": "^3.11.2",
|
||||
"release-it": "^17.2.1",
|
||||
"nuxt": "^3.12.1",
|
||||
"release-it": "^17.3.0",
|
||||
"typescript": "^5.4.5",
|
||||
"unbuild": "^2.0.0",
|
||||
"valibot": "^0.30.0",
|
||||
"valibot30": "npm:valibot@0.30.0",
|
||||
"valibot": "^0.31.1",
|
||||
"vitest": "^1.6.0",
|
||||
"vitest-environment-nuxt": "^1.0.0",
|
||||
"vue-tsc": "^2.0.16",
|
||||
"yup": "^1.4.0",
|
||||
"zod": "^3.23.6"
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"resolutions": {
|
||||
"@nuxt/ui": "workspace:*",
|
||||
"@nuxt/module-builder": "0.5.5"
|
||||
"@nuxt/module-builder": "0.5.5",
|
||||
"vue-tsc": "2.0.16"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/ui": "latest",
|
||||
"nuxt": "^3.11.2"
|
||||
"nuxt": "^3.12.1"
|
||||
}
|
||||
}
|
||||
|
||||
7596
pnpm-lock.yaml
generated
7596
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
<div :class="alertClass" v-bind="attrs">
|
||||
<div class="flex" :class="[ui.gap, { 'items-start': (description || $slots.description), 'items-center': !description && !$slots.description }]">
|
||||
<slot name="icon" :icon="icon">
|
||||
<UIcon v-if="icon" :name="icon" :ui="ui.icon.base" />
|
||||
<UIcon v-if="icon" :name="icon" :class="ui.icon.base" />
|
||||
</slot>
|
||||
<slot name="avatar" :avatar="avatar">
|
||||
<UAvatar v-if="avatar" v-bind="{ size: ui.avatar.size, ...avatar }" :class="ui.avatar.base" />
|
||||
@@ -14,19 +14,23 @@
|
||||
{{ title }}
|
||||
</slot>
|
||||
</p>
|
||||
<p 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) && 'mt-0 leading-5')">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="(description || $slots.description) && actions.length" :class="ui.actions">
|
||||
<UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
|
||||
<div v-if="(description || $slots.description) && (actions.length || $slots.actions)" :class="ui.actions">
|
||||
<slot name="actions">
|
||||
<UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="closeButton || (!description && !$slots.description && actions.length)" :class="twMerge(ui.actions, 'mt-0')">
|
||||
<template v-if="!description && !$slots.description && actions.length">
|
||||
<UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
|
||||
<template v-if="!description && !$slots.description && (actions.length || $slots.actions)">
|
||||
<slot name="actions">
|
||||
<UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
<UButton v-if="closeButton" aria-label="Close" v-bind="{ ...(ui.default.closeButton || {}), ...closeButton }" @click.stop="$emit('close')" />
|
||||
|
||||
@@ -10,7 +10,8 @@ import { useEventBus } from '@vueuse/core'
|
||||
import type { ZodSchema } from 'zod'
|
||||
import type { ValidationError as JoiError, Schema as JoiSchema } from 'joi'
|
||||
import type { ObjectSchema as YupObjectSchema, ValidationError as YupError } from 'yup'
|
||||
import type { ObjectSchemaAsync as ValibotObjectSchema } from 'valibot'
|
||||
import type { BaseSchema as ValibotSchema30, BaseSchemaAsync as ValibotSchemaAsync30 } from 'valibot30'
|
||||
import type { GenericSchema as ValibotSchema, GenericSchemaAsync as ValibotSchemaAsync, SafeParser as ValibotSafeParser, SafeParserAsync as ValibotSafeParserAsync } from 'valibot'
|
||||
import type { FormError, FormEvent, FormEventType, FormSubmitEvent, FormErrorEvent, Form } from '../../types/form'
|
||||
import { useId } from '#imports'
|
||||
|
||||
@@ -25,11 +26,13 @@ class FormException extends Error {
|
||||
export default defineComponent({
|
||||
props: {
|
||||
schema: {
|
||||
type: Object as
|
||||
type: [Object, Function] as
|
||||
| PropType<ZodSchema>
|
||||
| PropType<YupObjectSchema<any>>
|
||||
| PropType<JoiSchema>
|
||||
| PropType<ValibotObjectSchema<any>>,
|
||||
| PropType<ValibotSchema30 | ValibotSchemaAsync30>
|
||||
| PropType<ValibotSchema | ValibotSchemaAsync>
|
||||
| PropType<ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>>,
|
||||
default: undefined
|
||||
},
|
||||
state: {
|
||||
@@ -151,7 +154,6 @@ export default defineComponent({
|
||||
validate,
|
||||
errors,
|
||||
setErrors (errs: FormError[], path?: string) {
|
||||
errors.value = errs
|
||||
if (path) {
|
||||
errors.value = errors.value.filter(
|
||||
(error) => error.path !== path
|
||||
@@ -256,21 +258,19 @@ async function getJoiErrors (
|
||||
}
|
||||
}
|
||||
|
||||
function isValibotSchema (schema: any): schema is ValibotObjectSchema<any> {
|
||||
return schema._parse !== undefined
|
||||
function isValibotSchema (schema: any): schema is ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any> {
|
||||
return '_parse' in schema || '_run' in schema || (typeof schema === 'function' && 'schema' in schema)
|
||||
}
|
||||
|
||||
async function getValibotError (
|
||||
state: any,
|
||||
schema: ValibotObjectSchema<any>
|
||||
schema: ValibotSchema30 | ValibotSchemaAsync30 | ValibotSchema | ValibotSchemaAsync | ValibotSafeParser<any, any> | ValibotSafeParserAsync<any, any>
|
||||
): Promise<FormError[]> {
|
||||
const result = await schema._parse(state)
|
||||
if (result.issues) {
|
||||
return result.issues.map((issue) => ({
|
||||
path: issue.path?.map(p => p.key).join('.') || '',
|
||||
message: issue.message
|
||||
}))
|
||||
}
|
||||
return []
|
||||
const result = await ('_parse' in schema ? schema._parse(state) : '_run' in schema ? schema._run({ typed: false, value: state }, {}) : schema(state))
|
||||
return result.issues?.map((issue) => ({
|
||||
// We know that the key for a form schema is always a string or a number
|
||||
path: issue.path?.map((item) => item.key).join('.') || '',
|
||||
message: issue.message
|
||||
})) || []
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="ui.wrapper">
|
||||
<div :class="(type === 'hidden') ? 'hidden' : ui.wrapper">
|
||||
<input
|
||||
:id="inputId"
|
||||
ref="input"
|
||||
|
||||
@@ -199,11 +199,11 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const guessOptionValue = (option: any) => {
|
||||
return get(option, props.valueAttribute, get(option, props.optionAttribute))
|
||||
return get(option, props.valueAttribute, '')
|
||||
}
|
||||
|
||||
const guessOptionText = (option: any) => {
|
||||
return get(option, props.optionAttribute, get(option, props.valueAttribute))
|
||||
return get(option, props.optionAttribute, '')
|
||||
}
|
||||
|
||||
const normalizeOption = (option: any) => {
|
||||
|
||||
@@ -391,7 +391,7 @@ export default defineComponent({
|
||||
variant?.replaceAll('{color}', color.value),
|
||||
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
|
||||
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
|
||||
), props.placeholder && (props.modelValue === undefined && props.modelValue === null) && ui.value.placeholder, props.selectClass)
|
||||
), props.placeholder && !props.modelValue && ui.value.placeholder, props.selectClass)
|
||||
})
|
||||
|
||||
const isLeading = computed(() => {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<ULink
|
||||
as="span"
|
||||
:class="[ui.base, index === links.length - 1 ? ui.active : !!link.to ? ui.inactive : '']"
|
||||
v-bind="getULinkProps(link)"
|
||||
:aria-current="index === links.length - 1 ? 'page' : undefined"
|
||||
v-bind="getULinkProps(link)"
|
||||
@click="link.click"
|
||||
>
|
||||
<slot name="icon" :link="link" :index="index" :is-active="index === links.length - 1">
|
||||
|
||||
@@ -321,7 +321,10 @@ export default defineComponent({
|
||||
)
|
||||
})
|
||||
|
||||
const emptyState = computed(() => ({ ...ui.value.default.emptyState, ...props.emptyState }))
|
||||
const emptyState = computed(() => {
|
||||
if (props.emptyState === null) return null
|
||||
return { ...ui.value.default.emptyState, ...props.emptyState }
|
||||
})
|
||||
|
||||
// Methods
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</HTab>
|
||||
</HTabList>
|
||||
|
||||
<HTabPanels :class="ui.container">
|
||||
<HTabPanels v-if="content" :class="ui.container">
|
||||
<HTabPanel v-for="(item, index) of items" :key="index" v-slot="{ selected }" :class="ui.base" :unmount="unmount">
|
||||
<slot :name="item.slot || 'item'" :item="item" :index="index" :selected="selected">
|
||||
{{ item.content }}
|
||||
@@ -88,6 +88,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
content: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
class: {
|
||||
type: [String, Object, Array] as PropType<any>,
|
||||
default: () => ''
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
{{ title }}
|
||||
</slot>
|
||||
</p>
|
||||
<p 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) && 'mt-0 leading-5')">
|
||||
<slot name="description" :description="description">
|
||||
{{ description }}
|
||||
</slot>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="(description || $slots.description) && actions.length" :class="ui.actions">
|
||||
<UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
|
||||
@@ -131,7 +131,8 @@ export default defineComponent({
|
||||
ui.value.wrapper,
|
||||
ui.value.background?.replaceAll('{color}', props.color),
|
||||
ui.value.rounded,
|
||||
ui.value.shadow
|
||||
ui.value.shadow,
|
||||
ui.value.ring?.replaceAll('{color}', props.color)
|
||||
), props.class)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<TransitionRoot as="template" :appear="appear" :show="isOpen" @after-leave="onAfterLeave">
|
||||
<HDialog :class="[ui.wrapper, { 'justify-end': side === 'right' }]" v-bind="attrs" @close="close">
|
||||
<HDialog :class="[ui.wrapper, { 'justify-end': side === 'right' }, { 'items-end': side === 'bottom' }]" v-bind="attrs" @close="close">
|
||||
<TransitionChild v-if="overlay" as="template" :appear="appear" v-bind="ui.overlay.transition">
|
||||
<div :class="[ui.overlay.base, ui.overlay.background]" />
|
||||
</TransitionChild>
|
||||
|
||||
<TransitionChild as="template" :appear="appear" v-bind="transitionClass">
|
||||
<HDialogPanel :class="[ui.base, ui.width, ui.background, ui.ring, ui.padding]">
|
||||
<HDialogPanel :class="[ui.base, sideType === 'horizontal' ? [ui.width, 'h-full'] : [ui.height, 'w-full'], ui.background, ui.ring, ui.padding]">
|
||||
<slot />
|
||||
</HDialogPanel>
|
||||
</TransitionChild>
|
||||
@@ -46,9 +46,9 @@ export default defineComponent({
|
||||
default: false
|
||||
},
|
||||
side: {
|
||||
type: String as PropType<'left' | 'right'>,
|
||||
type: String as PropType<'left' | 'right' | 'top' | 'bottom'>,
|
||||
default: 'right',
|
||||
validator: (value: string) => ['left', 'right'].includes(value)
|
||||
validator: (value: string) => ['left', 'right', 'top', 'bottom'].includes(value)
|
||||
},
|
||||
overlay: {
|
||||
type: Boolean,
|
||||
@@ -89,14 +89,52 @@ export default defineComponent({
|
||||
return {}
|
||||
}
|
||||
|
||||
let enterFrom, leaveTo
|
||||
switch (props.side) {
|
||||
case 'left':
|
||||
enterFrom = ui.value.translate.left
|
||||
leaveTo = ui.value.translate.left
|
||||
break
|
||||
case 'right':
|
||||
enterFrom = ui.value.translate.right
|
||||
leaveTo = ui.value.translate.right
|
||||
break
|
||||
case 'top':
|
||||
enterFrom = ui.value.translate.top
|
||||
leaveTo = ui.value.translate.top
|
||||
break
|
||||
case 'bottom':
|
||||
enterFrom = ui.value.translate.bottom
|
||||
leaveTo = ui.value.translate.bottom
|
||||
break
|
||||
default:
|
||||
enterFrom = ui.value.translate.right
|
||||
leaveTo = ui.value.translate.right
|
||||
}
|
||||
|
||||
return {
|
||||
...ui.value.transition,
|
||||
enterFrom: props.side === 'left' ? ui.value.translate.left : ui.value.translate.right,
|
||||
enterFrom,
|
||||
enterTo: ui.value.translate.base,
|
||||
leaveFrom: ui.value.translate.base,
|
||||
leaveTo: props.side === 'left' ? ui.value.translate.left : ui.value.translate.right
|
||||
leaveTo
|
||||
}
|
||||
})
|
||||
const sideType = computed(() => {
|
||||
switch (props.side) {
|
||||
case 'left':
|
||||
return 'horizontal'
|
||||
case 'right':
|
||||
return 'horizontal'
|
||||
case 'top':
|
||||
return 'vertical'
|
||||
case 'bottom':
|
||||
return 'vertical'
|
||||
default:
|
||||
return 'right'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function close (value: boolean) {
|
||||
if (props.preventClose) {
|
||||
@@ -121,9 +159,10 @@ export default defineComponent({
|
||||
attrs,
|
||||
isOpen,
|
||||
transitionClass,
|
||||
sideType,
|
||||
onAfterLeave,
|
||||
close
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
@@ -16,6 +16,7 @@ export const useCarouselScroll = (el: Ref<HTMLElement>) => {
|
||||
function onMouseUp () {
|
||||
el.value.style.removeProperty('scroll-behavior')
|
||||
el.value.style.removeProperty('scroll-snap-type')
|
||||
el.value.style.removeProperty('pointer-events')
|
||||
|
||||
window.removeEventListener('mousemove', onMouseMove)
|
||||
window.removeEventListener('mouseup', onMouseUp)
|
||||
@@ -24,6 +25,8 @@ export const useCarouselScroll = (el: Ref<HTMLElement>) => {
|
||||
function onMouseMove (e) {
|
||||
e.preventDefault()
|
||||
|
||||
el.value.style.pointerEvents = 'none'
|
||||
|
||||
const delta = e.pageX - x.value
|
||||
|
||||
x.value = e.pageX
|
||||
|
||||
2
src/runtime/types/link.d.ts
vendored
2
src/runtime/types/link.d.ts
vendored
@@ -7,6 +7,6 @@ export interface Link extends NuxtLinkProps {
|
||||
active?: boolean
|
||||
exact?: boolean
|
||||
exactQuery?: boolean
|
||||
exactMatch?: boolean
|
||||
exactHash?: boolean
|
||||
inactiveClass?: string
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ export default {
|
||||
padding: '',
|
||||
shadow: 'shadow-xl',
|
||||
width: 'w-screen max-w-md',
|
||||
height: 'h-screen max-h-96',
|
||||
translate: {
|
||||
base: 'translate-x-0',
|
||||
left: '-translate-x-full rtl:translate-x-full',
|
||||
right: 'translate-x-full rtl:-translate-x-full'
|
||||
right: 'translate-x-full rtl:-translate-x-full',
|
||||
top: '-translate-y-full',
|
||||
bottom: 'translate-y-full'
|
||||
},
|
||||
// Syntax for `<TransitionRoot>` component https://headlessui.com/vue/transition#basic-example
|
||||
transition: {
|
||||
|
||||
Reference in New Issue
Block a user