@pmwcs/base
Version:
PMWCS base module
61 lines (53 loc) • 1.8 kB
JavaScript
import { createElement, Fragment } from 'preact'
import { memo, forwardRef } from 'preact/compat'
import classNamesFunc from 'classnames'
import { parseThemeOptions } from './with-theme'
export const Tag = forwardRef(function Tag (props, ref) {
const { tag, theme, element, ...rest } = props
const TagEl = tag === undefined ? 'div' : tag
const finalProps = element ? element.props(rest) : rest
const finalRef = element ? mergeRefs(ref, element.setRef) : ref
return createElement(TagEl, { ...finalProps, ref: finalRef })
})
export const useClassNames = (props, classNames) => classNamesFunc(
props.className,
...(props.theme ? parseThemeOptions(props.theme) : []),
...(typeof classNames === 'function' ? classNames(props) : classNames)
)
export const mergeRefs = (
...refs
) => (el) => {
for (const ref of refs) {
if (typeof ref === 'function') {
ref(el)
} else if (ref && 'current' in ref) {
// @ts-ignore
ref.current = el
}
}
}
export const handleRef = (
ref,
value
) => {
if (typeof ref === 'function') {
ref(value)
} else if (ref && 'current' in ref) {
// @ts-ignore
ref.current = value
}
}
export function createComponent (Component) {
const ForwardComponent = forwardRef(Component)
// Interestingly enough, we only need this declaration
// for a generic placeholder for typescript inference,
// we don't actually have to pay the penalty for using it at runtime :)
const WrappedComponent = () => createElement(Fragment, null)
WrappedComponent.displayName = Component.constructor.name || 'PMWCSComponent'
ForwardComponent.displayName = WrappedComponent.displayName
return ForwardComponent
}
export function createMemoComponent (Component) {
const Comp = createComponent(Component)
return memo(Comp)
}