-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(factories): create reusable shorthand factory
- Loading branch information
1 parent
acfdd0d
commit 0b01f0b
Showing
3 changed files
with
64 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import _ from 'lodash' | ||
import cx from 'classnames' | ||
import React, { isValidElement } from 'react' | ||
|
||
import Icon from './elements/Icon/Icon' | ||
import Image from './elements/Image/Image' | ||
import Label from './elements/Label/Label' | ||
|
||
/** | ||
* Merges props and classNames. | ||
* | ||
* @param {object} props A props object | ||
* @param {object} extraProps A props object | ||
* @returns {object} A new props object | ||
*/ | ||
const mergePropsAndClassName = (props, extraProps) => { | ||
let className | ||
if (_.has(props, 'className') || _.has(extraProps.className)) { | ||
className = cx(props.className, extraProps.className) // eslint-disable-line react/prop-types | ||
} | ||
return { ...props, ...extraProps, className } | ||
} | ||
|
||
/** | ||
* A more robust React.createElement. | ||
* It can create elements from primitive values. | ||
* | ||
* @param {function|string} Component A ReactClass or string | ||
* @param {function} mapValueToProps A function that maps a primitive value to the Component props | ||
* @param {string|object|function} val The value to create a ReactElement from | ||
* @param {object} extraProps Additional props to add to the final ReactElement | ||
* @returns {function|null} | ||
*/ | ||
export function createShorthand(Component, mapValueToProps, val, extraProps = {}) { | ||
// Clone ReactElements | ||
if (isValidElement(val)) { | ||
return React.cloneElement(val, mergePropsAndClassName(val.props, extraProps)) | ||
} | ||
|
||
// Create ReactElements from props objects | ||
if (_.isPlainObject(val)) { | ||
return <Component {...mergePropsAndClassName(val, extraProps)} /> | ||
} | ||
|
||
// Map values to props and create a ReactElement | ||
if (!_.isNil(val)) { | ||
return <Component {...mergePropsAndClassName(mapValueToProps(val), extraProps)} /> | ||
} | ||
|
||
// React requires ReactElements or null be returned | ||
return null | ||
} | ||
|
||
function createShorthandFactory(Component, mapValueToProps) { | ||
return _.partial(createShorthand, Component, mapValueToProps) | ||
} | ||
|
||
// ---------------------------------------- | ||
// Factories | ||
// ---------------------------------------- | ||
export const createIcon = createShorthandFactory(Icon, value => ({ name: value })) | ||
export const createImage = createShorthandFactory(Image, value => ({ src: value })) | ||
export const createImg = createShorthandFactory('img', value => ({ src: value })) | ||
export const createLabel = createShorthandFactory(Label, value => ({ content: value })) |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.