UNPKG

@larva.io/webcomponents

Version:

Fentrica SmartUnits WebComponents package

1,119 lines (1,115 loc) 37 kB
/*! * (C) Fentrica http://fentrica.com - Seee LICENSE.md */ function transitionEnd(el, callback) { let unRegTrans; const opts = { passive: true }; function unregister() { if (unRegTrans) { unRegTrans(); } } function onTransitionEnd(ev) { if (el === ev.target) { unregister(); callback(ev); } } if (el) { el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts); el.addEventListener('transitionend', onTransitionEnd, opts); unRegTrans = () => { el.removeEventListener('webkitTransitionEnd', onTransitionEnd, opts); el.removeEventListener('transitionend', onTransitionEnd, opts); }; } return unregister; } const CSS_VALUE_REGEX = /(^-?\d*\.?\d*)(.*)/; const DURATION_MIN = 32; const TRANSITION_END_FALLBACK_PADDING_MS = 400; const TRANSFORM_PROPS = { 'translateX': 1, 'translateY': 1, 'translateZ': 1, 'scale': 1, 'scaleX': 1, 'scaleY': 1, 'scaleZ': 1, 'rotate': 1, 'rotateX': 1, 'rotateY': 1, 'rotateZ': 1, 'skewX': 1, 'skewY': 1, 'perspective': 1 }; const win = typeof window !== 'undefined' ? window : {}; const raf = win.requestAnimationFrame ? win.requestAnimationFrame.bind(win) : (f) => f(Date.now()); class Animator { constructor() { this._hasDur = false; this._hasTweenEffect = false; this._isAsync = false; this._isReverse = false; this._destroyed = false; this.hasChildren = false; this.isPlaying = false; this.hasCompleted = false; } addElement(el) { if (el != null) { if (el.length > 0) { for (let i = 0; i < el.length; i++) { this._addEl(el[i]); } } else { this._addEl(el); } } return this; } /** * NO DOM */ _addEl(el) { if (el.nodeType === 1) { (this._elements = this._elements || []).push(el); } } /** * Add a child animation to this animation. */ add(childAnimation) { childAnimation.parent = this; this.hasChildren = true; (this._childAnimations = this._childAnimations || []).push(childAnimation); return this; } /** * Get the duration of this animation. If this animation does * not have a duration, then it'll get the duration from its parent. */ getDuration(opts) { if (opts && opts.duration !== undefined) { return opts.duration; } else if (this._duration !== undefined) { return this._duration; } else if (this.parent) { return this.parent.getDuration(); } return 0; } /** * Returns if the animation is a root one. */ isRoot() { return !this.parent; } /** * Set the duration for this animation. */ duration(milliseconds) { this._duration = milliseconds; return this; } /** * Get the easing of this animation. If this animation does * not have an easing, then it'll get the easing from its parent. */ getEasing() { if (this._isReverse && this._reversedEasingName !== undefined) { return this._reversedEasingName; } return this._easingName !== undefined ? this._easingName : (this.parent && this.parent.getEasing()) || null; } /** * Set the easing for this animation. */ easing(name) { this._easingName = name; return this; } /** * Set the easing for this reversed animation. */ easingReverse(name) { this._reversedEasingName = name; return this; } /** * Add the "from" value for a specific property. */ from(prop, val) { this._addProp('from', prop, val); return this; } /** * Add the "to" value for a specific property. */ to(prop, val, clearProperyAfterTransition = false) { const fx = this._addProp('to', prop, val); if (clearProperyAfterTransition) { // if this effect is a transform then clear the transform effect // otherwise just clear the actual property this.afterClearStyles([fx.trans ? 'transform' : prop]); } return this; } /** * Shortcut to add both the "from" and "to" for the same property. */ fromTo(prop, fromVal, toVal, clearProperyAfterTransition) { return this.from(prop, fromVal).to(prop, toVal, clearProperyAfterTransition); } /** * NO DOM */ _getProp(name) { if (this._fxProperties) { return this._fxProperties.find(prop => prop.effectName === name); } return undefined; } _addProp(state, prop, val) { let fxProp = this._getProp(prop); if (!fxProp) { // first time we've see this EffectProperty const shouldTrans = (TRANSFORM_PROPS[prop] === 1); fxProp = { effectName: prop, trans: shouldTrans, // add the will-change property for transforms or opacity wc: (shouldTrans ? 'transform' : prop) }; (this._fxProperties = this._fxProperties || []).push(fxProp); } // add from/to EffectState to the EffectProperty const fxState = { val, num: 0, effectUnit: '', }; fxProp[state] = fxState; if (typeof val === 'string' && val.indexOf(' ') < 0) { const r = val.match(CSS_VALUE_REGEX); if (r) { const num = parseFloat(r[1]); if (!isNaN(num)) { fxState.num = num; } fxState.effectUnit = (r[0] !== r[2] ? r[2] : ''); } } else if (typeof val === 'number') { fxState.num = val; } return fxProp; } /** * Add CSS class to this animation's elements * before the animation begins. */ beforeAddClass(className) { (this._beforeAddClasses = this._beforeAddClasses || []).push(className); return this; } /** * Remove CSS class from this animation's elements * before the animation begins. */ beforeRemoveClass(className) { (this._beforeRemoveClasses = this._beforeRemoveClasses || []).push(className); return this; } /** * Set CSS inline styles to this animation's elements * before the animation begins. */ beforeStyles(styles) { this._beforeStyles = styles; return this; } /** * Clear CSS inline styles from this animation's elements * before the animation begins. */ beforeClearStyles(propertyNames) { this._beforeStyles = this._beforeStyles || {}; for (const prop of propertyNames) { this._beforeStyles[prop] = ''; } return this; } /** * Add a function which contains DOM reads, which will run * before the animation begins. */ beforeAddRead(domReadFn) { (this._readCallbacks = this._readCallbacks || []).push(domReadFn); return this; } /** * Add a function which contains DOM writes, which will run * before the animation begins. */ beforeAddWrite(domWriteFn) { (this._writeCallbacks = this._writeCallbacks || []).push(domWriteFn); return this; } /** * Add CSS class to this animation's elements * after the animation finishes. */ afterAddClass(className) { (this._afterAddClasses = this._afterAddClasses || []).push(className); return this; } /** * Remove CSS class from this animation's elements * after the animation finishes. */ afterRemoveClass(className) { (this._afterRemoveClasses = this._afterRemoveClasses || []).push(className); return this; } /** * Set CSS inline styles to this animation's elements * after the animation finishes. */ afterStyles(styles) { this._afterStyles = styles; return this; } /** * Clear CSS inline styles from this animation's elements * after the animation finishes. */ afterClearStyles(propertyNames) { this._afterStyles = this._afterStyles || {}; for (const prop of propertyNames) { this._afterStyles[prop] = ''; } return this; } /** * Play the animation. */ play(opts) { // If the animation was already invalidated (it did finish), do nothing if (this._destroyed) { return; } // this is the top level animation and is in full control // of when the async play() should actually kick off // if there is no duration then it'll set the TO property immediately // if there is a duration, then it'll stage all animations at the // FROM property and transition duration, wait a few frames, then // kick off the animation by setting the TO property for each animation this._isAsync = this._hasDuration(opts); // ensure all past transition end events have been cleared this._clearAsync(); // recursively kicks off the correct progress step for each child animation // ******** DOM WRITE **************** this._playInit(opts); // doubling up RAFs since this animation was probably triggered // from an input event, and just having one RAF would have this code // run within the same frame as the triggering input event, and the // input event probably already did way too much work for one frame raf(() => { raf(() => { this._playDomInspect(opts); }); }); } playAsync(opts) { return new Promise(resolve => { this.onFinish(resolve, { oneTimeCallback: true, clearExistingCallbacks: true }); this.play(opts); return this; }); } playSync() { // If the animation was already invalidated (it did finish), do nothing if (!this._destroyed) { const opts = { duration: 0 }; this._isAsync = false; this._clearAsync(); this._playInit(opts); this._playDomInspect(opts); } } /** * DOM WRITE * RECURSION */ _playInit(opts) { // always default that an animation does not tween // a tween requires that an Animation class has an element // and that it has at least one FROM/TO effect // and that the FROM/TO effect can tween numeric values this._hasTweenEffect = false; this.isPlaying = true; this.hasCompleted = false; this._hasDur = (this.getDuration(opts) > DURATION_MIN); const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._playInit(opts); } } if (this._hasDur) { // if there is a duration then we want to start at step 0 // ******** DOM WRITE **************** this._progress(0); // add the will-change properties // ******** DOM WRITE **************** this._willChange(true); } } /** * DOM WRITE * NO RECURSION * ROOT ANIMATION */ _playDomInspect(opts) { // fire off all the "before" function that have DOM READS in them // elements will be in the DOM, however visibily hidden // so we can read their dimensions if need be // ******** DOM READ **************** // ******** DOM WRITE **************** this._beforeAnimation(); // for the root animation only // set the async TRANSITION END event // and run onFinishes when the transition ends const dur = this.getDuration(opts); if (this._isAsync) { this._asyncEnd(dur, true); } // ******** DOM WRITE **************** this._playProgress(opts); if (this._isAsync && !this._destroyed) { // this animation has a duration so we need another RAF // for the CSS TRANSITION properties to kick in raf(() => { this._playToStep(1); }); } } /** * DOM WRITE * RECURSION */ _playProgress(opts) { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._playProgress(opts); } } if (this._hasDur) { // set the CSS TRANSITION duration/easing // ******** DOM WRITE **************** this._setTrans(this.getDuration(opts), false); } else { // this animation does not have a duration, so it should not animate // just go straight to the TO properties and call it done // ******** DOM WRITE **************** this._progress(1); // since there was no animation, immediately run the after // ******** DOM WRITE **************** this._setAfterStyles(); // this animation has no duration, so it has finished // other animations could still be running this._didFinish(true); } } /** * DOM WRITE * RECURSION */ _playToStep(stepValue) { if (!this._destroyed) { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._playToStep(stepValue); } } if (this._hasDur) { // browser had some time to render everything in place // and the transition duration/easing is set // now set the TO properties which will trigger the transition to begin // ******** DOM WRITE **************** this._progress(stepValue); } } } /** * DOM WRITE * NO RECURSION * ROOT ANIMATION */ _asyncEnd(dur, shouldComplete) { const self = this; function onTransitionEnd() { // congrats! a successful transition completed! // ensure transition end events and timeouts have been cleared self._clearAsync(); // ******** DOM WRITE **************** self._playEnd(); // transition finished self._didFinishAll(shouldComplete, true, false); } function onTransitionFallback() { console.debug('Animation onTransitionFallback, CSS onTransitionEnd did not fire!'); // oh noz! the transition end event didn't fire in time! // instead the fallback timer when first // if all goes well this fallback should never fire // clear the other async end events from firing self._timerId = undefined; self._clearAsync(); // set the after styles // ******** DOM WRITE **************** self._playEnd(shouldComplete ? 1 : 0); // transition finished self._didFinishAll(shouldComplete, true, false); } // set the TRANSITION END event on one of the transition elements self._unregisterTrnsEnd = transitionEnd(self._transEl(), onTransitionEnd); // set a fallback timeout if the transition end event never fires, or is too slow // transition end fallback: (animation duration + XXms) self._timerId = setTimeout(onTransitionFallback, (dur + TRANSITION_END_FALLBACK_PADDING_MS)); } /** * DOM WRITE * RECURSION */ _playEnd(stepValue) { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._playEnd(stepValue); } } if (this._hasDur) { if (stepValue !== undefined) { // too late to have a smooth animation, just finish it // ******** DOM WRITE **************** this._setTrans(0, true); // ensure the ending progress step gets rendered // ******** DOM WRITE **************** this._progress(stepValue); } // set the after styles // ******** DOM WRITE **************** this._setAfterStyles(); // remove the will-change properties // ******** DOM WRITE **************** this._willChange(false); } } /** * NO DOM * RECURSION */ _hasDuration(opts) { if (this.getDuration(opts) > DURATION_MIN) { return true; } const children = this._childAnimations; if (children) { for (const child of children) { if (child._hasDuration(opts)) { return true; } } } return false; } /** * NO DOM * RECURSION */ _hasDomReads() { if (this._readCallbacks && this._readCallbacks.length > 0) { return true; } const children = this._childAnimations; if (children) { for (const child of children) { if (child._hasDomReads()) { return true; } } } return false; } /** * Immediately stop at the end of the animation. */ stop(stepValue = 1) { // ensure all past transition end events have been cleared this._clearAsync(); this._hasDur = true; this._playEnd(stepValue); } /** * NO DOM * NO RECURSION */ _clearAsync() { if (this._unregisterTrnsEnd) { this._unregisterTrnsEnd(); } if (this._timerId) { clearTimeout(this._timerId); } this._timerId = this._unregisterTrnsEnd = undefined; } /** * DOM WRITE * NO RECURSION */ _progress(stepValue) { // bread 'n butter let val; const elements = this._elements; const effects = this._fxProperties; if (!elements || elements.length === 0 || !effects || this._destroyed) { return; } // flip the number if we're going in reverse if (this._isReverse) { stepValue = 1 - stepValue; } let i = 0; let j = 0; let finalTransform = ''; let fx; for (i = 0; i < effects.length; i++) { fx = effects[i]; if (fx.from && fx.to) { const fromNum = fx.from.num; const toNum = fx.to.num; const tweenEffect = (fromNum !== toNum); if (tweenEffect) { this._hasTweenEffect = true; } if (stepValue === 0) { // FROM val = fx.from.val; } else if (stepValue === 1) { // TO val = fx.to.val; } else if (tweenEffect) { // EVERYTHING IN BETWEEN const valNum = (((toNum - fromNum) * stepValue) + fromNum); const unit = fx.to.effectUnit; val = valNum + unit; } if (val !== null) { const prop = fx.effectName; if (fx.trans) { finalTransform += prop + '(' + val + ') '; } else { for (j = 0; j < elements.length; j++) { // ******** DOM WRITE **************** elements[j].style.setProperty(prop, val); } } } } } // place all transforms on the same property if (finalTransform.length > 0) { if (!this._isReverse && stepValue !== 1 || this._isReverse && stepValue !== 0) { finalTransform += 'translateZ(0px)'; } for (i = 0; i < elements.length; i++) { // ******** DOM WRITE **************** elements[i].style.setProperty('transform', finalTransform); } } } /** * DOM WRITE * NO RECURSION */ _setTrans(dur, forcedLinearEasing) { // Transition is not enabled if there are not effects const elements = this._elements; if (!elements || elements.length === 0 || !this._fxProperties) { return; } // set the TRANSITION properties inline on the element const easing = (forcedLinearEasing ? 'linear' : this.getEasing()); const durString = dur + 'ms'; for (const { style } of elements) { if (dur > 0) { // ******** DOM WRITE **************** style.transitionDuration = durString; // each animation can have a different easing if (easing !== null) { // ******** DOM WRITE **************** style.transitionTimingFunction = easing; } } else { style.transitionDuration = '0'; } } } /** * DOM READ * DOM WRITE * RECURSION */ _beforeAnimation() { // fire off all the "before" function that have DOM READS in them // elements will be in the DOM, however visibily hidden // so we can read their dimensions if need be // ******** DOM READ **************** this._fireBeforeReadFunc(); // ******** DOM READS ABOVE / DOM WRITES BELOW **************** // fire off all the "before" function that have DOM WRITES in them // ******** DOM WRITE **************** this._fireBeforeWriteFunc(); // stage all of the before css classes and inline styles // ******** DOM WRITE **************** this._setBeforeStyles(); } /** * DOM WRITE * RECURSION */ _setBeforeStyles() { const children = this._childAnimations; if (children) { for (const child of children) { child._setBeforeStyles(); } } const elements = this._elements; // before the animations have started // only set before styles if animation is not reversed if (!elements || elements.length === 0 || this._isReverse) { return; } const addClasses = this._beforeAddClasses; const removeClasses = this._beforeRemoveClasses; for (const el of elements) { const elementClassList = el.classList; // css classes to add before the animation if (addClasses) { for (const c of addClasses) { // ******** DOM WRITE **************** elementClassList.add(c); } } // css classes to remove before the animation if (removeClasses) { for (const c of removeClasses) { // ******** DOM WRITE **************** elementClassList.remove(c); } } // inline styles to add before the animation if (this._beforeStyles) { for (const [key, value] of Object.entries(this._beforeStyles)) { // ******** DOM WRITE **************** el.style.setProperty(key, value); } } } } /** * DOM READ * RECURSION */ _fireBeforeReadFunc() { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM READ **************** child._fireBeforeReadFunc(); } } const readFunctions = this._readCallbacks; if (readFunctions) { for (const callback of readFunctions) { // ******** DOM READ **************** callback(); } } } /** * DOM WRITE * RECURSION */ _fireBeforeWriteFunc() { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._fireBeforeWriteFunc(); } } const writeFunctions = this._writeCallbacks; if (writeFunctions) { for (const callback of writeFunctions) { // ******** DOM WRITE **************** callback(); } } } /** * DOM WRITE */ _setAfterStyles() { const elements = this._elements; if (!elements) { return; } for (const el of elements) { const elementClassList = el.classList; // remove the transition duration/easing // ******** DOM WRITE **************** el.style.transitionDuration = el.style.transitionTimingFunction = ''; if (this._isReverse) { // finished in reverse direction // css classes that were added before the animation should be removed const beforeAddClasses = this._beforeAddClasses; if (beforeAddClasses) { for (const c of beforeAddClasses) { elementClassList.remove(c); } } // css classes that were removed before the animation should be added const beforeRemoveClasses = this._beforeRemoveClasses; if (beforeRemoveClasses) { for (const c of beforeRemoveClasses) { elementClassList.add(c); } } // inline styles that were added before the animation should be removed const beforeStyles = this._beforeStyles; if (beforeStyles) { for (const propName of Object.keys(beforeStyles)) { // ******** DOM WRITE **************** el.style.removeProperty(propName); } } } else { // finished in forward direction // css classes to add after the animation const afterAddClasses = this._afterAddClasses; if (afterAddClasses) { for (const c of afterAddClasses) { // ******** DOM WRITE **************** elementClassList.add(c); } } // css classes to remove after the animation const afterRemoveClasses = this._afterRemoveClasses; if (afterRemoveClasses) { for (const c of afterRemoveClasses) { // ******** DOM WRITE **************** elementClassList.remove(c); } } // inline styles to add after the animation const afterStyles = this._afterStyles; if (afterStyles) { for (const [key, value] of Object.entries(afterStyles)) { el.style.setProperty(key, value); } } } } } /** * DOM WRITE * NO RECURSION */ _willChange(addWillChange) { let wc; const effects = this._fxProperties; let willChange; if (addWillChange && effects) { wc = []; for (const effect of effects) { const propWC = effect.wc; if (propWC === 'webkitTransform') { wc.push('transform', '-webkit-transform'); } else if (propWC !== undefined) { wc.push(propWC); } } willChange = wc.join(','); } else { willChange = ''; } const elements = this._elements; if (elements) { for (const el of elements) { // ******** DOM WRITE **************** el.style.setProperty('will-change', willChange); } } } /** * Start the animation with a user controlled progress. */ progressStart() { // ensure all past transition end events have been cleared this._clearAsync(); // ******** DOM READ/WRITE **************** this._beforeAnimation(); // ******** DOM WRITE **************** this._progressStart(); } /** * DOM WRITE * RECURSION */ _progressStart() { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._progressStart(); } } // force no duration, linear easing // ******** DOM WRITE **************** this._setTrans(0, true); // ******** DOM WRITE **************** this._willChange(true); } /** * Set the progress step for this animation. * progressStep() is not debounced, so it should not be called faster than 60FPS. */ progressStep(stepValue) { // only update if the last update was more than 16ms ago stepValue = Math.min(1, Math.max(0, stepValue)); const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child.progressStep(stepValue); } } // ******** DOM WRITE **************** this._progress(stepValue); } /** * End the progress animation. */ progressEnd(shouldComplete, currentStepValue, dur = -1) { if (this._isReverse) { // if the animation is going in reverse then // flip the step value: 0 becomes 1, 1 becomes 0 currentStepValue = 1 - currentStepValue; } const stepValue = shouldComplete ? 1 : 0; const diff = Math.abs(currentStepValue - stepValue); if (dur < 0) { dur = this._duration || 0; } else if (diff < 0.05) { dur = 0; } this._isAsync = (dur > 30); this._progressEnd(shouldComplete, stepValue, dur, this._isAsync); if (this._isAsync) { // for the root animation only // set the async TRANSITION END event // and run onFinishes when the transition ends // ******** DOM WRITE **************** this._asyncEnd(dur, shouldComplete); // this animation has a duration so we need another RAF // for the CSS TRANSITION properties to kick in if (!this._destroyed) { raf(() => { this._playToStep(stepValue); }); } } } /** * DOM WRITE * RECURSION */ _progressEnd(shouldComplete, stepValue, dur, isAsync) { const children = this._childAnimations; if (children) { for (const child of children) { // ******** DOM WRITE **************** child._progressEnd(shouldComplete, stepValue, dur, isAsync); } } if (!isAsync) { // stop immediately // set all the animations to their final position // ******** DOM WRITE **************** this._progress(stepValue); this._willChange(false); this._setAfterStyles(); this._didFinish(shouldComplete); } else { // animate it back to it's ending position this.isPlaying = true; this.hasCompleted = false; this._hasDur = true; // ******** DOM WRITE **************** this._willChange(true); this._setTrans(dur, false); } } /** * Add a callback to fire when the animation has finished. */ onFinish(callback, opts) { if (opts && opts.clearExistingCallbacks) { this._onFinishCallbacks = this._onFinishOneTimeCallbacks = undefined; } if (opts && opts.oneTimeCallback) { this._onFinishOneTimeCallbacks = this._onFinishOneTimeCallbacks || []; this._onFinishOneTimeCallbacks.push(callback); } else { this._onFinishCallbacks = this._onFinishCallbacks || []; this._onFinishCallbacks.push(callback); } return this; } /** * NO DOM * RECURSION */ _didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations) { const children = this._childAnimations; if (children) { for (const child of children) { child._didFinishAll(hasCompleted, finishAsyncAnimations, finishNoDurationAnimations); } } if (finishAsyncAnimations && this._isAsync || finishNoDurationAnimations && !this._isAsync) { this._didFinish(hasCompleted); } } /** * NO RECURSION */ _didFinish(hasCompleted) { this.isPlaying = false; this.hasCompleted = hasCompleted; if (this._onFinishCallbacks) { // run all finish callbacks for (const callback of this._onFinishCallbacks) { callback(this); } } if (this._onFinishOneTimeCallbacks) { // run all "onetime" finish callbacks for (const callback of this._onFinishOneTimeCallbacks) { callback(this); } this._onFinishOneTimeCallbacks.length = 0; } } /** * Reverse the animation. */ reverse(shouldReverse = true) { const children = this._childAnimations; if (children) { for (const child of children) { child.reverse(shouldReverse); } } this._isReverse = !!shouldReverse; return this; } /** * Recursively destroy this animation and all child animations. */ destroy() { this._didFinish(false); this._destroyed = true; const children = this._childAnimations; if (children) { for (const child of children) { child.destroy(); } } this._clearAsync(); if (this._elements) { this._elements.length = 0; } if (this._readCallbacks) { this._readCallbacks.length = 0; } if (this._writeCallbacks) { this._writeCallbacks.length = 0; } this.parent = undefined; if (this._childAnimations) { this._childAnimations.length = 0; } if (this._onFinishCallbacks) { this._onFinishCallbacks.length = 0; } if (this._onFinishOneTimeCallbacks) { this._onFinishOneTimeCallbacks.length = 0; } } /** * NO DOM */ _transEl() { // get the lowest level element that has an Animator const children = this._childAnimations; if (children) { for (const child of children) { const targetEl = child._transEl(); if (targetEl) { return targetEl; } } } return (this._hasTweenEffect && this._hasDur && this._elements !== undefined && this._elements.length > 0 ? this._elements[0] : null); } } function create(animationBuilder, baseEl, opts) { if (animationBuilder) { return animationBuilder(Animator, baseEl, opts); } return Promise.resolve(new Animator()); } export { create }; //# sourceMappingURL=p-Beh6uSne.js.map //# sourceMappingURL=p-Beh6uSne.js.map