import { IOnboardingAction, IOnboardingContext, IOnboardingState, OnboardingActionType, OnboardingContext } from './Provider'; import { ITipDescriptor } from './types'; import _ from 'lodash'; import { useCallback, useContext, useEffect } from 'react'; import * as yup from 'yup'; function useOnboardingContext(): IOnboardingContext { const context = useContext(OnboardingContext); if (context === undefined) { throw new Error( '[Onboarding] useOnboardingContext: context undefined. Please provide a valid OnboardingContext using OnboardingProvider' ); } return context; } function useOnboardingState(): IOnboardingState { const context = useOnboardingContext(); return context.state; } function useOnboardingDispatch(): React.Dispatch { const context = useOnboardingContext(); return context.dispatch; } function useOnboardingTip(config: ITipDescriptor): { tip: ITipDescriptor & { open: boolean }; dismiss: () => void; } { yup.object({ id: yup.string().required(), step: yup.number().required() }).validateSync(config); const { id, step, completeOnboarding } = config; const { show, tips, currentStep } = useOnboardingState(); const tip = _.find(tips, { id: id }); const { dismissed } = tip ?? {}; const dispatch = useOnboardingDispatch(); const dismiss = useCallback(() => { dispatch({ type: OnboardingActionType.DISMISS_TIP, payload: id }); }, [dispatch, id]); useEffect(() => { if (_.isNil(tip) || step !== tip?.step) { dispatch({ type: OnboardingActionType.REGISTER_TIP, payload: { id: id, step: step, completeOnboarding: completeOnboarding } }); } }, [id, step, completeOnboarding, tip, dispatch]); useEffect(() => { return () => { dispatch({ type: OnboardingActionType.UNREGISTER_TIP, payload: id }); }; }, [id, dispatch]); return { tip: _.chain(tip ?? config) .clone() .extend({ open: show && !_.isNil(tip) && currentStep === step && !dismissed }) .value(), dismiss: dismiss }; } function useRestartOnboarding(): () => void { const dispatch = useOnboardingDispatch(); return useCallback(() => { dispatch({ type: OnboardingActionType.RESTART }); }, [dispatch]); } export { useOnboardingTip, useRestartOnboarding };