mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
fix(components): refactor types after @nuxt/module-builder upgrade (#3855)
This commit is contained in:
@@ -31,13 +31,10 @@ const component = ({ name, primitive, pro, prose, content }) => {
|
||||
? `
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfig${camelName} = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
|
||||
|
||||
const ${camelName} = tv({ extend: tv(theme), ...(appConfig${camelName}.${key}?.${prose ? 'prose?.' : ''}${camelName} || {}) })
|
||||
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
|
||||
|
||||
export interface ${upperName}Props {
|
||||
/**
|
||||
@@ -46,7 +43,7 @@ export interface ${upperName}Props {
|
||||
*/
|
||||
as?: any
|
||||
class?: any
|
||||
ui?: Partial<typeof ${camelName}.slots>
|
||||
ui?: ${upperName}['slots']
|
||||
}
|
||||
|
||||
export interface ${upperName}Slots {
|
||||
@@ -55,12 +52,17 @@ export interface ${upperName}Slots {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<${upperName}Props>()
|
||||
defineSlots<${upperName}Slots>()
|
||||
|
||||
const ui = ${camelName}()
|
||||
const appConfig = useAppConfig() as ${upperName}['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -71,22 +73,16 @@ const ui = ${camelName}()
|
||||
`
|
||||
: `
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ${upperName}RootProps, ${upperName}RootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfig${camelName} = _appConfig as AppConfig & { ${key}: { ${prose ? 'prose: { ' : ''}${camelName}: Partial<typeof theme> } }${prose ? ' }' : ''}
|
||||
|
||||
const ${camelName} = tv({ extend: tv(theme), ...(appConfig${camelName}.${key}?.${prose ? 'prose?.' : ''}${camelName} || {}) })
|
||||
|
||||
type ${upperName}Variants = VariantProps<typeof ${camelName}>
|
||||
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
|
||||
|
||||
export interface ${upperName}Props extends Pick<${upperName}RootProps> {
|
||||
class?: any
|
||||
ui?: Partial<typeof ${camelName}.slots>
|
||||
ui?: ${upperName}['slots']
|
||||
}
|
||||
|
||||
export interface ${upperName}Emits extends ${upperName}RootEmits {}
|
||||
@@ -95,16 +91,21 @@ export interface ${upperName}Slots {}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { ${upperName}Root, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<${upperName}Props>()
|
||||
const emits = defineEmits<${upperName}Emits>()
|
||||
const slots = defineSlots<${upperName}Slots>()
|
||||
|
||||
const appConfig = useAppConfig() as ${upperName}['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props), emits)
|
||||
|
||||
const ui = ${camelName}()
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"@nuxt/content": "^3.4.0",
|
||||
"@nuxt/image": "^1.10.0",
|
||||
"@nuxt/ui": "latest",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@6b838c4",
|
||||
"@nuxt/ui-pro": "https://pkg.pr.new/@nuxt/ui-pro@655b0bd",
|
||||
"@nuxthub/core": "^0.8.24",
|
||||
"@nuxtjs/plausible": "^1.2.0",
|
||||
"@octokit/rest": "^21.1.1",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -246,8 +246,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:..
|
||||
'@nuxt/ui-pro':
|
||||
specifier: https://pkg.pr.new/@nuxt/ui-pro@6b838c4
|
||||
version: https://pkg.pr.new/@nuxt/ui-pro@6b838c4(@babel/parser@7.27.0)(joi@17.13.3)(magicast@0.3.5)(superstruct@2.0.2)(typescript@5.8.3)(valibot@1.0.0(typescript@5.8.3))(vue@3.5.13(typescript@5.8.3))(yup@1.6.1)(zod@3.24.2)
|
||||
specifier: https://pkg.pr.new/@nuxt/ui-pro@655b0bd
|
||||
version: https://pkg.pr.new/@nuxt/ui-pro@655b0bd(@babel/parser@7.27.0)(joi@17.13.3)(magicast@0.3.5)(superstruct@2.0.2)(typescript@5.8.3)(valibot@1.0.0(typescript@5.8.3))(vue@3.5.13(typescript@5.8.3))(yup@1.6.1)(zod@3.24.2)
|
||||
'@nuxthub/core':
|
||||
specifier: ^0.8.24
|
||||
version: 0.8.24(db0@0.3.1(better-sqlite3@11.9.1))(ioredis@5.6.0)(magicast@0.3.5)(vite@6.2.6(@types/node@22.13.14)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(yaml@2.7.1))
|
||||
@@ -1484,8 +1484,8 @@ packages:
|
||||
vitest:
|
||||
optional: true
|
||||
|
||||
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@6b838c4':
|
||||
resolution: {tarball: https://pkg.pr.new/@nuxt/ui-pro@6b838c4}
|
||||
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@655b0bd':
|
||||
resolution: {tarball: https://pkg.pr.new/@nuxt/ui-pro@655b0bd}
|
||||
version: 3.0.2
|
||||
peerDependencies:
|
||||
joi: ^17.13.0
|
||||
@@ -8437,7 +8437,7 @@ snapshots:
|
||||
- typescript
|
||||
- yaml
|
||||
|
||||
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@6b838c4(@babel/parser@7.27.0)(joi@17.13.3)(magicast@0.3.5)(superstruct@2.0.2)(typescript@5.8.3)(valibot@1.0.0(typescript@5.8.3))(vue@3.5.13(typescript@5.8.3))(yup@1.6.1)(zod@3.24.2)':
|
||||
'@nuxt/ui-pro@https://pkg.pr.new/@nuxt/ui-pro@655b0bd(@babel/parser@7.27.0)(joi@17.13.3)(magicast@0.3.5)(superstruct@2.0.2)(typescript@5.8.3)(valibot@1.0.0(typescript@5.8.3))(vue@3.5.13(typescript@5.8.3))(yup@1.6.1)(zod@3.24.2)':
|
||||
dependencies:
|
||||
'@ai-sdk/vue': 1.2.7(vue@3.5.13(typescript@5.8.3))(zod@3.24.2)
|
||||
'@nuxt/kit': 3.16.2(magicast@0.3.5)
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
<script lang="ts">
|
||||
import type { AccordionRootProps, AccordionRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/accordion'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { DynamicSlots } from '../types/utils'
|
||||
import type { DynamicSlots, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigAccordion = _appConfig as AppConfig & { ui: { accordion: Partial<typeof theme> } }
|
||||
|
||||
const accordion = tv({ extend: tv(theme), ...(appConfigAccordion.ui?.accordion || {}) })
|
||||
type Accordion = ComponentConfig<typeof theme, AppConfig, 'accordion'>
|
||||
|
||||
export interface AccordionItem {
|
||||
label?: string
|
||||
@@ -48,7 +44,7 @@ export interface AccordionProps<T extends AccordionItem = AccordionItem> extends
|
||||
*/
|
||||
labelKey?: string
|
||||
class?: any
|
||||
ui?: Partial<typeof accordion.slots>
|
||||
ui?: Accordion['slots']
|
||||
}
|
||||
|
||||
export interface AccordionEmits extends AccordionRootEmits {}
|
||||
@@ -71,6 +67,7 @@ import { AccordionRoot, AccordionItem, AccordionHeader, AccordionTrigger, Accord
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
const props = withDefaults(defineProps<AccordionProps<T>>(), {
|
||||
@@ -82,10 +79,11 @@ const props = withDefaults(defineProps<AccordionProps<T>>(), {
|
||||
const emits = defineEmits<AccordionEmits>()
|
||||
const slots = defineSlots<AccordionSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Accordion['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'collapsible', 'defaultValue', 'disabled', 'modelValue', 'type', 'unmountOnHide'), emits)
|
||||
|
||||
const ui = computed(() => accordion({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.accordion || {}) })({
|
||||
disabled: props.disabled
|
||||
}))
|
||||
</script>
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/alert'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ButtonProps } from '../types'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigAlert = _appConfig as AppConfig & { ui: { alert: Partial<typeof theme> } }
|
||||
|
||||
const alert = tv({ extend: tv(theme), ...(appConfigAlert.ui?.alert || {}) })
|
||||
|
||||
type AlertVariants = VariantProps<typeof alert>
|
||||
type Alert = ComponentConfig<typeof theme, AppConfig, 'alert'>
|
||||
|
||||
export interface AlertProps {
|
||||
/**
|
||||
@@ -28,16 +22,16 @@ export interface AlertProps {
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: AlertVariants['color']
|
||||
color?: Alert['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'solid'
|
||||
*/
|
||||
variant?: AlertVariants['variant']
|
||||
variant?: Alert['variants']['variant']
|
||||
/**
|
||||
* The orientation between the content and the actions.
|
||||
* @defaultValue 'vertical'
|
||||
*/
|
||||
orientation?: AlertVariants['orientation']
|
||||
orientation?: Alert['variants']['orientation']
|
||||
/**
|
||||
* Display a list of actions:
|
||||
* - under the title and description when orientation is `vertical`
|
||||
@@ -59,7 +53,7 @@ export interface AlertProps {
|
||||
*/
|
||||
closeIcon?: string
|
||||
class?: any
|
||||
ui?: Partial<typeof alert.slots>
|
||||
ui?: Alert['slots']
|
||||
}
|
||||
|
||||
export interface AlertEmits {
|
||||
@@ -71,7 +65,7 @@ export interface AlertSlots {
|
||||
title(props?: {}): any
|
||||
description(props?: {}): any
|
||||
actions(props?: {}): any
|
||||
close(props: { ui: ReturnType<typeof alert> }): any
|
||||
close(props: { ui: { [K in keyof Required<Alert['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -80,6 +74,7 @@ import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
import UButton from './Button.vue'
|
||||
@@ -91,9 +86,9 @@ const emits = defineEmits<AlertEmits>()
|
||||
const slots = defineSlots<AlertSlots>()
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Alert['AppConfig']
|
||||
|
||||
const ui = computed(() => alert({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.alert || {}) })({
|
||||
color: props.color,
|
||||
variant: props.variant,
|
||||
orientation: props.orientation,
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/avatar'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigAvatar = _appConfig as AppConfig & { ui: { avatar: Partial<typeof theme> } }
|
||||
|
||||
const avatar = tv({ extend: tv(theme), ...(appConfigAvatar.ui?.avatar || {}) })
|
||||
|
||||
type AvatarVariants = VariantProps<typeof avatar>
|
||||
type Avatar = ComponentConfig<typeof theme, AppConfig, 'avatar'>
|
||||
|
||||
export interface AvatarProps {
|
||||
/**
|
||||
@@ -27,10 +21,10 @@ export interface AvatarProps {
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: AvatarVariants['size']
|
||||
size?: Avatar['variants']['size']
|
||||
class?: any
|
||||
style?: any
|
||||
ui?: Partial<typeof avatar.slots>
|
||||
ui?: Avatar['slots']
|
||||
}
|
||||
|
||||
export interface AvatarSlots {
|
||||
@@ -41,8 +35,10 @@ export interface AvatarSlots {
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { Primitive, Slot } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import ImageComponent from '#build/ui-image-component'
|
||||
import { useAvatarGroup } from '../composables/useAvatarGroup'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
@@ -51,10 +47,11 @@ const props = withDefaults(defineProps<AvatarProps>(), { as: 'span' })
|
||||
|
||||
const fallback = computed(() => props.text || (props.alt || '').split(' ').map(word => word.charAt(0)).join('').substring(0, 2))
|
||||
|
||||
const appConfig = useAppConfig() as Avatar['AppConfig']
|
||||
const { size } = useAvatarGroup(props)
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = computed(() => avatar({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.avatar || {}) })({
|
||||
size: size.value
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/avatar-group'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigAvatarGroup = _appConfig as AppConfig & { ui: { avatarGroup: Partial<typeof theme> } }
|
||||
|
||||
const avatarGroup = tv({ extend: tv(theme), ...(appConfigAvatarGroup.ui?.avatarGroup || {}) })
|
||||
|
||||
type AvatarGroupVariants = VariantProps<typeof avatarGroup>
|
||||
type AvatarGroup = ComponentConfig<typeof theme, AppConfig, 'avatarGroup'>
|
||||
|
||||
export interface AvatarGroupProps {
|
||||
/**
|
||||
@@ -20,13 +14,13 @@ export interface AvatarGroupProps {
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: AvatarGroupVariants['size']
|
||||
size?: AvatarGroup['variants']['size']
|
||||
/**
|
||||
* The maximum number of avatars to display.
|
||||
*/
|
||||
max?: number | string
|
||||
class?: any
|
||||
ui?: Partial<typeof avatarGroup.slots>
|
||||
ui?: AvatarGroup['slots']
|
||||
}
|
||||
|
||||
export interface AvatarGroupSlots {
|
||||
@@ -37,13 +31,17 @@ export interface AvatarGroupSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed, provide } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { avatarGroupInjectionKey } from '../composables/useAvatarGroup'
|
||||
import { tv } from '../utils/tv'
|
||||
import UAvatar from './Avatar.vue'
|
||||
|
||||
const props = defineProps<AvatarGroupProps>()
|
||||
const slots = defineSlots<AvatarGroupSlots>()
|
||||
|
||||
const ui = computed(() => avatarGroup({
|
||||
const appConfig = useAppConfig() as AvatarGroup['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.avatarGroup || {}) })({
|
||||
size: props.size
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/badge'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigBadge = _appConfig as AppConfig & { ui: { badge: Partial<typeof theme> } }
|
||||
|
||||
const badge = tv({ extend: tv(theme), ...(appConfigBadge.ui?.badge || {}) })
|
||||
|
||||
type BadgeVariants = VariantProps<typeof badge>
|
||||
type Badge = ComponentConfig<typeof theme, AppConfig, 'badge'>
|
||||
|
||||
export interface BadgeProps extends Omit<UseComponentIconsProps, 'loading' | 'loadingIcon'> {
|
||||
/**
|
||||
@@ -23,17 +17,17 @@ export interface BadgeProps extends Omit<UseComponentIconsProps, 'loading' | 'lo
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: BadgeVariants['color']
|
||||
color?: Badge['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'solid'
|
||||
*/
|
||||
variant?: BadgeVariants['variant']
|
||||
variant?: Badge['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: BadgeVariants['size']
|
||||
size?: Badge['variants']['size']
|
||||
class?: any
|
||||
ui?: Partial<typeof badge.slots>
|
||||
ui?: Badge['slots']
|
||||
}
|
||||
|
||||
export interface BadgeSlots {
|
||||
@@ -46,8 +40,10 @@ export interface BadgeSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useButtonGroup } from '../composables/useButtonGroup'
|
||||
import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
|
||||
@@ -56,10 +52,11 @@ const props = withDefaults(defineProps<BadgeProps>(), {
|
||||
})
|
||||
defineSlots<BadgeSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Badge['AppConfig']
|
||||
const { orientation, size: buttonGroupSize } = useButtonGroup<BadgeProps>(props)
|
||||
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
|
||||
|
||||
const ui = computed(() => badge({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.badge || {}) })({
|
||||
color: props.color,
|
||||
variant: props.variant,
|
||||
size: buttonGroupSize.value || props.size,
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/breadcrumb'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, LinkProps } from '../types'
|
||||
import type { DynamicSlots, PartialString } from '../types/utils'
|
||||
import type { DynamicSlots, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigBreadcrumb = _appConfig as AppConfig & { ui: { breadcrumb: Partial<typeof theme> } }
|
||||
|
||||
const breadcrumb = tv({ extend: tv(theme), ...(appConfigBreadcrumb.ui?.breadcrumb || {}) })
|
||||
type Breadcrumb = ComponentConfig<typeof theme, AppConfig, 'breadcrumb'>
|
||||
|
||||
export interface BreadcrumbItem extends Omit<LinkProps, 'raw' | 'custom'> {
|
||||
label?: string
|
||||
@@ -41,7 +37,7 @@ export interface BreadcrumbProps<T extends BreadcrumbItem = BreadcrumbItem> {
|
||||
*/
|
||||
labelKey?: string
|
||||
class?: any
|
||||
ui?: PartialString<typeof breadcrumb.slots>
|
||||
ui?: Breadcrumb['slots']
|
||||
}
|
||||
|
||||
type SlotProps<T extends BreadcrumbItem> = (props: { item: T, index: number, active?: boolean }) => any
|
||||
@@ -62,6 +58,7 @@ import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import { pickLinkProps } from '../utils/link'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
@@ -73,13 +70,14 @@ const props = withDefaults(defineProps<BreadcrumbProps<T>>(), {
|
||||
labelKey: 'label'
|
||||
})
|
||||
const slots = defineSlots<BreadcrumbSlots<T>>()
|
||||
|
||||
const { dir } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Breadcrumb['AppConfig']
|
||||
|
||||
const separatorIcon = computed(() => props.separatorIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronLeft : appConfig.ui.icons.chevronRight))
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = breadcrumb()
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.breadcrumb || {}) })())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,36 +1,29 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/button'
|
||||
import type { LinkProps } from './Link.vue'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigButton = _appConfig as AppConfig & { ui: { button: Partial<typeof theme> } }
|
||||
|
||||
const button = tv({ extend: tv(theme), ...(appConfigButton.ui?.button || {}) })
|
||||
|
||||
type ButtonVariants = VariantProps<typeof button>
|
||||
type Button = ComponentConfig<typeof theme, AppConfig, 'button'>
|
||||
|
||||
export interface ButtonProps extends UseComponentIconsProps, Omit<LinkProps, 'raw' | 'custom'> {
|
||||
label?: string
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: ButtonVariants['color']
|
||||
activeColor?: ButtonVariants['color']
|
||||
color?: Button['variants']['color']
|
||||
activeColor?: Button['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'solid'
|
||||
*/
|
||||
variant?: ButtonVariants['variant']
|
||||
activeVariant?: ButtonVariants['variant']
|
||||
variant?: Button['variants']['variant']
|
||||
activeVariant?: Button['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ButtonVariants['size']
|
||||
size?: Button['variants']['size']
|
||||
/** Render the button with equal padding on all sides. */
|
||||
square?: boolean
|
||||
/** Render the button full width. */
|
||||
@@ -39,7 +32,7 @@ export interface ButtonProps extends UseComponentIconsProps, Omit<LinkProps, 'ra
|
||||
loadingAuto?: boolean
|
||||
onClick?: ((event: MouseEvent) => void | Promise<void>) | Array<((event: MouseEvent) => void | Promise<void>)>
|
||||
class?: any
|
||||
ui?: PartialString<typeof button.slots>
|
||||
ui?: Button['slots']
|
||||
}
|
||||
|
||||
export interface ButtonSlots {
|
||||
@@ -51,11 +44,14 @@ export interface ButtonSlots {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type Ref, computed, ref, inject } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { useForwardProps } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useButtonGroup } from '../composables/useButtonGroup'
|
||||
import { formLoadingInjectionKey } from '../composables/useFormField'
|
||||
import { omit } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import { pickLinkProps } from '../utils/link'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
@@ -69,10 +65,11 @@ const props = withDefaults(defineProps<ButtonProps>(), {
|
||||
})
|
||||
const slots = defineSlots<ButtonSlots>()
|
||||
|
||||
const linkProps = useForwardProps(pickLinkProps(props))
|
||||
|
||||
const appConfig = useAppConfig() as Button['AppConfig']
|
||||
const { orientation, size: buttonSize } = useButtonGroup<ButtonProps>(props)
|
||||
|
||||
const linkProps = useForwardProps(pickLinkProps(props))
|
||||
|
||||
const loadingAutoState = ref(false)
|
||||
const formLoading = inject<Ref<boolean> | undefined>(formLoadingInjectionKey, undefined)
|
||||
|
||||
@@ -95,17 +92,19 @@ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponen
|
||||
)
|
||||
|
||||
const ui = computed(() => tv({
|
||||
extend: button,
|
||||
variants: {
|
||||
active: {
|
||||
true: {
|
||||
base: props.activeClass
|
||||
},
|
||||
false: {
|
||||
base: props.inactiveClass
|
||||
extend: tv(theme),
|
||||
...defu({
|
||||
variants: {
|
||||
active: {
|
||||
true: {
|
||||
base: props.activeClass
|
||||
},
|
||||
false: {
|
||||
base: props.inactiveClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, appConfig.ui?.button || {})
|
||||
})({
|
||||
color: props.color,
|
||||
variant: props.variant,
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/button-group'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigButtonGroup = _appConfig as AppConfig & { ui: { buttonGroup: Partial<typeof theme> } }
|
||||
|
||||
const buttonGroup = tv({ extend: tv(theme), ...(appConfigButtonGroup.ui?.buttonGroup) })
|
||||
|
||||
type ButtonGroupVariants = VariantProps<typeof buttonGroup>
|
||||
type ButtonGroup = ComponentConfig<typeof theme, AppConfig, 'buttonGroup'>
|
||||
|
||||
export interface ButtonGroupProps {
|
||||
/**
|
||||
@@ -20,13 +14,14 @@ export interface ButtonGroupProps {
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ButtonGroupVariants['size']
|
||||
size?: ButtonGroup['variants']['size']
|
||||
/**
|
||||
* The orientation the buttons are laid out.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
orientation?: ButtonGroupVariants['orientation']
|
||||
orientation?: ButtonGroup['variants']['orientation']
|
||||
class?: any
|
||||
ui?: ButtonGroup['slots']
|
||||
}
|
||||
|
||||
export interface ButtonGroupSlots {
|
||||
@@ -37,13 +32,20 @@ export interface ButtonGroupSlots {
|
||||
<script setup lang="ts">
|
||||
import { provide, computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { buttonGroupInjectionKey } from '../composables/useButtonGroup'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<ButtonGroupProps>(), {
|
||||
orientation: 'horizontal'
|
||||
})
|
||||
defineSlots<ButtonGroupSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as ButtonGroup['AppConfig']
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.buttonGroup || {}) }))
|
||||
|
||||
provide(buttonGroupInjectionKey, computed(() => ({
|
||||
orientation: props.orientation,
|
||||
size: props.size
|
||||
@@ -51,7 +53,7 @@ provide(buttonGroupInjectionKey, computed(() => ({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive :as="as" :class="buttonGroup({ orientation, class: props.class })">
|
||||
<Primitive :as="as" :class="ui({ orientation, class: props.class })">
|
||||
<slot />
|
||||
</Primitive>
|
||||
</template>
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { CalendarRootProps, CalendarRootEmits, RangeCalendarRootProps, RangeCalendarRootEmits, DateRange, CalendarCellTriggerProps } from 'reka-ui'
|
||||
import type { DateValue } from '@internationalized/date'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { ButtonProps } from '../types'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/calendar'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCalendar = _appConfig as AppConfig & { ui: { calendar: Partial<typeof theme> } }
|
||||
|
||||
const calendar = tv({ extend: tv(theme), ...(appConfigCalendar.ui?.calendar || {}) })
|
||||
|
||||
type CalendarVariants = VariantProps<typeof calendar>
|
||||
type Calendar = ComponentConfig<typeof theme, AppConfig, 'calendar'>
|
||||
|
||||
type CalendarDefaultValue<R extends boolean = false, M extends boolean = false> = R extends true
|
||||
? DateRange
|
||||
@@ -82,11 +75,11 @@ export interface CalendarProps<R extends boolean = false, M extends boolean = fa
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: CalendarVariants['color']
|
||||
color?: Calendar['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: CalendarVariants['size']
|
||||
size?: Calendar['variants']['size']
|
||||
/** Whether or not a range of dates can be selected */
|
||||
range?: R & boolean
|
||||
/** Whether or not multiple dates can be selected */
|
||||
@@ -98,7 +91,7 @@ export interface CalendarProps<R extends boolean = false, M extends boolean = fa
|
||||
defaultValue?: CalendarDefaultValue<R, M>
|
||||
modelValue?: CalendarModelValue<R, M>
|
||||
class?: any
|
||||
ui?: PartialString<typeof calendar.slots>
|
||||
ui?: Calendar['slots']
|
||||
}
|
||||
|
||||
export interface CalendarEmits<R extends boolean, M extends boolean> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
|
||||
@@ -119,6 +112,7 @@ import { Calendar as SingleCalendar, RangeCalendar } from 'reka-ui/namespaced'
|
||||
import { reactiveOmit } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
const props = withDefaults(defineProps<CalendarProps<R, M>>(), {
|
||||
@@ -129,8 +123,8 @@ const props = withDefaults(defineProps<CalendarProps<R, M>>(), {
|
||||
const emits = defineEmits<CalendarEmits<R, M>>()
|
||||
defineSlots<CalendarSlots>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { code: locale, dir, t } = useLocale()
|
||||
const appConfig = useAppConfig() as Calendar['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactiveOmit(props, 'range', 'modelValue', 'defaultValue', 'color', 'size', 'monthControls', 'yearControls', 'class', 'ui'), emits)
|
||||
|
||||
@@ -139,7 +133,7 @@ const nextMonthIcon = computed(() => props.nextMonthIcon || (dir.value === 'rtl'
|
||||
const prevYearIcon = computed(() => props.prevYearIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleRight : appConfig.ui.icons.chevronDoubleLeft))
|
||||
const prevMonthIcon = computed(() => props.prevMonthIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronRight : appConfig.ui.icons.chevronLeft))
|
||||
|
||||
const ui = computed(() => calendar({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.calendar || {}) })({
|
||||
color: props.color,
|
||||
size: props.size
|
||||
}))
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/card'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCard = _appConfig as AppConfig & { ui: { card: Partial<typeof theme> } }
|
||||
|
||||
const card = tv({ extend: tv(theme), ...(appConfigCard.ui?.card || {}) })
|
||||
|
||||
type CardVariants = VariantProps<typeof card>
|
||||
type Card = ComponentConfig<typeof theme, AppConfig, 'card'>
|
||||
|
||||
export interface CardProps {
|
||||
/**
|
||||
@@ -20,9 +14,9 @@ export interface CardProps {
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: CardVariants['variant']
|
||||
variant?: Card['variants']['variant']
|
||||
class?: any
|
||||
ui?: Partial<typeof card.slots>
|
||||
ui?: Card['slots']
|
||||
}
|
||||
|
||||
export interface CardSlots {
|
||||
@@ -35,11 +29,17 @@ export interface CardSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<CardProps>()
|
||||
const slots = defineSlots<CardSlots>()
|
||||
|
||||
const ui = computed(() => card({ variant: props.variant }))
|
||||
const appConfig = useAppConfig() as Card['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.card || {}) })({
|
||||
variant: props.variant
|
||||
}))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { AcceptableValue } from 'reka-ui'
|
||||
import type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel'
|
||||
@@ -10,17 +9,11 @@ import type { AutoHeightOptionsType } from 'embla-carousel-auto-height'
|
||||
import type { ClassNamesOptionsType } from 'embla-carousel-class-names'
|
||||
import type { FadeOptionsType } from 'embla-carousel-fade'
|
||||
import type { WheelGesturesPluginOptions } from 'embla-carousel-wheel-gestures'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/carousel'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCarousel = _appConfig as AppConfig & { ui: { carousel: Partial<typeof theme> } }
|
||||
|
||||
const carousel = tv({ extend: tv(theme), ...(appConfigCarousel.ui?.carousel || {}) })
|
||||
|
||||
type CarouselVariants = VariantProps<typeof carousel>
|
||||
type Carousel = ComponentConfig<typeof theme, AppConfig, 'carousel'>
|
||||
|
||||
export type CarouselItem = AcceptableValue
|
||||
|
||||
@@ -66,7 +59,7 @@ export interface CarouselProps<T extends CarouselItem = CarouselItem> extends Om
|
||||
* The orientation of the carousel.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
orientation?: CarouselVariants['orientation']
|
||||
orientation?: Carousel['variants']['orientation']
|
||||
items?: T[]
|
||||
/**
|
||||
* Enable Autoplay plugin
|
||||
@@ -99,7 +92,7 @@ export interface CarouselProps<T extends CarouselItem = CarouselItem> extends Om
|
||||
*/
|
||||
wheelGestures?: boolean | WheelGesturesPluginOptions
|
||||
class?: any
|
||||
ui?: PartialString<typeof carousel.slots>
|
||||
ui?: Carousel['slots']
|
||||
}
|
||||
|
||||
export type CarouselSlots<T extends CarouselItem = CarouselItem> = {
|
||||
@@ -115,6 +108,7 @@ import { Primitive, useForwardProps } from 'reka-ui'
|
||||
import { reactivePick, computedAsync } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
const props = withDefaults(defineProps<CarouselProps<T>>(), {
|
||||
@@ -148,14 +142,15 @@ const props = withDefaults(defineProps<CarouselProps<T>>(), {
|
||||
})
|
||||
defineSlots<CarouselSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { dir, t } = useLocale()
|
||||
const appConfig = useAppConfig() as Carousel['AppConfig']
|
||||
|
||||
const rootProps = useForwardProps(reactivePick(props, 'active', 'align', 'breakpoints', 'containScroll', 'dragFree', 'dragThreshold', 'duration', 'inViewThreshold', 'loop', 'skipSnaps', 'slidesToScroll', 'startIndex', 'watchDrag', 'watchResize', 'watchSlides', 'watchFocus'))
|
||||
|
||||
const prevIcon = computed(() => props.prevIcon || (dir.value === 'rtl' ? appConfig.ui.icons.arrowRight : appConfig.ui.icons.arrowLeft))
|
||||
const nextIcon = computed(() => props.nextIcon || (dir.value === 'rtl' ? appConfig.ui.icons.arrowLeft : appConfig.ui.icons.arrowRight))
|
||||
|
||||
const ui = computed(() => carousel({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.carousel || {}) })({
|
||||
orientation: props.orientation
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { CheckboxRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/checkbox'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCheckbox = _appConfig as AppConfig & { ui: { checkbox: Partial<typeof theme> } }
|
||||
|
||||
const checkbox = tv({ extend: tv(theme), ...(appConfigCheckbox.ui?.checkbox || {}) })
|
||||
|
||||
type CheckboxVariants = VariantProps<typeof checkbox>
|
||||
type Checkbox = ComponentConfig<typeof theme, AppConfig, 'checkbox'>
|
||||
|
||||
export interface CheckboxProps extends Pick<CheckboxRootProps, 'disabled' | 'required' | 'name' | 'value' | 'id' | 'defaultValue'> {
|
||||
/**
|
||||
@@ -23,11 +17,11 @@ export interface CheckboxProps extends Pick<CheckboxRootProps, 'disabled' | 'req
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: CheckboxVariants['color']
|
||||
color?: Checkbox['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: CheckboxVariants['size']
|
||||
size?: Checkbox['variants']['size']
|
||||
/**
|
||||
* The icon displayed when checked.
|
||||
* @defaultValue appConfig.ui.icons.check
|
||||
@@ -41,7 +35,7 @@ export interface CheckboxProps extends Pick<CheckboxRootProps, 'disabled' | 'req
|
||||
*/
|
||||
indeterminateIcon?: string
|
||||
class?: any
|
||||
ui?: Partial<typeof checkbox.slots>
|
||||
ui?: Checkbox['slots']
|
||||
}
|
||||
|
||||
export type CheckboxEmits = {
|
||||
@@ -60,6 +54,7 @@ import { Primitive, CheckboxRoot, CheckboxIndicator, Label, useForwardProps } fr
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
@@ -70,13 +65,14 @@ const emits = defineEmits<CheckboxEmits>()
|
||||
|
||||
const modelValue = defineModel<boolean | 'indeterminate'>({ default: undefined })
|
||||
|
||||
const appConfig = useAppConfig() as Checkbox['AppConfig']
|
||||
|
||||
const rootProps = useForwardProps(reactivePick(props, 'required', 'value', 'defaultValue'))
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { id: _id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField<CheckboxProps>(props)
|
||||
const id = _id.value ?? useId()
|
||||
|
||||
const ui = computed(() => checkbox({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.checkbox || {}) })({
|
||||
size: size.value,
|
||||
color: color.value,
|
||||
required: props.required,
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/chip'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigChip = _appConfig as AppConfig & { ui: { chip: Partial<typeof theme> } }
|
||||
|
||||
const chip = tv({ extend: tv(theme), ...(appConfigChip.ui?.chip || {}) })
|
||||
|
||||
type ChipVariants = VariantProps<typeof chip>
|
||||
type Chip = ComponentConfig<typeof theme, AppConfig, 'chip'>
|
||||
|
||||
export interface ChipProps {
|
||||
/**
|
||||
@@ -22,22 +16,22 @@ export interface ChipProps {
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: ChipVariants['color']
|
||||
color?: Chip['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ChipVariants['size']
|
||||
size?: Chip['variants']['size']
|
||||
/**
|
||||
* The position of the chip.
|
||||
* @defaultValue 'top-right'
|
||||
*/
|
||||
position?: ChipVariants['position']
|
||||
position?: Chip['variants']['position']
|
||||
/** When `true`, keep the chip inside the component for rounded elements. */
|
||||
inset?: boolean
|
||||
/** When `true`, render the chip relatively to the parent. */
|
||||
standalone?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof chip.slots>
|
||||
ui?: Chip['slots']
|
||||
}
|
||||
|
||||
export interface ChipEmits {
|
||||
@@ -53,7 +47,9 @@ export interface ChipSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive, Slot } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useAvatarGroup } from '../composables/useAvatarGroup'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
@@ -66,8 +62,9 @@ defineSlots<ChipSlots>()
|
||||
const show = defineModel<boolean>('show', { default: true })
|
||||
|
||||
const { size } = useAvatarGroup(props)
|
||||
const appConfig = useAppConfig() as Chip['AppConfig']
|
||||
|
||||
const ui = computed(() => chip({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.chip || {}) })({
|
||||
color: props.color,
|
||||
size: size.value,
|
||||
position: props.position,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { CollapsibleRootProps, CollapsibleRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/collapsible'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCollapsible = _appConfig as AppConfig & { ui: { collapsible: Partial<typeof theme> } }
|
||||
|
||||
const collapsible = tv({ extend: tv(theme), ...(appConfigCollapsible.ui?.collapsible || {}) })
|
||||
type Collapsible = ComponentConfig<typeof theme, AppConfig, 'collapsible'>
|
||||
|
||||
export interface CollapsibleProps extends Pick<CollapsibleRootProps, 'defaultOpen' | 'open' | 'disabled' | 'unmountOnHide'> {
|
||||
/**
|
||||
@@ -16,7 +13,7 @@ export interface CollapsibleProps extends Pick<CollapsibleRootProps, 'defaultOpe
|
||||
*/
|
||||
as?: any
|
||||
class?: any
|
||||
ui?: Partial<typeof collapsible.slots>
|
||||
ui?: Collapsible['slots']
|
||||
}
|
||||
|
||||
export interface CollapsibleEmits extends CollapsibleRootEmits {}
|
||||
@@ -28,8 +25,11 @@ export interface CollapsibleSlots {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { CollapsibleRoot, CollapsibleTrigger, CollapsibleContent, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<CollapsibleProps>(), {
|
||||
unmountOnHide: true
|
||||
@@ -37,10 +37,12 @@ const props = withDefaults(defineProps<CollapsibleProps>(), {
|
||||
const emits = defineEmits<CollapsibleEmits>()
|
||||
const slots = defineSlots<CollapsibleSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Collapsible['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'disabled', 'unmountOnHide'), emits)
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = collapsible()
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.collapsible || {}) })())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { MaybeRefOrGetter } from '@vueuse/shared'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/color-picker'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { HSLObject } from 'colortranslator'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigColorPicker = _appConfig as AppConfig & { ui: { colorPicker: Partial<typeof theme> } }
|
||||
|
||||
const colorPicker = tv({ extend: tv(theme), ...(appConfigColorPicker.ui?.colorPicker || {}) })
|
||||
|
||||
type ColorPickerVariants = VariantProps<typeof colorPicker>
|
||||
type ColorPicker = ComponentConfig<typeof theme, AppConfig, 'colorPicker'>
|
||||
|
||||
type HSVColor = {
|
||||
h: number
|
||||
@@ -67,9 +61,9 @@ export type ColorPickerProps = {
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ColorPickerVariants['size']
|
||||
size?: ColorPicker['variants']['size']
|
||||
class?: any
|
||||
ui?: Partial<typeof colorPicker.slots>
|
||||
ui?: ColorPicker['slots']
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -80,6 +74,8 @@ import { Primitive } from 'reka-ui'
|
||||
import { useEventListener, useElementBounding, watchThrottled, watchPausable } from '@vueuse/core'
|
||||
import { isClient } from '@vueuse/shared'
|
||||
import { ColorTranslator } from 'colortranslator'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<ColorPickerProps>(), {
|
||||
format: 'hex',
|
||||
@@ -88,6 +84,12 @@ const props = withDefaults(defineProps<ColorPickerProps>(), {
|
||||
})
|
||||
const modelValue = defineModel<string>(undefined)
|
||||
|
||||
const appConfig = useAppConfig() as ColorPicker['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.colorPicker || {}) })({
|
||||
size: props.size
|
||||
}))
|
||||
|
||||
const pickedColor = computed<HSVColor>({
|
||||
get() {
|
||||
try {
|
||||
@@ -258,10 +260,6 @@ const trackThumbStyle = computed(() => ({
|
||||
backgroundColor: trackThumbColor.value,
|
||||
top: `${trackThumbPosition.value.y}%`
|
||||
}))
|
||||
|
||||
const ui = computed(() => colorPicker({
|
||||
size: props.size
|
||||
}))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -4,16 +4,12 @@ import type { ListboxRootProps, ListboxRootEmits } from 'reka-ui'
|
||||
import type { FuseResult } from 'fuse.js'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { UseFuseOptions } from '@vueuse/integrations/useFuse'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/command-palette'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ButtonProps, ChipProps, KbdProps, InputProps, LinkProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigCommandPalette = _appConfig as AppConfig & { ui: { commandPalette: Partial<typeof theme> } }
|
||||
|
||||
const commandPalette = tv({ extend: tv(theme), ...(appConfigCommandPalette.ui?.commandPalette || {}) })
|
||||
type CommandPalette = ComponentConfig<typeof theme, AppConfig, 'commandPalette'>
|
||||
|
||||
export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
|
||||
prefix?: string
|
||||
@@ -115,7 +111,7 @@ export interface CommandPaletteProps<G, T> extends Pick<ListboxRootProps, 'multi
|
||||
*/
|
||||
labelKey?: string
|
||||
class?: any
|
||||
ui?: PartialString<typeof commandPalette.slots>
|
||||
ui?: CommandPalette['slots']
|
||||
}
|
||||
|
||||
export type CommandPaletteEmits<T> = ListboxRootEmits<T> & {
|
||||
@@ -126,7 +122,7 @@ type SlotProps<T> = (props: { item: T, index: number }) => any
|
||||
|
||||
export type CommandPaletteSlots<G extends { slot?: string }, T extends { slot?: string }> = {
|
||||
'empty'(props: { searchTerm?: string }): any
|
||||
'close'(props: { ui: ReturnType<typeof commandPalette> }): any
|
||||
'close'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
'item': SlotProps<T>
|
||||
'item-leading': SlotProps<T>
|
||||
'item-label': SlotProps<T>
|
||||
@@ -144,6 +140,7 @@ import { useFuse } from '@vueuse/integrations/useFuse'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { omit, get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import { highlight } from '../utils/fuse'
|
||||
import { pickLinkProps } from '../utils/link'
|
||||
import UIcon from './Icon.vue'
|
||||
@@ -166,13 +163,13 @@ const slots = defineSlots<CommandPaletteSlots<G, T>>()
|
||||
const searchTerm = defineModel<string>('searchTerm', { default: '' })
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as CommandPalette['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'disabled', 'multiple', 'modelValue', 'defaultValue', 'highlightOnHover'), emits)
|
||||
const inputProps = useForwardProps(reactivePick(props, 'loading', 'loadingIcon'))
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = commandPalette()
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.commandPalette || {}) })())
|
||||
|
||||
const fuse = computed(() => defu({}, props.fuse, {
|
||||
fuseOptions: {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/container'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigContainer = _appConfig as AppConfig & { ui: { container: Partial<typeof theme> } }
|
||||
|
||||
const container = tv({ extend: tv(theme), ...(appConfigContainer.ui?.container || {}) })
|
||||
type Container = ComponentConfig<typeof theme, AppConfig, 'container'>
|
||||
|
||||
export interface ContainerProps {
|
||||
/**
|
||||
@@ -23,14 +20,21 @@ export interface ContainerSlots {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<ContainerProps>()
|
||||
defineSlots<ContainerSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Container['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.container || {}) }))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive :as="as" :class="container({ class: props.class })">
|
||||
<Primitive :as="as" :class="ui({ class: props.class })">
|
||||
<slot />
|
||||
</Primitive>
|
||||
</template>
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps, ContextMenuContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/context-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, KbdProps, LinkProps } from '../types'
|
||||
import type {
|
||||
ArrayOrNested,
|
||||
DynamicSlots,
|
||||
MergeTypes,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigContextMenu = _appConfig as AppConfig & { ui: { contextMenu: Partial<typeof theme> } }
|
||||
|
||||
const contextMenu = tv({ extend: tv(theme), ...(appConfigContextMenu.ui?.contextMenu || {}) })
|
||||
|
||||
type ContextMenuVariants = VariantProps<typeof contextMenu>
|
||||
type ContextMenu = ComponentConfig<typeof theme, AppConfig, 'contextMenu'>
|
||||
|
||||
export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
|
||||
label?: string
|
||||
@@ -28,7 +14,7 @@ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custo
|
||||
* @IconifyIcon
|
||||
*/
|
||||
icon?: string
|
||||
color?: ContextMenuVariants['color']
|
||||
color?: ContextMenu['variants']['color']
|
||||
avatar?: AvatarProps
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
|
||||
kbds?: KbdProps['value'][] | KbdProps[]
|
||||
@@ -53,7 +39,7 @@ export interface ContextMenuProps<T extends ArrayOrNested<ContextMenuItem> = Arr
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ContextMenuVariants['size']
|
||||
size?: ContextMenu['variants']['size']
|
||||
items?: T
|
||||
/**
|
||||
* The icon displayed when an item is checked.
|
||||
@@ -88,7 +74,7 @@ export interface ContextMenuProps<T extends ArrayOrNested<ContextMenuItem> = Arr
|
||||
labelKey?: keyof NestedItem<T>
|
||||
disabled?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof contextMenu.slots>
|
||||
ui?: ContextMenu['slots']
|
||||
}
|
||||
|
||||
export interface ContextMenuEmits extends ContextMenuRootEmits {}
|
||||
@@ -112,7 +98,9 @@ export type ContextMenuSlots<
|
||||
import { computed, toRef } from 'vue'
|
||||
import { ContextMenuRoot, ContextMenuTrigger, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { omit } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UContextMenuContent from './ContextMenuContent.vue'
|
||||
|
||||
const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
|
||||
@@ -124,12 +112,13 @@ const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
|
||||
const emits = defineEmits<ContextMenuEmits>()
|
||||
const slots = defineSlots<ContextMenuSlots<T>>()
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'modal'), emits)
|
||||
const appConfig = useAppConfig() as ContextMenu['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const proxySlots = omit(slots, ['default'])
|
||||
|
||||
const ui = computed(() => contextMenu({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.contextMenu || {}) })({
|
||||
size: props.size
|
||||
}))
|
||||
</script>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { ContextMenuContentProps as RekaContextMenuContentProps, ContextMenuContentEmits as RekaContextMenuContentEmits } from 'reka-ui'
|
||||
import theme from '#build/ui/context-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type theme from '#build/ui/context-menu'
|
||||
import type { AvatarProps, ContextMenuItem, ContextMenuSlots, KbdProps } from '../types'
|
||||
import type { ArrayOrNested, NestedItem } from '../types/utils'
|
||||
import type { ArrayOrNested, NestedItem, ComponentConfig } from '../types/utils'
|
||||
|
||||
const _contextMenu = tv(theme)()
|
||||
type ContextMenu = ComponentConfig<typeof theme, AppConfig, 'contextMenu'>
|
||||
|
||||
interface ContextMenuContentProps<T extends ArrayOrNested<ContextMenuItem>> extends Omit<RekaContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
|
||||
items?: T
|
||||
@@ -25,8 +25,8 @@ interface ContextMenuContentProps<T extends ArrayOrNested<ContextMenuItem>> exte
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
class?: any
|
||||
ui: typeof _contextMenu
|
||||
uiOverride?: any
|
||||
ui: { [K in keyof Required<ContextMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
uiOverride?: ContextMenu['slots']
|
||||
}
|
||||
|
||||
interface ContextMenuContentEmits extends RekaContextMenuContentEmits {}
|
||||
@@ -53,8 +53,9 @@ const props = defineProps<ContextMenuContentProps<T>>()
|
||||
const emits = defineEmits<ContextMenuContentEmits>()
|
||||
const slots = defineSlots<ContextMenuSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { dir } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const proxySlots = omit(slots, ['default'])
|
||||
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
import type { DrawerRootProps, DrawerRootEmits } from 'vaul-vue'
|
||||
import type { DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/drawer'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
import type { EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigDrawer = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme> } }
|
||||
|
||||
const drawer = tv({ extend: tv(theme), ...(appConfigDrawer.ui?.drawer || {}) })
|
||||
type Drawer = ComponentConfig<typeof theme, AppConfig, 'drawer'>
|
||||
|
||||
export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'shouldScaleBackground' | 'setBackgroundColorOnScale' | 'scrollLockTimeout' | 'fixed' | 'dismissible' | 'modal' | 'open' | 'defaultOpen' | 'nested' | 'direction' | 'noBodyStyles' | 'handleOnly' | 'preventScrollRestoration' | 'snapPoints'> {
|
||||
/**
|
||||
@@ -42,7 +38,7 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
|
||||
*/
|
||||
portal?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof drawer.slots>
|
||||
ui?: Drawer['slots']
|
||||
}
|
||||
|
||||
export interface DrawerEmits extends DrawerRootEmits {}
|
||||
@@ -63,6 +59,8 @@ import { computed, toRef } from 'vue'
|
||||
import { useForwardPropsEmits } from 'reka-ui'
|
||||
import { DrawerRoot, DrawerTrigger, DrawerPortal, DrawerOverlay, DrawerContent, DrawerTitle, DrawerDescription, DrawerHandle } from 'vaul-vue'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<DrawerProps>(), {
|
||||
direction: 'bottom',
|
||||
@@ -75,13 +73,15 @@ const props = withDefaults(defineProps<DrawerProps>(), {
|
||||
const emits = defineEmits<DrawerEmits>()
|
||||
const slots = defineSlots<DrawerSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Drawer['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'closeThreshold', 'shouldScaleBackground', 'setBackgroundColorOnScale', 'scrollLockTimeout', 'fixed', 'dismissible', 'modal', 'open', 'defaultOpen', 'nested', 'direction', 'noBodyStyles', 'handleOnly', 'preventScrollRestoration', 'snapPoints'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
const contentEvents = {
|
||||
closeAutoFocus: (e: Event) => e.preventDefault()
|
||||
}
|
||||
|
||||
const ui = computed(() => drawer({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}) })({
|
||||
direction: props.direction,
|
||||
inset: props.inset
|
||||
}))
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuContentEmits, DropdownMenuArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/dropdown-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, KbdProps, LinkProps } from '../types'
|
||||
import type {
|
||||
ArrayOrNested,
|
||||
DynamicSlots,
|
||||
MergeTypes,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigDropdownMenu = _appConfig as AppConfig & { ui: { dropdownMenu: Partial<typeof theme> } }
|
||||
|
||||
const dropdownMenu = tv({ extend: tv(theme), ...(appConfigDropdownMenu.ui?.dropdownMenu || {}) })
|
||||
|
||||
type DropdownMenuVariants = VariantProps<typeof dropdownMenu>
|
||||
type DropdownMenu = ComponentConfig<typeof theme, AppConfig, 'dropdownMenu'>
|
||||
|
||||
export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
|
||||
label?: string
|
||||
@@ -28,7 +14,7 @@ export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cust
|
||||
* @IconifyIcon
|
||||
*/
|
||||
icon?: string
|
||||
color?: DropdownMenuVariants['color']
|
||||
color?: DropdownMenu['variants']['color']
|
||||
avatar?: AvatarProps
|
||||
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>
|
||||
kbds?: KbdProps['value'][] | KbdProps[]
|
||||
@@ -53,7 +39,7 @@ export interface DropdownMenuProps<T extends ArrayOrNested<DropdownMenuItem> = A
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: DropdownMenuVariants['size']
|
||||
size?: DropdownMenu['variants']['size']
|
||||
items?: T
|
||||
/**
|
||||
* The icon displayed when an item is checked.
|
||||
@@ -96,7 +82,7 @@ export interface DropdownMenuProps<T extends ArrayOrNested<DropdownMenuItem> = A
|
||||
labelKey?: keyof NestedItem<T>
|
||||
disabled?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof dropdownMenu.slots>
|
||||
ui?: DropdownMenu['slots']
|
||||
}
|
||||
|
||||
export interface DropdownMenuEmits extends DropdownMenuRootEmits {}
|
||||
@@ -121,7 +107,9 @@ import { computed, toRef } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuArrow, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { omit } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UDropdownMenuContent from './DropdownMenuContent.vue'
|
||||
|
||||
const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
|
||||
@@ -133,12 +121,14 @@ const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
|
||||
const emits = defineEmits<DropdownMenuEmits>()
|
||||
const slots = defineSlots<DropdownMenuSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig() as DropdownMenu['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'modal'), emits)
|
||||
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as DropdownMenuContentProps)
|
||||
const arrowProps = toRef(() => props.arrow as DropdownMenuArrowProps)
|
||||
const proxySlots = omit(slots, ['default'])
|
||||
|
||||
const ui = computed(() => dropdownMenu({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.dropdownMenu || {}) })({
|
||||
size: props.size
|
||||
}))
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { DropdownMenuContentProps as RekaDropdownMenuContentProps, DropdownMenuContentEmits as RekaDropdownMenuContentEmits } from 'reka-ui'
|
||||
import theme from '#build/ui/dropdown-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type theme from '#build/ui/dropdown-menu'
|
||||
import type { KbdProps, AvatarProps, DropdownMenuItem, DropdownMenuSlots } from '../types'
|
||||
import type { ArrayOrNested, NestedItem } from '../types/utils'
|
||||
import type { ArrayOrNested, NestedItem, ComponentConfig } from '../types/utils'
|
||||
|
||||
const _dropdownMenu = tv(theme)()
|
||||
type DropdownMenu = ComponentConfig<typeof theme, AppConfig, 'dropdownMenu'>
|
||||
|
||||
interface DropdownMenuContentProps<T extends ArrayOrNested<DropdownMenuItem>> extends Omit<RekaDropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
|
||||
items?: T
|
||||
@@ -26,8 +26,8 @@ interface DropdownMenuContentProps<T extends ArrayOrNested<DropdownMenuItem>> ex
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
class?: any
|
||||
ui: typeof _dropdownMenu
|
||||
uiOverride?: any
|
||||
ui: { [K in keyof Required<DropdownMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
uiOverride?: DropdownMenu['slots']
|
||||
}
|
||||
|
||||
interface DropdownMenuContentEmits extends RekaDropdownMenuContentEmits {}
|
||||
@@ -59,8 +59,9 @@ const props = defineProps<DropdownMenuContentProps<T>>()
|
||||
const emits = defineEmits<DropdownMenuContentEmits>()
|
||||
const slots = defineSlots<DropdownMenuContentSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { dir } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const proxySlots = omit(slots, ['default'])
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/form'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
|
||||
import type { DeepReadonly } from 'vue'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import theme from '#build/ui/form'
|
||||
import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigForm = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
|
||||
|
||||
const form = tv({ extend: tv(theme), ...(appConfigForm.ui?.form || {}) })
|
||||
type FormConfig = ComponentConfig<typeof theme, AppConfig, 'form'>
|
||||
|
||||
export interface FormProps<T extends object> {
|
||||
id?: string | number
|
||||
@@ -56,7 +53,9 @@ export interface FormSlots {
|
||||
<script lang="ts" setup generic="T extends object">
|
||||
import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
|
||||
import { useEventBus } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
|
||||
import { tv } from '../utils/tv'
|
||||
import { validateSchema } from '../utils/form'
|
||||
import { FormValidationException } from '../types/form'
|
||||
|
||||
@@ -71,6 +70,10 @@ const props = withDefaults(defineProps<FormProps<T>>(), {
|
||||
const emits = defineEmits<FormEmits<T>>()
|
||||
defineSlots<FormSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as FormConfig['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.form || {}) }))
|
||||
|
||||
const formId = props.id ?? useId() as string
|
||||
|
||||
const bus = useEventBus<FormEvent<T>>(`form-${formId}`)
|
||||
@@ -287,7 +290,7 @@ defineExpose<Form<T>>({
|
||||
<component
|
||||
:is="parentBus ? 'div' : 'form'"
|
||||
:id="formId"
|
||||
:class="form({ class: props.class })"
|
||||
:class="ui({ class: props.class })"
|
||||
@submit.prevent="onSubmitWrapper"
|
||||
>
|
||||
<slot :errors="errors" />
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/form-field'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigFormField = _appConfig as AppConfig & { ui: { formField: Partial<typeof theme> } }
|
||||
|
||||
const formField = tv({ extend: tv(theme), ...(appConfigFormField.ui?.formField || {}) })
|
||||
|
||||
type FormFieldVariants = VariantProps<typeof formField>
|
||||
type FormField = ComponentConfig<typeof theme, AppConfig, 'formField'>
|
||||
|
||||
export interface FormFieldProps {
|
||||
/**
|
||||
@@ -29,7 +23,7 @@ export interface FormFieldProps {
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: FormFieldVariants['size']
|
||||
size?: FormField['variants']['size']
|
||||
required?: boolean
|
||||
/** If true, validation on input will be active immediately instead of waiting for a blur event. */
|
||||
eagerValidation?: boolean
|
||||
@@ -39,7 +33,7 @@ export interface FormFieldProps {
|
||||
*/
|
||||
validateOnInputDelay?: number
|
||||
class?: any
|
||||
ui?: Partial<typeof formField.slots>
|
||||
ui?: FormField['slots']
|
||||
}
|
||||
|
||||
export interface FormFieldSlots {
|
||||
@@ -55,13 +49,17 @@ export interface FormFieldSlots {
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, inject, provide, type Ref, useId } from 'vue'
|
||||
import { Primitive, Label } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { formFieldInjectionKey, inputIdInjectionKey } from '../composables/useFormField'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { FormError, FormFieldInjectedOptions } from '../types/form'
|
||||
|
||||
const props = defineProps<FormFieldProps>()
|
||||
const slots = defineSlots<FormFieldSlots>()
|
||||
|
||||
const ui = computed(() => formField({
|
||||
const appConfig = useAppConfig() as FormField['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.formField || {}) })({
|
||||
size: props.size,
|
||||
required: props.required
|
||||
}))
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { InputHTMLAttributes } from 'vue'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/input'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigInput = _appConfig as AppConfig & { ui: { input: Partial<typeof theme> } }
|
||||
|
||||
const input = tv({ extend: tv(theme), ...(appConfigInput.ui?.input || {}) })
|
||||
|
||||
type InputVariants = VariantProps<typeof input>
|
||||
type Input = ComponentConfig<typeof theme, AppConfig, 'input'>
|
||||
|
||||
export interface InputProps extends UseComponentIconsProps {
|
||||
/**
|
||||
@@ -29,15 +22,15 @@ export interface InputProps extends UseComponentIconsProps {
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: InputVariants['color']
|
||||
color?: Input['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: InputVariants['variant']
|
||||
variant?: Input['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: InputVariants['size']
|
||||
size?: Input['variants']['size']
|
||||
required?: boolean
|
||||
autocomplete?: InputHTMLAttributes['autocomplete']
|
||||
autofocus?: boolean
|
||||
@@ -46,7 +39,7 @@ export interface InputProps extends UseComponentIconsProps {
|
||||
/** Highlight the ring color like a focus state. */
|
||||
highlight?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof input.slots>
|
||||
ui?: Input['slots']
|
||||
}
|
||||
|
||||
export interface InputEmits {
|
||||
@@ -65,10 +58,12 @@ export interface InputSlots {
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useButtonGroup } from '../composables/useButtonGroup'
|
||||
import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { looseToNumber } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
|
||||
@@ -84,14 +79,15 @@ const slots = defineSlots<InputSlots>()
|
||||
|
||||
const [modelValue, modelModifiers] = defineModel<string | number | null>()
|
||||
|
||||
const appConfig = useAppConfig() as Input['AppConfig']
|
||||
const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled, emitFormFocus, ariaAttrs } = useFormField<InputProps>(props, { deferInputValidation: true })
|
||||
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
|
||||
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
|
||||
|
||||
const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)
|
||||
|
||||
const ui = computed(() => input({
|
||||
type: props.type as InputVariants['type'],
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.input || {}) })({
|
||||
type: props.type as Input['variants']['type'],
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: inputSize?.value,
|
||||
|
||||
@@ -1,27 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { InputHTMLAttributes } from 'vue'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/input-menu'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type {
|
||||
AcceptableValue,
|
||||
ArrayOrNested,
|
||||
GetItemKeys,
|
||||
GetModelValue,
|
||||
GetModelValueEmits,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigInputMenu = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
|
||||
|
||||
const inputMenu = tv({ extend: tv(theme), ...(appConfigInputMenu.ui?.inputMenu || {}) })
|
||||
type InputMenu = ComponentConfig<typeof theme, AppConfig, 'inputMenu'>
|
||||
|
||||
interface _InputMenuItem {
|
||||
label?: string
|
||||
@@ -42,8 +28,6 @@ interface _InputMenuItem {
|
||||
}
|
||||
export type InputMenuItem = _InputMenuItem | AcceptableValue | boolean
|
||||
|
||||
type InputMenuVariants = VariantProps<typeof inputMenu>
|
||||
|
||||
export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOrNested<InputMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'resetSearchTermOnSelect' | 'highlightOnHover'>, UseComponentIconsProps {
|
||||
/**
|
||||
* The element or component this component should render as.
|
||||
@@ -57,15 +41,15 @@ export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOr
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: InputMenuVariants['color']
|
||||
color?: InputMenu['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: InputMenuVariants['variant']
|
||||
variant?: InputMenu['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: InputMenuVariants['size']
|
||||
size?: InputMenu['variants']['size']
|
||||
required?: boolean
|
||||
autofocus?: boolean
|
||||
autofocusDelay?: number
|
||||
@@ -138,7 +122,7 @@ export interface InputMenuProps<T extends ArrayOrNested<InputMenuItem> = ArrayOr
|
||||
*/
|
||||
ignoreFilter?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof inputMenu.slots>
|
||||
ui?: InputMenu['slots']
|
||||
}
|
||||
|
||||
export type InputMenuEmits<A extends ArrayOrNested<InputMenuItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Pick<ComboboxRootEmits, 'update:open'> & {
|
||||
@@ -161,8 +145,16 @@ export interface InputMenuSlots<
|
||||
M extends boolean = false,
|
||||
T extends NestedItem<A> = NestedItem<A>
|
||||
> {
|
||||
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof inputMenu> }): any
|
||||
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof inputMenu> }): any
|
||||
'leading'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<InputMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'trailing'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<InputMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'empty'(props: { searchTerm?: string }): any
|
||||
'item': SlotProps<T>
|
||||
'item-leading': SlotProps<T>
|
||||
@@ -186,6 +178,7 @@ import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { compare, get, isArrayOfArray } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
import UChip from './Chip.vue'
|
||||
@@ -206,7 +199,7 @@ const slots = defineSlots<InputMenuSlots<T, VK, M>>()
|
||||
const searchTerm = defineModel<string>('searchTerm', { default: '' })
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as InputMenu['AppConfig']
|
||||
const { contains } = useFilter({ sensitivity: 'base' })
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'required', 'multiple', 'resetSearchTermOnBlur', 'resetSearchTermOnSelect', 'highlightOnHover', 'ignoreFilter'), emits)
|
||||
@@ -221,7 +214,7 @@ const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)
|
||||
|
||||
const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
|
||||
|
||||
const ui = computed(() => inputMenu({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.inputMenu || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: inputSize?.value,
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { NumberFieldRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/input-number'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigInputNumber = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
|
||||
|
||||
const inputNumber = tv({ extend: tv(theme), ...(appConfigInputNumber.ui?.inputNumber || {}) })
|
||||
|
||||
type InputNumberVariants = VariantProps<typeof inputNumber>
|
||||
type InputNumber = ComponentConfig<typeof theme, AppConfig, 'inputNumber'>
|
||||
|
||||
export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue' | 'defaultValue' | 'min' | 'max' | 'step' | 'stepSnapping' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions' | 'disableWheelChange'> {
|
||||
/**
|
||||
@@ -22,9 +15,9 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
|
||||
as?: any
|
||||
/** The placeholder text when the input is empty. */
|
||||
placeholder?: string
|
||||
color?: InputNumberVariants['color']
|
||||
variant?: InputNumberVariants['variant']
|
||||
size?: InputNumberVariants['size']
|
||||
color?: InputNumber['variants']['color']
|
||||
variant?: InputNumber['variants']['variant']
|
||||
size?: InputNumber['variants']['size']
|
||||
/** Highlight the ring color like a focus state. */
|
||||
highlight?: boolean
|
||||
/**
|
||||
@@ -62,7 +55,7 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
|
||||
*/
|
||||
locale?: string
|
||||
class?: any
|
||||
ui?: PartialString<typeof inputNumber.slots>
|
||||
ui?: InputNumber['slots']
|
||||
}
|
||||
|
||||
export interface InputNumberEmits {
|
||||
@@ -84,6 +77,7 @@ import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
@@ -94,15 +88,16 @@ const props = withDefaults(defineProps<InputNumberProps>(), {
|
||||
const emits = defineEmits<InputNumberEmits>()
|
||||
defineSlots<InputNumberSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as InputNumber['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'stepSnapping', 'formatOptions', 'disableWheelChange'), emits)
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { emitFormBlur, emitFormFocus, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled, ariaAttrs } = useFormField<InputNumberProps>(props)
|
||||
|
||||
const { t, code: codeLocale } = useLocale()
|
||||
const locale = computed(() => props.locale || codeLocale.value)
|
||||
|
||||
const ui = computed(() => inputNumber({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.inputNumber || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: size.value,
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/kbd'
|
||||
import type { KbdKey } from '../composables/useKbd'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigKbd = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
|
||||
|
||||
const kbd = tv({ extend: tv(theme), ...(appConfigKbd.ui?.kbd || {}) })
|
||||
|
||||
type KbdVariants = VariantProps<typeof kbd>
|
||||
type Kbd = ComponentConfig<typeof theme, AppConfig, 'kbd'>
|
||||
|
||||
export interface KbdProps {
|
||||
/**
|
||||
@@ -22,11 +16,11 @@ export interface KbdProps {
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: KbdVariants['variant']
|
||||
variant?: Kbd['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: KbdVariants['size']
|
||||
size?: Kbd['variants']['size']
|
||||
class?: any
|
||||
}
|
||||
|
||||
@@ -36,8 +30,11 @@ export interface KbdSlots {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useKbd } from '../composables/useKbd'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<KbdProps>(), {
|
||||
as: 'kbd'
|
||||
@@ -45,10 +42,13 @@ const props = withDefaults(defineProps<KbdProps>(), {
|
||||
defineSlots<KbdSlots>()
|
||||
|
||||
const { getKbdKey } = useKbd()
|
||||
const appConfig = useAppConfig() as Kbd['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.kbd || {}) }))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive :as="as" :class="kbd({ variant, size, class: props.class })">
|
||||
<Primitive :as="as" :class="ui({ variant, size, class: props.class })">
|
||||
<slot>
|
||||
{{ getKbdKey(value) }}
|
||||
</slot>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { ButtonHTMLAttributes } from 'vue'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
|
||||
import theme from '#build/ui/link'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
type Link = ComponentConfig<typeof theme, AppConfig, 'link'>
|
||||
|
||||
interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
||||
/**
|
||||
@@ -52,10 +53,6 @@ interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
||||
noPrefetch?: boolean
|
||||
}
|
||||
|
||||
const appConfigLink = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
|
||||
|
||||
const link = tv({ extend: tv(theme), ...(appConfigLink.ui?.link || {}) })
|
||||
|
||||
export interface LinkProps extends NuxtLinkProps {
|
||||
/**
|
||||
* The element or component this component should render as when not a link.
|
||||
@@ -91,10 +88,12 @@ export interface LinkSlots {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { isEqual, diff } from 'ohash/utils'
|
||||
import { useForwardProps } from 'reka-ui'
|
||||
import { reactiveOmit } from '@vueuse/core'
|
||||
import { useRoute } from '#imports'
|
||||
import { useRoute, useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
import ULinkBase from './LinkBase.vue'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
@@ -110,16 +109,20 @@ const props = withDefaults(defineProps<LinkProps>(), {
|
||||
defineSlots<LinkSlots>()
|
||||
|
||||
const route = useRoute()
|
||||
const appConfig = useAppConfig() as Link['AppConfig']
|
||||
|
||||
const nuxtLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'raw', 'class'))
|
||||
|
||||
const ui = computed(() => tv({
|
||||
extend: link,
|
||||
variants: {
|
||||
active: {
|
||||
true: props.activeClass,
|
||||
false: props.inactiveClass
|
||||
extend: tv(theme),
|
||||
...defu({
|
||||
variants: {
|
||||
active: {
|
||||
true: props.activeClass,
|
||||
false: props.inactiveClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}, appConfig.ui?.link || {})
|
||||
}))
|
||||
|
||||
function isPartiallyEqual(item1: any, item2: any) {
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/modal'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
import type { EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigModal = _appConfig as AppConfig & { ui: { modal: Partial<typeof theme> } }
|
||||
|
||||
const modal = tv({ extend: tv(theme), ...(appConfigModal.ui?.modal || {}) })
|
||||
type Modal = ComponentConfig<typeof theme, AppConfig, 'modal'>
|
||||
|
||||
export interface ModalProps extends DialogRootProps {
|
||||
title?: string
|
||||
@@ -54,7 +50,7 @@ export interface ModalProps extends DialogRootProps {
|
||||
*/
|
||||
dismissible?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof modal.slots>
|
||||
ui?: Modal['slots']
|
||||
}
|
||||
|
||||
export interface ModalEmits extends DialogRootEmits {
|
||||
@@ -67,7 +63,7 @@ export interface ModalSlots {
|
||||
header(props?: {}): any
|
||||
title(props?: {}): any
|
||||
description(props?: {}): any
|
||||
close(props: { ui: ReturnType<typeof modal> }): any
|
||||
close(props: { ui: { [K in keyof Required<Modal['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
body(props?: {}): any
|
||||
footer(props?: {}): any
|
||||
}
|
||||
@@ -79,6 +75,7 @@ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent,
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
const props = withDefaults(defineProps<ModalProps>(), {
|
||||
@@ -93,7 +90,7 @@ const emits = defineEmits<ModalEmits>()
|
||||
const slots = defineSlots<ModalSlots>()
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Modal['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
@@ -114,7 +111,7 @@ const contentEvents = computed(() => {
|
||||
return events
|
||||
})
|
||||
|
||||
const ui = computed(() => modal({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.modal || {}) })({
|
||||
transition: props.transition,
|
||||
fullscreen: props.fullscreen
|
||||
}))
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, NavigationMenuContentEmits, CollapsibleRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/navigation-menu'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, BadgeProps, LinkProps } from '../types'
|
||||
import type {
|
||||
ArrayOrNested,
|
||||
DynamicSlots,
|
||||
MergeTypes,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigNavigationMenu = _appConfig as AppConfig & { ui: { navigationMenu: Partial<typeof theme> } }
|
||||
|
||||
const navigationMenu = tv({ extend: tv(theme), ...(appConfigNavigationMenu.ui?.navigationMenu || {}) })
|
||||
type NavigationMenu = ComponentConfig<typeof theme, AppConfig, 'navigationMenu'>
|
||||
|
||||
export interface NavigationMenuChildItem extends Omit<NavigationMenuItem, 'type'> {
|
||||
/** Description is only used when `orientation` is `horizontal`. */
|
||||
@@ -55,8 +43,6 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
type NavigationMenuVariants = VariantProps<typeof navigationMenu>
|
||||
|
||||
export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem> = ArrayOrNested<NavigationMenuItem>> extends Pick<NavigationMenuRootProps, 'modelValue' | 'defaultValue' | 'delayDuration' | 'disableClickTrigger' | 'disableHoverTrigger' | 'skipDelayDuration' | 'disablePointerLeaveClose' | 'unmountOnHide'> {
|
||||
/**
|
||||
* The element or component this component should render as.
|
||||
@@ -80,11 +66,11 @@ export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem>
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: NavigationMenuVariants['color']
|
||||
color?: NavigationMenu['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'pill'
|
||||
*/
|
||||
variant?: NavigationMenuVariants['variant']
|
||||
variant?: NavigationMenu['variants']['variant']
|
||||
/**
|
||||
* The orientation of the menu.
|
||||
* @defaultValue 'horizontal'
|
||||
@@ -101,7 +87,7 @@ export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem>
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
highlightColor?: NavigationMenuVariants['highlightColor']
|
||||
highlightColor?: NavigationMenu['variants']['highlightColor']
|
||||
/** The content of the menu. */
|
||||
content?: Omit<NavigationMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<NavigationMenuContentEmits>>
|
||||
/**
|
||||
@@ -109,7 +95,7 @@ export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem>
|
||||
* Only works when `orientation` is `horizontal`.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
contentOrientation?: NavigationMenuVariants['contentOrientation']
|
||||
contentOrientation?: NavigationMenu['variants']['contentOrientation']
|
||||
/**
|
||||
* Display an arrow alongside the menu.
|
||||
* @defaultValue false
|
||||
@@ -121,7 +107,7 @@ export interface NavigationMenuProps<T extends ArrayOrNested<NavigationMenuItem>
|
||||
*/
|
||||
labelKey?: keyof NestedItem<T>
|
||||
class?: any
|
||||
ui?: PartialString<typeof navigationMenu.slots>
|
||||
ui?: NavigationMenu['slots']
|
||||
}
|
||||
|
||||
export interface NavigationMenuEmits extends NavigationMenuRootEmits {}
|
||||
@@ -147,6 +133,7 @@ import { NavigationMenuRoot, NavigationMenuList, NavigationMenuItem, NavigationM
|
||||
import { createReusableTemplate } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { get, isArrayOfArray } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import { pickLinkProps } from '../utils/link'
|
||||
import ULinkBase from './LinkBase.vue'
|
||||
import ULink from './Link.vue'
|
||||
@@ -166,6 +153,8 @@ const props = withDefaults(defineProps<NavigationMenuProps<T>>(), {
|
||||
const emits = defineEmits<NavigationMenuEmits>()
|
||||
const slots = defineSlots<NavigationMenuSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig() as NavigationMenu['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(computed(() => ({
|
||||
as: props.as,
|
||||
modelValue: props.modelValue,
|
||||
@@ -178,11 +167,8 @@ const rootProps = useForwardPropsEmits(computed(() => ({
|
||||
disablePointerLeaveClose: props.disablePointerLeaveClose,
|
||||
unmountOnHide: props.unmountOnHide
|
||||
})), emits)
|
||||
|
||||
const contentProps = toRef(() => props.content)
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, active?: boolean }>()
|
||||
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, level?: number }>({
|
||||
props: {
|
||||
@@ -192,7 +178,7 @@ const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: N
|
||||
}
|
||||
})
|
||||
|
||||
const ui = computed(() => navigationMenu({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.navigationMenu || {}) })({
|
||||
orientation: props.orientation,
|
||||
contentOrientation: props.contentOrientation,
|
||||
collapsed: props.collapsed,
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { PaginationRootProps, PaginationRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/pagination'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigPagination = _appConfig as AppConfig & { ui: { pagination: Partial<typeof theme> } }
|
||||
|
||||
const pagination = tv({ extend: tv(theme), ...(appConfigPagination.ui?.pagination || {}) })
|
||||
type Pagination = ComponentConfig<typeof theme, AppConfig, 'pagination'>
|
||||
|
||||
export interface PaginationProps extends Partial<Pick<PaginationRootProps, 'defaultPage' | 'disabled' | 'itemsPerPage' | 'page' | 'showEdges' | 'siblingCount' | 'total'>> {
|
||||
/**
|
||||
@@ -79,7 +76,7 @@ export interface PaginationProps extends Partial<Pick<PaginationRootProps, 'defa
|
||||
*/
|
||||
to?: (page: number) => ButtonProps['to']
|
||||
class?: any
|
||||
ui?: Partial<typeof pagination.slots>
|
||||
ui?: Pagination['slots']
|
||||
}
|
||||
|
||||
export interface PaginationEmits extends PaginationRootEmits {}
|
||||
@@ -110,6 +107,7 @@ import { PaginationRoot, PaginationList, PaginationListItem, PaginationFirst, Pa
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationProps>(), {
|
||||
@@ -127,8 +125,9 @@ const props = withDefaults(defineProps<PaginationProps>(), {
|
||||
const emits = defineEmits<PaginationEmits>()
|
||||
const slots = defineSlots<PaginationSlots>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const { dir } = useLocale()
|
||||
const appConfig = useAppConfig() as Pagination['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultPage', 'disabled', 'itemsPerPage', 'page', 'showEdges', 'siblingCount', 'total'), emits)
|
||||
|
||||
const firstIcon = computed(() => props.firstIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleRight : appConfig.ui.icons.chevronDoubleLeft))
|
||||
@@ -137,7 +136,7 @@ const nextIcon = computed(() => props.nextIcon || (dir.value === 'rtl' ? appConf
|
||||
const lastIcon = computed(() => props.lastIcon || (dir.value === 'rtl' ? appConfig.ui.icons.chevronDoubleLeft : appConfig.ui.icons.chevronDoubleRight))
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = pagination()
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.pagination || {}) })())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/pin-input'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigPinInput = _appConfig as AppConfig & { ui: { pinInput: Partial<typeof theme> } }
|
||||
|
||||
const pinInput = tv({ extend: tv(theme), ...(appConfigPinInput.ui?.pinInput || {}) })
|
||||
|
||||
type PinInputVariants = VariantProps<typeof pinInput>
|
||||
type PinInput = ComponentConfig<typeof theme, AppConfig, 'pinInput'>
|
||||
|
||||
export interface PinInputProps extends Pick<PinInputRootProps, 'defaultValue' | 'disabled' | 'id' | 'mask' | 'modelValue' | 'name' | 'otp' | 'placeholder' | 'required' | 'type'> {
|
||||
/**
|
||||
@@ -23,15 +16,15 @@ export interface PinInputProps extends Pick<PinInputRootProps, 'defaultValue' |
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: PinInputVariants['color']
|
||||
color?: PinInput['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: PinInputVariants['variant']
|
||||
variant?: PinInput['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: PinInputVariants['size']
|
||||
size?: PinInput['variants']['size']
|
||||
/**
|
||||
* The number of input fields.
|
||||
* @defaultValue 5
|
||||
@@ -41,7 +34,7 @@ export interface PinInputProps extends Pick<PinInputRootProps, 'defaultValue' |
|
||||
autofocusDelay?: number
|
||||
highlight?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof pinInput.slots>
|
||||
ui?: PinInput['slots']
|
||||
}
|
||||
|
||||
export type PinInputEmits = PinInputRootEmits & {
|
||||
@@ -56,8 +49,10 @@ import type { ComponentPublicInstance } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { PinInputInput, PinInputRoot, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { looseToNumber } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<PinInputProps>(), {
|
||||
type: 'text',
|
||||
@@ -66,10 +61,13 @@ const props = withDefaults(defineProps<PinInputProps>(), {
|
||||
})
|
||||
const emits = defineEmits<PinInputEmits>()
|
||||
|
||||
const appConfig = useAppConfig() as PinInput['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultValue', 'disabled', 'id', 'mask', 'modelValue', 'name', 'otp', 'placeholder', 'required', 'type'), emits)
|
||||
|
||||
const { emitFormInput, emitFormFocus, emitFormChange, emitFormBlur, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<PinInputProps>(props)
|
||||
|
||||
const ui = computed(() => pinInput({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.pinInput || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: size.value,
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverContentEmits, PopoverArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/popover'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
import type { EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigPopover = _appConfig as AppConfig & { ui: { popover: Partial<typeof theme> } }
|
||||
|
||||
const popover = tv({ extend: tv(theme), ...(appConfigPopover.ui?.popover || {}) })
|
||||
type Popover = ComponentConfig<typeof theme, AppConfig, 'popover'>
|
||||
|
||||
export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps, 'openDelay' | 'closeDelay'> {
|
||||
/**
|
||||
@@ -37,7 +33,7 @@ export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps,
|
||||
*/
|
||||
dismissible?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof popover.slots>
|
||||
ui?: Popover['slots']
|
||||
}
|
||||
|
||||
export interface PopoverEmits extends PopoverRootEmits {}
|
||||
@@ -54,6 +50,8 @@ import { defu } from 'defu'
|
||||
import { useForwardPropsEmits } from 'reka-ui'
|
||||
import { Popover, HoverCard } from 'reka-ui/namespaced'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<PopoverProps>(), {
|
||||
portal: true,
|
||||
@@ -65,6 +63,8 @@ const props = withDefaults(defineProps<PopoverProps>(), {
|
||||
const emits = defineEmits<PopoverEmits>()
|
||||
const slots = defineSlots<PopoverSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Popover['AppConfig']
|
||||
|
||||
const pick = props.mode === 'hover' ? reactivePick(props, 'defaultOpen', 'open', 'openDelay', 'closeDelay') : reactivePick(props, 'defaultOpen', 'open', 'modal')
|
||||
const rootProps = useForwardPropsEmits(pick, emits)
|
||||
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as PopoverContentProps)
|
||||
@@ -82,7 +82,7 @@ const contentEvents = computed(() => {
|
||||
const arrowProps = toRef(() => props.arrow as PopoverArrowProps)
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = computed(() => popover({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.popover || {}) })({
|
||||
side: contentProps.value.side
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ProgressRootProps, ProgressRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/progress'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigProgress = _appConfig as AppConfig & { ui: { progress: Partial<typeof theme> } }
|
||||
|
||||
const progress = tv({ extend: tv(theme), ...(appConfigProgress.ui?.progress || {}) })
|
||||
|
||||
type ProgressVariants = VariantProps<typeof progress>
|
||||
type Progress = ComponentConfig<typeof theme, AppConfig, 'progress'>
|
||||
|
||||
export interface ProgressProps extends Pick<ProgressRootProps, 'getValueLabel' | 'modelValue'> {
|
||||
/**
|
||||
@@ -28,23 +22,23 @@ export interface ProgressProps extends Pick<ProgressRootProps, 'getValueLabel' |
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: ProgressVariants['size']
|
||||
size?: Progress['variants']['size']
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: ProgressVariants['color']
|
||||
color?: Progress['variants']['color']
|
||||
/**
|
||||
* The orientation of the progress bar.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
orientation?: ProgressVariants['orientation']
|
||||
orientation?: Progress['variants']['orientation']
|
||||
/**
|
||||
* The animation of the progress bar.
|
||||
* @defaultValue 'carousel'
|
||||
*/
|
||||
animation?: ProgressVariants['animation']
|
||||
animation?: Progress['variants']['animation']
|
||||
class?: any
|
||||
ui?: Partial<typeof progress.slots>
|
||||
ui?: Progress['slots']
|
||||
}
|
||||
|
||||
export interface ProgressEmits extends ProgressRootEmits {}
|
||||
@@ -61,7 +55,9 @@ export type ProgressSlots = {
|
||||
import { computed } from 'vue'
|
||||
import { Primitive, ProgressRoot, ProgressIndicator, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<ProgressProps>(), {
|
||||
inverted: false,
|
||||
@@ -72,6 +68,7 @@ const emits = defineEmits<ProgressEmits>()
|
||||
const slots = defineSlots<ProgressSlots>()
|
||||
|
||||
const { dir } = useLocale()
|
||||
const appConfig = useAppConfig() as Progress['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'getValueLabel', 'modelValue'), emits)
|
||||
|
||||
@@ -160,7 +157,7 @@ function stepVariant(index: number | string) {
|
||||
return 'other'
|
||||
}
|
||||
|
||||
const ui = computed(() => progress({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.progress || {}) })({
|
||||
animation: props.animation,
|
||||
size: props.size,
|
||||
color: props.color,
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { RadioGroupRootProps, RadioGroupRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/radio-group'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AcceptableValue } from '../types/utils'
|
||||
import type { AcceptableValue, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigRadioGroup = _appConfig as AppConfig & { ui: { radioGroup: Partial<typeof theme> } }
|
||||
|
||||
const radioGroup = tv({ extend: tv(theme), ...(appConfigRadioGroup.ui?.radioGroup || {}) })
|
||||
|
||||
type RadioGroupVariants = VariantProps<typeof radioGroup>
|
||||
type RadioGroup = ComponentConfig<typeof theme, AppConfig, 'radioGroup'>
|
||||
|
||||
export type RadioGroupValue = AcceptableValue
|
||||
export type RadioGroupItem = {
|
||||
@@ -48,15 +41,15 @@ export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> exte
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: RadioGroupVariants['size']
|
||||
size?: RadioGroup['variants']['size']
|
||||
/**
|
||||
* @defaultValue 'list'
|
||||
*/
|
||||
variant?: RadioGroupVariants['variant']
|
||||
variant?: RadioGroup['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: RadioGroupVariants['color']
|
||||
color?: RadioGroup['variants']['color']
|
||||
/**
|
||||
* The orientation the radio buttons are laid out.
|
||||
* @defaultValue 'vertical'
|
||||
@@ -66,9 +59,9 @@ export interface RadioGroupProps<T extends RadioGroupItem = RadioGroupItem> exte
|
||||
* Position of the indicator.
|
||||
* @defaultValue 'start'
|
||||
*/
|
||||
indicator?: RadioGroupVariants['indicator']
|
||||
indicator?: RadioGroup['variants']['indicator']
|
||||
class?: any
|
||||
ui?: Partial<typeof radioGroup.slots>
|
||||
ui?: RadioGroup['slots']
|
||||
}
|
||||
|
||||
export type RadioGroupEmits = RadioGroupRootEmits & {
|
||||
@@ -88,8 +81,10 @@ export interface RadioGroupSlots<T extends RadioGroupItem = RadioGroupItem> {
|
||||
import { computed, useId } from 'vue'
|
||||
import { RadioGroupRoot, RadioGroupItem, RadioGroupIndicator, Label, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<RadioGroupProps<T>>(), {
|
||||
valueKey: 'value',
|
||||
@@ -100,12 +95,14 @@ const props = withDefaults(defineProps<RadioGroupProps<T>>(), {
|
||||
const emits = defineEmits<RadioGroupEmits>()
|
||||
const slots = defineSlots<RadioGroupSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig() as RadioGroup['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'orientation', 'loop', 'required'), emits)
|
||||
|
||||
const { emitFormChange, emitFormInput, color, name, size, id: _id, disabled, ariaAttrs } = useFormField<RadioGroupProps<T>>(props, { bind: false })
|
||||
const id = _id.value ?? useId()
|
||||
|
||||
const ui = computed(() => radioGroup({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.radioGroup || {}) })({
|
||||
size: size.value,
|
||||
color: color.value,
|
||||
disabled: disabled.value,
|
||||
|
||||
@@ -1,27 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { SelectRootProps, SelectRootEmits, SelectContentProps, SelectContentEmits, SelectArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/select'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type {
|
||||
AcceptableValue,
|
||||
ArrayOrNested,
|
||||
GetItemKeys,
|
||||
GetItemValue,
|
||||
GetModelValue,
|
||||
GetModelValueEmits,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetItemValue, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSelect = _appConfig as AppConfig & { ui: { select: Partial<typeof theme> } }
|
||||
|
||||
const select = tv({ extend: tv(theme), ...(appConfigSelect.ui?.select || {}) })
|
||||
type Select = ComponentConfig<typeof theme, AppConfig, 'select'>
|
||||
|
||||
interface SelectItemBase {
|
||||
label?: string
|
||||
@@ -43,8 +28,6 @@ interface SelectItemBase {
|
||||
}
|
||||
export type SelectItem = SelectItemBase | AcceptableValue | boolean
|
||||
|
||||
type SelectVariants = VariantProps<typeof select>
|
||||
|
||||
export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested<SelectItem>, VK extends GetItemKeys<T> = 'value', M extends boolean = false> extends Omit<SelectRootProps<T>, 'dir' | 'multiple' | 'modelValue' | 'defaultValue' | 'by'>, UseComponentIconsProps {
|
||||
id?: string
|
||||
/** The placeholder text when the select is empty. */
|
||||
@@ -52,15 +35,15 @@ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: SelectVariants['color']
|
||||
color?: Select['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: SelectVariants['variant']
|
||||
variant?: Select['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: SelectVariants['size']
|
||||
size?: Select['variants']['size']
|
||||
/**
|
||||
* The icon displayed to open the menu.
|
||||
* @defaultValue appConfig.ui.icons.chevronDown
|
||||
@@ -108,7 +91,7 @@ export interface SelectProps<T extends ArrayOrNested<SelectItem> = ArrayOrNested
|
||||
/** Highlight the ring color like a focus state. */
|
||||
highlight?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof select.slots>
|
||||
ui?: Select['slots']
|
||||
}
|
||||
|
||||
export type SelectEmits<A extends ArrayOrNested<SelectItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<SelectRootEmits, 'update:modelValue'> & {
|
||||
@@ -125,9 +108,20 @@ export interface SelectSlots<
|
||||
M extends boolean = false,
|
||||
T extends NestedItem<A> = NestedItem<A>
|
||||
> {
|
||||
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
||||
'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
|
||||
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof select> }): any
|
||||
'leading'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'default'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
}): any
|
||||
'trailing'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<Select['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'item': SlotProps<T>
|
||||
'item-leading': SlotProps<T>
|
||||
'item-label': SlotProps<T>
|
||||
@@ -145,6 +139,7 @@ import { useButtonGroup } from '../composables/useButtonGroup'
|
||||
import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { compare, get, isArrayOfArray } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
import UChip from './Chip.vue'
|
||||
@@ -159,7 +154,8 @@ const props = withDefaults(defineProps<SelectProps<T, VK, M>>(), {
|
||||
const emits = defineEmits<SelectEmits<T, VK, M>>()
|
||||
const slots = defineSlots<SelectSlots<T, VK, M>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Select['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'disabled', 'autocomplete', 'required', 'multiple'), emits)
|
||||
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8, position: 'popper' }) as SelectContentProps)
|
||||
const arrowProps = toRef(() => props.arrow as SelectArrowProps)
|
||||
@@ -170,7 +166,7 @@ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponen
|
||||
|
||||
const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
|
||||
|
||||
const ui = computed(() => select({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.select || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: selectSize?.value,
|
||||
|
||||
@@ -1,27 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxContentEmits, ComboboxArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/select-menu'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
||||
import type {
|
||||
AcceptableValue,
|
||||
ArrayOrNested,
|
||||
GetItemKeys,
|
||||
GetItemValue,
|
||||
GetModelValue,
|
||||
GetModelValueEmits,
|
||||
NestedItem,
|
||||
PartialString,
|
||||
EmitsToProps
|
||||
} from '../types/utils'
|
||||
import type { AcceptableValue, ArrayOrNested, GetItemKeys, GetItemValue, GetModelValue, GetModelValueEmits, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSelectMenu = _appConfig as AppConfig & { ui: { selectMenu: Partial<typeof theme> } }
|
||||
|
||||
const selectMenu = tv({ extend: tv(theme), ...(appConfigSelectMenu.ui?.selectMenu || {}) })
|
||||
type SelectMenu = ComponentConfig<typeof theme, AppConfig, 'selectMenu'>
|
||||
|
||||
interface _SelectMenuItem {
|
||||
label?: string
|
||||
@@ -42,8 +27,6 @@ interface _SelectMenuItem {
|
||||
}
|
||||
export type SelectMenuItem = _SelectMenuItem | AcceptableValue | boolean
|
||||
|
||||
type SelectMenuVariants = VariantProps<typeof selectMenu>
|
||||
|
||||
export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'open' | 'defaultOpen' | 'disabled' | 'name' | 'resetSearchTermOnBlur' | 'resetSearchTermOnSelect' | 'highlightOnHover'>, UseComponentIconsProps {
|
||||
id?: string
|
||||
/** The placeholder text when the select is empty. */
|
||||
@@ -58,15 +41,15 @@ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = Array
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: SelectMenuVariants['color']
|
||||
color?: SelectMenu['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: SelectMenuVariants['variant']
|
||||
variant?: SelectMenu['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: SelectMenuVariants['size']
|
||||
size?: SelectMenu['variants']['size']
|
||||
required?: boolean
|
||||
/**
|
||||
* The icon displayed to open the menu.
|
||||
@@ -131,7 +114,7 @@ export interface SelectMenuProps<T extends ArrayOrNested<SelectMenuItem> = Array
|
||||
*/
|
||||
ignoreFilter?: boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof selectMenu.slots>
|
||||
ui?: SelectMenu['slots']
|
||||
}
|
||||
|
||||
export type SelectMenuEmits<A extends ArrayOrNested<SelectMenuItem>, VK extends GetItemKeys<A> | undefined, M extends boolean> = Pick<ComboboxRootEmits, 'update:open'> & {
|
||||
@@ -154,9 +137,20 @@ export interface SelectMenuSlots<
|
||||
M extends boolean = false,
|
||||
T extends NestedItem<A> = NestedItem<A>
|
||||
> {
|
||||
'leading'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof selectMenu> }): any
|
||||
'default'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean }): any
|
||||
'trailing'(props: { modelValue?: GetModelValue<A, VK, M>, open: boolean, ui: ReturnType<typeof selectMenu> }): any
|
||||
'leading'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<SelectMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'default'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
}): any
|
||||
'trailing'(props: {
|
||||
modelValue?: GetModelValue<A, VK, M>
|
||||
open: boolean
|
||||
ui: { [K in keyof Required<SelectMenu['slots']>]: (props?: Record<string, any>) => string }
|
||||
}): any
|
||||
'empty'(props: { searchTerm?: string }): any
|
||||
'item': SlotProps<T>
|
||||
'item-leading': SlotProps<T>
|
||||
@@ -177,6 +171,7 @@ import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { compare, get, isArrayOfArray } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
import UChip from './Chip.vue'
|
||||
@@ -197,7 +192,7 @@ const slots = defineSlots<SelectMenuSlots<T, VK, M>>()
|
||||
const searchTerm = defineModel<string>('searchTerm', { default: '' })
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as SelectMenu['AppConfig']
|
||||
const { contains } = useFilter({ sensitivity: 'base' })
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'required', 'multiple', 'resetSearchTermOnBlur', 'resetSearchTermOnSelect', 'highlightOnHover'), emits)
|
||||
@@ -213,7 +208,7 @@ const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)
|
||||
|
||||
const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
|
||||
|
||||
const ui = computed(() => selectMenu({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.selectMenu || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: selectSize?.value,
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { SeparatorProps as _SeparatorProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/separator'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSeparator = _appConfig as AppConfig & { ui: { separator: Partial<typeof theme> } }
|
||||
|
||||
const separator = tv({ extend: tv(theme), ...(appConfigSeparator.ui?.separator || {}) })
|
||||
|
||||
type SeparatorVariants = VariantProps<typeof separator>
|
||||
type Separator = ComponentConfig<typeof theme, AppConfig, 'separator'>
|
||||
|
||||
export interface SeparatorProps extends Pick<_SeparatorProps, 'decorative'> {
|
||||
/**
|
||||
@@ -31,22 +25,22 @@ export interface SeparatorProps extends Pick<_SeparatorProps, 'decorative'> {
|
||||
/**
|
||||
* @defaultValue 'neutral'
|
||||
*/
|
||||
color?: SeparatorVariants['color']
|
||||
color?: Separator['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'xs'
|
||||
*/
|
||||
size?: SeparatorVariants['size']
|
||||
size?: Separator['variants']['size']
|
||||
/**
|
||||
* @defaultValue 'solid'
|
||||
*/
|
||||
type?: SeparatorVariants['type']
|
||||
type?: Separator['variants']['type']
|
||||
/**
|
||||
* The orientation of the separator.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
orientation?: _SeparatorProps['orientation']
|
||||
class?: any
|
||||
ui?: Partial<typeof separator.slots>
|
||||
ui?: Separator['slots']
|
||||
}
|
||||
|
||||
export interface SeparatorSlots {
|
||||
@@ -58,6 +52,8 @@ export interface SeparatorSlots {
|
||||
import { computed } from 'vue'
|
||||
import { Separator, useForwardProps } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
|
||||
@@ -66,9 +62,11 @@ const props = withDefaults(defineProps<SeparatorProps>(), {
|
||||
})
|
||||
const slots = defineSlots<SeparatorSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Separator['AppConfig']
|
||||
|
||||
const rootProps = useForwardProps(reactivePick(props, 'as', 'decorative', 'orientation'))
|
||||
|
||||
const ui = computed(() => separator({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.separator || {}) })({
|
||||
color: props.color,
|
||||
orientation: props.orientation,
|
||||
size: props.size,
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/skeleton'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSkeleton = _appConfig as AppConfig & { ui: { skeleton: Partial<typeof theme> } }
|
||||
|
||||
const skeleton = tv({ extend: tv(theme), ...(appConfigSkeleton.ui?.skeleton || {}) })
|
||||
type Skeleton = ComponentConfig<typeof theme, AppConfig, 'skeleton'>
|
||||
|
||||
export interface SkeletonProps {
|
||||
/**
|
||||
@@ -19,13 +16,20 @@ export interface SkeletonProps {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<SkeletonProps>()
|
||||
|
||||
const appConfig = useAppConfig() as Skeleton['AppConfig']
|
||||
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.skeleton || {}) }))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive :as="as" :class="skeleton({ class: props.class })">
|
||||
<Primitive :as="as" :class="ui({ class: props.class })">
|
||||
<slot />
|
||||
</Primitive>
|
||||
</template>
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { DialogRootProps, DialogRootEmits, DialogContentProps, DialogContentEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/slideover'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ButtonProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
import type { EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSlideover = _appConfig as AppConfig & { ui: { slideover: Partial<typeof theme> } }
|
||||
|
||||
const slideover = tv({ extend: tv(theme), ...(appConfigSlideover.ui?.slideover || {}) })
|
||||
|
||||
type SlideoverVariants = VariantProps<typeof slideover>
|
||||
type Slideover = ComponentConfig<typeof theme, AppConfig, 'slideover'>
|
||||
|
||||
export interface SlideoverProps extends DialogRootProps {
|
||||
title?: string
|
||||
@@ -33,7 +26,7 @@ export interface SlideoverProps extends DialogRootProps {
|
||||
* The side of the slideover.
|
||||
* @defaultValue 'right'
|
||||
*/
|
||||
side?: SlideoverVariants['side']
|
||||
side?: Slideover['variants']['side']
|
||||
/**
|
||||
* Render the slideover in a portal.
|
||||
* @defaultValue true
|
||||
@@ -57,7 +50,7 @@ export interface SlideoverProps extends DialogRootProps {
|
||||
*/
|
||||
dismissible?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof slideover.slots>
|
||||
ui?: Slideover['slots']
|
||||
}
|
||||
|
||||
export interface SlideoverEmits extends DialogRootEmits {
|
||||
@@ -70,7 +63,7 @@ export interface SlideoverSlots {
|
||||
header(props?: {}): any
|
||||
title(props?: {}): any
|
||||
description(props?: {}): any
|
||||
close(props: { ui: ReturnType<typeof slideover> }): any
|
||||
close(props: { ui: { [K in keyof Required<Slideover['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
body(props?: {}): any
|
||||
footer(props?: {}): any
|
||||
}
|
||||
@@ -82,6 +75,7 @@ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent,
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UButton from './Button.vue'
|
||||
|
||||
const props = withDefaults(defineProps<SlideoverProps>(), {
|
||||
@@ -97,7 +91,7 @@ const emits = defineEmits<SlideoverEmits>()
|
||||
const slots = defineSlots<SlideoverSlots>()
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Slideover['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
|
||||
const contentProps = toRef(() => props.content)
|
||||
@@ -118,7 +112,7 @@ const contentEvents = computed(() => {
|
||||
return events
|
||||
})
|
||||
|
||||
const ui = computed(() => slideover({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.slideover || {}) })({
|
||||
transition: props.transition,
|
||||
side: props.side
|
||||
}))
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { SliderRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/slider'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSlider = _appConfig as AppConfig & { ui: { slider: Partial<typeof theme> } }
|
||||
|
||||
const slider = tv({ extend: tv(theme), ...(appConfigSlider.ui?.slider || {}) })
|
||||
|
||||
type SliderVariants = VariantProps<typeof slider>
|
||||
type Slider = ComponentConfig<typeof theme, AppConfig, 'slider'>
|
||||
|
||||
export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'> {
|
||||
/**
|
||||
@@ -21,11 +15,11 @@ export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' |
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: SliderVariants['size']
|
||||
size?: Slider['variants']['size']
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: SliderVariants['color']
|
||||
color?: Slider['variants']['color']
|
||||
/**
|
||||
* The orientation of the slider.
|
||||
* @defaultValue 'horizontal'
|
||||
@@ -34,7 +28,7 @@ export interface SliderProps extends Pick<SliderRootProps, 'name' | 'disabled' |
|
||||
/** The value of the slider when initially rendered. Use when you do not need to control the state of the slider. */
|
||||
defaultValue?: number | number[]
|
||||
class?: any
|
||||
ui?: Partial<typeof slider.slots>
|
||||
ui?: Slider['slots']
|
||||
}
|
||||
|
||||
export interface SliderEmits {
|
||||
@@ -47,7 +41,9 @@ export interface SliderEmits {
|
||||
import { computed } from 'vue'
|
||||
import { SliderRoot, SliderRange, SliderTrack, SliderThumb, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = withDefaults(defineProps<SliderProps>(), {
|
||||
min: 0,
|
||||
@@ -59,6 +55,8 @@ const emits = defineEmits<SliderEmits>()
|
||||
|
||||
const modelValue = defineModel<number | number[]>()
|
||||
|
||||
const appConfig = useAppConfig() as Slider['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'orientation', 'min', 'max', 'step', 'minStepsBetweenThumbs', 'inverted'), emits)
|
||||
|
||||
const { id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField<SliderProps>(props)
|
||||
@@ -84,7 +82,7 @@ const sliderValue = computed({
|
||||
|
||||
const thumbsCount = computed(() => sliderValue.value?.length ?? 1)
|
||||
|
||||
const ui = computed(() => slider({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.slider || {}) })({
|
||||
disabled: disabled.value,
|
||||
size: size.value,
|
||||
color: color.value,
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { StepperRootProps, StepperRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/stepper'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { DynamicSlots } from '../types/utils'
|
||||
import type { DynamicSlots, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigStepper = _appConfig as AppConfig & { ui: { stepper: Partial<typeof theme> } }
|
||||
|
||||
const stepper = tv({ extend: tv(theme), ...(appConfigStepper.ui?.stepper || {}) })
|
||||
|
||||
type StepperVariants = VariantProps<typeof stepper>
|
||||
type Stepper = ComponentConfig<typeof theme, AppConfig, 'stepper'>
|
||||
|
||||
export interface StepperItem {
|
||||
slot?: string
|
||||
@@ -38,23 +31,23 @@ export interface StepperProps<T extends StepperItem = StepperItem> extends Pick<
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: StepperVariants['size']
|
||||
size?: Stepper['variants']['size']
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: StepperVariants['color']
|
||||
color?: Stepper['variants']['color']
|
||||
/**
|
||||
* The orientation of the stepper.
|
||||
* @defaultValue 'horizontal'
|
||||
*/
|
||||
orientation?: StepperVariants['orientation']
|
||||
orientation?: Stepper['variants']['orientation']
|
||||
/**
|
||||
* The value of the step that should be active when initially rendered. Use when you do not need to control the state of the steps.
|
||||
*/
|
||||
defaultValue?: string | number
|
||||
disabled?: boolean
|
||||
ui?: Partial<typeof stepper.slots>
|
||||
class?: any
|
||||
ui?: Stepper['slots']
|
||||
}
|
||||
|
||||
export type StepperEmits<T extends StepperItem = StepperItem> = Omit<StepperRootEmits, 'update:modelValue'> & {
|
||||
@@ -77,6 +70,8 @@ export type StepperSlots<T extends StepperItem = StepperItem> = {
|
||||
import { computed } from 'vue'
|
||||
import { StepperRoot, StepperItem, StepperTrigger, StepperIndicator, StepperSeparator, StepperTitle, StepperDescription, useForwardProps } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
const props = withDefaults(defineProps<StepperProps<T>>(), {
|
||||
@@ -88,9 +83,11 @@ const slots = defineSlots<StepperSlots<T>>()
|
||||
|
||||
const modelValue = defineModel<string | number>()
|
||||
|
||||
const appConfig = useAppConfig() as Stepper['AppConfig']
|
||||
|
||||
const rootProps = useForwardProps(reactivePick(props, 'as', 'orientation', 'linear'))
|
||||
|
||||
const ui = computed(() => stepper({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.stepper || {}) })({
|
||||
orientation: props.orientation,
|
||||
size: props.size,
|
||||
color: props.color
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { SwitchRootProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/switch'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigSwitch = _appConfig as AppConfig & { ui: { switch: Partial<typeof theme> } }
|
||||
|
||||
const switchTv = tv({ extend: tv(theme), ...(appConfigSwitch.ui?.switch || {}) })
|
||||
|
||||
type SwitchVariants = VariantProps<typeof switchTv>
|
||||
type Switch = ComponentConfig<typeof theme, AppConfig, 'switch'>
|
||||
|
||||
export interface SwitchProps extends Pick<SwitchRootProps, 'disabled' | 'id' | 'name' | 'required' | 'value' | 'defaultValue'> {
|
||||
/**
|
||||
@@ -22,11 +15,11 @@ export interface SwitchProps extends Pick<SwitchRootProps, 'disabled' | 'id' | '
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: SwitchVariants['color']
|
||||
color?: Switch['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: SwitchVariants['size']
|
||||
size?: Switch['variants']['size']
|
||||
/** When `true`, the loading icon will be displayed. */
|
||||
loading?: boolean
|
||||
/**
|
||||
@@ -48,7 +41,7 @@ export interface SwitchProps extends Pick<SwitchRootProps, 'disabled' | 'id' | '
|
||||
label?: string
|
||||
description?: string
|
||||
class?: any
|
||||
ui?: PartialString<typeof switchTv.slots>
|
||||
ui?: Switch['slots']
|
||||
}
|
||||
|
||||
export type SwitchEmits = {
|
||||
@@ -67,6 +60,7 @@ import { Primitive, SwitchRoot, SwitchThumb, useForwardProps, Label } from 'reka
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
@@ -77,13 +71,14 @@ const emits = defineEmits<SwitchEmits>()
|
||||
|
||||
const modelValue = defineModel<boolean>({ default: undefined })
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Switch['AppConfig']
|
||||
|
||||
const rootProps = useForwardProps(reactivePick(props, 'required', 'value', 'defaultValue'))
|
||||
|
||||
const { id: _id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField<SwitchProps>(props)
|
||||
const id = _id.value ?? useId()
|
||||
|
||||
const ui = computed(() => switchTv({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.switch || {}) })({
|
||||
size: size.value,
|
||||
color: color.value,
|
||||
required: props.required,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import type { RowData } from '@tanstack/table-core'
|
||||
import type {
|
||||
@@ -36,9 +35,8 @@ import type {
|
||||
VisibilityOptions,
|
||||
VisibilityState
|
||||
} from '@tanstack/vue-table'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/table'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
declare module '@tanstack/table-core' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@@ -50,11 +48,7 @@ declare module '@tanstack/table-core' {
|
||||
}
|
||||
}
|
||||
|
||||
const appConfigTable = _appConfig as AppConfig & { ui: { table: Partial<typeof theme> } }
|
||||
|
||||
const table = tv({ extend: tv(theme), ...(appConfigTable.ui?.table || {}) })
|
||||
|
||||
type TableVariants = VariantProps<typeof table>
|
||||
type Table = ComponentConfig<typeof theme, AppConfig, 'table'>
|
||||
|
||||
export type TableRow<T> = Row<T>
|
||||
export type TableData = RowData
|
||||
@@ -90,11 +84,11 @@ export interface TableProps<T extends TableData> extends TableOptions<T> {
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
loadingColor?: TableVariants['loadingColor']
|
||||
loadingColor?: Table['variants']['loadingColor']
|
||||
/**
|
||||
* @defaultValue 'carousel'
|
||||
*/
|
||||
loadingAnimation?: TableVariants['loadingAnimation']
|
||||
loadingAnimation?: Table['variants']['loadingAnimation']
|
||||
/**
|
||||
* @link [API Docs](https://tanstack.com/table/v8/docs/api/features/global-filtering#table-options)
|
||||
* @link [Guide](https://tanstack.com/table/v8/docs/guide/global-filtering)
|
||||
@@ -157,7 +151,7 @@ export interface TableProps<T extends TableData> extends TableOptions<T> {
|
||||
facetedOptions?: FacetedOptions<T>
|
||||
onSelect?: (row: TableRow<T>, e?: Event) => void
|
||||
class?: any
|
||||
ui?: Partial<typeof table.slots>
|
||||
ui?: Table['slots']
|
||||
}
|
||||
|
||||
type DynamicHeaderSlots<T, K = keyof T> = Record<string, (props: HeaderContext<T, unknown>) => any> & Record<`${K extends string ? K : never}-header`, (props: HeaderContext<T, unknown>) => any>
|
||||
@@ -178,17 +172,20 @@ import { Primitive } from 'reka-ui'
|
||||
import { upperFirst } from 'scule'
|
||||
import { FlexRender, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getExpandedRowModel, useVueTable } from '@tanstack/vue-table'
|
||||
import { reactiveOmit } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
const props = defineProps<TableProps<T>>()
|
||||
const slots = defineSlots<TableSlots<T>>()
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig() as Table['AppConfig']
|
||||
|
||||
const data = computed(() => props.data ?? [])
|
||||
const columns = computed<TableColumn<T>[]>(() => props.columns ?? Object.keys(data.value[0] ?? {}).map((accessorKey: string) => ({ accessorKey, header: upperFirst(accessorKey) })))
|
||||
|
||||
const ui = computed(() => table({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.table || {}) })({
|
||||
sticky: props.sticky,
|
||||
loading: props.loading,
|
||||
loadingColor: props.loadingColor,
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { TabsRootProps, TabsRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/tabs'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { DynamicSlots, PartialString } from '../types/utils'
|
||||
import type { DynamicSlots, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigTabs = _appConfig as AppConfig & { ui: { tabs: Partial<typeof theme> } }
|
||||
|
||||
const tabs = tv({ extend: tv(theme), ...(appConfigTabs.ui?.tabs || {}) })
|
||||
type Tabs = ComponentConfig<typeof theme, AppConfig, 'tabs'>
|
||||
|
||||
export interface TabsItem {
|
||||
label?: string
|
||||
@@ -28,8 +23,6 @@ export interface TabsItem {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
type TabsVariants = VariantProps<typeof tabs>
|
||||
|
||||
export interface TabsProps<T extends TabsItem = TabsItem> extends Pick<TabsRootProps<string | number>, 'defaultValue' | 'modelValue' | 'activationMode' | 'unmountOnHide'> {
|
||||
/**
|
||||
* The element or component this component should render as.
|
||||
@@ -40,15 +33,15 @@ export interface TabsProps<T extends TabsItem = TabsItem> extends Pick<TabsRootP
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: TabsVariants['color']
|
||||
color?: Tabs['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'pill'
|
||||
*/
|
||||
variant?: TabsVariants['variant']
|
||||
variant?: Tabs['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: TabsVariants['size']
|
||||
size?: Tabs['variants']['size']
|
||||
/**
|
||||
* The orientation of the tabs.
|
||||
* @defaultValue 'horizontal'
|
||||
@@ -65,7 +58,7 @@ export interface TabsProps<T extends TabsItem = TabsItem> extends Pick<TabsRootP
|
||||
*/
|
||||
labelKey?: string
|
||||
class?: any
|
||||
ui?: PartialString<typeof tabs.slots>
|
||||
ui?: Tabs['slots']
|
||||
}
|
||||
|
||||
export interface TabsEmits extends TabsRootEmits<string | number> {}
|
||||
@@ -87,7 +80,9 @@ export type TabsSlots<T extends TabsItem = TabsItem> = {
|
||||
import { computed } from 'vue'
|
||||
import { TabsRoot, TabsList, TabsIndicator, TabsTrigger, TabsContent, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
|
||||
@@ -101,9 +96,11 @@ const props = withDefaults(defineProps<TabsProps<T>>(), {
|
||||
const emits = defineEmits<TabsEmits>()
|
||||
const slots = defineSlots<TabsSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig() as Tabs['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'orientation', 'activationMode', 'unmountOnHide'), emits)
|
||||
|
||||
const ui = computed(() => tabs({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tabs || {}) })({
|
||||
color: props.color,
|
||||
variant: props.variant,
|
||||
size: props.size,
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/textarea'
|
||||
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps } from '../types'
|
||||
import type { PartialString } from '../types/utils'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigTextarea = _appConfig as AppConfig & { ui: { textarea: Partial<typeof theme> } }
|
||||
|
||||
const textarea = tv({ extend: tv(theme), ...(appConfigTextarea.ui?.textarea || {}) })
|
||||
|
||||
type TextareaVariants = VariantProps<typeof textarea>
|
||||
type Textarea = ComponentConfig<typeof theme, AppConfig, 'textarea'>
|
||||
|
||||
export interface TextareaProps extends UseComponentIconsProps {
|
||||
/**
|
||||
@@ -27,15 +20,15 @@ export interface TextareaProps extends UseComponentIconsProps {
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: TextareaVariants['color']
|
||||
color?: Textarea['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'outline'
|
||||
*/
|
||||
variant?: TextareaVariants['variant']
|
||||
variant?: Textarea['variants']['variant']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: TextareaVariants['size']
|
||||
size?: Textarea['variants']['size']
|
||||
required?: boolean
|
||||
autofocus?: boolean
|
||||
autofocusDelay?: number
|
||||
@@ -47,7 +40,7 @@ export interface TextareaProps extends UseComponentIconsProps {
|
||||
maxrows?: number
|
||||
/** Highlight the ring color like a focus state. */
|
||||
highlight?: boolean
|
||||
ui?: PartialString<typeof textarea.slots>
|
||||
ui?: Textarea['slots']
|
||||
}
|
||||
|
||||
export interface TextareaEmits {
|
||||
@@ -66,9 +59,11 @@ export interface TextareaSlots {
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, nextTick, watch } from 'vue'
|
||||
import { Primitive } from 'reka-ui'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useComponentIcons } from '../composables/useComponentIcons'
|
||||
import { useFormField } from '../composables/useFormField'
|
||||
import { looseToNumber } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
@@ -83,10 +78,11 @@ const emits = defineEmits<TextareaEmits>()
|
||||
|
||||
const [modelValue, modelModifiers] = defineModel<string | number | null>()
|
||||
|
||||
const appConfig = useAppConfig() as Textarea['AppConfig']
|
||||
const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, size, color, id, name, highlight, disabled, ariaAttrs } = useFormField<TextareaProps>(props, { deferInputValidation: true })
|
||||
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
|
||||
|
||||
const ui = computed(() => textarea({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.textarea || {}) })({
|
||||
color: color.value,
|
||||
variant: props.variant,
|
||||
size: size?.value,
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ToastRootProps, ToastRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/toast'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { AvatarProps, ButtonProps } from '../types'
|
||||
import type { StringOrVNode } from '../types/utils'
|
||||
import type { StringOrVNode, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigToast = _appConfig as AppConfig & { ui: { toast: Partial<typeof theme> } }
|
||||
|
||||
const toast = tv({ extend: tv(theme), ...(appConfigToast.ui?.toast || {}) })
|
||||
|
||||
type ToastVariants = VariantProps<typeof toast>
|
||||
type Toast = ComponentConfig<typeof theme, AppConfig, 'toast'>
|
||||
|
||||
export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open' | 'type' | 'duration'> {
|
||||
/**
|
||||
@@ -30,12 +23,12 @@ export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open'
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: ToastVariants['color']
|
||||
color?: Toast['variants']['color']
|
||||
/**
|
||||
* The orientation between the content and the actions.
|
||||
* @defaultValue 'vertical'
|
||||
*/
|
||||
orientation?: ToastVariants['orientation']
|
||||
orientation?: Toast['variants']['orientation']
|
||||
/**
|
||||
* Display a list of actions:
|
||||
* - under the title and description when orientation is `vertical`
|
||||
@@ -56,7 +49,7 @@ export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open'
|
||||
*/
|
||||
closeIcon?: string
|
||||
class?: any
|
||||
ui?: Partial<typeof toast.slots>
|
||||
ui?: Toast['slots']
|
||||
}
|
||||
|
||||
export interface ToastEmits extends ToastRootEmits {}
|
||||
@@ -66,7 +59,7 @@ export interface ToastSlots {
|
||||
title(props?: {}): any
|
||||
description(props?: {}): any
|
||||
actions(props?: {}): any
|
||||
close(props: { ui: ReturnType<typeof toast> }): any
|
||||
close(props: { ui: { [K in keyof Required<Toast['slots']>]: (props?: Record<string, any>) => string } }): any
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -76,6 +69,7 @@ import { ToastRoot, ToastTitle, ToastDescription, ToastAction, ToastClose, useFo
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useLocale } from '../composables/useLocale'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
import UAvatar from './Avatar.vue'
|
||||
import UButton from './Button.vue'
|
||||
@@ -88,11 +82,11 @@ const emits = defineEmits<ToastEmits>()
|
||||
const slots = defineSlots<ToastSlots>()
|
||||
|
||||
const { t } = useLocale()
|
||||
const appConfig = useAppConfig()
|
||||
const appConfig = useAppConfig() as Toast['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'duration', 'type'), emits)
|
||||
|
||||
const ui = computed(() => toast({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.toast || {}) })({
|
||||
color: props.color,
|
||||
orientation: props.orientation,
|
||||
title: !!props.title || !!slots.title
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { ToastProviderProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/toaster'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigToaster = _appConfig as AppConfig & { ui: { toaster: Partial<typeof theme> } }
|
||||
|
||||
const toaster = tv({ extend: tv(theme), ...(appConfigToaster.ui?.toaster || {}) })
|
||||
|
||||
type ToasterVariants = VariantProps<typeof toaster>
|
||||
type Toaster = ComponentConfig<typeof theme, AppConfig, 'toaster'>
|
||||
|
||||
export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'> {
|
||||
/**
|
||||
* The position on the screen to display the toasts.
|
||||
* @defaultValue 'bottom-right'
|
||||
*/
|
||||
position?: ToasterVariants['position']
|
||||
position?: Toaster['variants']['position']
|
||||
/**
|
||||
* Expand the toasts to show multiple toasts at once.
|
||||
* @defaultValue true
|
||||
@@ -29,7 +23,7 @@ export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'>
|
||||
*/
|
||||
portal?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof toaster.slots>
|
||||
ui?: Toaster['slots']
|
||||
}
|
||||
|
||||
export interface ToasterSlots {
|
||||
@@ -45,8 +39,10 @@ export default {
|
||||
import { ref, computed } from 'vue'
|
||||
import { ToastProvider, ToastViewport, ToastPortal, useForwardProps } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { useToast } from '../composables/useToast'
|
||||
import { omit } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UToast from './Toast.vue'
|
||||
|
||||
const props = withDefaults(defineProps<ToasterProps>(), {
|
||||
@@ -56,9 +52,10 @@ const props = withDefaults(defineProps<ToasterProps>(), {
|
||||
})
|
||||
defineSlots<ToasterSlots>()
|
||||
|
||||
const providerProps = useForwardProps(reactivePick(props, 'duration', 'label', 'swipeThreshold'))
|
||||
|
||||
const { toasts, remove } = useToast()
|
||||
const appConfig = useAppConfig() as Toaster['AppConfig']
|
||||
|
||||
const providerProps = useForwardProps(reactivePick(props, 'duration', 'label', 'swipeThreshold'))
|
||||
|
||||
const swipeDirection = computed(() => {
|
||||
switch (props.position) {
|
||||
@@ -76,7 +73,7 @@ const swipeDirection = computed(() => {
|
||||
return 'right'
|
||||
})
|
||||
|
||||
const ui = computed(() => toaster({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.toaster || {}) })({
|
||||
position: props.position,
|
||||
swipeDirection: swipeDirection.value
|
||||
}))
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { TooltipRootProps, TooltipRootEmits, TooltipContentProps, TooltipContentEmits, TooltipArrowProps } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/tooltip'
|
||||
import { tv } from '../utils/tv'
|
||||
import type { KbdProps } from '../types'
|
||||
import type { EmitsToProps } from '../types/utils'
|
||||
import type { EmitsToProps, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfigTooltip = _appConfig as AppConfig & { ui: { tooltip: Partial<typeof theme> } }
|
||||
|
||||
const tooltip = tv({ extend: tv(theme), ...(appConfigTooltip.ui?.tooltip || {}) })
|
||||
type Tooltip = ComponentConfig<typeof theme, AppConfig, 'tooltip'>
|
||||
|
||||
export interface TooltipProps extends TooltipRootProps {
|
||||
/** The text content of the tooltip. */
|
||||
@@ -32,7 +28,7 @@ export interface TooltipProps extends TooltipRootProps {
|
||||
*/
|
||||
portal?: boolean
|
||||
class?: any
|
||||
ui?: Partial<typeof tooltip.slots>
|
||||
ui?: Tooltip['slots']
|
||||
}
|
||||
|
||||
export interface TooltipEmits extends TooltipRootEmits {}
|
||||
@@ -48,6 +44,8 @@ import { computed, toRef } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { TooltipRoot, TooltipTrigger, TooltipPortal, TooltipContent, TooltipArrow, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { tv } from '../utils/tv'
|
||||
import UKbd from './Kbd.vue'
|
||||
|
||||
const props = withDefaults(defineProps<TooltipProps>(), {
|
||||
@@ -56,12 +54,14 @@ const props = withDefaults(defineProps<TooltipProps>(), {
|
||||
const emits = defineEmits<TooltipEmits>()
|
||||
const slots = defineSlots<TooltipSlots>()
|
||||
|
||||
const appConfig = useAppConfig() as Tooltip['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'delayDuration', 'disableHoverableContent', 'disableClosingTrigger', 'disabled', 'ignoreNonKeyboardFocus'), emits)
|
||||
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as TooltipContentProps)
|
||||
const arrowProps = toRef(() => props.arrow as TooltipArrowProps)
|
||||
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const ui = computed(() => tooltip({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tooltip || {}) })({
|
||||
side: contentProps.value.side
|
||||
}))
|
||||
</script>
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
<!-- eslint-disable vue/block-tag-newline -->
|
||||
<script lang="ts">
|
||||
import type { VariantProps } from 'tailwind-variants'
|
||||
import type { TreeRootProps, TreeRootEmits } from 'reka-ui'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/tree'
|
||||
import { tv } from '../utils/tv'
|
||||
import type {
|
||||
DynamicSlots,
|
||||
GetItemKeys,
|
||||
GetModelValue,
|
||||
GetModelValueEmits,
|
||||
NestedItem,
|
||||
PartialString
|
||||
} from '../types/utils'
|
||||
import type { DynamicSlots, GetItemKeys, GetModelValue, GetModelValueEmits, NestedItem, ComponentConfig } from '../types/utils'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { tree: Partial<typeof theme> } }
|
||||
|
||||
const tree = tv({ extend: tv(theme), ...(appConfig.ui?.tree || {}) })
|
||||
|
||||
type TreeVariants = VariantProps<typeof tree>
|
||||
type Tree = ComponentConfig<typeof theme, AppConfig, 'tree'>
|
||||
|
||||
export type TreeItem = {
|
||||
/**
|
||||
@@ -50,11 +36,11 @@ export interface TreeProps<T extends TreeItem[] = TreeItem[], VK extends GetItem
|
||||
/**
|
||||
* @defaultValue 'primary'
|
||||
*/
|
||||
color?: TreeVariants['color']
|
||||
color?: Tree['variants']['color']
|
||||
/**
|
||||
* @defaultValue 'md'
|
||||
*/
|
||||
size?: TreeVariants['size']
|
||||
size?: Tree['variants']['size']
|
||||
/**
|
||||
* The key used to get the value from the item.
|
||||
* @defaultValue 'value'
|
||||
@@ -91,7 +77,7 @@ export interface TreeProps<T extends TreeItem[] = TreeItem[], VK extends GetItem
|
||||
/** Whether multiple options can be selected or not. */
|
||||
multiple?: M & boolean
|
||||
class?: any
|
||||
ui?: PartialString<typeof tree.slots>
|
||||
ui?: Tree['slots']
|
||||
}
|
||||
|
||||
export type TreeEmits<A extends TreeItem[], VK extends GetItemKeys<A> | undefined, M extends boolean> = Omit<TreeRootEmits, 'update:modelValue'> & GetModelValueEmits<A, VK, M>
|
||||
@@ -114,7 +100,9 @@ export type TreeSlots<
|
||||
import { computed } from 'vue'
|
||||
import { TreeRoot, TreeItem, useForwardPropsEmits } from 'reka-ui'
|
||||
import { reactivePick, createReusableTemplate } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
import { get } from '../utils'
|
||||
import { tv } from '../utils/tv'
|
||||
import UIcon from './Icon.vue'
|
||||
|
||||
const props = withDefaults(defineProps<TreeProps<T, VK, M>>(), {
|
||||
@@ -124,11 +112,13 @@ const props = withDefaults(defineProps<TreeProps<T, VK, M>>(), {
|
||||
const emits = defineEmits<TreeEmits<T, VK, M>>()
|
||||
const slots = defineSlots<TreeSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig() as Tree['AppConfig']
|
||||
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'items', 'multiple', 'expanded', 'disabled', 'propagateSelect'), emits)
|
||||
|
||||
const [DefineTreeTemplate, ReuseTreeTemplate] = createReusableTemplate<{ items?: TreeItem[], level: number }, TreeSlots<T>>()
|
||||
|
||||
const ui = computed(() => tree({
|
||||
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.tree || {}) })({
|
||||
color: props.color,
|
||||
size: props.size
|
||||
}))
|
||||
|
||||
@@ -33,10 +33,6 @@ export type GetObjectField<MaybeObject, Key extends string> = MaybeObject extend
|
||||
? MaybeObject[Key]
|
||||
: never
|
||||
|
||||
export type PartialString<T> = {
|
||||
[K in keyof T]?: string
|
||||
}
|
||||
|
||||
export type AcceptableValue = Exclude<_AcceptableValue, Record<string, any>>
|
||||
export type ArrayOrNested<T> = T[] | T[][]
|
||||
export type NestedItem<T> = T extends Array<infer I> ? NestedItem<I> : T
|
||||
@@ -91,3 +87,49 @@ export type EmitsToProps<T> = {
|
||||
? (...args: Args) => void
|
||||
: never
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility type to flatten intersection types for better IDE hover information.
|
||||
* @template T The type to flatten.
|
||||
*/
|
||||
type Id<T> = {} & { [P in keyof T]: T[P] }
|
||||
|
||||
type ComponentVariants<T extends { variants?: Record<string, Record<string, any>> }> = {
|
||||
[K in keyof T['variants']]: keyof T['variants'][K]
|
||||
}
|
||||
|
||||
type ComponentSlots<T extends { slots?: Record<string, any> }> = Id<{
|
||||
[K in keyof T['slots']]?: string
|
||||
}>
|
||||
|
||||
type GetComponentAppConfig<A, U extends string, K extends string> =
|
||||
A extends Record<U, Record<K, any>> ? A[U][K] : {}
|
||||
|
||||
type ComponentAppConfig<
|
||||
T,
|
||||
A extends Record<string, any>,
|
||||
K extends string,
|
||||
U extends string = 'ui' | 'uiPro' | 'uiPro.prose'
|
||||
> = A & (
|
||||
U extends 'uiPro.prose'
|
||||
? { uiPro?: { prose?: { [k in K]?: Partial<T> } } }
|
||||
: { [key in Exclude<U, 'uiPro.prose'>]?: { [k in K]?: Partial<T> } }
|
||||
)
|
||||
|
||||
/**
|
||||
* Defines the configuration shape expected for a component.
|
||||
* @template T The component's theme imported from `#build/ui/*`.
|
||||
* @template A The base AppConfig type from `@nuxt/schema`.
|
||||
* @template K The key identifying the component (e.g., 'badge').
|
||||
* @template U The top-level key in AppConfig ('ui' or 'uiPro').
|
||||
*/
|
||||
export type ComponentConfig<
|
||||
T extends Record<string, any>,
|
||||
A extends Record<string, any>,
|
||||
K extends string,
|
||||
U extends 'ui' | 'uiPro' | 'uiPro.prose' = 'ui'
|
||||
> = {
|
||||
AppConfig: ComponentAppConfig<T, A, K, U>
|
||||
variants: ComponentVariants<T & GetComponentAppConfig<A, U, K>>
|
||||
slots: ComponentSlots<T>
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createTV, type defaultConfig } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
const appConfigTv = _appConfig as AppConfig & { ui: { tv: typeof defaultConfig } }
|
||||
const appConfigTv = appConfig as AppConfig & { ui: { tv: typeof defaultConfig } }
|
||||
|
||||
export const tv = /* @__PURE__ */ createTV(appConfigTv.ui?.tv)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { ButtonHTMLAttributes } from 'vue'
|
||||
import { tv } from 'tailwind-variants'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
|
||||
import theme from '#build/ui/link'
|
||||
import type { ComponentConfig } from '../../types/utils'
|
||||
|
||||
type Link = ComponentConfig<typeof theme, AppConfig, 'link'>
|
||||
|
||||
interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
||||
/**
|
||||
@@ -52,10 +53,6 @@ interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
||||
noPrefetch?: boolean
|
||||
}
|
||||
|
||||
const appConfigLink = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
|
||||
|
||||
const link = tv({ extend: tv(theme), ...(appConfigLink.ui?.link || {}) })
|
||||
|
||||
export interface LinkProps extends NuxtLinkProps {
|
||||
/**
|
||||
* The element or component this component should render as when not a link.
|
||||
@@ -91,12 +88,14 @@ export interface LinkSlots {
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, getCurrentInstance } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { isEqual, diff } from 'ohash/utils'
|
||||
import { useForwardProps } from 'reka-ui'
|
||||
import { reactiveOmit } from '@vueuse/core'
|
||||
import { hasProtocol } from 'ufo'
|
||||
import { useRoute } from '#imports'
|
||||
import { useRoute, useAppConfig } from '#imports'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { tv } from '../../utils/tv'
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
@@ -126,16 +125,20 @@ const route = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig() as Link['AppConfig']
|
||||
|
||||
const routerLinkProps = useForwardProps(reactiveOmit(props, 'as', 'type', 'disabled', 'active', 'exact', 'exactQuery', 'exactHash', 'activeClass', 'inactiveClass', 'to', 'raw', 'class'))
|
||||
|
||||
const ui = computed(() => tv({
|
||||
extend: link,
|
||||
variants: {
|
||||
active: {
|
||||
true: props.activeClass,
|
||||
false: props.inactiveClass
|
||||
extend: tv(theme),
|
||||
...defu({
|
||||
variants: {
|
||||
active: {
|
||||
true: props.activeClass,
|
||||
false: props.inactiveClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}, appConfig.ui?.link || {})
|
||||
}))
|
||||
|
||||
function isPartiallyEqual(item1: any, item2: any) {
|
||||
|
||||
Reference in New Issue
Block a user