From f6b8206bc5fe09260c0a2b06c1164b2b8a85c81b Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 13:21:38 +0200 Subject: [PATCH 01/16] Absorb .ap into the main file --- src/ReactDream.js | 5 ++--- src/internals/doAp.js | 2 -- test/internals/doAp.js | 15 --------------- test/internals/index.js | 2 -- 4 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 src/internals/doAp.js delete mode 100644 test/internals/doAp.js diff --git a/src/ReactDream.js b/src/ReactDream.js index a57cf39..28266e2 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -4,7 +4,6 @@ import recomposeDefaultProps from 'recompose/defaultProps' import setPropTypes from 'recompose/setPropTypes' import withDebugger from '@hocs/with-debugger' import withLog from '@hocs/with-log' -import doAp from './internals/doAp' import doConcat from './internals/doConcat' import doContramap from './internals/doContramap' import doMap from './internals/doMap' @@ -17,9 +16,9 @@ import styleFromProps from './styleFromProps' // ALGEBRAS // ////////////////////////////////////////////////////////////////////////// // -// ap : higherOrderComponent -> ReactDream -> ReactDream +// ap : (Component -> Component) -> ReactDream -> ReactDream const ap = higherOrderComponent => ReactDreamComponent => - ReactDream(doAp(higherOrderComponent)(ReactDreamComponent)) + ReactDream(ReactDreamComponent.fork(higherOrderComponent)) // chain : Component -> (Component -> ReactDream) -> ReactDream const chain = Component => kleisliReactDreamComponent => kleisliReactDreamComponent(Component) diff --git a/src/internals/doAp.js b/src/internals/doAp.js deleted file mode 100644 index e45900a..0000000 --- a/src/internals/doAp.js +++ /dev/null @@ -1,2 +0,0 @@ -// doAp : (Component -> Component) -> ReactDream -> Component -export default higherOrderComponent => DreamComponent => DreamComponent.fork(higherOrderComponent) diff --git a/test/internals/doAp.js b/test/internals/doAp.js deleted file mode 100644 index 1124cc5..0000000 --- a/test/internals/doAp.js +++ /dev/null @@ -1,15 +0,0 @@ -import doAp from '../../src/internals/doAp' -import { example, suite } from '../dsl' - -export default suite( - 'doAp', - example( - 'passes the component to fork of the argument', - - () => doAp(false)({ - fork: x => !x, - }), - - true - ) -) diff --git a/test/internals/index.js b/test/internals/index.js index 52cc320..7c96dd5 100644 --- a/test/internals/index.js +++ b/test/internals/index.js @@ -1,5 +1,4 @@ import { example, suite } from '../dsl' -import doApSuite from './doAp' import doConcatSuite from './doConcat' import doContramapSuite from './doContramap' import doMapSuite from './doMap' @@ -7,7 +6,6 @@ import doPromapSuite from './doPromap' export default suite( 'internals', - ...doApSuite, ...doConcatSuite, ...doContramapSuite, ...doMapSuite, From 129685798d244aec0d0e1db929a2be6cb5271c56 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 14:44:28 +0200 Subject: [PATCH 02/16] Absorb .concat into the main file --- src/ReactDream.js | 26 +++++++++++++++++++------- src/internals/doConcat.js | 12 ------------ test/ReactDream.js | 8 ++++++-- test/internals/doConcat.js | 19 ------------------- test/internals/index.js | 2 -- 5 files changed, 25 insertions(+), 42 deletions(-) delete mode 100644 src/internals/doConcat.js delete mode 100644 test/internals/doConcat.js diff --git a/src/ReactDream.js b/src/ReactDream.js index 28266e2..c1f1e87 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -1,10 +1,12 @@ +import React, { Fragment } from 'react' import compose from 'recompose/compose' +import getDisplayName from 'recompose/getDisplayName' import setDisplayName from 'recompose/setDisplayName' import recomposeDefaultProps from 'recompose/defaultProps' import setPropTypes from 'recompose/setPropTypes' import withDebugger from '@hocs/with-debugger' import withLog from '@hocs/with-log' -import doConcat from './internals/doConcat' + import doContramap from './internals/doContramap' import doMap from './internals/doMap' import doPromap from './internals/doPromap' @@ -21,14 +23,24 @@ const ap = higherOrderComponent => ReactDreamComponent => ReactDream(ReactDreamComponent.fork(higherOrderComponent)) // chain : Component -> (Component -> ReactDream) -> ReactDream -const chain = Component => kleisliReactDreamComponent => kleisliReactDreamComponent(Component) - -// map : Component -> (Component -> Component) -> ReactDream -const map = Component => higherOrderComponent => ReactDream(doMap(higherOrderComponent)(Component)) +const chain = Component => kleisliReactDreamComponent => + kleisliReactDreamComponent(Component) // concat : Component -> Component -> ReactDream -const concat = Component => OtherComponent => - ReactDream(doConcat(OtherComponent.Component)(Component)) +const concat = Component => ReactDreamComponent => + ReactDream( + setDisplayName( + getDisplayName(Component) + .concat(getDisplayName(ReactDreamComponent.CompComponent)) + )(props => + + + ) + ) + +// map : Component -> (Component -> Component) -> ReactDream +const map = Component => higherOrderComponent => + ReactDream(doMap(higherOrderComponent)(Component)) // contramap : Component -> (a -> Props) -> ReactDream const contramap = Component => propsPreprocessor => diff --git a/src/internals/doConcat.js b/src/internals/doConcat.js deleted file mode 100644 index 95cc617..0000000 --- a/src/internals/doConcat.js +++ /dev/null @@ -1,12 +0,0 @@ -import React, { Fragment } from 'react' -import getDisplayName from 'recompose/getDisplayName' -import setDisplayName from 'recompose/setDisplayName' - -// doConcat : Component -> Component -> Component -export default ComponentA => ComponentB => - setDisplayName( - getDisplayName(ComponentB).concat(getDisplayName(ComponentA)) - )(props => - - - ) diff --git a/test/ReactDream.js b/test/ReactDream.js index 87d1845..da4d6aa 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -303,13 +303,17 @@ export default suite( example( 'combines two Components so that they return an array of elements', () => { - const Concatenation = ReactDream(({ x }) => x).concat(ReactDream(({ y }) => y)) + const Concatenation = ReactDream(({ x }) =>
) + .concat(ReactDream(({ y }) =>
)) const renderer = create() return renderer.toJSON() }, - [1, 2] + [ + { type: 'hr', props: { id: 1 }, children: null }, + { type: 'br', props: { id: 2 }, children: null } + ] ) ) ), diff --git a/test/internals/doConcat.js b/test/internals/doConcat.js deleted file mode 100644 index 7f290e6..0000000 --- a/test/internals/doConcat.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' -import { create } from 'react-test-renderer' -import doConcat from '../../src/internals/doConcat' -import { example, suite } from '../dsl' - -export default suite( - 'doConcat', - example( - 'forwards all props to both and renders them in a Fragment', - - () => { - const Concatenation = doConcat(({ y }) => y)(({ x }) => x) - - return create().toJSON() - }, - - [1, 2] - ) -) diff --git a/test/internals/index.js b/test/internals/index.js index 7c96dd5..c10f256 100644 --- a/test/internals/index.js +++ b/test/internals/index.js @@ -1,12 +1,10 @@ import { example, suite } from '../dsl' -import doConcatSuite from './doConcat' import doContramapSuite from './doContramap' import doMapSuite from './doMap' import doPromapSuite from './doPromap' export default suite( 'internals', - ...doConcatSuite, ...doContramapSuite, ...doMapSuite, ...doPromapSuite From 12ef7e649e87b967fc3f693d1e2b652fde39d43e Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 14:57:25 +0200 Subject: [PATCH 03/16] Remove useless withStyleFromProps --- src/index.js | 2 -- src/withStyleFromProps.js | 4 ---- 2 files changed, 6 deletions(-) delete mode 100644 src/withStyleFromProps.js diff --git a/src/index.js b/src/index.js index 5d1225d..56bdd30 100644 --- a/src/index.js +++ b/src/index.js @@ -4,8 +4,6 @@ export { default as createElementWithProps } from './createElementWithProps' export { default as styleFromProps } from './styleFromProps' -export { default as withStyleFromProps } from './withStyleFromProps' - export { default as addProps } from './partialApplication/addProps' export { default as ap } from './partialApplication/ap' export { default as chain } from './partialApplication/chain' diff --git a/src/withStyleFromProps.js b/src/withStyleFromProps.js deleted file mode 100644 index fd6882e..0000000 --- a/src/withStyleFromProps.js +++ /dev/null @@ -1,4 +0,0 @@ -import doContramap from './internals/doContramap' -import styleFromProps from './styleFromProps' - -export default getStyleFromProps => doContramap(styleFromProps(getStyleFromProps)) From a8d739988dc44ca55cfdd3daf3e5df43cd8e49df Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 15:11:31 +0200 Subject: [PATCH 04/16] Rework most of .contramap usages. Promap is now broken --- src/ReactDream.js | 51 ++++-- src/helpers/getRotateStyle.js | 17 ++ src/helpers/getScaleStyle.js | 16 ++ .../getTranslateStyle.js} | 20 ++- src/internals/doContramap.js | 15 -- src/internals/doPromap.js | 7 - src/internals/doRotate.js | 18 --- src/internals/doScale.js | 18 --- test/internals/doContramap.js | 153 ------------------ test/internals/doPromap.js | 43 ----- test/internals/index.js | 4 - 11 files changed, 76 insertions(+), 286 deletions(-) create mode 100644 src/helpers/getRotateStyle.js create mode 100644 src/helpers/getScaleStyle.js rename src/{internals/doTranslate.js => helpers/getTranslateStyle.js} (67%) delete mode 100644 src/internals/doContramap.js delete mode 100644 src/internals/doPromap.js delete mode 100644 src/internals/doRotate.js delete mode 100644 src/internals/doScale.js delete mode 100644 test/internals/doContramap.js delete mode 100644 test/internals/doPromap.js diff --git a/src/ReactDream.js b/src/ReactDream.js index c1f1e87..058ece2 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -7,18 +7,20 @@ import setPropTypes from 'recompose/setPropTypes' import withDebugger from '@hocs/with-debugger' import withLog from '@hocs/with-log' -import doContramap from './internals/doContramap' +import isReferentiallyTransparentFunctionComponent from './isReferentiallyTransparentFunctionComponent' + import doMap from './internals/doMap' -import doPromap from './internals/doPromap' -import doRotate from './internals/doRotate' -import doTranslate from './internals/doTranslate' -import doScale from './internals/doScale' +import getRotateStyle from './helpers/getRotateStyle' +import getScaleStyle from './helpers/getScaleStyle' +import getTranslateStyle from './helpers/getTranslateStyle' import styleFromProps from './styleFromProps' // ALGEBRAS // ////////////////////////////////////////////////////////////////////////// // -// ap : (Component -> Component) -> ReactDream -> ReactDream +// ap : (ReactComponent a e -> b) -> +// ReactDream (ReactComponent a e) -> +// ReactDream (b) const ap = higherOrderComponent => ReactDreamComponent => ReactDream(ReactDreamComponent.fork(higherOrderComponent)) @@ -26,7 +28,9 @@ const ap = higherOrderComponent => ReactDreamComponent => const chain = Component => kleisliReactDreamComponent => kleisliReactDreamComponent(Component) -// concat : Component -> Component -> ReactDream +// concat : ReactComponent a e -> +// ReactComponent b f -> +// ReactDream (ReactComponent c g) const concat = Component => ReactDreamComponent => ReactDream( setDisplayName( @@ -42,13 +46,25 @@ const concat = Component => ReactDreamComponent => const map = Component => higherOrderComponent => ReactDream(doMap(higherOrderComponent)(Component)) -// contramap : Component -> (a -> Props) -> ReactDream -const contramap = Component => propsPreprocessor => - ReactDream(doContramap(propsPreprocessor)(Component)) +// contramap : ReactComponent a e -> +// (a -> b) -> +// ReactDream (ReactComponent b e) +const contramap = Component => propsPreprocessor => { + const Enhanced = isReferentiallyTransparentFunctionComponent(Component) + ? compose(Component, propsPreprocessor) + : props => + + Enhanced.displayName = getDisplayName(Component) + + return ReactDream(Enhanced) +} + +// doPromap : ((a -> Props), (Component -> Component)) -> Component -> Component +// // promap : Component -> (a -> Props) -> (Component -> Component) -> ReactDream +// const promap = Component => (propsPreprocessor, higherOrderComponent) => +// ReactDream(doPromap(propsPreprocessor, higherOrderComponent)(Component)) +// compose(doMap(higherOrderComponent), doContramap(propsPreprocessor)) -// promap : Component -> (a -> Props) -> (Component -> Component) -> ReactDream -const promap = Component => (propsPreprocessor, higherOrderComponent) => - ReactDream(doPromap(propsPreprocessor, higherOrderComponent)(Component)) // CUSTOM HELPERS // ////////////////////////////////////////////////////////////////////////// // @@ -91,14 +107,15 @@ const propTypes = Component => propTypesToSet => ReactDream(setPropTypes(propTyp // translate : Component -> (Props -> [Number]) -> ReactDream const translate = Component => getTranslateFromProps => - ReactDream(doTranslate(getTranslateFromProps)(Component)) + contramap(Component)(getTranslateStyle(getTranslateFromProps)) // rotate : Component -> (Props -> Number) -> ReactDream const rotate = Component => getRotateFromProps => - ReactDream(doRotate(getRotateFromProps)(Component)) + contramap(Component)(getRotateStyle(getRotateFromProps)) // scale : Component -> (Props -> Number) -> ReactDream -const scale = Component => getScaleFromProps => ReactDream(doScale(getScaleFromProps)(Component)) +const scale = Component => getScaleFromProps => + contramap(Component)(getScaleStyle(getScaleFromProps)) // style : Component -> (Props -> Style) -> ReactDream const style = Component => getStyleFromProps => @@ -117,7 +134,7 @@ const ReactDream = Component => ({ concat: concat(Component), contramap: contramap(Component), map: map(Component), - promap: promap(Component), + // promap: promap(Component), // Custom helpers addProps: addProps(Component), diff --git a/src/helpers/getRotateStyle.js b/src/helpers/getRotateStyle.js new file mode 100644 index 0000000..a41e456 --- /dev/null +++ b/src/helpers/getRotateStyle.js @@ -0,0 +1,17 @@ +const calculateTransform = oldTransform => rotation => + oldTransform ? `${oldTransform} rotate(${rotation}deg)` : `rotate(${rotation}deg)` + +// getRotateStyle : (Props a -> Number) -> Props a -> Props b +export default getRotateFromProps => + props => ({ + ...props, + style: { + ...props.style, + transform: + calculateTransform( + props && props.style && props.style.transform + )( + getRotateFromProps(props) + ), + }, + }) diff --git a/src/helpers/getScaleStyle.js b/src/helpers/getScaleStyle.js new file mode 100644 index 0000000..6b68679 --- /dev/null +++ b/src/helpers/getScaleStyle.js @@ -0,0 +1,16 @@ +const calculateTransform = oldTransform => scaling => + oldTransform ? `${oldTransform} scale(${scaling})` : `scale(${scaling})` + +// getScaleStyle : (Props -> Number) -> Component -> Component +export default getScaleFromProps => + props => ({ + ...props, + style: { + ...props.style, + transform: calculateTransform( + props && props.style && props.style.transform + )( + getScaleFromProps(props) + ), + }, + }) diff --git a/src/internals/doTranslate.js b/src/helpers/getTranslateStyle.js similarity index 67% rename from src/internals/doTranslate.js rename to src/helpers/getTranslateStyle.js index bb9e454..db04040 100644 --- a/src/internals/doTranslate.js +++ b/src/helpers/getTranslateStyle.js @@ -1,6 +1,3 @@ -import { compose } from 'recompose' -import doContramap from './doContramap' - const calculateTransform = oldTransform => ([x, y, z]) => { switch (true) { case x != null && y != null && z != null: @@ -24,15 +21,16 @@ const calculateTransform = oldTransform => ([x, y, z]) => { } } -// doTranslate : (Props -> [Number]) -> Component -> Component -export default getTranslateFromProps => Component => - doContramap(props => ({ +// getTranslateStyle : (Props a -> [Number]) -> Props a -> Props b +export default getTranslateFromProps => + props => ({ ...props, style: { ...props.style, - transform: compose( - calculateTransform(props && props.style && props.style.transform), - getTranslateFromProps - )(props), + transform: calculateTransform( + props && props.style && props.style.transform + )( + getTranslateFromProps(props) + ), }, - }))(Component) + }) diff --git a/src/internals/doContramap.js b/src/internals/doContramap.js deleted file mode 100644 index 32e0a7d..0000000 --- a/src/internals/doContramap.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import compose from 'recompose/compose' -import getDisplayName from 'recompose/getDisplayName' -import isReferentiallyTransparentFunctionComponent from '../isReferentiallyTransparentFunctionComponent' - -// doContramap : (a -> Props) -> Component -> Component -export default propsPreprocessor => Component => { - const Enhanced = isReferentiallyTransparentFunctionComponent(Component) - ? compose(Component, propsPreprocessor) - : props => - - Enhanced.displayName = getDisplayName(Component) - - return Enhanced -} diff --git a/src/internals/doPromap.js b/src/internals/doPromap.js deleted file mode 100644 index afa6e6c..0000000 --- a/src/internals/doPromap.js +++ /dev/null @@ -1,7 +0,0 @@ -import compose from 'recompose/compose' -import doContramap from './doContramap' -import doMap from './doMap' - -// doPromap : ((a -> Props), (Component -> Component)) -> Component -> Component -export default (propsPreprocessor, higherOrderComponent) => - compose(doMap(higherOrderComponent), doContramap(propsPreprocessor)) diff --git a/src/internals/doRotate.js b/src/internals/doRotate.js deleted file mode 100644 index 93bedd1..0000000 --- a/src/internals/doRotate.js +++ /dev/null @@ -1,18 +0,0 @@ -import { compose } from 'recompose' -import doContramap from './doContramap' - -const calculateTransform = oldTransform => rotation => - oldTransform ? `${oldTransform} rotate(${rotation}deg)` : `rotate(${rotation}deg)` - -// doRotate : (Props -> Number) -> Component -> Component -export default getRotateFromProps => Component => - doContramap(props => ({ - ...props, - style: { - ...props.style, - transform: compose( - calculateTransform(props && props.style && props.style.transform), - getRotateFromProps - )(props), - }, - }))(Component) diff --git a/src/internals/doScale.js b/src/internals/doScale.js deleted file mode 100644 index e7702c6..0000000 --- a/src/internals/doScale.js +++ /dev/null @@ -1,18 +0,0 @@ -import { compose } from 'recompose' -import doContramap from './doContramap' - -const calculateTransform = oldTransform => scaling => - oldTransform ? `${oldTransform} scale(${scaling})` : `scale(${scaling})` - -// doScale : (Props -> Number) -> Component -> Component -export default getScaleFromProps => Component => - doContramap(props => ({ - ...props, - style: { - ...props.style, - transform: compose( - calculateTransform(props && props.style && props.style.transform), - getScaleFromProps - )(props), - }, - }))(Component) diff --git a/test/internals/doContramap.js b/test/internals/doContramap.js deleted file mode 100644 index 7f42981..0000000 --- a/test/internals/doContramap.js +++ /dev/null @@ -1,153 +0,0 @@ -import React, { Component } from 'react' -import { create } from 'react-test-renderer' -import doContramap from '../../src/internals/doContramap' -import { example, suite } from '../dsl' - -export default suite( - 'doContramap', - - ...suite( - 'is a referentially transparent function component', - - example( - 'pre composes the propsPreprocesssor', - - () => { - const ReferentiallyTransparentComponent = x => !x - const propsPreprocessor = () => true - - return doContramap(propsPreprocessor)(ReferentiallyTransparentComponent)() - }, - - false - ), - - example( - 'it has name', - - () => { - function ReferentiallyTransparentComponent(x) { - return x - } - - return doContramap(x => x)(ReferentiallyTransparentComponent).displayName - }, - - 'ReferentiallyTransparentComponent' - ), - - example( - 'it has displayName', - - () => { - const ReferentiallyTransparentComponent = x => x - ReferentiallyTransparentComponent.displayName = 'Casablanca' - - return doContramap(x => x)(ReferentiallyTransparentComponent).displayName - }, - - 'Casablanca' - ), - ), - - ...suite( - 'is not referentially transparent', - - example( - 'returns a new component that wraps building the inner component with the propsPreprocesssor filtering the props', - - () => { - class NotReferentiallyTransparent extends Component { - constructor() { - super() - - this.state = {} - } - - render() { - return ( -
- {this.props.name} -
- ) - } - } - - const propsPreprocesssor = () => ({ name: 'Regina Spektor' }) - - const Enhanced = doContramap(propsPreprocesssor)(NotReferentiallyTransparent) - - const renderer = create() - - return renderer.toJSON().children - }, - - [ 'Regina Spektor' ] - ), - - example( - 'it has name', - - () => { - class NotReferentiallyTransparent extends Component { - constructor() { - super() - - this.state = {} - } - - render() { - return ( -
- {this.props.name} -
- ) - } - } - - const propsPreprocesssor = () => ({ name: 'Regina Spektor' }) - - const Enhanced = doContramap(propsPreprocesssor)(NotReferentiallyTransparent) - - return Enhanced.displayName - }, - - 'NotReferentiallyTransparent' - ), - - ...suite( - 'it has displayName', - - example( - 'preserves it', - () => { - class NotReferentiallyTransparent extends Component { - constructor() { - super() - - this.state = {} - } - - render() { - return ( -
- {this.props.name} -
- ) - } - } - - NotReferentiallyTransparent.displayName = 'BeginToHope' - - const propsPreprocesssor = () => ({ name: 'Regina Spektor' }) - - const Enhanced = doContramap(propsPreprocesssor)(NotReferentiallyTransparent) - - return Enhanced.displayName - }, - - 'BeginToHope' - ) - ) - ) -) diff --git a/test/internals/doPromap.js b/test/internals/doPromap.js deleted file mode 100644 index 23aafa0..0000000 --- a/test/internals/doPromap.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react' -import { create } from 'react-test-renderer' -import doPromap from '../../src/internals/doPromap' -import { example, suite } from '../dsl' - -export default suite( - 'doPromap', - example( - 'run the component through the higher-order component and the pre processor', - - () => { - const propsPreprocessor = () => ({ name: 'Radiohead' }) - const higherOrderComponent = Target => ({ name }) => -
- - {name} - -
- - const Div = props =>

