app-walkthrough
Version:
An intuitive guided walkthrough library with UI highlighting and voice narration for web apps.
74 lines (73 loc) • 2.52 kB
JavaScript
import { handleDropdownAction } from "./handleDropdownAction";
import { handleInputAction } from "./handleInputAction";
import { setHighlight } from "./highlight";
import { speakTextAsync } from "./speech";
import { findElement, safeClick, wait } from "./utils";
import { isUiAction, isUrlAction } from "./dataTypes";
export async function handleUrlAction(step, navigate) {
var _a;
if (!isUrlAction(step))
return;
if (step.beforeMessage)
await speakTextAsync(step.beforeMessage);
// Navigate to the new page
navigate(step.urlString);
// Wait for the next tick to allow React Router to update
await new Promise(requestAnimationFrame);
// Wait until document.readyState === 'complete' or 'interactive'
while (document.readyState !== "complete" &&
document.readyState !== "interactive") {
await wait(100);
}
// Add a small delay to allow React hydration
await wait(500);
if (step.afterMessage)
await speakTextAsync(step.afterMessage);
const waitSeconds = (_a = step.waitSeconds) !== null && _a !== void 0 ? _a : 5;
await wait(waitSeconds * 1000);
}
function handleClickAction(element, step) {
if (["click", "clickRowAction", "clickTab"].includes(step.actionType)) {
safeClick(element);
}
}
export async function handleUiAction(step) {
if (!isUiAction(step) || step.selectors.length === 0)
return false;
const element = findElement(step.selectors, document);
if (!element) {
console.log("Element not found. Step:", step.selectors);
return false;
}
console.log("Element found:", element);
setHighlight(element);
if (step.beforeMessage)
await speakTextAsync(step.beforeMessage);
handleStepAction(element, step);
element.blur();
if (step.afterMessage)
await speakTextAsync(step.afterMessage);
return true;
}
function handleStepAction(element, step) {
switch (step.actionType) {
case "input":
handleInputAction(element, step);
break;
case "select":
case "dropdownClick":
case "dropdownSearchClick":
case "multiSelect":
handleDropdownAction(element, step);
break;
case "click":
case "clickRowAction":
case "clickTab":
handleClickAction(element, step);
break;
// Future extensibility:
// case "select":
// handleSelectAction(element, step);
// break;
}
}