import * as T from "./types" ; import { isArray , push } from "./utils" ; const KEYS = [ "propsKeys" , "styleKeys" , "themeKeys" ] ; export function unique ( renderers , initial = [ ] ) { return renderers . reduce ( ( collection , renderer ) => { const isComposed = renderer . type === "compose" ; const isIncluded = collection . includes ( renderer ) ; const { renderers : renderFuncs } = renderer . options ; if ( ! isComposed && ! isIncluded ) collection . push ( renderer ) ; if ( isArray ( renderFuncs ) ) unique ( renderFuncs , initial ) ; return collection ; } , initial ) ; } export function compose < P extends T . ThemeProps , S extends T . Style > ( options ) { let { name } = options ; if ( ! /Set$/ . test ( name ) ) name += "Set" ; const renderers = unique ( options . renderers ) ; const composedOptions = { propsKeys : [ ] , styleKeys : [ ] , themeKeys : [ ] , renderers } ; renderers . forEach ( ( renderer ) => KEYS . forEach ( ( optionsKey ) => { const composedKeys = composedOptions [ optionsKey ] ; const rendererKeys = renderer . options [ optionsKey ] ; if ( rendererKeys ) { rendererKeys . forEach ( ( key ) => { if ( ! composedKeys . includes ( key ) ) composedKeys . push ( key ) ; } ) ; } } ) ) ; const renderProps = ( props ) => { const result = renderers . reduce ( ( styles , renderer ) => { const output = renderer ( props ) ; if ( output ) push . apply ( styles , output ) ; return styles ; } , [ ] ) ; return result . length ? result : null ; } ; Object . defineProperty ( renderProps , "name" , { value : name } ) ; renderProps . type = "compose" as "compose" ; renderProps . options = composedOptions ; return renderProps ; }