Fantasy Land type for React Components
defaultProps allows you to set the defaultProps
of the wrapped React component.
const SubmitButton = Html.Button
.defaultProps({ type: 'submit' })
propTypes sets the propTypes
of the React component.
import PropTypes from 'prop-types'
const Title = Html.H1
.style(({ highlighted }) => ({
backgroundColor: highlighted ? 'yellow' : 'transparent'
}))
.propTypes({
children: PropTypes.node,
highlighted: PropTypes.bool
})
Both rely on recompose
higher-order components under the hood.
Now .log
and .debug
are simply wrapping @hocs/with-log and @hocs/with-debugger .
This also means that they are safer to use, since they will become no-ops when NODE_ENV
is production
.
Pointfree style provides a flexibility that chains don’t have. Now all of React Dream methods can be written pointfree by requiring the helper.
So now this:
const HeaderWrapper = Html.Header
.contramap(omit(['clicked', 'updateClicked']))
.style(({ clicked }) => ({
backgroundColor: clicked ? 'red' : 'green',
cursor: 'pointer',
padding: 15,
}))
.name('HeaderWrapper')
.map(
withHandlers({
onClick: ({ clicked, updateClicked }) => () => updateClicked(!clicked),
})
)
.map(withState('clicked', 'updateClicked', false))
…can also be written as:
import {Html, map, name, style, contramap} from 'react-dream'
const HeaderWrapper = compose(
map(withState('clicked', 'updateClicked', false)),
map(
withHandlers({
onClick: ({ clicked, updateClicked }) => () => updateClicked(!clicked),
})
),
name('HeaderWrapper'),
style(({ clicked }) => ({
backgroundColor: clicked ? 'red' : 'green',
cursor: 'pointer',
padding: 15,
})),
contramap(omit(['clicked', 'updateClicked']))
)(Html.Header)
rotate
sets up a style transform
property with the specified rotation, in degrees. If there is a transform already, rotate
will append to it:
const Title = Html.H1
.rotate(props => 45)
render(
<Title.Component style={{ transform: 'translateX(20px)' }} />,
document.getElementById('root')
)
…will result in transform: 'translateX(20px) rotate(45deg)'
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 => ({transformOrigin: 'center'}))
.
scale
sets up a style transform
property with the specified scaling factor. If there is a transform already, scale
will append to it:
const Title = Html.H1
.scale(props => 1.5)
render(
<Title.Component style={{ transform: 'translateX(20px)' }} />,
document.getElementById('root')
)
…will result in transform: 'translateX(20px) scale(1.5)'
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:
const Title = Html.H1
.translate(props => [30])
.translate(props => [null, 30])
.translate(props => [null, null, 30])
…will result in transform: 'translateZ(30px) translateY(30px) translateX(30px)'
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
:
const Header = Html.Div
.promap(
({title}) => ({children: title}),
setDisplayName('Header')
)
.log(text) allows to easily log in the middle of a chain.
.debug() allows to inject a debugger
statement in the middle of a chain.
New wrappers for easily adding and removing props:
const Title = Html.H1
.removeProps('label')
.addProps(({ label }) => ({
children: label
}))