UNPKG

47.6 kBJavaScriptView Raw
1import _extends from '@babel/runtime/helpers/esm/extends';
2import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';
3import React, { useState, useCallback, forwardRef, useRef, useEffect, useImperativeHandle, useMemo } from 'react';
4
5const is = {
6 arr: Array.isArray,
7 obj: a => Object.prototype.toString.call(a) === '[object Object]',
8 fun: a => typeof a === 'function',
9 str: a => typeof a === 'string',
10 num: a => typeof a === 'number',
11 und: a => a === void 0,
12 nul: a => a === null,
13 set: a => a instanceof Set,
14 map: a => a instanceof Map,
15
16 equ(a, b) {
17 if (typeof a !== typeof b) return false;
18 if (is.str(a) || is.num(a)) return a === b;
19 if (is.obj(a) && is.obj(b) && Object.keys(a).length + Object.keys(b).length === 0) return true;
20 let i;
21
22 for (i in a) if (!(i in b)) return false;
23
24 for (i in b) if (a[i] !== b[i]) return false;
25
26 return is.und(i) ? a === b : true;
27 }
28
29};
30function merge(target, lowercase) {
31 if (lowercase === void 0) {
32 lowercase = true;
33 }
34
35 return object => (is.arr(object) ? object : Object.keys(object)).reduce((acc, element) => {
36 const key = lowercase ? element[0].toLowerCase() + element.substring(1) : element;
37 acc[key] = target(key);
38 return acc;
39 }, target);
40}
41function useForceUpdate() {
42 const _useState = useState(false),
43 f = _useState[1];
44
45 const forceUpdate = useCallback(() => f(v => !v), []);
46 return forceUpdate;
47}
48function withDefault(value, defaultValue) {
49 return is.und(value) || is.nul(value) ? defaultValue : value;
50}
51function toArray(a) {
52 return !is.und(a) ? is.arr(a) ? a : [a] : [];
53}
54function callProp(obj) {
55 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
56 args[_key - 1] = arguments[_key];
57 }
58
59 return is.fun(obj) ? obj(...args) : obj;
60}
61
62function getForwardProps(props) {
63 const to = props.to,
64 from = props.from,
65 config = props.config,
66 onStart = props.onStart,
67 onRest = props.onRest,
68 onFrame = props.onFrame,
69 children = props.children,
70 reset = props.reset,
71 reverse = props.reverse,
72 force = props.force,
73 immediate = props.immediate,
74 delay = props.delay,
75 attach = props.attach,
76 destroyed = props.destroyed,
77 interpolateTo = props.interpolateTo,
78 ref = props.ref,
79 lazy = props.lazy,
80 forward = _objectWithoutPropertiesLoose(props, ["to", "from", "config", "onStart", "onRest", "onFrame", "children", "reset", "reverse", "force", "immediate", "delay", "attach", "destroyed", "interpolateTo", "ref", "lazy"]);
81
82 return forward;
83}
84
85function interpolateTo(props) {
86 const forward = getForwardProps(props);
87 if (is.und(forward)) return _extends({
88 to: forward
89 }, props);
90 const rest = Object.keys(props).reduce((a, k) => !is.und(forward[k]) ? a : _extends({}, a, {
91 [k]: props[k]
92 }), {});
93 return _extends({
94 to: forward
95 }, rest);
96}
97function handleRef(ref, forward) {
98 if (forward) {
99 // If it's a function, assume it's a ref callback
100 if (is.fun(forward)) forward(ref);else if (is.obj(forward)) {
101 forward.current = ref;
102 }
103 }
104
105 return ref;
106}
107
108class Animated {
109 constructor() {
110 this.payload = void 0;
111 this.children = [];
112 }
113
114 getAnimatedValue() {
115 return this.getValue();
116 }
117
118 getPayload() {
119 return this.payload || this;
120 }
121
122 attach() {}
123
124 detach() {}
125
126 getChildren() {
127 return this.children;
128 }
129
130 addChild(child) {
131 if (this.children.length === 0) this.attach();
132 this.children.push(child);
133 }
134
135 removeChild(child) {
136 const index = this.children.indexOf(child);
137 this.children.splice(index, 1);
138 if (this.children.length === 0) this.detach();
139 }
140
141}
142class AnimatedArray extends Animated {
143 constructor() {
144 super(...arguments);
145 this.payload = [];
146
147 this.attach = () => this.payload.forEach(p => p instanceof Animated && p.addChild(this));
148
149 this.detach = () => this.payload.forEach(p => p instanceof Animated && p.removeChild(this));
150 }
151
152}
153class AnimatedObject extends Animated {
154 constructor() {
155 super(...arguments);
156 this.payload = {};
157
158 this.attach = () => Object.values(this.payload).forEach(s => s instanceof Animated && s.addChild(this));
159
160 this.detach = () => Object.values(this.payload).forEach(s => s instanceof Animated && s.removeChild(this));
161 }
162
163 getValue(animated) {
164 if (animated === void 0) {
165 animated = false;
166 }
167
168 const payload = {};
169
170 for (const key in this.payload) {
171 const value = this.payload[key];
172 if (animated && !(value instanceof Animated)) continue;
173 payload[key] = value instanceof Animated ? value[animated ? 'getAnimatedValue' : 'getValue']() : value;
174 }
175
176 return payload;
177 }
178
179 getAnimatedValue() {
180 return this.getValue(true);
181 }
182
183}
184
185let applyAnimatedValues;
186function injectApplyAnimatedValues(fn, transform) {
187 applyAnimatedValues = {
188 fn,
189 transform
190 };
191}
192let colorNames;
193function injectColorNames(names) {
194 colorNames = names;
195}
196let requestFrame = cb => typeof window !== 'undefined' ? window.requestAnimationFrame(cb) : -1;
197let cancelFrame = id => {
198 typeof window !== 'undefined' && window.cancelAnimationFrame(id);
199};
200function injectFrame(raf, caf) {
201 requestFrame = raf;
202 cancelFrame = caf;
203}
204let interpolation;
205function injectStringInterpolator(fn) {
206 interpolation = fn;
207}
208let now = () => Date.now();
209function injectNow(nowFn) {
210 now = nowFn;
211}
212let defaultElement;
213function injectDefaultElement(el) {
214 defaultElement = el;
215}
216let animatedApi = node => node.current;
217function injectAnimatedApi(fn) {
218 animatedApi = fn;
219}
220let createAnimatedStyle;
221function injectCreateAnimatedStyle(factory) {
222 createAnimatedStyle = factory;
223}
224let manualFrameloop = false;
225function injectManualFrameloop(manual) {
226 manualFrameloop = manual;
227}
228
229var Globals = /*#__PURE__*/Object.freeze({
230 get applyAnimatedValues () { return applyAnimatedValues; },
231 injectApplyAnimatedValues: injectApplyAnimatedValues,
232 get colorNames () { return colorNames; },
233 injectColorNames: injectColorNames,
234 get requestFrame () { return requestFrame; },
235 get cancelFrame () { return cancelFrame; },
236 injectFrame: injectFrame,
237 get interpolation () { return interpolation; },
238 injectStringInterpolator: injectStringInterpolator,
239 get now () { return now; },
240 injectNow: injectNow,
241 get defaultElement () { return defaultElement; },
242 injectDefaultElement: injectDefaultElement,
243 get animatedApi () { return animatedApi; },
244 injectAnimatedApi: injectAnimatedApi,
245 get createAnimatedStyle () { return createAnimatedStyle; },
246 injectCreateAnimatedStyle: injectCreateAnimatedStyle,
247 get manualFrameloop () { return manualFrameloop; },
248 injectManualFrameloop: injectManualFrameloop
249});
250
251/**
252 * Wraps the `style` property with `AnimatedStyle`.
253 */
254
255class AnimatedProps extends AnimatedObject {
256 constructor(props, callback) {
257 super();
258 this.update = void 0;
259 this.payload = !props.style ? props : _extends({}, props, {
260 style: createAnimatedStyle(props.style)
261 });
262 this.update = callback;
263 this.attach();
264 }
265
266}
267
268const createAnimatedComponent = Component => {
269 const AnimatedComponent = forwardRef((props, _ref) => {
270 const forceUpdate = useForceUpdate();
271 const mounted = useRef(true);
272 const propsAnimated = useRef(null);
273 const node = useRef(null);
274 const attachProps = useCallback(props => {
275 const oldPropsAnimated = propsAnimated.current;
276
277 const callback = () => {
278 if (node.current) {
279 const didUpdate = applyAnimatedValues.fn(node.current, propsAnimated.current.getAnimatedValue());
280 if (didUpdate === false) forceUpdate();
281 }
282 };
283
284 propsAnimated.current = new AnimatedProps(props, callback);
285 oldPropsAnimated && oldPropsAnimated.detach();
286 }, []);
287 useEffect(() => () => {
288 mounted.current = false;
289 propsAnimated.current && propsAnimated.current.detach();
290 }, []);
291 useImperativeHandle(_ref, () => animatedApi(node, mounted, forceUpdate));
292 attachProps(props);
293
294 const _getValue = propsAnimated.current.getValue(),
295 scrollTop = _getValue.scrollTop,
296 scrollLeft = _getValue.scrollLeft,
297 animatedProps = _objectWithoutPropertiesLoose(_getValue, ["scrollTop", "scrollLeft"]);
298
299 return React.createElement(Component, _extends({}, animatedProps, {
300 ref: childRef => node.current = handleRef(childRef, _ref)
301 }));
302 });
303 return AnimatedComponent;
304};
305
306function createInterpolator(range, output, extrapolate) {
307 if (typeof range === 'function') {
308 return range;
309 }
310
311 if (Array.isArray(range)) {
312 return createInterpolator({
313 range,
314 output: output,
315 extrapolate
316 });
317 }
318
319 if (interpolation && typeof range.output[0] === 'string') {
320 return interpolation(range);
321 }
322
323 const config = range;
324 const outputRange = config.output;
325 const inputRange = config.range || [0, 1];
326 const extrapolateLeft = config.extrapolateLeft || config.extrapolate || 'extend';
327 const extrapolateRight = config.extrapolateRight || config.extrapolate || 'extend';
328
329 const easing = config.easing || (t => t);
330
331 return input => {
332 const range = findRange(input, inputRange);
333 return interpolate(input, inputRange[range], inputRange[range + 1], outputRange[range], outputRange[range + 1], easing, extrapolateLeft, extrapolateRight, config.map);
334 };
335}
336
337function interpolate(input, inputMin, inputMax, outputMin, outputMax, easing, extrapolateLeft, extrapolateRight, map) {
338 let result = map ? map(input) : input; // Extrapolate
339
340 if (result < inputMin) {
341 if (extrapolateLeft === 'identity') return result;else if (extrapolateLeft === 'clamp') result = inputMin;
342 }
343
344 if (result > inputMax) {
345 if (extrapolateRight === 'identity') return result;else if (extrapolateRight === 'clamp') result = inputMax;
346 }
347
348 if (outputMin === outputMax) return outputMin;
349 if (inputMin === inputMax) return input <= inputMin ? outputMin : outputMax; // Input Range
350
351 if (inputMin === -Infinity) result = -result;else if (inputMax === Infinity) result = result - inputMin;else result = (result - inputMin) / (inputMax - inputMin); // Easing
352
353 result = easing(result); // Output Range
354
355 if (outputMin === -Infinity) result = -result;else if (outputMax === Infinity) result = result + outputMin;else result = result * (outputMax - outputMin) + outputMin;
356 return result;
357}
358
359function findRange(input, inputRange) {
360 for (var i = 1; i < inputRange.length - 1; ++i) if (inputRange[i] >= input) break;
361
362 return i - 1;
363}
364
365class AnimatedInterpolation extends AnimatedArray {
366 constructor(parents, range, output) {
367 super();
368 this.calc = void 0;
369 this.payload = parents instanceof AnimatedArray && !(parents instanceof AnimatedInterpolation) ? parents.getPayload() : Array.isArray(parents) ? parents : [parents];
370 this.calc = createInterpolator(range, output);
371 }
372
373 getValue() {
374 return this.calc(...this.payload.map(value => value.getValue()));
375 }
376
377 updateConfig(range, output) {
378 this.calc = createInterpolator(range, output);
379 }
380
381 interpolate(range, output) {
382 return new AnimatedInterpolation(this, range, output);
383 }
384
385}
386
387const interpolate$1 = (parents, range, output) => parents && new AnimatedInterpolation(parents, range, output);
388
389const config = {
390 default: {
391 tension: 170,
392 friction: 26
393 },
394 gentle: {
395 tension: 120,
396 friction: 14
397 },
398 wobbly: {
399 tension: 180,
400 friction: 12
401 },
402 stiff: {
403 tension: 210,
404 friction: 20
405 },
406 slow: {
407 tension: 280,
408 friction: 60
409 },
410 molasses: {
411 tension: 280,
412 friction: 120
413 }
414};
415
416/** API
417 * useChain(references, timeSteps, timeFrame)
418 */
419
420function useChain(refs, timeSteps, timeFrame) {
421 if (timeFrame === void 0) {
422 timeFrame = 1000;
423 }
424
425 const previous = useRef();
426 useEffect(() => {
427 if (is.equ(refs, previous.current)) refs.forEach((_ref) => {
428 let current = _ref.current;
429 return current && current.start();
430 });else if (timeSteps) {
431 refs.forEach((_ref2, index) => {
432 let current = _ref2.current;
433
434 if (current) {
435 const ctrls = current.controllers;
436
437 if (ctrls.length) {
438 const t = timeFrame * timeSteps[index];
439 ctrls.forEach(ctrl => {
440 ctrl.queue = ctrl.queue.map(e => _extends({}, e, {
441 delay: e.delay + t
442 }));
443 ctrl.start();
444 });
445 }
446 }
447 });
448 } else refs.reduce((q, _ref3, rI) => {
449 let current = _ref3.current;
450 return q = q.then(() => current.start());
451 }, Promise.resolve());
452 previous.current = refs;
453 });
454}
455
456/**
457 * Animated works by building a directed acyclic graph of dependencies
458 * transparently when you render your Animated components.
459 *
460 * new Animated.Value(0)
461 * .interpolate() .interpolate() new Animated.Value(1)
462 * opacity translateY scale
463 * style transform
464 * View#234 style
465 * View#123
466 *
467 * A) Top Down phase
468 * When an AnimatedValue is updated, we recursively go down through this
469 * graph in order to find leaf nodes: the views that we flag as needing
470 * an update.
471 *
472 * B) Bottom Up phase
473 * When a view is flagged as needing an update, we recursively go back up
474 * in order to build the new value that it needs. The reason why we need
475 * this two-phases process is to deal with composite props such as
476 * transform which can receive values from multiple parents.
477 */
478function addAnimatedStyles(node, styles) {
479 if ('update' in node) {
480 styles.add(node);
481 } else {
482 node.getChildren().forEach(child => addAnimatedStyles(child, styles));
483 }
484}
485
486class AnimatedValue extends Animated {
487 constructor(_value) {
488 var _this;
489
490 super();
491 _this = this;
492 this.animatedStyles = new Set();
493 this.value = void 0;
494 this.startPosition = void 0;
495 this.lastPosition = void 0;
496 this.lastVelocity = void 0;
497 this.startTime = void 0;
498 this.lastTime = void 0;
499 this.done = false;
500
501 this.setValue = function (value, flush) {
502 if (flush === void 0) {
503 flush = true;
504 }
505
506 _this.value = value;
507 if (flush) _this.flush();
508 };
509
510 this.value = _value;
511 this.startPosition = _value;
512 this.lastPosition = _value;
513 }
514
515 flush() {
516 if (this.animatedStyles.size === 0) {
517 addAnimatedStyles(this, this.animatedStyles);
518 }
519
520 this.animatedStyles.forEach(animatedStyle => animatedStyle.update());
521 }
522
523 clearStyles() {
524 this.animatedStyles.clear();
525 }
526
527 getValue() {
528 return this.value;
529 }
530
531 interpolate(range, output) {
532 return new AnimatedInterpolation(this, range, output);
533 }
534
535}
536
537class AnimatedValueArray extends AnimatedArray {
538 constructor(values) {
539 super();
540 this.payload = values.map(n => new AnimatedValue(n));
541 }
542
543 setValue(value, flush) {
544 if (flush === void 0) {
545 flush = true;
546 }
547
548 if (Array.isArray(value)) {
549 if (value.length === this.payload.length) {
550 value.forEach((v, i) => this.payload[i].setValue(v, flush));
551 }
552 } else {
553 this.payload.forEach(p => p.setValue(value, flush));
554 }
555 }
556
557 getValue() {
558 return this.payload.map(v => v.getValue());
559 }
560
561 interpolate(range, output) {
562 return new AnimatedInterpolation(this, range, output);
563 }
564
565}
566
567let active = false;
568const controllers = new Set();
569
570const update = () => {
571 if (!active) return;
572 let time = now();
573
574 for (let controller of controllers) {
575 let isActive = false;
576
577 for (let configIdx = 0; configIdx < controller.configs.length; configIdx++) {
578 let config = controller.configs[configIdx];
579 let endOfAnimation, lastTime;
580
581 for (let valIdx = 0; valIdx < config.animatedValues.length; valIdx++) {
582 let animation = config.animatedValues[valIdx]; // If an animation is done, skip, until all of them conclude
583
584 if (animation.done) continue;
585 let from = config.fromValues[valIdx];
586 let to = config.toValues[valIdx];
587 let position = animation.lastPosition;
588 let isAnimated = to instanceof Animated;
589 let velocity = Array.isArray(config.initialVelocity) ? config.initialVelocity[valIdx] : config.initialVelocity;
590 if (isAnimated) to = to.getValue(); // Conclude animation if it's either immediate, or from-values match end-state
591
592 if (config.immediate) {
593 animation.setValue(to);
594 animation.done = true;
595 continue;
596 } // Break animation when string values are involved
597
598
599 if (typeof from === 'string' || typeof to === 'string') {
600 animation.setValue(to);
601 animation.done = true;
602 continue;
603 }
604
605 if (config.duration !== void 0) {
606 /** Duration easing */
607 position = from + config.easing((time - animation.startTime) / config.duration) * (to - from);
608 endOfAnimation = time >= animation.startTime + config.duration;
609 } else if (config.decay) {
610 /** Decay easing */
611 position = from + velocity / (1 - 0.998) * (1 - Math.exp(-(1 - 0.998) * (time - controller.startTime)));
612 endOfAnimation = Math.abs(animation.lastPosition - position) < 0.1;
613 if (endOfAnimation) to = position;
614 } else {
615 /** Spring easing */
616 lastTime = animation.lastTime !== void 0 ? animation.lastTime : time;
617 velocity = animation.lastVelocity !== void 0 ? animation.lastVelocity : config.initialVelocity; // If we lost a lot of frames just jump to the end.
618
619 if (time > lastTime + 64) lastTime = time; // http://gafferongames.com/game-physics/fix-your-timestep/
620
621 let numSteps = Math.floor(time - lastTime);
622
623 for (let i = 0; i < numSteps; ++i) {
624 let force = -config.tension * (position - to);
625 let damping = -config.friction * velocity;
626 let acceleration = (force + damping) / config.mass;
627 velocity = velocity + acceleration * 1 / 1000;
628 position = position + velocity * 1 / 1000;
629 } // Conditions for stopping the spring animation
630
631
632 let isOvershooting = config.clamp && config.tension !== 0 ? from < to ? position > to : position < to : false;
633 let isVelocity = Math.abs(velocity) <= config.precision;
634 let isDisplacement = config.tension !== 0 ? Math.abs(to - position) <= config.precision : true;
635 endOfAnimation = isOvershooting || isVelocity && isDisplacement;
636 animation.lastVelocity = velocity;
637 animation.lastTime = time;
638 } // Trails aren't done until their parents conclude
639
640
641 if (isAnimated && !config.toValues[valIdx].done) endOfAnimation = false;
642
643 if (endOfAnimation) {
644 // Ensure that we end up with a round value
645 if (animation.value !== to) position = to;
646 animation.done = true;
647 } else isActive = true;
648
649 animation.setValue(position);
650 animation.lastPosition = position;
651 } // Keep track of updated values only when necessary
652
653
654 if (controller.props.onFrame) controller.values[config.name] = config.interpolation.getValue();
655 } // Update callbacks in the end of the frame
656
657
658 if (controller.props.onFrame) controller.props.onFrame(controller.values); // Either call onEnd or next frame
659
660 if (!isActive) {
661 controllers.delete(controller);
662 controller.stop(true);
663 }
664 } // Loop over as long as there are controllers ...
665
666
667 if (controllers.size) {
668 if (!manualFrameloop) requestFrame(update);
669 } else active = false;
670};
671
672const start = controller => {
673 if (!controllers.has(controller)) {
674 controllers.add(controller);
675 if (!active && !manualFrameloop) requestFrame(update);
676 active = true;
677 }
678};
679
680const stop = controller => {
681 if (controllers.has(controller)) controllers.delete(controller);
682};
683
684let G = 0;
685
686class Controller {
687 constructor() {
688 this.id = void 0;
689 this.idle = true;
690 this.hasChanged = false;
691 this.guid = 0;
692 this.local = 0;
693 this.props = {};
694 this.merged = {};
695 this.animations = {};
696 this.interpolations = {};
697 this.values = {};
698 this.configs = [];
699 this.listeners = [];
700 this.queue = [];
701 this.localQueue = void 0;
702
703 this.getValues = () => this.interpolations;
704
705 this.id = G++;
706 }
707 /** update(props)
708 * This function filters input props and creates an array of tasks which are executed in .start()
709 * Each task is allowed to carry a delay, which means it can execute asnychroneously */
710
711
712 update(args) {
713 //this._id = n + this.id
714 if (!args) return this; // Extract delay and the to-prop from props
715
716 const _ref = interpolateTo(args),
717 _ref$delay = _ref.delay,
718 delay = _ref$delay === void 0 ? 0 : _ref$delay,
719 to = _ref.to,
720 props = _objectWithoutPropertiesLoose(_ref, ["delay", "to"]);
721
722 if (is.arr(to) || is.fun(to)) {
723 // If config is either a function or an array queue it up as is
724 this.queue.push(_extends({}, props, {
725 delay,
726 to
727 }));
728 } else if (to) {
729 // Otherwise go through each key since it could be delayed individually
730 let merge$$1 = {};
731 Object.entries(to).forEach((_ref2) => {
732 let k = _ref2[0],
733 v = _ref2[1];
734
735 // Fetch delay and create an entry, consisting of the to-props, the delay, and basic props
736 const entry = _extends({
737 to: {
738 [k]: v
739 },
740 delay: callProp(delay, k)
741 }, props); // If it doesn't have a delay, merge it, otherwise add it to the queue
742
743
744 if (!entry.delay) merge$$1 = _extends({}, merge$$1, entry, {
745 to: _extends({}, merge$$1.to, entry.to)
746 });else this.queue = [...this.queue, entry];
747 }); // Append merged props, if present
748
749 if (Object.keys(merge$$1).length > 0) this.queue = [...this.queue, merge$$1];
750 } // Sort queue, so that async calls go last
751
752
753 this.queue = this.queue.sort((a, b) => a.delay - b.delay); // Diff the reduced props immediately (they'll contain the from-prop and some config)
754
755 this.diff(props);
756 return this;
757 }
758 /** start(onEnd)
759 * This function either executes a queue, if present, or starts the frameloop, which animates */
760
761
762 start(onEnd) {
763 // If a queue is present we must excecute it
764 if (this.queue.length) {
765 this.idle = false; // Updates can interrupt trailing queues, in that case we just merge values
766
767 if (this.localQueue) {
768 this.localQueue.forEach((_ref3) => {
769 let _ref3$from = _ref3.from,
770 from = _ref3$from === void 0 ? {} : _ref3$from,
771 _ref3$to = _ref3.to,
772 to = _ref3$to === void 0 ? {} : _ref3$to;
773 if (is.obj(from)) this.merged = _extends({}, from, this.merged);
774 if (is.obj(to)) this.merged = _extends({}, this.merged, to);
775 });
776 } // The guid helps us tracking frames, a new queue over an old one means an override
777 // We discard async calls in that caseÍ
778
779
780 const local = this.local = ++this.guid;
781 const queue = this.localQueue = this.queue;
782 this.queue = []; // Go through each entry and execute it
783
784 queue.forEach((_ref4, index) => {
785 let delay = _ref4.delay,
786 props = _objectWithoutPropertiesLoose(_ref4, ["delay"]);
787
788 const cb = finished => {
789 if (index === queue.length - 1 && local === this.guid && finished) {
790 this.idle = true;
791 if (this.props.onRest) this.props.onRest(this.merged);
792 }
793
794 if (onEnd) onEnd();
795 }; // Entries can be delayed, ansyc or immediate
796
797
798 let async = is.arr(props.to) || is.fun(props.to);
799
800 if (delay) {
801 setTimeout(() => {
802 if (local === this.guid) {
803 if (async) this.runAsync(props, cb);else this.diff(props).start(cb);
804 }
805 }, delay);
806 } else if (async) this.runAsync(props, cb);else this.diff(props).start(cb);
807 });
808 } // Otherwise we kick of the frameloop
809 else {
810 if (is.fun(onEnd)) this.listeners.push(onEnd);
811 if (this.props.onStart) this.props.onStart();
812 start(this);
813 }
814
815 return this;
816 }
817
818 stop(finished) {
819 this.listeners.forEach(onEnd => onEnd(finished));
820 this.listeners = [];
821 return this;
822 }
823 /** Pause sets onEnd listeners free, but also removes the controller from the frameloop */
824
825
826 pause(finished) {
827 this.stop(true);
828 if (finished) stop(this);
829 return this;
830 }
831
832 runAsync(_ref5, onEnd) {
833 var _this = this;
834
835 let delay = _ref5.delay,
836 props = _objectWithoutPropertiesLoose(_ref5, ["delay"]);
837
838 const local = this.local; // If "to" is either a function or an array it will be processed async, therefor "to" should be empty right now
839 // If the view relies on certain values "from" has to be present
840
841 let queue = Promise.resolve(undefined);
842
843 if (is.arr(props.to)) {
844 for (let i = 0; i < props.to.length; i++) {
845 const index = i;
846
847 const fresh = _extends({}, props, {
848 to: props.to[index]
849 });
850
851 if (is.arr(fresh.config)) fresh.config = fresh.config[index];
852 queue = queue.then(() => {
853 //this.stop()
854 if (local === this.guid) return new Promise(r => this.diff(interpolateTo(fresh)).start(r));
855 });
856 }
857 } else if (is.fun(props.to)) {
858 let index = 0;
859 let last;
860 queue = queue.then(() => props.to( // next(props)
861 p => {
862 const fresh = _extends({}, props, interpolateTo(p));
863
864 if (is.arr(fresh.config)) fresh.config = fresh.config[index];
865 index++; //this.stop()
866
867 if (local === this.guid) return last = new Promise(r => this.diff(fresh).start(r));
868 return;
869 }, // cancel()
870 function (finished) {
871 if (finished === void 0) {
872 finished = true;
873 }
874
875 return _this.stop(finished);
876 }).then(() => last));
877 }
878
879 queue.then(onEnd);
880 }
881
882 diff(props) {
883 this.props = _extends({}, this.props, props);
884 let _this$props = this.props,
885 _this$props$from = _this$props.from,
886 from = _this$props$from === void 0 ? {} : _this$props$from,
887 _this$props$to = _this$props.to,
888 to = _this$props$to === void 0 ? {} : _this$props$to,
889 _this$props$config = _this$props.config,
890 config = _this$props$config === void 0 ? {} : _this$props$config,
891 reverse = _this$props.reverse,
892 attach = _this$props.attach,
893 reset = _this$props.reset,
894 immediate = _this$props.immediate; // Reverse values when requested
895
896 if (reverse) {
897 var _ref6 = [to, from];
898 from = _ref6[0];
899 to = _ref6[1];
900 } // This will collect all props that were ever set, reset merged props when necessary
901
902
903 this.merged = _extends({}, from, this.merged, to);
904 this.hasChanged = false; // Attachment handling, trailed springs can "attach" themselves to a previous spring
905
906 let target = attach && attach(this); // Reduces input { name: value } pairs into animated values
907
908 this.animations = Object.entries(this.merged).reduce((acc, _ref7) => {
909 let name = _ref7[0],
910 value = _ref7[1];
911 // Issue cached entries, except on reset
912 let entry = acc[name] || {}; // Figure out what the value is supposed to be
913
914 const isNumber = is.num(value);
915 const isString = is.str(value) && !value.startsWith('#') && !/\d/.test(value) && !colorNames[value];
916 const isArray = is.arr(value);
917 const isInterpolation = !isNumber && !isArray && !isString;
918 let fromValue = !is.und(from[name]) ? from[name] : value;
919 let toValue = isNumber || isArray ? value : isString ? value : 1;
920 let toConfig = callProp(config, name);
921 if (target) toValue = target.animations[name].parent;
922 let parent = entry.parent,
923 interpolation$$1 = entry.interpolation,
924 toValues = toArray(target ? toValue.getPayload() : toValue),
925 animatedValues;
926 let newValue = value;
927 if (isInterpolation) newValue = interpolation({
928 range: [0, 1],
929 output: [value, value]
930 })(1);
931 let currentValue = interpolation$$1 && interpolation$$1.getValue(); // Change detection flags
932
933 const isFirst = is.und(parent);
934 const isActive = !isFirst && entry.animatedValues.some(v => !v.done);
935 const currentValueDiffersFromGoal = !is.equ(newValue, currentValue);
936 const hasNewGoal = !is.equ(newValue, entry.previous);
937 const hasNewConfig = !is.equ(toConfig, entry.config); // Change animation props when props indicate a new goal (new value differs from previous one)
938 // and current values differ from it. Config changes trigger a new update as well (though probably shouldn't?)
939
940 if (reset || hasNewGoal && currentValueDiffersFromGoal || hasNewConfig) {
941 // Convert regular values into animated values, ALWAYS re-use if possible
942 if (isNumber || isString) parent = interpolation$$1 = entry.parent || new AnimatedValue(fromValue);else if (isArray) parent = interpolation$$1 = entry.parent || new AnimatedValueArray(fromValue);else if (isInterpolation) {
943 let prev = entry.interpolation && entry.interpolation.calc(entry.parent.value);
944 prev = prev !== void 0 && !reset ? prev : fromValue;
945
946 if (entry.parent) {
947 parent = entry.parent;
948 parent.setValue(0, false);
949 } else parent = new AnimatedValue(0);
950
951 const range = {
952 output: [prev, value]
953 };
954
955 if (entry.interpolation) {
956 interpolation$$1 = entry.interpolation;
957 entry.interpolation.updateConfig(range);
958 } else interpolation$$1 = parent.interpolate(range);
959 }
960 toValues = toArray(target ? toValue.getPayload() : toValue);
961 animatedValues = toArray(parent.getPayload());
962 if (reset && !isInterpolation) parent.setValue(fromValue, false);
963 this.hasChanged = true; // Reset animated values
964
965 animatedValues.forEach(value => {
966 value.startPosition = value.value;
967 value.lastPosition = value.value;
968 value.lastVelocity = isActive ? value.lastVelocity : undefined;
969 value.lastTime = isActive ? value.lastTime : undefined;
970 value.startTime = now();
971 value.done = false;
972 value.animatedStyles.clear();
973 }); // Set immediate values
974
975 if (callProp(immediate, name)) parent.setValue(value, false);
976 return _extends({}, acc, {
977 [name]: _extends({}, entry, {
978 name,
979 parent,
980 interpolation: interpolation$$1,
981 animatedValues,
982 toValues,
983 previous: newValue,
984 config: toConfig,
985 fromValues: toArray(parent.getValue()),
986 immediate: callProp(immediate, name),
987 initialVelocity: withDefault(toConfig.velocity, 0),
988 clamp: withDefault(toConfig.clamp, false),
989 precision: withDefault(toConfig.precision, 0.01),
990 tension: withDefault(toConfig.tension, 170),
991 friction: withDefault(toConfig.friction, 26),
992 mass: withDefault(toConfig.mass, 1),
993 duration: toConfig.duration,
994 easing: withDefault(toConfig.easing, t => t),
995 decay: toConfig.decay
996 })
997 });
998 } else {
999 if (!currentValueDiffersFromGoal) {
1000 // So ... the current target value (newValue) appears to be different from the previous value,
1001 // which normally constitutes an update, but the actual value (currentValue) matches the target!
1002 // In order to resolve this without causing an animation update we silently flag the animation as done,
1003 // which it technically is. Interpolations also needs a config update with their target set to 1.
1004 if (isInterpolation) {
1005 parent.setValue(1, false);
1006 interpolation$$1.updateConfig({
1007 output: [newValue, newValue]
1008 });
1009 }
1010
1011 parent.done = true;
1012 this.hasChanged = true;
1013 return _extends({}, acc, {
1014 [name]: _extends({}, acc[name], {
1015 previous: newValue
1016 })
1017 });
1018 }
1019
1020 return acc;
1021 }
1022 }, this.animations);
1023
1024 if (this.hasChanged) {
1025 // Make animations available to frameloop
1026 this.configs = Object.values(this.animations);
1027 this.values = {};
1028 this.interpolations = {};
1029
1030 for (let key in this.animations) {
1031 this.interpolations[key] = this.animations[key].interpolation;
1032 this.values[key] = this.animations[key].interpolation.getValue();
1033 }
1034 }
1035
1036 return this;
1037 }
1038
1039 destroy() {
1040 this.stop();
1041 this.props = {};
1042 this.merged = {};
1043 this.animations = {};
1044 this.interpolations = {};
1045 this.values = {};
1046 this.configs = [];
1047 this.local = 0;
1048 }
1049
1050}
1051
1052/** API
1053 * const props = useSprings(number, [{ ... }, { ... }, ...])
1054 * const [props, set] = useSprings(number, (i, controller) => ({ ... }))
1055 */
1056
1057const useSprings = (length, props) => {
1058 const mounted = useRef(false);
1059 const ctrl = useRef();
1060 const isFn = is.fun(props); // The controller maintains the animation values, starts and stops animations
1061
1062 const _useMemo = useMemo(() => {
1063 // Remove old controllers
1064 if (ctrl.current) {
1065 ctrl.current.map(c => c.destroy());
1066 ctrl.current = undefined;
1067 }
1068
1069 let ref;
1070 return [new Array(length).fill().map((_, i) => {
1071 const ctrl = new Controller();
1072 const newProps = isFn ? callProp(props, i, ctrl) : props[i];
1073 if (i === 0) ref = newProps.ref;
1074 ctrl.update(newProps);
1075 if (!ref) ctrl.start();
1076 return ctrl;
1077 }), ref];
1078 }, [length]),
1079 controllers = _useMemo[0],
1080 ref = _useMemo[1];
1081
1082 ctrl.current = controllers; // The hooks reference api gets defined here ...
1083
1084 const api = useImperativeHandle(ref, () => ({
1085 start: () => Promise.all(ctrl.current.map(c => new Promise(r => c.start(r)))),
1086 stop: finished => ctrl.current.forEach(c => c.stop(finished)),
1087
1088 get controllers() {
1089 return ctrl.current;
1090 }
1091
1092 })); // This function updates the controllers
1093
1094 const updateCtrl = useMemo(() => updateProps => ctrl.current.map((c, i) => {
1095 c.update(isFn ? callProp(updateProps, i, c) : updateProps[i]);
1096 if (!ref) c.start();
1097 }), [length]); // Update controller if props aren't functional
1098
1099 useEffect(() => {
1100 if (mounted.current) {
1101 if (!isFn) updateCtrl(props);
1102 } else if (!ref) ctrl.current.forEach(c => c.start());
1103 }); // Update mounted flag and destroy controller on unmount
1104
1105 useEffect(() => (mounted.current = true, () => ctrl.current.forEach(c => c.destroy())), []); // Return animated props, or, anim-props + the update-setter above
1106
1107 const propValues = ctrl.current.map(c => c.getValues());
1108 return isFn ? [propValues, updateCtrl, finished => ctrl.current.forEach(c => c.pause(finished))] : propValues;
1109};
1110
1111/** API
1112 * const props = useSpring({ ... })
1113 * const [props, set] = useSpring(() => ({ ... }))
1114 */
1115
1116const useSpring = props => {
1117 const isFn = is.fun(props);
1118
1119 const _useSprings = useSprings(1, isFn ? props : [props]),
1120 result = _useSprings[0],
1121 set = _useSprings[1],
1122 pause = _useSprings[2];
1123
1124 return isFn ? [result[0], set, pause] : result;
1125};
1126
1127/** API
1128 * const trails = useTrail(number, { ... })
1129 * const [trails, set] = useTrail(number, () => ({ ... }))
1130 */
1131
1132const useTrail = (length, props) => {
1133 const mounted = useRef(false);
1134 const isFn = is.fun(props);
1135 const updateProps = callProp(props);
1136 const instances = useRef();
1137
1138 const _useSprings = useSprings(length, (i, ctrl) => {
1139 if (i === 0) instances.current = [];
1140 instances.current.push(ctrl);
1141 return _extends({}, updateProps, {
1142 config: callProp(updateProps.config, i),
1143 attach: i > 0 && (() => instances.current[i - 1])
1144 });
1145 }),
1146 result = _useSprings[0],
1147 set = _useSprings[1],
1148 pause = _useSprings[2]; // Set up function to update controller
1149
1150
1151 const updateCtrl = useMemo(() => props => set((i, ctrl) => {
1152 const last = props.reverse ? i === 0 : length - 1 === i;
1153 const attachIdx = props.reverse ? i + 1 : i - 1;
1154 const attachController = instances.current[attachIdx];
1155 return _extends({}, props, {
1156 config: callProp(props.config || updateProps.config, i),
1157 attach: attachController && (() => attachController)
1158 });
1159 }), [length, updateProps.reverse]); // Update controller if props aren't functional
1160
1161 useEffect(() => void (mounted.current && !isFn && updateCtrl(props))); // Update mounted flag and destroy controller on unmount
1162
1163 useEffect(() => void (mounted.current = true), []);
1164 return isFn ? [result, updateCtrl, pause] : result;
1165};
1166
1167/** API
1168 * const transitions = useTransition(items, itemKeys, { ... })
1169 * const [transitions, update] = useTransition(items, itemKeys, () => ({ ... }))
1170 */
1171
1172let guid = 0;
1173const ENTER = 'enter';
1174const LEAVE = 'leave';
1175const UPDATE = 'update';
1176
1177const mapKeys = (items, keys) => (typeof keys === 'function' ? items.map(keys) : toArray(keys)).map(String);
1178
1179const get = props => {
1180 let items = props.items,
1181 _props$keys = props.keys,
1182 keys = _props$keys === void 0 ? item => item : _props$keys,
1183 rest = _objectWithoutPropertiesLoose(props, ["items", "keys"]);
1184
1185 items = toArray(items !== void 0 ? items : null);
1186 return _extends({
1187 items,
1188 keys: mapKeys(items, keys)
1189 }, rest);
1190};
1191
1192function useTransition(input, keyTransform, config) {
1193 const props = _extends({
1194 items: input,
1195 keys: keyTransform || (i => i)
1196 }, config);
1197
1198 const _get = get(props),
1199 _get$lazy = _get.lazy,
1200 lazy = _get$lazy === void 0 ? false : _get$lazy,
1201 _get$unique = _get.unique,
1202 _get$reset = _get.reset,
1203 reset = _get$reset === void 0 ? false : _get$reset,
1204 enter = _get.enter,
1205 leave = _get.leave,
1206 update = _get.update,
1207 onDestroyed = _get.onDestroyed,
1208 keys = _get.keys,
1209 items = _get.items,
1210 onFrame = _get.onFrame,
1211 _onRest = _get.onRest,
1212 onStart = _get.onStart,
1213 ref = _get.ref,
1214 extra = _objectWithoutPropertiesLoose(_get, ["lazy", "unique", "reset", "enter", "leave", "update", "onDestroyed", "keys", "items", "onFrame", "onRest", "onStart", "ref"]);
1215
1216 const forceUpdate = useForceUpdate();
1217 const mounted = useRef(false);
1218 const state = useRef({
1219 mounted: false,
1220 first: true,
1221 deleted: [],
1222 current: {},
1223 transitions: [],
1224 prevProps: {},
1225 paused: !!props.ref,
1226 instances: !mounted.current && new Map(),
1227 forceUpdate
1228 });
1229 useImperativeHandle(props.ref, () => ({
1230 start: () => Promise.all(Array.from(state.current.instances).map((_ref) => {
1231 let c = _ref[1];
1232 return new Promise(r => c.start(r));
1233 })),
1234 stop: finished => Array.from(state.current.instances).forEach((_ref2) => {
1235 let c = _ref2[1];
1236 return c.stop(finished);
1237 }),
1238
1239 get controllers() {
1240 return Array.from(state.current.instances).map((_ref3) => {
1241 let c = _ref3[1];
1242 return c;
1243 });
1244 }
1245
1246 })); // Update state
1247
1248 state.current = diffItems(state.current, props);
1249
1250 if (state.current.changed) {
1251 // Update state
1252 state.current.transitions.forEach(transition => {
1253 const slot = transition.slot,
1254 from = transition.from,
1255 to = transition.to,
1256 config = transition.config,
1257 trail = transition.trail,
1258 key = transition.key,
1259 item = transition.item;
1260 if (!state.current.instances.has(key)) state.current.instances.set(key, new Controller()); // update the map object
1261
1262 const ctrl = state.current.instances.get(key);
1263
1264 const newProps = _extends({}, extra, {
1265 to,
1266 from,
1267 config,
1268 ref,
1269 onRest: values => {
1270 if (state.current.mounted) {
1271 if (transition.destroyed) {
1272 // If no ref is given delete destroyed items immediately
1273 if (!ref && !lazy) cleanUp(state, key);
1274 if (onDestroyed) onDestroyed(item);
1275 } // A transition comes to rest once all its springs conclude
1276
1277
1278 const curInstances = Array.from(state.current.instances);
1279 const active = curInstances.some((_ref4) => {
1280 let c = _ref4[1];
1281 return !c.idle;
1282 });
1283 if (!active && (ref || lazy) && state.current.deleted.length > 0) cleanUp(state);
1284 if (_onRest) _onRest(item, slot, values);
1285 }
1286 },
1287 onStart: onStart && (() => onStart(item, slot)),
1288 onFrame: onFrame && (values => onFrame(item, slot, values)),
1289 delay: trail,
1290 reset: reset && slot === ENTER // Update controller
1291
1292 });
1293
1294 ctrl.update(newProps);
1295 if (!state.current.paused) ctrl.start();
1296 });
1297 }
1298
1299 useEffect(() => {
1300 state.current.mounted = mounted.current = true;
1301 return () => {
1302 state.current.mounted = mounted.current = false;
1303 Array.from(state.current.instances).map((_ref5) => {
1304 let c = _ref5[1];
1305 return c.destroy();
1306 });
1307 state.current.instances.clear();
1308 };
1309 }, []);
1310 return state.current.transitions.map((_ref6) => {
1311 let item = _ref6.item,
1312 slot = _ref6.slot,
1313 key = _ref6.key;
1314 return {
1315 item,
1316 key,
1317 state: slot,
1318 props: state.current.instances.get(key).getValues()
1319 };
1320 });
1321}
1322
1323function cleanUp(state, filterKey) {
1324 const deleted = state.current.deleted;
1325
1326 for (let _ref7 of deleted) {
1327 let key = _ref7.key;
1328
1329 const filter = t => t.key !== key;
1330
1331 if (is.und(filterKey) || filterKey === key) {
1332 state.current.instances.delete(key);
1333 state.current.transitions = state.current.transitions.filter(filter);
1334 state.current.deleted = state.current.deleted.filter(filter);
1335 }
1336 }
1337
1338 state.current.forceUpdate();
1339}
1340
1341function diffItems(_ref8, props) {
1342 let first = _ref8.first,
1343 prevProps = _ref8.prevProps,
1344 state = _objectWithoutPropertiesLoose(_ref8, ["first", "prevProps"]);
1345
1346 let _get2 = get(props),
1347 items = _get2.items,
1348 keys = _get2.keys,
1349 initial = _get2.initial,
1350 from = _get2.from,
1351 enter = _get2.enter,
1352 leave = _get2.leave,
1353 update = _get2.update,
1354 _get2$trail = _get2.trail,
1355 trail = _get2$trail === void 0 ? 0 : _get2$trail,
1356 unique = _get2.unique,
1357 config = _get2.config,
1358 _get2$order = _get2.order,
1359 order = _get2$order === void 0 ? [ENTER, LEAVE, UPDATE] : _get2$order;
1360
1361 let _get3 = get(prevProps),
1362 _keys = _get3.keys,
1363 _items = _get3.items;
1364
1365 let current = _extends({}, state.current);
1366
1367 let deleted = [...state.deleted]; // Compare next keys with current keys
1368
1369 let currentKeys = Object.keys(current);
1370 let currentSet = new Set(currentKeys);
1371 let nextSet = new Set(keys);
1372 let added = keys.filter(item => !currentSet.has(item));
1373 let removed = state.transitions.filter(item => !item.destroyed && !nextSet.has(item.originalKey)).map(i => i.originalKey);
1374 let updated = keys.filter(item => currentSet.has(item));
1375 let delay = -trail;
1376
1377 while (order.length) {
1378 const changeType = order.shift();
1379
1380 switch (changeType) {
1381 case ENTER:
1382 {
1383 added.forEach((key, index) => {
1384 // In unique mode, remove fading out transitions if their key comes in again
1385 if (unique && deleted.find(d => d.originalKey === key)) deleted = deleted.filter(t => t.originalKey !== key);
1386 const keyIndex = keys.indexOf(key);
1387 const item = items[keyIndex];
1388 const slot = first && initial !== void 0 ? 'initial' : ENTER;
1389 current[key] = {
1390 slot,
1391 originalKey: key,
1392 key: unique ? String(key) : guid++,
1393 item,
1394 trail: delay = delay + trail,
1395 config: callProp(config, item, slot),
1396 from: callProp(first ? initial !== void 0 ? initial || {} : from : from, item),
1397 to: callProp(enter, item)
1398 };
1399 });
1400 break;
1401 }
1402
1403 case LEAVE:
1404 {
1405 removed.forEach(key => {
1406 const keyIndex = _keys.indexOf(key);
1407
1408 const item = _items[keyIndex];
1409 const slot = LEAVE;
1410 deleted.unshift(_extends({}, current[key], {
1411 slot,
1412 destroyed: true,
1413 left: _keys[Math.max(0, keyIndex - 1)],
1414 right: _keys[Math.min(_keys.length, keyIndex + 1)],
1415 trail: delay = delay + trail,
1416 config: callProp(config, item, slot),
1417 to: callProp(leave, item)
1418 }));
1419 delete current[key];
1420 });
1421 break;
1422 }
1423
1424 case UPDATE:
1425 {
1426 updated.forEach(key => {
1427 const keyIndex = keys.indexOf(key);
1428 const item = items[keyIndex];
1429 const slot = UPDATE;
1430 current[key] = _extends({}, current[key], {
1431 item,
1432 slot,
1433 trail: delay = delay + trail,
1434 config: callProp(config, item, slot),
1435 to: callProp(update, item)
1436 });
1437 });
1438 break;
1439 }
1440 }
1441 }
1442
1443 let out = keys.map(key => current[key]); // This tries to restore order for deleted items by finding their last known siblings
1444 // only using the left sibling to keep order placement consistent for all deleted items
1445
1446 deleted.forEach((_ref9) => {
1447 let left = _ref9.left,
1448 right = _ref9.right,
1449 item = _objectWithoutPropertiesLoose(_ref9, ["left", "right"]);
1450
1451 let pos; // Was it the element on the left, if yes, move there ...
1452
1453 if ((pos = out.findIndex(t => t.originalKey === left)) !== -1) pos += 1; // And if nothing else helps, move it to the start ¯\_(ツ)_/¯
1454
1455 pos = Math.max(0, pos);
1456 out = [...out.slice(0, pos), item, ...out.slice(pos)];
1457 });
1458 return _extends({}, state, {
1459 changed: added.length || removed.length || updated.length,
1460 first: first && added.length === 0,
1461 transitions: out,
1462 current,
1463 deleted,
1464 prevProps: props
1465 });
1466}
1467
1468// Solution: https://stackoverflow.com/questions/638565/parsing-scientific-notation-sensibly/658662
1469
1470const stringShapeRegex = /[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
1471
1472const createStringInterpolator = config$$1 => {
1473 const outputRange = config$$1.output;
1474 const outputRanges = outputRange[0].match(stringShapeRegex).map(() => []);
1475 outputRange.forEach(value => {
1476 value.match(stringShapeRegex).forEach((number, i) => outputRanges[i].push(+number));
1477 });
1478 const interpolations = outputRange[0].match(stringShapeRegex).map((_, i) => createInterpolator(_extends({}, config$$1, {
1479 output: outputRanges[i]
1480 })));
1481 return input => {
1482 let i = 0;
1483 return outputRange[0].replace(stringShapeRegex, () => interpolations[i++](input));
1484 };
1485};
1486
1487injectStringInterpolator(createStringInterpolator);
1488injectApplyAnimatedValues(() => false, style => style);
1489const apply = merge(createAnimatedComponent, false);
1490const Interpolation = {
1491 create: createInterpolator
1492};
1493
1494export { apply, config, createAnimatedComponent as animated, interpolate$1 as interpolate, Globals, useSpring, useTrail, useTransition, useChain, useSprings, Interpolation };