Driver refactoring

This commit is contained in:
Kamran Ahmed
2023-07-01 11:13:24 +01:00
parent a0a08e9fa3
commit e459aae50b
5 changed files with 73 additions and 32 deletions
+19
View File
@@ -0,0 +1,19 @@
---
title: "Theming"
groupTitle: "Introduction"
sort: 3
---
You can customize the look and feel of the driver by applying CSS to following classes.
```css
/* Applied to the `body` when the driver: */
.driver-active {} /* is active */
.driver-fade {} /* is animated */
.driver-simple {} /* is not animated */
```
Following classes are applied to the overlay element (i.e. called stage.
```css
.driver-stage {}
+29 -7
View File
@@ -1,5 +1,5 @@
import { AllowedButtons, destroyPopover, Popover } from "./popover";
import { destroyStage } from "./stage";
import { destroyOverlay } from "./overlay";
import { destroyEvents, initEvents, requireRefresh } from "./events";
import { Config, configure, DriverHook, getConfig } from "./config";
import { destroyHighlight, highlight } from "./highlight";
@@ -57,19 +57,40 @@ export function driver(options: Config = {}) {
}
function handleArrowLeft() {
const steps = getConfig("steps") || [];
const isTransitioning = getState("__transitionCallback");
if (isTransitioning) {
return;
}
const activeIndex = getState("activeIndex");
const activeStep = getState("activeStep");
const activeElement = getState("activeElement");
if (typeof activeIndex === "undefined" || typeof activeStep === "undefined") {
return;
}
const currentStepIndex = getState("activeIndex");
if (typeof currentStepIndex === "undefined") {
return;
}
const previousStepIndex = currentStepIndex - 1;
if (steps[previousStepIndex]) {
drive(previousStepIndex);
const onPrevClick = activeStep.popover?.onPrevClick || getConfig("onPrevClick");
if (onPrevClick) {
return onPrevClick(activeElement, activeStep, {
config: getConfig(),
state: getState(),
});
}
movePrevious();
}
function handleArrowRight() {
const isTransitioning = getState("__transitionCallback");
if (isTransitioning) {
return;
}
const activeIndex = getState("activeIndex");
const activeStep = getState("activeStep");
const activeElement = getState("activeElement");
@@ -113,8 +134,9 @@ export function driver(options: Config = {}) {
}
if (!steps[stepIndex]) {
console.warn(`Step not found at index: ${stepIndex}`);
destroy();
return;
}
setState("activeIndex", stepIndex);
@@ -185,7 +207,7 @@ export function driver(options: Config = {}) {
destroyEvents();
destroyPopover();
destroyHighlight();
destroyStage();
destroyOverlay();
destroyEmitter();
resetState();
+2 -2
View File
@@ -1,5 +1,5 @@
import { DriveStep } from "./driver";
import { refreshStage, trackActiveElement, transitionStage } from "./stage";
import { refreshOverlay, trackActiveElement, transitionStage } from "./overlay";
import { getConfig } from "./config";
import { repositionPopover, renderPopover, hidePopover } from "./popover";
import { bringInView } from "./utils";
@@ -51,7 +51,7 @@ export function refreshActiveHighlight() {
}
trackActiveElement(activeHighlight);
refreshStage();
refreshOverlay();
repositionPopover(activeHighlight, activeStep);
}
+21 -21
View File
@@ -31,7 +31,7 @@ export function transitionStage(elapsed: number, duration: number, from: Element
height,
};
renderStage(activeStagePosition);
renderOverlay(activeStagePosition);
setState("__activeStagePosition", activeStagePosition);
}
@@ -51,18 +51,18 @@ export function trackActiveElement(element: Element) {
setState("__activeStagePosition", activeStagePosition);
renderStage(activeStagePosition);
renderOverlay(activeStagePosition);
}
export function refreshStage() {
export function refreshOverlay() {
const activeStagePosition = getState("__activeStagePosition");
const stageSvg = getState("__stageSvg");
const overlaySvg = getState("__overlaySvg");
if (!activeStagePosition) {
return;
}
if (!stageSvg) {
if (!overlaySvg) {
console.warn("No stage svg found.");
return;
}
@@ -70,14 +70,14 @@ export function refreshStage() {
const windowX = window.innerWidth;
const windowY = window.innerHeight;
stageSvg.setAttribute("viewBox", `0 0 ${windowX} ${windowY}`);
overlaySvg.setAttribute("viewBox", `0 0 ${windowX} ${windowY}`);
}
function mountStage(stagePosition: StageDefinition) {
const stageSvg = createStageSvg(stagePosition);
document.body.appendChild(stageSvg);
function mountOverlay(stagePosition: StageDefinition) {
const overlaySvg = createOverlaySvg(stagePosition);
document.body.appendChild(overlaySvg);
onDriverClick(stageSvg, e => {
onDriverClick(overlaySvg, e => {
const target = e.target as SVGElement;
if (target.tagName !== "path") {
return;
@@ -86,20 +86,20 @@ function mountStage(stagePosition: StageDefinition) {
emit("overlayClick");
});
setState("__stageSvg", stageSvg);
setState("__overlaySvg", overlaySvg);
}
function renderStage(stagePosition: StageDefinition) {
const stageSvg = getState("__stageSvg");
function renderOverlay(stagePosition: StageDefinition) {
const overlaySvg = getState("__overlaySvg");
// TODO: cancel rendering if element is not visible
if (!stageSvg) {
mountStage(stagePosition);
if (!overlaySvg) {
mountOverlay(stagePosition);
return;
}
const pathElement = stageSvg.firstElementChild as SVGPathElement | null;
const pathElement = overlaySvg.firstElementChild as SVGPathElement | null;
if (pathElement?.tagName !== "path") {
throw new Error("no path element found in stage svg");
}
@@ -107,7 +107,7 @@ function renderStage(stagePosition: StageDefinition) {
pathElement.setAttribute("d", generateStageSvgPathString(stagePosition));
}
function createStageSvg(stage: StageDefinition): SVGSVGElement {
function createOverlaySvg(stage: StageDefinition): SVGSVGElement {
const windowX = window.innerWidth;
const windowY = window.innerHeight;
@@ -170,9 +170,9 @@ function generateStageSvgPathString(stage: StageDefinition) {
M${highlightBoxX},${highlightBoxY} h${highlightBoxWidth} a${normalizedRadius},${normalizedRadius} 0 0 1 ${normalizedRadius},${normalizedRadius} v${highlightBoxHeight} a${normalizedRadius},${normalizedRadius} 0 0 1 -${normalizedRadius},${normalizedRadius} h-${highlightBoxWidth} a${normalizedRadius},${normalizedRadius} 0 0 1 -${normalizedRadius},-${normalizedRadius} v-${highlightBoxHeight} a${normalizedRadius},${normalizedRadius} 0 0 1 ${normalizedRadius},-${normalizedRadius} z`;
}
export function destroyStage() {
const stageSvg = getState("__stageSvg");
if (stageSvg) {
stageSvg.remove();
export function destroyOverlay() {
const overlaySvg = getState("__overlaySvg");
if (overlaySvg) {
overlaySvg.remove();
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
import { StageDefinition } from "./stage";
import { StageDefinition } from "./overlay";
import { PopoverDOM } from "./popover";
import { DriveStep } from "./driver";
@@ -17,7 +17,7 @@ export type State = {
__resizeTimeout?: number;
__transitionCallback?: () => void;
__activeStagePosition?: StageDefinition;
__stageSvg?: SVGSVGElement;
__overlaySvg?: SVGSVGElement;
};
let currentState: State = {};