Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions example/html-tooltip/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@ <h4>Section Six</h4>
</div>
<script type="text/javascript" src="../../dist/intro.js"></script>
<script type="text/javascript">
function onBeforeChange () {
return new Promise((resolve) => {
setTimeout(resolve, 1000)
})
}
function startIntro(){
var intro = introJs.tour();
intro.setOptions({
hideNext: true,
language: 'de_DE',
steps: [
{
Expand Down Expand Up @@ -102,7 +106,7 @@ <h4>Section Six</h4>
}
]
});

intro.onBeforeChange(onBeforeChange)
intro.start();
}
</script>
Expand Down
4 changes: 2 additions & 2 deletions src/packages/hint/components/HintTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type HintTooltipProps = Omit<
renderAsHtml?: boolean;
};

export const HintTooltip = ({
export const HintTooltip = async ({
hintItem,
closeButtonEnabled,
closeButtonOnClick,
Expand All @@ -28,7 +28,7 @@ export const HintTooltip = ({
className,
renderAsHtml,
...props
}: HintTooltipProps) => {
}: HintTooltipProps): Promise<HTMLElement> => {
const text = hintItem.hint;

return Tooltip(
Expand Down
12 changes: 11 additions & 1 deletion src/packages/hint/components/HintsRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ export const HintsRoot = ({ hint }: HintsRootProps) => {

if (!hintItem) return;

const referenceLayer = ReferenceLayer({
// Create placeholder for async tooltip
const referencePlaceholder = div();

// Async load the reference layer
ReferenceLayer({
activeHintSignal,
hintItem,

Expand All @@ -87,8 +91,14 @@ export const HintsRoot = ({ hint }: HintsRootProps) => {
closeButtonOnClick: (hintItem: HintItem) => hideHint(hint, hintItem),
className: hint.getOption("tooltipClass"),
text: hintItem.hint,
}).then((referenceLayer) => {
if (referenceLayer) {
referencePlaceholder.replaceWith(referenceLayer);
}
});

const referenceLayer = referencePlaceholder;

dom.add(root, referenceLayer);
});

Expand Down
59 changes: 29 additions & 30 deletions src/packages/hint/components/ReferenceLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,39 @@ export type ReferenceLayerProps = HintTooltipProps & {
helperElementPadding: number;
};

export const ReferenceLayer = ({
export const ReferenceLayer = async ({
activeHintSignal,
targetElement,
helperElementPadding,
...props
}: ReferenceLayerProps) => {
}: ReferenceLayerProps): Promise<HTMLElement | null> => {
const initialActiveHintSignal = activeHintSignal.val;

return () => {
// remove the reference layer if the active hint signal is set to undefined
// e.g. when the user clicks outside the hint
if (activeHintSignal.val == undefined) return null;

// remove the reference layer if the active hint signal changes
// and the initial active hint signal is not same as the current active hint signal (e.g. when the user clicks on another hint)
if (initialActiveHintSignal !== activeHintSignal.val) return null;

const referenceLayer = div(
{
[dataStepAttribute]: activeHintSignal.val,
className: `${tooltipReferenceLayerClassName} ${hintReferenceClassName}`,
},
HintTooltip(props)
);

setTimeout(() => {
setPositionRelativeTo(
targetElement,
referenceLayer,
props.hintItem.hintTooltipElement as HTMLElement,
helperElementPadding
);
}, 1);

return referenceLayer;
};
if (
activeHintSignal.val == undefined ||
initialActiveHintSignal !== activeHintSignal.val
) {
return null;
}

const tooltip = await HintTooltip(props);

const referenceLayer = div(
{
[dataStepAttribute]: activeHintSignal.val,
className: `${tooltipReferenceLayerClassName} ${hintReferenceClassName}`,
},
tooltip
);

//setTimeout(() => {
setPositionRelativeTo(
targetElement,
referenceLayer,
props.hintItem.hintTooltipElement as HTMLElement,
helperElementPadding
);
//}, 1);

return referenceLayer;
};
2 changes: 1 addition & 1 deletion src/packages/tooltip/tooltip.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe("Tour Tooltip", () => {
for (let i = 0; i < mockTour.getSteps().length; i++) {
const step = mockTour.getStep(i);

const tooltip = Tooltip({
const tooltip = await Tooltip({
className: "custom-tooltip",
element: step.element as HTMLElement,
position: step.position,
Expand Down
27 changes: 14 additions & 13 deletions src/packages/tooltip/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export type TooltipProps = {
text: string;
};

export const Tooltip = (
export const Tooltip = async (
{
position: initialPosition,
element,
Expand All @@ -338,7 +338,7 @@ export const Tooltip = (
onClick,
}: TooltipProps,
children?: ChildDom[]
) => {
): Promise<HTMLElement> => {
const top = dom.state<string>("auto");
const right = dom.state<string>("auto");
const bottom = dom.state<string>("auto");
Expand Down Expand Up @@ -437,17 +437,18 @@ export const Tooltip = (
[children],
]
);

// apply the transition effect
setTimeout(() => {
opacity.val = 1;
}, transitionDuration);

setTimeout(() => {
// set the correct height and width of the tooltip after it has been rendered
tooltipHeight.val = tooltip.offsetHeight;
tooltipWidth.val = tooltip.offsetWidth;
}, 1);
// after tooltip creation (just before return)
queueMicrotask(() => {
requestAnimationFrame(() => {
tooltipHeight.val = tooltip.offsetHeight;
tooltipWidth.val = tooltip.offsetWidth;

// Fade in
requestAnimationFrame(() => {
opacity.val = 1;
});
});
});

return tooltip;
};
47 changes: 22 additions & 25 deletions src/packages/tour/components/DisableInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,35 @@ export type HelperLayerProps = {
helperElementPadding: number;
};

export const DisableInteraction = ({
export const DisableInteraction = async ({
currentStep,
steps,
refreshes,
targetElement,
helperElementPadding,
}: HelperLayerProps) => {
}: HelperLayerProps): Promise<HTMLElement | null> => {
// derive current step
const step = dom.derive(() =>
currentStep.val !== undefined ? steps[currentStep.val] : null
);

return () => {
if (!step.val) {
return null;
}

const disableInteraction = div({
className: disableInteractionClassName,
});

dom.derive(() => {
// set the position of the reference layer if the refreshes signal changes
if (!step.val || refreshes.val == undefined) return;

setPositionRelativeToStep(
targetElement,
disableInteraction,
step.val,
helperElementPadding
);
});

return disableInteraction;
};
if (!step.val) return null;

const disableInteraction = div({
className: disableInteractionClassName,
});

dom.derive(() => {
// set the position of the reference layer if the refreshes signal changes
if (!step.val || refreshes.val == undefined) return;

setPositionRelativeToStep(
targetElement,
disableInteraction,
step.val,
helperElementPadding
);
});

return disableInteraction;
};
4 changes: 2 additions & 2 deletions src/packages/tour/components/HelperLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ export type HelperLayerProps = {
helperLayerPadding: number;
};

export const HelperLayer = ({
export const HelperLayer = async ({
currentStep,
steps,
refreshes,
targetElement,
tourHighlightClass,
overlayOpacity,
helperLayerPadding,
}: HelperLayerProps) => {
}: HelperLayerProps): Promise<HTMLElement | null> => {
const step = dom.derive(() =>
currentStep.val !== undefined ? steps[currentStep.val] : null
);
Expand Down
4 changes: 2 additions & 2 deletions src/packages/tour/components/OverlayLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export type OverlayLayerProps = {
onExitTour: () => Promise<Tour>;
};

export const OverlayLayer = ({
export const OverlayLayer = async ({
exitOnOverlayClick,
onExitTour,
}: OverlayLayerProps) => {
}: OverlayLayerProps): Promise<HTMLElement> => {
const overlayLayer = div({
className: overlayClassName,
style: style({
Expand Down
14 changes: 8 additions & 6 deletions src/packages/tour/components/ReferenceLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ export type ReferenceLayerProps = TourTooltipProps & {
helperElementPadding: number;
};

export const ReferenceLayer = ({
export const ReferenceLayer = async ({
targetElement,
helperElementPadding,
...props
}: ReferenceLayerProps) => {
}: ReferenceLayerProps): Promise<HTMLElement | null> => {
// Wait for tooltip to be ready (async)
const tooltip = await TourTooltip(props);
if (!tooltip) return null;

const referenceLayer = div(
{
className: tooltipReferenceLayerClassName,
},
TourTooltip(props)
{ className: tooltipReferenceLayerClassName },
tooltip
);

dom.derive(() => {
Expand Down
17 changes: 15 additions & 2 deletions src/packages/tour/components/TourRoot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ jest.mock("./OverlayLayer", () => ({
jest.mock("./DisableInteraction", () => ({
DisableInteraction: jest.fn(() => "DisableInteraction"),
}));
jest.mock("./HelperLayer", () => ({
HelperLayer: jest.fn(() => "HelperLayer"),
}));
jest.mock("./ReferenceLayer", () => ({
ReferenceLayer: jest.fn(() => "ReferenceLayer"),
}));
jest.mock("../steps", () => ({ nextStep: jest.fn(), previousStep: jest.fn() }));

jest.useFakeTimers();
Expand All @@ -17,8 +23,15 @@ describe("TourRoot", () => {
tour = {
getCurrentStepSignal: jest.fn(() => ({ val: 0 })),
getRefreshesSignal: jest.fn(() => ({ val: 0 })),
getSteps: jest.fn(() => [{ disableInteraction: false }]),
getTargetElement: jest.fn(() => "targetElement"),
getStepReadySignal: jest.fn(() => ({ val: true })),
getSteps: jest.fn(() => [
{
disableInteraction: false,
element: document.createElement("div"),
intro: "test",
},
]),
getTargetElement: jest.fn(() => document.createElement("div")),
getOption: jest.fn((option: keyof typeof Option) => {
const options = {
highlightClass: "highlight",
Expand Down
Loading
Loading