Last active
July 17, 2022 12:19
-
-
Save bbg/5224d4e10034f3e7eb1f3be9f788cd32 to your computer and use it in GitHub Desktop.
generic-component-styled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference types="styled-jsx" /> | |
import clsx from 'clsx'; | |
import React, { Fragment } from 'react'; | |
type Property = { | |
display: | |
| 'block' | |
| 'inline-block' | |
| 'inline' | |
| 'flex' | |
| 'inline-flex' | |
| 'table' | |
| 'inline-table' | |
| 'table-caption' | |
| 'table-cell' | |
| 'table-column' | |
| 'table-column-group' | |
| 'table-footer-group' | |
| 'table-header-group' | |
| 'table-row-group' | |
| 'table-row' | |
| 'flow-root' | |
| 'grid' | |
| 'inline-grid' | |
| 'contents' | |
| 'list-item' | |
| 'none'; | |
flexDirection: 'row' | 'column' | 'row-reverse' | 'column-reverse' | string; | |
flexWrap: 'wrap' | 'nowrap' | 'wrap-reverse' | string; | |
flexBasis: number | string; | |
flexGrow: '1' | '0' | string; | |
flexShrink: '1' | '0' | string; | |
justifyContent: | |
| 'flex-start' | |
| 'flex-end' | |
| 'center' | |
| 'space-between' | |
| 'space-around' | |
| string; | |
alignItems: | |
| 'flex-start' | |
| 'flex-end' | |
| 'center' | |
| 'baseline' | |
| 'stretch' | |
| string; | |
alignContent: | |
| 'flex-start' | |
| 'flex-end' | |
| 'center' | |
| 'space-between' | |
| 'space-around' | |
| 'stretch' | |
| string; | |
order: | |
| '0' | |
| '1' | |
| '2' | |
| '3' | |
| '4' | |
| '5' | |
| '6' | |
| '7' | |
| '8' | |
| '9' | |
| '10' | |
| '11' | |
| '12' | |
| '-9999' | |
| '9999' | |
| 'auto' | |
| string; | |
flex: | |
| '1 1 0%' | |
| '0 1 auto' | |
| '1 1 auto' | |
| 'initial' | |
| 'inherit' | |
| 'unset' | |
| 'none' | |
| string; | |
alignSelf: | |
| 'auto' | |
| 'flex-start' | |
| 'flex-end' | |
| 'center' | |
| 'baseline' | |
| 'stretch' | |
| string; | |
justifySelf: | |
| 'auto' | |
| 'flex-start' | |
| 'flex-end' | |
| 'center' | |
| 'space-between' | |
| 'space-around' | |
| string; | |
shrink: number; | |
placeContent: | |
| 'center' | |
| 'start' | |
| 'end' | |
| 'space-between' | |
| 'space-around' | |
| 'space-evenly' | |
| 'stretch' | |
| string; | |
placeItems: 'center' | 'start' | 'end' | 'stretch' | string; | |
placeSelf: 'center' | 'start' | 'end' | 'stretch' | 'auto' | string; | |
gridTemplateColumns: string; | |
gridColumn: string; | |
gridColumnStart: | |
| '1' | |
| '2' | |
| '3' | |
| '4' | |
| '5' | |
| '6' | |
| '7' | |
| '8' | |
| '9' | |
| '10' | |
| '11' | |
| '12' | |
| '13' | |
| 'auto' | |
| string; | |
gridColumnEnd: | |
| '1' | |
| '2' | |
| '3' | |
| '4' | |
| '5' | |
| '6' | |
| '7' | |
| '8' | |
| '9' | |
| '10' | |
| '11' | |
| '12' | |
| '13' | |
| 'auto' | |
| string; | |
gridTemplateRows: 'none' | string; | |
gridRow: string; | |
gridRowStart: '1' | '2' | '3' | '4' | '5' | '6' | '7' | 'auto' | string; | |
gridRowEnd: '1' | '2' | '3' | '4' | '5' | '6' | '7' | 'auto' | string; | |
gridAutoFlow: | |
| 'row' | |
| 'column' | |
| 'dense' | |
| 'row dense' | |
| 'column dense' | |
| string; | |
gridAutoColumns: | |
| 'auto' | |
| 'min-content' | |
| 'max-content' | |
| 'minmax(0, 1fr)' | |
| string; | |
gridAutoRows: | |
| 'auto' | |
| 'min-content' | |
| 'max-content' | |
| 'minmax(0, 1fr)' | |
| string; | |
p: number | string; | |
m: number | string; | |
w: number | string; | |
h: number | string; | |
minw: number | string; | |
maxw: number | string; | |
minh: number | string; | |
maxh: number | string; | |
ygap: number | string; | |
xgap: number | string; | |
radius: number | string; | |
lineHeight: number | string; | |
color: string; | |
bgColor: string; | |
fontSize: string; | |
fontWeight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900; | |
textAlign: 'left' | 'right' | 'center' | 'justify' | string; | |
textColor: string; | |
textDecoration: | |
| 'underline' | |
| 'line-through' | |
| 'none' | |
| 'overline' | |
| 'no-underline' | |
| string; | |
textDecorationColor: string; | |
textDecorationStyle: | |
| 'solid' | |
| 'double' | |
| 'dotted' | |
| 'dashed' | |
| 'wavy' | |
| string; | |
textDecorationThickness: number | string; | |
textUnderlineOffset: number | string; | |
textTransform: string; | |
textOverflow: string; | |
textIndent: number | string; | |
border: string; | |
borderWidth: number; | |
borderStyle: string; | |
borderColor: string; | |
borderTop: string; | |
borderRight: string; | |
borderBottom: string; | |
borderLeft: string; | |
borderTopLeftRadius: string; | |
borderTopRightRadius: string; | |
borderBottomLeftRadius: string; | |
borderBottomRightRadius: string; | |
borderImage: string; | |
borderImageSlice: string; | |
borderImageWidth: string; | |
borderImageOutset: string; | |
borderCollapse: 'separate' | 'collapse' | string; | |
borderSpacing: number | string; | |
tableLayout: 'auto' | 'fixed' | string; | |
outline: string; | |
outlineWidth: number | string; | |
outlineColor: string; | |
outlineStyle: | |
| 'solid' | |
| 'double' | |
| 'dotted' | |
| 'dashed' | |
| 'wavy' | |
| 'hidden' | |
| string; | |
outlineOffset: number | string; | |
outlineRadius: number | string; | |
backgroundAttachment: 'fixed' | 'scroll' | 'local' | string; | |
backgroundClip: | |
| 'border-box' | |
| 'padding-box' | |
| 'content-box' | |
| 'text' | |
| string; | |
backgroundColor: string; | |
backgroundOrigin: 'border-box' | 'padding-box' | 'content-box' | string; | |
backgroundPosition: | |
| 'left' | |
| 'center' | |
| 'right' | |
| 'bottom' | |
| 'center' | |
| 'left bottom' | |
| 'left top' | |
| 'right bottom' | |
| 'right top' | |
| 'top' | |
| string; | |
backgroundRepeat: | |
| 'repeat' | |
| 'repeat-x' | |
| 'repeat-y' | |
| 'no-repeat' | |
| 'round' | |
| 'space' | |
| string; | |
backgroundSize: 'auto' | 'cover' | 'contain' | string; | |
backgroundImage: string; | |
boxShadow: string; | |
opacity: number | string; | |
zIndex: number | string; | |
mixBlendMode: | |
| 'normal' | |
| 'multiply' | |
| 'screen' | |
| 'overlay' | |
| 'darken' | |
| 'lighten' | |
| 'color-dodge' | |
| 'color-burn' | |
| 'hard-light' | |
| 'soft-light' | |
| 'difference' | |
| 'exclusion' | |
| 'hue' | |
| 'saturation' | |
| 'color' | |
| 'luminosity' | |
| 'normal' | |
| 'inherit' | |
| 'plus-lighter' | |
| string; | |
backgroundBlendMode: | |
| 'multiply' | |
| 'screen' | |
| 'overlay' | |
| 'darken' | |
| 'lighten' | |
| 'color-dodge' | |
| 'color-burn' | |
| 'hard-light' | |
| 'soft-light' | |
| 'difference' | |
| 'exclusion' | |
| 'hue' | |
| 'saturation' | |
| 'color' | |
| 'luminosity' | |
| 'normal' | |
| 'inherit' | |
| string; | |
filter: string; | |
backdropFilter: string; | |
transform: string; | |
transformOrigin: string; | |
transition: string; | |
transitionProperty: string; | |
transitionDuration: string; | |
transitionTimingFunction: string; | |
transitionDelay: string; | |
accentColor: string; | |
appearance: 'none'; | |
cursor: 'auto' | 'default' | 'pointer' | 'text' | 'wait' | string; | |
caretColor: string; | |
pointerEvents: 'auto' | 'none' | 'all' | string; | |
resize: 'none' | 'both' | 'horizontal' | 'vertical' | string; | |
float: 'left' | 'right' | 'none' | string; | |
clear: 'left' | 'right' | 'both' | 'none' | string; | |
isolation: 'isolate' | 'auto' | 'inherit' | 'unset' | string; | |
objectFit: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down' | string; | |
objectPosition: | |
| 'bottom' | |
| 'center' | |
| 'left' | |
| 'left bottom' | |
| 'left top' | |
| 'right' | |
| 'right bottom' | |
| 'right top' | |
| 'top' | |
| string; | |
overflow: 'auto' | 'hidden' | 'clip' | 'auto' | 'visible' | 'scroll' | string; | |
overflowX: | |
| 'auto' | |
| 'hidden' | |
| 'clip' | |
| 'auto' | |
| 'visible' | |
| 'scroll' | |
| string; | |
overflowY: | |
| 'auto' | |
| 'hidden' | |
| 'clip' | |
| 'auto' | |
| 'visible' | |
| 'scroll' | |
| string; | |
overscroll: 'auto' | 'contain' | 'none' | string; | |
overscrollX: 'auto' | 'contain' | 'none' | string; | |
overscrollY: 'auto' | 'contain' | 'none' | string; | |
verticalAlign: | |
| 'baseline' | |
| 'top' | |
| 'middle' | |
| 'bottom' | |
| 'text-top' | |
| 'text-bottom' | |
| 'sub' | |
| 'super' | |
| string; | |
whiteSpace: 'normal' | 'nowrap' | 'pre' | 'pre-line' | 'pre-wrap' | string; | |
wordWrap: string; | |
content: 'none'; | |
scrollBehavior: 'auto' | 'smooth'; | |
scrollMargin: number | string; | |
scrollMarginLeft: number | string; | |
scrollMarginRight: number | string; | |
scrollMarginTop: number | string; | |
scrollMarginBottom: number | string; | |
scrollPadding: number | string; | |
scrollPaddingLeft: number | string; | |
scrollPaddingRight: number | string; | |
scrollPaddingTop: number | string; | |
scrollPaddingBottom: number | string; | |
scrollSnapAlign: 'none' | 'start' | 'center' | 'end' | 'stretch'; | |
scrollSnapStop: 'always' | 'normal' | 'never'; | |
scrollSnapType: 'none' | 'mandatory' | 'proximity' | string; | |
touchAction: | |
| 'auto' | |
| 'none' | |
| 'pan-x' | |
| 'pan-left;' | |
| 'pan-right;' | |
| 'pan-y' | |
| 'pan-up' | |
| 'pan-down' | |
| 'pinch-zoom' | |
| 'manipulation'; | |
userSelect: 'none' | 'text' | 'all' | 'auto' | string; | |
willChange: 'auto' | 'scroll-position' | 'contents' | 'transform' | string; | |
fill: string; | |
stroke: string; | |
strokeWidth: number | string; | |
aspectRatio: 'auto' | '1 / 1' | '16 / 9' | number | string; | |
columns: number | string; | |
breakAfter: | |
| 'auto' | |
| 'avoid' | |
| 'all' | |
| 'avoid-page' | |
| 'page' | |
| 'left' | |
| 'right' | |
| 'column' | |
| string; | |
breakBefore: | |
| 'auto' | |
| 'avoid' | |
| 'all' | |
| 'avoid-page' | |
| 'page' | |
| 'left' | |
| 'right' | |
| 'column' | |
| string; | |
breakInside: 'auto' | 'avoid' | 'avoid-page' | 'avoid-column' | string; | |
boxDecorationBreak: 'slice' | 'clone' | string; | |
boxSizing: 'border-box' | 'content-box' | string; | |
position: 'static' | 'relative' | 'absolute' | 'fixed' | 'sticky' | string; | |
top: number | string; | |
left: number | string; | |
bottom: number | string; | |
right: number | string; | |
visibility: 'visible' | 'hidden' | 'collapse' | string; | |
hover: Record<string, string>; | |
/* hover?: { | |
[property: string]: Property; | |
}; */ | |
}; | |
type GenericOwnProps<E extends React.ElementType = React.ElementType> = Partial< | |
Property | |
> & { | |
children?: JSX.Element | JSX.Element[] | string; | |
as?: E; | |
cls?: string | Record<string, string> | string[]; | |
}; | |
export type GenericProps<E extends React.ElementType> = GenericOwnProps<E> & | |
Omit<React.ComponentProps<E>, keyof GenericOwnProps>; | |
const __DEFAULT_ELEMENT__ = 'div'; | |
const shortName = [ | |
{ | |
shortname: 'p', | |
longname: 'padding', | |
}, | |
{ | |
shortname: 'm', | |
longname: 'margin', | |
}, | |
{ | |
shortname: 'w', | |
longname: 'width', | |
}, | |
{ | |
shortname: 'h', | |
longname: 'height', | |
}, | |
{ | |
shortname: 'minw', | |
longname: 'minWidth', | |
}, | |
{ | |
shortname: 'maxw', | |
longname: 'maxWidth', | |
}, | |
{ | |
shortname: 'minh', | |
longname: 'minHeight', | |
}, | |
{ | |
shortname: 'maxh', | |
longname: 'maxHeight', | |
}, | |
{ | |
shortname: 'ygap', | |
longname: 'rowGap', | |
}, | |
{ | |
shortname: 'xgap', | |
longname: 'columnGap', | |
}, | |
{ | |
shortname: 'bgColor', | |
longname: 'backgroundColor', | |
}, | |
{ | |
shortname: 'radius', | |
longname: 'borderRadius', | |
}, | |
{ | |
shortname: 'overscroll', | |
longname: 'overscrollBehavior', | |
}, | |
{ | |
shortname: 'overscrollX', | |
longname: 'overscrollBehaviorX', | |
}, | |
{ | |
shortname: 'overscrollY', | |
longname: 'overscrollBehaviorY', | |
}, | |
]; | |
function longName(value: string): string { | |
const object = shortName.find(data => data?.shortname === value); | |
return object ? object.longname : value; | |
} | |
function converter(value: string | number): string { | |
return typeof value === 'number' ? `${value}rem` : value; | |
} | |
function className(value: string): string { | |
const property = longName(value); | |
return property.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`); | |
} | |
function css(props: Record<string, string>): string { | |
return Object.entries(props) | |
.map(([key, value]) => `${className(key)}: ${converter(value)};`) | |
.join(';'); | |
} | |
function Title<E extends React.ElementType = typeof __DEFAULT_ELEMENT__>({ | |
children, | |
as, | |
cls, | |
hover, | |
...props | |
}: GenericProps<E>) { | |
const Component = as || __DEFAULT_ELEMENT__; | |
return ( | |
<Fragment> | |
<Component className={clsx('timboo', cls)} {...props}> | |
{children} | |
</Component> | |
<style jsx>{` | |
.timboo { | |
${css(props)} | |
} | |
.timboo:hover { | |
${css(hover ?? {})} | |
} | |
`}</style> | |
</Fragment> | |
); | |
} | |
export default Title; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment