import React, { createContext, type PropsWithChildren, useContext, useEffect, useState, } from "react"; import { runOnJS, useAnimatedReaction } from "react-native-reanimated"; import { getTransformComponents } from "../../utils/transform"; import type { ChartTransformState } from "../hooks/useChartTransformState"; interface CartesianTransformContext { k: number; kx: number; ky: number; tx: number; ty: number; } const CartesianTransformContext = createContext< CartesianTransformContext | undefined >(undefined); type CartesianTransformProviderProps = PropsWithChildren<{ transformState?: ChartTransformState; }>; export const CartesianTransformProvider = ({ transformState, children, }: CartesianTransformProviderProps) => { const [transform, setTransform] = useState<{ k: number; kx: number; ky: number; tx: number; ty: number; }>(() => { const components = getTransformComponents(undefined); return { k: components.scaleX, kx: components.scaleX, ky: components.scaleY, tx: components.translateX, ty: components.translateY, }; }); // This is done in a useEffect to prevent Reanimated warning // about setting shared value in the render phase useEffect(() => { if (transformState) { setTransform(() => { const components = getTransformComponents(transformState.matrix.value); return { k: components.scaleX, kx: components.scaleX, ky: components.scaleY, tx: components.translateX, ty: components.translateY, }; }); } }, []); // eslint-disable-line react-hooks/exhaustive-deps useAnimatedReaction( () => { return getTransformComponents(transformState?.matrix.value); }, (cv, pv) => { if ( cv.scaleX !== pv?.scaleX || cv.scaleY !== pv.scaleY || cv.translateX !== pv.translateX || cv.translateY !== pv.translateY ) { runOnJS(setTransform)({ k: cv.scaleX, kx: cv.scaleX, ky: cv.scaleY, tx: cv.translateX, ty: cv.translateY, }); } }, ); return ( {children} ); }; export const useCartesianTransformContext = () => { const context = useContext(CartesianTransformContext); if (context === undefined) { throw new Error( "useCartesianTransformContext must be used within a CartesianTransformProvider", ); } return context; };