@tamagui/react-native-web-lite
Version:
React Native for Web
137 lines (121 loc) • 3.85 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @format
*/
import AnimatedNode from './AnimatedNode'
import AnimatedTransform from './AnimatedTransform'
import AnimatedWithChildren from './AnimatedWithChildren'
import NativeAnimatedHelper from '../NativeAnimatedHelper'
import { StyleSheet } from '@tamagui/react-native-web-internals'
const flattenStyle = StyleSheet.flatten
function createAnimatedStyle(inputStyle) {
const style = flattenStyle(inputStyle)
const animatedStyles = {}
for (const key in style) {
const value = style[key]
if (key === 'transform' && Array.isArray(value)) {
animatedStyles[key] = new AnimatedTransform(value)
} else if (value instanceof AnimatedNode) {
animatedStyles[key] = value
} else if (value && !Array.isArray(value) && typeof value === 'object') {
animatedStyles[key] = createAnimatedStyle(value)
}
}
return animatedStyles
}
class AnimatedStyle extends AnimatedWithChildren {
_inputStyle
_style
constructor(style) {
super()
this._inputStyle = style
this._style = createAnimatedStyle(style)
}
// Recursively get values for nested styles (like iOS's shadowOffset)
_walkStyleAndGetValues(style) {
const updatedStyle = {}
for (const key in style) {
const value = style[key]
if (value instanceof AnimatedNode) {
if (!value.__isNative) {
// We cannot use value of natively driven nodes this way as the value we have access from
// JS may not be up to date.
updatedStyle[key] = value.__getValue()
}
} else if (value && !Array.isArray(value) && typeof value === 'object') {
// Support animating nested values (for example: shadowOffset.height)
updatedStyle[key] = this._walkStyleAndGetValues(value)
} else {
updatedStyle[key] = value
}
}
return updatedStyle
}
__getValue() {
return [this._inputStyle, this._walkStyleAndGetValues(this._style)]
}
// Recursively get animated values for nested styles (like iOS's shadowOffset)
_walkStyleAndGetAnimatedValues(style) {
const updatedStyle = {}
for (const key in style) {
const value = style[key]
if (value instanceof AnimatedNode) {
updatedStyle[key] = value.__getAnimatedValue()
} else if (value && !Array.isArray(value) && typeof value === 'object') {
// Support animating nested values (for example: shadowOffset.height)
updatedStyle[key] = this._walkStyleAndGetAnimatedValues(value)
}
}
return updatedStyle
}
__getAnimatedValue() {
return this._walkStyleAndGetAnimatedValues(this._style)
}
__attach() {
for (const key in this._style) {
const value = this._style[key]
if (value instanceof AnimatedNode) {
value.__addChild(this)
}
}
}
__detach() {
for (const key in this._style) {
const value = this._style[key]
if (value instanceof AnimatedNode) {
value.__removeChild(this)
}
}
super.__detach()
}
__makeNative() {
for (const key in this._style) {
const value = this._style[key]
if (value instanceof AnimatedNode) {
value.__makeNative()
}
}
super.__makeNative()
}
__getNativeConfig() {
const styleConfig = {}
for (const styleKey in this._style) {
if (this._style[styleKey] instanceof AnimatedNode) {
const style = this._style[styleKey]
style.__makeNative()
styleConfig[styleKey] = style.__getNativeTag()
}
}
NativeAnimatedHelper.validateStyles(styleConfig)
return {
type: 'style',
style: styleConfig,
}
}
}
export default AnimatedStyle