react-native-unistyles
Version:
Level up your React Native StyleSheet
82 lines (65 loc) • 2.64 kB
text/typescript
import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react'
import { runOnUI, useSharedValue } from 'react-native-reanimated'
import { UnistyleDependency } from '../../specs'
import type { UnistylesValues } from '../../types'
import { services } from '../../web/services'
import { getClosestBreakpointValue } from '../../web/utils'
import type { UseUpdateVariantColorConfig } from './types'
export const useUpdateVariantColor = <T extends Record<string, any>>({
animateCallback,
colorKey,
style
}: UseUpdateVariantColorConfig<T>) => {
const [dummyDiv] = useState(() => {
const div = document.createElement('div')
div.style.display = 'none'
document.body.appendChild(div)
return div
})
const parsedStyles = useMemo(() => {
return services.shadowRegistry.addStyles([style]).parsedStyles
}, [style])
const getCurrentColor = useCallback(
() => {
if (!parsedStyles) {
return 'rgb(0, 0, 0)'
}
const currentColor = parsedStyles[colorKey as keyof UnistylesValues] as string | Record<string, string>
const currentColorVar = typeof currentColor === 'string'
? currentColor
: getClosestBreakpointValue<string>(services.runtime, currentColor) ?? 'rgb(0, 0, 0)'
if (currentColorVar.startsWith('var(--')) {
dummyDiv.style.color = currentColorVar
return getComputedStyle(dummyDiv).color
}
return currentColorVar
},
[style, colorKey]
)
const fromValue = useSharedValue<string>(getCurrentColor())
const toValue = useSharedValue<string>(getCurrentColor())
useEffect(() => {
const dispose = services.listener.addListeners([UnistyleDependency.Theme], () => {
runOnUI(() => {
animateCallback?.(toValue.get(), getCurrentColor())
})()
})
return () => dispose()
}, [style, colorKey])
useLayoutEffect(() => {
animateCallback?.(toValue.get(), getCurrentColor())
const colorStyle = parsedStyles?.[colorKey as keyof UnistylesValues]
if (typeof colorStyle !== 'object' || colorStyle === null) {
return
}
const dispose = services.listener.addListeners([UnistyleDependency.Breakpoints], () => {
animateCallback?.(toValue.get(), getCurrentColor())
})
return () => dispose()
}, [style, colorKey])
useEffect(() => () => dummyDiv.remove(), [])
return {
fromValue,
toValue
}
}