UNPKG

react-bootstrap

Version:

Bootstrap 3 components build with React

143 lines (125 loc) 4.33 kB
/** * Copyright 2013-2014, Facebook, Inc. * All rights reserved. * * This file contains modified versions of: * https://github.com/facebook/react/blob/v0.12.0/src/utils/cloneWithProps.js * https://github.com/facebook/react/blob/v0.12.0/src/core/ReactPropTransferer.js * * This source code is licensed under the BSD-style license found here: * https://github.com/facebook/react/blob/v0.12.0/LICENSE * An additional grant of patent rights can be found here: * https://github.com/facebook/react/blob/v0.12.0/PATENTS * * TODO: This should be replaced as soon as cloneWithProps is available via * the core React package or a separate package. * @see https://github.com/facebook/react/issues/1906 */ var React = require('react'); var joinClasses = require('./joinClasses'); var assign = require("./Object.assign"); /** * Creates a transfer strategy that will merge prop values using the supplied * `mergeStrategy`. If a prop was previously unset, this just sets it. * * @param {function} mergeStrategy * @return {function} */ function createTransferStrategy(mergeStrategy) { return function(props, key, value) { if (!props.hasOwnProperty(key)) { props[key] = value; } else { props[key] = mergeStrategy(props[key], value); } }; } var transferStrategyMerge = createTransferStrategy(function(a, b) { // `merge` overrides the first object's (`props[key]` above) keys using the // second object's (`value`) keys. An object's style's existing `propA` would // get overridden. Flip the order here. return assign({}, b, a); }); function emptyFunction() {} /** * Transfer strategies dictate how props are transferred by `transferPropsTo`. * NOTE: if you add any more exceptions to this list you should be sure to * update `cloneWithProps()` accordingly. */ var TransferStrategies = { /** * Never transfer `children`. */ children: emptyFunction, /** * Transfer the `className` prop by merging them. */ className: createTransferStrategy(joinClasses), /** * Transfer the `style` prop (which is an object) by merging them. */ style: transferStrategyMerge }; /** * Mutates the first argument by transferring the properties from the second * argument. * * @param {object} props * @param {object} newProps * @return {object} */ function transferInto(props, newProps) { for (var thisKey in newProps) { if (!newProps.hasOwnProperty(thisKey)) { continue; } var transferStrategy = TransferStrategies[thisKey]; if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) { transferStrategy(props, thisKey, newProps[thisKey]); } else if (!props.hasOwnProperty(thisKey)) { props[thisKey] = newProps[thisKey]; } } return props; } /** * Merge two props objects using TransferStrategies. * * @param {object} oldProps original props (they take precedence) * @param {object} newProps new props to merge in * @return {object} a new object containing both sets of props merged. */ function mergeProps(oldProps, newProps) { return transferInto(assign({}, oldProps), newProps); } var ReactPropTransferer = { mergeProps: mergeProps }; var CHILDREN_PROP = 'children'; /** * Sometimes you want to change the props of a child passed to you. Usually * this is to add a CSS class. * * @param {object} child child component you'd like to clone * @param {object} props props you'd like to modify. They will be merged * as if you used `transferPropsTo()`. * @return {object} a clone of child with props merged in. */ function cloneWithProps(child, props) { var newProps = ReactPropTransferer.mergeProps(props, child.props); // Use `child.props.children` if it is provided. if (!newProps.hasOwnProperty(CHILDREN_PROP) && child.props.hasOwnProperty(CHILDREN_PROP)) { newProps.children = child.props.children; } if (React.version.substr(0, 4) === '0.12'){ var mockLegacyFactory = function(){}; mockLegacyFactory.isReactLegacyFactory = true; mockLegacyFactory.type = child.type; return React.createElement(mockLegacyFactory, newProps); } // The current API doesn't retain _owner and _context, which is why this // doesn't use ReactElement.cloneAndReplaceProps. return React.createElement(child.type, newProps); } module.exports = cloneWithProps;