Skip to content

Instantly share code, notes, and snippets.

@wspl
Created June 13, 2018 05:24
Show Gist options
  • Save wspl/1f45a3d36cc9c2e4ebf618a29e769ef8 to your computer and use it in GitHub Desktop.
Save wspl/1f45a3d36cc9c2e4ebf618a29e769ef8 to your computer and use it in GitHub Desktop.
Easy naming react components for styling
import { DetailedHTMLProps, HTMLAttributes, InputHTMLAttributes } from 'react'
import * as React from 'react'
import classNames from 'classnames'
export type NamedComponentsProps<A extends HTMLAttributes<E>, E extends Element> = DetailedHTMLProps<A, E> & {
innerRef?: (ref: E) => void
flags?: { [key: string]: boolean }
}
export type NamedComponentsMap<A extends HTMLAttributes<E>, E extends Element> = {
[key: string]: (props: NamedComponentsProps<A, E>) =>
React.Component<NamedComponentsProps<A, E>, {}>
}
const elementMatchDict = {
span: ['Text', 'Label', 'Title'],
input: ['Input']
}
interface INamedComponents {
(ns: string): NamedComponentsMap<HTMLAttributes<HTMLElement>, HTMLElement>
input(ns: string): NamedComponentsMap<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
}
export const NamedComponents = ((ns: string) => {
return new Proxy({}, {
get: (target, name: string) => {
const elementFilteredResult = Object
.entries(elementMatchDict)
.filter(([element, suffixes]) =>
suffixes
.filter(s => name.endsWith(s))
.length > 0
)
const element = elementFilteredResult.length > 0 ? elementFilteredResult[0][0] : 'div'
return class extends React.Component<NamedComponentsProps<HTMLAttributes<HTMLElement>, HTMLElement>, {}> {
render() {
return React.createElement(element, {
className: classNames(ns, name, this.props.flags),
ref: ref => this.props.innerRef && this.props.innerRef(ref as HTMLElement),
...Object
.keys(this.props)
.filter(key => !['className', 'flags', 'ref', 'innerRef'].includes(key))
.reduce((obj, key) => {
obj[key] = this.props[key]
return obj
}, {})
}, this.props.children)
}
}
}
})
}) as INamedComponents
NamedComponents.input = ((ns: string) => NamedComponents(ns) as NamedComponentsMap<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment