Skip to content

Commit

Permalink
feat: add pause and resume
Browse files Browse the repository at this point in the history
  • Loading branch information
hdbv95 committed Dec 11, 2024
1 parent edca06d commit 3da402a
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 12 deletions.
25 changes: 22 additions & 3 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { ReactElement, useCallback, useMemo, useRef } from "react";
import { Alert, Animated, Button, Dimensions, SafeAreaView, Text } from "react-native";
import {
AttachStep,
PauseParams,
SpotlightTourProvider,
StopParams,
TourBox,
Expand Down Expand Up @@ -32,8 +33,17 @@ export function App(): ReactElement {
);
}, []);

const alertPause = useCallback(({ index }: PauseParams) => {
Alert.alert(
"Pause Example",
dedent`
Paused on step: ${String(index)}
`,
);
}, []);

const tourSteps = useMemo((): TourStep[] => [{
render: ({ next }) => (
render: ({ next, pause }) => (
<SpotDescriptionView>
<DescriptionText>
<BoldText>{"Tour: Intro section\n"}</BoldText>
Expand All @@ -42,8 +52,13 @@ export function App(): ReactElement {
If you want to go to the next step, please press \
`}
<BoldText>{"Next.\n"}</BoldText>
{dedent`
If you want to Pause the Tour, please press \
`}
<BoldText>{"Pause.\n"}</BoldText>
</DescriptionText>
<ButtonsGroupView>
<Button title="Pause" onPress={pause} />
<Button title="Next" onPress={next} />
</ButtonsGroupView>
</SpotDescriptionView>
Expand All @@ -65,6 +80,8 @@ export function App(): ReactElement {
If you want to go to the next step, please press \
`}
<BoldText>{"Next.\n"}</BoldText>
{"If you want to pause the tour, press "}
<BoldText>{"Pause.\n"}</BoldText>
{"If you want to go to the previous step, press "}
<BoldText>{"Previous.\n"}</BoldText>
</Text>
Expand All @@ -79,7 +96,7 @@ export function App(): ReactElement {
toValue: Dimensions.get("screen").height * 0.25,
useNativeDriver: false, // Translate animation not supported native by native driver
})
.start(() => resolve());
.start(() => resolve());
});
},
render: ({ previous, stop }) => (
Expand Down Expand Up @@ -113,13 +130,15 @@ export function App(): ReactElement {
nativeDriver={true}
onBackdropPress="continue"
onStop={showSummary}
onPause={alertPause}
motion="bounce"
shape="circle"
arrow={{ color: "#B0C4DE" }}
>
{({ start }) => (
{({ start, resume, lastCurrent }) => (
<>
<Button title="Start" onPress={start} />
{lastCurrent !== undefined && <Button title="Resume" onPress={resume} />}

<SectionContainerView>
<AttachStep index={0}>
Expand Down
41 changes: 40 additions & 1 deletion package/src/lib/SpotlightTour.context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ export interface RenderProps {
* Goes to the next step, if any. Stops the tour on the last step.
*/
next: () => void;
/**
* Pauses the tour execution.
*/
pause: () => void;
/**
* Goes to the previous step, if any.
*/
previous: () => void;
/**
* Resumes the tour execution.
*/
resume: () => void;
/**
* Terminates the tour execution.
*/
Expand Down Expand Up @@ -81,6 +89,20 @@ export interface StopParams {
isLast: boolean;
}

export interface PauseParams {
/**
* Step index when paused.
*/
index: number;
}

export interface ResumeParams {
/**
* Step index where the tour resumed.
*/
index: number;
}

export interface ArrowOptions {
/**
* The color of the tooltip arrow.
Expand Down Expand Up @@ -198,14 +220,26 @@ export interface SpotlightTour {
* @param index the index of the step to go
*/
goTo: (index: number) => void;
/**
* The last step index, when the tour was paused
*/
lastCurrent?: number;
/**
* Goes to the next step, if any. Stops the tour on the last step.
*/
next: () => void;
/**
* Pauses the tour execution.
*/
pause: () => void;
/**
* Goes to the previous step, if any.
*/
previous: () => void;
/**
* Resumes the tour execution.
*/
resume: () => void;
/**
* Kicks off the tour from step `0`.
*/
Expand Down Expand Up @@ -244,7 +278,9 @@ export const SpotlightTourContext = createContext<SpotlightTourCtx>({
changeSpot: () => undefined,
goTo: () => undefined,
next: () => undefined,
pause: () => undefined,
previous: () => undefined,
resume: () => undefined,
spot: ZERO_SPOT,
start: () => undefined,
steps: [],
Expand All @@ -257,13 +293,16 @@ export const SpotlightTourContext = createContext<SpotlightTourCtx>({
* @returns the SpotlightTour context
*/
export function useSpotlightTour(): SpotlightTour {
const { current, goTo, next, previous, start, stop } = useContext(SpotlightTourContext);
const { current, lastCurrent, goTo, next, previous, start, stop, pause, resume } = useContext(SpotlightTourContext);

return {
current,
goTo,
lastCurrent,
next,
pause,
previous,
resume,
start,
stop,
};
Expand Down
44 changes: 42 additions & 2 deletions package/src/lib/SpotlightTour.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
BackdropPressBehavior,
Motion,
OSConfig,
PauseParams,
ResumeParams,
Shape,
SpotlightTour,
SpotlightTourContext,
Expand Down Expand Up @@ -61,6 +63,18 @@ export interface SpotlightTourProviderProps extends TooltipProps {
* **NOTE:** You can also override this behavior on each step configuration.
*/
onBackdropPress?: BackdropPressBehavior;
/**
* Handler which gets executed when {@link SpotlightTour.pause|pause} is
* invoked. It receives the {@link PauseParams} so
* you can access the step index where the tour paused.
*/
onPause?: (values: PauseParams) => void;
/**
* Handler which gets executed when {@link SpotlightTour.resume|resume} is
* invoked. It receives the {@link ResumeParams} so
* you can access the step index where the tour resumed.
*/
onResume?: (values: ResumeParams) => void;
/**
* Handler which gets executed when {@link SpotlightTour.stop|stop} is
* invoked. It receives the {@link StopParams} so
Expand Down Expand Up @@ -117,6 +131,8 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
nativeDriver = true,
onBackdropPress,
onStop,
onPause,
onResume,
overlayColor = "black",
overlayOpacity = 0.45,
shape = "circle",
Expand All @@ -125,6 +141,7 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
} = props;

const [current, setCurrent] = useState<number>();
const [lastCurrent, setLastCurrent] = useState<number>();
const [spot, setSpot] = useState(ZERO_SPOT);

const overlay = useRef<TourOverlayRef>({
Expand All @@ -139,7 +156,7 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
overlay.current.hideTooltip(),
Promise.resolve().then(step.before),
])
.then(() => setCurrent(index));
.then(() => setCurrent(index));
}
}, [steps]);

Expand All @@ -158,9 +175,20 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
}
return undefined;
});
setLastCurrent(current);
setSpot(ZERO_SPOT);
}, [onStop]);

const pause = useCallback((): void => {
setLastCurrent(current);
setCurrent(prev => {
if (prev !== undefined) {
onPause?.({ index: prev });
}
return undefined;
});
}, [onPause, current]);

const next = useCallback((): void => {
if (current !== undefined) {
current === steps.length - 1
Expand All @@ -179,6 +207,13 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
renderStep(index);
}, [renderStep]);

const resume = useCallback((): void => {
if (lastCurrent !== undefined) {
goTo(lastCurrent);
onResume?.({ index: lastCurrent });
}
}, [onResume, lastCurrent]);

const currentStep = useMemo((): TourStep => {
const step = current !== undefined
? steps[current]
Expand All @@ -191,19 +226,24 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
changeSpot,
current,
goTo,
lastCurrent,
next,
pause,
previous,
resume,
spot,
start,
steps,
stop,
}), [changeSpot, current, goTo, next, previous, spot, start, steps, stop]);
}), [changeSpot, current, lastCurrent, goTo, next, previous, spot, start, steps, stop, pause]);

useImperativeHandle(ref, () => ({
current,
goTo,
next,
pause,
previous,
resume,
start,
stop,
}));
Expand Down
30 changes: 29 additions & 1 deletion package/src/lib/components/tour-box/TourBox.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export interface TourBoxProps extends RenderProps {
* Should hide the Next button.
*/
hideNext?: boolean;
/**
* Should hide the Pause button.
*/
hidePause?: boolean;
/**
* Next button styles.
*/
Expand All @@ -46,6 +50,14 @@ export interface TourBoxProps extends RenderProps {
* Callback for when the Next button is pressed.
*/
onNext?: () => void;
/**
* Callback for when the Pause button is pressed.
*/
onPause?: () => void;
/**
* Pause button text.
*/
pauseText?: string;
/**
* TourBox main container styles.
*/
Expand All @@ -72,11 +84,14 @@ export function TourBox(props: TourBoxProps): ReactElement {
const {
backText = "Back",
nextText = "Next",
pauseText = "Pause",
title,
hideNext,
hideBack,
hidePause,
onBack,
onNext,
onPause,
backStyle,
nextStyle,
titleStyle,
Expand All @@ -86,6 +101,7 @@ export function TourBox(props: TourBoxProps): ReactElement {
isFirst,
previous,
stop,
pause,
next,
} = props;

Expand All @@ -99,6 +115,11 @@ export function TourBox(props: TourBoxProps): ReactElement {
onNext?.();
}, [isLast, stop, next, onNext]);

const handlePause = useCallback((): void => {
pause();
onPause?.();
}, [pause]);

return (
<MainContainer style={style}>
{title !== undefined && (
Expand All @@ -109,7 +130,7 @@ export function TourBox(props: TourBoxProps): ReactElement {

{children}

{(!hideBack || !hideNext) && (
{(!hideBack || !hideNext || !hidePause) && (
<FooterContainer>
{!hideBack && (
<NavButton style={backStyle} onPress={handleBack}>
Expand All @@ -118,6 +139,13 @@ export function TourBox(props: TourBoxProps): ReactElement {
</Text>
</NavButton>
)}
{!hidePause && (
<NavButton style={backStyle} onPress={handlePause}>
<Text>
{pauseText}
</Text>
</NavButton>
)}
{!hideNext && (
<NavButton style={nextStyle} onPress={handleNext}>
<Text>
Expand Down
Loading

0 comments on commit 3da402a

Please sign in to comment.