text: import { __rest, __assign } from 'tslib';
  import { invariant } from 'hey-listen';
  
  var getPoseValues = function (_a) {
      var transition = _a.transition,
          delay = _a.delay,
          delayChildren = _a.delayChildren,
          staggerChildren = _a.staggerChildren,
          staggerDirection = _a.staggerDirection,
          afterChildren = _a.afterChildren,
          beforeChildren = _a.beforeChildren,
          preTransition = _a.preTransition,
          applyAtStart = _a.applyAtStart,
          applyAtEnd = _a.applyAtEnd,
          props = __rest(_a, ["transition", "delay", "delayChildren", "staggerChildren", "staggerDirection", "afterChildren", "beforeChildren", "preTransition", "applyAtStart", "applyAtEnd"]);
      return props;
  };
  var selectPoses = function (_a) {
      var label = _a.label,
          props = _a.props,
          values = _a.values,
          parentValues = _a.parentValues,
          ancestorValues = _a.ancestorValues,
          onChange = _a.onChange,
          passive = _a.passive,
          initialPose = _a.initialPose,
          poses = __rest(_a, ["label", "props", "values", "parentValues", "ancestorValues", "onChange", "passive", "initialPose"]);
      return poses;
  };
  var selectAllValues = function (values, selectValue) {
      var allValues = {};
      values.forEach(function (value, key) {
          return allValues[key] = selectValue(value);
      });
      return allValues;
  };
  
  var resolveProp = function (target, props) {
      return typeof target === 'function' ? target(props) : target;
  };
  var poseDefault = function (pose, prop, defaultValue, resolveProps) {
      return pose && pose[prop] !== undefined ? resolveProp(pose[prop], resolveProps) : defaultValue;
  };
  var startChildAnimations = function (children, next, pose, props) {
      var animations = [];
      var delay = poseDefault(pose, 'delayChildren', 0, props);
      var stagger = poseDefault(pose, 'staggerChildren', 0, props);
      var staggerDirection = poseDefault(pose, 'staggerDirection', 1, props);
      var maxStaggerDuration = (children.size - 1) * stagger;
      var generateStaggerDuration = staggerDirection === 1 ? function (i) {
          return i * stagger;
      } : function (i) {
          return maxStaggerDuration - i * stagger;
      };
      Array.from(children).forEach(function (child, i) {
          animations.push(child.set(next, __assign({}, props, { delay: delay + generateStaggerDuration(i) })));
      });
      return animations;
  };
  var resolveTransition = function (transition, key, value, props, convertTransitionDefinition, getInstantTransition) {
      var resolvedTransition;
      if (typeof transition === 'function') {
          resolvedTransition = transition(props);
      } else if (transition[key] || transition.default) {
          var keyTransition = transition[key] || transition.default;
          if (typeof keyTransition === 'function') {
              resolvedTransition = keyTransition(props);
          } else {
              resolvedTransition = keyTransition;
          }
      } else {
          resolvedTransition = transition;
      }
      return resolvedTransition === false ? getInstantTransition(value, props) : convertTransitionDefinition(value, resolvedTransition, props);
  };
  var findInsertionIndex = function (poseList, priorityList, priorityIndex) {
      var insertionIndex = 0;
      for (var i = priorityIndex - 1; i >= 0; i--) {
          var nextHighestPriorityIndex = poseList.indexOf(priorityList[i]);
          if (nextHighestPriorityIndex !== -1) {
              insertionIndex = nextHighestPriorityIndex + 1;
              break;
          }
      }
      return insertionIndex;
  };
  var applyValues = function (toApply, values, props, setValue, setValueNative) {
      invariant(typeof toApply === 'object', 'applyAtStart and applyAtEnd must be of type object');
      return Object.keys(toApply).forEach(function (key) {
          var valueToSet = resolveProp(toApply[key], props);
          values.has(key) ? setValue(values.get(key), valueToSet) : setValueNative(key, valueToSet, props);
      });
  };
  var createPoseSetter = function (setterProps) {
      var state = setterProps.state,
          poses = setterProps.poses,
          startAction = setterProps.startAction,
          stopAction = setterProps.stopAction,
          getInstantTransition = setterProps.getInstantTransition,
          addActionDelay = setterProps.addActionDelay,
          getTransitionProps = setterProps.getTransitionProps,
          resolveTarget = setterProps.resolveTarget,
          transformPose = setterProps.transformPose,
          posePriority = setterProps.posePriority,
          convertTransitionDefinition = setterProps.convertTransitionDefinition,
          setValue = setterProps.setValue,
          setValueNative = setterProps.setValueNative;
      return function (next, nextProps, propagate) {
          if (nextProps === void 0) {
              nextProps = {};
          }
          if (propagate === void 0) {
              propagate = true;
          }
          var children = state.children,
              values = state.values,
              props = state.props,
              activeActions = state.activeActions,
              activePoses = state.activePoses;
          var _a = nextProps.delay,
              delay = _a === void 0 ? 0 : _a;
          var hasChildren = children.size;
          var baseTransitionProps = __assign({}, props, nextProps);
          var nextPose = poses[next];
          var getChildAnimations = function () {
              return hasChildren && propagate ? startChildAnimations(children, next, nextPose, baseTransitionProps) : [];
          };
          var getParentAnimations = function () {
              if (!nextPose) return [];
              if (transformPose) nextPose = transformPose(nextPose, next, state);
              var preTransition = nextPose.preTransition,
                  getTransition = nextPose.transition,
                  applyAtStart = nextPose.applyAtStart,
                  applyAtEnd = nextPose.applyAtEnd;
              if (preTransition) preTransition(baseTransitionProps);
              if (applyAtStart) {
                  applyValues(applyAtStart, values, baseTransitionProps, setValue, setValueNative);
              }
              var animations = Object.keys(getPoseValues(nextPose)).map(function (key) {
                  var valuePoses = activePoses.has(key) ? activePoses.get(key) : (activePoses.set(key, []), activePoses.get(key));
                  var existingIndex = valuePoses.indexOf(next);
                  if (existingIndex !== -1) valuePoses.splice(existingIndex, 1);
                  var priority = posePriority ? posePriority.indexOf(next) : 0;
                  var insertionIndex = priority <= 0 ? 0 : findInsertionIndex(valuePoses, posePriority, priority);
                  valuePoses.splice(insertionIndex, 0, next);
                  return insertionIndex === 0 ? new Promise(function (complete) {
                      var value = values.get(key);
                      var transitionProps = __assign({}, baseTransitionProps, { key: key,
                          value: value });
                      var target = resolveTarget(value, resolveProp(nextPose[key], transitionProps));
                      if (activeActions.has(key)) stopAction(activeActions.get(key));
                      var resolveTransitionProps = __assign({ to: target }, transitionProps, getTransitionProps(value, target, transitionProps));
                      var transition = resolveTransition(getTransition, key, value, resolveTransitionProps, convertTransitionDefinition, getInstantTransition);
                      var poseDelay = resolveProp(nextPose.delay, transitionProps);
                      if (delay || poseDelay) {
                          transition = addActionDelay(delay || poseDelay, transition);
                      }
                      activeActions.set(key, startAction(value, transition, complete));
                  }) : Promise.resolve();
              });
              return applyAtEnd ? [Promise.all(animations).then(function () {
                  applyValues(applyAtEnd, values, baseTransitionProps, setValue, setValueNative);
              })] : animations;
          };
          if (nextPose && hasChildren) {
              if (resolveProp(nextPose.beforeChildren, baseTransitionProps)) {
                  return Promise.all(getParentAnimations()).then(function () {
                      return Promise.all(getChildAnimations());
                  });
              } else if (resolveProp(nextPose.afterChildren, baseTransitionProps)) {
                  return Promise.all(getChildAnimations()).then(function () {
                      return Promise.all(getParentAnimations());
                  });
              }
          }
          return Promise.all(getParentAnimations().concat(getChildAnimations()));
      };
  };
  
  var DEFAULT_INITIAL_POSE = 'init';
  var isScale = function (key) {
      return key.includes('scale');
  };
  var defaultReadValueFromSource = function (key) {
      return isScale(key) ? 1 : 0;
  };
  var getInitialValue = function (poses, key, initialPose, props, readValueFromSource, activePoses) {
      if (readValueFromSource === void 0) {
          readValueFromSource = defaultReadValueFromSource;
      }
      var posesToSearch = Array.isArray(initialPose) ? initialPose : [initialPose];
      posesToSearch.push(DEFAULT_INITIAL_POSE);
      var pose = posesToSearch.filter(Boolean).find(function (name) {
          return poses[name] && poses[name][key] !== undefined;
      });
      activePoses.set(key, [pose || DEFAULT_INITIAL_POSE]);
      return pose ? resolveProp(poses[pose][key], props) : readValueFromSource(key, props);
  };
  var createValues = function (values, _a) {
      var userSetValues = _a.userSetValues,
          createValue = _a.createValue,
          convertValue = _a.convertValue,
          readValueFromSource = _a.readValueFromSource,
          initialPose = _a.initialPose,
          poses = _a.poses,
          activePoses = _a.activePoses,
          props = _a.props;
      return function (key) {
          if (values.has(key)) return;
          var value;
          if (userSetValues && userSetValues[key] !== undefined) {
              value = convertValue(userSetValues[key], key, props);
          } else {
              var initValue = getInitialValue(poses, key, initialPose, props, readValueFromSource, activePoses);
              value = createValue(initValue, key, props);
          }
          values.set(key, value);
      };
  };
  var scrapeValuesFromPose = function (values, props) {
      return function (key) {
          var pose = props.poses[key];
          Object.keys(getPoseValues(pose)).forEach(createValues(values, props));
      };
  };
  var getAncestorValue = function (key, fromParent, ancestors) {
      if (fromParent === true) {
          return ancestors[0] && ancestors[0].values.get(key);
      } else {
          var foundAncestor = ancestors.find(function (_a) {
              var label = _a.label;
              return label === fromParent;
          });
          return foundAncestor && foundAncestor.values.get(key);
      }
  };
  var bindPassiveValues = function (values, _a) {
      var passive = _a.passive,
          ancestorValues = _a.ancestorValues,
          createValue = _a.createValue,
          readValue = _a.readValue,
          props = _a.props;
      return function (key) {
          var _a = passive[key],
              valueKey = _a[0],
              passiveProps = _a[1],
              fromParent = _a[2];
          var valueToBind = fromParent && ancestorValues.length ? getAncestorValue(valueKey, fromParent, ancestorValues) : values.has(valueKey) ? values.get(valueKey) : false;
          if (!valueToBind) return;
          var newValue = createValue(readValue(valueToBind), key, props, {
              passiveParentKey: valueKey,
              passiveParent: valueToBind,
              passiveProps: passiveProps
          });
          values.set(key, newValue);
      };
  };
  var createValueMap = function (props) {
      var poses = props.poses,
          passive = props.passive;
      var values = new Map();
      Object.keys(poses).forEach(scrapeValuesFromPose(values, props));
      if (passive) Object.keys(passive).forEach(bindPassiveValues(values, props));
      return values;
  };
  
  var applyDefaultTransition = function (pose, key, defaultTransitions) {
      return __assign({}, pose, { transition: defaultTransitions.has(key) ? defaultTransitions.get(key) : defaultTransitions.get('default') });
  };
  var generateTransitions = function (poses, defaultTransitions) {
      Object.keys(poses).forEach(function (key) {
          var pose = poses[key];
          invariant(typeof pose === 'object', "Pose '" + key + "' is of invalid type. All poses should be objects.");
          poses[key] = pose.transition !== undefined ? pose : applyDefaultTransition(pose, key, defaultTransitions);
      });
      return poses;
  };
  
  var sortByReversePriority = function (priorityOrder) {
      return function (a, b) {
          var aP = priorityOrder.indexOf(a);
          var bP = priorityOrder.indexOf(b);
          if (aP === -1 && bP !== -1) return -1;
          if (aP !== -1 && bP === -1) return 1;
          return aP - bP;
      };
  };
  
  var poseFactory = function (_a) {
      var getDefaultProps = _a.getDefaultProps,
          defaultTransitions = _a.defaultTransitions,
          bindOnChange = _a.bindOnChange,
          startAction = _a.startAction,
          stopAction = _a.stopAction,
          readValue = _a.readValue,
          readValueFromSource = _a.readValueFromSource,
          resolveTarget = _a.resolveTarget,
          setValue = _a.setValue,
          setValueNative = _a.setValueNative,
          createValue = _a.createValue,
          convertValue = _a.convertValue,
          getInstantTransition = _a.getInstantTransition,
          getTransitionProps = _a.getTransitionProps,
          addActionDelay = _a.addActionDelay,
          selectValueToRead = _a.selectValueToRead,
          convertTransitionDefinition = _a.convertTransitionDefinition,
          transformPose = _a.transformPose,
          posePriority = _a.posePriority,
          extendAPI = _a.extendAPI;
      return function (config) {
          var parentValues = config.parentValues,
              _a = config.ancestorValues,
              ancestorValues = _a === void 0 ? [] : _a;
          if (parentValues) ancestorValues.unshift({ values: parentValues });
          var activeActions = new Map();
          var activePoses = new Map();
          var children = new Set();
          var poses = generateTransitions(selectPoses(config), defaultTransitions);
          var props = config.props || {};
          if (getDefaultProps) props = __assign({}, props, getDefaultProps(config));
          var passive = config.passive,
              userSetValues = config.values,
              _b = config.initialPose,
              initialPose = _b === void 0 ? DEFAULT_INITIAL_POSE : _b;
          var values = createValueMap({
              poses: poses,
              passive: passive,
              ancestorValues: ancestorValues,
              readValue: readValue,
              createValue: createValue,
              convertValue: convertValue,
              readValueFromSource: readValueFromSource,
              userSetValues: userSetValues,
              initialPose: initialPose,
              activePoses: activePoses,
              props: props
          });
          var state = {
              activeActions: activeActions,
              activePoses: activePoses,
              children: children,
              props: props,
              values: values
          };
          var onChange = config.onChange;
          if (onChange) Object.keys(onChange).forEach(bindOnChange(values, onChange));
          var set = createPoseSetter({
              state: state,
              poses: poses,
              getInstantTransition: getInstantTransition,
              getTransitionProps: getTransitionProps,
              convertTransitionDefinition: convertTransitionDefinition,
              setValue: setValue,
              setValueNative: setValueNative,
              startAction: startAction,
              stopAction: stopAction,
              resolveTarget: resolveTarget,
              addActionDelay: addActionDelay,
              transformPose: transformPose,
              posePriority: posePriority
          });
          var has = function (poseName) {
              return !!poses[poseName];
          };
          var api = {
              set: set,
              unset: function (poseName, poseProps) {
                  var posesToSet = [];
                  activePoses.forEach(function (valuePoses) {
                      var poseIndex = valuePoses.indexOf(poseName);
                      if (poseIndex === -1) return;
                      var currentPose = valuePoses[0];
                      valuePoses.splice(poseIndex, 1);
                      var nextPose = valuePoses[0];
                      if (nextPose === currentPose) return;
                      if (posesToSet.indexOf(nextPose) === -1) {
                          posesToSet.push(nextPose);
                      }
                  });
                  var animationsToResolve = posesToSet.sort(sortByReversePriority(posePriority)).map(function (poseToSet) {
                      return set(poseToSet, poseProps, false);
                  });
                  children.forEach(function (child) {
                      return animationsToResolve.push(child.unset(poseName));
                  });
                  return Promise.all(animationsToResolve);
              },
              get: function (valueName) {
                  return valueName ? selectValueToRead(values.get(valueName)) : selectAllValues(values, selectValueToRead);
              },
              has: has,
              setProps: function (newProps) {
                  return state.props = __assign({}, state.props, newProps);
              },
              _addChild: function (childConfig, factory) {
                  var child = factory(__assign({ initialPose: initialPose }, childConfig, { ancestorValues: [{ label: config.label, values: values }].concat(ancestorValues) }));
                  children.add(child);
                  return child;
              },
              removeChild: function (child) {
                  return children.delete(child);
              },
              clearChildren: function () {
                  children.forEach(function (child) {
                      return child.destroy();
                  });
                  children.clear();
              },
              destroy: function () {
                  activeActions.forEach(stopAction);
                  children.forEach(function (child) {
                      return child.destroy();
                  });
              }
          };
          return extendAPI(api, state, config);
      };
  };
  
  export default poseFactory;
  