58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { useShepherd } from 'react-shepherd';
|
|
import { StepOptions, TourOptions } from 'shepherd.js';
|
|
import { useLocation } from 'react-router';
|
|
import 'shepherd.js/dist/css/shepherd.css';
|
|
import './Onboarding.css';
|
|
|
|
import { hasTourBeenShown, markTourAsShown, defaultShowHandler, middleware } from './utilities';
|
|
|
|
const Onboarding = () => {
|
|
const Shepherd = useShepherd();
|
|
const location = useLocation();
|
|
const tours = window.config.tours as Array<{
|
|
id: string;
|
|
route: string;
|
|
tourOptions: TourOptions;
|
|
steps: StepOptions[];
|
|
}>;
|
|
|
|
/**
|
|
* Show the tour if it hasn't been shown yet based on the current route.
|
|
* Constructs a tour instance and adds steps to it based on the matching tour.
|
|
*/
|
|
useEffect(() => {
|
|
if (!tours) {
|
|
return;
|
|
}
|
|
|
|
const matchingTour = tours.find(tour => tour.route === location.pathname);
|
|
if (!matchingTour || hasTourBeenShown(matchingTour.id)) {
|
|
return;
|
|
}
|
|
|
|
const tourInstance = new Shepherd.Tour({
|
|
...matchingTour.tourOptions,
|
|
defaultStepOptions: {
|
|
...matchingTour.tourOptions?.defaultStepOptions,
|
|
floatingUIOptions: matchingTour.tourOptions?.defaultStepOptions?.floatingUIOptions || {
|
|
middleware,
|
|
},
|
|
when: {
|
|
...matchingTour.tourOptions?.defaultStepOptions?.when,
|
|
show:
|
|
matchingTour.tourOptions?.defaultStepOptions?.when?.show ||
|
|
(() => defaultShowHandler(Shepherd)),
|
|
},
|
|
},
|
|
});
|
|
matchingTour.steps.forEach(step => tourInstance.addStep(step));
|
|
tourInstance.start();
|
|
markTourAsShown(matchingTour.id);
|
|
}, [Shepherd, tours, location.pathname]);
|
|
|
|
return null;
|
|
};
|
|
|
|
export { Onboarding };
|