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 # 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) ## [3.1.1](https://github.com/nuxt/ui/compare/v3.1.0...v3.1.1) (2025-05-02)
### Features ### Features

View File

@@ -12,6 +12,7 @@ const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSe
}) })
const links = useLinks() const links = useLinks()
const searchLinks = useSearchLinks()
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white') 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 radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}') const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
@@ -41,6 +42,7 @@ useServerSeoMeta({
useFaviconFromTheme() useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation) const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
provide('navigation', mappedNavigation) provide('navigation', mappedNavigation)
@@ -51,7 +53,7 @@ provide('navigation', mappedNavigation)
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" /> <NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
<template v-if="!route.path.startsWith('/examples')"> <template v-if="!route.path.startsWith('/examples')">
<!-- <Banner /> --> <Banner />
<Header :links="links" /> <Header :links="links" />
</template> </template>
@@ -63,7 +65,23 @@ provide('navigation', mappedNavigation)
<template v-if="!route.path.startsWith('/examples')"> <template v-if="!route.path.startsWith('/examples')">
<Footer /> <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> </template>
</UApp> </UApp>
</template> </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> </script>
<template> <template>
<ProseCollapsible v-if="schemaProps?.length" class="mt-1 mb-0"> <ProseCollapsible v-if="schemaProps?.length" class="mt-1">
<ProseUl> <ProseUl>
<ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name"> <ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name">
<HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" /> <HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" />

View File

@@ -26,7 +26,6 @@ function getEmojiFlag(locale: string): string {
km: 'kh', // Khmer -> Cambodia km: 'kh', // Khmer -> Cambodia
ko: 'kr', // Korean -> South Korea ko: 'kr', // Korean -> South Korea
nb: 'no', // Norwegian Bokmål -> Norway nb: 'no', // Norwegian Bokmål -> Norway
sl: 'si', // Slovenian -> Slovenia
sv: 'se', // Swedish -> Sweden sv: 'se', // Swedish -> Sweden
uk: 'ua', // Ukrainian -> Ukraine uk: 'ua', // Ukrainian -> Ukraine
ur: 'pk', // Urdu -> Pakistan 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 links = useLinks()
const searchLinks = useSearchLinks()
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white') 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 radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}') const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
@@ -48,6 +49,7 @@ useServerSeoMeta({
useFaviconFromTheme() useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation) const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
provide('navigation', mappedNavigation) provide('navigation', mappedNavigation)
@@ -57,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp> <UApp>
<NuxtLoadingIndicator color="#FFF" /> <NuxtLoadingIndicator color="#FFF" />
<!-- <Banner /> --> <Banner />
<Header :links="links" /> <Header :links="links" />
@@ -65,6 +67,22 @@ provide('navigation', mappedNavigation)
<Footer /> <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> </UApp>
</template> </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 type = page.value?.path.includes('components') ? 'Vue Component ' : page.value?.path.includes('composables') ? 'Vue Composable ' : ''
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
useSeoMeta({ useSeoMeta({
titleTemplate: `${prefix}%s ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`, titleTemplate: `%s ${type}- Nuxt UI ${page.value.module === 'ui-pro' ? 'Pro' : ''} ${page.value.framework === 'vue' ? ' for Vue' : ''}`,
title, title: page.value.navigation?.title ? page.value.navigation.title : page.value.title,
ogTitle: `${prefix}${title} ${suffix}- Nuxt UI ${page.value?.module === 'ui-pro' ? 'Pro' : ''} ${page.value?.framework === 'vue' ? ' for Vue' : ''}`, 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, description: page.value.description,
ogDescription: description ogDescription: page.value.description
}) })
if (route.path.startsWith('/components')) { if (route.path.startsWith('/components')) {

View File

@@ -1,20 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute() const route = useRoute()
const colorMode = useColorMode()
const appConfig = useAppConfig()
const name = route.params.slug?.[0] 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') 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> </script>

View File

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

View File

@@ -67,6 +67,17 @@ defineOgImageComponent('Docs', {
</li> </li>
</ul> </ul>
</div> </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> </UPageHero>
</UMain> </UMain>
</template> </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 ### Extend colors
::framework-only ::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"} - `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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"} - `label?: string`{lang="ts-type"}
- `icon?: string`{lang="ts-type"} - `icon?: string`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"} - `avatar?: AvatarProps`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `class?: any`{lang="ts-type"} - `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. 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`: 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 ::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"} - `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key) - [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"} - `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 ::component-code
--- ---
@@ -201,7 +199,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
color: 'primary' color: 'primary'
variant: 'card' variant: 'card'
@@ -232,7 +229,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
size: 'xl' size: 'xl'
variant: 'list' variant: 'list'
@@ -263,7 +259,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
orientation: 'horizontal' orientation: 'horizontal'
variant: 'list' variant: 'list'
@@ -298,7 +293,6 @@ items:
variant: variant:
- list - list
- card - card
- table
props: props:
indicator: 'end' indicator: 'end'
variant: 'card' 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"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e?: Event): void`{lang="ts-type"} - `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. 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) - [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items) - [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: ContextMenuItem[] | ContextMenuItem[][]`{lang="ts-type"} - `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. 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) - [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items)
- [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items) - [`onUpdateChecked?(checked: boolean): void`{lang="ts-type"}](#with-checkbox-items)
- `children?: DropdownMenuItem[] | DropdownMenuItem[][]`{lang="ts-type"} - `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. 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) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{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 ::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"} - `open?: boolean`{lang="ts-type"}
- `value?: string`{lang="ts-type"} - `value?: string`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `class?: any`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`slot?: string`{lang="ts-type"}](#with-custom-slot)
- `onSelect?(e: Event): void`{lang="ts-type"} - `onSelect?(e: Event): void`{lang="ts-type"}
- `children?: NavigationMenuChildItem[]`{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. 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` - `label: string`
- `description?: string` - `description?: string`
- `icon?: string` - `icon?: string`
- `onSelect?(e: Event): void`
- `class?: any` - `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. Use the `orientation` prop to change the orientation of the NavigationMenu.
::note ::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 ::component-code
@@ -242,108 +241,6 @@ props:
Groups will be spaced when orientation is `horizontal` and separated when orientation is `vertical`. 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 ### Highlight
Use the `highlight` prop to display a highlighted border for the active item. 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 ## 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 ### 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. 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"} - `description?: string`{lang="ts-type"}
- [`value?: string`{lang="ts-type"}](#value-key) - [`value?: string`{lang="ts-type"}](#value-key)
- `disabled?: boolean`{lang="ts-type"} - `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 ::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) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- `onSelect?(e: Event): void`{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 ::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) - [`avatar?: AvatarProps`{lang="ts-type"}](#with-avatar-in-items)
- [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items) - [`chip?: ChipProps`{lang="ts-type"}](#with-chip-in-items)
- `disabled?: boolean`{lang="ts-type"} - `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 ::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. 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"} - `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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"} - `value?: string | number`{lang="ts-type"}
- `disabled?: boolean`{lang="ts-type"} - `disabled?: boolean`{lang="ts-type"}
- [`slot?: string`{lang="ts-type"}](#with-custom-slot) - [`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 ::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"} - `children?: TreeItem[]`{lang="ts-type"}
- `onToggle?(e: Event): void`{lang="ts-type"} - `onToggle?(e: Event): void`{lang="ts-type"}
- `onSelect?(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 ::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. 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", "name": "@nuxt/ui-docs",
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@ai-sdk/vue": "^1.2.12", "@ai-sdk/vue": "^1.2.11",
"@iconify-json/logos": "^1.2.4", "@iconify-json/logos": "^1.2.4",
"@iconify-json/lucide": "^1.2.43", "@iconify-json/lucide": "^1.2.41",
"@iconify-json/simple-icons": "^1.2.34", "@iconify-json/simple-icons": "^1.2.33",
"@iconify-json/vscode-icons": "^1.2.21", "@iconify-json/vscode-icons": "^1.2.20",
"@nuxt/content": "^3.5.1", "@nuxt/content": "^3.5.1",
"@nuxt/image": "^1.10.0", "@nuxt/image": "^1.10.0",
"@nuxt/ui": "latest", "@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", "@nuxthub/core": "^0.8.27",
"@nuxtjs/plausible": "^1.2.0", "@nuxtjs/plausible": "^1.2.0",
"@octokit/rest": "^21.1.1", "@octokit/rest": "^21.1.1",
"@rollup/plugin-yaml": "^4.1.2", "@rollup/plugin-yaml": "^4.1.2",
"@vueuse/integrations": "^13.2.0", "@vueuse/integrations": "^13.1.0",
"@vueuse/nuxt": "^13.2.0", "@vueuse/nuxt": "^13.1.0",
"ai": "^4.3.15", "ai": "^4.3.15",
"capture-website": "^4.2.0", "capture-website": "^4.2.0",
"joi": "^17.13.3", "joi": "^17.13.3",
"motion-v": "^1.0.2", "motion-v": "^1.0.2",
"nuxt": "^3.17.3", "nuxt": "^3.17.2",
"nuxt-component-meta": "^0.11.0", "nuxt-component-meta": "^0.11.0",
"nuxt-llms": "^0.1.2", "nuxt-llms": "^0.1.2",
"nuxt-og-image": "^5.1.3", "nuxt-og-image": "^5.1.3",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"shiki-stream": "^0.1.2",
"shiki-transformer-color-highlight": "^1.0.0", "shiki-transformer-color-highlight": "^1.0.0",
"sortablejs": "^1.15.6", "sortablejs": "^1.15.6",
"superstruct": "^2.0.2", "superstruct": "^2.0.2",
"ufo": "^1.6.1", "ufo": "^1.6.1",
"valibot": "^1.1.0", "valibot": "^1.1.0",
"workers-ai-provider": "^0.4.1", "workers-ai-provider": "^0.3.1",
"yup": "^1.6.1", "yup": "^1.6.1",
"zod": "^3.24.4" "zod": "^3.24.4"
}, },
"devDependencies": { "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 { createWorkersAI } from 'workers-ai-provider'
import { z } from 'zod'
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const { messages } = await readBody(event) const { messages } = await readBody(event)
@@ -13,30 +12,11 @@ export default defineEventHandler(async (event) => {
} }
: undefined : undefined
const workersAI = createWorkersAI({ binding: hubAI(), gateway }) const workersAI = createWorkersAI({ binding: hubAI(), gateway })
const autorag = hubAutoRAG('ui3')
return streamText({ return streamText({
model: workersAI('@cf/meta/llama-3.3-70b-instruct-fp8-fast'), model: workersAI('@cf/meta/llama-3.2-3b-instruct'),
messages, maxTokens: 10000,
system: `You are a helpful assistant for Nuxt UI. Check your knowledge base before answering any questions. system: 'You are a helpful assistant that can answer questions and help.',
Only respond to questions using information from tool calls. messages
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
}
})
}
}).toDataStreamResponse() }).toDataStreamResponse()
}) })

