From 7400e1b13c9094ba23a2094528ce6a19f9c1debb Mon Sep 17 00:00:00 2001 From: binrysearch Date: Sat, 7 Sep 2024 09:10:39 +0100 Subject: [PATCH] fix exitIntro tests --- src/packages/tour/components/TourRoot.ts | 10 +- src/packages/tour/components/TourTooltip.ts | 329 ++++++++++---------- src/packages/tour/exitIntro.test.ts | 2 +- src/packages/tour/exitIntro.ts | 47 +-- src/packages/tour/steps.ts | 18 +- 5 files changed, 183 insertions(+), 223 deletions(-) diff --git a/src/packages/tour/components/TourRoot.ts b/src/packages/tour/components/TourRoot.ts index a74c44463..2754b716f 100644 --- a/src/packages/tour/components/TourRoot.ts +++ b/src/packages/tour/components/TourRoot.ts @@ -35,8 +35,7 @@ export const TourRoot = ({ tour }: TourRootProps) => { const root = div( { className: "introjs-tour", - style: () => - style({ opacity: `${opacity.val}` }), + style: () => style({ opacity: `${opacity.val}` }), }, // helperLayer should not be re-rendered when the state changes for the transition to work helperLayer, @@ -157,11 +156,7 @@ export const TourRoot = ({ tour }: TourRootProps) => { // the 300ms delay is coming from the helper layer transition duration tooltipTransitionDuration = 300; - return div( - overlayLayer, - referenceLayer, - disableInteraction - ); + return div(overlayLayer, referenceLayer, disableInteraction); } ); @@ -174,7 +169,6 @@ export const TourRoot = ({ tour }: TourRootProps) => { root.remove(); }, 250); } - }); setTimeout(() => { diff --git a/src/packages/tour/components/TourTooltip.ts b/src/packages/tour/components/TourTooltip.ts index 7a486bc76..0296540ce 100644 --- a/src/packages/tour/components/TourTooltip.ts +++ b/src/packages/tour/components/TourTooltip.ts @@ -51,22 +51,21 @@ const Bullets = ({ steps, onBulletClick, }: { - step: TourStep, + step: TourStep; steps: TourStep[]; onBulletClick: (stepNumber: number) => void; }): HTMLElement => { - return div({ className: bulletsClassName }, [ ul({ role: "tablist" }, [ ...steps.map(({ step: stepNumber }) => { const innerLi = li( { - role: "presentation" + role: "presentation", }, [ a({ role: "tab", - className: () => + className: () => `${step.step === stepNumber ? activeClassName : ""}`, onclick: (e: any) => { const stepNumberAttribute = ( @@ -89,27 +88,29 @@ const Bullets = ({ }; const ProgressBar = ({ - steps, - currentStep, - progressBarAdditionalClass + steps, + currentStep, + progressBarAdditionalClass, }: { - steps: TourStep[]; - currentStep: number; - progressBarAdditionalClass: string; + steps: TourStep[]; + currentStep: number; + progressBarAdditionalClass: string; }) => { - const progress = (currentStep / steps.length) * 100; - - return div({ className: progressClassName }, [ - div({ - className: `${progressBarClassName} ${progressBarAdditionalClass ? progressBarAdditionalClass : ""}`, - "role": "progress", - "aria-valuemin": "0", - "aria-valuemax": "100", - "aria-valuenow": () => progress.toString(), - style: `width:${progress}%;`, - }), - ]); -} + const progress = (currentStep / steps.length) * 100; + + return div({ className: progressClassName }, [ + div({ + className: `${progressBarClassName} ${ + progressBarAdditionalClass ? progressBarAdditionalClass : "" + }`, + role: "progress", + "aria-valuemin": "0", + "aria-valuemax": "100", + "aria-valuenow": () => progress.toString(), + style: `width:${progress}%;`, + }), + ]); +}; const StepNumber = ({ step, @@ -129,12 +130,12 @@ const Button = ({ label, onClick, disabled, - className + className, }: { label: string; onClick: (e: any) => void; - disabled?: PropValueOrDerived - className?: PropValueOrDerived + disabled?: PropValueOrDerived; + className?: PropValueOrDerived; }) => { return a( { @@ -159,7 +160,7 @@ const NextButton = ({ hidePrev, nextToDone, onClick, - buttonClass + buttonClass, }: { steps: TourStep[]; currentStep: number; @@ -173,55 +174,47 @@ const NextButton = ({ onClick: (e: any) => void; buttonClass: string; }) => { - const isFullButton = currentStep === 0 && steps.length > 1 && hidePrev; - const isLastStep = currentStep === steps.length - 1 || steps.length === 1; - - const isDisabled = van.derive(() => { - // when the current step is the last one or there is only one step to show - return ( - isLastStep && - !hideNext && - !nextToDone - ); - }); - - const isDoneButton = van.derive(() => { - return ( - isLastStep && - !hideNext && - nextToDone - ); - }); - - const nextButton = Button({ - label: isDoneButton.val ? doneLabel : nextLabel, - onClick, - className: () => { - const classNames = [buttonClass, nextButtonClassName]; - - if (isDoneButton.val) { - classNames.push(doneButtonClassName); - } - - if (isDisabled.val) { - classNames.push(disabledButtonClassName); - } - - if (isFullButton) { - classNames.push(fullButtonClassName); - } - - return classNames.filter(Boolean).join(" "); - }, - }); + const isFullButton = currentStep === 0 && steps.length > 1 && hidePrev; + const isLastStep = currentStep === steps.length - 1 || steps.length === 1; + + const isDisabled = van.derive(() => { + // when the current step is the last one or there is only one step to show + return isLastStep && !hideNext && !nextToDone; + }); + + const isDoneButton = van.derive(() => { + return isLastStep && !hideNext && nextToDone; + }); + + const nextButton = Button({ + label: isDoneButton.val ? doneLabel : nextLabel, + onClick, + className: () => { + const classNames = [buttonClass, nextButtonClassName]; + + if (isDoneButton.val) { + classNames.push(doneButtonClassName); + } + + if (isDisabled.val) { + classNames.push(disabledButtonClassName); + } + + if (isFullButton) { + classNames.push(fullButtonClassName); + } + + return classNames.filter(Boolean).join(" "); + }, + }); - // wait for the button to be rendered - setTimeout(() => { - nextButton.focus() - }, 1); + // wait for the button to be rendered + setTimeout(() => { + nextButton.focus(); + }, 1); - return nextButton; -} + return nextButton; +}; const PrevButton = ({ label, @@ -298,8 +291,8 @@ const Buttons = ({ prevLabel: string; onPrevClick: (e: any) => void; }) => { - const isLastStep = currentStep === steps.length - 1 || steps.length === 1 - const isFirstStep = currentStep === 0 && steps.length > 1 + const isLastStep = currentStep === steps.length - 1 || steps.length === 1; + const isFirstStep = currentStep === 0 && steps.length > 1; return div( { className: tooltipButtonsClassName }, @@ -345,38 +338,42 @@ const Header = ({ }) => { return div({ className: tooltipHeaderClassName }, [ h1({ className: tooltipTitleClassName }, title), - Button({ className: skipButtonClassName, label: skipLabel, onClick: onSkipClick }), + Button({ + className: skipButtonClassName, + label: skipLabel, + onClick: onSkipClick, + }), ]); }; const scroll = ({ - step, - tooltip, - scrollToElement, - scrollPadding, + step, + tooltip, + scrollToElement, + scrollPadding, }: { - step: TourStep; - tooltip: HTMLElement; - scrollToElement: boolean; - scrollPadding: number; + step: TourStep; + tooltip: HTMLElement; + scrollToElement: boolean; + scrollPadding: number; }) => { - // when target is within a scrollable element - scrollParentToElement( - scrollToElement, - step.element as HTMLElement - ); + // when target is within a scrollable element + scrollParentToElement(scrollToElement, step.element as HTMLElement); - // change the scroll of the window, if needed - scrollTo( - scrollToElement, - step.scrollTo, - scrollPadding, - step.element as HTMLElement, - tooltip - ); + // change the scroll of the window, if needed + scrollTo( + scrollToElement, + step.scrollTo, + scrollPadding, + step.element as HTMLElement, + tooltip + ); }; -export type TourTooltipProps = Omit & { +export type TourTooltipProps = Omit< + TooltipProps, + "hintMode" | "position" | "targetOffset" +> & { step: TourStep; steps: TourStep[]; currentStep: number; @@ -389,7 +386,7 @@ export type TourTooltipProps = Omit void; prevLabel: string; onPrevClick: (e: any) => void; - skipLabel: string, + skipLabel: string; onSkipClick: (e: any) => void; buttonClass: string; nextToDone: boolean; @@ -405,7 +402,7 @@ export type TourTooltipProps = Omit void; @@ -447,73 +444,71 @@ export const TourTooltip = ({ dontShowAgainLabel, ...props }: TourTooltipProps) => { - const children = []; - const title = step.title; - const text = step.intro; - const position = step.position; - const targetOffset = getOffset(step.element as HTMLElement); - - children.push(Header({ title, skipLabel, onSkipClick })); - - children.push(div({ className: tooltipTextClassName }, p(text))); - - if (dontShowAgain) { - children.push( - DontShowAgain({ dontShowAgainLabel, onDontShowAgainChange }) - ); - } - - if (bullets) { - children.push(Bullets({ step, steps, onBulletClick })); - } - - if (progress) { - children.push( - ProgressBar({ steps, currentStep, progressBarAdditionalClass }) - ); - } - - if (stepNumbers) { - children.push(StepNumber({ step, steps, stepNumbersOfLabel })); - } - - if (buttons) { - children.push( - Buttons({ - steps, - currentStep, - - nextLabel: nextLabel, - onNextClick: onNextClick, - - prevLabel: prevLabel, - onPrevClick: onPrevClick, - - buttonClass, - nextToDone, - doneLabel, - hideNext, - hidePrev, - }) - ); - } - - const tooltip = Tooltip( - { - ...props, - hintMode: false, - position, - targetOffset, - }, - children + const children = []; + const title = step.title; + const text = step.intro; + const position = step.position; + const targetOffset = getOffset(step.element as HTMLElement); + + children.push(Header({ title, skipLabel, onSkipClick })); + + children.push(div({ className: tooltipTextClassName }, p(text))); + + if (dontShowAgain) { + children.push(DontShowAgain({ dontShowAgainLabel, onDontShowAgainChange })); + } + + if (bullets) { + children.push(Bullets({ step, steps, onBulletClick })); + } + + if (progress) { + children.push( + ProgressBar({ steps, currentStep, progressBarAdditionalClass }) ); + } + + if (stepNumbers) { + children.push(StepNumber({ step, steps, stepNumbersOfLabel })); + } + + if (buttons) { + children.push( + Buttons({ + steps, + currentStep, + + nextLabel: nextLabel, + onNextClick: onNextClick, + + prevLabel: prevLabel, + onPrevClick: onPrevClick, + + buttonClass, + nextToDone, + doneLabel, + hideNext, + hidePrev, + }) + ); + } + + const tooltip = Tooltip( + { + ...props, + hintMode: false, + position, + targetOffset, + }, + children + ); - scroll({ - step, - tooltip, - scrollToElement: scrollToElement, - scrollPadding: scrollPadding, - }); + scroll({ + step, + tooltip, + scrollToElement: scrollToElement, + scrollPadding: scrollPadding, + }); - return tooltip; + return tooltip; }; diff --git a/src/packages/tour/exitIntro.test.ts b/src/packages/tour/exitIntro.test.ts index ab88b62e5..07b4e3d1c 100644 --- a/src/packages/tour/exitIntro.test.ts +++ b/src/packages/tour/exitIntro.test.ts @@ -8,7 +8,7 @@ describe("exitIntro", () => { await mockTour.exit(false); - expect(mockTour.getCurrentStep()).toBe(-1); + expect(mockTour.getCurrentStep()).toBeUndefined(); }); test("should call the onexit and onbeforeexit callbacks", async () => { diff --git a/src/packages/tour/exitIntro.ts b/src/packages/tour/exitIntro.ts index 4d1968875..de0e5ff17 100644 --- a/src/packages/tour/exitIntro.ts +++ b/src/packages/tour/exitIntro.ts @@ -1,13 +1,8 @@ import removeShowElement from "./removeShowElement"; -import { removeChild, removeAnimatedChild } from "../../util/removeChild"; +import { removeChild } from "../../util/removeChild"; import { Tour } from "./tour"; -import { - floatingElementClassName, -} from "./classNames"; -import { - queryElementByClassName, - queryElementsByClassName, -} from "../../util/queryElement"; +import { floatingElementClassName } from "./classNames"; +import { queryElementByClassName } from "../../util/queryElement"; /** * Exit from intro @@ -22,39 +17,14 @@ export default async function exitIntro( const targetElement = tour.getTargetElement(); let continueExit: boolean | undefined = true; - // calling onbeforeexit callback - // + // calling the onBeforeExit callback if it is defined // If this callback return `false`, it would halt the process continueExit = await tour.callback("beforeExit")?.call(tour, targetElement); // skip this check if `force` parameter is `true` - // otherwise, if `onbeforeexit` returned `false`, don't exit the intro + // otherwise, if `onBeforEexit` returned `false`, don't exit the intro if (!force && continueExit === false) return false; - // remove overlay layers from the page - // const overlayLayers = Array.from( - // queryElementsByClassName(overlayClassName, targetElement) - // ); - - // if (overlayLayers && overlayLayers.length) { - // for (const overlayLayer of overlayLayers) { - // removeChild(overlayLayer); - // } - // } - - //const referenceLayer = queryElementByClassName( - // tooltipReferenceLayerClassName, - // targetElement - //); - //removeChild(referenceLayer); - - //remove disableInteractionLayer - // const disableInteractionLayer = queryElementByClassName( - // disableInteractionClassName, - // targetElement - // ); - // removeChild(disableInteractionLayer); - //remove intro floating element const floatingElement = queryElementByClassName( floatingElementClassName, @@ -64,13 +34,6 @@ export default async function exitIntro( removeShowElement(); - //remove all helper layers - // const helperLayer = queryElementByClassName( - // helperLayerClassName, - // targetElement - // ); - // await removeAnimatedChild(helperLayer); - //check if any callback is defined await tour.callback("exit")?.call(tour); diff --git a/src/packages/tour/steps.ts b/src/packages/tour/steps.ts index 978eda828..074a06e9b 100644 --- a/src/packages/tour/steps.ts +++ b/src/packages/tour/steps.ts @@ -43,7 +43,13 @@ export type TourStep = { export async function nextStep(tour: Tour) { tour.incrementCurrentStep(); - const nextStep = tour.getStep(tour.getCurrentStep()); + const currentStep = tour.getCurrentStep(); + + if (currentStep === undefined) { + return false; + } + + const nextStep = tour.getStep(currentStep); let continueStep: boolean | undefined = true; continueStep = await tour @@ -55,7 +61,7 @@ export async function nextStep(tour: Tour) { tour.getDirection() ); - // if `onbeforechange` returned `false`, stop displaying the element + // if `onBeforeChange` returned `false`, stop displaying the element if (continueStep === false) { tour.decrementCurrentStep(); return false; @@ -80,13 +86,15 @@ export async function nextStep(tour: Tour) { * @api private */ export async function previousStep(tour: Tour) { - if (tour.getCurrentStep() <= 0) { + const currentStep = tour.getCurrentStep(); + + if (currentStep === undefined || currentStep <= 0) { return false; } tour.decrementCurrentStep(); - const nextStep = tour.getStep(tour.getCurrentStep()); + const nextStep = tour.getStep(currentStep); let continueStep: boolean | undefined = true; continueStep = await tour @@ -98,7 +106,7 @@ export async function previousStep(tour: Tour) { tour.getDirection() ); - // if `onbeforechange` returned `false`, stop displaying the element + // if `onBeforeChange` returned `false`, stop displaying the element if (continueStep === false) { tour.incrementCurrentStep(); return false;