import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'react' import { runOnUI, useSharedValue } from 'react-native-reanimated' import type { UnistylesValues } from '../../types' import type { UseUpdateVariantColorConfig } from './types' import { UnistyleDependency } from '../../specs' import { services } from '../../web/services' import { getClosestBreakpointValue } from '../../web/utils' export const useUpdateVariantColor = >({ animateCallback, colorKey, style, }: UseUpdateVariantColorConfig) => { 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 const currentColorVar = typeof currentColor === 'string' ? currentColor : (getClosestBreakpointValue(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(getCurrentColor()) const toValue = useSharedValue(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, } }