View File

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

View File

@@ -11,12 +11,12 @@
}, },
"dependencies": { "dependencies": {
"@nuxt/ui": "latest", "@nuxt/ui": "latest",
"vue": "^3.5.14", "vue": "^3.5.13",
"vue-router": "^4.5.1", "vue-router": "^4.5.1",
"zod": "^3.24.4" "zod": "^3.24.4"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.2.4", "@vitejs/plugin-vue": "^5.2.3",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"vite": "^6.3.5", "vite": "^6.3.5",
"vue-tsc": "^2.2.10" "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" color="neutral"
/> />
</div> </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" /> <UBadge v-for="size in sizes" :key="size" label="Badge" :size="size" />
</div> </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" /> <UBadge v-for="size in sizes" :key="size" icon="i-lucide-rocket" label="Badge" :size="size" />
</div> </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" /> <UBadge v-for="size in sizes" :key="size" :avatar="{ src: 'https://github.com/benjamincanac.png' }" label="Badge" :size="size" />
</div> </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> </div>
</template> </template>

View File

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

View File

@@ -9,11 +9,11 @@
"typecheck": "nuxt typecheck" "typecheck": "nuxt typecheck"
}, },
"dependencies": { "dependencies": {
"@iconify-json/lucide": "^1.2.43", "@iconify-json/lucide": "^1.2.41",
"@iconify-json/simple-icons": "^1.2.34", "@iconify-json/simple-icons": "^1.2.33",
"@nuxt/ui": "latest", "@nuxt/ui": "latest",
"@nuxthub/core": "^0.8.27", "@nuxthub/core": "^0.8.27",
"nuxt": "^3.17.3", "nuxt": "^3.17.2",
"zod": "^3.24.4" "zod": "^3.24.4"
}, },
"devDependencies": { "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', { await registerModule('@nuxt/icon', 'icon', { cssLayer: 'components' })
cssLayer: 'components'
})
if (options.fonts) { if (options.fonts) {
await registerModule('@nuxt/fonts', 'fonts', { await registerModule('@nuxt/fonts', 'fonts', {})
defaults: {
weights: [400, 500, 600, 700]
}
})
} }
if (options.colorMode) { if (options.colorMode) {
await registerModule('@nuxtjs/color-mode', 'colorMode', { await registerModule('@nuxtjs/color-mode', 'colorMode', { classSuffix: '', disableTransition: true })
classSuffix: '',
disableTransition: true
})
} }
addPlugin({ src: resolve('./runtime/plugins/colors') }) 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 }) 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.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) { if (options.colorMode) {
plugins.push(resolvePathSync('../runtime/vue/plugins/color-mode', { extensions: ['.ts', '.mjs', '.js'], url: import.meta.url })) 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. */ /** A unique value for the accordion item. Defaults to the index. */
value?: string value?: string
disabled?: boolean disabled?: boolean
class?: any
ui?: Pick<Accordion['slots'], 'item' | 'header' | 'trigger' | 'leadingIcon' | 'label' | 'trailingIcon' | 'content' | 'body'>
[key: string]: any [key: string]: any
} }
@@ -98,27 +96,27 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.accordion ||
:key="index" :key="index"
:value="item.value || String(index)" :value="item.value || String(index)"
:disabled="item.disabled" :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] })"> <AccordionHeader as="div" :class="ui.header({ class: props.ui?.header })">
<AccordionTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger], disabled: item.disabled })"> <AccordionTrigger :class="ui.trigger({ class: props.ui?.trigger, disabled: item.disabled })">
<slot name="leading" :item="item" :index="index" :open="open"> <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> </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> <slot :item="item" :index="index" :open="open">{{ get(item, props.labelKey as string) }}</slot>
</span> </span>
<slot name="trailing" :item="item" :index="index" :open="open"> <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> </slot>
</AccordionTrigger> </AccordionTrigger>
</AccordionHeader> </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"> <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"> <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 }} {{ item.content }}
</slot> </slot>

View File

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

View File

@@ -15,8 +15,6 @@ export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
icon?: string icon?: string
avatar?: AvatarProps avatar?: AvatarProps
slot?: string slot?: string
class?: any
ui?: Pick<Breadcrumb['slots'], 'item' | 'link' | 'linkLeadingIcon' | 'linkLeadingAvatar' | 'linkLabel' | 'separator' | 'separatorIcon'>
[key: string]: any [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] })"> <Primitive :as="as" aria-label="breadcrumb" :class="ui.root({ class: [props.ui?.root, props.class] })">
<ol :class="ui.list({ class: props.ui?.list })"> <ol :class="ui.list({ class: props.ui?.list })">
<template v-for="(item, index) in items" :key="index"> <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> <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') 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"> <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 })" /> <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, item.ui?.linkLeadingAvatar], 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> </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"> <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) }} {{ get(item, props.labelKey as string) }}
</slot> </slot>
@@ -107,9 +105,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb |
</ULink> </ULink>
</li> </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"> <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> </slot>
</li> </li>
</template> </template>

