{"id":16092924,"url":"https://github.com/xaviervia/react-dream","last_synced_at":"2025-04-09T22:11:29.995Z","repository":{"id":40813345,"uuid":"99415645","full_name":"xaviervia/react-dream","owner":"xaviervia","description":"Fantasy Land type for React Components","archived":false,"fork":false,"pushed_at":"2023-01-12T09:55:42.000Z","size":553,"stargazers_count":188,"open_issues_count":15,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-09T22:11:25.479Z","etag":null,"topics":["fantasy-land","react"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xaviervia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-05T10:22:22.000Z","updated_at":"2024-11-11T17:36:59.000Z","dependencies_parsed_at":"2023-02-09T11:15:50.119Z","dependency_job_id":null,"html_url":"https://github.com/xaviervia/react-dream","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaviervia%2Freact-dream","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaviervia%2Freact-dream/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaviervia%2Freact-dream/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaviervia%2Freact-dream/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xaviervia","download_url":"https://codeload.github.com/xaviervia/react-dream/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248119294,"owners_count":21050755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fantasy-land","react"],"created_at":"2024-10-09T16:44:29.148Z","updated_at":"2025-04-09T22:11:29.971Z","avatar_url":"https://github.com/xaviervia.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![react-dream-logo](banner.png)\n\n# React Dream\n\n[![Build Status](https://travis-ci.org/xaviervia/react-dream.svg)](https://travis-ci.org/xaviervia/react-dream)\n[![npm version](https://img.shields.io/npm/v/react-dream.svg?maxAge=1000)](https://www.npmjs.com/package/react-dream)\n\n[Fantasy Land](https://github.com/fantasyland/fantasy-land) type for [React Components](https://facebook.github.io/react/)\n\n**Caution: Experimental** (not _extremely_ anymore though)\n\n## Installation\n\n```\nnpm add react-dream\n```\n\nYou will also need a couple of peer dependencies:\n\n```\nnpm add react recompose\n```\n\n## Table of contents\n\n- [Usage](#usage)\n- [API](#api)\n  - [map](#mapcomponent--enhancedcomponent)\n  - [contramap](#contramapprops--modifiedprops)\n  - [promap](#promapprops--modifiedprops-component--enhancedcomponent)\n  - [ap + of](#ap--of)\n  - [concat](#concat)\n  - [chain](#chain)\n  - [fork](#forkcomponent--)\n  - [addProps](#addpropsprops--propstoadd--object)\n  - [removeProps](#removepropspropnamestoremove--string)\n  - [defaultProps](#defaultpropsprops--object)\n  - [propTypes](#proptypesproptypes--object)\n  - [style](#styleprops--stylestoadd--object)\n  - [name](#namenewdisplayname--string)\n  - [rotate](#rotateprops--rotation--number)\n  - [scale](#scaleprops--scalefactor--number)\n  - [translate](#translateprops--x--number-y--number-z--number)\n  - [log](#logprops--value--any)\n  - [debug](#debug)\n- [Built-in primitives](#built-in-primitives)\n\n## Usage\n\n### Lifting React components into ReactDream\n\nFor example, for a ReactNative View:\n\n```js\nimport ReactDream from 'react-dream'\nimport { View } from 'react-native'\n\nconst DreamView = ReactDream(View)\n```\n\n…or for a web `div`:\n\n```js\nimport React from 'react'\nimport ReactDream from 'react-dream'\n\nconst DreamView = ReactDream(props =\u003e \u003cdiv {...props} /\u003e)\n```\n\n### Complete example\n\nHere is an extensive example that can be found in [examples](https://github.com/xaviervia/react-dream-examples/blob/master/pages/index.js):\n\n\u003e If you are not familiar with Fantasy Land types, I can highly recommend the [video tutorials by Brian Lonsdorf](https://egghead.io/instructors/brian-lonsdorf)\n\n\u003e Note that this and the following examples use already-built wrappers that you can pull from [react-dream-web-builtins](https://github.com/xaviervia/react-dream-web-builtins). This are convenient but might not be easy to tree shake when bundling, so use with caution.\n\n```js\nimport React from 'react'\nimport { render } from 'react-dom'\nimport { withHandlers, withState } from 'recompose'\nimport { of } from 'react-dream'\nimport { Html } from 'react-dream-web-builtins'\n\nconst withChildren = North =\u003e South =\u003e Wrapper =\u003e ({ north, south, wrapper, ...props }) =\u003e\n  \u003cWrapper { ...props } { ...wrapper }}\u003e\n    \u003cNorth { ...props } { ...north }} /\u003e\n    \u003cSouth { ...props } { ...south }} /\u003e\n  \u003c/Wrapper\u003e\n\nconst Title = Html.H1\n  .style(() =\u003e ({\n    fontFamily: 'sans-serif',\n    fontSize: 18,\n  }))\n  .name('Title')\n\nconst Tagline = Html.P\n  .style(() =\u003e ({\n    fontFamily: 'sans-serif',\n    fontSize: 13,\n  }))\n  .name('Tagline')\n\nconst HeaderWrapper = Html.Header\n  .removeProps('clicked', 'updateClicked')\n  .style(({ clicked }) =\u003e ({\n    backgroundColor: clicked ? 'red' : 'green',\n    cursor: 'pointer',\n    padding: 15,\n  }))\n  .name('HeaderWrapper')\n  .map(\n    withHandlers({\n      onClick: ({ clicked, updateClicked }) =\u003e () =\u003e updateClicked(!clicked),\n    })\n  )\n  .map(withState('clicked', 'updateClicked', false))\n\nconst Header = of(withChildren)\n  .ap(Title)\n  .ap(Tagline)\n  .ap(HeaderWrapper)\n  .contramap(({ title, tagline }) =\u003e ({\n    north: { children: title },\n    south: { children: tagline },\n  }))\n  .name('Header')\n\nHeader.fork(Component =\u003e\n  render(\n    \u003cComponent\n      title=\"Hello World\"\n      tagline=\"Of Fantasy Land Types for React\"\n    /\u003e,\n    document.getElementById('root')\n  )\n)\n```\n\nRender part could also be written:\n\n```js\nrender(\n  \u003cHeader.Component\n    title=\"Hello World\"\n    tagline=\"Of Fantasy Land Types for React\"\n  /\u003e,\n  document.getElementById('root')\n)\n```\n\n### Pointfree style\n\nAll methods of `ReactDream` are available as functions that can be partially applied and then take the ReactDream component as the last argument. This makes it possible to write compositions that can then be applied to a ReactDream object. The elements of the example above could be rewritten as:\n\n```js\nimport React from 'react'\nimport { render } from 'react-dom'\nimport { compose, withHandlers, withState } from 'recompose'\nimport { ap, removeProps, contramap, map, name, of, style } from 'react-dream'\nimport { Html } from 'react-dream-web-builtins'\n\nconst withChildren = North =\u003e South =\u003e Wrapper =\u003e ({ north, south, wrapper, ...props }) =\u003e\n  \u003cWrapper { ...props } { ...wrapper }}\u003e\n    \u003cNorth { ...props } { ...north }} /\u003e\n    \u003cSouth { ...props } { ...south }} /\u003e\n  \u003c/Wrapper\u003e\n\nconst Title = compose(\n  name('Title'),\n  style(() =\u003e ({\n    fontFamily: 'sans-serif',\n    fontSize: 18,\n  }))\n)(Html.H1)\n\nconst Tagline = compose(\n  name('Tagline'),\n  style(() =\u003e ({\n    fontFamily: 'sans-serif',\n    fontSize: 13,\n  }))\n)(Html.P)\n\nconst HeaderWrapper = compose(\n  map(withState('clicked', 'updateClicked', false)),\n  map(\n    withHandlers({\n      onClick: ({ clicked, updateClicked }) =\u003e () =\u003e updateClicked(!clicked),\n    })\n  ),\n  name('HeaderWrapper'),\n  style(({ clicked }) =\u003e ({\n    backgroundColor: clicked ? 'red' : 'green',\n    cursor: 'pointer',\n    padding: 15,\n  })),\n  removeProps('clicked', 'updateClicked')\n)(Html.Header)\n\nconst Header = compose(\n  name('Header'),\n  contramap(({ title, tagline }) =\u003e ({\n    north: { children: title },\n    south: { children: tagline },\n  })),\n  ap(HeaderWrapper),\n  ap(Tagline),\n  ap(Title)\n)(of(withChildren))\n```\n\n## API\n\nThe following are the methods of objects of the ReactDream type. There are two types of methods:\n\n- Algebras: they come from Fantasy Land, and they are defined following that specification.\n- Helpers: they are derivations (use cases) of the methods that come from the algebras. Added for convenience.\n\nReactDream implements these Fantasy Land algebras:\n\n- Profunctor (map, contramap, promap)\n- Applicative (of, ap)\n- Semigroup (concat)\n- Monad (chain)\n\nCheck [Fantasy Land](https://github.com/fantasyland/fantasy-land) for more details.\n\n### map(Component =\u003e EnhancedComponent)\n\n`map` allows to wrap the function with regular higher-order components, such as the ones provided by [recompose](https://github.com/acdlite/recompose).\n\n```js\nimport React from 'react'\nimport ReactDream from 'react-dream'\nimport { withHandlers, withState } from 'recompose'\n\nconst Counter = ReactDream(({counter, onClick}) =\u003e\n  \u003cdiv\u003e\n    \u003cbutton onClick={onClick}\u003eAdd 1\u003c/button\u003e\n    \u003cp\u003e{counter}\u003c/p\u003e\n  \u003c/div\u003e\n)\n  .map(\n    withHandlers({\n      onClick: ({ counter, updateCount }) =\u003e () =\u003e updateCount(counter + 1),\n    })\n  )\n  .map(withState('counter', 'updateCount', 0))\n```\n\nThis is because `map` expects a function from `a -\u003e b` in the general case but from `Component -\u003e a` in this particular case since holding components is the intended usage of ReactDream. Higher-order components are functions from `Component -\u003e Component`, so they perfectly fit the bill.\n\n### contramap(props =\u003e modifiedProps)\n\n`contramap` allows to preprocess props before they reach the component.\n\n```js\nconst Title = H1\n  .contramap(({label}) =\u003e ({\n    children: label\n  }))\n  .name('Title')\n\nrender(\n  \u003cTitle.Component\n    label='This will be the content now'\n  /\u003e,\n  domElement\n)\n```\n\nThis is a common pattern for higher-order Components, and the key advantage of using `contramap` instead of `map` for this purpose is that if the wrapped component is a stateless, function component, you avoid an unnecessary call to React. Another advantage is that functions passed to `contramap` as an argument are simply pure functions, without mentioning React at all, with the signature `Props -\u003e Props`.\n\n### promap(props =\u003e modifiedProps, Component =\u003e EnhancedComponent)\n\n`promap` can be thought of as a shorthand for doing `contramap` and `map` at the same time. The first argument to it is the function that is going to be used to `contramap` and the second is the one to be used to `map`:\n\n```js\nconst Header = Html.Div\n  .promap(\n    ({title}) =\u003e ({children: title}),\n    setDisplayName('Header')\n  )\n```\n\n### ap + of\n\n`ap` allows you to apply a higher-order components to regular components, and `of` allows you to lift any value to `ReactDream`, which is useful for lifting higher-order components.\n\nApplying second-order components (`Component -\u003e Component`) can also be done with `map`: where `ap` shines is in allowing you to apply a higher-order component that takes two or more components (third or higher order, such as `Component -\u003e Component -\u003e Component -\u003e Component`), that is otherwise not possible with `map`. This makes it possible to abstract control flow or composition patterns in higher-order components:\n\n**Control flow example**\n\n```js\nconst eitherLeftOrRight = Left =\u003e Right =\u003e ({left, ...props}) =\u003e\n  left\n    ? \u003cLeft {...props} /\u003e\n    : \u003cRight {...props} /\u003e\n\nconst TitleOrSubtitle = of(eitherLeftOrRight)\n  .ap(Html.H1)\n  .ap(Html.H2)\n  .addProps({isTitle} =\u003e ({\n    left: isTitle\n  }))\n\nrender(\n  \u003cTitleOrSubtitle.Component isTitle={true}\u003e\n    This will be an H1 title\n  \u003c/TitleOrSubtitle.Component\u003e\n  , domElement\n)\n```\n\n**Parent-children pattern example**\n\n```js\nconst withChildren = North =\u003e South =\u003e Wrapper =\u003e ({north, south, wrapper, ...props}) =\u003e\n  \u003cWrapper { ...props } { ...wrapper }}\u003e\n    \u003cNorth { ...props } { ...north }} /\u003e\n    \u003cSouth { ...props } { ...south }} /\u003e\n  \u003c/Wrapper\u003e\n\nconst PageHeader = of(withChildren)\n  .ap(Html.H1)\n  .ap(Html.P)\n  .ap(Html.Header)\n  .addProps({title, subtitle} =\u003e ({\n    north: { children: title },\n    south: { children: subtitle },\n  }))\n\nrender(\n  \u003cPageHeader.Component\n    title='Hello World'\n    subtitle='Lorem ipsum dolor sit amet et consectetur'\n  /\u003e\n  , domElement\n)\n```\n\n### concat\n\n\u003e Requires React 16+\n\n`concat` constructs a new component that wraps the current component and another one being passed as siblings, passing the props to both of them. For example:\n\n```js\nimport { Html } from 'react-dream'\n\nconst Header = Html.H1\n  .concat(Html.P)\n```\n\nSince props are passed to both elements in the composition, invoking the above defined `Header` like this:\n\n```js\n\u003cHeader.Component\u003eHello\u003c/Header.Component\u003e\n```\n\n…will result in:\n\n```html\n\u003ch1\u003eHello\u003c/h1\u003e\n\u003cp\u003eHello\u003c/p\u003e\n```\n\nSo to make concatenation more useful, it is necessary for the elements to be configured to capture the props that are useful for them:\n\n```js\nimport { Html } from 'react-dream'\n\nconst Header = Html.H1\n  .contramap(({title}) =\u003e ({children: title}))\n  .concat(\n    Html.P\n      .contramap(({description}) =\u003e ({children: description}))\n  )\n```\n\nThis way the composition can be used like this:\n\n```js\n\u003cHeader.Component\n  title='Hello'\n  description='World!'\n/\u003e\n```\n\n…and will result in:\n\n```html\n\u003ch1\u003eHello\u003c/h1\u003e\n\u003cp\u003eWorld!\u003c/p\u003e\n```\n\nNote: while `concat` is for all practical purposes associative (as far as the resulting elements in the DOM are concerned), the React Components themselves are not joined together in an associative way, and this can be seen in the React DevTools. This violation of associativity is what makes it impossible for ReactDream to implement Monoid.\n\n### chain\n\n`chain` is useful as a escape hatch if you want to escape from ReactDream and do something very React-y\n\n```js\nimport ReactDream from 'react-dream'\nimport { Svg } from 'react-dream-web-builtins'\n\nconst wrapWithGLayer = Component =\u003e ReactDream(props =\u003e\n  \u003cg\u003e\n    \u003cComponent {...props} /\u003e\n  \u003c/g\u003e\n)\n\nconst LayerWithCircle = Svg.Circle\n  .contramap(() =\u003e ({\n    r: 5,\n    x: 10,\n    y: 10\n  })\n  .chain(wrapWithGLayer)\n```\n\nAside from Fantasy Land algebras, ReactDream provides the methods:\n\n### fork(Component =\u003e {})\n\nCalls the argument function with the actual component in the inside. This function is intended to be used to get the component for rendering, which is a side effect:\n\n```js\nH1.fork(Component =\u003e render(\u003cComponent\u003eHello\u003c/Component\u003e, domElement))\n```\n\n### addProps(props =\u003e propsToAdd : Object)\n\n`addProps` allows you to pass a function whose result will be merged with the regular props. This is useful to add derived props to a component:\n\n```js\nimport { Svg } from 'react-dream-web-builtins'\n\nconst Picture = Svg.Svg\n  .addProps(props =\u003e ({\n    viewBox: `0 0 ${props.width} ${props.height}`\n  }))\n\nrender(\n  \u003cPicture.Component\n    width={50}\n    height={50}\n  /\u003e,\n  domElement\n)\n```\n\nThe new props will be merged below the regular ones, so that the consumer can always override your props:\n\n```diff\nimport { Svg } from 'react-dream-web-builtins'\n\nconst Picture = Svg.Svg\n  .addProps(props =\u003e ({\n+    // This will be now ignored\n    viewBox: `0 0 ${props.width} ${props.height}`\n  }))\n\nrender(\n  \u003cPicture.Component\n+    viewBox='0 0 100 100'\n    width={50}\n    height={50}\n  /\u003e,\n  domElement\n)\n```\n\n#### `addProps` is a use case of `contramap`\n\n```js\n.addProps(({width, height}) =\u003e ({\n  viewBox: `0 0 ${props.width} ${props.height}`\n}))\n```\n\n…is equivalent to:\n\n```js\n.contramap(props =\u003e ({\n  ...props,\n  viewBox: `0 0 ${props.width} ${props.height}`\n}))\n```\n\n### removeProps(...propNamesToRemove : [String])\n\n`removeProps` filters out props. Very useful to avoid the React warnings of unrecognized props.\n\n```js\nconst ButtonWithStates = Html.Button\n  .removeProps('hovered', 'pressed')\n  .style(({hovered, pressed}) =\u003e ({\n    color: pressed ? 'red' : (hovered ? 'orange' : 'black')\n  }))\n```\n\n#### `removeProps` is an use case of `contramap`\n\n```js\n.removeProps('title', 'hovered')\n```\n\n…is equivalent to:\n\n```js\n.contramap(({title, hovered, ...otherProps}) =\u003e otherProps)\n```\n\n### defaultProps(props : Object)\n\n`defaultProps` allows you to set the, well, `defaultProps` of the wrapped React component.\n\n```js\nconst SubmitButton = Html.Button\n  .defaultProps({ type: 'submit' })\n```\n\n#### `defaultProps` is an use case of `map`\n\n```js\nconst SubmitButton = Html.Button\n  .defaultProps({ type: 'submit' })\n```\n\nUnder the hood is using `recompose`’s `defaultProps` function:\n\n```js\nimport { defaultProps } from 'recompose'\n\nconst SubmitButton = Html.Button\n  .map(defaultProps({ type: 'submit' }))\n```\n\n### propTypes(propTypes : Object)\n\n`propTypes` sets the `propTypes` of the React component.\n\n```js\nimport PropTypes from 'prop-types'\n\nconst Title = Html.H1\n  .style(({ highlighted }) =\u003e ({\n    backgroundColor: highlighted ? 'yellow' : 'transparent'\n  }))\n  .propTypes({\n    children: PropTypes.node,\n    highlighted: PropTypes.bool\n  })\n```\n\n#### `propTypes` is an use case of `map`\n\nThe example above is equivalent to:\n\n```js\nimport PropTypes from 'prop-types'\nimport { setPropTypes } from 'recompose'\n\nconst Title = Html.H1\n  .style(({ highlighted }) =\u003e ({\n    backgroundColor: highlighted ? 'yellow' : 'transparent'\n  }))\n  .map(setPropTypes({\n    children: PropTypes.node,\n    highlighted: PropTypes.bool\n  }))\n```\n\n### style(props =\u003e stylesToAdd : Object)\n\nThe `style` helper gives a simple way of adding properties to the `style` prop of the target component. It takes a function from props to a style object. The function will be invoked each time with the props. The result will be set as the `style` prop of the wrapper component. If there are styles coming from outside, they will be merged together with the result of this function. For example:\n\n```js\nconst Title = Html.H1\n  .style(props =\u003e ({color: highlighted ? 'red' : 'black'}))\n\nrender(\n  \u003cTitle\n    highlighted\n    style={{backgroundColor: 'green'}}\n  /\u003e,\n  domElement\n)\n```\n\nThe resulting style will be: `{ color: 'red', backgroundColor: 'green' }`.\n\n#### `style` is an use case of `contramap`\n\n```js\n.style(({hovered}) =\u003e ({\n  color: hovered ? 'red' : 'black'\n}))\n```\n\n…is equivalent to:\n\n```js\n.contramap(props =\u003e ({\n  style: {\n    color: props.hovered ? 'red' : 'black',\n    ...props.style\n  },\n  ...props\n}))\n```\n\n### name(newDisplayName : String)\n\nSets the `displayName` of the component:\n\n```js\nconst Tagline = H2.name('Tagline')\n```\n\n#### `name` is an use case of `map`\n\n```js\n.name('Tagline')\n```\n\n…is equivalent to:\n\n```js\nimport { setDisplayName } from 'recompose'\n\n.map(setDisplayName('Title'))\n```\n\n### rotate(props =\u003e rotation : number)\n\n`rotate` sets up a style `transform` property with the specified rotation, in degrees. If there is a transform already, `rotate` will append to it:\n\n```js\nconst Title = Html.H1\n  .rotate(props =\u003e 45)\n\nrender(\n  \u003cTitle.Component style={{ transform: 'rotate(45deg)' }} /\u003e,\n  document.getElementById('root')\n)\n```\n\n…will result in `transform: 'translateX(20px) rotate(45deg)'`\n\n\u003e Just a reminder: rotations start from the top left edge as the axis, which is rarely what one wants. If you want the rotation to happen from the center, you can set `transform-origin: 'center'`, that with ReactDream would be `.style(props =\u003e ({transformOrigin: 'center'}))`.\n\n#### `rotate` is an use case of `contramap`\n\n```js\n.rotate(props =\u003e 45)\n```\n\n…is equivalent to:\n\n```js\n.contramap(props =\u003e ({\n  style: {\n    transform: props.transform\n      ? `${props.transform} rotate(45deg)`\n      : 'rotate(45deg)'\n    ...props.style\n  },\n  ...props\n}))\n```\n\n### scale(props =\u003e scaleFactor : number)\n\n`scale` sets up a style `transform` property with the specified scaling factor. If there is a transform already, `scale` will append to it:\n\n```js\nconst Title = Html.H1\n  .scale(props =\u003e 1.5)\n\nrender(\n  \u003cTitle.Component style={{ transform: 'scale(1.5)' }} /\u003e,\n  document.getElementById('root')\n)\n```\n\n…will result in `transform: 'translateX(20px) scale(1.5)'`\n\n##### `scale` is an use case of `contramap`\n\n```js\n.scale(props =\u003e 2)\n```\n\n…is equivalent to:\n\n```js\n.contramap(props =\u003e ({\n  style: {\n    transform: props.transform\n      ? `${props.transform} scale(2)`\n      : 'scale(2)'\n    ...props.style\n  },\n  ...props\n}))\n```\n\n### translate(props =\u003e [x : number, y : number, z : number])\n\n`translate` allows you to easily set up the `transform` style property with the specified displacement. If there is a transform already, `translate` will append to it:\n\n```js\nconst Title = Html.H1\n  .translate(props =\u003e [30])\n  .translate(props =\u003e [null, 30])\n  .translate(props =\u003e [null, null, 30])\n```\n\n…will result in `transform: 'translateZ(30px) translateY(30px) translateX(30px)'`\n\n#### `translate` is an use case of `contramap`\n\n```js\n.translate(({x, y}) =\u003e [x, y])\n```\n\n…is equivalent to:\n\n```js\n.contramap(props =\u003e ({\n  style: {\n    transform: props.transform\n      ? `${props.transform} translate(${x}px, ${y}px)`\n      :  `translate(${x}px, ${y}px)`\n    ...props.style\n  },\n  ...props\n}))\n```\n\n## Debugging\n\nThe downside of chaining method calls is that debugging is not super intuitive. Since there are no statements, it’s not possible to place a `console.log()` or `debugger` call in the middle of the chain without some overhead. To simplify that, two methods for debugging are bundled:\n\n### log(props =\u003e value : any)\n\nWhenever the Component is called with new props, it will print:\n\n- The component displayName\n- The value by the argument function. The value can be anything, it will be passed as-is to the `console.log` function.\n\nPretty useful to debug what exactly is happening in the chain:\n\n```js\nconst Title = Html.H1\n  .log(props =\u003e 'what props gets to the H1?')\n  .log(props =\u003e props)\n  .contramap(({hovered, label}) =\u003e ({\n    children: hovered ? 'Hovered!' : label\n  }))\n  .log(({label}) =\u003e 'is there a label before the contramap? ' + label)\n  .name('Title')\n  .log(({label}) =\u003e 'does it also get a label from outside? ' + label)\n\nrender(\n  \u003cTitle.Component hovered label='Label from outside' /\u003e,\n  domElement\n)\n```\n\n`log` will become a no-op when the `NODE_ENV` is `production`.\n\nFor more details check out [@hocs/with-log](https://github.com/deepsweet/hocs/tree/master/packages/with-log) documentation which React Dream is using under the hood.\n\n#### `log` is an use case of `map`\n\n```js\n.log(({a}) =\u003e `a is: ${a}`)\n```\n\n…is equivalent to:\n\n```js\nimport withLog from '@hocs/with-log'\n\n.map(withLog(({a}) =\u003e `a is: ${a}`))\n```\n\n### debug()\n\n**Careful**: This method allows you to inject a `debugger` statement at that point in the chain. The result will allow you to inspect the Component and its props, from the JavaScript scope of the [@hocs/with-debugger higher-order component](https://github.com/deepsweet/hocs/tree/master/packages/with-debugger).\n\n```js\nimport React from 'react'\nimport { render } from 'react-dom'\nimport { Html } from 'react-dream-web-builtins'\n\nconst App = Html.Div\n  .debug()\n  .removeProps('a', 'c', 'randomProp')\n  .addProps(() =\u003e ({\n    a: '1',\n    c: '4'\n  }))\n```\n\nIt will be called on each render of the component.\n\n`debug` will become a no-op when the `NODE_ENV` is `production`.\n\nFor more details check out [@hocs/with-debugger](https://github.com/deepsweet/hocs/tree/master/packages/with-debugger) documentation which React Dream is using under the hood.\n\n#### `debug` is an use case of `map`\n\n```js\n.debug()\n```\n\n…is equivalent to:\n\n```js\nimport withDebugger from '@hocs/with-debugger'\n\n.map(withDebugger)\n```\n\n## Built-in Primitives\n\nA separate package, [react-dream-web-builtins](https://github.com/xaviervia/react-dream-web-builtins) ships with a complete set of HTML and SVG primitives lifted into the type. You can access them like:\n\n```js\nimport { Svg, Html } from 'react-dream-web-builtins'\n\nconst MyDiv = Html.Div\n\nconst MyLayer = Svg.G\n```\n\nRead more in the package [README]((https://github.com/xaviervia/react-dream-web-builtins))\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxaviervia%2Freact-dream","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxaviervia%2Freact-dream","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxaviervia%2Freact-dream/lists"}