You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							150 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							150 lines
						
					
					
						
							4.9 KiB
						
					
					
				"use strict";
 | 
						|
 | 
						|
exports.__esModule = true;
 | 
						|
exports.getChildMapping = getChildMapping;
 | 
						|
exports.mergeChildMappings = mergeChildMappings;
 | 
						|
exports.getInitialChildMapping = getInitialChildMapping;
 | 
						|
exports.getNextChildMapping = getNextChildMapping;
 | 
						|
 | 
						|
var _react = require("react");
 | 
						|
 | 
						|
/**
 | 
						|
 * Given `this.props.children`, return an object mapping key to child.
 | 
						|
 *
 | 
						|
 * @param {*} children `this.props.children`
 | 
						|
 * @return {object} Mapping of key to child
 | 
						|
 */
 | 
						|
function getChildMapping(children, mapFn) {
 | 
						|
  var mapper = function mapper(child) {
 | 
						|
    return mapFn && (0, _react.isValidElement)(child) ? mapFn(child) : child;
 | 
						|
  };
 | 
						|
 | 
						|
  var result = Object.create(null);
 | 
						|
  if (children) _react.Children.map(children, function (c) {
 | 
						|
    return c;
 | 
						|
  }).forEach(function (child) {
 | 
						|
    // run the map function here instead so that the key is the computed one
 | 
						|
    result[child.key] = mapper(child);
 | 
						|
  });
 | 
						|
  return result;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * When you're adding or removing children some may be added or removed in the
 | 
						|
 * same render pass. We want to show *both* since we want to simultaneously
 | 
						|
 * animate elements in and out. This function takes a previous set of keys
 | 
						|
 * and a new set of keys and merges them with its best guess of the correct
 | 
						|
 * ordering. In the future we may expose some of the utilities in
 | 
						|
 * ReactMultiChild to make this easy, but for now React itself does not
 | 
						|
 * directly have this concept of the union of prevChildren and nextChildren
 | 
						|
 * so we implement it here.
 | 
						|
 *
 | 
						|
 * @param {object} prev prev children as returned from
 | 
						|
 * `ReactTransitionChildMapping.getChildMapping()`.
 | 
						|
 * @param {object} next next children as returned from
 | 
						|
 * `ReactTransitionChildMapping.getChildMapping()`.
 | 
						|
 * @return {object} a key set that contains all keys in `prev` and all keys
 | 
						|
 * in `next` in a reasonable order.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
function mergeChildMappings(prev, next) {
 | 
						|
  prev = prev || {};
 | 
						|
  next = next || {};
 | 
						|
 | 
						|
  function getValueForKey(key) {
 | 
						|
    return key in next ? next[key] : prev[key];
 | 
						|
  } // For each key of `next`, the list of keys to insert before that key in
 | 
						|
  // the combined list
 | 
						|
 | 
						|
 | 
						|
  var nextKeysPending = Object.create(null);
 | 
						|
  var pendingKeys = [];
 | 
						|
 | 
						|
  for (var prevKey in prev) {
 | 
						|
    if (prevKey in next) {
 | 
						|
      if (pendingKeys.length) {
 | 
						|
        nextKeysPending[prevKey] = pendingKeys;
 | 
						|
        pendingKeys = [];
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      pendingKeys.push(prevKey);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  var i;
 | 
						|
  var childMapping = {};
 | 
						|
 | 
						|
  for (var nextKey in next) {
 | 
						|
    if (nextKeysPending[nextKey]) {
 | 
						|
      for (i = 0; i < nextKeysPending[nextKey].length; i++) {
 | 
						|
        var pendingNextKey = nextKeysPending[nextKey][i];
 | 
						|
        childMapping[nextKeysPending[nextKey][i]] = getValueForKey(pendingNextKey);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    childMapping[nextKey] = getValueForKey(nextKey);
 | 
						|
  } // Finally, add the keys which didn't appear before any key in `next`
 | 
						|
 | 
						|
 | 
						|
  for (i = 0; i < pendingKeys.length; i++) {
 | 
						|
    childMapping[pendingKeys[i]] = getValueForKey(pendingKeys[i]);
 | 
						|
  }
 | 
						|
 | 
						|
  return childMapping;
 | 
						|
}
 | 
						|
 | 
						|
function getProp(child, prop, props) {
 | 
						|
  return props[prop] != null ? props[prop] : child.props[prop];
 | 
						|
}
 | 
						|
 | 
						|
function getInitialChildMapping(props, onExited) {
 | 
						|
  return getChildMapping(props.children, function (child) {
 | 
						|
    return (0, _react.cloneElement)(child, {
 | 
						|
      onExited: onExited.bind(null, child),
 | 
						|
      in: true,
 | 
						|
      appear: getProp(child, 'appear', props),
 | 
						|
      enter: getProp(child, 'enter', props),
 | 
						|
      exit: getProp(child, 'exit', props)
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function getNextChildMapping(nextProps, prevChildMapping, onExited) {
 | 
						|
  var nextChildMapping = getChildMapping(nextProps.children);
 | 
						|
  var children = mergeChildMappings(prevChildMapping, nextChildMapping);
 | 
						|
  Object.keys(children).forEach(function (key) {
 | 
						|
    var child = children[key];
 | 
						|
    if (!(0, _react.isValidElement)(child)) return;
 | 
						|
    var hasPrev = (key in prevChildMapping);
 | 
						|
    var hasNext = (key in nextChildMapping);
 | 
						|
    var prevChild = prevChildMapping[key];
 | 
						|
    var isLeaving = (0, _react.isValidElement)(prevChild) && !prevChild.props.in; // item is new (entering)
 | 
						|
 | 
						|
    if (hasNext && (!hasPrev || isLeaving)) {
 | 
						|
      // console.log('entering', key)
 | 
						|
      children[key] = (0, _react.cloneElement)(child, {
 | 
						|
        onExited: onExited.bind(null, child),
 | 
						|
        in: true,
 | 
						|
        exit: getProp(child, 'exit', nextProps),
 | 
						|
        enter: getProp(child, 'enter', nextProps)
 | 
						|
      });
 | 
						|
    } else if (!hasNext && hasPrev && !isLeaving) {
 | 
						|
      // item is old (exiting)
 | 
						|
      // console.log('leaving', key)
 | 
						|
      children[key] = (0, _react.cloneElement)(child, {
 | 
						|
        in: false
 | 
						|
      });
 | 
						|
    } else if (hasNext && hasPrev && (0, _react.isValidElement)(prevChild)) {
 | 
						|
      // item hasn't changed transition states
 | 
						|
      // copy over the last transition props;
 | 
						|
      // console.log('unchanged', key)
 | 
						|
      children[key] = (0, _react.cloneElement)(child, {
 | 
						|
        onExited: onExited.bind(null, child),
 | 
						|
        in: prevChild.props.in,
 | 
						|
        exit: getProp(child, 'exit', nextProps),
 | 
						|
        enter: getProp(child, 'enter', nextProps)
 | 
						|
      });
 | 
						|
    }
 | 
						|
  });
 | 
						|
  return children;
 | 
						|
} |