{"version":3,"names":["useEffect","useRef","makeShareable","startMapper","stopMapper","updateProps","updatePropsJestWrapper","initialUpdaterRun","useSharedValue","buildWorkletsHash","isAnimated","shallowEqual","validateAnimatedStyles","makeViewDescriptorsSet","useViewRefSet","isJest","shouldBeUseWeb","SHOULD_BE_USE_WEB","prepareAnimation","frameTimestamp","animatedProp","lastAnimation","lastValue","Array","isArray","forEach","prop","index","onFrame","animation","value","current","undefined","callStart","timestamp","onStart","Object","keys","key","runAnimations","result","animationsActive","allFinished","entry","finished","callback","k","styleUpdater","viewDescriptors","updater","state","maybeViewRef","isAnimatedProps","arguments","length","animations","newValues","oldValues","last","nonAnimatedNewValues","hasAnimations","hasNonAnimatedValues","global","__frameTimestamp","_getAnimationTimestamp","frame","isAnimationCancelled","isAnimationRunning","updates","propName","requestAnimationFrame","jestStyleUpdater","animatedStyle","adapters","checkSharedValueUsage","currentKey","element","Error","useAnimatedStyle","dependencies","viewsRef","animatedUpdaterData","inputs","values","__closure","_dependencies","__DEV__","__workletHash","adaptersArray","adaptersHash","areAnimationsActive","jestAnimatedStyle","push","initialStyle","initial","remoteState","shareableViewDescriptors","fun","updaterFn","adapter","mapperId","animatedStyleHandle"],"sources":["useAnimatedStyle.ts"],"sourcesContent":["'use strict';\nimport type { MutableRefObject } from 'react';\nimport { useEffect, useRef } from 'react';\n\nimport { makeShareable, startMapper, stopMapper } from '../core';\nimport updateProps, { updatePropsJestWrapper } from '../UpdateProps';\nimport { initialUpdaterRun } from '../animation';\nimport { useSharedValue } from './useSharedValue';\nimport {\n buildWorkletsHash,\n isAnimated,\n shallowEqual,\n validateAnimatedStyles,\n} from './utils';\nimport type {\n AnimatedStyleHandle,\n DefaultStyle,\n DependencyList,\n Descriptor,\n JestAnimatedStyleHandle,\n} from './commonTypes';\nimport type { ViewDescriptorsSet, ViewRefSet } from '../ViewDescriptorsSet';\nimport { makeViewDescriptorsSet, useViewRefSet } from '../ViewDescriptorsSet';\nimport { isJest, shouldBeUseWeb } from '../PlatformChecker';\nimport type {\n AnimationObject,\n Timestamp,\n NestedObjectValues,\n SharedValue,\n StyleProps,\n __AdapterWorkletFunction,\n __BasicWorkletFunction,\n WorkletFunction,\n} from '../commonTypes';\nimport type { AnimatedStyle } from '../helperTypes';\n\nconst SHOULD_BE_USE_WEB = shouldBeUseWeb();\n\ninterface AnimatedState {\n last: AnimatedStyle;\n animations: AnimatedStyle;\n isAnimationRunning: boolean;\n isAnimationCancelled: boolean;\n}\n\ninterface AnimatedUpdaterData {\n initial: {\n value: AnimatedStyle;\n updater: () => AnimatedStyle;\n };\n remoteState: AnimatedState;\n viewDescriptors: ViewDescriptorsSet;\n}\n\nfunction prepareAnimation(\n frameTimestamp: number,\n animatedProp: AnimatedStyle,\n lastAnimation: AnimatedStyle,\n lastValue: AnimatedStyle\n): void {\n 'worklet';\n if (Array.isArray(animatedProp)) {\n animatedProp.forEach((prop, index) => {\n prepareAnimation(\n frameTimestamp,\n prop,\n lastAnimation && lastAnimation[index],\n lastValue && lastValue[index]\n );\n });\n // return animatedProp;\n }\n if (typeof animatedProp === 'object' && animatedProp.onFrame) {\n const animation = animatedProp;\n\n let value = animation.current;\n if (lastValue !== undefined && lastValue !== null) {\n if (typeof lastValue === 'object') {\n if (lastValue.value !== undefined) {\n // previously it was a shared value\n value = lastValue.value;\n } else if (lastValue.onFrame !== undefined) {\n if (lastAnimation?.current !== undefined) {\n // it was an animation before, copy its state\n value = lastAnimation.current;\n } else if (lastValue?.current !== undefined) {\n // it was initialized\n value = lastValue.current;\n }\n }\n } else {\n // previously it was a plain value, just set it as starting point\n value = lastValue;\n }\n }\n\n animation.callStart = (timestamp: Timestamp) => {\n animation.onStart(animation, value, timestamp, lastAnimation);\n };\n animation.callStart(frameTimestamp);\n animation.callStart = null;\n } else if (typeof animatedProp === 'object') {\n // it is an object\n Object.keys(animatedProp).forEach((key) =>\n prepareAnimation(\n frameTimestamp,\n animatedProp[key],\n lastAnimation && lastAnimation[key],\n lastValue && lastValue[key]\n )\n );\n }\n}\n\nfunction runAnimations(\n animation: AnimatedStyle,\n timestamp: Timestamp,\n key: number | string,\n result: AnimatedStyle,\n animationsActive: SharedValue\n): boolean {\n 'worklet';\n if (!animationsActive.value) {\n return true;\n }\n if (Array.isArray(animation)) {\n result[key] = [];\n let allFinished = true;\n animation.forEach((entry, index) => {\n if (\n !runAnimations(entry, timestamp, index, result[key], animationsActive)\n ) {\n allFinished = false;\n }\n });\n return allFinished;\n } else if (typeof animation === 'object' && animation.onFrame) {\n let finished = true;\n if (!animation.finished) {\n if (animation.callStart) {\n animation.callStart(timestamp);\n animation.callStart = null;\n }\n finished = animation.onFrame(animation, timestamp);\n animation.timestamp = timestamp;\n if (finished) {\n animation.finished = true;\n animation.callback && animation.callback(true /* finished */);\n }\n }\n result[key] = animation.current;\n return finished;\n } else if (typeof animation === 'object') {\n result[key] = {};\n let allFinished = true;\n Object.keys(animation).forEach((k) => {\n if (\n !runAnimations(\n animation[k],\n timestamp,\n k,\n result[key],\n animationsActive\n )\n ) {\n allFinished = false;\n }\n });\n return allFinished;\n } else {\n result[key] = animation;\n return true;\n }\n}\n\nfunction styleUpdater(\n viewDescriptors: SharedValue,\n updater: __BasicWorkletFunction>,\n state: AnimatedState,\n maybeViewRef: ViewRefSet | undefined,\n animationsActive: SharedValue,\n isAnimatedProps = false\n): void {\n 'worklet';\n const animations = state.animations ?? {};\n const newValues = updater() ?? {};\n const oldValues = state.last;\n const nonAnimatedNewValues: StyleProps = {};\n\n let hasAnimations = false;\n let frameTimestamp: number | undefined;\n let hasNonAnimatedValues = false;\n for (const key in newValues) {\n const value = newValues[key];\n if (isAnimated(value)) {\n frameTimestamp = global.__frameTimestamp || _getAnimationTimestamp();\n prepareAnimation(frameTimestamp, value, animations[key], oldValues[key]);\n animations[key] = value;\n hasAnimations = true;\n } else {\n hasNonAnimatedValues = true;\n nonAnimatedNewValues[key] = value;\n delete animations[key];\n }\n }\n\n if (hasAnimations) {\n const frame = (timestamp: Timestamp) => {\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const { animations, last, isAnimationCancelled } = state;\n if (isAnimationCancelled) {\n state.isAnimationRunning = false;\n return;\n }\n\n const updates: AnimatedStyle = {};\n let allFinished = true;\n for (const propName in animations) {\n const finished = runAnimations(\n animations[propName],\n timestamp,\n propName,\n updates,\n animationsActive\n );\n if (finished) {\n last[propName] = updates[propName];\n delete animations[propName];\n } else {\n allFinished = false;\n }\n }\n\n if (updates) {\n updateProps(viewDescriptors, updates, maybeViewRef);\n }\n\n if (!allFinished) {\n requestAnimationFrame(frame);\n } else {\n state.isAnimationRunning = false;\n }\n };\n\n state.animations = animations;\n if (!state.isAnimationRunning) {\n state.isAnimationCancelled = false;\n state.isAnimationRunning = true;\n frame(frameTimestamp!);\n }\n\n if (hasNonAnimatedValues) {\n updateProps(viewDescriptors, nonAnimatedNewValues, maybeViewRef);\n }\n } else {\n state.isAnimationCancelled = true;\n state.animations = [];\n\n if (!shallowEqual(oldValues, newValues)) {\n updateProps(viewDescriptors, newValues, maybeViewRef, isAnimatedProps);\n }\n }\n state.last = newValues;\n}\n\nfunction jestStyleUpdater(\n viewDescriptors: SharedValue,\n updater: __BasicWorkletFunction>,\n state: AnimatedState,\n maybeViewRef: ViewRefSet | undefined,\n animationsActive: SharedValue,\n animatedStyle: MutableRefObject>,\n adapters: __AdapterWorkletFunction[] = []\n): void {\n 'worklet';\n const animations: AnimatedStyle = state.animations ?? {};\n const newValues = updater() ?? {};\n const oldValues = state.last;\n\n // extract animated props\n let hasAnimations = false;\n let frameTimestamp: number | undefined;\n Object.keys(animations).forEach((key) => {\n const value = newValues[key];\n if (!isAnimated(value)) {\n delete animations[key];\n }\n });\n Object.keys(newValues).forEach((key) => {\n const value = newValues[key];\n if (isAnimated(value)) {\n frameTimestamp = global.__frameTimestamp || _getAnimationTimestamp();\n prepareAnimation(frameTimestamp, value, animations[key], oldValues[key]);\n animations[key] = value;\n hasAnimations = true;\n }\n });\n\n function frame(timestamp: Timestamp) {\n // eslint-disable-next-line @typescript-eslint/no-shadow\n const { animations, last, isAnimationCancelled } = state;\n if (isAnimationCancelled) {\n state.isAnimationRunning = false;\n return;\n }\n\n const updates: AnimatedStyle = {};\n let allFinished = true;\n Object.keys(animations).forEach((propName) => {\n const finished = runAnimations(\n animations[propName],\n timestamp,\n propName,\n updates,\n animationsActive\n );\n if (finished) {\n last[propName] = updates[propName];\n delete animations[propName];\n } else {\n allFinished = false;\n }\n });\n\n if (Object.keys(updates).length) {\n updatePropsJestWrapper(\n viewDescriptors,\n updates,\n maybeViewRef,\n animatedStyle,\n adapters\n );\n }\n\n if (!allFinished) {\n requestAnimationFrame(frame);\n } else {\n state.isAnimationRunning = false;\n }\n }\n\n if (hasAnimations) {\n state.animations = animations;\n if (!state.isAnimationRunning) {\n state.isAnimationCancelled = false;\n state.isAnimationRunning = true;\n frame(frameTimestamp!);\n }\n } else {\n state.isAnimationCancelled = true;\n state.animations = [];\n }\n\n // calculate diff\n state.last = newValues;\n\n if (!shallowEqual(oldValues, newValues)) {\n updatePropsJestWrapper(\n viewDescriptors,\n newValues,\n maybeViewRef,\n animatedStyle,\n adapters\n );\n }\n}\n\n// check for invalid usage of shared values in returned object\nfunction checkSharedValueUsage(\n prop: NestedObjectValues,\n currentKey?: string\n): void {\n if (Array.isArray(prop)) {\n // if it's an array (i.ex. transform) validate all its elements\n for (const element of prop) {\n checkSharedValueUsage(element, currentKey);\n }\n } else if (\n typeof prop === 'object' &&\n prop !== null &&\n prop.value === undefined\n ) {\n // if it's a nested object, run validation for all its props\n for (const key of Object.keys(prop)) {\n checkSharedValueUsage(prop[key], key);\n }\n } else if (\n currentKey !== undefined &&\n typeof prop === 'object' &&\n prop !== null &&\n prop.value !== undefined\n ) {\n // if shared value is passed insted of its value, throw an error\n throw new Error(\n `[Reanimated] Invalid value passed to \\`${currentKey}\\`, maybe you forgot to use \\`.value\\`?`\n );\n }\n}\n\n/**\n * Lets you create a styles object, similar to StyleSheet styles, which can be animated using shared values.\n *\n * @param updater - A function returning an object with style properties you want to animate.\n * @param dependencies - An optional array of dependencies. Only relevant when using Reanimated without the Babel plugin on the Web.\n * @returns An animated style object which has to be passed to the `style` property of an Animated component you want to animate.\n * @see https://docs.swmansion.com/react-native-reanimated/docs/core/useAnimatedStyle\n */\n// You cannot pass Shared Values to `useAnimatedStyle` directly.\n// @ts-expect-error This overload is required by our API.\nexport function useAnimatedStyle