83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
import { h, type FunctionComponent } from 'preact'
|
|
import cn from 'classnames'
|
|
|
|
type Styles<C extends string, D extends string, S extends string> = {
|
|
base?: string
|
|
touched?: string
|
|
element?: string
|
|
label?: string
|
|
icon?: string
|
|
|
|
autoHeight?: string
|
|
fullWidth?: string
|
|
invert?: string
|
|
} & Record<C, string> &
|
|
Record<D, string> &
|
|
Record<S, string>
|
|
|
|
type Options<C extends string, D extends string, I extends string, S extends string> = {
|
|
defaults: Pick<Props<C, D, I, S>, 'autoHeight' | 'color' | 'design' | 'fullWidth' | 'icon' | 'invert' | 'size'>
|
|
icons: Record<I, string>
|
|
styles: Styles<C, D, S>
|
|
}
|
|
|
|
type Props<C extends string, D extends string, I extends string, S extends string> = {
|
|
autoHeight?: boolean
|
|
className?: string
|
|
color?: C
|
|
design?: D
|
|
href?: string
|
|
fullWidth?: boolean
|
|
icon?: I
|
|
iconSize?: string
|
|
invert?: boolean
|
|
size?: S
|
|
tabIndex?: number
|
|
title?: string
|
|
}
|
|
|
|
export default function linkButtonFactory<
|
|
C extends string = never,
|
|
D extends string = never,
|
|
I extends string = never,
|
|
S extends string = never,
|
|
>({ defaults, icons, styles }: Options<C, D, I, S>) {
|
|
const LinkButton: FunctionComponent<Props<C, D, I, S>> = ({
|
|
autoHeight = defaults?.autoHeight,
|
|
children,
|
|
className,
|
|
color = defaults?.color,
|
|
design = defaults?.design,
|
|
href,
|
|
fullWidth = defaults?.fullWidth,
|
|
icon = defaults?.icon,
|
|
iconSize,
|
|
invert = defaults?.invert,
|
|
size = defaults?.size,
|
|
tabIndex,
|
|
title,
|
|
}) => (
|
|
<a
|
|
className={cn(
|
|
styles.base,
|
|
design && styles[design],
|
|
size && styles[size],
|
|
color && styles[color],
|
|
autoHeight && styles.autoHeight,
|
|
fullWidth && styles.fullWidth,
|
|
invert && styles.invert,
|
|
className,
|
|
)}
|
|
style={iconSize && { '--icon-size': iconSize }}
|
|
href={href}
|
|
tabIndex={tabIndex}
|
|
title={title}
|
|
>
|
|
{icon && <i className={styles.icon} style={{ maskImage: `url(${icons[icon] || icon})` }} />}
|
|
{children && <span>{children}</span>}
|
|
</a>
|
|
)
|
|
|
|
return LinkButton
|
|
}
|