|
| 1 | +/* eslint-disable @typescript-eslint/no-explicit-any */ |
| 2 | +import type { defaultConfig, ClassValue, TVVariants, TVCompoundVariants, TVDefaultVariants } from 'tailwind-variants' |
| 3 | +import { createTV } from 'tailwind-variants' |
| 4 | +import type { AppConfig } from '@nuxt/schema' |
| 5 | +import appConfig from '#build/app.config' |
| 6 | + |
| 7 | +/** |
| 8 | + * Defines the AppConfig object based on the tailwind-variants configuration. |
| 9 | + */ |
| 10 | +export type TVConfig<T extends Record<string, any>> = { |
| 11 | + [P in keyof T]?: { |
| 12 | + [K in keyof T[P]as K extends 'base' | 'slots' | 'variants' | 'compoundVariants' | 'defaultVariants' ? K : never]?: K extends 'base' ? ClassValue |
| 13 | + : K extends 'slots' ? { |
| 14 | + [S in keyof T[P]['slots']]?: ClassValue |
| 15 | + } |
| 16 | + : K extends 'variants' ? TVVariants<T[P]['slots'], ClassValue, T[P]['variants']> |
| 17 | + : K extends 'compoundVariants' ? TVCompoundVariants<T[P]['variants'], T[P]['slots'], ClassValue, object, undefined> |
| 18 | + : K extends 'defaultVariants' ? TVDefaultVariants<T[P]['variants'], T[P]['slots'], object, undefined> |
| 19 | + : never |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +/** |
| 24 | + * Utility type to flatten intersection types for better IDE hover information. |
| 25 | + * @template T The type to flatten. |
| 26 | + */ |
| 27 | +type Id<T> = {} & { [P in keyof T]: T[P] } |
| 28 | + |
| 29 | +type ComponentVariants<T extends { variants?: Record<string, Record<string, any>> }> = { |
| 30 | + [K in keyof T['variants']]: keyof T['variants'][K] |
| 31 | +} |
| 32 | + |
| 33 | +type ComponentSlots<T extends { slots?: Record<string, any> }> = Id<{ |
| 34 | + [K in keyof T['slots']]?: ClassValue |
| 35 | +}> |
| 36 | + |
| 37 | +type GetComponentAppConfig<A, U extends string, K extends string> |
| 38 | + = A extends Record<U, Record<K, any>> ? A[U][K] : object |
| 39 | + |
| 40 | +type ComponentAppConfig< |
| 41 | + T, |
| 42 | + A extends Record<string, any>, |
| 43 | + K extends string, |
| 44 | + U extends string = 'ui' | 'ui.prose' |
| 45 | +> = A & ( |
| 46 | + U extends 'ui.prose' |
| 47 | + ? { ui?: { prose?: { [k in K]?: Partial<T> } } } |
| 48 | + : { [key in Exclude<U, 'ui.prose'>]?: { [k in K]?: Partial<T> } } |
| 49 | +) |
| 50 | + |
| 51 | +/** |
| 52 | + * Defines the configuration shape expected for a component. |
| 53 | + * @template T The component's theme imported from `#build/ui/*`. |
| 54 | + * @template A The base AppConfig type from `@nuxt/schema`. |
| 55 | + * @template K The key identifying the component (e.g., 'badge'). |
| 56 | + * @template U The top-level key in AppConfig ('ui' or 'uiPro'). |
| 57 | + */ |
| 58 | +export type ComponentConfig< |
| 59 | + T extends Record<string, any>, |
| 60 | + A extends Record<string, any>, |
| 61 | + K extends string, |
| 62 | + U extends 'ui' | 'ui.prose' = 'ui' |
| 63 | +> = { |
| 64 | + AppConfig: ComponentAppConfig<T, A, K, U> |
| 65 | + variants: ComponentVariants<T & GetComponentAppConfig<A, U, K>> |
| 66 | + slots: ComponentSlots<T> |
| 67 | +} |
| 68 | + |
| 69 | +// ------------------------------- |
| 70 | + |
| 71 | +const appConfigTv = appConfig as AppConfig & { ui: { tv: typeof defaultConfig } } |
| 72 | + |
| 73 | +export const tv = /* @__PURE__ */ createTV(appConfigTv.ui?.tv) |
0 commit comments