- - const Enhanced = doPromap(propsPreprocessor, higherOrderComponent)(Div) - - const renderer = create() - - return renderer.toJSON() - }, - - { - type: 'div', - props: {}, - children: [ - { - type: 'h1', - props: { - name: 'Radiohead' - }, - children: null - } - ] - } - ) -) diff --git a/test/internals/index.js b/test/internals/index.js index c10f256..a3f9669 100644 --- a/test/internals/index.js +++ b/test/internals/index.js @@ -1,11 +1,7 @@ import { example, suite } from '../dsl' -import doContramapSuite from './doContramap' import doMapSuite from './doMap' -import doPromapSuite from './doPromap' export default suite( 'internals', - ...doContramapSuite, ...doMapSuite, - ...doPromapSuite ) From fbfd7efe90905683fec98933b23d3398ab395024 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 17:33:25 +0200 Subject: [PATCH 05/16] Fix .map implementation to follow the laws --- src/ReactDream.js | 9 +++++---- src/internals/doMap.js | 2 -- test/ReactDream.js | 44 +++++++++++++++++++++++++++++++---------- test/index.js | 4 +--- test/internals/doMap.js | 18 ----------------- test/internals/index.js | 7 ------- 6 files changed, 40 insertions(+), 44 deletions(-) delete mode 100644 src/internals/doMap.js delete mode 100644 test/internals/doMap.js delete mode 100644 test/internals/index.js diff --git a/src/ReactDream.js b/src/ReactDream.js index 058ece2..54e6814 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -9,7 +9,6 @@ import withLog from '@hocs/with-log' import isReferentiallyTransparentFunctionComponent from './isReferentiallyTransparentFunctionComponent' -import doMap from './internals/doMap' import getRotateStyle from './helpers/getRotateStyle' import getScaleStyle from './helpers/getScaleStyle' import getTranslateStyle from './helpers/getTranslateStyle' @@ -42,9 +41,11 @@ const concat = Component => ReactDreamComponent => ) ) -// map : Component -> (Component -> Component) -> ReactDream -const map = Component => higherOrderComponent => - ReactDream(doMap(higherOrderComponent)(Component)) +// map : ReactComponent e a -> +// (ReactComponent e a -> ReactComponent e b) -> +// ReactDream (ReactComponent e b) +const map = Component => postProcessor => + ReactDream(props => postProcessor()) // contramap : ReactComponent a e -> // (a -> b) -> diff --git a/src/internals/doMap.js b/src/internals/doMap.js deleted file mode 100644 index 395b071..0000000 --- a/src/internals/doMap.js +++ /dev/null @@ -1,2 +0,0 @@ -// (Component -> Component) -> Component -> Component -export default higherOrderComponent => Component => higherOrderComponent(Component) diff --git a/test/ReactDream.js b/test/ReactDream.js index da4d6aa..243f927 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -23,17 +23,31 @@ export default suite( 'map', example( - 'runs the Component through the HoC and puts it back in a ReactDream', + 'passes the resulting element through the function', () => { - const Component = 1 - const higherOrderComponent = x => x + 1 - const EnhancedReactDreamComponent = ReactDream(Component).map(higherOrderComponent) + const Component = () =>

