import React, { createContext, useContext, useState, useCallback, useRef } from 'react'; import { LayoutRectangle } from 'react-native'; export interface CoachStep { elementKey: string; title: string; description: string; tooltipSide: 'above' | 'below' | 'left' | 'right'; } interface CoachMarksState { isActive: boolean; currentStep: number; steps: CoachStep[]; layouts: Record; registerLayout: (key: string, layout: LayoutRectangle) => void; startTour: (steps: CoachStep[]) => void; next: () => void; skip: () => void; } const CoachMarksContext = createContext(null); export const useCoachMarks = () => { const ctx = useContext(CoachMarksContext); if (!ctx) throw new Error('useCoachMarks must be within CoachMarksProvider'); return ctx; }; export const CoachMarksProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [isActive, setIsActive] = useState(false); const [currentStep, setCurrentStep] = useState(0); const [steps, setSteps] = useState([]); const layouts = useRef>({}); const [, forceRender] = useState(0); const registerLayout = useCallback((key: string, layout: LayoutRectangle) => { layouts.current[key] = layout; forceRender(n => n + 1); }, []); const startTour = useCallback((newSteps: CoachStep[]) => { setSteps(newSteps); setCurrentStep(0); setIsActive(true); }, []); const next = useCallback(() => { setCurrentStep(prev => { if (prev + 1 >= steps.length) { setIsActive(false); return 0; } return prev + 1; }); }, [steps.length]); const skip = useCallback(() => { setIsActive(false); setCurrentStep(0); }, []); return ( {children} ); };