Add support for showing progress
Browse files- index.html +6 -0
- src/config.ts +4 -1
- src/driver.ts +8 -0
- src/popover.ts +36 -15
- src/style.css +8 -0
index.html
CHANGED
|
@@ -3,6 +3,8 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
|
|
|
|
| 6 |
<title>Vite App</title>
|
| 7 |
|
| 8 |
<style>
|
|
@@ -410,6 +412,7 @@ npm install driver.js</pre
|
|
| 410 |
animate: false,
|
| 411 |
backdropColor: "blue",
|
| 412 |
opacity: 0.3,
|
|
|
|
| 413 |
steps: basicTourSteps,
|
| 414 |
});
|
| 415 |
|
|
@@ -438,6 +441,8 @@ npm install driver.js</pre
|
|
| 438 |
const driverObj = driver({
|
| 439 |
animate: true,
|
| 440 |
opacity: 0.3,
|
|
|
|
|
|
|
| 441 |
steps: [
|
| 442 |
{
|
| 443 |
element: ".page-header",
|
|
@@ -524,6 +529,7 @@ npm install driver.js</pre
|
|
| 524 |
|
| 525 |
document.getElementById("basic-tour").addEventListener("click", () => {
|
| 526 |
const driverObj = driver({
|
|
|
|
| 527 |
steps: basicTourSteps,
|
| 528 |
});
|
| 529 |
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8" />
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<!-- prefetch image -->
|
| 7 |
+
<link rel="preconnect" href="https://i.imgur.com/" />
|
| 8 |
<title>Vite App</title>
|
| 9 |
|
| 10 |
<style>
|
|
|
|
| 412 |
animate: false,
|
| 413 |
backdropColor: "blue",
|
| 414 |
opacity: 0.3,
|
| 415 |
+
showProgress: true,
|
| 416 |
steps: basicTourSteps,
|
| 417 |
});
|
| 418 |
|
|
|
|
| 441 |
const driverObj = driver({
|
| 442 |
animate: true,
|
| 443 |
opacity: 0.3,
|
| 444 |
+
showProgress: true,
|
| 445 |
+
progressText: "{{current}} / {{total}}",
|
| 446 |
steps: [
|
| 447 |
{
|
| 448 |
element: ".page-header",
|
|
|
|
| 529 |
|
| 530 |
document.getElementById("basic-tour").addEventListener("click", () => {
|
| 531 |
const driverObj = driver({
|
| 532 |
+
showProgress: true,
|
| 533 |
steps: basicTourSteps,
|
| 534 |
});
|
| 535 |
|
src/config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
import { DriveStep } from "./driver";
|
| 2 |
-
import {AllowedButtons, PopoverDOM} from "./popover";
|
| 3 |
|
| 4 |
export type Config = {
|
| 5 |
steps?: DriveStep[];
|
|
@@ -17,9 +17,11 @@ export type Config = {
|
|
| 17 |
popoverClass?: string;
|
| 18 |
popoverOffset?: number;
|
| 19 |
showButtons?: AllowedButtons[];
|
|
|
|
| 20 |
disableButtons?: AllowedButtons[];
|
| 21 |
|
| 22 |
// Button texts
|
|
|
|
| 23 |
nextBtnText?: string;
|
| 24 |
prevBtnText?: string;
|
| 25 |
doneBtnText?: string;
|
|
@@ -49,6 +51,7 @@ export function configure(config: Config = {}) {
|
|
| 49 |
allowClose: true,
|
| 50 |
opacity: 0.7,
|
| 51 |
smoothScroll: false,
|
|
|
|
| 52 |
stagePadding: 10,
|
| 53 |
stageRadius: 5,
|
| 54 |
popoverOffset: 10,
|
|
|
|
| 1 |
import { DriveStep } from "./driver";
|
| 2 |
+
import { AllowedButtons, PopoverDOM } from "./popover";
|
| 3 |
|
| 4 |
export type Config = {
|
| 5 |
steps?: DriveStep[];
|
|
|
|
| 17 |
popoverClass?: string;
|
| 18 |
popoverOffset?: number;
|
| 19 |
showButtons?: AllowedButtons[];
|
| 20 |
+
showProgress?: boolean;
|
| 21 |
disableButtons?: AllowedButtons[];
|
| 22 |
|
| 23 |
// Button texts
|
| 24 |
+
progressText?: string;
|
| 25 |
nextBtnText?: string;
|
| 26 |
prevBtnText?: string;
|
| 27 |
doneBtnText?: string;
|
|
|
|
| 51 |
allowClose: true,
|
| 52 |
opacity: 0.7,
|
| 53 |
smoothScroll: false,
|
| 54 |
+
showProgress: false,
|
| 55 |
stagePadding: 10,
|
| 56 |
stageRadius: 5,
|
| 57 |
popoverOffset: 10,
|
src/driver.ts
CHANGED
|
@@ -120,13 +120,19 @@ export function driver(options: Config = {}) {
|
|
| 120 |
|
| 121 |
const doneBtnText = currentStep.popover?.doneBtnText || getConfig("doneBtnText") || "Done";
|
| 122 |
const allowsClosing = getConfig("allowClose");
|
|
|
|
|
|
|
|
|
|
| 123 |
|
|
|
|
| 124 |
highlight({
|
| 125 |
...currentStep,
|
| 126 |
popover: {
|
| 127 |
showButtons: ["next", "previous", ...(allowsClosing ? ["close" as AllowedButtons] : [])],
|
| 128 |
nextBtnText: !hasNextStep ? doneBtnText : undefined,
|
| 129 |
disableButtons: [...(!hasPreviousStep ? ["previous" as AllowedButtons] : [])],
|
|
|
|
|
|
|
| 130 |
onNextClick: () => {
|
| 131 |
if (!hasNextStep) {
|
| 132 |
destroy();
|
|
@@ -211,6 +217,8 @@ export function driver(options: Config = {}) {
|
|
| 211 |
popover: step.popover
|
| 212 |
? {
|
| 213 |
showButtons: [],
|
|
|
|
|
|
|
| 214 |
...step.popover!,
|
| 215 |
}
|
| 216 |
: undefined,
|
|
|
|
| 120 |
|
| 121 |
const doneBtnText = currentStep.popover?.doneBtnText || getConfig("doneBtnText") || "Done";
|
| 122 |
const allowsClosing = getConfig("allowClose");
|
| 123 |
+
const showProgress = typeof currentStep.popover?.showProgress !== "undefined" ? currentStep.popover?.showProgress : getConfig("showProgress")
|
| 124 |
+
const progressText = currentStep.popover?.progressText || getConfig("progressText") || "{{current}} of {{total}}";
|
| 125 |
+
const progressTextReplaced = progressText.replace("{{current}}", `${stepIndex + 1}`).replace("{{total}}", `${steps.length}`);
|
| 126 |
|
| 127 |
+
console.log(showProgress);
|
| 128 |
highlight({
|
| 129 |
...currentStep,
|
| 130 |
popover: {
|
| 131 |
showButtons: ["next", "previous", ...(allowsClosing ? ["close" as AllowedButtons] : [])],
|
| 132 |
nextBtnText: !hasNextStep ? doneBtnText : undefined,
|
| 133 |
disableButtons: [...(!hasPreviousStep ? ["previous" as AllowedButtons] : [])],
|
| 134 |
+
showProgress: showProgress,
|
| 135 |
+
progressText: progressTextReplaced,
|
| 136 |
onNextClick: () => {
|
| 137 |
if (!hasNextStep) {
|
| 138 |
destroy();
|
|
|
|
| 217 |
popover: step.popover
|
| 218 |
? {
|
| 219 |
showButtons: [],
|
| 220 |
+
showProgress: false,
|
| 221 |
+
progressText: "",
|
| 222 |
...step.popover!,
|
| 223 |
}
|
| 224 |
: undefined,
|
src/popover.ts
CHANGED
|
@@ -16,11 +16,13 @@ export type Popover = {
|
|
| 16 |
align?: Alignment;
|
| 17 |
|
| 18 |
showButtons?: AllowedButtons[];
|
|
|
|
| 19 |
disableButtons?: AllowedButtons[];
|
| 20 |
|
| 21 |
popoverClass?: string;
|
| 22 |
|
| 23 |
// Button texts
|
|
|
|
| 24 |
doneBtnText?: string;
|
| 25 |
nextBtnText?: string;
|
| 26 |
prevBtnText?: string;
|
|
@@ -41,6 +43,7 @@ export type PopoverDOM = {
|
|
| 41 |
title: HTMLElement;
|
| 42 |
description: HTMLElement;
|
| 43 |
footer: HTMLElement;
|
|
|
|
| 44 |
previousButton: HTMLElement;
|
| 45 |
nextButton: HTMLElement;
|
| 46 |
closeButton: HTMLElement;
|
|
@@ -70,13 +73,16 @@ export function renderPopover(element: Element, step: DriveStep) {
|
|
| 70 |
description,
|
| 71 |
showButtons,
|
| 72 |
disableButtons,
|
|
|
|
| 73 |
|
| 74 |
nextBtnText = getConfig("nextBtnText") || "Next →",
|
| 75 |
prevBtnText = getConfig("prevBtnText") || "← Previous",
|
|
|
|
| 76 |
} = step.popover || {};
|
| 77 |
|
| 78 |
popover.nextButton.innerHTML = nextBtnText;
|
| 79 |
popover.previousButton.innerHTML = prevBtnText;
|
|
|
|
| 80 |
|
| 81 |
if (title) {
|
| 82 |
popover.title.innerText = title;
|
|
@@ -93,27 +99,36 @@ export function renderPopover(element: Element, step: DriveStep) {
|
|
| 93 |
}
|
| 94 |
|
| 95 |
const showButtonsConfig: AllowedButtons[] = showButtons || getConfig("showButtons")!;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
-
popover.closeButton.style.display = showButtonsConfig.includes("close") ?
|
| 98 |
-
|
|
|
|
| 99 |
popover.footer.style.display = "flex";
|
| 100 |
-
|
| 101 |
-
popover.
|
|
|
|
|
|
|
| 102 |
} else {
|
| 103 |
popover.footer.style.display = "none";
|
| 104 |
}
|
| 105 |
|
| 106 |
-
const disabledButtonsConfig: AllowedButtons[] = disableButtons || getConfig(
|
| 107 |
-
if (disabledButtonsConfig?.includes(
|
| 108 |
-
|
| 109 |
}
|
| 110 |
|
| 111 |
-
if (disabledButtonsConfig?.includes(
|
| 112 |
-
|
| 113 |
}
|
| 114 |
|
| 115 |
-
if (disabledButtonsConfig?.includes(
|
| 116 |
-
|
| 117 |
}
|
| 118 |
|
| 119 |
// Reset the popover position
|
|
@@ -182,7 +197,7 @@ export function renderPopover(element: Element, step: DriveStep) {
|
|
| 182 |
repositionPopover(element, step);
|
| 183 |
bringInView(popoverWrapper);
|
| 184 |
|
| 185 |
-
const onPopoverRendered = step.popover?.onPopoverRendered || getConfig(
|
| 186 |
if (onPopoverRendered) {
|
| 187 |
onPopoverRendered(popover);
|
| 188 |
}
|
|
@@ -566,13 +581,17 @@ function createPopover(): PopoverDOM {
|
|
| 566 |
description.style.display = "none";
|
| 567 |
description.innerText = "Popover description is here";
|
| 568 |
|
| 569 |
-
const footer = document.createElement("div");
|
| 570 |
-
footer.classList.add("driver-popover-footer");
|
| 571 |
-
|
| 572 |
const closeButton = document.createElement("button");
|
| 573 |
closeButton.classList.add("driver-popover-close-btn");
|
| 574 |
closeButton.innerHTML = "×";
|
| 575 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 576 |
const footerButtons = document.createElement("span");
|
| 577 |
footerButtons.classList.add("driver-popover-navigation-btns");
|
| 578 |
|
|
@@ -586,6 +605,7 @@ function createPopover(): PopoverDOM {
|
|
| 586 |
|
| 587 |
footerButtons.appendChild(previousButton);
|
| 588 |
footerButtons.appendChild(nextButton);
|
|
|
|
| 589 |
footer.appendChild(footerButtons);
|
| 590 |
|
| 591 |
wrapper.appendChild(closeButton);
|
|
@@ -604,6 +624,7 @@ function createPopover(): PopoverDOM {
|
|
| 604 |
nextButton,
|
| 605 |
closeButton,
|
| 606 |
footerButtons,
|
|
|
|
| 607 |
};
|
| 608 |
}
|
| 609 |
|
|
|
|
| 16 |
align?: Alignment;
|
| 17 |
|
| 18 |
showButtons?: AllowedButtons[];
|
| 19 |
+
showProgress?: boolean;
|
| 20 |
disableButtons?: AllowedButtons[];
|
| 21 |
|
| 22 |
popoverClass?: string;
|
| 23 |
|
| 24 |
// Button texts
|
| 25 |
+
progressText?: string;
|
| 26 |
doneBtnText?: string;
|
| 27 |
nextBtnText?: string;
|
| 28 |
prevBtnText?: string;
|
|
|
|
| 43 |
title: HTMLElement;
|
| 44 |
description: HTMLElement;
|
| 45 |
footer: HTMLElement;
|
| 46 |
+
progress: HTMLElement;
|
| 47 |
previousButton: HTMLElement;
|
| 48 |
nextButton: HTMLElement;
|
| 49 |
closeButton: HTMLElement;
|
|
|
|
| 73 |
description,
|
| 74 |
showButtons,
|
| 75 |
disableButtons,
|
| 76 |
+
showProgress,
|
| 77 |
|
| 78 |
nextBtnText = getConfig("nextBtnText") || "Next →",
|
| 79 |
prevBtnText = getConfig("prevBtnText") || "← Previous",
|
| 80 |
+
progressText = getConfig("progressText") || "{current} of {total}",
|
| 81 |
} = step.popover || {};
|
| 82 |
|
| 83 |
popover.nextButton.innerHTML = nextBtnText;
|
| 84 |
popover.previousButton.innerHTML = prevBtnText;
|
| 85 |
+
popover.progress.innerHTML = progressText;
|
| 86 |
|
| 87 |
if (title) {
|
| 88 |
popover.title.innerText = title;
|
|
|
|
| 99 |
}
|
| 100 |
|
| 101 |
const showButtonsConfig: AllowedButtons[] = showButtons || getConfig("showButtons")!;
|
| 102 |
+
const showProgressConfig = showProgress || getConfig("showProgress") || false;
|
| 103 |
+
const showFooter =
|
| 104 |
+
showButtonsConfig?.includes("next") ||
|
| 105 |
+
showButtonsConfig?.includes("previous") ||
|
| 106 |
+
showButtonsConfig?.includes("close") ||
|
| 107 |
+
showProgressConfig;
|
| 108 |
|
| 109 |
+
popover.closeButton.style.display = showButtonsConfig.includes("close") ? "block" : "none";
|
| 110 |
+
|
| 111 |
+
if (showFooter) {
|
| 112 |
popover.footer.style.display = "flex";
|
| 113 |
+
|
| 114 |
+
popover.progress.style.display = showProgressConfig ? "block" : "none";
|
| 115 |
+
popover.nextButton.style.display = showButtonsConfig.includes("next") ? "block" : "none";
|
| 116 |
+
popover.previousButton.style.display = showButtonsConfig.includes("previous") ? "block" : "none";
|
| 117 |
} else {
|
| 118 |
popover.footer.style.display = "none";
|
| 119 |
}
|
| 120 |
|
| 121 |
+
const disabledButtonsConfig: AllowedButtons[] = disableButtons || getConfig("disableButtons")! || [];
|
| 122 |
+
if (disabledButtonsConfig?.includes("next")) {
|
| 123 |
+
popover.nextButton.classList.add("driver-popover-btn-disabled");
|
| 124 |
}
|
| 125 |
|
| 126 |
+
if (disabledButtonsConfig?.includes("previous")) {
|
| 127 |
+
popover.previousButton.classList.add("driver-popover-btn-disabled");
|
| 128 |
}
|
| 129 |
|
| 130 |
+
if (disabledButtonsConfig?.includes("close")) {
|
| 131 |
+
popover.closeButton.classList.add("driver-popover-btn-disabled");
|
| 132 |
}
|
| 133 |
|
| 134 |
// Reset the popover position
|
|
|
|
| 197 |
repositionPopover(element, step);
|
| 198 |
bringInView(popoverWrapper);
|
| 199 |
|
| 200 |
+
const onPopoverRendered = step.popover?.onPopoverRendered || getConfig("onPopoverRendered");
|
| 201 |
if (onPopoverRendered) {
|
| 202 |
onPopoverRendered(popover);
|
| 203 |
}
|
|
|
|
| 581 |
description.style.display = "none";
|
| 582 |
description.innerText = "Popover description is here";
|
| 583 |
|
|
|
|
|
|
|
|
|
|
| 584 |
const closeButton = document.createElement("button");
|
| 585 |
closeButton.classList.add("driver-popover-close-btn");
|
| 586 |
closeButton.innerHTML = "×";
|
| 587 |
|
| 588 |
+
const footer = document.createElement("div");
|
| 589 |
+
footer.classList.add("driver-popover-footer");
|
| 590 |
+
|
| 591 |
+
const progress = document.createElement("span");
|
| 592 |
+
progress.classList.add("driver-popover-progress-text");
|
| 593 |
+
progress.innerText = "";
|
| 594 |
+
|
| 595 |
const footerButtons = document.createElement("span");
|
| 596 |
footerButtons.classList.add("driver-popover-navigation-btns");
|
| 597 |
|
|
|
|
| 605 |
|
| 606 |
footerButtons.appendChild(previousButton);
|
| 607 |
footerButtons.appendChild(nextButton);
|
| 608 |
+
footer.appendChild(progress);
|
| 609 |
footer.appendChild(footerButtons);
|
| 610 |
|
| 611 |
wrapper.appendChild(closeButton);
|
|
|
|
| 624 |
nextButton,
|
| 625 |
closeButton,
|
| 626 |
footerButtons,
|
| 627 |
+
progress,
|
| 628 |
};
|
| 629 |
}
|
| 630 |
|
src/style.css
CHANGED
|
@@ -101,9 +101,17 @@
|
|
| 101 |
text-align: right;
|
| 102 |
zoom: 1;
|
| 103 |
display: flex;
|
|
|
|
| 104 |
justify-content: space-between;
|
| 105 |
}
|
| 106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
.driver-popover-footer button {
|
| 108 |
all: unset;
|
| 109 |
display: inline-block;
|
|
|
|
| 101 |
text-align: right;
|
| 102 |
zoom: 1;
|
| 103 |
display: flex;
|
| 104 |
+
align-items: center;
|
| 105 |
justify-content: space-between;
|
| 106 |
}
|
| 107 |
|
| 108 |
+
.driver-popover-progress-text {
|
| 109 |
+
font-size: 13px;
|
| 110 |
+
font-weight: 400;
|
| 111 |
+
color: #a2a2a2;
|
| 112 |
+
zoom: 1;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
.driver-popover-footer button {
|
| 116 |
all: unset;
|
| 117 |
display: inline-block;
|