From c90d7fa4f05601d7239dfb7a3d25210f6fe111f8 Mon Sep 17 00:00:00 2001 From: "github@finnesand.no" Date: Tue, 25 Aug 2020 20:13:28 +0200 Subject: [PATCH] filter, variables and functions within with() is nestable --- src/base/attachAttrs.ts | 86 +++++++++++++++++++---------- src/base/attachMethodsToInstance.ts | 4 +- src/base/index.ts | 35 ++++++------ src/system/setup.ts | 2 +- 4 files changed, 80 insertions(+), 47 deletions(-) diff --git a/src/base/attachAttrs.ts b/src/base/attachAttrs.ts index 554913e..39bd44b 100644 --- a/src/base/attachAttrs.ts +++ b/src/base/attachAttrs.ts @@ -2,33 +2,54 @@ import render from '../system/render'; import { forwardRef } from '../system/setup'; import getFilteredProps from './getFilteredProps'; -function as(this: any, a: any) { +function as(this: any, component: any, a: any) { this.mergedProps = { ...this.mergedProps, as: a }; - return this; + return component; } -function withComponent(this: any, attrsIn: any, val: any, filter: string[]) { +function withComponent( + this: any, + { + forwardProps = {}, + forwardFunctions = [], + forwardFilter = [], + forwardVariant = {} + }, + val: any, + filter: string[] = [] +) { /* eslint-disable @typescript-eslint/no-use-before-define */ const attachAttrsBound = attachAttrs.bind(this); /* eslint-enable @typescript-eslint/no-use-before-define */ - const { mergedProps } = this; + const { mergedProps, variant } = this; + const filters = [ + ...this.removeProps, + ...forwardFilter, + ...Object.keys(variant), + ...filter + ]; const WrappedComponent = (props?: any, ref = { current: null }) => { const refOut = ref && forwardRef ? { ref } : {}; const styles = typeof val === 'function' ? val(props) : val; - const attrs = typeof attrsIn === 'function' ? attrsIn(props) : attrsIn; + const attrs = + typeof forwardProps === 'function' ? forwardProps(props) : forwardProps; + const functionAttrs = forwardFunctions.reduce((acc, cur: any) => { + return { ...acc, ...(typeof cur === 'function' ? cur(props) : cur) }; + }, {}); const initValues = this.getInitialValues(props); - const variantStyles = this.getVariantStyles(props); - const filteredProps = getFilteredProps(props, [ - ...this.removeProps, - ...filter - ]); + const variantStyles = this.getVariantStyles(props, { + ...forwardVariant, + ...variant + }); + const filteredProps = getFilteredProps(props, filters); return render({ ...initValues, ...attrs, ...mergedProps, + ...functionAttrs, ...variantStyles, ...styles, ...filteredProps, @@ -36,44 +57,53 @@ function withComponent(this: any, attrsIn: any, val: any, filter: string[]) { }); }; + const parentProps = { + forwardProps: { ...forwardProps, ...mergedProps, ...val }, + forwardFunctions: [...forwardFunctions, val], + forwardFilter: filters, + forwardVariant: variant + }; + // if used without forwardRef - attachAttrsBound(WrappedComponent, { ...attrsIn, ...mergedProps, ...val }); + attachAttrsBound(WrappedComponent, parentProps); const Forwarded = forwardRef ? forwardRef(WrappedComponent) : WrappedComponent; // if used with forwardRef - attachAttrsBound(Forwarded, { ...mergedProps, ...val }); + attachAttrsBound(Forwarded, parentProps); - this.mergedProps = {}; + this.reset(); - return forwardRef ? Forwarded : WrappedComponent; + return Forwarded; } -function merge(this: any, components: any) { - const mergedProps = Array.isArray(components) - ? components.reduce((acc: any, cur: any) => ({ ...acc, ...cur.attrs }), {}) - : components.attrs; +function merge(this: any, component: any, componentsToBeMerged: any | any[]) { + const mergedProps = Array.isArray(componentsToBeMerged) + ? componentsToBeMerged.reduce( + (acc: any, cur: any) => ({ ...acc, ...cur.attrs }), + {} + ) + : componentsToBeMerged.attrs; this.mergedProps = { ...this.mergedProps, ...mergedProps }; - return this; + return component; } -function variants(this: any, types: any) { +function variants(this: any, component: any, types: any) { this.variant = types; - return this; + return component; } -function attachAttrs(this: any, component: any, attrs: any) { +function attachAttrs(this: any, component: any, parentProps: any = {}) { /* eslint no-param-reassign: ["error", { "props": false }] */ - component.as = as.bind(this); - // attrs argument necessary for passing attrs to nested component - component.with = withComponent.bind(this, attrs); - component.attrs = attrs; - component.merge = merge.bind(this); - component.variants = variants.bind(this); + // components attribute is necessary for nesting components + component.as = as.bind(this, component); + component.with = withComponent.bind(this, parentProps); + component.merge = merge.bind(this, component); + component.variants = variants.bind(this, component); } export default attachAttrs; diff --git a/src/base/attachMethodsToInstance.ts b/src/base/attachMethodsToInstance.ts index 0586c72..85219e1 100644 --- a/src/base/attachMethodsToInstance.ts +++ b/src/base/attachMethodsToInstance.ts @@ -9,8 +9,8 @@ function attachMethodsToInstance(Component: any, instance: any) { Component.variants = function w(variantObj: any) { return instance.variants(variantObj); }; - Component.with = function w(props: any) { - return instance.with(props); + Component.with = function w(props: any, filter: string[]) { + return instance.with(props, filter); }; } diff --git a/src/base/index.ts b/src/base/index.ts index 7852281..b346084 100644 --- a/src/base/index.ts +++ b/src/base/index.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import render from '../system/render'; import { forwardRef } from '../system/setup'; import attachAttrs from './attachAttrs'; @@ -42,8 +41,7 @@ class Base { return typeof initValues === 'function' ? initValues(props) : initValues; } - getVariantStyles(props: any) { - const variants = { ...this.variant }; + getVariantStyles(props: any, variants: any = {}) { const variantNames = Object.keys(variants); let variantStyles = {}; for (let i = 0; i < variantNames.length; i++) { @@ -81,19 +79,17 @@ class Base { return this; } - with(val: any, filter: string[]) { + with(val: any, filter: string[] = []) { const attachAttrsBound = attachAttrs.bind(this); - const { mergedProps } = this; + const { mergedProps, variant } = this; + const filters = [...this.removeProps, ...Object.keys(variant), ...filter]; const WrappedComponent = (props?: any, ref = { current: null }) => { const refOut = ref && forwardRef ? { ref } : {}; const styles = typeof val === 'function' ? val(props) : val; const initValues = this.getInitialValues(props); - const variantStyles = this.getVariantStyles(props); - const filteredProps = getFilteredProps(props, [ - ...this.removeProps, - ...filter - ]); + const variantStyles = this.getVariantStyles(props, variant); + const filteredProps = getFilteredProps(props, [...filters]); return render({ ...initValues, @@ -105,20 +101,27 @@ class Base { }); }; + const attachedProps = { + forwardProps: { ...mergedProps, ...val }, + forwardFunctions: [val], + forwardFilter: filters, + forwardVariant: variant + // forwardMerge: mergedProps + }; + // if used without forwardRef - attachAttrsBound(WrappedComponent, { ...mergedProps, ...val }); + attachAttrsBound(WrappedComponent, attachedProps); + // if used with forwardRef const Forwarded = forwardRef ? forwardRef(WrappedComponent) : WrappedComponent; - // if used with forwardRef - attachAttrsBound(Forwarded, { ...mergedProps, ...val }); + attachAttrsBound(Forwarded, attachedProps); - // this.reset(); - this.mergedProps = {}; + this.reset(); // return WrappedComponent; - return forwardRef ? Forwarded : WrappedComponent; + return Forwarded; } merge(components: any) { diff --git a/src/system/setup.ts b/src/system/setup.ts index 6eb8b3e..4a46145 100644 --- a/src/system/setup.ts +++ b/src/system/setup.ts @@ -9,7 +9,7 @@ interface Config { /* eslint-disable import/no-mutable-exports */ export let h: (nodeName: string, attributes: any, children: any[]) => any; export let themeInternal: Theme = defaultTheme; -export let defaultFun = false; +export let defaultFun = true; export let forwardRef: Function | undefined; /* eslint-enable import/no-mutable-exports */