File size: 3,311 Bytes
aa3b624 66a740c 9db3a38 82a88c5 9bde4cc aa3b624 edd7dca aa3b624 edd7dca aa3b624 edd7dca aa3b624 9bde4cc aa3b624 9bde4cc aa3b624 9bde4cc aa3b624 75e70b4 aa3b624 66a740c 9db3a38 9bde4cc 9db3a38 aa3b624 9bde4cc 4c98241 9bde4cc aa3b624 66a740c aa3b624 8480986 9db3a38 9bde4cc aa3b624 9bde4cc aa3b624 82a88c5 9db3a38 82a88c5 aa3b624 9bde4cc edd7dca aa3b624 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import { DriveStep } from "./driver";
import { refreshStage, trackActiveElement, transitionStage } from "./stage";
import { getConfig } from "./config";
import { repositionPopover, renderPopover, hidePopover } from "./popover";
import { bringInView } from "./utils";
import { getState, setState } from "./state";
function mountDummyElement(): Element {
const existingDummy = document.getElementById("driver-dummy-element");
if (existingDummy) {
return existingDummy;
}
let element = document.createElement("div");
element.id = "driver-dummy-element";
element.style.width = "0";
element.style.height = "0";
element.style.pointerEvents = "none";
element.style.opacity = "0";
element.style.position = "fixed";
element.style.top = "50%";
element.style.left = "50%";
document.body.appendChild(element);
return element;
}
export function highlight(step: DriveStep) {
const { element } = step;
let elemObj = typeof element === "string" ? document.querySelector(element) : element;
if (!elemObj) {
elemObj = mountDummyElement();
}
const previousHighlight = getState("activeHighlight");
const transferHighlightFrom = previousHighlight || elemObj;
const transferHighlightTo = elemObj;
transferHighlight(transferHighlightFrom, transferHighlightTo);
setState("previousHighlight", transferHighlightFrom);
setState("activeHighlight", transferHighlightTo);
}
export function refreshActiveHighlight() {
const activeHighlight = getState("activeHighlight");
if (!activeHighlight) {
return;
}
trackActiveElement(activeHighlight);
refreshStage();
repositionPopover(activeHighlight);
}
function transferHighlight(from: Element, to: Element) {
const duration = 400;
const start = Date.now();
// If it's the first time we're highlighting an element, we show
// the popover immediately. Otherwise, we wait for the animation
// to finish before showing the popover.
const hasDelayedPopover = to && (!from || from !== to);
hidePopover();
const animate = () => {
const transitionCallback = getState("transitionCallback");
// This makes sure that the repeated calls to transferHighlight
// don't interfere with each other. Only the last call will be
// executed.
if (transitionCallback !== animate) {
return;
}
const elapsed = Date.now() - start;
if (getConfig("animate") && elapsed < duration) {
transitionStage(elapsed, duration, from, to);
} else {
trackActiveElement(to);
if (hasDelayedPopover) {
renderPopover(to);
}
setState("transitionCallback", undefined);
}
window.requestAnimationFrame(animate);
};
setState("transitionCallback", animate);
window.requestAnimationFrame(animate);
bringInView(to);
if (!hasDelayedPopover) {
renderPopover(to);
}
from.classList.remove("driver-active-element");
to.classList.add("driver-active-element");
}
export function destroyHighlight() {
setState("activeHighlight", undefined);
setState("previousHighlight", undefined);
setState("transitionCallback", undefined);
document.getElementById("driver-dummy-element")?.remove();
document.querySelectorAll(".driver-active-element").forEach(element => {
element.classList.remove("driver-active-element");
});
}
|