Open jeremy-coleman opened 5 years ago
better editor feedback without being aidsy than pretty much every other style library (at least imo)
import React from 'react' import { HTMLProps, CSSProperties } from 'react' const h = React.createElement //new CSSRuleList() //items, length //let r = new CSSStyleRule //was using this like this, jus took context out though idk, deal later //{theme: defined(context.theme, props.theme, pallete: 'none')} const defined = (...args) => { for (var i = 0; i < args.length; i++) { if (args[i] !== undefined) return args[i] } } let cache = {} let prefix = 'x' const rules: CSSStyleRule[] = [] //[] let insert = (rule: CSSStyleRule) => void rules.push(rule as CSSStyleRule) const hyph = s => s.replace(/[A-Z]|^ms/g, '-$&').toLowerCase() const mx = (rule, media) => (media ? `${media}{${rule}}` : rule) const rx = (cn, prop, val) => `.${cn}{${hyph(prop)}:${val}}` const noAnd = s => s.replace(/&/g, '') const parse = (obj, child = '', media?) => Object.keys(obj) .map(key => { const val = obj[key] if (val === null) return '' if (typeof val === 'object') { const m2 = /^@/.test(key) ? key : null const c2 = m2 ? child : child + key return parse(val, c2, m2 || media) } const _key = key + val + child + media if (cache[_key]) return cache[_key] const className = prefix + rules.length.toString(36) insert(mx(rx(className + noAnd(child), key, val), media)) cache[_key] = className return className }) .join(' ') function cxs(...styles) { return styles .map(style => parse(style)) .join(' ') .trim() } cxs.css = () => rules.sort().join('') cxs.reset = () => { cache = {} while (rules.length) rules.pop() } cxs.prefix = val => (prefix = val) if (typeof document !== 'undefined') { const sheet = document.head.appendChild(document.createElement('style')).sheet as CSSStyleSheet insert = (rule: CSSStyleRule & string) => { rules.push(rule as CSSStyleRule) sheet.insertRule(rule, sheet.cssRules.length) } } type DomProps = Partial<HTMLProps<any>> type CSX = { css?: CSSProperties } type StyledCSX = DomProps & CSX type Proptional<P> = CSSProperties | ((...args: P[]) => CSSProperties) function styled<P>(C) { return (...args: Proptional<P>[]) => { const Comp = (props: P & StyledCSX) => { const stylePropKeys = [...Object.keys({}), 'css'] //const styleProps = Object.assign({ theme: defined(context.theme, props.theme, {}) }, props) const next: any = {} for (let key in props) { if (stylePropKeys.includes(key)) continue next[key] = props[key] } next.className = [ next.className, ...args .map(proptional => (typeof proptional === 'function' ? proptional(props) : proptional)) .filter(s => !!s) .map(s => cxs(s)), cxs(props.css || {}), ] .join(' ') .trim() return h(C, next) } return Comp } } styled.css = cxs.css styled.reset = cxs.reset export { cxs } export { styled } export default styled // export function styledComponentWithProps<T, U extends HTMLElement = HTMLElement>(styledFunction: StyledFunction<React.HTMLProps<U>>): StyledFunction<T & React.HTMLProps<U>> { // return styledFunction as any; // } // thanks microsoft, please teach our youth how to read, i think you've got it figured out // type Unpacked<T> = T extends (infer U)[] // ? U // : T extends (...args: any[]) => infer U // ? U // : T extends Promise<infer U> // ? U // : T // type T0 = Unpacked<string> // string // type T1 = Unpacked<string[]> // string // type T2 = Unpacked<() => string> // string // type Foo<T> = T extends { a: infer U; b: infer U } ? U : never // type T10 = Foo<{ a: string; b: string }> // string // type T11 = Foo<{ a: string; b: number }> // string | number //type CC = (...args: CSSProperties[]) => infer R ? R : CSSProperties //type ReturnType<T> = (...args) => T ? T : CSSProperties // im going to space mountain charley fml // function styled1(C) { // return (...args) => { // const Comp = (props, context: any = {}) => { // const stylePropKeys = [...Object.keys({}), 'css'] // const styleProps = Object.assign({ theme: defined(context.theme, props.theme, {}) }, props) // const next: any = {} // for (let key in props) { // if (stylePropKeys.includes(key)) continue // next[key] = props[key] // } // next.className = [ // next.className, // ...args // .map(a => (typeof a === 'function' ? a(styleProps) : a)) // .filter(s => !!s) // .map(s => cxs(s)), // cxs(props.css || {}), // ] // .join(' ') // .trim() // return h(C, next) // } // return Comp // } // }
usage
import React from 'react' import { styled } from './styled' type Props = { color: 'green' | 'black' } let MyButton = styled<Props>('button')(props => ({ backgroundColor: (props.color && props.color) || 'green', })) let NoPropsButton = styled('button')({ backgroundColor: 'green', }) export { MyButton, NoPropsButton } let Demo = props => <MyButton onClick={e => console.log('hi')} color={'black'}/>
better editor feedback without being aidsy than pretty much every other style library (at least imo)
usage