Compare commits

..

22 Commits

Author SHA1 Message Date
HugoRCD
266e870e67 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-05-11 19:21:02 +02:00
HugoRCD
322a6f467a Merge remote-tracking branch 'origin/v3' into fix/3952 2025-05-07 10:38:04 +02:00
HugoRCD
0c1417b6b1 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-05-05 21:59:21 +02:00
HugoRCD
7c4329ded7 Merge branch 'v3' into fix/3952 2025-05-02 10:16:44 +02:00
HugoRCD
adf11f4326 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-04-29 21:25:30 +02:00
Hugo Richard
b507f69b87 Merge branch 'v3' into fix/3952 2025-04-29 15:27:11 +02:00
HugoRCD
67bcb496a9 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-04-29 14:34:56 +02:00
Benjamin Canac
4104cd993b Revert "fix(InputMenu/Select/SelectMenu): add min-w-fit to content slot (#4010)"
This reverts commit 0f2d2e5d03.
2025-04-29 12:59:43 +02:00
Alain Limoges
e8d493a00e docs(form-field/switch): fix typo (#4015) 2025-04-29 12:18:45 +02:00
Hannes Küttner
0f2d2e5d03 fix(InputMenu/Select/SelectMenu): add min-w-fit to content slot (#4010) 2025-04-28 15:13:02 +02:00
renovate[bot]
4d17989302 chore(deps): update all non-major dependencies (v3) (#4002)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 15:02:25 +02:00
Benjamin Canac
eb7607749d fix(module): define default shades for named tailwindcss colors
Resolves #3977
2025-04-28 12:40:03 +02:00
Benjamin Canac
c0347f6e06 fix(defineShortcuts): bring back meta to ctrl convert on non macos platforms
Resolves #3869, resolves #3318

Co-Authored-By: Sylvain Marroufin <marroufin.sylvain@gmail.com>
2025-04-28 12:40:03 +02:00
Daniel Roe
6366118709 fix(module): support nuxt-nightly (#3996) 2025-04-28 10:43:22 +02:00
Eugen Istoc
9f7f5910ee feat(useOverlay): add closeAll method (#3984) 2025-04-25 15:04:03 +02:00
Hugo Richard
996573f26d Merge branch 'v3' into fix/3952 2025-04-25 12:15:53 +02:00
Benjamin Canac
88ff542e63 fix(templates): add missing border-bg / divide-bg utilities 2025-04-25 11:52:42 +02:00
HugoRCD
1a119e6279 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-04-25 10:45:30 +02:00
HugoRCD
776aef6e7f improve code reusability 2025-04-25 10:45:26 +02:00
HugoRCD
8284d05529 Merge remote-tracking branch 'origin/v3' into fix/3952 2025-04-24 16:53:59 +02:00
HugoRCD
713e943144 remove log 2025-04-24 16:30:46 +02:00
HugoRCD
505c1e502a fix(vue): make theme reactive 2025-04-24 16:09:38 +02:00
109 changed files with 3834 additions and 4741 deletions

View File

@@ -1,46 +1,5 @@
# Changelog
## [3.1.2](https://github.com/nuxt/ui/compare/v3.1.1...v3.1.2) (2025-05-15)
### Features
* **Badge:** add `square` prop ([#4008](https://github.com/nuxt/ui/issues/4008)) ([894e8a6](https://github.com/nuxt/ui/commit/894e8a61b6fea3618fc863bd77678385e9d021c2))
* **CheckboxGroup:** add `table` variant ([#3997](https://github.com/nuxt/ui/issues/3997)) ([1b6ab27](https://github.com/nuxt/ui/commit/1b6ab271ea3875a7c77ffe9367c7c341083dd53c))
* **components:** add `ui` field in items ([#4060](https://github.com/nuxt/ui/issues/4060)) ([b9adc83](https://github.com/nuxt/ui/commit/b9adc83e787db02507e6e7bb1aabc684eccc197b))
* **InputNumber:** add `increment-disabled` / `decrement-disabled` props ([#4141](https://github.com/nuxt/ui/issues/4141)) ([c7fba2e](https://github.com/nuxt/ui/commit/c7fba2e0ebfb7153f3bfb727165d653bbd3dbe54))
* **locale:** add Slovenian language ([#4140](https://github.com/nuxt/ui/issues/4140)) ([e86dc79](https://github.com/nuxt/ui/commit/e86dc79e51b2773a77ada5f12d4f0964fbc83354))
* **NavigationMenu:** add `collapsible` field in items ([2be60cd](https://github.com/nuxt/ui/commit/2be60cddfe10fd1e2466900fd53e21ee0c877227)), closes [#3353](https://github.com/nuxt/ui/issues/3353) [#3911](https://github.com/nuxt/ui/issues/3911)
* **NavigationMenu:** handle `tooltip` in items ([46c2987](https://github.com/nuxt/ui/commit/46c2987ebfd30b2b071a96a745b7270e852e96de)), closes [#4050](https://github.com/nuxt/ui/issues/4050)
* **Slider:** handle `tooltip` around thumbs ([d140acc](https://github.com/nuxt/ui/commit/d140acc608c6ae11c0a0531fe443588776ea7807)), closes [#1469](https://github.com/nuxt/ui/issues/1469)
* **Toast:** add `progress` prop to hide progress bar ([#4125](https://github.com/nuxt/ui/issues/4125)) ([92632e9](https://github.com/nuxt/ui/commit/92632e969eaa11521a166e50e346753929b7f523))
### Bug Fixes
* **Badge/Button:** handle zero value in label correctly ([#4108](https://github.com/nuxt/ui/issues/4108)) ([f244d15](https://github.com/nuxt/ui/commit/f244d15b96d97cd8ba34ba9c18f23965e17e3cef))
* **ButtonGroup:** add `z-index` on focused element ([204953b](https://github.com/nuxt/ui/commit/204953b780bde08dbfde230fc8887674449227b7))
* **Calendar:** wrong color for today date with `neutral` color ([7d51a9e](https://github.com/nuxt/ui/commit/7d51a9e479cb6105ea37759c5cd67ff9f7702c49)), closes [#4084](https://github.com/nuxt/ui/issues/4084) [#3629](https://github.com/nuxt/ui/issues/3629)
* **Checkbox/RadioGroup:** render correct element without `variant` ([f2fd778](https://github.com/nuxt/ui/commit/f2fd778c0a604f2d65aec9f3fe2d54b6d4e8c3a2)), closes [#3998](https://github.com/nuxt/ui/issues/3998)
* **CheckboxGroup:** relative `UCheckbox` import ([7551a85](https://github.com/nuxt/ui/commit/7551a85ad2d92b59e2909396affb862403d5b27a)), closes [#4090](https://github.com/nuxt/ui/issues/4090)
* **ColorPicker:** make thumb touch draggable ([#4101](https://github.com/nuxt/ui/issues/4101)) ([cc20a26](https://github.com/nuxt/ui/commit/cc20a26f07268d19119ab4c7c254033143bb63f4))
* **components:** `class` should have priority over `ui` prop ([e6e510b](https://github.com/nuxt/ui/commit/e6e510b848d995a286a51d50a120d67483e11232))
* **FormField:** block form field injection after use ([#4150](https://github.com/nuxt/ui/issues/4150)) ([d79da9d](https://github.com/nuxt/ui/commit/d79da9d7b60c9972af64acd8e6eef4ae7d6bc3eb))
* **FormField:** use `div` for `error` and `help` slots ([459a041](https://github.com/nuxt/ui/commit/459a0410ab729fde60865e84632b36903465f57e))
* **inertia:** link always render as anchor tag ([#3989](https://github.com/nuxt/ui/issues/3989)) ([e81464a](https://github.com/nuxt/ui/commit/e81464a43ede4e63ce3dc92429bbfef48614f731))
* **inertia:** make `useAppConfig` reactive ([12303a8](https://github.com/nuxt/ui/commit/12303a87be62dae84ef774e3a9795deb0ac90cc7))
* **Input/Textarea:** handle generic types ([3c8d6cd](https://github.com/nuxt/ui/commit/3c8d6cd01dfafed5844c376f52adbdda0c814420)), closes [nuxt/ui-pro#887](https://github.com/nuxt/ui-pro/issues/887)
* **InputNumber:** handle inside button group ([2e4c308](https://github.com/nuxt/ui/commit/2e4c3082a1e66fa597086dc3431fec37fa29ef62)), closes [#4155](https://github.com/nuxt/ui/issues/4155)
* **Link:** consistent behavior between nuxt, vue and inertia ([#4134](https://github.com/nuxt/ui/issues/4134)) ([67da90a](https://github.com/nuxt/ui/commit/67da90a2f638124f640c4271d3376c5ff3fab6a1))
* **module:** configure `@nuxt/fonts` with default weights ([276268d](https://github.com/nuxt/ui/commit/276268d311f57715cec47bc600a0ccc3d3885682))
* **NavigationMenu:** arrow position conflict ([#4137](https://github.com/nuxt/ui/issues/4137)) ([0dc4678](https://github.com/nuxt/ui/commit/0dc4678c68e4b500be49c38336dc75b73843e38d))
* **Select:** support more primitive types in `value` field ([#4105](https://github.com/nuxt/ui/issues/4105)) ([09b4699](https://github.com/nuxt/ui/commit/09b4699aeadaa195ea081509f8e237bb2c346238))
* **Slider:** handle generic types ([d7a4d02](https://github.com/nuxt/ui/commit/d7a4d029b77d2dfa0b8efcd2755d482fa5e31fd3))
* **Stepper:** use `div` tag for `title` & `description` ([a57844e](https://github.com/nuxt/ui/commit/a57844e41676c13ed1af861424961b88cee7b4da)), closes [#4096](https://github.com/nuxt/ui/issues/4096)
* **Tabs:** prevent trigger truncate without parent width ([06e5689](https://github.com/nuxt/ui/commit/06e5689da80b36205d0548d5d6b58510938e4a6e)), closes [#4056](https://github.com/nuxt/ui/issues/4056)
* **Tabs:** set `focus:outline-none` with `link` variant ([999a0f8](https://github.com/nuxt/ui/commit/999a0f84671fad20fa3dc50c6774af2e0200b32e))
* **templates:** dont write unused variants in theme files ([d3df3bb](https://github.com/nuxt/ui/commit/d3df3bb929fe6732f27b182d1664213884a662ec))
* **Toaster:** allow `base` slot override ([c63d2f3](https://github.com/nuxt/ui/commit/c63d2f380aac16f1d1e812516df3dca7fa7c8034))
* **vue:** make `useAppConfig` reactive ([869c070](https://github.com/nuxt/ui/commit/869c0708bd351c7be44e5e430c348b19dd316db9)), closes [#3952](https://github.com/nuxt/ui/issues/3952)
## [3.1.1](https://github.com/nuxt/ui/compare/v3.1.0...v3.1.1) (2025-05-02)
### Features

View File

@@ -12,6 +12,7 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
})
const links = useLinks()
const searchLinks = useSearchLinks()
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
@@ -41,6 +42,7 @@ useServerSeoMeta({
useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
provide('navigation', mappedNavigation)
@@ -51,7 +53,7 @@ provide('navigation', mappedNavigation)
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
<template v-if="!route.path.startsWith('/examples')">
<!-- <Banner /> -->
<Banner />
<Header :links="links" />
</template>
@@ -63,7 +65,23 @@ provide('navigation', mappedNavigation)
<template v-if="!route.path.startsWith('/examples')">
<Footer />
<Search :files="files" :navigation="filteredNavigation" />
<ClientOnly>
<LazyUContentSearch
:links="searchLinks"
:files="files"
:groups="[{
id: 'framework',
label: 'Framework',
items: frameworks
}, {
id: 'module',
label: 'Module',
items: modules
}]"
:navigation="filteredNavigation"
:fuse="{ resultLimit: 100 }"
/>
</ClientOnly>
</template>
</UApp>
</template>

View File

@@ -1,199 +0,0 @@
<script setup lang="ts">
import type { DefineComponent } from 'vue'
import type { ContentNavigationItem } from '@nuxt/content'
import { useChat } from '@ai-sdk/vue'
import ProseStreamPre from './prose/PreStream.vue'
const components = {
pre: ProseStreamPre as unknown as DefineComponent
}
interface ContentSearchFile {
id: string
title: string
titles: string[]
level: number
content: string
}
defineProps<{
files?: ContentSearchFile[]
navigation?: ContentNavigationItem[]
}>()
const { frameworks, modules } = useSharedData()
const { messages, input, handleSubmit, status, error, reload, setMessages } = useChat({
maxSteps: 2
})
const ai = ref(false)
const searchTerm = ref('')
const links = computed(() => [{
label: 'Ask AI',
icon: 'i-lucide-bot',
onSelect: (e: any) => {
e.preventDefault()
ai.value = true
}
}, {
label: 'Docs',
icon: 'i-lucide-square-play',
to: '/getting-started'
}, {
label: 'Components',
icon: 'i-lucide-square-code',
to: '/components'
}, {
icon: 'i-lucide-sparkles',
label: 'Pro > Features',
description: 'A collection of premium Vue components.',
to: '/pro'
}, {
icon: 'i-lucide-credit-card',
label: 'Pro > Pricing',
description: 'Free in development, buy when ready to launch.',
to: '/pro/pricing'
}, {
icon: 'i-lucide-panels-top-left',
label: 'Pro > Templates',
description: 'Official templates made with Nuxt UI Pro.',
to: '/pro/templates'
}, {
icon: 'i-lucide-circle-check',
label: 'Pro > Activate',
description: 'Enable Nuxt UI Pro in your production projects.',
to: '/pro/activate'
}, {
label: 'Figma',
icon: 'i-simple-icons-figma',
to: '/figma'
}, {
icon: 'i-lucide-presentation',
label: 'Community > Showcase',
description: 'Check out some of the amazing projects built with Nuxt UI.',
to: '/showcase'
}, {
label: 'Community > Contribution',
description: 'A comprehensive guide on contributing to Nuxt UI, including project structure, development workflow, and best practices.',
icon: 'i-lucide-git-pull-request-arrow',
to: '/getting-started/contribution'
}, {
label: 'Community > Roadmap',
description: 'Track our development progress in real-time.',
icon: 'i-lucide-map',
to: '/roadmap'
}, {
label: 'Community > Devtools',
description: 'Integrate Nuxt UI with Nuxt Devtools with Compodium.',
icon: 'i-lucide-code',
to: 'https://github.com/romhml/compodium',
target: '_blank'
}, {
label: 'Community > Team',
description: 'Meet the team behind Nuxt UI.',
icon: 'i-lucide-users',
to: '/team'
}, {
label: 'Releases',
icon: 'i-lucide-rocket',
to: 'https://github.com/nuxt/ui/releases',
target: '_blank'
}])
const groups = computed(() => [{
id: 'ai',
label: 'AI',
ignoreFilter: true,
items: [{
label: searchTerm.value ? `Ask Nuxt AI for “${searchTerm.value}` : 'Ask Nuxt AI',
icon: 'i-lucide-bot',
onSelect: (e: any) => {
e.preventDefault()
ai.value = true
if (searchTerm.value) {
setMessages([{
id: '1',
role: 'user',
content: searchTerm.value
}])
reload()
}
}
}]
}, {
id: 'framework',
label: 'Framework',
items: frameworks.value
}, {
id: 'module',
label: 'Module',
items: modules.value
}])
function onClose(e: Event) {
console.log('onClose')
e.preventDefault()
ai.value = false
}
</script>
<template>
<LazyUContentSearch
v-model:search-term="searchTerm"
:links="links"
:files="files"
:groups="groups"
:navigation="navigation"
:fuse="{ resultLimit: 100 }"
>
<template v-if="ai" #content>
<UChatPalette>
<UChatMessages
:messages="messages"
:status="status"
:user="{ side: 'left', variant: 'naked', icon: 'i-lucide-user' }"
:assistant="{ icon: 'i-lucide-bot' }"
>
<template #content="{ message }">
<MDCCached
v-if="message.toolInvocations?.[0]?.state === 'result'"
:value="message.toolInvocations?.[0]?.result"
:cache-key="message.id"
unwrap="p"
:components="components"
:parser-options="{ highlight: false }"
/>
<MDCCached
v-else-if="message.content.length > 0"
:value="message.content"
:cache-key="message.id"
unwrap="p"
:components="components"
:parser-options="{ highlight: false }"
/>
<span v-else class="italic font-light">
Searching documentation...
</span>
</template>
</UChatMessages>
<template #prompt>
<UChatPrompt
v-model="input"
icon="i-lucide-search"
variant="naked"
:error="error"
@submit="handleSubmit"
@close="onClose"
/>
</template>
</UChatPalette>
</template>
</LazyUContentSearch>
</template>

View File

@@ -38,7 +38,7 @@ const schemaProps = computed(() => {
</script>
<template>
<ProseCollapsible v-if="schemaProps?.length" class="mt-1 mb-0">
<ProseCollapsible v-if="schemaProps?.length" class="mt-1">
<ProseUl>
<ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name">
<HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" />

View File

@@ -26,7 +26,6 @@ function getEmojiFlag(locale: string): string {
km: 'kh', // Khmer -> Cambodia
ko: 'kr', // Korean -> South Korea
nb: 'no', // Norwegian Bokmål -> Norway
sl: 'si', // Slovenian -> Slovenia
sv: 'se', // Swedish -> Sweden
uk: 'ua', // Ukrainian -> Ukraine
ur: 'pk', // Urdu -> Pakistan

View File

@@ -1,44 +0,0 @@
<script setup lang="ts">
import { ShikiCachedRenderer } from 'shiki-stream/vue'
const colorMode = useColorMode()
const highlighter = await useHighlighter()
const props = defineProps<{
code: string
language: string
class?: string
meta?: string
}>()
const trimmedCode = computed(() => {
return props.code.trim().replace(/`+$/, '')
})
const lang = computed(() => {
switch (props.language) {
case 'vue':
return 'vue'
case 'javascript':
return 'js'
case 'typescript':
return 'ts'
case 'css':
return 'css'
default:
return props.language
}
})
const key = computed(() => {
return `${lang.value}-${colorMode.value}`
})
</script>
<template>
<ProsePre v-bind="props">
<ShikiCachedRenderer
:key="key"
:highlighter="highlighter"
:code="trimmedCode"
:lang="lang"
:theme="colorMode.value === 'dark' ? 'material-theme-palenight' : 'material-theme-lighter'"
/>
</ProsePre>
</template>

View File

@@ -1,21 +0,0 @@
import { createHighlighter, type HighlighterGeneric } from 'shiki'
import { createJavaScriptRegexEngine } from 'shiki/engine-javascript.mjs'
let highlighter: HighlighterGeneric<any, any> | null = null
let promise: Promise<HighlighterGeneric<any, any>> | null = null
export const useHighlighter = async () => {
if (!promise) {
promise = createHighlighter({
langs: ['vue', 'js', 'ts', 'css', 'html', 'json', 'yaml', 'markdown', 'bash'],
themes: ['material-theme-palenight', 'material-theme-lighter'],
engine: createJavaScriptRegexEngine()
})
}
if (!highlighter) {
highlighter = await promise
}
return highlighter
}

View File

@@ -0,0 +1,66 @@
export function useSearchLinks() {
return [{
label: 'Docs',
icon: 'i-lucide-square-play',
to: '/getting-started'
}, {
label: 'Components',
icon: 'i-lucide-square-code',
to: '/components'
}, {
icon: 'i-lucide-sparkles',
label: 'Pro > Features',
description: 'A collection of premium Vue components.',
to: '/pro'
}, {
icon: 'i-lucide-credit-card',
label: 'Pro > Pricing',
description: 'Free in development, buy when ready to launch.',
to: '/pro/pricing'
}, {
icon: 'i-lucide-panels-top-left',
label: 'Pro > Templates',
description: 'Official templates made with Nuxt UI Pro.',
to: '/pro/templates'
}, {
icon: 'i-lucide-circle-check',
label: 'Pro > Activate',
description: 'Enable Nuxt UI Pro in your production projects.',
to: '/pro/activate'
}, {
label: 'Figma',
icon: 'i-simple-icons-figma',
to: '/figma'
}, {
icon: 'i-lucide-presentation',
label: 'Community > Showcase',
description: 'Check out some of the amazing projects built with Nuxt UI.',
to: '/showcase'
}, {
label: 'Community > Contribution',
description: 'A comprehensive guide on contributing to Nuxt UI, including project structure, development workflow, and best practices.',
icon: 'i-lucide-git-pull-request-arrow',
to: '/getting-started/contribution'
}, {
label: 'Community > Roadmap',
description: 'Track our development progress in real-time.',
icon: 'i-lucide-map',
to: '/roadmap'
}, {
label: 'Community > Devtools',
description: 'Integrate Nuxt UI with Nuxt Devtools with Compodium.',
icon: 'i-lucide-code',
to: 'https://github.com/romhml/compodium',
target: '_blank'
}, {
label: 'Community > Team',
description: 'Meet the team behind Nuxt UI.',
icon: 'i-lucide-users',
to: '/team'
}, {
label: 'Releases',
icon: 'i-lucide-rocket',
to: 'https://github.com/nuxt/ui/releases',
target: '_blank'
}]
}

View File

@@ -15,6 +15,7 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
})
const links = useLinks()
const searchLinks = useSearchLinks()
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
@@ -48,6 +49,7 @@ useServerSeoMeta({
useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
provide('navigation', mappedNavigation)
@@ -57,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp>
<NuxtLoadingIndicator color="#FFF" />
<!-- <Banner /> -->
<Banner />
<Header :links="links" />
@@ -65,6 +67,22 @@ provide('navigation', mappedNavigation)
<Footer />
<Search :files="files" :navigation="filteredNavigation" />
<ClientOnly>
<LazyUContentSearch
:links="searchLinks"
:files="files"
:groups="[{
id: 'framework',
label: 'Framework',
items: frameworks
}, {
id: 'module',
label: 'Module',
items: modules
}]"
:navigation="filteredNavigation"
:fuse="{ resultLimit: 100 }"
/>
</ClientOnly>
</UApp>
</template>

View File

@@ -65,17 +65,13 @@ if (!import.meta.prerender) {
})
}
const title = page.value?.navigation?.title ? page.value.navigation.title : page.value?.title
const prefix = page.value?.path.includes('components') || page.value?.path.includes('composables') ? 'Vue ' : ''
const suffix = page.value?.path.includes('components') ? 'Component ' : page.value?.path.includes('composables') ? 'Composable ' : ''
const description = page.value?.description
const type = page.value?.path.includes('components') ? 'Vue Component ' : page.value?.path.includes('composables') ? 'Vue Composable ' : ''
useSeoMeta({
titleTemplate: `${prefix}%s ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`,
title,
ogTitle: `${prefix}${title} ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`,
description,
ogDescription: description
titleTemplate: `%s ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
title: page.value.navigation?.title ? page.value.navigation.title : page.value.title,
ogTitle: `${page.value.navigation?.title ? page.value.navigation.title : page.value.title} ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
description: page.value.description,
ogDescription: page.value.description
})
if (route.path.startsWith('/components')) {

View File

@@ -1,20 +1,8 @@
<script setup lang="ts">
const route = useRoute()
const colorMode = useColorMode()
const appConfig = useAppConfig()
const name = route.params.slug?.[0]
if (route.query.theme) {
colorMode.preference = route.query.theme === 'light' ? 'light' : 'dark'
}
if (route.query.neutral) {
appConfig.ui.colors.neutral = route.query.neutral as string
}
if (route.query.primary) {
appConfig.ui.colors.primary = route.query.primary as string
}
const width = computed(() => route.query.width && Number.parseInt(route.query.width as string) > 0 ? `${Number.parseInt(route.query.width as string) - 2}px` : '864px')
</script>

View File

@@ -24,41 +24,32 @@ onMounted(async () => {
const nuxtWordPosition = document.querySelector('#nuxt')?.getBoundingClientRect()
const initialScrollX = window.scrollX
const initialScrollY = window.scrollY
if (figmaWordPosition && nuxtWordPosition) {
const cursor1Sequence = async () => {
await animate('#cursor1', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1 }).finished
await animate('#cursor1', { opacity: 1 }, { duration: 0.3 }).finished
await animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width / 2),
top: Math.round(figmaWordPosition.top + initialScrollY - figmaWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
await animate('#cursor1', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#cursor1', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#figma', { color: 'var(--ui-info)' }, { duration: 0.3, ease: 'easeOut' }).finished
await animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width),
top: Math.round(figmaWordPosition.top + initialScrollY)
}, { duration: 0.6, ease: 'easeInOut' }).finished
}
animate('#cursor1', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1 })
.then(() => animate('#cursor1', { opacity: 1 }, { duration: 0.3 }))
.then(() => {
return animate('#cursor1', {
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width / 2),
top: Math.round(figmaWordPosition.top + initialScrollY - figmaWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' })
})
.then(() => animate('#cursor1', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#cursor1', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#figma', { color: 'var(--ui-info)' }, { duration: 0.3, ease: 'easeOut' }))
.then(() => animate('#cursor1', { left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width), top: Math.round(figmaWordPosition.top + initialScrollY) }, { duration: 0.6, ease: 'easeInOut' }))
const cursor2Sequence = async () => {
await animate('#cursor2', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1, delay: 0.6 }).finished
await animate('#cursor2', { opacity: 1 }, { duration: 0.3 }).finished
await animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width / 2),
top: Math.round(nuxtWordPosition.top + initialScrollY - nuxtWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
await animate('#cursor2', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#cursor2', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
await animate('#nuxt', { color: 'var(--ui-success)' }, { duration: 0.3, ease: 'easeOut' }).finished
await animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width),
top: Math.round(nuxtWordPosition.top + initialScrollY)
}, { duration: 0.6, ease: 'easeInOut' }).finished
}
await Promise.all([cursor1Sequence(), cursor2Sequence()])
animate('#cursor2', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1, delay: 0.6 })
.then(() => animate('#cursor2', { opacity: 1 }, { duration: 0.3 }))
.then(() => {
return animate('#cursor2', {
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width / 2),
top: Math.round(nuxtWordPosition.top + initialScrollY - nuxtWordPosition.height / 4)
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' })
})
.then(() => animate('#cursor2', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#cursor2', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }))
.then(() => animate('#nuxt', { color: 'var(--ui-success)' }, { duration: 0.3, ease: 'easeOut' }))
.then(() => animate('#cursor2', { left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width), top: Math.round(nuxtWordPosition.top + initialScrollY) }, { duration: 0.6, ease: 'easeInOut' }))
}
})
</script>

View File

@@ -67,6 +67,17 @@ defineOgImageComponent('Docs', {
</li>
</ul>
</div>
<div class="flex justify-center -mb-[36px]">
<UButton
label="Submit your project"
trailing-icon="i-lucide-plus"
color="neutral"
size="lg"
to="https://github.com/nuxt/ui/edit/v3/docs/content/showcase.yml"
target="_blank"
/>
</div>
</UPageHero>
</UMain>
</template>

View File

@@ -229,10 +229,6 @@ export default defineConfig({
::
::caution
When configuring your theme colors, you must use either color names from the [default Tailwind palette](https://tailwindcss.com/docs/colors) (like 'blue', 'green', etc.) or reference custom colors that you've previously defined in your [CSS file](#theme).
::
### Extend colors
::framework-only

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, header?: ClassNameValue, trigger?: ClassNameValue, leadingIcon?: ClassNameValue, label?: ClassNameValue, trailingIcon?: ClassNameValue, content?: ClassNameValue, body?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -16,9 +16,8 @@ Use the `items` prop as an array of objects with the following properties:
- `label?: string`{lang="ts-type"}
- `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLabel?: ClassNameValue, separator?: ClassNameValue, separatorIcon?: ClassNameValue }`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -27,11 +27,6 @@ class: 'p-8'
---
::
You can also pass an array of objects with the following properties:
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue }`{lang="ts-type"}
You can control how many items are visible by using the [`basis`](https://tailwindcss.com/docs/flex-basis) / [`width`](https://tailwindcss.com/docs/width) utility classes on the `item`:
::component-example

View File

@@ -49,8 +49,6 @@ You can also pass an array of objects with the following properties:
- `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, icon?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---
@@ -201,7 +199,6 @@ items:
variant:
- list
- card
- table
props:
color: 'primary'
variant: 'card'
@@ -232,7 +229,6 @@ items:
variant:
- list
- card
- table
props:
size: 'xl'
variant: 'list'
@@ -263,7 +259,6 @@ items:
variant:
- list
- card
- table
props:
orientation: 'horizontal'
variant: 'list'
@@ -298,7 +293,6 @@ items:
variant:
- list
- card
- table
props:
indicator: 'end'
variant: 'card'

View File

@@ -53,8 +53,6 @@ Each group contains an `items` array of objects that define the commands. Each i
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e?: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelPrefix?: ClassNameValue, itemLabelBase?: ClassNameValue, itemLabelSuffix?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue, itemTrailingHighlightedIcon?: ClassNameValue, itemTrailingIcon?: ClassNameValue,}`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -28,12 +28,11 @@ Use the `items` prop as an array of objects with the following properties:
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -28,12 +28,11 @@ Use the `items` prop as an array of objects with the following properties:
- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLabel?: ClassNameValue, itemLabelExternalIcon?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue, itemTrailingKbds?: ClassNameValue, itemTrailingKbdsSize?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.

View File

@@ -55,8 +55,6 @@ You can also pass an array of objects with the following properties:
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { tagsItem?: ClassNameValue, tagsItemText?: ClassNameValue, tagsItemDelete?: ClassNameValue, tagsItemDeleteIcon?: ClassNameValue, label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -29,11 +29,10 @@ Use the `items` prop as an array of objects with the following properties:
- `open?: boolean`{lang="ts-type"}
- `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"}
- `children?: NavigationMenuChildItem[]`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { linkLeadingAvatarSize?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkLabelExternalIcon?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingBadgeSize?: ClassNameValue, linkTrailingBadge?: ClassNameValue, linkTrailingIcon?: ClassNameValue, label?: ClassNameValue, link?: ClassNameValue, content?: ClassNameValue, childList?: ClassNameValue, childItem?: ClassNameValue, childLink?: ClassNameValue, childLinkIcon?: ClassNameValue, childLinkWrapper?: ClassNameValue, childLinkLabel?: ClassNameValue, childLinkLabelExternalIcon?: ClassNameValue, childLinkDescription?: ClassNameValue }`{lang="ts-type"}
You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc.
@@ -135,8 +134,8 @@ Each item can take a `children` array of objects with the following properties t
- `label: string`
- `description?: string`
- `icon?: string`
- `onSelect?(e: Event): void`
- `class?: any`
- `onSelect?(e: Event): void`
::
@@ -145,7 +144,7 @@ Each item can take a `children` array of objects with the following properties t
Use the `orientation` prop to change the orientation of the NavigationMenu.
::note
When orientation is `vertical`, a [Collapsible](/components/collapsible) component is used to display children. You can control the open state of each item using the `open` and `defaultOpen` properties.
When orientation is `vertical`, a [Collapsible](/components/collapsible) component is used to display children. You can control the open state of each item using the `open` and `defaultOpen` properties. You can also use the `collapsible` property to control if the item is collapsible.
::
::component-code
@@ -242,108 +241,6 @@ props:
Groups will be spaced when orientation is `horizontal` and separated when orientation is `vertical`.
::
### Collapsed
Use the `collapsed` prop to collapse the NavigationMenu, this can be useful in a sidebar for example.
::component-code
---
collapse: true
ignore:
- items
- orientation
- class
external:
- items
externalTypes:
- NavigationMenuItem[][]
props:
collapsed: true
orientation: 'vertical'
items:
- - label: Links
type: 'label'
- label: Guide
icon: i-lucide-book-open
children:
- label: Introduction
description: Fully styled and customizable components for Nuxt.
icon: i-lucide-house
- label: Installation
description: Learn how to install and configure Nuxt UI in your application.
icon: i-lucide-cloud-download
- label: 'Icons'
icon: 'i-lucide-smile'
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
- label: 'Colors'
icon: 'i-lucide-swatch-book'
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
- label: 'Theme'
icon: 'i-lucide-cog'
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
- label: Composables
icon: i-lucide-database
collapsible: false
open: false
children:
- label: defineShortcuts
icon: i-lucide-file-text
description: Define shortcuts for your application.
to: /composables/define-shortcuts
- label: useOverlay
icon: i-lucide-file-text
description: Display a modal/slideover within your application.
to: /composables/use-overlay
- label: useToast
icon: i-lucide-file-text
description: Display a toast within your application.
to: /composables/use-toast
- label: Components
icon: i-lucide-box
collapsible: false
open: false
to: /components
active: true
children:
- label: Link
icon: i-lucide-file-text
description: Use NuxtLink with superpowers.
to: /components/link
- label: Modal
icon: i-lucide-file-text
description: Display a modal within your application.
to: /components/modal
- label: NavigationMenu
icon: i-lucide-file-text
description: Display a list of links.
to: /components/navigation-menu
- label: Pagination
icon: i-lucide-file-text
description: Display a list of pages.
to: /components/pagination
- label: Popover
icon: i-lucide-file-text
description: Display a non-modal dialog that floats around a trigger element.
to: /components/popover
- label: Progress
icon: i-lucide-file-text
description: Show a horizontal bar to indicate task progression.
to: /components/progress
- - label: GitHub
icon: i-simple-icons-github
badge: 3.8k
to: https://github.com/nuxt/ui
target: _blank
- label: Help
icon: i-lucide-circle-help
disabled: true
---
::
::tip
You can set the `collapsible: false` property on items with children to prevent them from being collapsible. This allows the item to act as a regular link while still displaying its children in a submenu.
::
### Highlight
Use the `highlight` prop to display a highlighted border for the active item.
@@ -885,126 +782,6 @@ You can inspect the DOM to see each item's content being rendered.
## Examples
### With tooltips in items :badge{label="New" class="align-text-top"}
You can use the `tooltip` property to display a [Tooltip](/components/tooltip) around an item. This can be useful when the menu is collapsed.
::component-code
---
collapse: true
ignore:
- items
- orientation
- class
external:
- items
externalTypes:
- NavigationMenuItem[][]
props:
collapsed: true
orientation: 'vertical'
items:
- - label: Links
type: 'label'
- label: Guide
icon: i-lucide-book-open
tooltip:
text: 'Guide'
children:
- label: Introduction
description: Fully styled and customizable components for Nuxt.
icon: i-lucide-house
tooltip:
text: 'Introduction'
- label: Installation
description: Learn how to install and configure Nuxt UI in your application.
icon: i-lucide-cloud-download
tooltip:
text: 'Installation'
- label: 'Icons'
icon: 'i-lucide-smile'
description: 'You have nothing to do, @nuxt/icon will handle it automatically.'
tooltip:
text: 'Icons'
- label: 'Colors'
icon: 'i-lucide-swatch-book'
description: 'Choose a primary and a neutral color from your Tailwind CSS theme.'
tooltip:
text: 'Colors'
- label: 'Theme'
icon: 'i-lucide-cog'
description: 'You can customize components by using the `class` / `ui` props or in your app.config.ts.'
tooltip:
text: 'Theme'
- label: Composables
icon: i-lucide-database
tooltip:
text: 'Composables'
collapsible: false
open: false
children:
- label: defineShortcuts
icon: i-lucide-file-text
description: Define shortcuts for your application.
to: /composables/define-shortcuts
- label: useOverlay
icon: i-lucide-file-text
description: Display a modal/slideover within your application.
to: /composables/use-overlay
- label: useToast
icon: i-lucide-file-text
description: Display a toast within your application.
to: /composables/use-toast
- label: Components
icon: i-lucide-box
tooltip:
text: 'Components'
to: /components
active: true
collapsible: false
open: false
children:
- label: Link
icon: i-lucide-file-text
description: Use NuxtLink with superpowers.
to: /components/link
- label: Modal
icon: i-lucide-file-text
description: Display a modal within your application.
to: /components/modal
- label: NavigationMenu
icon: i-lucide-file-text
description: Display a list of links.
to: /components/navigation-menu
- label: Pagination
icon: i-lucide-file-text
description: Display a list of pages.
to: /components/pagination
- label: Popover
icon: i-lucide-file-text
description: Display a non-modal dialog that floats around a trigger element.
to: /components/popover
- label: Progress
icon: i-lucide-file-text
description: Show a horizontal bar to indicate task progression.
to: /components/progress
- - label: GitHub
icon: i-simple-icons-github
badge: 3.8k
to: https://github.com/nuxt/ui
target: _blank
tooltip:
text: 'GitHub'
kbds:
- 3.8k
- label: Help
icon: i-lucide-circle-help
disabled: true
tooltip:
text: 'Help'
---
::
### Control active item
You can control the active item by using the `default-value` prop or the `v-model` directive with the index of the item.

View File

@@ -46,8 +46,6 @@ You can also pass an array of objects with the following properties:
- `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, base?: ClassNameValue, 'indicator'?: ClassNameValue, wrapper?: ClassNameValue, label?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -57,8 +57,6 @@ You can also pass an array of objects with the following properties:
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -48,8 +48,6 @@ You can also pass an array of objects with the following properties:
- [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { label?: ClassNameValue, separator?: ClassNameValue, item?: ClassNameValue, itemLeadingIcon?: ClassNameValue, itemLeadingAvatarSize?: ClassNameValue, itemLeadingAvatar?: ClassNameValue, itemLeadingChipSize?: ClassNameValue, itemLeadingChip?: ClassNameValue, itemLabel?: ClassNameValue, itemTrailing?: ClassNameValue, itemTrailingIcon?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -136,7 +136,7 @@ props:
---
::
### Tooltip :badge{label="New" class="align-text-top"}
### Tooltip :badge{label="Soon" class="align-text-top"}
Use the `tooltip` prop to display a [Tooltip](/components/tooltip) around the Slider thumbs with the current value. You can set it to `true` for default behavior or pass an object to customize it with any property from the [Tooltip](/components/tooltip#props) component.

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, container?: ClassNameValue, trigger?: ClassNameValue, indicator?: ClassNameValue, icon?: ClassNameValue, separator?: ClassNameValue, wrapper?: ClassNameValue, title?: ClassNameValue, description?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -23,8 +23,6 @@ Use the `items` prop as an array of objects with the following properties:
- `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"}
- `ui?: { trigger?: ClassNameValue, leadingIcon?: ClassNameValue, leadingAvatar?: ClassNameValue, label?: ClassNameValue, content?: ClassNameValue }`{lang="ts-type"}
::component-code
---

View File

@@ -26,8 +26,6 @@ Use the `items` prop as an array of objects with the following properties:
- `children?: TreeItem[]`{lang="ts-type"}
- `onToggle?(e: Event): void`{lang="ts-type"}
- `onSelect?(e?: Event): void`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- `ui?: { item?: ClassNameValue, itemWithChildren?: ClassNameValue, link?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkTrailing?: ClassNameValue, linkTrailingIcon?: ClassNameValue, listWithChildren?: ClassNameValue }`{lang="ts-type"}
::note
A unique identifier is required for each item. The component will use the `value` prop as identifier, falling back to `label` if `value` is not provided. One of these must be provided for the component to work properly.

View File

@@ -3,41 +3,40 @@
"name": "@nuxt/ui-docs",
"type": "module",
"dependencies": {
"@ai-sdk/vue": "^1.2.12",
"@ai-sdk/vue": "^1.2.11",
"@iconify-json/logos": "^1.2.4",
"@iconify-json/lucide": "^1.2.43",
"@iconify-json/simple-icons": "^1.2.34",
"@iconify-json/vscode-icons": "^1.2.21",
"@iconify-json/lucide": "^1.2.41",
"@iconify-json/simple-icons": "^1.2.33",
"@iconify-json/vscode-icons": "^1.2.20",
"@nuxt/content": "^3.5.1",
"@nuxt/image": "^1.10.0",
"@nuxt/ui": "latest",
"@nuxt/ui-pro": "^3.1.2",
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@a30de4d",
"@nuxthub/core": "^0.8.27",
"@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^21.1.1",
"@rollup/plugin-yaml": "^4.1.2",
"@vueuse/integrations": "^13.2.0",
"@vueuse/nuxt": "^13.2.0",
"@vueuse/integrations": "^13.1.0",
"@vueuse/nuxt": "^13.1.0",
"ai": "^4.3.15",
"capture-website": "^4.2.0",
"joi": "^17.13.3",
"motion-v": "^1.0.2",
"nuxt": "^3.17.3",
"nuxt": "^3.17.2",
"nuxt-component-meta": "^0.11.0",
"nuxt-llms": "^0.1.2",
"nuxt-og-image": "^5.1.3",
"prettier": "^3.5.3",
"shiki-stream": "^0.1.2",
"shiki-transformer-color-highlight": "^1.0.0",
"sortablejs": "^1.15.6",
"superstruct": "^2.0.2",
"ufo": "^1.6.1",
"valibot": "^1.1.0",
"workers-ai-provider": "^0.4.1",
"workers-ai-provider": "^0.3.1",
"yup": "^1.6.1",
"zod": "^3.24.4"
},
"devDependencies": {
"wrangler": "^4.15.1"
"wrangler": "^4.14.4"
}
}

View File

@@ -1,6 +1,5 @@
import { streamText, tool } from 'ai'
import { streamText } from 'ai'
import { createWorkersAI } from 'workers-ai-provider'
import { z } from 'zod'
export default defineEventHandler(async (event) => {
const { messages } = await readBody(event)
@@ -13,30 +12,11 @@ export default defineEventHandler(async (event) => {
}
: undefined
const workersAI = createWorkersAI({ binding: hubAI(), gateway })
const autorag = hubAutoRAG('ui3')
return streamText({
model: workersAI('@cf/meta/llama-3.3-70b-instruct-fp8-fast'),
messages,
system: `You are a helpful assistant for Nuxt UI. Check your knowledge base before answering any questions.
Only respond to questions using information from tool calls.
if no relevant information is found in the tool calls, respond, "Sorry, I don't know."
Format your markdown response using the following rules:
- Use the vue lang for code blocks syntax highlighting.
- Don't use markdown headings.
`,
tools: {
searchDocumentation: tool({
description: `search the documentation for information to answer questions.`,
parameters: z.object({
question: z.string().describe('the users question')
}),
execute: async ({ question }) => {
return (await autorag.aiSearch({
query: question
})).response
}
})
}
model: workersAI('@cf/meta/llama-3.2-3b-instruct'),
maxTokens: 10000,
system: 'You are a helpful assistant that can answer questions and help.',
messages
}).toDataStreamResponse()
})

View File

@@ -1,8 +1,8 @@
{
"name": "@nuxt/ui",
"description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
"version": "3.1.2",
"packageManager": "pnpm@10.11.0",
"version": "3.1.1",
"packageManager": "pnpm@10.10.0",
"repository": {
"type": "git",
"url": "git+https://github.com/nuxt/ui.git"
@@ -115,18 +115,18 @@
"@iconify/vue": "^4.3.0",
"@internationalized/date": "^3.8.0",
"@internationalized/number": "^3.6.1",
"@nuxt/fonts": "^0.11.4",
"@nuxt/fonts": "^0.11.2",
"@nuxt/icon": "^1.12.0",
"@nuxt/kit": "^3.17.3",
"@nuxt/schema": "^3.17.3",
"@nuxt/kit": "^3.17.2",
"@nuxt/schema": "^3.17.2",
"@nuxtjs/color-mode": "^3.5.2",
"@standard-schema/spec": "^1.0.0",
"@tailwindcss/postcss": "^4.1.6",
"@tailwindcss/vite": "^4.1.6",
"@tailwindcss/postcss": "^4.1.5",
"@tailwindcss/vite": "^4.1.5",
"@tanstack/vue-table": "^8.21.3",
"@unhead/vue": "^2.0.8",
"@vueuse/core": "^13.2.0",
"@vueuse/integrations": "^13.2.0",
"@vueuse/core": "^13.1.0",
"@vueuse/integrations": "^13.1.0",
"colortranslator": "^4.1.0",
"consola": "^3.4.2",
"defu": "^6.1.4",
@@ -147,24 +147,24 @@
"reka-ui": "^2.2.1",
"scule": "^1.3.0",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^4.1.6",
"tailwindcss": "^4.1.5",
"tinyglobby": "^0.2.13",
"unplugin": "^2.3.4",
"unplugin": "^2.3.2",
"unplugin-auto-import": "^19.2.0",
"unplugin-vue-components": "^28.5.0",
"vaul-vue": "^0.4.1",
"vue-component-type-helpers": "^2.2.10"
},
"devDependencies": {
"@nuxt/eslint-config": "^1.3.1",
"@nuxt/eslint-config": "^1.3.0",
"@nuxt/module-builder": "^1.0.1",
"@nuxt/test-utils": "^3.18.0",
"@release-it/conventional-changelog": "^10.0.1",
"@vue/test-utils": "^2.4.6",
"embla-carousel": "^8.6.0",
"eslint": "^9.26.0",
"happy-dom": "^17.4.7",
"nuxt": "^3.17.3",
"happy-dom": "^17.4.6",
"nuxt": "^3.17.2",
"release-it": "^19.0.2",
"vitest": "^3.1.3",
"vitest-environment-nuxt": "^1.0.1",
@@ -209,7 +209,7 @@
"debug": "4.3.7",
"rollup": "4.34.9",
"unimport": "4.1.1",
"unplugin": "^2.3.4"
"unplugin": "^2.3.2"
},
"pnpm": {
"onlyBuiltDependencies": [

View File

@@ -11,12 +11,12 @@
},
"dependencies": {
"@nuxt/ui": "latest",
"vue": "^3.5.14",
"vue": "^3.5.13",
"vue-router": "^4.5.1",
"zod": "^3.24.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.4",
"@vitejs/plugin-vue": "^5.2.3",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vue-tsc": "^2.2.10"

View File

@@ -36,27 +36,14 @@ const variants = Object.keys(theme.variants.variant) as Array<keyof typeof theme
color="neutral"
/>
</div>
<div class="flex items-center gap-2 ms-[-90px]">
<div class="flex items-center gap-2 ms-[-56px]">
<UBadge v-for="size in sizes" :key="size" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-122px]">
<div class="flex items-center gap-2 ms-[-86px]">
<UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-130px]">
<div class="flex items-center gap-2 ms-[-86px]">
<UBadge v-for="size in sizes" :key="size" :avatar="{ src: 'https://github.com/benjamincanac.png' }" label="Badge" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-52px]">
<UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" :size="size" />
</div>
<div class="flex items-center gap-2 ms-[-60px]">
<UBadge
v-for="size in sizes"
:key="size"
:avatar="{ src: 'https://github.com/benjamincanac.png' }"
:size="size"
color="neutral"
variant="outline"
/>
</div>
</div>
</template>

View File

@@ -1,8 +1,9 @@
<script setup lang="ts">
import themeCheckbox from '#build/ui/checkbox'
import theme from '#build/ui/checkbox-group'
const sizes = Object.keys(theme.variants.size) as Array<keyof typeof theme.variants.size>
const variants = Object.keys(theme.variants.variant)
const variants = Object.keys(themeCheckbox.variants.variant)
const variant = ref('list' as const)
const literalOptions = [

View File

@@ -9,11 +9,11 @@
"typecheck": "nuxt typecheck"
},
"dependencies": {
"@iconify-json/lucide": "^1.2.43",
"@iconify-json/simple-icons": "^1.2.34",
"@iconify-json/lucide": "^1.2.41",
"@iconify-json/simple-icons": "^1.2.33",
"@nuxt/ui": "latest",
"@nuxthub/core": "^0.8.27",
"nuxt": "^3.17.3",
"nuxt": "^3.17.2",
"zod": "^3.24.4"
},
"devDependencies": {

3522
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -91,21 +91,12 @@ export default defineNuxtModule<ModuleOptions>({
}
}
await registerModule('@nuxt/icon', 'icon', {
cssLayer: 'components'
})
await registerModule('@nuxt/icon', 'icon', { cssLayer: 'components' })
if (options.fonts) {
await registerModule('@nuxt/fonts', 'fonts', {
defaults: {
weights: [400, 500, 600, 700]
}
})
await registerModule('@nuxt/fonts', 'fonts', {})
}
if (options.colorMode) {
await registerModule('@nuxtjs/color-mode', 'colorMode', {
classSuffix: '',
disableTransition: true
})
await registerModule('@nuxtjs/color-mode', 'colorMode', { classSuffix: '', disableTransition: true })
}
addPlugin({ src: resolve('./runtime/plugins/colors') })

View File

@@ -16,6 +16,7 @@ export default function PluginsPlugin(options: NuxtUIOptions) {
const plugins = globSync(['**/*', '!*.d.ts'], { cwd: join(runtimeDir, 'plugins'), absolute: true })
plugins.unshift(resolvePathSync('../runtime/vue/plugins/head', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }))
plugins.push(resolvePathSync('../runtime/vue/plugins/colors', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }))
if (options.colorMode) {
plugins.push(resolvePathSync('../runtime/vue/plugins/color-mode', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url }))
}

View File

@@ -22,8 +22,6 @@ export interface AccordionItem {
/** A unique value for the accordion item. Defaults to the index. */
value?: string
disabled?: boolean
class?: any
ui?: Pick<Accordion['slots'], 'item' | 'header' | 'trigger' | 'leadingIcon' | 'label' | 'trailingIcon' | 'content' | 'body'>
[key: string]: any
}
@@ -98,27 +96,27 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.accordion ||
:key="index"
:value="item.value || String(index)"
:disabled="item.disabled"
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
:class="ui.item({ class: props.ui?.item })"
>
<AccordionHeader as="div" :class="ui.header({ class: [props.ui?.header, item.ui?.header] })">
<AccordionTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger], disabled: item.disabled })">
<AccordionHeader as="div" :class="ui.header({ class: props.ui?.header })">
<AccordionTrigger :class="ui.trigger({ class: props.ui?.trigger, disabled: item.disabled })">
<slot name="leading" :item="item" :index="index" :open="open">
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: [props.ui?.leadingIcon, item?.ui?.leadingIcon] })" />
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: props.ui?.label })">
<slot :item="item" :index="index" :open="open">{{ get(item, props.labelKey as string) }}</slot>
</span>
<slot name="trailing" :item="item" :index="index" :open="open">
<UIcon :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.trailingIcon({ class: [props.ui?.trailingIcon, item.ui?.trailingIcon] })" />
<UIcon :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
</slot>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent v-if="item.content || !!slots.content || (item.slot && !!slots[item.slot as keyof AccordionSlots<T>]) || !!slots.body || (item.slot && !!slots[`${item.slot}-body` as keyof AccordionSlots<T>])" :class="ui.content({ class: [props.ui?.content, item.ui?.content] })">
<AccordionContent v-if="item.content || !!slots.content || (item.slot && !!slots[item.slot as keyof AccordionSlots<T>]) || !!slots.body || (item.slot && !!slots[`${item.slot}-body` as keyof AccordionSlots<T>])" :class="ui.content({ class: props.ui?.content })">
<slot :name="((item.slot || 'content') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
<div :class="ui.body({ class: [props.ui?.body, item.ui?.body] })">
<div :class="ui.body({ class: props.ui?.body })">
<slot :name="((item.slot ? `${item.slot}-body`: 'body') as keyof AccordionSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index" :open="open">
{{ item.content }}
</slot>

View File

@@ -26,8 +26,6 @@ export interface BadgeProps extends Omit<UseComponentIconsProps, 'loading' | 'lo
* @defaultValue 'md'
*/
size?: Badge['variants']['size']
/** Render the badge with equal padding on all sides. */
square?: boolean
class?: any
ui?: Badge['slots']
}
@@ -52,7 +50,7 @@ import UAvatar from './Avatar.vue'
const props = withDefaults(defineProps<BadgeProps>(), {
as: 'span'
})
const slots = defineSlots<BadgeSlots>()
defineSlots<BadgeSlots>()
const appConfig = useAppConfig() as Badge['AppConfig']
const { orientation, size: buttonGroupSize } = useButtonGroup<BadgeProps>(props)
@@ -62,7 +60,6 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.badge || {})
color: props.color,
variant: props.variant,
size: buttonGroupSize.value || props.size,
square: props.square || (!slots.default && !props.label),
buttonGroup: orientation.value
}))
</script>

View File

@@ -15,8 +15,6 @@ export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
icon?: string
avatar?: AvatarProps
slot?: string
class?: any
ui?: Pick<Breadcrumb['slots'], 'item' | 'link' | 'linkLeadingIcon' | 'linkLeadingAvatar' | 'linkLabel' | 'separator' | 'separatorIcon'>
[key: string]: any
}
@@ -86,16 +84,16 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb |
<Primitive :as="as" aria-label="breadcrumb" :class="ui.root({ class: [props.ui?.root, props.class] })">
<ol :class="ui.list({ class: props.ui?.list })">
<template v-for="(item, index) in items" :key="index">
<li :class="ui.item({ class: [props.ui?.item, item.ui?.item] })">
<li :class="ui.item({ class: props.ui?.item })">
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
<ULinkBase v-bind="slotProps" as="span" :aria-current="active && (index === items!.length - 1) ? 'page' : undefined" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })">
<ULinkBase v-bind="slotProps" as="span" :aria-current="active && (index === items!.length - 1) ? 'page' : undefined" :class="ui.link({ class: [props.ui?.link, item.class], active: index === items!.length - 1, disabled: !!item.disabled, to: !!item.to })">
<slot :name="((item.slot || 'item') as keyof BreadcrumbSlots<T>)" :item="item" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
<UIcon v-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon], active: index === items!.length - 1 })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: [props.ui?.linkLeadingAvatar, item.ui?.linkLeadingAvatar], active: index === items!.length - 1 })" />
<UIcon v-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active: index === items!.length - 1 })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active: index === items!.length - 1 })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>]" :class="ui.linkLabel({ class: [props.ui?.linkLabel, item.ui?.linkLabel] })">
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>]" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof BreadcrumbSlots<T>)" :item="item" :active="index === items!.length - 1" :index="index">
{{ get(item, props.labelKey as string) }}
</slot>
@@ -107,9 +105,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb |
</ULink>
</li>
<li v-if="index < items!.length - 1" role="presentation" aria-hidden="true" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator] })">
<li v-if="index < items!.length - 1" role="presentation" aria-hidden="true" :class="ui.separator({ class: props.ui?.separator })">
<slot name="separator">
<UIcon :name="separatorIcon" :class="ui.separatorIcon({ class: [props.ui?.separatorIcon, item.ui?.separatorIcon] })" />
<UIcon :name="separatorIcon" :class="ui.separatorIcon({ class: props.ui?.separatorIcon })" />
</slot>
</li>
</template>

View File

@@ -1,8 +1,9 @@
<script lang="ts">
import type { AppConfig } from '@nuxt/schema'
import theme from '#build/ui/button'
import type { LinkProps } from './Link.vue'
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
import type { LinkProps, AvatarProps } from '../types'
import type { AvatarProps } from '../types'
import type { ComponentConfig } from '../types/utils'
type Button = ComponentConfig<typeof theme, AppConfig, 'button'>
@@ -122,13 +123,14 @@ const ui = computed(() => tv({
v-slot="{ active, ...slotProps }"
:type="type"
:disabled="disabled || isLoading"
:class="ui.base({ class: [props.ui?.base, props.class] })"
v-bind="omit(linkProps, ['type', 'disabled', 'onClick'])"
custom
>
<ULinkBase
v-bind="slotProps"
:class="ui.base({
class: [props.ui?.base, props.class],
class: [props.class, props.ui?.base],
active,
...(active && activeVariant ? { variant: activeVariant } : {}),
...(active && activeColor ? { color: activeColor } : {})

View File

@@ -15,13 +15,7 @@ import type { ComponentConfig } from '../types/utils'
type Carousel = ComponentConfig<typeof theme, AppConfig, 'carousel'>
interface _CarouselItem {
class?: any
ui?: Pick<Carousel['slots'], 'item'>
[key: string]: any
}
export type CarouselItem = _CarouselItem | AcceptableValue
export type CarouselItem = AcceptableValue
export interface CarouselProps<T extends CarouselItem = CarouselItem> extends Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
/**
@@ -260,10 +254,6 @@ function onSelect(api: EmblaCarouselType) {
emits('select', selectedIndex.value)
}
function isCarouselItem(item: CarouselItem): item is _CarouselItem {
return typeof item === 'object' && item !== null
}
onMounted(() => {
if (!emblaApi.value) {
return
@@ -298,7 +288,7 @@ defineExpose({
:key="index"
role="group"
aria-roledescription="slide"
:class="ui.item({ class: [props.ui?.item, isCarouselItem(item) && item.ui?.item, isCarouselItem(item) && item.class] })"
:class="ui.item({ class: props.ui?.item })"
>
<slot :item="item" :index="index" />
</div>

View File

@@ -101,7 +101,7 @@ function onUpdate(value: any) {
<!-- eslint-disable vue/no-template-shadow -->
<template>
<Primitive :as="(!variant || variant === 'list') ? as : Label" :class="ui.root({ class: [props.ui?.root, props.class] })">
<Primitive :as="variant === 'list' ? as : Label" :class="ui.root({ class: [props.ui?.root, props.class] })">
<div :class="ui.container({ class: props.ui?.container })">
<CheckboxRoot
:id="id"
@@ -122,7 +122,7 @@ function onUpdate(value: any) {
</div>
<div v-if="(label || !!slots.label) || (description || !!slots.description)" :class="ui.wrapper({ class: props.ui?.wrapper })">
<component :is="(!variant || variant === 'list') ? Label : 'p'" v-if="label || !!slots.label" :for="id" :class="ui.label({ class: props.ui?.label })">
<component :is="variant === 'list' ? Label : 'p'" v-if="label || !!slots.label" :for="id" :class="ui.label({ class: props.ui?.label })">
<slot name="label" :label="label">
{{ label }}
</slot>

View File

@@ -14,12 +14,10 @@ export type CheckboxGroupItem = {
description?: string
disabled?: boolean
value?: string
class?: any
ui?: Pick<CheckboxGroup['slots'], 'item'> & Omit<Required<CheckboxProps>['ui'], 'root'>
[key: string]: any
} | CheckboxGroupValue
export interface CheckboxGroupProps<T extends CheckboxGroupItem = CheckboxGroupItem> extends Pick<CheckboxGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'>, Pick<CheckboxProps, 'color' | 'indicator' | 'icon'> {
export interface CheckboxGroupProps<T extends CheckboxGroupItem = CheckboxGroupItem> extends Pick<CheckboxGroupRootProps, 'defaultValue' | 'disabled' | 'loop' | 'modelValue' | 'name' | 'required'>, Pick<CheckboxProps, 'color' | 'variant' | 'indicator' | 'icon'> {
/**
* The element or component this component should render as.
* @defaultValue 'div'
@@ -46,10 +44,6 @@ export interface CheckboxGroupProps<T extends CheckboxGroupItem = CheckboxGroupI
* @defaultValue 'md'
*/
size?: CheckboxGroup['variants']['size']
/**
* @defaultValue 'list'
*/
variant?: CheckboxGroup['variants']['variant']
/**
* The orientation the checkbox buttons are laid out.
* @defaultValue 'vertical'
@@ -103,9 +97,7 @@ const id = _id.value ?? useId()
const ui = computed(() => tv({ extend: theme, ...(appConfig.ui?.checkboxGroup || {}) })({
size: size.value,
required: props.required,
orientation: props.orientation,
color: props.color,
variant: props.variant
orientation: props.orientation
}))
function normalizeItem(item: any) {
@@ -179,8 +171,8 @@ function onUpdate(value: any) {
:size="size"
:name="name"
:disabled="item.disabled || disabled"
:ui="{ ...(props.ui ? omit(props.ui, ['root']) : undefined), ...(item.ui || {}) }"
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
:ui="props.ui ? omit(props.ui, ['root']) : undefined"
:class="ui.item({ class: props.ui?.item })"
>
<template v-for="(_, name) in proxySlots" #[name]>
<slot :name="(name as keyof CheckboxGroupSlots<T>)" :item="item" />

View File

@@ -27,8 +27,6 @@ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
disabled?: boolean
slot?: string
onSelect?(e?: Event): void
class?: any
ui?: Pick<CommandPalette['slots'], 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemLabelPrefix' | 'itemLabelBase' | 'itemLabelSuffix' | 'itemTrailing' | 'itemTrailingKbds' | 'itemTrailingKbdsSize' | 'itemTrailingHighlightedIcon' | 'itemTrailingIcon'>
[key: string]: any
}
@@ -295,42 +293,42 @@ const groups = computed(() => {
@select="item.onSelect"
>
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class], active: active || item.active })">
<ULinkBase v-bind="slotProps" :class="ui.item({ class: props.ui?.item, active: active || item.active })">
<slot :name="((item.slot || group.slot || 'item') as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading` : group.slot ? `${group.slot}-leading` : `item-leading`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon], loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon], active: active || item.active })" />
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active: active || item.active })" />
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, active: active || item.active })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar, active: active || item.active })" />
<UChip
v-else-if="item.chip"
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
inset
standalone
v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip], active: active || item.active })"
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip, active: active || item.active })"
/>
</slot>
<span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>]" :class="ui.itemLabel({ class: [props.ui?.itemLabel, item.ui?.itemLabel], active: active || item.active })">
<span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>]" :class="ui.itemLabel({ class: props.ui?.itemLabel, active: active || item.active })">
<slot :name="((item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
<span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: [props.ui?.itemLabelPrefix, item.ui?.itemLabelPrefix] })">{{ item.prefix }}</span>
<span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: props.ui?.itemLabelPrefix })">{{ item.prefix }}</span>
<span :class="ui.itemLabelBase({ class: [props.ui?.itemLabelBase, item.ui?.itemLabelBase], active: active || item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
<span :class="ui.itemLabelBase({ class: props.ui?.itemLabelBase, active: active || item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
<span :class="ui.itemLabelSuffix({ class: [props.ui?.itemLabelSuffix, item.ui?.itemLabelSuffix], active: active || item.active })" v-html="item.suffixHtml || item.suffix" />
<span :class="ui.itemLabelSuffix({ class: props.ui?.itemLabelSuffix, active: active || item.active })" v-html="item.suffixHtml || item.suffix" />
</slot>
</span>
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
<slot :name="((item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
<span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [props.ui?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
<span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: props.ui?.itemTrailingKbds })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
</span>
<UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: [props.ui?.itemTrailingHighlightedIcon, item.ui?.itemTrailingHighlightedIcon] })" />
<UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: props.ui?.itemTrailingHighlightedIcon })" />
</slot>
<ListboxItemIndicator as-child>
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })" />
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
</ListboxItemIndicator>
</span>
</slot>

View File

@@ -32,8 +32,6 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custo
children?: ArrayOrNested<ContextMenuItem>
onSelect?(e: Event): void
onUpdateChecked?(checked: boolean): void
class?: any
ui?: Pick<ContextMenu['slots'], 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLabel' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>
[key: string]: any
}

View File

@@ -77,29 +77,29 @@ const groups = computed<ContextMenuItem[][]>(() =>
<DefineItemTemplate v-slot="{ item, active, index }">
<slot :name="((item.slot || 'item') as keyof ContextMenuSlots<T>)" :item="item" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, active })" />
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })" />
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
<UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>]" :class="ui.itemLabel({ class: [uiOverride?.itemLabel, item.ui?.itemLabel], active })">
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>]" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
{{ get(item, props.labelKey as string) }}
</slot>
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: [uiOverride?.itemLabelExternalIcon, item.ui?.itemLabelExternalIcon], color: item?.color, active })" />
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
</span>
<span :class="ui.itemTrailing({ class: [uiOverride?.itemTrailing, item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color, active })" />
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [uiOverride?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
</span>
</slot>
<ContextMenu.ItemIndicator as-child>
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color })" />
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color })" />
</ContextMenu.ItemIndicator>
</span>
</slot>
@@ -111,17 +111,17 @@ const groups = computed<ContextMenuItem[][]>(() =>
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
<ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: [uiOverride?.label, item.ui?.label, item.class] })">
<ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
<ReuseItemTemplate :item="item" :index="index" />
</ContextMenu.Label>
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: [uiOverride?.separator, item.ui?.separator, item.class] })" />
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: uiOverride?.separator })" />
<ContextMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
<ContextMenu.SubTrigger
as="button"
type="button"
:disabled="item.disabled"
:text-value="get(item, props.labelKey as string)"
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
:class="ui.item({ class: uiOverride?.item, color: item?.color })"
>
<ReuseItemTemplate :item="item" :index="index" />
</ContextMenu.SubTrigger>
@@ -150,7 +150,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
:model-value="item.checked"
:disabled="item.disabled"
:text-value="get(item, props.labelKey as string)"
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
:class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
@update:model-value="item.onUpdateChecked"
@select="item.onSelect"
>
@@ -164,7 +164,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
@select="item.onSelect"
>
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom>
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], active, color: item?.color })">
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], active, color: item?.color })">
<ReuseItemTemplate :item="item" :active="active" :index="index" />
</ULinkBase>
</ULink>

View File

@@ -32,8 +32,6 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
children?: ArrayOrNested<DropdownMenuItem>
onSelect?(e: Event): void
onUpdateChecked?(checked: boolean): void
class?: any
ui?: Pick<DropdownMenu['slots'], 'item' | 'label' | 'separator' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLabel' | 'itemLabelExternalIcon' | 'itemTrailing' | 'itemTrailingIcon' | 'itemTrailingKbds' | 'itemTrailingKbdsSize'>
[key: string]: any
}

View File

@@ -83,29 +83,29 @@ const groups = computed<DropdownMenuItem[][]>(() =>
<DefineItemTemplate v-slot="{ item, active, index }">
<slot :name="((item.slot || 'item') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [uiOverride?.itemLeadingIcon, item.ui?.itemLeadingIcon], color: item?.color, active })" />
<UAvatar v-else-if="item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [uiOverride?.itemLeadingAvatar, item.ui?.itemLeadingAvatar], active })" />
<UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
<UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>]" :class="ui.itemLabel({ class: [uiOverride?.itemLabel, item.ui?.itemLabel], active })">
<span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>]" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
{{ get(item, props.labelKey as string) }}
</slot>
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: [uiOverride?.itemLabelExternalIcon, item.ui?.itemLabelExternalIcon], color: item?.color, active })" />
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
</span>
<span :class="ui.itemTrailing({ class: [uiOverride?.itemTrailing, item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof DropdownMenuContentSlots<T>)" :item="(item as Extract<NestedItem<T>, { slot: string; }>)" :active="active" :index="index">
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color, active })" />
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [uiOverride?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((item.ui?.itemTrailingKbdsSize || props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
<UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
</span>
</slot>
<DropdownMenu.ItemIndicator as-child>
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [uiOverride?.itemTrailingIcon, item.ui?.itemTrailingIcon], color: item?.color })" />
<UIcon :name="checkedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color })" />
</DropdownMenu.ItemIndicator>
</span>
</slot>
@@ -117,17 +117,17 @@ const groups = computed<DropdownMenuItem[][]>(() =>
<DropdownMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
<DropdownMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: [uiOverride?.label, item.ui?.label, item.class] })">
<DropdownMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
<ReuseItemTemplate :item="item" :index="index" />
</DropdownMenu.Label>
<DropdownMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: [uiOverride?.separator, item.ui?.separator, item.class] })" />
<DropdownMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: uiOverride?.separator })" />
<DropdownMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
<DropdownMenu.SubTrigger
as="button"
type="button"
:disabled="item.disabled"
:text-value="get(item, props.labelKey as string)"
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
:class="ui.item({ class: uiOverride?.item, color: item?.color })"
>
<ReuseItemTemplate :item="item" :index="index" />
</DropdownMenu.SubTrigger>
@@ -158,7 +158,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
:model-value="item.checked"
:disabled="item.disabled"
:text-value="get(item, props.labelKey as string)"
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
:class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
@update:model-value="item.onUpdateChecked"
@select="item.onSelect"
>
@@ -172,7 +172,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
@select="item.onSelect"
>
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom>
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color, active })">
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color, active })">
<ReuseItemTemplate :item="item" :active="active" :index="index" />
</ULinkBase>
</ULink>

View File

@@ -115,16 +115,16 @@ provide(formFieldInjectionKey, computed(() => ({
<div :class="[(label || !!slots.label || description || !!slots.description) && ui.container({ class: props.ui?.container })]">
<slot :error="error" />
<div v-if="(typeof error === 'string' && error) || !!slots.error" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })">
<p v-if="(typeof error === 'string' && error) || !!slots.error" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })">
<slot name="error" :error="error">
{{ error }}
</slot>
</div>
<div v-else-if="help || !!slots.help" :class="ui.help({ class: props.ui?.help })">
</p>
<p v-else-if="help || !!slots.help" :class="ui.help({ class: props.ui?.help })">
<slot name="help" :help="help">
{{ help }}
</slot>
</div>
</p>
</div>
</Primitive>
</template>

View File

@@ -4,7 +4,7 @@ import type { AppConfig } from '@nuxt/schema'
import theme from '#build/ui/input'
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
import type { AvatarProps } from '../types'
import type { AcceptableValue, ComponentConfig } from '../types/utils'
import type { ComponentConfig } from '../types/utils'
type Input = ComponentConfig<typeof theme, AppConfig, 'input'>
@@ -42,8 +42,8 @@ export interface InputProps extends UseComponentIconsProps {
ui?: Input['slots']
}
export interface InputEmits<T extends AcceptableValue = AcceptableValue> {
(e: 'update:modelValue', payload: T): void
export interface InputEmits {
(e: 'update:modelValue', payload: string | number): void
(e: 'blur', event: FocusEvent): void
(e: 'change', event: Event): void
}
@@ -55,7 +55,7 @@ export interface InputSlots {
}
</script>
<script setup lang="ts" generic="T extends AcceptableValue">
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { Primitive } from 'reka-ui'
import { useAppConfig } from '#imports'
@@ -74,13 +74,12 @@ const props = withDefaults(defineProps<InputProps>(), {
autocomplete: 'off',
autofocusDelay: 0
})
const emits = defineEmits<InputEmits<T>>()
const emits = defineEmits<InputEmits>()
const slots = defineSlots<InputSlots>()
const [modelValue, modelModifiers] = defineModel<T>()
const [modelValue, modelModifiers] = defineModel<string | number | null>()
const appConfig = useAppConfig() as Input['AppConfig']
const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField<InputProps>(props, { deferInputValidation: true })
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
@@ -115,7 +114,7 @@ function updateInput(value: string | null) {
value ||= null
}
modelValue.value = value as T
modelValue.value = value
emitFormInput()
}

View File

@@ -24,8 +24,6 @@ interface _InputMenuItem {
type?: 'label' | 'separator' | 'item'
disabled?: boolean
onSelect?(e?: Event): void
class?: any
ui?: Pick<InputMenu['slots'], 'tagsItem' | 'tagsItemText' | 'tagsItemDelete' | 'tagsItemDeleteIcon' | 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChip' | 'itemLeadingChipSize' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
[key: string]: any
}
export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean
@@ -428,16 +426,16 @@ defineExpose({
@focus="onFocus"
@remove-tag="onRemoveTag"
>
<TagsInputItem v-for="(item, index) in tags" :key="index" :value="item" :class="ui.tagsItem({ class: [props.ui?.tagsItem, isInputItem(item) && item.ui?.tagsItem] })">
<TagsInputItemText :class="ui.tagsItemText({ class: [props.ui?.tagsItemText, isInputItem(item) && item.ui?.tagsItemText] })">
<TagsInputItem v-for="(item, index) in tags" :key="index" :value="item" :class="ui.tagsItem({ class: props.ui?.tagsItem })">
<TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
<slot name="tags-item-text" :item="(item as NestedItem<T>)" :index="index">
{{ displayValue(item as T) }}
</slot>
</TagsInputItemText>
<TagsInputItemDelete :class="ui.tagsItemDelete({ class: [props.ui?.tagsItemDelete, isInputItem(item) && item.ui?.tagsItemDelete] })" :disabled="disabled">
<TagsInputItemDelete :class="ui.tagsItemDelete({ class: props.ui?.tagsItemDelete })" :disabled="disabled">
<slot name="tags-item-delete" :item="(item as NestedItem<T>)" :index="index">
<UIcon :name="deleteIcon || appConfig.ui.icons.close" :class="ui.tagsItemDeleteIcon({ class: [props.ui?.tagsItemDeleteIcon, isInputItem(item) && item.ui?.tagsItemDeleteIcon] })" />
<UIcon :name="deleteIcon || appConfig.ui.icons.close" :class="ui.tagsItemDeleteIcon({ class: props.ui?.tagsItemDeleteIcon })" />
</slot>
</TagsInputItemDelete>
</TagsInputItem>
@@ -495,44 +493,44 @@ defineExpose({
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
<ComboboxLabel v-if="isInputItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
<ComboboxLabel v-if="isInputItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
{{ get(item, props.labelKey as string) }}
</ComboboxLabel>
<ComboboxSeparator v-else-if="isInputItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
<ComboboxSeparator v-else-if="isInputItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
<ComboboxItem
v-else
:class="ui.item({ class: [props.ui?.item, isInputItem(item) && item.ui?.item, isInputItem(item) && item.class] })"
:class="ui.item({ class: props.ui?.item })"
:disabled="isInputItem(item) && item.disabled"
:value="props.valueKey && isInputItem(item) ? get(item, props.valueKey as string) : item"
@select="onSelect($event, item)"
>
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
<UIcon v-if="isInputItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
<UAvatar v-else-if="isInputItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
<UIcon v-if="isInputItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
<UAvatar v-else-if="isInputItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
<UChip
v-else-if="isInputItem(item) && item.chip"
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
inset
standalone
v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/>
</slot>
<span :class="ui.itemLabel({ class: [props.ui?.itemLabel, isInputItem(item) && item.ui?.itemLabel] })">
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isInputItem(item) ? get(item, props.labelKey as string) : item }}
</slot>
</span>
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isInputItem(item) && item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<ComboboxItemIndicator as-child>
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isInputItem(item) && item.ui?.itemTrailingIcon] })" />
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
</ComboboxItemIndicator>
</span>
</slot>

View File

@@ -36,8 +36,6 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
* @IconifyIcon
*/
incrementIcon?: string
/** Disable the increment button. */
incrementDisabled?: boolean
/**
* Configure the decrement button. The `color` and `size` are inherited.
* @defaultValue { variant: 'link' }
@@ -49,8 +47,6 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
* @IconifyIcon
*/
decrementIcon?: string
/** Disable the decrement button. */
decrementDisabled?: boolean
autofocus?: boolean
autofocusDelay?: number
/**
@@ -79,7 +75,6 @@ import { onMounted, ref, computed } from 'vue'
import { NumberFieldRoot, NumberFieldInput, NumberFieldDecrement, NumberFieldIncrement, useForwardPropsEmits } from 'reka-ui'
import { reactivePick } from '@vueuse/core'
import { useAppConfig } from '#imports'
import { useButtonGroup } from '../composables/useButtonGroup'
import { useFormField } from '../composables/useFormField'
import { useLocale } from '../composables/useLocale'
import { tv } from '../utils/tv'
@@ -88,31 +83,26 @@ import UButton from './Button.vue'
defineOptions({ inheritAttrs: false })
const props = withDefaults(defineProps<InputNumberProps>(), {
orientation: 'horizontal',
disabledIncrement: false,
disabledDecrement: false
orientation: 'horizontal'
})
const emits = defineEmits<InputNumberEmits>()
defineSlots<InputNumberSlots>()
const { t, code: codeLocale } = useLocale()
const appConfig = useAppConfig() as InputNumber['AppConfig']
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'stepSnapping', 'formatOptions', 'disableWheelChange'), emits)
const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size: formGroupSize, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputNumberProps>(props)
const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
const { t, code: codeLocale } = useLocale()
const locale = computed(() => props.locale || codeLocale.value)
const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.inputNumber || {}) })({
color: color.value,
variant: props.variant,
size: inputSize.value,
size: size.value,
highlight: highlight.value,
orientation: props.orientation,
buttonGroup: orientation.value
orientation: props.orientation
}))
const incrementIcon = computed(() => props.incrementIcon || (props.orientation === 'horizontal' ? appConfig.ui.icons.plus : appConfig.ui.icons.chevronUp))
@@ -172,7 +162,7 @@ defineExpose({
/>
<div :class="ui.increment({ class: props.ui?.increment })">
<NumberFieldIncrement as-child :disabled="disabled || incrementDisabled">
<NumberFieldIncrement as-child :disabled="disabled">
<slot name="increment">
<UButton
:icon="incrementIcon"
@@ -187,7 +177,7 @@ defineExpose({
</div>
<div :class="ui.decrement({ class: props.ui?.decrement })">
<NumberFieldDecrement as-child :disabled="disabled || decrementDisabled">
<NumberFieldDecrement as-child :disabled="disabled">
<slot name="decrement">
<UButton
:icon="decrementIcon"

View File

@@ -89,12 +89,11 @@ export interface LinkSlots {
<script setup lang="ts">
import { computed } from 'vue'
import { defu } from 'defu'
import { isEqual } from 'ohash/utils'
import { isEqual, diff } from 'ohash/utils'
import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core'
import { useRoute, useAppConfig } from '#imports'
import { tv } from '../utils/tv'
import { isPartiallyEqual } from '../utils/link'
import ULinkBase from './LinkBase.vue'
defineOptions({ inheritAttrs: false })
@@ -112,7 +111,7 @@ defineSlots<LinkSlots>()
const route = useRoute()
const appConfig = useAppConfig() as Link['AppConfig']
const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'to', 'href', 'raw', 'custom', 'class'))
const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'raw', 'class'))
const ui = computed(() => tv({
extend: tv(theme),
@@ -126,7 +125,19 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {})
}))
const to = computed(() => props.to ?? props.href)
function isPartiallyEqual(item1: any, item2: any) {
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
if (q.type === 'added') {
filtered.add(q.key)
}
return filtered
}, new Set<string>())
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
return isEqual(item1Filtered, item2Filtered)
}
function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
if (props.active !== undefined) {
@@ -166,7 +177,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any) {
</script>
<template>
<NuxtLink v-slot="{ href, navigate, route: linkRoute, rel, target, isExternal, isActive, isExactActive }" v-bind="nuxtLinkProps" :to="to" custom>
<NuxtLink v-slot="{ href, navigate, route: linkRoute, rel, target, isExternal, isActive, isExactActive }" v-bind="nuxtLinkProps" custom>
<template v-if="custom">
<slot
v-bind="{

View File

@@ -8,7 +8,7 @@ import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps,
type NavigationMenu = ComponentConfig<typeof theme, AppConfig, 'navigationMenu'>
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type' | 'ui'> {
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type'> {
/** Description is only used when `orientation` is `horizontal`. */
description?: string
[key: string]: any
@@ -43,10 +43,6 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
*/
type?: 'label' | 'link'
slot?: string
/**
* The value of the item. Avoid using `index` as the value to prevent conflicts in horizontal orientation with Reka UI.
* @defaultValue `item-${index}`
*/
value?: string
/**
* Make the item collapsible.
@@ -56,8 +52,6 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
collapsible?: boolean
children?: NavigationMenuChildItem[]
onSelect?(e: Event): void
class?: any
ui?: Pick<NavigationMenu['slots'], 'item' | 'linkLeadingAvatarSize' | 'linkLeadingAvatar' | 'linkLeadingIcon' | 'linkLabel' | 'linkLabelExternalIcon' | 'linkTrailing' | 'linkTrailingBadgeSize' | 'linkTrailingBadge' | 'linkTrailingIcon' | 'label' | 'link' | 'content' | 'childList' | 'childItem' | 'childLink' | 'childLinkIcon' | 'childLinkWrapper' | 'childLinkLabel' | 'childLinkLabelExternalIcon' | 'childLinkDescription'>
[key: string]: any
}
@@ -222,34 +216,34 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<DefineLinkTemplate v-slot="{ item, active, index }">
<slot :name="((item.slot || 'item') as keyof NavigationMenuSlots<T>)" :item="item" :index="index">
<slot :name="((item.slot ? `${item.slot}-leading` : 'item-leading') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
<UAvatar v-if="item.avatar" :size="((item.ui?.linkLeadingAvatarSize || props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: [props.ui?.linkLeadingAvatar, item.ui?.linkLeadingAvatar], active, disabled: !!item.disabled })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon], active, disabled: !!item.disabled })" />
<UAvatar v-if="item.avatar" :size="((props.ui?.linkLeadingAvatarSize || ui.linkLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.linkLeadingAvatar({ class: props.ui?.linkLeadingAvatar, active, disabled: !!item.disabled })" />
<UIcon v-else-if="item.icon" :name="item.icon" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon, active, disabled: !!item.disabled })" />
</slot>
<span
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>])"
:class="ui.linkLabel({ class: [props.ui?.linkLabel, item.ui?.linkLabel] })"
:class="ui.linkLabel({ class: props.ui?.linkLabel })"
>
<slot :name="((item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
{{ get(item, props.labelKey as string) }}
</slot>
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: [props.ui?.linkLabelExternalIcon, item.ui?.linkLabelExternalIcon], active })" />
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
</span>
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[(item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>])" :class="ui.linkTrailing({ class: [props.ui?.linkTrailing, item.ui?.linkTrailing] })">
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[(item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
<slot :name="((item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
<UBadge
v-if="item.badge"
color="neutral"
variant="outline"
:size="((item.ui?.linkTrailingBadgeSize || props.ui?.linkTrailingBadgeSize || ui.linkTrailingBadgeSize()) as BadgeProps['size'])"
:size="((props.ui?.linkTrailingBadgeSize || ui.linkTrailingBadgeSize()) as BadgeProps['size'])"
v-bind="(typeof item.badge === 'string' || typeof item.badge === 'number') ? { label: item.badge } : item.badge"
:class="ui.linkTrailingBadge({ class: [props.ui?.linkTrailingBadge, item.ui?.linkTrailingBadge] })"
:class="ui.linkTrailingBadge({ class: props.ui?.linkTrailingBadge })"
/>
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length && item.collapsible !== false)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon], active })" />
<UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon], active })" />
<UIcon v-if="(orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])) || (orientation === 'vertical' && item.children?.length && item.collapsible !== false)" :name="item.trailingIcon || trailingIcon || appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
<UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
</slot>
</span>
</slot>
@@ -259,13 +253,13 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<component
:is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"
as="li"
:value="item.value || `item-${index}`"
:value="item.value || String(index)"
:default-open="item.defaultOpen"
:disabled="(orientation === 'vertical' && item.children?.length) ? item.collapsible === false : undefined"
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
:open="item.open"
>
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
<ReuseLinkTemplate :item="item" :index="index" />
</div>
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && item.collapsible !== false) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
@@ -277,31 +271,31 @@ const lists = computed<NavigationMenuItem[][]>(() =>
@select="item.onSelect"
>
<UTooltip v-if="!!item.tooltip" :content="{ side: 'right' }" v-bind="item.tooltip">
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
</ULinkBase>
</UTooltip>
<ULinkBase v-else v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
<ULinkBase v-else v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
<ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
</ULinkBase>
</component>
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])" v-bind="contentProps" :class="ui.content({ class: [props.ui?.content, item.ui?.content] })">
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[(item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
<slot :name="((item.slot ? `${item.slot}-content` : 'item-content') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
<ul :class="ui.childList({ class: [props.ui?.childList, item.ui?.childList] })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: [props.ui?.childItem, item.ui?.childItem] })">
<ul :class="ui.childList({ class: props.ui?.childList })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, item.ui?.childLink, childItem.class], active: childActive })">
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: [props.ui?.childLinkIcon, item.ui?.childLinkIcon], active: childActive })" />
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />
<div :class="ui.childLinkWrapper({ class: [props.ui?.childLinkWrapper, item.ui?.childLinkWrapper] })">
<p :class="ui.childLinkLabel({ class: [props.ui?.childLinkLabel, item.ui?.childLinkLabel], active: childActive })">
<div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
<p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
{{ get(childItem, props.labelKey as string) }}
<UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: [props.ui?.childLinkLabelExternalIcon, item.ui?.childLinkLabelExternalIcon], active: childActive })" />
<UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
</p>
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: [props.ui?.childLinkDescription, item.ui?.childLinkDescription], active: childActive })">
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
{{ childItem.description }}
</p>
</div>
@@ -322,7 +316,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
:item="childItem"
:index="childIndex"
:level="level + 1"
:class="ui.childItem({ class: [props.ui?.childItem, childItem.ui?.childItem] })"
:class="ui.childItem({ class: props.ui?.childItem })"
/>
</ul>
</template>
@@ -334,7 +328,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
<NavigationMenuList :class="ui.list({ class: props.ui?.list })">
<ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="ui.item({ class: [props.ui?.item, item.ui?.item] })" />
<ReuseItemTemplate v-for="(item, index) in list" :key="`list-${listIndex}-${index}`" :item="item" :index="index" :class="ui.item({ class: props.ui?.item })" />
</NavigationMenuList>
<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" />

View File

@@ -12,8 +12,6 @@ export type RadioGroupItem = {
description?: string
disabled?: boolean
value?: RadioGroupValue
class?: any
ui?: Pick<RadioGroup['slots'], 'item' | 'container' | 'base' | 'indicator' | 'wrapper' | 'label' | 'description'>
[key: string]: any
} | RadioGroupValue
@@ -178,25 +176,25 @@ function onUpdate(value: any) {
</slot>
</legend>
<component :is="(!variant || variant === 'list') ? 'div' : Label" v-for="item in normalizedItems" :key="item.value" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })">
<div :class="ui.container({ class: [props.ui?.container, item.ui?.container] })">
<component :is="variant === 'list' ? 'div' : Label" v-for="item in normalizedItems" :key="item.value" :class="ui.item({ class: props.ui?.item })">
<div :class="ui.container({ class: props.ui?.container })">
<RadioGroupItem
:id="item.id"
:value="item.value"
:disabled="item.disabled"
:class="ui.base({ class: [props.ui?.base, item.ui?.base], disabled: item.disabled })"
:class="ui.base({ class: props.ui?.base, disabled: item.disabled })"
>
<RadioGroupIndicator :class="ui.indicator({ class: [props.ui?.indicator, item.ui?.indicator] })" />
<RadioGroupIndicator :class="ui.indicator({ class: props.ui?.indicator })" />
</RadioGroupItem>
</div>
<div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })">
<component :is="(!variant || variant === 'list') ? Label : 'p'" v-if="item.label || !!slots.label" :for="item.id" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
<div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: props.ui?.wrapper })">
<component :is="variant === 'list' ? Label : 'p'" v-if="item.label || !!slots.label" :for="item.id" :class="ui.label({ class: props.ui?.label })">
<slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">
{{ item.label }}
</slot>
</component>
<p v-if="item.description || !!slots.description" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })">
<p v-if="item.description || !!slots.description" :class="ui.description({ class: props.ui?.description })">
<slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
{{ item.description }}
</slot>

View File

@@ -24,8 +24,6 @@ interface SelectItemBase {
value?: AcceptableValue | boolean
disabled?: boolean
onSelect?(e?: Event): void
class?: any
ui?: Pick<Select['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
[key: string]: any
}
export type SelectItem = SelectItemBase | AcceptableValue | boolean
@@ -273,44 +271,44 @@ function isSelectItem(item: SelectItem): item is SelectItemBase {
<SelectViewport :class="ui.viewport({ class: props.ui?.viewport })">
<SelectGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
<SelectLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
{{ get(item, props.labelKey as string) }}
</SelectLabel>
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
<SelectSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
<SelectItem
v-else
:class="ui.item({ class: [props.ui?.item, isSelectItem(item) && item.ui?.item, isSelectItem(item) && item.class] })"
:class="ui.item({ class: props.ui?.item })"
:disabled="isSelectItem(item) && item.disabled"
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
@select="isSelectItem(item) && item.onSelect?.($event)"
>
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
<UChip
v-else-if="isSelectItem(item) && item.chip"
:size="((item.ui?.itemLeadingChipSize || props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
inset
standalone
v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/>
</slot>
<SelectItemText :class="ui.itemLabel({ class: [props.ui?.itemLabel, isSelectItem(item) && item.ui?.itemLabel] })">
<SelectItemText :class="ui.itemLabel({ class: props.ui?.itemLabel })">
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
</slot>
</SelectItemText>
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isSelectItem(item) && item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<SelectItemIndicator as-child>
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isSelectItem(item) && item.ui?.itemTrailingIcon] })" />
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
</SelectItemIndicator>
</span>
</slot>

View File

@@ -23,8 +23,6 @@ interface _SelectMenuItem {
type?: 'label' | 'separator' | 'item'
disabled?: boolean
onSelect?(e?: Event): void
class?: any
ui?: Pick<SelectMenu['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
[key: string]: any
}
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
@@ -422,44 +420,44 @@ function isSelectItem(item: SelectMenuItem): item is _SelectMenuItem {
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
<ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: [props.ui?.label, item.ui?.label, item.class] })">
<ComboboxLabel v-if="isSelectItem(item) && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
{{ get(item, props.labelKey as string) }}
</ComboboxLabel>
<ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: [props.ui?.separator, item.ui?.separator, item.class] })" />
<ComboboxSeparator v-else-if="isSelectItem(item) && item.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
<ComboboxItem
v-else
:class="ui.item({ class: [props.ui?.item, isSelectItem(item) && item.ui?.item, isSelectItem(item) && item.class] })"
:class="ui.item({ class: props.ui?.item })"
:disabled="isSelectItem(item) && item.disabled"
:value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
@select="onSelect($event, item)"
>
<slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :item="(item as NestedItem<T>)" :index="index">
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: [props.ui?.itemLeadingIcon, item.ui?.itemLeadingIcon] })" />
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((item.ui?.itemLeadingAvatarSize || props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: [props.ui?.itemLeadingAvatar, item.ui?.itemLeadingAvatar] })" />
<UIcon v-if="isSelectItem(item) && item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
<UAvatar v-else-if="isSelectItem(item) && item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
<UChip
v-else-if="isSelectItem(item) && item.chip"
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
inset
standalone
v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })"
:class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/>
</slot>
<span :class="ui.itemLabel({ class: [props.ui?.itemLabel, isSelectItem(item) && item.ui?.itemLabel] })">
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
<slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
</slot>
</span>
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, isSelectItem(item) && item.ui?.itemTrailing] })">
<span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
<slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<ComboboxItemIndicator as-child>
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, isSelectItem(item) && item.ui?.itemTrailingIcon] })" />
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
</ComboboxItemIndicator>
</span>
</slot>

View File

@@ -38,13 +38,13 @@ export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' |
ui?: Slider['slots']
}
export interface SliderEmits<T extends number | number[] = number | number[]> {
(e: 'update:modelValue', payload: T): void
export interface SliderEmits {
(e: 'update:modelValue', payload: number | number[]): void
(e: 'change', payload: Event): void
}
</script>
<script setup lang="ts" generic="T extends number | number[]">
<script setup lang="ts">
import { computed } from 'vue'
import { SliderRoot, SliderRange, SliderTrack, SliderThumb, useForwardPropsEmits } from 'reka-ui'
import { reactivePick } from '@vueuse/core'
@@ -59,9 +59,9 @@ const props = withDefaults(defineProps<SliderProps>(), {
step: 1,
orientation: 'horizontal'
})
const emits = defineEmits<SliderEmits<T>>()
const emits = defineEmits<SliderEmits>()
const modelValue = defineModel<T>()
const modelValue = defineModel<number | number[]>()
const appConfig = useAppConfig() as Slider['AppConfig']
@@ -81,10 +81,10 @@ const sliderValue = computed({
if (typeof modelValue.value === 'number') {
return [modelValue.value]
}
return (modelValue.value as number[]) ?? defaultSliderValue.value
return modelValue.value ?? defaultSliderValue.value
},
set(value) {
modelValue.value = (value?.length !== 1 ? value : value[0]) as T
modelValue.value = value?.length !== 1 ? value : value[0]
}
})

View File

@@ -18,8 +18,6 @@ export interface StepperItem {
icon?: string
content?: string
disabled?: boolean
class?: any
ui?: Pick<Stepper['slots'], 'item' | 'container' | 'trigger' | 'indicator' | 'icon' | 'separator' | 'wrapper' | 'title' | 'description'>
[key: string]: any
}
@@ -138,13 +136,13 @@ defineExpose({
:key="item.value ?? count"
:step="count"
:disabled="item.disabled || props.disabled"
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })"
:class="ui.item({ class: props.ui?.item })"
>
<div :class="ui.container({ class: [props.ui?.container, item.ui?.container] })">
<StepperTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger] })">
<StepperIndicator :class="ui.indicator({ class: [props.ui?.indicator, item.ui?.indicator] })">
<div :class="ui.container({ class: props.ui?.container })">
<StepperTrigger :class="ui.trigger({ class: props.ui?.trigger })">
<StepperIndicator :class="ui.indicator({ class: props.ui?.indicator })">
<slot name="indicator" :item="item">
<UIcon v-if="item.icon" :name="item.icon" :class="ui.icon({ class: [props.ui?.icon, item.ui?.icon] })" />
<UIcon v-if="item.icon" :name="item.icon" :class="ui.icon({ class: props.ui?.icon })" />
<template v-else>
{{ count + 1 }}
</template>
@@ -154,17 +152,17 @@ defineExpose({
<StepperSeparator
v-if="count < items.length - 1"
:class="ui.separator({ class: [props.ui?.separator, item.ui?.separator] })"
:class="ui.separator({ class: props.ui?.separator })"
/>
</div>
<div :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })">
<StepperTitle as="div" :class="ui.title({ class: [props.ui?.title, item.ui?.title] })">
<div :class="ui.wrapper({ class: props.ui?.wrapper })">
<StepperTitle as="div" :class="ui.title({ class: props.ui?.title })">
<slot name="title" :item="item">
{{ item.title }}
</slot>
</StepperTitle>
<StepperDescription as="div" :class="ui.description({ class: [props.ui?.description, item.ui?.description] })">
<StepperDescription as="div" :class="ui.description({ class: props.ui?.description })">
<slot name="description" :item="item">
{{ item.description }}
</slot>

View File

@@ -20,8 +20,6 @@ export interface TabsItem {
/** A unique value for the tab item. Defaults to the index. */
value?: string | number
disabled?: boolean
class?: any
ui?: Pick<Tabs['slots'], 'trigger' | 'leadingIcon' | 'leadingAvatar' | 'label' | 'content'>
[key: string]: any
}
@@ -117,13 +115,13 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tabs || {})
<slot name="list-leading" />
<TabsTrigger v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :disabled="item.disabled" :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger] })">
<TabsTrigger v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :disabled="item.disabled" :class="ui.trigger({ class: props.ui?.trigger })">
<slot name="leading" :item="item" :index="index">
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: [props.ui?.leadingIcon, item.ui?.leadingIcon] })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.leadingAvatarSize || ui.leadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.leadingAvatar({ class: [props.ui?.leadingAvatar, item.ui?.leadingAvatar] })" />
<UIcon v-if="item.icon" :name="item.icon" :class="ui.leadingIcon({ class: props.ui?.leadingIcon })" />
<UAvatar v-else-if="item.avatar" :size="((props.ui?.leadingAvatarSize || ui.leadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.leadingAvatar({ class: props.ui?.leadingAvatar })" />
</slot>
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: [props.ui?.label, item.ui?.label] })">
<span v-if="get(item, props.labelKey as string) || !!slots.default" :class="ui.label({ class: props.ui?.label })">
<slot :item="item" :index="index">{{ get(item, props.labelKey as string) }}</slot>
</span>
@@ -134,7 +132,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tabs || {})
</TabsList>
<template v-if="!!content">
<TabsContent v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :class="ui.content({ class: [props.ui?.content, item.ui?.content, item.class] })">
<TabsContent v-for="(item, index) of items" :key="index" :value="item.value || String(index)" :class="ui.content({ class: props.ui?.content })">
<slot :name="((item.slot || 'content') as keyof TabsSlots<T>)" :item="(item as Extract<T, { slot: string; }>)" :index="index">
{{ item.content }}
</slot>

View File

@@ -3,7 +3,7 @@ import type { AppConfig } from '@nuxt/schema'
import theme from '#build/ui/textarea'
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
import type { AvatarProps } from '../types'
import type { AcceptableValue, ComponentConfig } from '../types/utils'
import type { ComponentConfig } from '../types/utils'
type Textarea = ComponentConfig<typeof theme, AppConfig, 'textarea'>
@@ -43,8 +43,8 @@ export interface TextareaProps extends UseComponentIconsProps {
ui?: Textarea['slots']
}
export interface TextareaEmits<T extends AcceptableValue = AcceptableValue> {
(e: 'update:modelValue', payload: T): void
export interface TextareaEmits {
(e: 'update:modelValue', payload: string | number): void
(e: 'blur', event: FocusEvent): void
(e: 'change', event: Event): void
}
@@ -56,7 +56,7 @@ export interface TextareaSlots {
}
</script>
<script setup lang="ts" generic="T extends AcceptableValue">
<script setup lang="ts">
import { ref, computed, onMounted, nextTick, watch } from 'vue'
import { Primitive } from 'reka-ui'
import { useAppConfig } from '#imports'
@@ -73,13 +73,12 @@ const props = withDefaults(defineProps<TextareaProps>(), {
autofocusDelay: 0,
autoresizeDelay: 0
})
const emits = defineEmits<TextareaEmits<T>>()
const slots = defineSlots<TextareaSlots>()
const emits = defineEmits<TextareaEmits>()
const [modelValue, modelModifiers] = defineModel<T>()
const [modelValue, modelModifiers] = defineModel<string | number | null>()
const appConfig = useAppConfig() as Textarea['AppConfig']
const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<TextareaProps>(props, { deferInputValidation: true })
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
@@ -110,7 +109,7 @@ function updateInput(value: string | null) {
value ||= null
}
modelValue.value = value as T
modelValue.value = value
emitFormInput()
}

View File

@@ -29,11 +29,6 @@ export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open'
* @defaultValue 'vertical'
*/
orientation?: Toast['variants']['orientation']
/**
* Whether to show the progress bar.
* @defaultValue true
*/
progress?: boolean
/**
* Display a list of actions:
* - under the title and description when orientation is `vertical`
@@ -81,8 +76,7 @@ import UButton from './Button.vue'
const props = withDefaults(defineProps<ToastProps>(), {
close: true,
orientation: 'vertical',
progress: true
orientation: 'vertical'
})
const emits = defineEmits<ToastEmits>()
const slots = defineSlots<ToastSlots>()
@@ -185,6 +179,6 @@ defineExpose({
</ToastClose>
</div>
<div v-if="progress && remaining > 0 && duration" :class="ui.progress({ class: props.ui?.progress })" :style="{ width: `${remaining / duration * 100}%` }" />
<div v-if="remaining > 0 && duration" :class="ui.progress({ class: props.ui?.progress })" :style="{ width: `${remaining / duration * 100}%` }" />
</ToastRoot>
</template>

View File

@@ -17,11 +17,6 @@ export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'>
* @defaultValue true
*/
expand?: boolean
/**
* Whether to show the progress bar on all toasts.
* @defaultValue true
*/
progress?: boolean
/**
* Render the toaster in a portal.
* @defaultValue true
@@ -54,8 +49,7 @@ import UToast from './Toast.vue'
const props = withDefaults(defineProps<ToasterProps>(), {
expand: true,
portal: true,
duration: 5000,
progress: true
duration: 5000
})
defineSlots<ToasterSlots>()
@@ -115,7 +109,6 @@ function getOffset(index: number) {
v-for="(toast, index) of toasts"
:key="toast.id"
ref="refs"
:progress="progress"
v-bind="omit(toast, ['id', 'close'])"
:close="(toast.close as boolean)"
:data-expanded="expanded"
@@ -128,7 +121,9 @@ function getOffset(index: number) {
'--translate': expanded ? 'calc(var(--offset) * var(--translate-factor))' : 'calc(var(--before) * var(--gap))',
'--transform': 'translateY(var(--translate)) scale(var(--scale))'
}"
:class="ui.base({ class: [props.ui?.base, toast.onClick ? 'cursor-pointer' : undefined] })"
:class="[ui.base(), {
'cursor-pointer': !!toast.onClick
}]"
@update:open="onUpdateOpen($event, toast.id)"
@click="toast.onClick && toast.onClick(toast)"
/>

View File

@@ -24,8 +24,6 @@ export type TreeItem = {
children?: TreeItem[]
onToggle?(e: Event): void
onSelect?(e?: Event): void
class?: any
ui?: Pick<Tree['slots'], 'item' | 'itemWithChildren' | 'link' | 'linkLeadingIcon' | 'linkLabel' | 'linkTrailing' | 'linkTrailingIcon' | 'listWithChildren'>
[key: string]: any
}
@@ -151,7 +149,7 @@ const defaultExpanded = computed(() =>
<li
v-for="(item, index) in items"
:key="`${level}-${index}`"
:class="level > 0 ? ui.itemWithChildren({ class: [props.ui?.itemWithChildren, item.ui?.itemWithChildren] }) : ui.item({ class: [props.ui?.item, item.ui?.item] })"
:class="level > 0 ? ui.itemWithChildren({ class: props.ui?.itemWithChildren }) : ui.item({ class: props.ui?.item })"
>
<TreeItem
v-slot="{ isExpanded, isSelected }"
@@ -161,37 +159,37 @@ const defaultExpanded = computed(() =>
@toggle="item.onToggle"
@select="item.onSelect"
>
<button :disabled="item.disabled || disabled" :class="ui.link({ class: [props.ui?.link, item.ui?.link, item.class], selected: isSelected, disabled: item.disabled || disabled })">
<button :disabled="item.disabled || disabled" :class="ui.link({ class: props.ui?.link, selected: isSelected, disabled: item.disabled || disabled })">
<slot :name="((item.slot || 'item') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
<slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof TreeSlots<T>)" v-bind="{ index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
<UIcon
v-if="item.icon"
:name="item.icon"
:class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon] })"
:class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon })"
/>
<UIcon
v-else-if="item.children?.length"
:name="isExpanded ? (expandedIcon ?? appConfig.ui.icons.folderOpen) : (collapsedIcon ?? appConfig.ui.icons.folder)"
:class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon] })"
:class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon })"
/>
</slot>
<span v-if="getItemLabel(item) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>]" :class="ui.linkLabel({ class: [props.ui?.linkLabel, item.ui?.linkLabel] })">
<span v-if="getItemLabel(item) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>]" :class="ui.linkLabel({ class: props.ui?.linkLabel })">
<slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
{{ getItemLabel(item) }}
</slot>
</span>
<span v-if="item.trailingIcon || item.children?.length || !!slots[(item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>]" :class="ui.linkTrailing({ class: [props.ui?.linkTrailing, item.ui?.linkTrailing] })">
<span v-if="item.trailingIcon || item.children?.length || !!slots[(item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>]" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
<slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof TreeSlots<T>)" v-bind="{ item, index, level, expanded: isExpanded, selected: isSelected }" :item="(item as Extract<NestedItem<T>, { slot: string; }>)">
<UIcon v-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon] })" />
<UIcon v-else-if="item.children?.length" :name="trailingIcon ?? appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: [props.ui?.linkTrailingIcon, item.ui?.linkTrailingIcon] })" />
<UIcon v-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon })" />
<UIcon v-else-if="item.children?.length" :name="trailingIcon ?? appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon })" />
</slot>
</span>
</slot>
</button>
<ul v-if="item.children?.length && isExpanded" :class="ui.listWithChildren({ class: [props.ui?.listWithChildren, item.ui?.listWithChildren] })">
<ul v-if="item.children?.length && isExpanded" :class="ui.listWithChildren({ class: props.ui?.listWithChildren })">
<ReuseTreeTemplate :items="item.children" :level="level + 1" />
</ul>
</TreeItem>

View File

@@ -1,4 +1,4 @@
import { inject, computed, type InjectionKey, type Ref, type ComputedRef, provide } from 'vue'
import { inject, computed, type InjectionKey, type Ref, type ComputedRef } from 'vue'
import { type UseEventBusReturn, useDebounceFn } from '@vueuse/core'
import type { FormFieldProps } from '../types'
import type { FormEvent, FormInputEvents, FormFieldInjectedOptions, FormInjectedOptions } from '../types/form'
@@ -15,7 +15,7 @@ type Props<T> = {
export const formOptionsInjectionKey: InjectionKey<ComputedRef<FormInjectedOptions>> = Symbol('nuxt-ui.form-options')
export const formBusInjectionKey: InjectionKey<UseEventBusReturn<FormEvent<any>, string>> = Symbol('nuxt-ui.form-events')
export const formFieldInjectionKey: InjectionKey<ComputedRef<FormFieldInjectedOptions<FormFieldProps>> | undefined> = Symbol('nuxt-ui.form-field')
export const formFieldInjectionKey: InjectionKey<ComputedRef<FormFieldInjectedOptions<FormFieldProps>>> = Symbol('nuxt-ui.form-field')
export const inputIdInjectionKey: InjectionKey<Ref<string | undefined>> = Symbol('nuxt-ui.input-id')
export const formInputsInjectionKey: InjectionKey<Ref<Record<string, { id?: string, pattern?: RegExp }>>> = Symbol('nuxt-ui.form-inputs')
export const formLoadingInjectionKey: InjectionKey<Readonly<Ref<boolean>>> = Symbol('nuxt-ui.form-loading')
@@ -27,9 +27,6 @@ export function useFormField<T>(props?: Props<T>, opts?: { bind?: boolean, defer
const formInputs = inject(formInputsInjectionKey, undefined)
const inputId = inject(inputIdInjectionKey, undefined)
// Blocks the FormField injection to avoid duplicating events when nesting input components.
provide(formFieldInjectionKey, undefined)
if (formField && inputId) {
if (opts?.bind === false) {
// Removes for="..." attribute on label for RadioGroup and alike.

View File

@@ -7,7 +7,7 @@ import type { ComponentConfig } from '../../types/utils'
type Link = ComponentConfig<typeof theme, AppConfig, 'link'>
interface NuxtLinkProps extends Omit<InertiaLinkProps, 'href' | 'onClick'> {
interface NuxtLinkProps extends Omit<InertiaLinkProps, 'href'> {
activeClass?: string
/**
* Route Location the link should navigate to when clicked on.
@@ -62,11 +62,10 @@ import { computed } from 'vue'
import { defu } from 'defu'
import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core'
import { usePage } from '@inertiajs/vue3'
import { usePage, Link as InertiaLink } from '@inertiajs/vue3'
import { hasProtocol } from 'ufo'
import { useAppConfig } from '#imports'
import { tv } from '../../utils/tv'
import ULinkBase from '../../components/LinkBase.vue'
defineOptions({ inheritAttrs: false })
@@ -79,11 +78,9 @@ const props = withDefaults(defineProps<LinkProps>(), {
})
defineSlots<LinkSlots>()
const page = usePage()
const appConfig = useAppConfig() as Link['AppConfig']
const routerLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'activeClass', 'inactiveClass', 'to', 'href', 'raw', 'custom', 'class'))
const routerLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'activeClass', 'inactiveClass', 'to', 'raw', 'class'))
const ui = computed(() => tv({
extend: tv(theme),
@@ -97,42 +94,14 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {})
}))
const href = computed(() => props.to ?? props.href)
const isExternal = computed(() => {
if (props.external) {
return true
}
if (!href.value) {
return false
}
return typeof href.value === 'string' && hasProtocol(href.value, { acceptRelative: true })
})
const isLinkActive = computed(() => {
if (props.active !== undefined) {
return props.active
}
if (!href.value) {
return false
}
if (props.exact && page.url === href.value) {
return true
}
if (!props.exact && page.url.startsWith(href.value)) {
return true
}
return false
if (props.external) return true
if (!props.to) return false
return typeof props.to === 'string' && hasProtocol(props.to, { acceptRelative: true })
})
const linkClass = computed(() => {
const active = isLinkActive.value
const active = isActive.value
if (props.raw) {
return [props.class, active ? props.activeClass : props.inactiveClass]
@@ -140,36 +109,74 @@ const linkClass = computed(() => {
return ui.value({ class: props.class, active, disabled: props.disabled })
})
const page = usePage()
const url = computed(() => props.to ?? props.href ?? '')
const isActive = computed(() => props.active || (!!url.value && (props.exact ? url.value === props.href : page?.url.startsWith(url.value))))
</script>
<template>
<template v-if="custom">
<slot
<template v-if="!isExternal && !!url">
<InertiaLink v-bind="routerLinkProps" :href="url">
<template v-if="custom">
<slot
v-bind="{
...$attrs,
as,
type,
disabled,
href: url,
active: isActive
}"
/>
</template>
<ULinkBase
v-else
v-bind="{
...$attrs,
as,
type,
disabled,
href: url,
active: isActive
}"
:class="linkClass"
>
<slot :active="isActive" />
</ULinkBase>
</InertiaLink>
</template>
<template v-else>
<template v-if="custom">
<slot
v-bind="{
...$attrs,
as,
type,
disabled,
href: to,
target: isExternal ? '_blank' : undefined,
active: isActive
}"
/>
</template>
<ULinkBase
v-else
v-bind="{
...$attrs,
...routerLinkProps,
as,
type,
disabled,
href,
active: isLinkActive,
isExternal
href: url,
target: isExternal ? '_blank' : undefined,
active: isActive
}"
/>
:is-external="isExternal"
:class="linkClass"
>
<slot :active="isActive" />
</ULinkBase>
</template>
<ULinkBase
v-else
v-bind="{
...$attrs,
...routerLinkProps,
as,
type,
disabled,
href,
isExternal
}"
:class="linkClass"
>
<slot :active="isLinkActive" />
</ULinkBase>
</template>

View File

@@ -1,77 +0,0 @@
<script lang="ts">
import type { LinkProps } from '../../types'
export interface LinkBaseProps {
as?: string
type?: string
disabled?: boolean
onClick?: ((e: MouseEvent) => void | Promise<void>) | Array<((e: MouseEvent) => void | Promise<void>)>
href?: string
target?: LinkProps['target']
active?: boolean
isExternal?: boolean
}
</script>
<script setup lang="ts">
import { Primitive } from 'reka-ui'
import { Link as InertiaLink } from '@inertiajs/vue3'
defineOptions({ inheritAttrs: false })
const props = withDefaults(defineProps<LinkBaseProps>(), {
as: 'button',
type: 'button'
})
function onClickWrapper(e: MouseEvent) {
if (props.disabled) {
e.stopPropagation()
e.preventDefault()
return
}
if (props.onClick) {
for (const onClick of Array.isArray(props.onClick) ? props.onClick : [props.onClick]) {
onClick(e)
}
}
}
</script>
<template>
<InertiaLink
v-if="!!href && !isExternal && !disabled"
:href="href"
v-bind="{
target: target || (isExternal ? '_blank' : undefined),
...$attrs
}"
@click="onClickWrapper"
>
<slot />
</InertiaLink>
<Primitive
v-else
v-bind="href ? {
'as': 'a',
'href': disabled ? undefined : href,
'aria-disabled': disabled ? 'true' : undefined,
'role': disabled ? 'link' : undefined,
'tabindex': disabled ? -1 : undefined,
'target': target || (isExternal ? '_blank' : undefined),
...$attrs
} : as === 'button' ? {
as,
type,
disabled,
...$attrs
} : {
as,
...$attrs
}"
@click="onClickWrapper"
>
<slot />
</Primitive>
</template>

View File

@@ -9,7 +9,6 @@ import { usePage } from '@inertiajs/vue3'
export { useHead } from '@unhead/vue'
export { useAppConfig } from '../vue/composables/useAppConfig'
export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale'
@@ -42,6 +41,8 @@ export const useColorMode = () => {
}
}
export const useAppConfig = () => appConfig
export const useCookie = <T = string>(
_name: string,
_options: Record<string, any> = {}

View File

@@ -32,7 +32,6 @@ export { default as pt_br } from './pt_br'
export { default as ro } from './ro'
export { default as ru } from './ru'
export { default as sk } from './sk'
export { default as sl } from './sl'
export { default as sv } from './sv'
export { default as th } from './th'
export { default as tj } from './tj'

View File

@@ -1,56 +0,0 @@
import type { Messages } from '../types'
import { defineLocale } from '../composables/defineLocale'
export default defineLocale<Messages>({
name: 'Slovenščina',
code: 'sl',
messages: {
inputMenu: {
noMatch: 'Ni ujemanj',
noData: 'Ni podatkov',
create: 'Ustvari "{label}"'
},
calendar: {
prevYear: 'Prejšnje leto',
nextYear: 'Naslednje leto',
prevMonth: 'Prejšnji mesec',
nextMonth: 'Naslednji mesec'
},
inputNumber: {
increment: 'Povišaj',
decrement: 'Zmanjšaj'
},
commandPalette: {
placeholder: 'Vpiši ukaz ali išči...',
noMatch: 'Ni ujemanj',
noData: 'Ni podatkov',
close: 'Zapri'
},
selectMenu: {
noMatch: 'Ni ujemanj',
noData: 'Ni podatkov',
create: 'Ustvari "{label}"',
search: 'Išči...'
},
toast: {
close: 'Zapri'
},
carousel: {
prev: 'Nazaj',
next: 'Naprej',
goto: 'Pojdi na {slide}'
},
modal: {
close: 'Zapri'
},
slideover: {
close: 'Zapri'
},
alert: {
close: 'Zapri'
},
table: {
noData: 'Ni podatkov'
}
}
})

View File

@@ -1,43 +1,13 @@
import { computed } from 'vue'
import colors from 'tailwindcss/colors'
import type { UseHeadInput } from '@unhead/vue/types'
import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports'
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const
function getColor(color: keyof typeof colors, shade: typeof shades[number]): string {
if (color in colors && typeof colors[color] === 'object' && shade in colors[color]) {
return colors[color][shade] as string
}
return ''
}
function generateShades(key: string, value: string) {
return `${shades.map(shade => `--ui-color-${key}-${shade}: var(--color-${value === 'neutral' ? 'old-neutral' : value}-${shade}, ${getColor(value as keyof typeof colors, shade)});`).join('\n ')}`
}
function generateColor(key: string, shade: number) {
return `--ui-${key}: var(--ui-color-${key}-${shade});`
}
import { generateColorStyles } from '../utils/colors'
export default defineNuxtPlugin(() => {
const appConfig = useAppConfig()
const nuxtApp = useNuxtApp()
const root = computed(() => {
const { neutral, ...colors } = appConfig.ui.colors
return `@layer base {
:root {
${Object.entries(appConfig.ui.colors).map(([key, value]: [string, string]) => generateShades(key, value)).join('\n ')}
}
:root, .light {
${Object.keys(colors).map(key => generateColor(key, 500)).join('\n ')}
}
.dark {
${Object.keys(colors).map(key => generateColor(key, 400)).join('\n ')}
}
}`
})
const root = computed(() => generateColorStyles(appConfig.ui.colors))
// Head
const headData: UseHeadInput = {

View File

@@ -0,0 +1,34 @@
import colors from 'tailwindcss/colors'
export const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const
export function getColor(color: keyof typeof colors, shade: typeof shades[number]): string {
if (color in colors && typeof colors[color] === 'object' && shade in colors[color]) {
return colors[color][shade] as string
}
return ''
}
export function generateShades(key: string, value: string) {
return `${shades.map(shade => `--ui-color-${key}-${shade}: var(--color-${value === 'neutral' ? 'old-neutral' : value}-${shade}, ${getColor(value as keyof typeof colors, shade)});`).join('\n ')}`
}
export function generateColor(key: string, shade: number) {
return `--ui-${key}: var(--ui-color-${key}-${shade});`
}
export function generateColorStyles(colors: Record<string, string>) {
const { neutral, ...rest } = colors
return `@layer base {
:root {
${Object.entries(colors).map(([key, value]: [string, string]) => generateShades(key, value)).join('\n ')}
}
:root, .light {
${Object.keys(rest).map(key => generateColor(key, 500)).join('\n ')}
}
.dark {
${Object.keys(rest).map(key => generateColor(key, 400)).join('\n ')}
}
}`
}

View File

@@ -1,5 +1,4 @@
import { reactivePick } from '@vueuse/core'
import { isEqual, diff } from 'ohash/utils'
import type { LinkProps } from '../types'
export function pickLinkProps(link: LinkProps & { [key: string]: any }) {
@@ -20,17 +19,3 @@ export function pickLinkProps(link: LinkProps & { [key: string]: any }) {
return reactivePick(link, ...propsToInclude)
}
export function isPartiallyEqual(item1: any, item2: any) {
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
if (q.type === 'added') {
filtered.add(q.key)
}
return filtered
}, new Set<string>())
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
return isEqual(item1Filtered, item2Filtered)
}

View File

@@ -87,17 +87,15 @@ export interface LinkSlots {
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { computed, getCurrentInstance } from 'vue'
import { defu } from 'defu'
import { isEqual } from 'ohash/utils'
import { isEqual, diff } from 'ohash/utils'
import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core'
import { hasProtocol } from 'ufo'
import { useRoute, RouterLink } from 'vue-router'
import { useAppConfig } from '#imports'
import { tv } from '../../utils/tv'
import { isPartiallyEqual } from '../../utils/link'
import ULinkBase from '../../components/LinkBase.vue'
defineOptions({ inheritAttrs: false })
@@ -111,11 +109,25 @@ const props = withDefaults(defineProps<LinkProps>(), {
})
defineSlots<LinkSlots>()
const route = useRoute()
// Check if vue-router is available by checking for the injection key
const hasRouter = computed(() => {
const app = getCurrentInstance()?.appContext.app
return !!(app?.config?.globalProperties?.$router)
})
// Only try to get route if router exists
const route = computed(() => {
if (!hasRouter.value) return null
try {
return useRoute()
} catch {
return null
}
})
const appConfig = useAppConfig() as Link['AppConfig']
const routerLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'to', 'href', 'raw', 'custom', 'class'))
const routerLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'to', 'raw', 'class'))
const ui = computed(() => tv({
extend: tv(theme),
@@ -129,18 +141,23 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {})
}))
const to = computed(() => props.to ?? props.href)
function isPartiallyEqual(item1: any, item2: any) {
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
if (q.type === 'added') {
filtered.add(q.key)
}
return filtered
}, new Set<string>())
const item1Filtered = Object.fromEntries(Object.entries(item1).filter(([key]) => !diffedKeys.has(key)))
const item2Filtered = Object.fromEntries(Object.entries(item2).filter(([key]) => !diffedKeys.has(key)))
return isEqual(item1Filtered, item2Filtered)
}
const isExternal = computed(() => {
if (props.external) {
return true
}
if (!to.value) {
return false
}
return typeof to.value === 'string' && hasProtocol(to.value, { acceptRelative: true })
if (!props.to) return false
return typeof props.to === 'string' && hasProtocol(props.to, { acceptRelative: true })
})
function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
@@ -148,17 +165,17 @@ function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
return props.active
}
if (!to.value) {
if (!props.to || !route.value) {
return false
}
if (props.exactQuery === 'partial') {
if (!isPartiallyEqual(linkRoute.query, route.query)) return false
if (!isPartiallyEqual(linkRoute.query, route.value.query)) return false
} else if (props.exactQuery === true) {
if (!isEqual(linkRoute.query, route.query)) return false
if (!isEqual(linkRoute.query, route.value.query)) return false
}
if (props.exactHash && linkRoute.hash !== route.hash) {
if (props.exactHash && linkRoute.hash !== route.value.hash) {
return false
}
@@ -185,8 +202,8 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
</script>
<template>
<template v-if="!isExternal && !!to">
<RouterLink v-slot="{ href, navigate, route: linkRoute, isActive, isExactActive }" v-bind="routerLinkProps" :to="to" custom>
<template v-if="hasRouter && !isExternal">
<RouterLink v-slot="{ href, navigate, route: linkRoute, isActive, isExactActive }" v-bind="routerLinkProps" :to="to || '#'" custom>
<template v-if="custom">
<slot
v-bind="{
@@ -195,7 +212,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
as,
type,
disabled,
href,
href: to ? href : undefined,
navigate,
active: isLinkActive({ route: linkRoute, isActive, isExactActive })
}"
@@ -209,7 +226,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
as,
type,
disabled,
href,
href: to ? href : undefined,
navigate
}"
:class="resolveLinkClass({ route: linkRoute, isActive, isExactActive })"
@@ -229,8 +246,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
disabled,
href: to,
target: isExternal ? '_blank' : undefined,
active,
isExternal
active: false
}"
/>
</template>
@@ -242,12 +258,12 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
type,
disabled,
href: (to as string),
target: isExternal ? '_blank' : undefined,
isExternal
target: isExternal ? '_blank' : undefined
}"
:is-external="isExternal"
:class="resolveLinkClass()"
>
<slot :active="active" />
<slot :active="false" />
</ULinkBase>
</template>
</template>

View File

@@ -0,0 +1,35 @@
import { computed, watchEffect } from 'vue'
import { useHead } from '@unhead/vue'
import type { Plugin } from 'vue'
import { useAppConfig } from '../composables/useAppConfig'
import { generateColorStyles } from '../../utils/colors'
export default {
install(app) {
app.runWithContext(() => {
const appConfig = useAppConfig()
const root = computed(() => generateColorStyles(appConfig.ui.colors))
useHead({
style: [{
innerHTML: root,
tagPriority: -2,
id: 'nuxt-ui-colors'
}]
})
if (typeof document !== 'undefined') {
watchEffect(() => {
let styleEl = document.querySelector('#nuxt-ui-colors-vue') as HTMLStyleElement
if (!styleEl) {
styleEl = document.createElement('style')
styleEl.id = 'nuxt-ui-colors-vue'
document.head.appendChild(styleEl)
}
styleEl.innerHTML = root.value
})
}
})
}
} satisfies Plugin

View File

@@ -9,7 +9,6 @@ import { useColorMode as useColorModeVueUse } from '@vueuse/core'
export { useHead } from '@unhead/vue'
export { useRoute, useRouter } from 'vue-router'
export { useAppConfig } from './composables/useAppConfig'
export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale'
@@ -31,6 +30,8 @@ export const useColorMode = () => {
}
}
export const useAppConfig = () => appConfig
export const useCookie = <T = string>(
_name: string,
_options: Record<string, any> = {}

View File

@@ -53,9 +53,6 @@ export default (options: Required<ModuleOptions>) => ({
leadingAvatarSize: '2xs',
trailingIcon: 'size-6'
}
},
square: {
true: ''
}
},
compoundVariants: [...(options.theme.colors || []).map((color: string) => ({
@@ -90,26 +87,6 @@ export default (options: Required<ModuleOptions>) => ({
color: 'neutral',
variant: 'subtle',
class: 'ring ring-inset ring-accented text-default bg-elevated'
}, {
size: 'xs',
square: true,
class: 'p-0.5'
}, {
size: 'sm',
square: true,
class: 'p-1'
}, {
size: 'md',
square: true,
class: 'p-1'
}, {
size: 'lg',
square: true,
class: 'p-1'
}, {
size: 'xl',
square: true,
class: 'p-1'
}],
defaultVariants: {
color: 'primary',

View File

@@ -1,18 +1,18 @@
export const buttonGroupVariant = {
buttonGroup: {
horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none',
vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none'
}
}
export const buttonGroupVariantWithRoot = {
buttonGroup: {
horizontal: {
root: 'group has-focus-visible:z-[1]',
root: 'group',
base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
},
vertical: {
root: 'group has-focus-visible:z-[1]',
root: 'group',
base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
}
}

View File

@@ -1,6 +1,4 @@
import type { ModuleOptions } from '../module'
export default (options: Required<ModuleOptions>) => ({
export default {
slots: {
root: 'relative',
fieldset: 'flex gap-x-2',
@@ -16,17 +14,6 @@ export default (options: Required<ModuleOptions>) => ({
fieldset: 'flex-col'
}
},
color: {
...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, {}])),
neutral: {}
},
variant: {
list: {},
card: {},
table: {
item: 'border border-muted'
}
},
size: {
xs: {
fieldset: 'gap-y-0.5',
@@ -55,53 +42,7 @@ export default (options: Required<ModuleOptions>) => ({
}
}
},
compoundVariants: [
{ size: 'xs', variant: 'table', class: { item: 'p-2.5' } },
{ size: 'sm', variant: 'table', class: { item: 'p-3' } },
{ size: 'md', variant: 'table', class: { item: 'p-3.5' } },
{ size: 'lg', variant: 'table', class: { item: 'p-4' } },
{ size: 'xl', variant: 'table', class: { item: 'p-4.5' } },
{
orientation: 'horizontal',
variant: 'table',
class: {
item: 'first-of-type:rounded-l-lg last-of-type:rounded-r-lg',
fieldset: 'gap-0 -space-x-px'
}
},
{
orientation: 'vertical',
variant: 'table',
class: {
item: 'first-of-type:rounded-t-lg last-of-type:rounded-b-lg',
fieldset: 'gap-0 -space-y-px'
}
},
...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'table',
class: {
item: `has-data-[state=checked]:bg-${color}/10 has-data-[state=checked]:border-${color}/50 has-data-[state=checked]:z-[1]`
}
})),
{
color: 'neutral',
variant: 'table',
class: {
item: 'has-data-[state=checked]:bg-elevated has-data-[state=checked]:border-inverted/50 has-data-[state=checked]:z-[1]'
}
},
{
variant: 'table',
disabled: true,
class: {
item: 'cursor-not-allowed opacity-75'
}
}
],
defaultVariants: {
size: 'md',
variant: 'list',
color: 'primary'
size: 'md'
}
})
}

View File

@@ -1,6 +1,5 @@
import type { ModuleOptions } from '../module'
import inputTheme from './input'
import { buttonGroupVariantWithRoot } from './button-group'
export default (options: Required<ModuleOptions>) => {
const input = inputTheme(options)
@@ -13,7 +12,6 @@ export default (options: Required<ModuleOptions>) => {
decrement: 'absolute flex items-center'
},
variants: {
...buttonGroupVariantWithRoot,
color: {
...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, ''])),
neutral: ''

View File

@@ -5,15 +5,10 @@ export default (options: Required<ModuleOptions>) => ({
variants: {
active: {
true: 'text-primary',
false: 'text-muted'
false: ['text-muted hover:text-default', options.theme.transitions && 'transition-colors']
},
disabled: {
true: 'cursor-not-allowed opacity-75'
}
},
compoundVariants: [{
active: false,
disabled: false,
class: ['hover:text-default', options.theme.transitions && 'transition-colors']
}]
}
})

View File

@@ -21,7 +21,6 @@ describe('Badge', () => {
['with avatar', { props: { avatar: { src: 'https://github.com/benjamincanac.png' } } }],
['with avatar and leadingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, leadingIcon: 'i-lucide-arrow-left' } }],
['with avatar and trailingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, trailingIcon: 'i-lucide-arrow-right' } }],
['with square', { props: { label: 'Badge', square: true } }],
['with as', { props: { label: 'Badge', as: 'div' } }],
['with class', { props: { label: 'Badge', class: 'rounded-full font-bold' } }],
['with ui', { props: { label: 'Badge', ui: { label: 'font-bold' } } }],

View File

@@ -9,7 +9,7 @@ import type { FormInputEvents } from '~/src/module'
describe('CheckboxGroup', () => {
const sizes = Object.keys(theme.variants.size) as any
const variants = Object.keys(theme.variants.variant) as any
const variants = Object.keys(themeCheckbox.variants.variant) as any
const indicators = Object.keys(themeCheckbox.variants.indicator) as any
const items = [

View File

@@ -10,12 +10,10 @@ describe('Link', () => {
['with to', { props: { to: '/' } }],
['with type', { props: { type: 'submit' as const } }],
['with disabled', { props: { disabled: true } }],
['with raw', { props: { raw: true } }],
['with class', { props: { class: 'font-medium' } }],
['with activeClass', { props: { active: true, activeClass: 'text-highlighted' } }],
['with inactiveClass', { props: { active: false, inactiveClass: 'hover:text-primary' } }],
['with raw', { props: { raw: true } }],
['with raw activeClass', { props: { raw: true, active: true, activeClass: 'text-highlighted' } }],
['with raw inactiveClass', { props: { raw: true, active: false, inactiveClass: 'hover:text-primary' } }],
['with class', { props: { class: 'font-medium' } }],
// Slots
['with default slot', { slots: { default: () => 'Default slot' } }]
])('renders %s correctly', async (nameOrHtml: string, options: { props?: LinkProps, slots?: Partial<LinkSlots> }) => {

View File

@@ -84,12 +84,12 @@ describe('NavigationMenu', () => {
it.each([
// Props
['with items', { props }],
['with modelValue', { props: { ...props, modelValue: 'item-0' } }],
['with modelValue', { props: { ...props, modelValue: '0' } }],
['with labelKey', { props: { ...props, labelKey: 'icon' } }],
['with arrow', { props: { ...props, arrow: true, modelValue: 'item-0' } }],
['with orientation vertical', { props: { ...props, orientation: 'vertical' as const, modelValue: 'item-0' } }],
['with orientation vertical and collapsed', { props: { ...props, orientation: 'vertical' as const, modelValue: 'item-0', collapsed: true } }],
['with content orientation vertical', { props: { ...props, contentOrientation: 'vertical' as const, modelValue: 'item-0' } }],
['with arrow', { props: { ...props, arrow: true, modelValue: '0' } }],
['with orientation vertical', { props: { ...props, orientation: 'vertical' as const, modelValue: '0' } }],
['with orientation vertical and collapsed', { props: { ...props, orientation: 'vertical' as const, modelValue: '0', collapsed: true } }],
['with content orientation vertical', { props: { ...props, contentOrientation: 'vertical' as const, modelValue: '0' } }],
...variants.map((variant: string) => [`with primary variant ${variant}`, { props: { ...props, variant } }]),
...variants.map((variant: string) => [`with neutral variant ${variant}`, { props: { ...props, variant, color: 'neutral' } }]),
...variants.map((variant: string) => [`with primary variant ${variant} highlight`, { props: { ...props, variant, highlight: true } }]),

View File

@@ -7,15 +7,15 @@ exports[`Badge > renders with as correctly 1`] = `
</div>"
`;
exports[`Badge > renders with avatar and leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with avatar and leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with avatar and trailingIcon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
<!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"
`;
exports[`Badge > renders with avatar correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
<!--v-if-->
<!--v-if--></span>"
`;
@@ -27,18 +27,18 @@ exports[`Badge > renders with class correctly 1`] = `
exports[`Badge > renders with default slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if-->Default slot<!--v-if--></span>"`;
exports[`Badge > renders with icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with label correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate">Badge</span>
<!--v-if--></span>"
`;
exports[`Badge > renders with leading and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leading and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1">Leading slot<!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted">Leading slot<!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leadingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg><!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with neutral variant outline correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md ring ring-inset ring-accented text-default bg-default"><!--v-if--><span class="truncate">Badge</span>
@@ -105,16 +105,11 @@ exports[`Badge > renders with size xs correctly 1`] = `
<!--v-if--></span>"
`;
exports[`Badge > renders with square correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><span class="truncate">Badge</span>
<!--v-if--></span>"
`;
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if-->Trailing slot</span>"`;
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if-->Trailing slot</span>"`;
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-4" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>"`;
exports[`Badge > renders with ui correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate font-bold">Badge</span>

View File

@@ -8,18 +8,18 @@ exports[`Badge > renders with as correctly 1`] = `
`;
exports[`Badge > renders with avatar and leadingIcon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
<!--v-if-->
<!--v-if--></span>"
`;
exports[`Badge > renders with avatar and trailingIcon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
<!--v-if--><span class="iconify i-lucide:arrow-right shrink-0 size-4" aria-hidden="true"></span></span>"
`;
exports[`Badge > renders with avatar correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="inline-flex items-center justify-center select-none overflow-hidden rounded-full align-middle bg-elevated size-4 text-[8px] shrink-0"><img role="img" src="https://github.com/benjamincanac.png" width="16" height="16" class="h-full w-full rounded-[inherit] object-cover"></span>
<!--v-if-->
<!--v-if--></span>"
`;
@@ -32,7 +32,7 @@ exports[`Badge > renders with class correctly 1`] = `
exports[`Badge > renders with default slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if-->Default slot<!--v-if--></span>"`;
exports[`Badge > renders with icon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="iconify i-lucide:rocket shrink-0 size-4" aria-hidden="true"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="iconify i-lucide:rocket shrink-0 size-4" aria-hidden="true"></span>
<!--v-if-->
<!--v-if--></span>"
`;
@@ -43,15 +43,15 @@ exports[`Badge > renders with label correctly 1`] = `
`;
exports[`Badge > renders with leading and icon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
<!--v-if-->
<!--v-if--></span>"
`;
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1">Leading slot<!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leading slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted">Leading slot<!--v-if--><!--v-if--></span>"`;
exports[`Badge > renders with leadingIcon correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><span class="iconify i-lucide:arrow-left shrink-0 size-4" aria-hidden="true"></span>
<!--v-if-->
<!--v-if--></span>"
`;
@@ -121,16 +121,11 @@ exports[`Badge > renders with size xs correctly 1`] = `
<!--v-if--></span>"
`;
exports[`Badge > renders with square correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><span class="truncate">Badge</span>
<!--v-if--></span>"
`;
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><span class="iconify i-lucide:arrow-right shrink-0 size-4" aria-hidden="true"></span></span>"`;
exports[`Badge > renders with trailing and icon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if--><span class="iconify i-lucide:arrow-right shrink-0 size-4" aria-hidden="true"></span></span>"`;
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if-->Trailing slot</span>"`;
exports[`Badge > renders with trailing slot correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if-->Trailing slot</span>"`;
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs gap-1 rounded-md bg-primary text-inverted p-1"><!--v-if--><!--v-if--><span class="iconify i-lucide:arrow-right shrink-0 size-4" aria-hidden="true"></span></span>"`;
exports[`Badge > renders with trailingIcon correctly 1`] = `"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><!--v-if--><span class="iconify i-lucide:arrow-right shrink-0 size-4" aria-hidden="true"></span></span>"`;
exports[`Badge > renders with ui correctly 1`] = `
"<span class="font-medium inline-flex items-center text-xs px-2 py-1 gap-1 rounded-md bg-primary text-inverted"><!--v-if--><span class="truncate font-bold">Badge</span>

View File

@@ -2,10 +2,10 @@
exports[`ButtonGroup > renders orientation vertical with default slot correctly 1`] = `
"<div class="relative flex flex-col -space-y-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -18,10 +18,10 @@ exports[`ButtonGroup > renders with class correctly 1`] = `"<div class="inline-f
exports[`ButtonGroup > renders with default slot correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -30,10 +30,10 @@ exports[`ButtonGroup > renders with default slot correctly 1`] = `
exports[`ButtonGroup > renders with size lg correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-sm gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-sm gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-3 py-2 text-sm gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-3 py-2 text-sm gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -42,10 +42,10 @@ exports[`ButtonGroup > renders with size lg correctly 1`] = `
exports[`ButtonGroup > renders with size md correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -54,10 +54,10 @@ exports[`ButtonGroup > renders with size md correctly 1`] = `
exports[`ButtonGroup > renders with size sm correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-xs gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -66,10 +66,10 @@ exports[`ButtonGroup > renders with size sm correctly 1`] = `
exports[`ButtonGroup > renders with size xl correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-base gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-base gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-3 py-2 text-base gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-3 py-2 text-base gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -78,10 +78,10 @@ exports[`ButtonGroup > renders with size xl correctly 1`] = `
exports[`ButtonGroup > renders with size xs correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2 py-1 text-xs gap-1 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2 py-1 text-xs gap-1 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2 py-1 text-xs gap-1 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2 py-1 text-xs gap-1 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>

View File

@@ -2,10 +2,10 @@
exports[`ButtonGroup > renders orientation vertical with default slot correctly 1`] = `
"<div class="relative flex flex-col -space-y-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -18,10 +18,10 @@ exports[`ButtonGroup > renders with class correctly 1`] = `"<div class="inline-f
exports[`ButtonGroup > renders with default slot correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -30,10 +30,10 @@ exports[`ButtonGroup > renders with default slot correctly 1`] = `
exports[`ButtonGroup > renders with size lg correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-sm gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-sm gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-3 py-2 text-sm gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-3 py-2 text-sm gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -42,10 +42,10 @@ exports[`ButtonGroup > renders with size lg correctly 1`] = `
exports[`ButtonGroup > renders with size md correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-sm gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -54,10 +54,10 @@ exports[`ButtonGroup > renders with size md correctly 1`] = `
exports[`ButtonGroup > renders with size sm correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2.5 py-1.5 text-xs gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2.5 py-1.5 text-xs gap-1.5 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -66,10 +66,10 @@ exports[`ButtonGroup > renders with size sm correctly 1`] = `
exports[`ButtonGroup > renders with size xl correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-base gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-3 py-2 text-base gap-2 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-3 py-2 text-base gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-3 py-2 text-base gap-2 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>
@@ -78,10 +78,10 @@ exports[`ButtonGroup > renders with size xl correctly 1`] = `
exports[`ButtonGroup > renders with size xs correctly 1`] = `
"<div class="relative inline-flex -space-x-px">
<div class="relative inline-flex items-center group has-focus-visible:z-[1]"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2 py-1 text-xs gap-1 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<div class="relative inline-flex items-center group"><input type="text" class="w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none px-2 py-1 text-xs gap-1 text-highlighted bg-default ring ring-inset ring-accented focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary" autocomplete="off">
<!--v-if-->
<!--v-if-->
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1] px-2 py-1 text-xs gap-1 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
</div> <button type="button" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none px-2 py-1 text-xs gap-1 text-inverted bg-primary hover:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
<!--v-if--> Click me!
<!--v-if-->
</button>

View File

@@ -1,187 +1,191 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Checkbox > renders with ariaLabel correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button aria-label="Aria label" class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with as correctly 1`] = `
"<section class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</section>"
</label>"
`;
exports[`Checkbox > renders with class correctly 1`] = `
"<div class="relative items-start flex-row inline-flex">
"<label class="relative items-start flex-row inline-flex">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with defaultValue correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="true" aria-required="false" data-state="checked"><span data-state="checked" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-full" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with description correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0" class="block font-medium text-default">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0" class="block font-medium text-default">Label</p>
<p class="text-muted">Description</p>
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with description slot correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0" class="block font-medium text-default">Description slot</label>
<div class="w-full ms-2 text-sm">
<p for="v-0" class="block font-medium text-default">Description slot</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with disabled correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4 cursor-not-allowed opacity-75" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked" data-disabled="" disabled="">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with icon correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with id correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="id" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indeterminate correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="mixed" aria-required="false" data-state="indeterminate"><span data-state="indeterminate" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-full" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indeterminateIcon correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="mixed" aria-required="false" data-state="indeterminate"><span data-state="indeterminate" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-full" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator end correctly 1`] = `
"<div class="relative flex items-start flex-row-reverse">
"<label class="relative flex items-start flex-row-reverse">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator hidden correctly 1`] = `
"<div class="relative flex items-start">
"<label class="relative flex items-start">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary sr-only size-4" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator start correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with label correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0" class="block font-medium text-default">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0" class="block font-medium text-default">Label</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with label slot correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0" class="block font-medium text-default">Label slot</label>
<div class="w-full ms-2 text-sm">
<p for="v-0" class="block font-medium text-default">Label slot</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with modelValue correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="true" aria-required="false" data-state="checked"><span data-state="checked" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="shrink-0 size-full" width="1em" height="1em" viewBox="0 0 16 16"></svg></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with name correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with neutral variant card correctly 1`] = `
@@ -225,83 +229,84 @@ exports[`Checkbox > renders with primary variant list correctly 1`] = `
`;
exports[`Checkbox > renders with required correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="true" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0" class="block font-medium text-default after:content-['*'] after:ms-0.5 after:text-error">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0" class="block font-medium text-default after:content-['*'] after:ms-0.5 after:text-error">Label</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with size lg correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4.5" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size md correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size sm correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-4"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-3.5" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size xl correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-6"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-5" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size xs correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-4"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-3" id="v-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with ui correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with value correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;

View File

@@ -1,187 +1,191 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Checkbox > renders with ariaLabel correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button aria-label="Aria label" class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with as correctly 1`] = `
"<section class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</section>"
</label>"
`;
exports[`Checkbox > renders with class correctly 1`] = `
"<div class="relative items-start flex-row inline-flex">
"<label class="relative items-start flex-row inline-flex">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with defaultValue correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="true" aria-required="false" data-state="checked"><span data-state="checked" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><span class="iconify i-lucide:check shrink-0 size-full" aria-hidden="true"></span></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with description correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0-0" class="block font-medium text-default">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0-0" class="block font-medium text-default">Label</p>
<p class="text-muted">Description</p>
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with description slot correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0-0" class="block font-medium text-default">Description slot</label>
<div class="w-full ms-2 text-sm">
<p for="v-0-0" class="block font-medium text-default">Description slot</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with disabled correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4 cursor-not-allowed opacity-75" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked" data-disabled="" disabled="">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with icon correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with id correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="id" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indeterminate correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="mixed" aria-required="false" data-state="indeterminate"><span data-state="indeterminate" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><span class="iconify i-lucide:minus shrink-0 size-full" aria-hidden="true"></span></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indeterminateIcon correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="mixed" aria-required="false" data-state="indeterminate"><span data-state="indeterminate" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><span class="iconify i-lucide:trash shrink-0 size-full" aria-hidden="true"></span></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator end correctly 1`] = `
"<div class="relative flex items-start flex-row-reverse">
"<label class="relative flex items-start flex-row-reverse">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator hidden correctly 1`] = `
"<div class="relative flex items-start">
"<label class="relative flex items-start">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary sr-only size-4" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with indicator start correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with label correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0-0" class="block font-medium text-default">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0-0" class="block font-medium text-default">Label</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with label slot correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0-0" class="block font-medium text-default">Label slot</label>
<div class="w-full ms-2 text-sm">
<p for="v-0-0" class="block font-medium text-default">Label slot</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with modelValue correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="true" aria-required="false" data-state="checked"><span data-state="checked" style="pointer-events: none;" class="flex items-center justify-center size-full text-inverted bg-primary"><span class="iconify i-lucide:check shrink-0 size-full" aria-hidden="true"></span></span>
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with name correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with neutral variant card correctly 1`] = `
@@ -225,83 +229,84 @@ exports[`Checkbox > renders with primary variant list correctly 1`] = `
`;
exports[`Checkbox > renders with required correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="true" data-state="unchecked">
<!---->
<!---->
</button></div>
<div class="w-full ms-2 text-sm"><label for="v-0-0" class="block font-medium text-default after:content-['*'] after:ms-0.5 after:text-error">Label</label>
<div class="w-full ms-2 text-sm">
<p for="v-0-0" class="block font-medium text-default after:content-['*'] after:ms-0.5 after:text-error">Label</p>
<!--v-if-->
</div>
</div>"
</label>"
`;
exports[`Checkbox > renders with size lg correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4.5" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size md correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size sm correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-4"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-3.5" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size xl correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-6"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-5" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with size xs correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-4"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-3" id="v-0-0" role="checkbox" type="button" aria-checked="1" aria-required="false" data-state="checked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with ui correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;
exports[`Checkbox > renders with value correctly 1`] = `
"<div class="relative flex items-start flex-row">
"<label class="relative flex items-start flex-row">
<div class="flex items-center h-5"><button class="rounded-sm ring ring-inset ring-accented overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary size-4" id="v-0-0" role="checkbox" type="button" aria-checked="false" aria-required="false" data-state="unchecked">
<!---->
<!---->
</button></div>
<!--v-if-->
</div>"
</label>"
`;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@ exports[`Form > custom validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -87,7 +87,7 @@ exports[`Form > joi validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -153,7 +153,7 @@ exports[`Form > superstruct validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -215,7 +215,7 @@ exports[`Form > valibot validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -277,7 +277,7 @@ exports[`Form > yup validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -339,7 +339,7 @@ exports[`Form > zod validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"

View File

@@ -25,7 +25,7 @@ exports[`Form > custom validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -87,7 +87,7 @@ exports[`Form > joi validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -153,7 +153,7 @@ exports[`Form > superstruct validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -215,7 +215,7 @@ exports[`Form > valibot validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -277,7 +277,7 @@ exports[`Form > yup validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"
@@ -339,7 +339,7 @@ exports[`Form > zod validation works > with error 1`] = `
<!--v-if-->
<!--v-if-->
</div>
<div id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</div>
<p id="v-0-0-1-error" class="mt-2 text-error">Must be at least 8 characters</p>
</div>
</div>
</form>"

View File

@@ -55,7 +55,7 @@ exports[`FormField > renders with error correctly 1`] = `
<!--v-if-->
</div>
<div class="">
<div id="v-0-0-error" class="mt-2 text-error">Username is already taken</div>
<p id="v-0-0-error" class="mt-2 text-error">Username is already taken</p>
</div>
</div>"
`;
@@ -67,7 +67,7 @@ exports[`FormField > renders with error slot correctly 1`] = `
<!--v-if-->
</div>
<div class="">
<div id="v-0-0-error" class="mt-2 text-error">Error slot</div>
<p id="v-0-0-error" class="mt-2 text-error">Error slot</p>
</div>
</div>"
`;
@@ -79,7 +79,7 @@ exports[`FormField > renders with help correctly 1`] = `
<!--v-if-->
</div>
<div class="">
<div class="mt-2 text-muted">Username must be unique</div>
<p class="mt-2 text-muted">Username must be unique</p>
</div>
</div>"
`;
@@ -91,7 +91,7 @@ exports[`FormField > renders with help slot correctly 1`] = `
<!--v-if-->
</div>
<div class="">
<div class="mt-2 text-muted">Help slot</div>
<p class="mt-2 text-muted">Help slot</p>
</div>
</div>"
`;

Some files were not shown because too many files have changed in this diff Show More