UNPKG

reactrators

Version:

A React library for composing and enhancing components with flexible and chainable functions. Simplify the process of injecting functionality and props into React components by providing a composable utility for building component enhancers.

44 lines (39 loc) 1.8 kB
import {ComponentType, createElement } from "react"; import {ComposableOptions, EnhancedProps, InjectableEntry, InjectableFunction} from "./types"; const _composeFns = (props: Record<string, any>, toCompose: (InjectableFunction | InjectableEntry)[], opts?: ComposableOptions): Record<string, any> => { return toCompose.reduce((acc, fn) => { if(!Array.isArray(fn) && typeof fn !== "function") { throw new Error("Hook must be a function or an array"); } if(Array.isArray(fn) && fn.length !== 2) { throw new Error("Hook must be an array with 2 elements"); } let fnToCall = fn; let params = undefined; if(Array.isArray(fn)) { if(typeof fn[0] !== "function" && typeof fn[1] !== "object") { throw new Error("Hook must be an array with first element as a function and second element as an object"); } const [ fnArray , paramsArray ] = fn as InjectableEntry; fnToCall = fnArray; params = paramsArray; } let fnInstanceParams = { ...params, ...props }; if(opts?.chainable) { fnInstanceParams = { ...acc, ...params, ...props }; } const fnInstance = (fnToCall as InjectableFunction)(fnInstanceParams); acc = { ...acc, ...fnInstance }; return acc }, {}); } const composable = (fn: (props?: Record<any, any>) => (InjectableFunction | InjectableEntry)[], opts: ComposableOptions ) => <P extends EnhancedProps>( Component: ComponentType<P> ) => { return (props: P) => { const injectable = fn(); const toInject = _composeFns(props, injectable, opts); return createElement(Component, { ...toInject, ...props }); } } export default composable;