View File

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

View File

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

View File

@@ -101,7 +101,7 @@ function onUpdate(value: any) {
<!-- eslint-disable vue/no-template-shadow --> <!-- eslint-disable vue/no-template-shadow -->
<template> <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 })"> <div :class="ui.container({ class: props.ui?.container })">
<CheckboxRoot <CheckboxRoot
:id="id" :id="id"
@@ -122,7 +122,7 @@ function onUpdate(value: any) {
</div> </div>
<div v-if="(label || !!slots.label) || (description || !!slots.description)" :class="ui.wrapper({ class: props.ui?.wrapper })"> <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"> <slot name="label" :label="label">
{{ label }} {{ label }}
</slot> </slot>

View File

@@ -14,12 +14,10 @@ export type CheckboxGroupItem = {
description?: string description?: string
disabled?: boolean disabled?: boolean
value?: string value?: string
class?: any
ui?: Pick<CheckboxGroup['slots'], 'item'> & Omit<Required<CheckboxProps>['ui'], 'root'>
[key: string]: any [key: string]: any
} | CheckboxGroupValue } | 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. * The element or component this component should render as.
* @defaultValue 'div' * @defaultValue 'div'
@@ -46,10 +44,6 @@ export interface CheckboxGroupProps<T extends CheckboxGroupItem = CheckboxGroupI
* @defaultValue 'md' * @defaultValue 'md'
*/ */
size?: CheckboxGroup['variants']['size'] size?: CheckboxGroup['variants']['size']
/**
* @defaultValue 'list'
*/
variant?: CheckboxGroup['variants']['variant']
/** /**
* The orientation the checkbox buttons are laid out. * The orientation the checkbox buttons are laid out.
* @defaultValue 'vertical' * @defaultValue 'vertical'
@@ -103,9 +97,7 @@ const id = _id.value ?? useId()
const ui = computed(() => tv({ extend: theme, ...(appConfig.ui?.checkboxGroup || {}) })({ const ui = computed(() => tv({ extend: theme, ...(appConfig.ui?.checkboxGroup || {}) })({
size: size.value, size: size.value,
required: props.required, required: props.required,
orientation: props.orientation, orientation: props.orientation
color: props.color,
variant: props.variant
})) }))
function normalizeItem(item: any) { function normalizeItem(item: any) {
@@ -179,8 +171,8 @@ function onUpdate(value: any) {
:size="size" :size="size"
:name="name" :name="name"
:disabled="item.disabled || disabled" :disabled="item.disabled || disabled"
:ui="{ ...(props.ui ? omit(props.ui, ['root']) : undefined), ...(item.ui || {}) }" :ui="props.ui ? omit(props.ui, ['root']) : undefined"
:class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class] })" :class="ui.item({ class: props.ui?.item })"
> >
<template v-for="(_, name) in proxySlots" #[name]> <template v-for="(_, name) in proxySlots" #[name]>
<slot :name="(name as keyof CheckboxGroupSlots<T>)" :item="item" /> <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 disabled?: boolean
slot?: string slot?: string
onSelect?(e?: Event): void 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 [key: string]: any
} }
@@ -295,42 +293,42 @@ const groups = computed(() => {
@select="item.onSelect" @select="item.onSelect"
> >
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom> <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 || 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"> <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-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, item.ui?.itemLeadingIcon], active: active || item.active })" /> <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="((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 })" /> <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 <UChip
v-else-if="item.chip" 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 inset
standalone standalone
v-bind="item.chip" 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> </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"> <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> </slot>
</span> </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"> <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] })"> <span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: props.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" /> <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> </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> </slot>
<ListboxItemIndicator as-child> <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> </ListboxItemIndicator>
</span> </span>
</slot> </slot>

View File

@@ -32,8 +32,6 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custo
children?: ArrayOrNested<ContextMenuItem> children?: ArrayOrNested<ContextMenuItem>
onSelect?(e: Event): void onSelect?(e: Event): void
onUpdateChecked?(checked: boolean): 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 [key: string]: any
} }

View File

@@ -77,29 +77,29 @@ const groups = computed<ContextMenuItem[][]>(() =>
<DefineItemTemplate v-slot="{ item, active, index }"> <DefineItemTemplate v-slot="{ item, active, index }">
<slot :name="((item.slot || 'item') as keyof ContextMenuSlots<T>)" :item="item" :index="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"> <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-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, item.ui?.itemLeadingIcon], color: item?.color, active })" /> <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="((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 })" /> <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> </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"> <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) }} {{ get(item, props.labelKey as string) }}
</slot> </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>
<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"> <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 })" /> <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, item.ui?.itemTrailingKbds] })"> <span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.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" /> <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> </span>
</slot> </slot>
<ContextMenu.ItemIndicator as-child> <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> </ContextMenu.ItemIndicator>
</span> </span>
</slot> </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 })"> <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}`"> <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" /> <ReuseItemTemplate :item="item" :index="index" />
</ContextMenu.Label> </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.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
<ContextMenu.SubTrigger <ContextMenu.SubTrigger
as="button" as="button"
type="button" type="button"
:disabled="item.disabled" :disabled="item.disabled"
:text-value="get(item, props.labelKey as string)" :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" /> <ReuseItemTemplate :item="item" :index="index" />
</ContextMenu.SubTrigger> </ContextMenu.SubTrigger>
@@ -150,7 +150,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
:model-value="item.checked" :model-value="item.checked"
:disabled="item.disabled" :disabled="item.disabled"
:text-value="get(item, props.labelKey as string)" :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" @update:model-value="item.onUpdateChecked"
@select="item.onSelect" @select="item.onSelect"
> >
@@ -164,7 +164,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
@select="item.onSelect" @select="item.onSelect"
> >
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom> <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" /> <ReuseItemTemplate :item="item" :active="active" :index="index" />
</ULinkBase> </ULinkBase>
</ULink> </ULink>

View File

@@ -32,8 +32,6 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
children?: ArrayOrNested<DropdownMenuItem> children?: ArrayOrNested<DropdownMenuItem>
onSelect?(e: Event): void onSelect?(e: Event): void
onUpdateChecked?(checked: boolean): 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 [key: string]: any
} }

View File

@@ -83,29 +83,29 @@ const groups = computed<DropdownMenuItem[][]>(() =>
<DefineItemTemplate v-slot="{ item, active, index }"> <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') 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"> <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-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, item.ui?.itemLeadingIcon], color: item?.color, active })" /> <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="((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 })" /> <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> </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"> <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) }} {{ get(item, props.labelKey as string) }}
</slot> </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>
<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"> <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 })" /> <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, item.ui?.itemTrailingKbds] })"> <span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.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" /> <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> </span>
</slot> </slot>
<DropdownMenu.ItemIndicator as-child> <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> </DropdownMenu.ItemIndicator>
</span> </span>
</slot> </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 })"> <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}`"> <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" /> <ReuseItemTemplate :item="item" :index="index" />
</DropdownMenu.Label> </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.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
<DropdownMenu.SubTrigger <DropdownMenu.SubTrigger
as="button" as="button"
type="button" type="button"
:disabled="item.disabled" :disabled="item.disabled"
:text-value="get(item, props.labelKey as string)" :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" /> <ReuseItemTemplate :item="item" :index="index" />
</DropdownMenu.SubTrigger> </DropdownMenu.SubTrigger>
@@ -158,7 +158,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
:model-value="item.checked" :model-value="item.checked"
:disabled="item.disabled" :disabled="item.disabled"
:text-value="get(item, props.labelKey as string)" :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" @update:model-value="item.onUpdateChecked"
@select="item.onSelect" @select="item.onSelect"
> >
@@ -172,7 +172,7 @@ const groups = computed<DropdownMenuItem[][]>(() =>
@select="item.onSelect" @select="item.onSelect"
> >
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<DropdownMenuItem, 'type'>)" custom> <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" /> <ReuseItemTemplate :item="item" :active="active" :index="index" />
</ULinkBase> </ULinkBase>
</ULink> </ULink>

View File

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

View File

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

View File

@@ -24,8 +24,6 @@ interface _InputMenuItem {
type?: 'label' | 'separator' | 'item' type?: 'label' | 'separator' | 'item'
disabled?: boolean disabled?: boolean
onSelect?(e?: Event): void 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 [key: string]: any
} }
export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean
@@ -428,16 +426,16 @@ defineExpose({
@focus="onFocus" @focus="onFocus"
@remove-tag="onRemoveTag" @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] })"> <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, isInputItem(item) && item.ui?.tagsItemText] })"> <TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
<slot name="tags-item-text" :item="(item as NestedItem<T>)" :index="index"> <slot name="tags-item-text" :item="(item as NestedItem<T>)" :index="index">
{{ displayValue(item as T) }} {{ displayValue(item as T) }}
</slot> </slot>
</TagsInputItemText> </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"> <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> </slot>
</TagsInputItemDelete> </TagsInputItemDelete>
</TagsInputItem> </TagsInputItem>
@@ -495,44 +493,44 @@ defineExpose({
<ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })"> <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}`"> <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) }} {{ get(item, props.labelKey as string) }}
</ComboboxLabel> </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 <ComboboxItem
v-else 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" :disabled="isInputItem(item) && item.disabled"
:value="props.valueKey && isInputItem(item) ? get(item, props.valueKey as string) : item" :value="props.valueKey && isInputItem(item) ? get(item, props.valueKey as string) : item"
@select="onSelect($event, item)" @select="onSelect($event, item)"
> >
<slot name="item" :item="(item as NestedItem<T>)" :index="index"> <slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :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] })" /> <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="((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] })" /> <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 <UChip
v-else-if="isInputItem(item) && item.chip" 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 inset
standalone standalone
v-bind="item.chip" v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })" :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/> />
</slot> </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"> <slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isInputItem(item) ? get(item, props.labelKey as string) : item }} {{ isInputItem(item) ? get(item, props.labelKey as string) : item }}
</slot> </slot>
</span> </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" /> <slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<ComboboxItemIndicator as-child> <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> </ComboboxItemIndicator>
</span> </span>
</slot> </slot>

View File

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

View File

@@ -89,12 +89,11 @@ export interface LinkSlots {
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { defu } from 'defu' import { defu } from 'defu'
import { isEqual } from 'ohash/utils' import { isEqual, diff } from 'ohash/utils'
import { useForwardProps } from 'reka-ui' import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core' import { reactiveOmit } from '@vueuse/core'
import { useRoute, useAppConfig } from '#imports' import { useRoute, useAppConfig } from '#imports'
import { tv } from '../utils/tv' import { tv } from '../utils/tv'
import { isPartiallyEqual } from '../utils/link'
import ULinkBase from './LinkBase.vue' import ULinkBase from './LinkBase.vue'
defineOptions({ inheritAttrs: false }) defineOptions({ inheritAttrs: false })
@@ -112,7 +111,7 @@ defineSlots<LinkSlots>()
const route = useRoute() const route = useRoute()
const appConfig = useAppConfig() as Link['AppConfig'] 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({ const ui = computed(() => tv({
extend: tv(theme), extend: tv(theme),
@@ -126,7 +125,19 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {}) }, 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) { function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
if (props.active !== undefined) { if (props.active !== undefined) {
@@ -166,7 +177,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any) {
</script> </script>
<template> <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"> <template v-if="custom">
<slot <slot
v-bind="{ v-bind="{

View File

@@ -8,7 +8,7 @@ import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps,
type NavigationMenu = ComponentConfig<typeof theme, AppConfig, 'navigationMenu'> 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 is only used when `orientation` is `horizontal`. */
description?: string description?: string
[key: string]: any [key: string]: any
@@ -43,10 +43,6 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
*/ */
type?: 'label' | 'link' type?: 'label' | 'link'
slot?: string 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 value?: string
/** /**
* Make the item collapsible. * Make the item collapsible.
@@ -56,8 +52,6 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
collapsible?: boolean collapsible?: boolean
children?: NavigationMenuChildItem[] children?: NavigationMenuChildItem[]
onSelect?(e: Event): void 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 [key: string]: any
} }
@@ -222,34 +216,34 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<DefineLinkTemplate v-slot="{ item, active, index }"> <DefineLinkTemplate v-slot="{ item, active, index }">
<slot :name="((item.slot || 'item') as keyof NavigationMenuSlots<T>)" :item="item" :index="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"> <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 })" /> <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, item.ui?.linkLeadingIcon], 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> </slot>
<span <span
v-if="(!collapsed || orientation !== 'vertical') && (get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label` : 'item-label') as keyof NavigationMenuSlots<T>])" 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"> <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) }} {{ get(item, props.labelKey as string) }}
</slot> </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>
<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"> <slot :name="((item.slot ? `${item.slot}-trailing` : 'item-trailing') as keyof NavigationMenuSlots<T>)" :item="item" :active="active" :index="index">
<UBadge <UBadge
v-if="item.badge" v-if="item.badge"
color="neutral" color="neutral"
variant="outline" 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" 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-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, item.ui?.linkTrailingIcon], active })" /> <UIcon v-else-if="item.trailingIcon" :name="item.trailingIcon" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon, active })" />
</slot> </slot>
</span> </span>
</slot> </slot>
@@ -259,13 +253,13 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<component <component
:is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem" :is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"
as="li" as="li"
:value="item.value || `item-${index}`" :value="item.value || String(index)"
:default-open="item.defaultOpen" :default-open="item.defaultOpen"
:disabled="(orientation === 'vertical' && item.children?.length) ? item.collapsible === false : undefined" :disabled="(orientation === 'vertical' && item.children?.length) ? item.collapsible === false : undefined"
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined" :unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
:open="item.open" :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" /> <ReuseLinkTemplate :item="item" :index="index" />
</div> </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> <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" @select="item.onSelect"
> >
<UTooltip v-if="!!item.tooltip" :content="{ side: 'right' }" v-bind="item.tooltip"> <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" /> <ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
</ULinkBase> </ULinkBase>
</UTooltip> </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" /> <ReuseLinkTemplate :item="item" :active="active || item.active" :index="index" />
</ULinkBase> </ULinkBase>
</component> </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"> <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] })"> <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, item.ui?.childItem] })"> <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> <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect"> <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 })"> <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, item.ui?.childLinkIcon], 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] })"> <div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
<p :class="ui.childLinkLabel({ class: [props.ui?.childLinkLabel, item.ui?.childLinkLabel], active: childActive })"> <p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
{{ get(childItem, props.labelKey as string) }} {{ 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>
<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 }} {{ childItem.description }}
</p> </p>
</div> </div>
@@ -322,7 +316,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
:item="childItem" :item="childItem"
:index="childIndex" :index="childIndex"
:level="level + 1" :level="level + 1"
:class="ui.childItem({ class: [props.ui?.childItem, childItem.ui?.childItem] })" :class="ui.childItem({ class: props.ui?.childItem })"
/> />
</ul> </ul>
</template> </template>
@@ -334,7 +328,7 @@ const lists = computed<NavigationMenuItem[][]>(() =>
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`"> <template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
<NavigationMenuList :class="ui.list({ class: props.ui?.list })"> <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> </NavigationMenuList>
<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" /> <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 description?: string
disabled?: boolean disabled?: boolean
value?: RadioGroupValue value?: RadioGroupValue
class?: any
ui?: Pick<RadioGroup['slots'], 'item' | 'container' | 'base' | 'indicator' | 'wrapper' | 'label' | 'description'>
[key: string]: any [key: string]: any
} | RadioGroupValue } | RadioGroupValue
@@ -178,25 +176,25 @@ function onUpdate(value: any) {
</slot> </slot>
</legend> </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] })"> <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, item.ui?.container] })"> <div :class="ui.container({ class: props.ui?.container })">
<RadioGroupItem <RadioGroupItem
:id="item.id" :id="item.id"
:value="item.value" :value="item.value"
:disabled="item.disabled" :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> </RadioGroupItem>
</div> </div>
<div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })"> <div v-if="(item.label || !!slots.label) || (item.description || !!slots.description)" :class="ui.wrapper({ class: props.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] })"> <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)"> <slot name="label" :item="item" :model-value="(modelValue as RadioGroupValue)">
{{ item.label }} {{ item.label }}
</slot> </slot>
</component> </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)"> <slot name="description" :item="item" :model-value="(modelValue as RadioGroupValue)">
{{ item.description }} {{ item.description }}
</slot> </slot>

View File

@@ -24,8 +24,6 @@ interface SelectItemBase {
value?: AcceptableValue | boolean value?: AcceptableValue | boolean
disabled?: boolean disabled?: boolean
onSelect?(e?: Event): void onSelect?(e?: Event): void
class?: any
ui?: Pick<Select['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
[key: string]: any [key: string]: any
} }
export type SelectItem = SelectItemBase | AcceptableValue | boolean 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 })"> <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 })"> <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}`"> <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) }} {{ get(item, props.labelKey as string) }}
</SelectLabel> </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 <SelectItem
v-else 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" :disabled="isSelectItem(item) && item.disabled"
:value="isSelectItem(item) ? get(item, props.valueKey as string) : item" :value="isSelectItem(item) ? get(item, props.valueKey as string) : item"
@select="isSelectItem(item) && item.onSelect?.($event)" @select="isSelectItem(item) && item.onSelect?.($event)"
> >
<slot name="item" :item="(item as NestedItem<T>)" :index="index"> <slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :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] })" /> <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="((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] })" /> <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 <UChip
v-else-if="isSelectItem(item) && item.chip" 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 inset
standalone standalone
v-bind="item.chip" v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })" :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/> />
</slot> </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"> <slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }} {{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
</slot> </slot>
</SelectItemText> </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" /> <slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<SelectItemIndicator as-child> <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> </SelectItemIndicator>
</span> </span>
</slot> </slot>

View File

@@ -23,8 +23,6 @@ interface _SelectMenuItem {
type?: 'label' | 'separator' | 'item' type?: 'label' | 'separator' | 'item'
disabled?: boolean disabled?: boolean
onSelect?(e?: Event): void onSelect?(e?: Event): void
class?: any
ui?: Pick<SelectMenu['slots'], 'label' | 'separator' | 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemTrailing' | 'itemTrailingIcon'>
[key: string]: any [key: string]: any
} }
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean 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 })"> <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}`"> <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) }} {{ get(item, props.labelKey as string) }}
</ComboboxLabel> </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 <ComboboxItem
v-else 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" :disabled="isSelectItem(item) && item.disabled"
:value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item" :value="props.valueKey && isSelectItem(item) ? get(item, props.valueKey as string) : item"
@select="onSelect($event, item)" @select="onSelect($event, item)"
> >
<slot name="item" :item="(item as NestedItem<T>)" :index="index"> <slot name="item" :item="(item as NestedItem<T>)" :index="index">
<slot name="item-leading" :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] })" /> <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="((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] })" /> <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 <UChip
v-else-if="isSelectItem(item) && item.chip" v-else-if="isSelectItem(item) && item.chip"
:size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])" :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
inset inset
standalone standalone
v-bind="item.chip" v-bind="item.chip"
:class="ui.itemLeadingChip({ class: [props.ui?.itemLeadingChip, item.ui?.itemLeadingChip] })" :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
/> />
</slot> </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"> <slot name="item-label" :item="(item as NestedItem<T>)" :index="index">
{{ isSelectItem(item) ? get(item, props.labelKey as string) : item }} {{ isSelectItem(item) ? get(item, props.labelKey as string) : item }}
</slot> </slot>
</span> </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" /> <slot name="item-trailing" :item="(item as NestedItem<T>)" :index="index" />
<ComboboxItemIndicator as-child> <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> </ComboboxItemIndicator>
</span> </span>
</slot> </slot>

View File

@@ -38,13 +38,13 @@ export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' |
ui?: Slider['slots'] ui?: Slider['slots']
} }
export interface SliderEmits<T extends number | number[] = number | number[]> { export interface SliderEmits {
(e: 'update:modelValue', payload: T): void (e: 'update:modelValue', payload: number | number[]): void
(e: 'change', payload: Event): void (e: 'change', payload: Event): void
} }
</script> </script>
<script setup lang="ts" generic="T extends number | number[]"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { SliderRoot, SliderRange, SliderTrack, SliderThumb, useForwardPropsEmits } from 'reka-ui' import { SliderRoot, SliderRange, SliderTrack, SliderThumb, useForwardPropsEmits } from 'reka-ui'
import { reactivePick } from '@vueuse/core' import { reactivePick } from '@vueuse/core'
@@ -59,9 +59,9 @@ const props = withDefaults(defineProps<SliderProps>(), {
step: 1, step: 1,
orientation: 'horizontal' 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'] const appConfig = useAppConfig() as Slider['AppConfig']
@@ -81,10 +81,10 @@ const sliderValue = computed({
if (typeof modelValue.value === 'number') { if (typeof modelValue.value === 'number') {
return [modelValue.value] return [modelValue.value]
} }
return (modelValue.value as number[]) ?? defaultSliderValue.value return modelValue.value ?? defaultSliderValue.value
}, },
set(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 icon?: string
content?: string content?: string
disabled?: boolean disabled?: boolean
class?: any
ui?: Pick<Stepper['slots'], 'item' | 'container' | 'trigger' | 'indicator' | 'icon' | 'separator' | 'wrapper' | 'title' | 'description'>
[key: string]: any [key: string]: any
} }
@@ -138,13 +136,13 @@ defineExpose({
:key="item.value ?? count" :key="item.value ?? count"
:step="count" :step="count"
:disabled="item.disabled || props.disabled" :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] })"> <div :class="ui.container({ class: props.ui?.container })">
<StepperTrigger :class="ui.trigger({ class: [props.ui?.trigger, item.ui?.trigger] })"> <StepperTrigger :class="ui.trigger({ class: props.ui?.trigger })">
<StepperIndicator :class="ui.indicator({ class: [props.ui?.indicator, item.ui?.indicator] })"> <StepperIndicator :class="ui.indicator({ class: props.ui?.indicator })">
<slot name="indicator" :item="item"> <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> <template v-else>
{{ count + 1 }} {{ count + 1 }}
</template> </template>
@@ -154,17 +152,17 @@ defineExpose({
<StepperSeparator <StepperSeparator
v-if="count < items.length - 1" 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>
<div :class="ui.wrapper({ class: [props.ui?.wrapper, item.ui?.wrapper] })"> <div :class="ui.wrapper({ class: props.ui?.wrapper })">
<StepperTitle as="div" :class="ui.title({ class: [props.ui?.title, item.ui?.title] })"> <StepperTitle as="div" :class="ui.title({ class: props.ui?.title })">
<slot name="title" :item="item"> <slot name="title" :item="item">
{{ item.title }} {{ item.title }}
</slot> </slot>
</StepperTitle> </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"> <slot name="description" :item="item">
{{ item.description }} {{ item.description }}
</slot> </slot>

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,8 +24,6 @@ export type TreeItem = {
children?: TreeItem[] children?: TreeItem[]
onToggle?(e: Event): void onToggle?(e: Event): void
onSelect?(e?: Event): void onSelect?(e?: Event): void
class?: any
ui?: Pick<Tree['slots'], 'item' | 'itemWithChildren' | 'link' | 'linkLeadingIcon' | 'linkLabel' | 'linkTrailing' | 'linkTrailingIcon' | 'listWithChildren'>
[key: string]: any [key: string]: any
} }
@@ -151,7 +149,7 @@ const defaultExpanded = computed(() =>
<li <li
v-for="(item, index) in items" v-for="(item, index) in items"
:key="`${level}-${index}`" :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 <TreeItem
v-slot="{ isExpanded, isSelected }" v-slot="{ isExpanded, isSelected }"
@@ -161,37 +159,37 @@ const defaultExpanded = computed(() =>
@toggle="item.onToggle" @toggle="item.onToggle"
@select="item.onSelect" @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') 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; }>)"> <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 <UIcon
v-if="item.icon" v-if="item.icon"
:name="item.icon" :name="item.icon"
:class="ui.linkLeadingIcon({ class: [props.ui?.linkLeadingIcon, item.ui?.linkLeadingIcon] })" :class="ui.linkLeadingIcon({ class: props.ui?.linkLeadingIcon })"
/> />
<UIcon <UIcon
v-else-if="item.children?.length" v-else-if="item.children?.length"
:name="isExpanded ? (expandedIcon ?? appConfig.ui.icons.folderOpen) : (collapsedIcon ?? appConfig.ui.icons.folder)" :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> </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; }>)"> <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) }} {{ getItemLabel(item) }}
</slot> </slot>
</span> </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; }>)"> <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-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, item.ui?.linkTrailingIcon] })" /> <UIcon v-else-if="item.children?.length" :name="trailingIcon ?? appConfig.ui.icons.chevronDown" :class="ui.linkTrailingIcon({ class: props.ui?.linkTrailingIcon })" />
</slot> </slot>
</span> </span>
</slot> </slot>
</button> </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" /> <ReuseTreeTemplate :items="item.children" :level="level + 1" />
</ul> </ul>
</TreeItem> </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 UseEventBusReturn, useDebounceFn } from '@vueuse/core'
import type { FormFieldProps } from '../types' import type { FormFieldProps } from '../types'
import type { FormEvent, FormInputEvents, FormFieldInjectedOptions, FormInjectedOptions } from '../types/form' 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 formOptionsInjectionKey: InjectionKey<ComputedRef<FormInjectedOptions>> = Symbol('nuxt-ui.form-options')
export const formBusInjectionKey: InjectionKey<UseEventBusReturn<FormEvent<any>, string>> = Symbol('nuxt-ui.form-events') 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 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 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') 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 formInputs = inject(formInputsInjectionKey, undefined)
const inputId = inject(inputIdInjectionKey, 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 (formField && inputId) {
if (opts?.bind === false) { if (opts?.bind === false) {
// Removes for="..." attribute on label for RadioGroup and alike. // 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'> type Link = ComponentConfig<typeof theme, AppConfig, 'link'>
interface NuxtLinkProps extends Omit<InertiaLinkProps, 'href' | 'onClick'> { interface NuxtLinkProps extends Omit<InertiaLinkProps, 'href'> {
activeClass?: string activeClass?: string
/** /**
* Route Location the link should navigate to when clicked on. * Route Location the link should navigate to when clicked on.
@@ -62,11 +62,10 @@ import { computed } from 'vue'
import { defu } from 'defu' import { defu } from 'defu'
import { useForwardProps } from 'reka-ui' import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core' import { reactiveOmit } from '@vueuse/core'
import { usePage } from '@inertiajs/vue3' import { usePage, Link as InertiaLink } from '@inertiajs/vue3'
import { hasProtocol } from 'ufo' import { hasProtocol } from 'ufo'
import { useAppConfig } from '#imports' import { useAppConfig } from '#imports'
import { tv } from '../../utils/tv' import { tv } from '../../utils/tv'
import ULinkBase from '../../components/LinkBase.vue'
defineOptions({ inheritAttrs: false }) defineOptions({ inheritAttrs: false })
@@ -79,11 +78,9 @@ const props = withDefaults(defineProps<LinkProps>(), {
}) })
defineSlots<LinkSlots>() defineSlots<LinkSlots>()
const page = usePage()
const appConfig = useAppConfig() as Link['AppConfig'] 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({ const ui = computed(() => tv({
extend: tv(theme), extend: tv(theme),
@@ -97,42 +94,14 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {}) }, appConfig.ui?.link || {})
})) }))
const href = computed(() => props.to ?? props.href)
const isExternal = computed(() => { const isExternal = computed(() => {
if (props.external) { if (props.external) return true
return true if (!props.to) return false
} return typeof props.to === 'string' && hasProtocol(props.to, { acceptRelative: 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
}) })
const linkClass = computed(() => { const linkClass = computed(() => {
const active = isLinkActive.value const active = isActive.value
if (props.raw) { if (props.raw) {
return [props.class, active ? props.activeClass : props.inactiveClass] 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 }) 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> </script>
<template> <template>
<template v-if="custom"> <template v-if="!isExternal && !!url">
<slot <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="{ v-bind="{
...$attrs, ...$attrs,
...routerLinkProps,
as, as,
type, type,
disabled, disabled,
href, href: url,
active: isLinkActive, target: isExternal ? '_blank' : undefined,
isExternal active: isActive
}" }"
/> :is-external="isExternal"
:class="linkClass"
>
<slot :active="isActive" />
</ULinkBase>
</template> </template>
<ULinkBase
v-else
v-bind="{
...$attrs,
...routerLinkProps,
as,
type,
disabled,
href,
isExternal
}"
:class="linkClass"
>
<slot :active="isLinkActive" />
</ULinkBase>
</template> </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 { useHead } from '@unhead/vue'
export { useAppConfig } from '../vue/composables/useAppConfig'
export { defineShortcuts } from '../composables/defineShortcuts' export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale' export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale' export { useLocale } from '../composables/useLocale'
@@ -42,6 +41,8 @@ export const useColorMode = () => {
} }
} }
export const useAppConfig = () => appConfig
export const useCookie = <T = string>( export const useCookie = <T = string>(
_name: string, _name: string,
_options: Record<string, any> = {} _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 ro } from './ro'
export { default as ru } from './ru' export { default as ru } from './ru'
export { default as sk } from './sk' export { default as sk } from './sk'
export { default as sl } from './sl'
export { default as sv } from './sv' export { default as sv } from './sv'
export { default as th } from './th' export { default as th } from './th'
export { default as tj } from './tj' 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 { computed } from 'vue'
import colors from 'tailwindcss/colors'
import type { UseHeadInput } from '@unhead/vue/types' import type { UseHeadInput } from '@unhead/vue/types'
import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports' import { defineNuxtPlugin, useAppConfig, useNuxtApp, useHead } from '#imports'
import { generateColorStyles } from '../utils/colors'
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});`
}
export default defineNuxtPlugin(() => { export default defineNuxtPlugin(() => {
const appConfig = useAppConfig() const appConfig = useAppConfig()
const nuxtApp = useNuxtApp() const nuxtApp = useNuxtApp()
const root = computed(() => { const root = computed(() => generateColorStyles(appConfig.ui.colors))
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 ')}
}
}`
})
// Head // Head
const headData: UseHeadInput = { 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 { reactivePick } from '@vueuse/core'
import { isEqual, diff } from 'ohash/utils'
import type { LinkProps } from '../types' import type { LinkProps } from '../types'
export function pickLinkProps(link: LinkProps & { [key: string]: any }) { export function pickLinkProps(link: LinkProps & { [key: string]: any }) {
@@ -20,17 +19,3 @@ export function pickLinkProps(link: LinkProps & { [key: string]: any }) {
return reactivePick(link, ...propsToInclude) 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>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed, getCurrentInstance } from 'vue'
import { defu } from 'defu' import { defu } from 'defu'
import { isEqual } from 'ohash/utils' import { isEqual, diff } from 'ohash/utils'
import { useForwardProps } from 'reka-ui' import { useForwardProps } from 'reka-ui'
import { reactiveOmit } from '@vueuse/core' import { reactiveOmit } from '@vueuse/core'
import { hasProtocol } from 'ufo' import { hasProtocol } from 'ufo'
import { useRoute, RouterLink } from 'vue-router' import { useRoute, RouterLink } from 'vue-router'
import { useAppConfig } from '#imports' import { useAppConfig } from '#imports'
import { tv } from '../../utils/tv' import { tv } from '../../utils/tv'
import { isPartiallyEqual } from '../../utils/link'
import ULinkBase from '../../components/LinkBase.vue'
defineOptions({ inheritAttrs: false }) defineOptions({ inheritAttrs: false })
@@ -111,11 +109,25 @@ const props = withDefaults(defineProps<LinkProps>(), {
}) })
defineSlots<LinkSlots>() 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 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({ const ui = computed(() => tv({
extend: tv(theme), extend: tv(theme),
@@ -129,18 +141,23 @@ const ui = computed(() => tv({
}, appConfig.ui?.link || {}) }, 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(() => { const isExternal = computed(() => {
if (props.external) { if (!props.to) return false
return true return typeof props.to === 'string' && hasProtocol(props.to, { acceptRelative: true })
}
if (!to.value) {
return false
}
return typeof to.value === 'string' && hasProtocol(to.value, { acceptRelative: true })
}) })
function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) { function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
@@ -148,17 +165,17 @@ function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
return props.active return props.active
} }
if (!to.value) { if (!props.to || !route.value) {
return false return false
} }
if (props.exactQuery === 'partial') { 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) { } 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 return false
} }
@@ -185,8 +202,8 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
</script> </script>
<template> <template>
<template v-if="!isExternal && !!to"> <template v-if="hasRouter && !isExternal">
<RouterLink v-slot="{ href, navigate, route: linkRoute, isActive, isExactActive }" v-bind="routerLinkProps" :to="to" custom> <RouterLink v-slot="{ href, navigate, route: linkRoute, isActive, isExactActive }" v-bind="routerLinkProps" :to="to || '#'" custom>
<template v-if="custom"> <template v-if="custom">
<slot <slot
v-bind="{ v-bind="{
@@ -195,7 +212,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
as, as,
type, type,
disabled, disabled,
href, href: to ? href : undefined,
navigate, navigate,
active: isLinkActive({ route: linkRoute, isActive, isExactActive }) active: isLinkActive({ route: linkRoute, isActive, isExactActive })
}" }"
@@ -209,7 +226,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
as, as,
type, type,
disabled, disabled,
href, href: to ? href : undefined,
navigate navigate
}" }"
:class="resolveLinkClass({ route: linkRoute, isActive, isExactActive })" :class="resolveLinkClass({ route: linkRoute, isActive, isExactActive })"
@@ -229,8 +246,7 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
disabled, disabled,
href: to, href: to,
target: isExternal ? '_blank' : undefined, target: isExternal ? '_blank' : undefined,
active, active: false
isExternal
}" }"
/> />
</template> </template>
@@ -242,12 +258,12 @@ function resolveLinkClass({ route, isActive, isExactActive }: any = {}) {
type, type,
disabled, disabled,
href: (to as string), href: (to as string),
target: isExternal ? '_blank' : undefined, target: isExternal ? '_blank' : undefined
isExternal
}" }"
:is-external="isExternal"
:class="resolveLinkClass()" :class="resolveLinkClass()"
> >
<slot :active="active" /> <slot :active="false" />
</ULinkBase> </ULinkBase>
</template> </template>
</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 { useHead } from '@unhead/vue'
export { useRoute, useRouter } from 'vue-router' export { useRoute, useRouter } from 'vue-router'
export { useAppConfig } from './composables/useAppConfig'
export { defineShortcuts } from '../composables/defineShortcuts' export { defineShortcuts } from '../composables/defineShortcuts'
export { defineLocale } from '../composables/defineLocale' export { defineLocale } from '../composables/defineLocale'
export { useLocale } from '../composables/useLocale' export { useLocale } from '../composables/useLocale'
@@ -31,6 +30,8 @@ export const useColorMode = () => {
} }
} }
export const useAppConfig = () => appConfig
export const useCookie = <T = string>( export const useCookie = <T = string>(
_name: string, _name: string,
_options: Record<string, any> = {} _options: Record<string, any> = {}

View File

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

View File

@@ -1,18 +1,18 @@
export const buttonGroupVariant = { export const buttonGroupVariant = {
buttonGroup: { buttonGroup: {
horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-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 focus-visible:z-[1]' vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none'
} }
} }
export const buttonGroupVariantWithRoot = { export const buttonGroupVariantWithRoot = {
buttonGroup: { buttonGroup: {
horizontal: { 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' 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: { 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' 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 {
export default (options: Required<ModuleOptions>) => ({
slots: { slots: {
root: 'relative', root: 'relative',
fieldset: 'flex gap-x-2', fieldset: 'flex gap-x-2',
@@ -16,17 +14,6 @@ export default (options: Required<ModuleOptions>) => ({
fieldset: 'flex-col' fieldset: 'flex-col'
} }
}, },
color: {
...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, {}])),
neutral: {}
},
variant: {
list: {},
card: {},
table: {
item: 'border border-muted'
}
},
size: { size: {
xs: { xs: {
fieldset: 'gap-y-0.5', 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: { defaultVariants: {
size: 'md', size: 'md'
variant: 'list',
color: 'primary'
} }
}) }

View File

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

View File

@@ -5,15 +5,10 @@ export default (options: Required<ModuleOptions>) => ({
variants: { variants: {
active: { active: {
true: 'text-primary', true: 'text-primary',
false: 'text-muted' false: ['text-muted hover:text-default', options.theme.transitions && 'transition-colors']
}, },
disabled: { disabled: {
true: 'cursor-not-allowed opacity-75' 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', { 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 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 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 as', { props: { label: 'Badge', as: 'div' } }],
['with class', { props: { label: 'Badge', class: 'rounded-full font-bold' } }], ['with class', { props: { label: 'Badge', class: 'rounded-full font-bold' } }],
['with ui', { props: { label: 'Badge', ui: { label: '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', () => { describe('CheckboxGroup', () => {
const sizes = Object.keys(theme.variants.size) as any 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 indicators = Object.keys(themeCheckbox.variants.indicator) as any
const items = [ const items = [

View File

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

View File

@@ -84,12 +84,12 @@ describe('NavigationMenu', () => {
it.each([ it.each([
// Props // Props
['with items', { props }], ['with items', { props }],
['with modelValue', { props: { ...props, modelValue: 'item-0' } }], ['with modelValue', { props: { ...props, modelValue: '0' } }],
['with labelKey', { props: { ...props, labelKey: 'icon' } }], ['with labelKey', { props: { ...props, labelKey: 'icon' } }],
['with arrow', { props: { ...props, arrow: true, modelValue: 'item-0' } }], ['with arrow', { props: { ...props, arrow: true, modelValue: '0' } }],
['with orientation vertical', { props: { ...props, orientation: 'vertical' as const, modelValue: 'item-0' } }], ['with orientation vertical', { props: { ...props, orientation: 'vertical' as const, modelValue: '0' } }],
['with orientation vertical and collapsed', { props: { ...props, orientation: 'vertical' as const, modelValue: 'item-0', collapsed: true } }], ['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: 'item-0' } }], ['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 primary variant ${variant}`, { props: { ...props, variant } }]),
...variants.map((variant: string) => [`with neutral variant ${variant}`, { props: { ...props, variant, color: 'neutral' } }]), ...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 } }]), ...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>" </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`] = ` 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>" <!--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`] = ` 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-->
<!--v-if--></span>" <!--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 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`] = ` 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> "<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>" <!--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`] = ` 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> "<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>" <!--v-if--></span>"
`; `;
exports[`Badge > renders with square correctly 1`] = ` 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>"`;
"<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 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 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 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 ui correctly 1`] = ` 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> "<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`] = ` 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-->
<!--v-if--></span>" <!--v-if--></span>"
`; `;
exports[`Badge > renders with avatar and trailingIcon correctly 1`] = ` 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>" <!--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`] = ` 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-->
<!--v-if--></span>" <!--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 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`] = ` 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-->
<!--v-if--></span>" <!--v-if--></span>"
`; `;
@@ -43,15 +43,15 @@ exports[`Badge > renders with label correctly 1`] = `
`; `;
exports[`Badge > renders with leading and icon 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-->
<!--v-if--></span>" <!--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`] = ` 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-->
<!--v-if--></span>" <!--v-if--></span>"
`; `;
@@ -121,16 +121,11 @@ exports[`Badge > renders with size xs correctly 1`] = `
<!--v-if--></span>" <!--v-if--></span>"
`; `;
exports[`Badge > renders with square correctly 1`] = ` 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>"`;
"<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 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 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 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 ui correctly 1`] = ` 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> "<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`] = ` exports[`ButtonGroup > renders orientation vertical with default slot correctly 1`] = `
"<div class="relative flex flex-col -space-y-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -18,10 +18,10 @@ exports[`ButtonGroup > renders with class correctly 1`] = `"<div class="inline-f
exports[`ButtonGroup > renders with default slot correctly 1`] = ` exports[`ButtonGroup > renders with default slot correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -30,10 +30,10 @@ exports[`ButtonGroup > renders with default slot correctly 1`] = `
exports[`ButtonGroup > renders with size lg correctly 1`] = ` exports[`ButtonGroup > renders with size lg correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -42,10 +42,10 @@ exports[`ButtonGroup > renders with size lg correctly 1`] = `
exports[`ButtonGroup > renders with size md correctly 1`] = ` exports[`ButtonGroup > renders with size md correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -54,10 +54,10 @@ exports[`ButtonGroup > renders with size md correctly 1`] = `
exports[`ButtonGroup > renders with size sm correctly 1`] = ` exports[`ButtonGroup > renders with size sm correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -66,10 +66,10 @@ exports[`ButtonGroup > renders with size sm correctly 1`] = `
exports[`ButtonGroup > renders with size xl correctly 1`] = ` exports[`ButtonGroup > renders with size xl correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -78,10 +78,10 @@ exports[`ButtonGroup > renders with size xl correctly 1`] = `
exports[`ButtonGroup > renders with size xs correctly 1`] = ` exports[`ButtonGroup > renders with size xs correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>

View File

@@ -2,10 +2,10 @@
exports[`ButtonGroup > renders orientation vertical with default slot correctly 1`] = ` exports[`ButtonGroup > renders orientation vertical with default slot correctly 1`] = `
"<div class="relative flex flex-col -space-y-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -18,10 +18,10 @@ exports[`ButtonGroup > renders with class correctly 1`] = `"<div class="inline-f
exports[`ButtonGroup > renders with default slot correctly 1`] = ` exports[`ButtonGroup > renders with default slot correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -30,10 +30,10 @@ exports[`ButtonGroup > renders with default slot correctly 1`] = `
exports[`ButtonGroup > renders with size lg correctly 1`] = ` exports[`ButtonGroup > renders with size lg correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -42,10 +42,10 @@ exports[`ButtonGroup > renders with size lg correctly 1`] = `
exports[`ButtonGroup > renders with size md correctly 1`] = ` exports[`ButtonGroup > renders with size md correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -54,10 +54,10 @@ exports[`ButtonGroup > renders with size md correctly 1`] = `
exports[`ButtonGroup > renders with size sm correctly 1`] = ` exports[`ButtonGroup > renders with size sm correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -66,10 +66,10 @@ exports[`ButtonGroup > renders with size sm correctly 1`] = `
exports[`ButtonGroup > renders with size xl correctly 1`] = ` exports[`ButtonGroup > renders with size xl correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>
@@ -78,10 +78,10 @@ exports[`ButtonGroup > renders with size xl correctly 1`] = `
exports[`ButtonGroup > renders with size xs correctly 1`] = ` exports[`ButtonGroup > renders with size xs correctly 1`] = `
"<div class="relative inline-flex -space-x-px"> "<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-->
<!--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--> Click me!
<!--v-if--> <!--v-if-->
</button> </button>

View File

@@ -1,187 +1,191 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Checkbox > renders with ariaLabel correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with as correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</section>" </label>"
`; `;
exports[`Checkbox > renders with class correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with defaultValue correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with description correctly 1`] = ` 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"> <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> </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> <p class="text-muted">Description</p>
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with description slot correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with disabled correctly 1`] = ` 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=""> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with icon correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with id correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indeterminate correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indeterminateIcon correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator end correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator hidden correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator start correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with label correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with label slot correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with modelValue correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with name correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with neutral variant card correctly 1`] = ` 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`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with size lg correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size md correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size sm correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size xl correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size xs correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with ui correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with value correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;

View File

@@ -1,187 +1,191 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Checkbox > renders with ariaLabel correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with as correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</section>" </label>"
`; `;
exports[`Checkbox > renders with class correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with defaultValue correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with description correctly 1`] = ` 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"> <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> </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> <p class="text-muted">Description</p>
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with description slot correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with disabled correctly 1`] = ` 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=""> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with icon correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with id correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indeterminate correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indeterminateIcon correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator end correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator hidden correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with indicator start correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with label correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with label slot correctly 1`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with modelValue correctly 1`] = ` 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> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with name correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with neutral variant card correctly 1`] = ` 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`] = ` 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"> <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> </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--> <!--v-if-->
</div> </div>
</div>" </label>"
`; `;
exports[`Checkbox > renders with size lg correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size md correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size sm correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size xl correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with size xs correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with ui correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--v-if-->
</div>" </label>"
`; `;
exports[`Checkbox > renders with value correctly 1`] = ` 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"> <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> </button></div>
<!--v-if--> <!--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-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -87,7 +87,7 @@ exports[`Form > joi validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -153,7 +153,7 @@ exports[`Form > superstruct validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -215,7 +215,7 @@ exports[`Form > valibot validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -277,7 +277,7 @@ exports[`Form > yup validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -339,7 +339,7 @@ exports[`Form > zod validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"

View File

@@ -25,7 +25,7 @@ exports[`Form > custom validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -87,7 +87,7 @@ exports[`Form > joi validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -153,7 +153,7 @@ exports[`Form > superstruct validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -215,7 +215,7 @@ exports[`Form > valibot validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -277,7 +277,7 @@ exports[`Form > yup validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"
@@ -339,7 +339,7 @@ exports[`Form > zod validation works > with error 1`] = `
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
</div> </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>
</div> </div>
</form>" </form>"

View File

@@ -55,7 +55,7 @@ exports[`FormField > renders with error correctly 1`] = `
<!--v-if--> <!--v-if-->
</div> </div>
<div class=""> <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>
</div>" </div>"
`; `;
@@ -67,7 +67,7 @@ exports[`FormField > renders with error slot correctly 1`] = `
<!--v-if--> <!--v-if-->
</div> </div>
<div class=""> <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>
</div>" </div>"
`; `;
@@ -79,7 +79,7 @@ exports[`FormField > renders with help correctly 1`] = `
<!--v-if--> <!--v-if-->
</div> </div>
<div class=""> <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>
</div>" </div>"
`; `;
@@ -91,7 +91,7 @@ exports[`FormField > renders with help slot correctly 1`] = `
<!--v-if--> <!--v-if-->
</div> </div>
<div class=""> <div class="">
<div class="mt-2 text-muted">Help slot</div> <p class="mt-2 text-muted">Help slot</p>
</div> </div>
</div>" </div>"
`; `;

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