Hello

+ const elementProcessor = element =>

{element}

+ const EnhancedReactDreamComponent = ReactDream(Component) + .map(elementProcessor) - return EnhancedReactDreamComponent.Component + return create() + .toJSON() }, - 2 + { + type: 'h2', + props: {}, + children: [ + { + type: 'h1', + props: {}, + children: [ + 'Hello' + ] + } + ] + } ) ) ), @@ -88,7 +102,9 @@ export default suite( () => { const ReferentiallyTransparentComponent = x => !x const propsPreprocessor = () => true - const ReactDreamComponent = ReactDream(ReferentiallyTransparentComponent) + const ReactDreamComponent = ReactDream( + ReferentiallyTransparentComponent + ) return ReactDreamComponent.contramap(propsPreprocessor).Component() }, @@ -106,7 +122,10 @@ export default suite( const ReactDreamComponent = ReactDream(ReferentiallyTransparentComponent) - return ReactDreamComponent.contramap(x => x).Component.displayName + return ReactDreamComponent + .contramap(x => x) + .Component + .displayName }, 'ReferentiallyTransparentComponent' ) @@ -120,9 +139,14 @@ export default suite( const ReferentiallyTransparentComponent = x => x ReferentiallyTransparentComponent.displayName = 'Casablanca' - const ReactDreamComponent = ReactDream(ReferentiallyTransparentComponent) + const ReactDreamComponent = ReactDream( + ReferentiallyTransparentComponent + ) - return ReactDreamComponent.contramap(x => x).Component.displayName + return ReactDreamComponent + .contramap(x => x) + .Component + .displayName }, 'Casablanca' ) diff --git a/test/index.js b/test/index.js index 8497fd8..5f1823b 100644 --- a/test/index.js +++ b/test/index.js @@ -149,7 +149,6 @@ const entrypointSuite = suite( ) import createElementWithPropsSuite from './createElementWithProps' -import internalsSuite from './internals' import partialApplicationSuite from './partialApplication' import ReactDreamSuite from './ReactDream' import styleFromPropsSuite from './styleFromProps' @@ -161,8 +160,7 @@ jsDomGlobal() washington([ ...entrypointSuite, ...createElementWithPropsSuite, - ...internalsSuite, ...partialApplicationSuite, ...ReactDreamSuite, ...styleFromPropsSuite, -]) +].filter(({ description }) => /Functor: map:/.test(description))) diff --git a/test/internals/doMap.js b/test/internals/doMap.js deleted file mode 100644 index 83cc231..0000000 --- a/test/internals/doMap.js +++ /dev/null @@ -1,18 +0,0 @@ -import doMap from '../../src/internals/doMap' -import { example, suite } from '../dsl' - -export default suite( - 'doMap', - example( - 'run the component through the higher-order component', - - () => { - const Component = 1 - const higherOrderComponent = x => x + 1 - - return doMap(higherOrderComponent)(Component) - }, - - 2 - ) -) diff --git a/test/internals/index.js b/test/internals/index.js deleted file mode 100644 index a3f9669..0000000 --- a/test/internals/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { example, suite } from '../dsl' -import doMapSuite from './doMap' - -export default suite( - 'internals', - ...doMapSuite, -) From 753d7fad69a22d1c8da20fed58cfb6630a84048b Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 17:35:37 +0200 Subject: [PATCH 06/16] Fix .name implementation --- src/ReactDream.js | 5 +++-- test/index.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index 54e6814..65ace26 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -89,8 +89,9 @@ const defaultProps = Component => props => ReactDream(recomposeDefaultProps(prop // log : Component -> (Props -> String) -> IO ReactDream const log = Component => messageFromProps => ReactDream(withLog(messageFromProps)(Component)) -// name : Component -> String -> ReactDream -const name = Component => compose(map(Component), setDisplayName) +// name : ReactComponent a e -> String -> ReactDream (ReactComponent a e) +const name = Component => name => + ReactDream(setDisplayName(name)(Component)) // removeProps : Component -> (...Array) -> ReactDream const removeProps = Component => (...propsToRemove) => diff --git a/test/index.js b/test/index.js index 5f1823b..93816ce 100644 --- a/test/index.js +++ b/test/index.js @@ -163,4 +163,4 @@ washington([ ...partialApplicationSuite, ...ReactDreamSuite, ...styleFromPropsSuite, -].filter(({ description }) => /Functor: map:/.test(description))) +]) From d05ab704dc5102a9eed10b79afdc202e8be849ea Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 17:36:47 +0200 Subject: [PATCH 07/16] More cleanup --- src/ReactDream.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index 65ace26..d94a446 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -105,7 +105,8 @@ const removeProps = Component => (...propsToRemove) => }) // propTypes : Component -> (PropTypes) -> ReactDream -const propTypes = Component => propTypesToSet => ReactDream(setPropTypes(propTypesToSet)(Component)) +const propTypes = Component => propTypesToSet => + ReactDream(setPropTypes(propTypesToSet)(Component)) // translate : Component -> (Props -> [Number]) -> ReactDream const translate = Component => getTranslateFromProps => From a70ab9f51e0da2cdf34ad3579678c00821f0acc5 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Sat, 28 Jul 2018 17:49:35 +0200 Subject: [PATCH 08/16] Fix .promap implementation to follow Profunctor laws --- src/ReactDream.js | 16 ++++++++++------ test/ReactDream.js | 23 +++++++---------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index d94a446..a9478b4 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -60,11 +60,15 @@ const contramap = Component => propsPreprocessor => { return ReactDream(Enhanced) } -// doPromap : ((a -> Props), (Component -> Component)) -> Component -> Component -// // promap : Component -> (a -> Props) -> (Component -> Component) -> ReactDream -// const promap = Component => (propsPreprocessor, higherOrderComponent) => -// ReactDream(doPromap(propsPreprocessor, higherOrderComponent)(Component)) -// compose(doMap(higherOrderComponent), doContramap(propsPreprocessor)) +// promap : ReactComponent b e -> +// ((a -> b), (e -> f)) -> +// ReactDream (ReactComponent a f) +const promap = Component => (preProcessor, postProcessor) => + map( + contramap(Component)(preProcessor).Component + )( + postProcessor + ) // CUSTOM HELPERS @@ -137,7 +141,7 @@ const ReactDream = Component => ({ concat: concat(Component), contramap: contramap(Component), map: map(Component), - // promap: promap(Component), + promap: promap(Component), // Custom helpers addProps: addProps(Component), diff --git a/test/ReactDream.js b/test/ReactDream.js index 243f927..065fd33 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -282,29 +282,20 @@ export default suite( ...suite( 'promap', example( - 'passes the Component through the higher-order Component and the props preprocessor', + 'passes the Component through the post and pre processor', () => { - const propsPreprocessor = () => ({ name: 'Radiohead' }) - const higherOrderComponent = Target => ({ name }) => -
- - {name} - -
- - const Enhanced = ReactDream(props =>

).promap( - propsPreprocessor, - higherOrderComponent - ) + const preProcessor = () => ({ name: 'Radiohead' }) + const postProcessor = element =>
{element}
- const renderer = create() + const Enhanced = ReactDream(props =>

) + .promap(preProcessor, postProcessor) - return renderer.toJSON() + return create().toJSON() }, { - type: 'div', + type: 'main', props: {}, children: [ { From 7da7b1a15572cfd72eff2f281ff5eacf78127025 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Thu, 16 Aug 2018 19:04:28 +0200 Subject: [PATCH 09/16] Remove `.ap` --- api.md | 57 ++++++++++++++++++++++++++++++++++++ src/ReactDream.js | 13 +------- src/index.js | 1 - src/partialApplication/ap.js | 1 - test/ReactDream.js | 37 ----------------------- test/index.js | 7 ----- test/partialApplication.js | 2 -- 7 files changed, 58 insertions(+), 60 deletions(-) create mode 100644 api.md delete mode 100644 src/partialApplication/ap.js diff --git a/api.md b/api.md new file mode 100644 index 0000000..3787181 --- /dev/null +++ b/api.md @@ -0,0 +1,57 @@ +## API options + + +```javascript +import ReactDream, { ReactBox } from 'react-dream' + +ReactDream.Stateless(({ title }) =>

{title}

) + .map(element =>
{element}
) + .contramap(({ language }) => ({ + title: language === 'en' ? 'Hello' : 'Hola' + })) + .enhance( + withState('updateTitle', 'title', 'Hola') + ) + .name('Header') + +ReactDream.Stateful(class extends Component {}) + .map() // not optimal! + +ReactDream.Stateful(class extends Component {}) + .toStateless() + .map() // optimal but verbose + +const withChildren = (Parent, Up, Down) => + ReactDream.Stateless(({ parent, up, down }) => + + + + + ) + +withChildren( + Header, + Title, + Tagline +) + .contramap() + +// will build a Stateful +ReactDream(class extends Component {}) + +// will build a Stateless +ReactDream(props =>
) + +ReactDream(props =>
) + .asBox() + .map() + +ReactBox(props =>
) + .asDream() + .map() + +// Equivalences +ReactDream(x).enhance(f) == ReactDream(x).asBox().map(f) +ReactBox(x).map(f) == ReactDream(x).enhance(f) +ReactBox.of(f).ap(x) == ReactBox(x).map(f) +``` diff --git a/src/ReactDream.js b/src/ReactDream.js index a9478b4..000f5a5 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -17,12 +17,6 @@ import styleFromProps from './styleFromProps' // ALGEBRAS // ////////////////////////////////////////////////////////////////////////// // -// ap : (ReactComponent a e -> b) -> -// ReactDream (ReactComponent a e) -> -// ReactDream (b) -const ap = higherOrderComponent => ReactDreamComponent => - ReactDream(ReactDreamComponent.fork(higherOrderComponent)) - // chain : Component -> (Component -> ReactDream) -> ReactDream const chain = Component => kleisliReactDreamComponent => kleisliReactDreamComponent(Component) @@ -45,7 +39,7 @@ const concat = Component => ReactDreamComponent => // (ReactComponent e a -> ReactComponent e b) -> // ReactDream (ReactComponent e b) const map = Component => postProcessor => - ReactDream(props => postProcessor()) + ReactDream(x => postProcessor(Component(x))) // contramap : ReactComponent a e -> // (a -> b) -> @@ -136,7 +130,6 @@ const ReactDream = Component => ({ Component, // Algebras - ap: ap(Component), chain: chain(Component), concat: concat(Component), contramap: contramap(Component), @@ -158,8 +151,4 @@ const ReactDream = Component => ({ translate: translate(Component), }) -ReactDream.of = ReactDream - -export const of = ReactDream.of - export default ReactDream diff --git a/src/index.js b/src/index.js index 56bdd30..e35ee80 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,6 @@ export { default as createElementWithProps } from './createElementWithProps' export { default as styleFromProps } from './styleFromProps' export { default as addProps } from './partialApplication/addProps' -export { default as ap } from './partialApplication/ap' export { default as chain } from './partialApplication/chain' export { default as concat } from './partialApplication/concat' export { default as contramap } from './partialApplication/contramap' diff --git a/src/partialApplication/ap.js b/src/partialApplication/ap.js deleted file mode 100644 index 1b5d392..0000000 --- a/src/partialApplication/ap.js +++ /dev/null @@ -1 +0,0 @@ -export default f => apply => apply.ap(f) diff --git a/test/ReactDream.js b/test/ReactDream.js index 065fd33..e76e417 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -52,43 +52,6 @@ export default suite( ) ), - ...suite( - 'Apply', - ...suite( - 'ap', - example( - 'passes the argument to the component', - () => { - const ReactDreamComponent = ReactDream(x => !x) - - return ReactDreamComponent.ap(ReactDream(false)).Component - }, - true - ) - ) - ), - - ...suite( - 'Applicative', - ...suite( - 'ReactDream.of', - example( - 'wraps the Component', - () => ReactDream.of(Target).Component, - Target - ) - ), - - ...suite( - 'of - named export', - example( - 'wraps the Component', - () => of(Target).Component, - Target - ) - ) - ), - ...suite( 'Contravariant', diff --git a/test/index.js b/test/index.js index 93816ce..b9db150 100644 --- a/test/index.js +++ b/test/index.js @@ -4,7 +4,6 @@ import EntrypointReactDream, * as entrypoint from '../src' import DirectReactDream from '../src/ReactDream' import addProps from '../src/partialApplication/addProps' -import ap from '../src/partialApplication/ap' import chain from '../src/partialApplication/chain' import concat from '../src/partialApplication/concat' import contramap from '../src/partialApplication/contramap' @@ -39,12 +38,6 @@ const entrypointSuite = suite( entrypoint.addProps ), - example( - 'exposes ap', - () => ap, - entrypoint.ap - ), - example( 'exposes chain', () => chain, diff --git a/test/partialApplication.js b/test/partialApplication.js index 9e21e0a..30c731e 100644 --- a/test/partialApplication.js +++ b/test/partialApplication.js @@ -1,6 +1,5 @@ import { example, suite } from './dsl' import addProps from '../src/partialApplication/addProps' -import ap from '../src/partialApplication/ap' import chain from '../src/partialApplication/chain' import concat from '../src/partialApplication/concat' import contramap from '../src/partialApplication/contramap' @@ -23,7 +22,6 @@ export default suite( ...[ ['addProps', addProps], - ['ap', ap], ['chain', chain], ['concat', concat], ['contramap', contramap], From fa93fa5759dbd83c2abc4b28c61fb1933ee7d01f Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Thu, 16 Aug 2018 19:41:41 +0200 Subject: [PATCH 10/16] .of --- src/index.js | 2 -- test/ReactDream.js | 2 +- test/index.js | 6 ------ 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/index.js b/src/index.js index e35ee80..bb21434 100644 --- a/src/index.js +++ b/src/index.js @@ -22,6 +22,4 @@ export { default as scale } from './partialApplication/scale' export { default as style } from './partialApplication/style' export { default as translate } from './partialApplication/translate' -export const of = ReactDream - export default ReactDream diff --git a/test/ReactDream.js b/test/ReactDream.js index e76e417..e785ed9 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import { create } from 'react-test-renderer' -import ReactDream, { of } from '../src/ReactDream' +import ReactDream from '../src/ReactDream' import { example, suite } from './dsl' const Target = x => x diff --git a/test/index.js b/test/index.js index b9db150..e5d851b 100644 --- a/test/index.js +++ b/test/index.js @@ -133,12 +133,6 @@ const entrypointSuite = suite( () => translate, entrypoint.translate ), - - example( - 'exposes of', - () => DirectReactDream, - entrypoint.of - ) ) import createElementWithPropsSuite from './createElementWithProps' From 9c6c1cb9d5ed734d323899768b3951f2e03c9532 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Fri, 17 Aug 2018 23:23:16 +0200 Subject: [PATCH 11/16] Cleanup --- src/ReactDream.js | 10 ++++++++-- src/index.js | 2 -- src/styleFromProps.js | 8 -------- test/index.js | 2 -- test/styleFromProps.js | 45 ------------------------------------------ 5 files changed, 8 insertions(+), 59 deletions(-) delete mode 100644 src/styleFromProps.js delete mode 100644 test/styleFromProps.js diff --git a/src/ReactDream.js b/src/ReactDream.js index 000f5a5..e8cf313 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -12,7 +12,6 @@ import isReferentiallyTransparentFunctionComponent from './isReferentiallyTransp import getRotateStyle from './helpers/getRotateStyle' import getScaleStyle from './helpers/getScaleStyle' import getTranslateStyle from './helpers/getTranslateStyle' -import styleFromProps from './styleFromProps' // ALGEBRAS // ////////////////////////////////////////////////////////////////////////// // @@ -120,7 +119,14 @@ const scale = Component => getScaleFromProps => // style : Component -> (Props -> Style) -> ReactDream const style = Component => getStyleFromProps => - contramap(Component)(styleFromProps(getStyleFromProps)) + contramap(Component)(props => ({ + ...props, + style: { + ...getStyleFromProps(props), + ...(props.style || {}), + }, + })) + // TYPE // ////////////////////////////////////////////////////////////////////////// // diff --git a/src/index.js b/src/index.js index bb21434..75f0323 100644 --- a/src/index.js +++ b/src/index.js @@ -2,8 +2,6 @@ import ReactDream from './ReactDream' export { default as createElementWithProps } from './createElementWithProps' -export { default as styleFromProps } from './styleFromProps' - export { default as addProps } from './partialApplication/addProps' export { default as chain } from './partialApplication/chain' export { default as concat } from './partialApplication/concat' diff --git a/src/styleFromProps.js b/src/styleFromProps.js deleted file mode 100644 index 4985500..0000000 --- a/src/styleFromProps.js +++ /dev/null @@ -1,8 +0,0 @@ -// styleFromProps : (Props -> Style) -> (Props -> Props) -export default getStyleFromProps => props => ({ - ...props, - style: { - ...getStyleFromProps(props), - ...(props.style || {}), - }, -}) diff --git a/test/index.js b/test/index.js index e5d851b..88dc9c9 100644 --- a/test/index.js +++ b/test/index.js @@ -138,7 +138,6 @@ const entrypointSuite = suite( import createElementWithPropsSuite from './createElementWithProps' import partialApplicationSuite from './partialApplication' import ReactDreamSuite from './ReactDream' -import styleFromPropsSuite from './styleFromProps' import jsDomGlobal from 'jsdom-global' @@ -149,5 +148,4 @@ washington([ ...createElementWithPropsSuite, ...partialApplicationSuite, ...ReactDreamSuite, - ...styleFromPropsSuite, ]) diff --git a/test/styleFromProps.js b/test/styleFromProps.js deleted file mode 100644 index b6be5c5..0000000 --- a/test/styleFromProps.js +++ /dev/null @@ -1,45 +0,0 @@ -import { example, suite } from './dsl' -import styleFromProps from '../src/styleFromProps' - -export default suite( - 'styleFromProps', - - example( - 'sets the `style` prop with the return value', - - () => styleFromProps( - ({ hovered }) => ({ - backgroundColor: hovered ? 'blue' : 'black', - }) - )({ hovered: true }), - - { - hovered: true, - style: { - backgroundColor: 'blue' - } - } - ), - - example( - 'merges the `style` prop with existing value', - - () => styleFromProps( - ({ hovered }) => ({ - backgroundColor: hovered ? 'blue' : 'black', - color: 'green', - }) - )({ - hovered: true, - style: { backgroundColor: 'lightblue' } - }), - - { - hovered: true, - style: { - backgroundColor: 'lightblue', - color: 'green', - } - } - ) -) From 3e57ff2019753016a223dc0f5c2fd6cf3b6863f4 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Tue, 21 Aug 2018 23:10:00 +0200 Subject: [PATCH 12/16] Introduce Stateless & Stateful constructors, and adapt Stateless contramap --- src/ReactDream.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- test/ReactDream.js | 41 ----------------------------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index e8cf313..3dfe695 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -40,6 +40,12 @@ const concat = Component => ReactDreamComponent => const map = Component => postProcessor => ReactDream(x => postProcessor(Component(x))) +// statelessContramap : ReactComponent a e -> +// (a -> b) -> +// ReactDream (ReactComponent b e) +const statelessContramap = Component => propsPreprocessor => + Stateless(compose(Component, propsPreprocessor)) + // contramap : ReactComponent a e -> // (a -> b) -> // ReactDream (ReactComponent b e) @@ -131,8 +137,34 @@ const style = Component => getStyleFromProps => // TYPE // ////////////////////////////////////////////////////////////////////////// // -// ReactDream : Component -> ReactDream -const ReactDream = Component => ({ +// Stateless : Component -> ReactDream +const Stateless = Component => ({ + Component, + + // Algebras + chain: chain(Component), + concat: concat(Component), + contramap: statelessContramap(Component), + map: map(Component), + promap: promap(Component), + + // Custom helpers + addProps: addProps(Component), + debug: debug(Component), + defaultProps: defaultProps(Component), + fork: fork(Component), + name: name(Component), + log: log(Component), + propTypes: propTypes(Component), + removeProps: removeProps(Component), + rotate: rotate(Component), + scale: scale(Component), + style: style(Component), + translate: translate(Component), +}) + +// Stateful : Component -> ReactDream +const Stateful = Component => ({ Component, // Algebras @@ -157,4 +189,13 @@ const ReactDream = Component => ({ translate: translate(Component), }) +// LIFTER +// /////////////////////////////////////////////////////////////////////////////////// // + +// ReactDream : Component -> ReactDream +const ReactDream = Component => + isReferentiallyTransparentFunctionComponent(Component) + ? Stateless(Component) + : Stateful(Component) + export default ReactDream diff --git a/test/ReactDream.js b/test/ReactDream.js index e785ed9..02cbb3a 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -73,49 +73,8 @@ export default suite( }, false ), - - ...suite( - 'it has name', - example( - 'preserves the name as displayName', - () => { - function ReferentiallyTransparentComponent(x) { - return x - } - - const ReactDreamComponent = ReactDream(ReferentiallyTransparentComponent) - - return ReactDreamComponent - .contramap(x => x) - .Component - .displayName - }, - 'ReferentiallyTransparentComponent' - ) ), - ...suite( - 'it has displayName', - example( - 'preserves it', - () => { - const ReferentiallyTransparentComponent = x => x - ReferentiallyTransparentComponent.displayName = 'Casablanca' - - const ReactDreamComponent = ReactDream( - ReferentiallyTransparentComponent - ) - - return ReactDreamComponent - .contramap(x => x) - .Component - .displayName - }, - 'Casablanca' - ) - ) - ), - ...suite( 'is not referentially transparent', example( From 2bf555310c30191e8a9ffbf7be51b34030bb4176 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Wed, 22 Aug 2018 10:36:39 +0200 Subject: [PATCH 13/16] Make Stateless promap work --- src/ReactDream.js | 25 +++++++++-------- test/ReactDream.js | 70 +--------------------------------------------- test/index.js | 4 ++- 3 files changed, 18 insertions(+), 81 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index 3dfe695..82f4d12 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -46,18 +46,21 @@ const map = Component => postProcessor => const statelessContramap = Component => propsPreprocessor => Stateless(compose(Component, propsPreprocessor)) -// contramap : ReactComponent a e -> +// statefulContramap : ReactComponent a e -> // (a -> b) -> // ReactDream (ReactComponent b e) -const contramap = Component => propsPreprocessor => { - const Enhanced = isReferentiallyTransparentFunctionComponent(Component) - ? compose(Component, propsPreprocessor) - : props => +const statefulContramap = Component => propsPreprocessor => + Stateful(props => ) - Enhanced.displayName = getDisplayName(Component) - - return ReactDream(Enhanced) -} +// statelessPromap : ReactComponent b e -> +// ((a -> b), (e -> f)) -> +// ReactDream (ReactComponent a f) +const statelessPromap = Component => (preProcessor, postProcessor) => + map( + statelessContramap(Component)(preProcessor).Component + )( + postProcessor + ) // promap : ReactComponent b e -> // ((a -> b), (e -> f)) -> @@ -146,7 +149,7 @@ const Stateless = Component => ({ concat: concat(Component), contramap: statelessContramap(Component), map: map(Component), - promap: promap(Component), + promap: statelessPromap(Component), // Custom helpers addProps: addProps(Component), @@ -170,7 +173,7 @@ const Stateful = Component => ({ // Algebras chain: chain(Component), concat: concat(Component), - contramap: contramap(Component), + contramap: statefulContramap(Component), map: map(Component), promap: promap(Component), diff --git a/test/ReactDream.js b/test/ReactDream.js index 02cbb3a..73f3495 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -73,7 +73,7 @@ export default suite( }, false ), - ), + ), ...suite( 'is not referentially transparent', @@ -111,74 +111,6 @@ export default suite( [ 'Regina Spektor' ] ), - ...suite( - 'it has name', - example( - 'preserves the name as displayName', - - () => { - class NotReferentiallyTransparent extends Component { - constructor() { - super() - - this.state = {} - } - - render() { - return ( -
- {this.props.name} -
- ) - } - } - - const propsPreprocesssor = () => ({ name: 'Regina Spektor' }) - - const ReactDreamComponent = ReactDream(NotReferentiallyTransparent) - - const Enhanced = ReactDreamComponent.contramap(propsPreprocesssor) - - return Enhanced.Component.displayName - }, - 'NotReferentiallyTransparent' - ) - ), - - ...suite( - 'it has displayName', - example( - 'preserves it', - () => { - class NotReferentiallyTransparent extends Component { - constructor() { - super() - - this.state = {} - } - - render() { - return ( -
- {this.props.name} -
- ) - } - } - - NotReferentiallyTransparent.displayName = 'BeginToHope' - - const propsPreprocesssor = () => ({ name: 'Regina Spektor' }) - - const ReactDreamComponent = ReactDream(NotReferentiallyTransparent) - - const Enhanced = ReactDreamComponent.contramap(propsPreprocesssor) - - return Enhanced.Component.displayName - }, - 'BeginToHope' - ) - ) ) ) ), diff --git a/test/index.js b/test/index.js index 88dc9c9..ef2974a 100644 --- a/test/index.js +++ b/test/index.js @@ -143,9 +143,11 @@ import jsDomGlobal from 'jsdom-global' jsDomGlobal() +const filter = ({ description }) => !/style|removeProps|rotate|scale|translate|addProps/.test(description) + washington([ ...entrypointSuite, ...createElementWithPropsSuite, ...partialApplicationSuite, - ...ReactDreamSuite, + ...ReactDreamSuite.filter(filter), ]) From 168951bbbde1e21844a8c68e9d7d5f42e1af21dc Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Wed, 22 Aug 2018 21:15:10 +0200 Subject: [PATCH 14/16] Test Stateless and Stateful data constructors separately --- src/ReactDream.js | 4 ++-- test/ReactDream.js | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index 82f4d12..c1f9303 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -141,7 +141,7 @@ const style = Component => getStyleFromProps => // ////////////////////////////////////////////////////////////////////////// // // Stateless : Component -> ReactDream -const Stateless = Component => ({ +export const Stateless = Component => ({ Component, // Algebras @@ -167,7 +167,7 @@ const Stateless = Component => ({ }) // Stateful : Component -> ReactDream -const Stateful = Component => ({ +export const Stateful = Component => ({ Component, // Algebras diff --git a/test/ReactDream.js b/test/ReactDream.js index 73f3495..6c12ab3 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' import { create } from 'react-test-renderer' -import ReactDream from '../src/ReactDream' +import ReactDream, { Stateless, Stateful } from '../src/ReactDream' import { example, suite } from './dsl' const Target = x => x @@ -8,12 +8,38 @@ const Target = x => x export default suite( 'ReactDream', - example( - 'wraps the Component', + ...suite( + 'Stateless', - () => ReactDream(Target).Component, + example( + 'Provides access to the component via .Component', + + () => Stateless(Target).Component, + + Target + ), + ), + ...suite( + 'Stateful', - Target + example( + 'Provides access to the component via .Component', + + () => Stateful(Target).Component, + + Target + ), + ), + ...suite( + 'Entrypoint', + + example( + 'Provides access to the component via .Component', + + () => ReactDream(Target).Component, + + Target + ), ), ...suite( From 491a5c0d14c54ac4da7c97c24ed3df4f5049cc76 Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Wed, 22 Aug 2018 21:23:06 +0200 Subject: [PATCH 15/16] Update washington version and use DSL from it directly --- package.json | 2 +- test/ReactDream.js | 2 +- test/createElementWithProps.js | 2 +- test/dsl.js | 5 ----- test/index.js | 3 +-- test/partialApplication.js | 2 +- yarn.lock | 27 ++++++++++++++++----------- 7 files changed, 21 insertions(+), 22 deletions(-) delete mode 100644 test/dsl.js diff --git a/package.json b/package.json index f5e6c5a..11495bb 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "react": "^16.0.0", "react-test-renderer": "^16.0.0", "recompose": "^0.24.0", - "washington": "^2.0.0-rc.3" + "washington": "^2.0.0-rc.5" }, "peerDependencies": { "react": "^16.0.0", diff --git a/test/ReactDream.js b/test/ReactDream.js index 6c12ab3..9f1a54b 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import { create } from 'react-test-renderer' import ReactDream, { Stateless, Stateful } from '../src/ReactDream' -import { example, suite } from './dsl' +import { example, suite } from 'washington' const Target = x => x diff --git a/test/createElementWithProps.js b/test/createElementWithProps.js index 23fe559..28dcd78 100644 --- a/test/createElementWithProps.js +++ b/test/createElementWithProps.js @@ -2,7 +2,7 @@ import React from 'react' import { create } from 'react-test-renderer' import { pick } from 'ramda' import createElementWithProps from '../src/createElementWithProps' -import { suite, example } from './dsl' +import { suite, example } from 'washington' export default suite( diff --git a/test/dsl.js b/test/dsl.js deleted file mode 100644 index cb24b67..0000000 --- a/test/dsl.js +++ /dev/null @@ -1,5 +0,0 @@ -export const suite = (name, ...suite) => - suite.map(x => ({...x, description: `${name}: ${x.description}`})) - -export const example = (description, test, shouldEqual) => - ({ description, test, shouldEqual }) diff --git a/test/index.js b/test/index.js index ef2974a..5735a20 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,4 @@ -import washington from 'washington' +import washington, { example, suite } from 'washington' import EntrypointReactDream, * as entrypoint from '../src' @@ -21,7 +21,6 @@ import scale from '../src/partialApplication/scale' import style from '../src/partialApplication/style' import translate from '../src/partialApplication/translate' -import { example, suite } from './dsl' const entrypointSuite = suite( 'entrypoint', diff --git a/test/partialApplication.js b/test/partialApplication.js index 30c731e..8acc683 100644 --- a/test/partialApplication.js +++ b/test/partialApplication.js @@ -1,4 +1,4 @@ -import { example, suite } from './dsl' +import { example, suite } from 'washington' import addProps from '../src/partialApplication/addProps' import chain from '../src/partialApplication/chain' import concat from '../src/partialApplication/concat' diff --git a/yarn.lock b/yarn.lock index f8d78e2..d135d33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2186,29 +2186,34 @@ w3c-hr-time@^1.0.1: dependencies: browser-process-hrtime "^0.1.2" -washington.core@^2.0.0-rc.3: - version "2.0.0-rc.3" - resolved "https://registry.yarnpkg.com/washington.core/-/washington.core-2.0.0-rc.3.tgz#e9b52f736f177961fa962160f9810d4068c2db01" +washington.core@^2.0.0-rc.4: + version "2.0.0-rc.4" + resolved "https://registry.yarnpkg.com/washington.core/-/washington.core-2.0.0-rc.4.tgz#1c845f68827a91d92d386119ce20ff405b6a11d7" dependencies: folktale "^v2.0.0-rc1" immutable "^3.8.1" immutable-ext "^1.0.8" partial.lenses "^9.4.1" -washington.formatter.terminal@^2.0.0-rc.3: - version "2.0.0-rc.3" - resolved "https://registry.yarnpkg.com/washington.formatter.terminal/-/washington.formatter.terminal-2.0.0-rc.3.tgz#da80f5a8faa4d56a6d7297783e55d657c41e7417" +washington.dsl@^2.0.0-rc.5: + version "2.0.0-rc.5" + resolved "https://registry.yarnpkg.com/washington.dsl/-/washington.dsl-2.0.0-rc.5.tgz#7d2b7c381445a8539d68b60df6b70b043eff295a" + +washington.formatter.terminal@^2.0.0-rc.4: + version "2.0.0-rc.4" + resolved "https://registry.yarnpkg.com/washington.formatter.terminal/-/washington.formatter.terminal-2.0.0-rc.4.tgz#d3b8b80a3e8a68a7c15c198abba9d883f8880fc9" dependencies: chalk "^1.1.3" folktale "^v2.0.0-rc1" partial.lenses "^9.4.1" -washington@^2.0.0-rc.3: - version "2.0.0-rc.3" - resolved "https://registry.yarnpkg.com/washington/-/washington-2.0.0-rc.3.tgz#40d40ef0dde10563f9f469e8ed38a25feae1baf7" +washington@^2.0.0-rc.5: + version "2.0.0-rc.5" + resolved "https://registry.yarnpkg.com/washington/-/washington-2.0.0-rc.5.tgz#a4baf5cf32afc25b2d0e160733a18ef4d31e866d" dependencies: - washington.core "^2.0.0-rc.3" - washington.formatter.terminal "^2.0.0-rc.3" + washington.core "^2.0.0-rc.4" + washington.dsl "^2.0.0-rc.5" + washington.formatter.terminal "^2.0.0-rc.4" webidl-conversions@^4.0.2: version "4.0.2" From 7b0ea230eaa4944574747c0f4a1804c78ee70b9f Mon Sep 17 00:00:00 2001 From: Xavier Via Date: Wed, 22 Aug 2018 22:49:46 +0200 Subject: [PATCH 16/16] Ensure the data constructors are exposed, and that the lifter lifts correctly --- src/ReactDream.js | 14 ++++++++++++++ src/index.js | 4 +++- test/ReactDream.js | 37 +++++++++++++++++++++++++++++++++++++ test/index.js | 17 ++++++++++++++++- 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/ReactDream.js b/src/ReactDream.js index c1f9303..d0b9f16 100644 --- a/src/ReactDream.js +++ b/src/ReactDream.js @@ -151,6 +151,13 @@ export const Stateless = Component => ({ map: map(Component), promap: statelessPromap(Component), + // Type + constructor: ReactDream, + match: ({ Stateless, _ }) => + Stateless !== undefined + ? Stateless(Component) + : _(), + // Custom helpers addProps: addProps(Component), debug: debug(Component), @@ -177,6 +184,13 @@ export const Stateful = Component => ({ map: map(Component), promap: promap(Component), + // Type + constructor: ReactDream, + match: ({ Stateful, _ }) => + Stateful !== undefined + ? Stateful(Component) + : _(), + // Custom helpers addProps: addProps(Component), debug: debug(Component), diff --git a/src/index.js b/src/index.js index 75f0323..4027667 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import ReactDream from './ReactDream' +import ReactDream, { Stateless as _Stateless, Stateful as _Stateful } from './ReactDream' export { default as createElementWithProps } from './createElementWithProps' @@ -20,4 +20,6 @@ export { default as scale } from './partialApplication/scale' export { default as style } from './partialApplication/style' export { default as translate } from './partialApplication/translate' +export const Stateless = _Stateless +export const Stateful = _Stateful export default ReactDream diff --git a/test/ReactDream.js b/test/ReactDream.js index 9f1a54b..d61040c 100644 --- a/test/ReactDream.js +++ b/test/ReactDream.js @@ -18,7 +18,16 @@ export default suite( Target ), + + example( + 'Provides access to the type representative via .constructor', + + () => Stateless(Target).constructor, + + ReactDream + ), ), + ...suite( 'Stateful', @@ -29,7 +38,16 @@ export default suite( Target ), + + example( + 'Provides access to the type representative via .constructor', + + () => Stateful(Target).constructor, + + ReactDream + ), ), + ...suite( 'Entrypoint', @@ -40,6 +58,25 @@ export default suite( Target ), + + example( + 'Builds a Stateless when referentially transparent', + + () => ReactDream(() =>
).match({ Stateless: () => true }), + + true + ), + + example( + 'Builds a Stateful when class component', + + () => ReactDream( + class extends Component { render () { return
} } + ) + .match({ Stateful: () => true }), + + true + ), ), ...suite( diff --git a/test/index.js b/test/index.js index 5735a20..4dd6e6f 100644 --- a/test/index.js +++ b/test/index.js @@ -2,7 +2,10 @@ import washington, { example, suite } from 'washington' import EntrypointReactDream, * as entrypoint from '../src' -import DirectReactDream from '../src/ReactDream' +import DirectReactDream, { + Stateless as DirectStateless, + Stateful as DirectStateful +} from '../src/ReactDream' import addProps from '../src/partialApplication/addProps' import chain from '../src/partialApplication/chain' import concat from '../src/partialApplication/concat' @@ -31,6 +34,18 @@ const entrypointSuite = suite( EntrypointReactDream ), + example( + 'exposes Stateless', + () => DirectStateless, + entrypoint.Stateless + ), + + example( + 'exposes Stateful', + () => DirectStateful, + entrypoint.Stateful + ), + example( 'exposes addProps', () => addProps,