205 lines
5 KiB
TypeScript
205 lines
5 KiB
TypeScript
import type { App } from 'vue'
|
|
import {
|
|
Select as PrimeSelect,
|
|
Dialog as PrimeDialog,
|
|
} from 'primevue'
|
|
import { ThemeLibrary, type Themeable, ThemeEngine, type LibComponent, type Key } from '../engine'
|
|
import {
|
|
NychLoadingIcon,
|
|
Button,
|
|
buttonVariants,
|
|
Input,
|
|
Textarea,
|
|
Switch,
|
|
Badge,
|
|
badgeVariants,
|
|
Checkbox,
|
|
CheckboxGroup,
|
|
RadioGroup,
|
|
RadioGroupItem,
|
|
Card,
|
|
CardHeader,
|
|
CardTitle,
|
|
CardDescription,
|
|
CardContent,
|
|
CardFooter,
|
|
CardAction,
|
|
Alert,
|
|
AlertTitle,
|
|
AlertDescription,
|
|
AlertAction,
|
|
alertVariants,
|
|
} from '../components'
|
|
|
|
export {
|
|
Button,
|
|
buttonVariants,
|
|
Input,
|
|
Textarea,
|
|
Switch,
|
|
Badge,
|
|
badgeVariants,
|
|
Checkbox,
|
|
CheckboxGroup,
|
|
RadioGroup,
|
|
RadioGroupItem,
|
|
Card,
|
|
CardHeader,
|
|
CardTitle,
|
|
CardDescription,
|
|
CardContent,
|
|
CardFooter,
|
|
CardAction,
|
|
Alert,
|
|
AlertTitle,
|
|
AlertDescription,
|
|
AlertAction,
|
|
alertVariants,
|
|
}
|
|
|
|
/**
|
|
* Build a Themeable that themes a PrimeVue component through its passthrough (`pt`) API.
|
|
*
|
|
* The engine injects the base class (`nych-<base>`) onto `pt.root`. This factory layers a
|
|
* `nych-<base>-<section>` class onto every additional section so multi-part components
|
|
* (Checkbox box, Select overlay, Card body, …) can be fully styled in unstyled mode, where
|
|
* PrimeVue emits no classes of its own.
|
|
*/
|
|
const ptThemeable = <T extends LibComponent>(
|
|
component: T,
|
|
base: string,
|
|
sections: string[] = [],
|
|
): Themeable<T> => ({
|
|
component,
|
|
unstyled: true as Themeable<T>['unstyled'],
|
|
classes: [`nych-${base}`],
|
|
injectionKeys: { class: 'pt' as Key<T> },
|
|
propMutator: ((props: Record<string, unknown>) => {
|
|
const pt = (props.pt as Record<string, { class?: string }>) ?? {}
|
|
|
|
for (const section of sections) {
|
|
const existing = pt[section]?.class
|
|
pt[section] = {
|
|
...(pt[section] ?? {}),
|
|
class: [existing, `nych-${base}-${section}`].filter(Boolean).join(' '),
|
|
}
|
|
}
|
|
|
|
props.pt = pt
|
|
|
|
return props
|
|
}) as Themeable<T>['propMutator'],
|
|
})
|
|
|
|
const loadingIconThemeable: Themeable<typeof NychLoadingIcon> = {
|
|
component: NychLoadingIcon,
|
|
unstyled: false,
|
|
}
|
|
|
|
const nychthemeron: ThemeLibrary = {
|
|
components: {
|
|
LoadingIcon: loadingIconThemeable,
|
|
Select: ptThemeable(PrimeSelect, 'select', [
|
|
'label',
|
|
'dropdown',
|
|
'dropdownIcon',
|
|
'overlay',
|
|
'header',
|
|
'listContainer',
|
|
'list',
|
|
'option',
|
|
'optionLabel',
|
|
'emptyMessage',
|
|
]),
|
|
Dialog: ptThemeable(PrimeDialog, 'dialog', [
|
|
'mask',
|
|
'header',
|
|
'title',
|
|
'headerActions',
|
|
'content',
|
|
'footer',
|
|
]),
|
|
},
|
|
}
|
|
|
|
const _engine = new ThemeEngine(nychthemeron)
|
|
|
|
export const LoadingIcon = _engine.getComponent<typeof NychLoadingIcon>('LoadingIcon')
|
|
export const Select: typeof PrimeSelect = _engine.getComponent<typeof PrimeSelect>('Select')
|
|
export const Dialog: typeof PrimeDialog = _engine.getComponent<typeof PrimeDialog>('Dialog')
|
|
|
|
export const createNychthemeron = (): {
|
|
Button: typeof Button
|
|
LoadingIcon: typeof NychLoadingIcon
|
|
Input: typeof Input
|
|
Textarea: typeof Textarea
|
|
Checkbox: typeof Checkbox
|
|
CheckboxGroup: typeof CheckboxGroup
|
|
RadioGroup: typeof RadioGroup
|
|
RadioGroupItem: typeof RadioGroupItem
|
|
Switch: typeof Switch
|
|
Select: typeof PrimeSelect
|
|
Card: typeof Card
|
|
CardHeader: typeof CardHeader
|
|
CardTitle: typeof CardTitle
|
|
CardDescription: typeof CardDescription
|
|
CardContent: typeof CardContent
|
|
CardFooter: typeof CardFooter
|
|
CardAction: typeof CardAction
|
|
Dialog: typeof PrimeDialog
|
|
Alert: typeof Alert
|
|
AlertTitle: typeof AlertTitle
|
|
AlertDescription: typeof AlertDescription
|
|
AlertAction: typeof AlertAction
|
|
Badge: typeof Badge
|
|
install: (app: App) => void
|
|
} => ({
|
|
Button,
|
|
LoadingIcon,
|
|
Input,
|
|
Textarea,
|
|
Checkbox,
|
|
CheckboxGroup,
|
|
RadioGroup,
|
|
RadioGroupItem,
|
|
Switch,
|
|
Select,
|
|
Card,
|
|
CardHeader,
|
|
CardTitle,
|
|
CardDescription,
|
|
CardContent,
|
|
CardFooter,
|
|
CardAction,
|
|
Dialog,
|
|
Alert,
|
|
AlertTitle,
|
|
AlertDescription,
|
|
AlertAction,
|
|
Badge,
|
|
install(app: App) {
|
|
app.component('NychButton', Button)
|
|
app.component('NychLoadingIcon', LoadingIcon)
|
|
app.component('NychInput', Input)
|
|
app.component('NychTextarea', Textarea)
|
|
app.component('NychCheckbox', Checkbox)
|
|
app.component('NychCheckboxGroup', CheckboxGroup)
|
|
app.component('NychRadioGroup', RadioGroup)
|
|
app.component('NychRadioGroupItem', RadioGroupItem)
|
|
app.component('NychSwitch', Switch)
|
|
app.component('NychSelect', Select)
|
|
app.component('NychCard', Card)
|
|
app.component('NychCardHeader', CardHeader)
|
|
app.component('NychCardTitle', CardTitle)
|
|
app.component('NychCardDescription', CardDescription)
|
|
app.component('NychCardContent', CardContent)
|
|
app.component('NychCardFooter', CardFooter)
|
|
app.component('NychCardAction', CardAction)
|
|
app.component('NychDialog', Dialog)
|
|
app.component('NychAlert', Alert)
|
|
app.component('NychAlertTitle', AlertTitle)
|
|
app.component('NychAlertDescription', AlertDescription)
|
|
app.component('NychAlertAction', AlertAction)
|
|
app.component('NychBadge', Badge)
|
|
},
|
|
})
|