@trail-cli/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +31 -0
- package/dist/index.global.js +232 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +932 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/guide-loader.ts","../src/session-storage.ts","../src/state.ts","../src/highlight.ts","../src/overlay.ts","../src/target-resolver.ts","../src/dom-watcher.ts","../src/spa-router.ts","../src/engine.ts","../src/index.ts"],"sourcesContent":["import { parseGuideJson, type Guide, type GuideValidationIssue } from \"@trail-cli/guide-schema\";\n\nexport type LoadGuideResult =\n | { success: true; guide: Guide }\n | {\n success: false;\n kind: \"not-found\" | \"network-error\" | \"server-error\" | \"invalid\";\n issues?: GuideValidationIssue[];\n };\n\n/**\n * Fetches a built guide JSON asset and validates it. The SDK only ever consumes the\n * static JSON produced by `trail build`, so the (larger) YAML parser stays out\n * of the runtime bundle — keeping the SDK lightweight per spec #34.\n */\nexport async function loadGuide(url: string): Promise<LoadGuideResult> {\n let response: Response;\n try {\n response = await fetch(url, { credentials: \"same-origin\" });\n } catch {\n return { success: false, kind: \"network-error\" };\n }\n\n if (!response.ok) {\n return { success: false, kind: response.status === 404 ? \"not-found\" : \"server-error\" };\n }\n\n const text = await response.text();\n const result = parseGuideJson(text);\n\n if (!result.success) {\n return { success: false, kind: \"invalid\", issues: result.issues };\n }\n\n return { success: true, guide: result.guide };\n}\n","export interface GuideCheckpoint {\n release: string;\n guideId: string;\n stepIndex: number;\n stepId: string;\n}\n\nconst STORAGE_KEY = \"trail:checkpoint\";\n\nfunction safeSessionStorage(): Storage | null {\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nexport function saveCheckpoint(checkpoint: GuideCheckpoint): void {\n const storage = safeSessionStorage();\n if (!storage) return;\n try {\n storage.setItem(STORAGE_KEY, JSON.stringify(checkpoint));\n } catch {\n // Storage can throw when full/disabled; progress simply won't survive a reload.\n }\n}\n\nexport function loadCheckpoint(release: string, guideId: string): GuideCheckpoint | null {\n const storage = safeSessionStorage();\n if (!storage) return null;\n try {\n const raw = storage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Partial<GuideCheckpoint>;\n if (\n parsed.release === release &&\n parsed.guideId === guideId &&\n typeof parsed.stepIndex === \"number\" &&\n Number.isInteger(parsed.stepIndex) &&\n typeof parsed.stepId === \"string\"\n ) {\n return { release, guideId, stepIndex: parsed.stepIndex, stepId: parsed.stepId };\n }\n storage.removeItem(STORAGE_KEY);\n return null;\n } catch {\n clearCheckpoint();\n return null;\n }\n}\n\nexport function clearCheckpoint(): void {\n const storage = safeSessionStorage();\n if (!storage) return;\n try {\n storage.removeItem(STORAGE_KEY);\n } catch {\n // Ignore.\n }\n}\n","import type { Guide } from \"@trail-cli/guide-schema\";\nimport type { GuideCheckpoint } from \"./session-storage.js\";\n\nexport function resolveCheckpointIndex(guide: Guide, checkpoint: GuideCheckpoint | null): number | null {\n if (!checkpoint) return 0;\n const index = guide.steps.findIndex((step) => step.id === checkpoint.stepId);\n return index >= 0 ? index : null;\n}\n\nexport class GuideState {\n readonly guide: Guide;\n private index: number;\n\n constructor(guide: Guide, startIndex = 0) {\n this.guide = guide;\n this.index = Math.min(Math.max(startIndex, 0), guide.steps.length - 1);\n }\n\n get currentIndex(): number {\n return this.index;\n }\n\n get currentStep() {\n return this.guide.steps[this.index]!;\n }\n\n get total(): number {\n return this.guide.steps.length;\n }\n\n get isFirst(): boolean {\n return this.index === 0;\n }\n\n get isLast(): boolean {\n return this.index === this.guide.steps.length - 1;\n }\n\n next(): boolean {\n if (this.isLast) return false;\n this.index += 1;\n return true;\n }\n\n back(): boolean {\n if (this.isFirst) return false;\n this.index -= 1;\n return true;\n }\n\n reset(): void {\n this.index = 0;\n }\n}\n","const PADDING = 6;\r\n\r\n/**\r\n * Draws a highlight rectangle around a target element using a \"spotlight\" box-shadow\r\n * (dims everything outside the box) and keeps it aligned via ResizeObserver/scroll/\r\n * resize listeners instead of polling, per spec #10.\r\n */\r\nexport class Spotlight {\r\n private readonly box: HTMLDivElement;\r\n private readonly blockers: HTMLDivElement[];\r\n private target: HTMLElement | null = null;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private rafHandle: number | null = null;\r\n\r\n constructor(container: HTMLElement) {\r\n this.box = document.createElement(\"div\");\r\n this.box.className = \"tg-spotlight\";\r\n this.blockers = Array.from({ length: 4 }, () => {\r\n const blocker = document.createElement(\"div\");\r\n blocker.className = \"tg-blocker\";\r\n container.appendChild(blocker);\r\n return blocker;\r\n });\r\n container.appendChild(this.box);\r\n\r\n window.addEventListener(\"resize\", this.scheduleReposition);\r\n window.addEventListener(\"scroll\", this.scheduleReposition, true);\r\n }\r\n\r\n attachTo(element: HTMLElement): void {\r\n this.detachObserver();\r\n this.target = element;\r\n this.resizeObserver = new ResizeObserver(this.scheduleReposition);\r\n this.resizeObserver.observe(element);\r\n this.box.style.display = \"block\";\r\n this.blockers.forEach((blocker) => (blocker.style.display = \"block\"));\r\n this.reposition();\r\n }\r\n\r\n hide(): void {\r\n this.target = null;\r\n this.detachObserver();\r\n this.box.style.display = \"none\";\r\n this.blockers.forEach((blocker) => (blocker.style.display = \"none\"));\r\n }\r\n\r\n destroy(): void {\r\n this.hide();\r\n window.removeEventListener(\"resize\", this.scheduleReposition);\r\n window.removeEventListener(\"scroll\", this.scheduleReposition, true);\r\n this.blockers.forEach((blocker) => blocker.remove());\r\n this.box.remove();\r\n }\r\n\r\n private detachObserver(): void {\r\n this.resizeObserver?.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n\r\n private scheduleReposition = (): void => {\r\n if (this.rafHandle !== null) return;\r\n this.rafHandle = requestAnimationFrame(() => {\r\n this.rafHandle = null;\r\n this.reposition();\r\n });\r\n };\r\n\r\n private reposition(): void {\r\n if (!this.target) return;\r\n const rect = this.target.getBoundingClientRect();\r\n this.box.style.top = `${rect.top - PADDING}px`;\r\n this.box.style.left = `${rect.left - PADDING}px`;\r\n this.box.style.width = `${rect.width + PADDING * 2}px`;\r\n this.box.style.height = `${rect.height + PADDING * 2}px`;\r\n\r\n const top = Math.max(0, rect.top - PADDING);\r\n const left = Math.max(0, rect.left - PADDING);\r\n const right = Math.min(window.innerWidth, rect.right + PADDING);\r\n const bottom = Math.min(window.innerHeight, rect.bottom + PADDING);\r\n const dimensions: [number, number, number, number][] = [\r\n [0, 0, window.innerWidth, top],\r\n [0, top, left, bottom - top],\r\n [right, top, window.innerWidth - right, bottom - top],\r\n [0, bottom, window.innerWidth, window.innerHeight - bottom],\r\n ];\r\n this.blockers.forEach((blocker, index) => {\r\n const [blockerLeft, blockerTop, width, height] = dimensions[index]!;\r\n Object.assign(blocker.style, {\r\n left: `${blockerLeft}px`,\r\n top: `${blockerTop}px`,\r\n width: `${width}px`,\r\n height: `${height}px`,\r\n });\r\n });\r\n }\r\n}\r\n","import { Spotlight } from \"./highlight.js\";\n\nconst STYLE_ID = \"trail-sdk-styles\";\n\nconst STYLES = `\n.tg-root { position: fixed; inset: 0; z-index: 2147483647; pointer-events: none; }\n.tg-spotlight {\n position: fixed;\n display: none;\n border: 2px solid #4f7cff;\n border-radius: 6px;\n box-shadow: 0 0 0 9999px rgba(15, 17, 26, 0.55);\n pointer-events: none;\n transition: top 120ms ease, left 120ms ease, width 120ms ease, height 120ms ease;\n}\n.tg-blocker { position: fixed; z-index: 0; pointer-events: auto; }\n.tg-panel {\n position: fixed;\n right: 20px;\n bottom: 20px;\n z-index: 2;\n width: 320px;\n max-width: calc(100vw - 40px);\n background: #12131a;\n color: #f4f5f7;\n border-radius: 12px;\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);\n padding: 16px 18px;\n font: 14px/1.4 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n pointer-events: auto;\n}\n.tg-panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }\n.tg-progress-text { font-size: 12px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: #9aa1b5; }\n.tg-exit-btn {\n background: transparent; border: none; color: #9aa1b5; font-size: 18px; line-height: 1; cursor: pointer;\n padding: 4px; border-radius: 6px;\n}\n.tg-exit-btn:hover, .tg-exit-btn:focus-visible { color: #f4f5f7; background: rgba(255,255,255,0.08); }\n.tg-progress-bar { height: 4px; border-radius: 2px; background: rgba(255,255,255,0.12); overflow: hidden; margin-bottom: 12px; }\n.tg-progress-fill { height: 100%; background: #4f7cff; transition: width 160ms ease; }\n.tg-title { margin: 0 0 6px; font-size: 15px; font-weight: 700; }\n.tg-instruction { margin: 0 0 16px; color: #d4d7e2; white-space: pre-line; }\n.tg-panel-footer { display: flex; justify-content: space-between; gap: 8px; }\n.tg-btn {\n appearance: none; border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06);\n color: #f4f5f7; padding: 8px 14px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer;\n}\n.tg-btn:hover { background: rgba(255,255,255,0.14); }\n.tg-btn:focus-visible { outline: 2px solid #4f7cff; outline-offset: 2px; }\n.tg-btn:disabled { opacity: 0.4; cursor: not-allowed; }\n.tg-btn-primary { background: #4f7cff; border-color: #4f7cff; }\n.tg-btn-primary:hover { background: #3f6ce0; }\n.tg-error .tg-title { color: #ff6b6b; }\n.tg-error-detail { font-size: 12px; color: #9aa1b5; margin: -8px 0 16px; }\n`;\n\nfunction injectStyles(): void {\n if (document.getElementById(STYLE_ID)) return;\n const style = document.createElement(\"style\");\n style.id = STYLE_ID;\n style.textContent = STYLES;\n document.head.appendChild(style);\n}\n\nexport interface StepViewModel {\n stepNumber: number;\n totalSteps: number;\n title: string;\n instruction: string;\n canGoBack: boolean;\n canGoNext: boolean;\n nextLabel: string;\n}\n\nexport interface ErrorViewModel {\n title: string;\n message: string;\n detail?: string;\n showRetry: boolean;\n}\n\nexport interface OverlayCallbacks {\n onNext: () => void;\n onBack: () => void;\n onExit: () => void;\n onRetry: () => void;\n}\n\n/** Owns the SDK's self-contained DOM overlay: spotlight highlight + instruction panel. */\nconst FOCUSABLE_SELECTOR =\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nexport class Overlay {\n private readonly root: HTMLDivElement;\n private readonly panel: HTMLDivElement;\n readonly spotlight: Spotlight;\n private readonly callbacks: OverlayCallbacks;\n private keydownHandler: ((event: KeyboardEvent) => void) | null = null;\n private readonly previousBodyOverflow: string;\n private readonly previouslyFocusedElement: HTMLElement | null;\n private focusTarget: HTMLElement | null = null;\n\n constructor(callbacks: OverlayCallbacks) {\n injectStyles();\n this.callbacks = callbacks;\n this.previouslyFocusedElement = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n\n this.root = document.createElement(\"div\");\n this.root.className = \"tg-root\";\n\n this.panel = document.createElement(\"div\");\n this.panel.className = \"tg-panel\";\n this.panel.setAttribute(\"role\", \"dialog\");\n this.panel.setAttribute(\"aria-label\", \"Trail guide\");\n this.panel.setAttribute(\"aria-live\", \"polite\");\n this.panel.tabIndex = -1;\n this.root.appendChild(this.panel);\n\n this.spotlight = new Spotlight(this.root);\n document.body.appendChild(this.root);\n\n this.previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n this.keydownHandler = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n this.callbacks.onExit();\n return;\n }\n if (event.key === \"Tab\") {\n this.trapTabFocus(event);\n }\n };\n document.addEventListener(\"keydown\", this.keydownHandler, true);\n }\n\n /** Keeps focus cycling between the guided target and the panel controls. */\n private trapTabFocus(event: KeyboardEvent): void {\n const panelFocusable = Array.from(this.panel.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => el.offsetParent !== null || el === document.activeElement,\n );\n const focusTarget =\n this.focusTarget &&\n this.focusTarget.isConnected &&\n this.focusTarget.matches(FOCUSABLE_SELECTOR) &&\n (this.focusTarget.offsetParent !== null || this.focusTarget === document.activeElement)\n ? this.focusTarget\n : null;\n const focusable = focusTarget ? [focusTarget, ...panelFocusable] : panelFocusable;\n\n if (focusable.length === 0) {\n event.preventDefault();\n this.focusPanel();\n return;\n }\n\n const first = focusable[0]!;\n const last = focusable[focusable.length - 1]!;\n const active = document.activeElement;\n\n if (active === this.panel || !focusable.includes(active as HTMLElement)) {\n event.preventDefault();\n (event.shiftKey ? last : first).focus();\n return;\n }\n\n if (focusTarget && active === focusTarget) {\n event.preventDefault();\n (event.shiftKey ? last : panelFocusable[0] ?? focusTarget).focus();\n return;\n }\n\n if (event.shiftKey && focusTarget && active === panelFocusable[0]) {\n event.preventDefault();\n focusTarget.focus();\n return;\n }\n\n if (event.shiftKey && active === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n }\n\n renderStep(model: StepViewModel): void {\n const progressPct = Math.round((model.stepNumber / model.totalSteps) * 100);\n this.panel.className = \"tg-panel\";\n this.panel.innerHTML = `\n <div class=\"tg-panel-header\">\n <span class=\"tg-progress-text\">Step ${model.stepNumber} of ${model.totalSteps}</span>\n <button type=\"button\" class=\"tg-exit-btn\" aria-label=\"Exit Trail guide\">×</button>\n </div>\n <div class=\"tg-progress-bar\"><div class=\"tg-progress-fill\" style=\"width:${progressPct}%\"></div></div>\n <h2 class=\"tg-title\"></h2>\n <p class=\"tg-instruction\"></p>\n <div class=\"tg-panel-footer\">\n <button type=\"button\" class=\"tg-btn tg-back-btn\">Back</button>\n <button type=\"button\" class=\"tg-btn tg-btn-primary tg-next-btn\"></button>\n </div>\n `;\n\n this.panel.querySelector(\".tg-title\")!.textContent = model.title;\n this.panel.querySelector(\".tg-instruction\")!.textContent = model.instruction;\n\n const backBtn = this.panel.querySelector<HTMLButtonElement>(\".tg-back-btn\")!;\n backBtn.disabled = !model.canGoBack;\n backBtn.addEventListener(\"click\", () => this.callbacks.onBack());\n\n const nextBtn = this.panel.querySelector<HTMLButtonElement>(\".tg-next-btn\")!;\n nextBtn.disabled = !model.canGoNext;\n nextBtn.textContent = model.nextLabel;\n nextBtn.addEventListener(\"click\", () => this.callbacks.onNext());\n\n this.panel.querySelector<HTMLButtonElement>(\".tg-exit-btn\")!.addEventListener(\"click\", () => this.callbacks.onExit());\n\n this.focusPanel();\n }\n\n setFocusTarget(element: HTMLElement | null): void {\n this.focusTarget = element;\n }\n\n scrollToTarget(element: HTMLElement): void {\n document.body.style.overflow = this.previousBodyOverflow;\n element.scrollIntoView({ behavior: \"auto\", block: \"center\", inline: \"nearest\" });\n document.body.style.overflow = \"hidden\";\n }\n\n setNextEnabled(enabled: boolean): void {\n const nextBtn = this.panel.querySelector<HTMLButtonElement>(\".tg-next-btn\");\n if (nextBtn) nextBtn.disabled = !enabled;\n }\n\n renderLocating(model: Pick<StepViewModel, \"stepNumber\" | \"totalSteps\" | \"title\" | \"instruction\">): void {\n this.spotlight.hide();\n this.panel.className = \"tg-panel\";\n this.panel.innerHTML = `\n <div class=\"tg-panel-header\">\n <span class=\"tg-progress-text\">Step ${model.stepNumber} of ${model.totalSteps}</span>\n <button type=\"button\" class=\"tg-exit-btn\" aria-label=\"Exit Trail guide\">×</button>\n </div>\n <h2 class=\"tg-title\"></h2>\n <p class=\"tg-instruction\"></p>\n <p class=\"tg-error-detail\">Locating element on the page…</p>\n `;\n this.panel.querySelector(\".tg-title\")!.textContent = model.title;\n this.panel.querySelector(\".tg-instruction\")!.textContent = model.instruction;\n this.panel.querySelector<HTMLButtonElement>(\".tg-exit-btn\")!.addEventListener(\"click\", () => this.callbacks.onExit());\n this.focusPanel();\n }\n\n renderError(model: ErrorViewModel): void {\n this.spotlight.hide();\n this.panel.className = \"tg-panel tg-error\";\n this.panel.innerHTML = `\n <div class=\"tg-panel-header\">\n <span class=\"tg-progress-text\">Trail</span>\n <button type=\"button\" class=\"tg-exit-btn\" aria-label=\"Exit Trail guide\">×</button>\n </div>\n <h2 class=\"tg-title\"></h2>\n <p class=\"tg-instruction\"></p>\n ${model.detail ? `<p class=\"tg-error-detail\"></p>` : \"\"}\n <div class=\"tg-panel-footer\">\n ${model.showRetry ? '<button type=\"button\" class=\"tg-btn tg-retry-btn\">Retry</button>' : \"<span></span>\"}\n <button type=\"button\" class=\"tg-btn tg-btn-primary tg-exit-btn2\">Exit</button>\n </div>\n `;\n this.panel.querySelector(\".tg-title\")!.textContent = model.title;\n this.panel.querySelector(\".tg-instruction\")!.textContent = model.message;\n if (model.detail) {\n this.panel.querySelector(\".tg-error-detail\")!.textContent = model.detail;\n }\n this.panel.querySelector<HTMLButtonElement>(\".tg-exit-btn\")!.addEventListener(\"click\", () => this.callbacks.onExit());\n this.panel.querySelector<HTMLButtonElement>(\".tg-exit-btn2\")!.addEventListener(\"click\", () => this.callbacks.onExit());\n this.panel.querySelector<HTMLButtonElement>(\".tg-retry-btn\")?.addEventListener(\"click\", () => this.callbacks.onRetry());\n this.focusPanel();\n }\n\n renderComplete(title: string, totalSteps: number, onRestart: () => void): void {\n this.spotlight.hide();\n this.panel.className = \"tg-panel\";\n this.panel.innerHTML = `\n <h2 class=\"tg-title\">Trail Guide Complete</h2>\n <p class=\"tg-instruction\"></p>\n <div class=\"tg-panel-footer\">\n <button type=\"button\" class=\"tg-btn tg-restart-btn\">Restart</button>\n <button type=\"button\" class=\"tg-btn tg-btn-primary tg-exit-btn\">Exit</button>\n </div>\n `;\n this.panel.querySelector(\".tg-instruction\")!.textContent =\n `${title} — ${totalSteps} of ${totalSteps} steps completed.`;\n this.panel.querySelector<HTMLButtonElement>(\".tg-restart-btn\")!.addEventListener(\"click\", onRestart);\n this.panel.querySelector<HTMLButtonElement>(\".tg-exit-btn\")!.addEventListener(\"click\", () => this.callbacks.onExit());\n this.focusPanel();\n }\n\n private focusPanel(): void {\n this.panel.focus({ preventScroll: true });\n }\n\n destroy(): void {\n this.spotlight.destroy();\n if (this.keydownHandler) {\n document.removeEventListener(\"keydown\", this.keydownHandler, true);\n }\n document.body.style.overflow = this.previousBodyOverflow;\n this.root.remove();\n if (this.previouslyFocusedElement?.isConnected) {\n this.previouslyFocusedElement.focus({ preventScroll: true });\n }\n }\n}\n","import type { Target } from \"@trail-cli/guide-schema\";\nimport { TARGET_STRATEGY_ORDER } from \"@trail-cli/guide-schema\";\n\nexport interface ResolveAttempt {\n strategy: string;\n detail: string;\n found: boolean;\n}\n\nexport interface ResolveResult {\n element: HTMLElement | null;\n attempts: ResolveAttempt[];\n}\n\n/** Minimal implicit ARIA role mapping for the handful of controls guides commonly target. */\nconst IMPLICIT_ROLE_SELECTORS: Record<string, string> = {\n button: 'button, input[type=\"button\"], input[type=\"submit\"], input[type=\"reset\"], [role=\"button\"]',\n link: 'a[href], [role=\"link\"]',\n textbox:\n 'input:not([type]), input[type=\"text\"], input[type=\"email\"], input[type=\"search\"], input[type=\"tel\"], input[type=\"url\"], input[type=\"password\"], textarea, [role=\"textbox\"]',\n checkbox: 'input[type=\"checkbox\"], [role=\"checkbox\"]',\n radio: 'input[type=\"radio\"], [role=\"radio\"]',\n combobox: 'select, [role=\"combobox\"]',\n option: 'option, [role=\"option\"]',\n heading: 'h1, h2, h3, h4, h5, h6, [role=\"heading\"]',\n tab: '[role=\"tab\"]',\n};\n\nfunction normalize(text: string | null | undefined): string {\n return (text ?? \"\").trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n\nfunction isVisible(el: Element): boolean {\n if (!(el instanceof HTMLElement)) return false;\n if (el.hidden) return false;\n const style = window.getComputedStyle(el);\n return style.display !== \"none\" && style.visibility !== \"hidden\" && style.opacity !== \"0\";\n}\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") return CSS.escape(value);\n return value.replace(/([^\\w-])/g, \"\\\\$1\");\n}\n\n/** A pragmatic subset of the accessible-name computation algorithm. */\nfunction accessibleName(el: Element): string {\n const ariaLabel = el.getAttribute(\"aria-label\");\n if (ariaLabel) return normalize(ariaLabel);\n\n const labelledBy = el.getAttribute(\"aria-labelledby\");\n if (labelledBy) {\n const text = labelledBy\n .split(/\\s+/)\n .map((id) => document.getElementById(id)?.textContent ?? \"\")\n .join(\" \");\n if (text.trim()) return normalize(text);\n }\n\n if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {\n if (el.value) return normalize(el.value);\n if (el.placeholder) return normalize(el.placeholder);\n }\n\n return normalize(el.textContent);\n}\n\nfunction findByTestId(testId: string): ResolveAttempt & { element: HTMLElement | null } {\n const element = document.querySelector<HTMLElement>(\n `[data-testid=\"${cssEscape(testId)}\"]`,\n );\n return { strategy: \"testId\", detail: `[data-testid=\"${testId}\"]`, found: !!element, element };\n}\n\nfunction findByRole(role: string, name: string): ResolveAttempt & { element: HTMLElement | null } {\n const selector = IMPLICIT_ROLE_SELECTORS[role] ?? `[role=\"${role}\"]`;\n const candidates = Array.from(document.querySelectorAll<HTMLElement>(selector)).filter(isVisible);\n const target = normalize(name);\n const element = candidates.find((el) => accessibleName(el) === target) ?? null;\n return { strategy: \"role\", detail: `role=\"${role}\" name=\"${name}\"`, found: !!element, element };\n}\n\nfunction findByLabel(label: string): ResolveAttempt & { element: HTMLElement | null } {\n const target = normalize(label);\n const labels = Array.from(document.querySelectorAll(\"label\"));\n for (const labelEl of labels) {\n if (normalize(labelEl.textContent) !== target) continue;\n const forId = labelEl.getAttribute(\"for\");\n if (forId) {\n const control = document.getElementById(forId);\n if (control instanceof HTMLElement && isVisible(control)) {\n return { strategy: \"label\", detail: `label=\"${label}\"`, found: true, element: control };\n }\n }\n const nested = labelEl.querySelector<HTMLElement>(\"input, select, textarea\");\n if (nested && isVisible(nested)) {\n return { strategy: \"label\", detail: `label=\"${label}\"`, found: true, element: nested };\n }\n }\n return { strategy: \"label\", detail: `label=\"${label}\"`, found: false, element: null };\n}\n\nconst TEXT_CANDIDATE_SELECTOR =\n 'button, a, [role=\"button\"], [role=\"link\"], input[type=\"submit\"], input[type=\"button\"], *';\n\nfunction findByText(text: string): ResolveAttempt & { element: HTMLElement | null } {\n const target = normalize(text);\n let best: HTMLElement | null = null;\n let bestScore = Infinity;\n\n for (const el of document.querySelectorAll<HTMLElement>(TEXT_CANDIDATE_SELECTOR)) {\n if (!isVisible(el)) continue;\n const ownText = normalize(el.textContent);\n if (!ownText || !ownText.includes(target)) continue;\n // Prefer the smallest element that still contains the text (innermost match).\n const score = el.children.length + ownText.length;\n if (score < bestScore) {\n best = el;\n bestScore = score;\n }\n }\n\n return { strategy: \"text\", detail: `text=\"${text}\"`, found: !!best, element: best };\n}\n\nfunction findBySelector(selector: string): ResolveAttempt & { element: HTMLElement | null } {\n let element: HTMLElement | null = null;\n try {\n element = document.querySelector<HTMLElement>(selector);\n } catch {\n // Invalid selector strings are surfaced as a failed attempt rather than throwing.\n }\n return { strategy: \"selector\", detail: selector, found: !!element, element };\n}\n\n/**\n * Resolves a guide {@link Target} to a DOM element, trying each strategy present on\n * the target in priority order: testId -> role/name -> label -> text -> selector.\n */\nexport function resolveTarget(target: Target): ResolveResult {\n const attempts: ResolveAttempt[] = [];\n\n for (const strategy of TARGET_STRATEGY_ORDER) {\n let result: ResolveAttempt & { element: HTMLElement | null };\n\n if (strategy === \"testId\" && target.testId) {\n result = findByTestId(target.testId);\n } else if (strategy === \"role\" && target.role && target.name) {\n result = findByRole(target.role, target.name);\n } else if (strategy === \"label\" && target.label) {\n result = findByLabel(target.label);\n } else if (strategy === \"text\" && target.text) {\n result = findByText(target.text);\n } else if (strategy === \"selector\" && target.selector) {\n result = findBySelector(target.selector);\n } else {\n continue;\n }\n\n attempts.push({ strategy: result.strategy, detail: result.detail, found: result.found });\n if (result.element) {\n return { element: result.element, attempts };\n }\n }\n\n return { element: null, attempts };\n}\n","export interface WaitForElementOptions {\r\n /** How long to wait before giving up, in ms. Defaults to 10000 (10s) per spec. */\r\n timeoutMs?: number;\r\n /** Root to observe for DOM mutations. Defaults to document.body. */\r\n root?: Node;\r\n}\r\n\r\nexport interface WaitForElementResult {\r\n element: HTMLElement | null;\r\n timedOut: boolean;\r\n}\r\n\r\n/**\r\n * Repeatedly calls `resolve()` until it returns an element, watching the DOM via a\r\n * single MutationObserver instead of polling. Resolves with `timedOut: true` if the\r\n * default 10s budget elapses first.\r\n */\r\nexport function waitForElement(\r\n resolve: () => HTMLElement | null,\r\n options: WaitForElementOptions = {},\r\n): { promise: Promise<WaitForElementResult>; cancel: () => void } {\r\n const timeoutMs = options.timeoutMs ?? 10_000;\r\n const root = options.root ?? document.body;\r\n\r\n let settled = false;\r\n let observer: MutationObserver | null = null;\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n let rafHandle: number | null = null;\r\n\r\n const cleanup = () => {\r\n observer?.disconnect();\r\n observer = null;\r\n if (timer !== null) clearTimeout(timer);\r\n if (rafHandle !== null) cancelAnimationFrame(rafHandle);\r\n };\r\n\r\n let resolvePromise!: (value: WaitForElementResult) => void;\r\n const promise = new Promise<WaitForElementResult>((res) => {\r\n resolvePromise = res;\r\n });\r\n\r\n const settle = (result: WaitForElementResult) => {\r\n if (settled) return;\r\n settled = true;\r\n cleanup();\r\n resolvePromise(result);\r\n };\r\n\r\n const attempt = () => {\r\n if (settled) return;\r\n const element = resolve();\r\n if (element) {\r\n settle({ element, timedOut: false });\r\n }\r\n };\r\n\r\n // Debounce rapid bursts of mutations onto a single animation frame.\r\n const scheduleAttempt = () => {\r\n if (rafHandle !== null) return;\r\n rafHandle = requestAnimationFrame(() => {\r\n rafHandle = null;\r\n attempt();\r\n });\r\n };\r\n\r\n attempt();\r\n if (!settled) {\r\n observer = new MutationObserver(scheduleAttempt);\r\n observer.observe(root, { childList: true, subtree: true, attributes: true, characterData: true });\r\n timer = setTimeout(() => settle({ element: null, timedOut: true }), timeoutMs);\r\n }\r\n\r\n return {\r\n promise,\r\n cancel: () => settle({ element: null, timedOut: false }),\r\n };\r\n}\r\n","const LOCATION_CHANGE_EVENT = \"trail:locationchange\";\n\nlet patched = false;\n\n/**\n * Patches `history.pushState`/`replaceState` once per page so SPA route changes made\n * by any router (React Router, Vue Router, Angular Router, ...) surface as a single\n * DOM event alongside native `popstate`. Framework-agnostic by design (see spec #12).\n */\nfunction ensurePatched(): void {\n if (patched) return;\n patched = true;\n\n const originalPushState = history.pushState.bind(history);\n const originalReplaceState = history.replaceState.bind(history);\n\n history.pushState = function patchedPushState(...args: Parameters<History[\"pushState\"]>) {\n const result = originalPushState(...args);\n window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT));\n return result;\n };\n\n history.replaceState = function patchedReplaceState(...args: Parameters<History[\"replaceState\"]>) {\n const result = originalReplaceState(...args);\n window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT));\n return result;\n };\n\n window.addEventListener(\"popstate\", () => {\n window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT));\n });\n}\n\n/** Subscribes to same-page URL changes (pushState/replaceState/popstate). */\nexport function onLocationChange(listener: () => void): () => void {\n ensurePatched();\n window.addEventListener(LOCATION_CHANGE_EVENT, listener);\n return () => window.removeEventListener(LOCATION_CHANGE_EVENT, listener);\n}\n","import type { Guide, GuideStep, Target } from \"@trail-cli/guide-schema\";\nimport { GuideState } from \"./state.js\";\nimport { Overlay } from \"./overlay.js\";\nimport { resolveTarget } from \"./target-resolver.js\";\nimport { waitForElement } from \"./dom-watcher.js\";\nimport { onLocationChange } from \"./spa-router.js\";\nimport { saveCheckpoint, clearCheckpoint } from \"./session-storage.js\";\n\nconst DEFAULT_TARGET_TIMEOUT_MS = 10_000;\n\nexport interface EngineOptions {\n guide: Guide;\n release: string;\n startIndex: number;\n onExit?: () => void;\n}\n\nexport interface TrailHandle {\n next: () => void;\n back: () => void;\n exit: () => void;\n}\n\n/** Orchestrates step state, target resolution, the overlay, and SPA route changes. */\nexport class TrailEngine implements TrailHandle {\n private readonly guide: Guide;\n private readonly release: string;\n private readonly state: GuideState;\n private readonly overlay: Overlay;\n private readonly unsubscribeLocation: () => void;\n private readonly onExitCallback?: () => void;\n private cancelWait: (() => void) | null = null;\n private cancelStepCompletion: (() => void) | null = null;\n private currentStepComplete = false;\n private destroyed = false;\n\n constructor(options: EngineOptions) {\n this.guide = options.guide;\n this.release = options.release;\n this.state = new GuideState(options.guide, options.startIndex);\n this.onExitCallback = options.onExit;\n\n this.overlay = new Overlay({\n onNext: () => this.next(),\n onBack: () => this.back(),\n onExit: () => this.exit(),\n onRetry: () => this.activateCurrentStep(),\n });\n\n // A completed action may trigger navigation before the tester presses Next.\n this.unsubscribeLocation = onLocationChange(() => {\n if (!this.currentStepComplete) this.activateCurrentStep();\n });\n\n this.activateCurrentStep();\n }\n\n next(): void {\n if (this.destroyed || !this.currentStepComplete) return;\n this.cancelWait?.();\n if (this.state.isLast) {\n this.complete();\n return;\n }\n this.state.next();\n this.activateCurrentStep();\n }\n\n back(): void {\n if (this.destroyed) return;\n this.cancelWait?.();\n this.state.back();\n this.activateCurrentStep();\n }\n\n exit(): void {\n if (this.destroyed) return;\n clearCheckpoint();\n this.destroy();\n this.onExitCallback?.();\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cancelWait?.();\n this.cancelStepCompletion?.();\n this.unsubscribeLocation();\n this.overlay.destroy();\n }\n\n private persist(): void {\n saveCheckpoint({\n release: this.release,\n guideId: this.guide.id,\n stepIndex: this.state.currentIndex,\n stepId: this.state.currentStep.id,\n });\n }\n\n private activateCurrentStep(): void {\n if (this.destroyed) return;\n this.cancelWait?.();\n this.cancelStepCompletion?.();\n this.cancelStepCompletion = null;\n this.currentStepComplete = false;\n this.overlay.setFocusTarget(null);\n this.persist();\n\n const step = this.state.currentStep;\n\n if (step.action === \"navigate\") {\n this.handleNavigateStep(step);\n return;\n }\n\n const target: Target | undefined = \"target\" in step ? step.target : undefined;\n\n if (!target) {\n this.renderReady(null, step);\n return;\n }\n\n this.overlay.renderLocating({\n stepNumber: this.state.currentIndex + 1,\n totalSteps: this.state.total,\n title: this.guide.title,\n instruction: step.instruction,\n });\n\n const timeoutMs = step.action === \"wait\" ? step.timeoutMs ?? DEFAULT_TARGET_TIMEOUT_MS : DEFAULT_TARGET_TIMEOUT_MS;\n const { promise, cancel } = waitForElement(() => resolveTarget(target).element, { timeoutMs });\n this.cancelWait = cancel;\n\n promise.then((result) => {\n if (this.destroyed) return;\n if (result.timedOut || !result.element) {\n this.renderMissingTarget(step, target);\n return;\n }\n this.overlay.scrollToTarget(result.element);\n this.renderReady(result.element, step);\n });\n }\n\n private handleNavigateStep(step: Extract<GuideStep, { action: \"navigate\" }>): void {\n const destination = new URL(step.url, window.location.origin);\n if (window.location.pathname === destination.pathname) {\n this.renderReady(null, step);\n return;\n }\n\n // Persist the *next* step so a full page navigation resumes past this one.\n saveCheckpoint({\n release: this.release,\n guideId: this.guide.id,\n stepIndex: Math.min(this.state.currentIndex + 1, this.state.total - 1),\n stepId: this.guide.steps[Math.min(this.state.currentIndex + 1, this.state.total - 1)]!.id,\n });\n destination.searchParams.set(\"trail\", this.guide.id);\n destination.searchParams.set(\"release\", this.release);\n window.location.assign(destination.toString());\n }\n\n private renderReady(element: HTMLElement | null, step: GuideStep): void {\n this.overlay.setFocusTarget(element);\n if (element) {\n this.overlay.spotlight.attachTo(element);\n } else {\n this.overlay.spotlight.hide();\n }\n this.overlay.renderStep({\n stepNumber: this.state.currentIndex + 1,\n totalSteps: this.state.total,\n title: this.guide.title,\n instruction: step.instruction,\n canGoBack: !this.state.isFirst,\n canGoNext: this.watchStepCompletion(element, step),\n nextLabel: this.state.isLast ? \"Finish\" : \"Next\",\n });\n }\n\n private watchStepCompletion(element: HTMLElement | null, step: GuideStep): boolean {\n if (!element || step.action === \"verify\" || step.action === \"wait\" || step.action === \"navigate\") {\n this.currentStepComplete = true;\n return true;\n }\n\n const controller = new AbortController();\n this.cancelStepCompletion = () => controller.abort();\n const complete = () => {\n this.currentStepComplete = true;\n this.overlay.setNextEnabled(true);\n if (step.autoAdvance) this.next();\n };\n\n if (step.action === \"input\" || step.action === \"select\") {\n const isExpectedValue = () =>\n (element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) &&\n element.value === step.value;\n const updateCompletion = () => {\n if (isExpectedValue()) {\n complete();\n return;\n }\n this.currentStepComplete = false;\n this.overlay.setNextEnabled(false);\n };\n element.addEventListener(\"input\", updateCompletion, { signal: controller.signal });\n element.addEventListener(\"change\", updateCompletion, { signal: controller.signal });\n const initiallyComplete = isExpectedValue();\n this.currentStepComplete = initiallyComplete;\n if (initiallyComplete && step.autoAdvance) {\n queueMicrotask(() => {\n if (!controller.signal.aborted && !this.destroyed) complete();\n });\n }\n return initiallyComplete;\n }\n\n element.addEventListener(\"click\", complete, { once: true, signal: controller.signal });\n return false;\n }\n\n private renderMissingTarget(step: GuideStep, target: Target): void {\n const { attempts } = resolveTarget(target);\n const detail = attempts\n .map((attempt) => `${attempt.strategy}: ${attempt.detail} — ${attempt.found ? \"found\" : \"not found\"}`)\n .join(\" | \");\n this.overlay.renderError({\n title: \"Target Not Found\",\n message:\n `${step.instruction}\\n\\nThe application element could not be located. Possible causes: ` +\n \"wrong page, application still loading, UI changed, or the guide is outdated.\",\n detail,\n showRetry: true,\n });\n }\n\n private complete(): void {\n this.cancelWait?.();\n this.overlay.setFocusTarget(null);\n clearCheckpoint();\n this.overlay.renderComplete(this.guide.title, this.state.total, () => this.restart());\n }\n\n private restart(): void {\n const destination = new URL(this.guide.start.url, window.location.origin);\n destination.searchParams.set(\"trail\", this.guide.id);\n destination.searchParams.set(\"release\", this.release);\n\n if (window.location.href === destination.toString()) {\n this.state.reset();\n this.activateCurrentStep();\n return;\n }\n\n window.location.assign(destination.toString());\n }\n}\n","import { loadGuide } from \"./guide-loader.js\";\nimport { clearCheckpoint, loadCheckpoint } from \"./session-storage.js\";\nimport { TrailEngine, type TrailHandle } from \"./engine.js\";\nimport { Overlay } from \"./overlay.js\";\nimport { resolveCheckpointIndex } from \"./state.js\";\n\nexport type { TrailHandle } from \"./engine.js\";\nexport type { Guide, GuideStep, Target } from \"@trail-cli/guide-schema\";\n\nexport interface TrailInitOptions {\n /** Explicit URL to a guide document (JSON or YAML). Overrides URL-based auto-detection. */\n guideUrl?: string;\n /** Base path used to resolve `?trail=&release=` query params. Defaults to \"/guides\". */\n guideBaseUrl?: string;\n}\n\ninterface ResolvedGuideRequest {\n url: string;\n guideId: string;\n release: string;\n}\n\nexport function resolveGuideRequest(options: TrailInitOptions): ResolvedGuideRequest | null {\n if (options.guideUrl) {\n const params = new URLSearchParams(new URL(options.guideUrl, window.location.href).search);\n return {\n url: options.guideUrl,\n guideId: params.get(\"trail\") ?? \"unknown\",\n release: params.get(\"release\") ?? \"unknown\",\n };\n }\n\n const params = new URLSearchParams(window.location.search);\n const guideId = params.get(\"trail\");\n const release = params.get(\"release\");\n if (!guideId || !release) return null;\n\n const base = (options.guideBaseUrl ?? \"/guides\").replace(/\\/$/, \"\");\n return { url: `${base}/releases/${release}/${guideId}.json`, guideId, release };\n}\n\nfunction showStandaloneError(title: string, message: string, detail?: string): void {\n const overlay = new Overlay({\n onNext: () => {},\n onBack: () => {},\n onRetry: () => overlay.destroy(),\n onExit: () => overlay.destroy(),\n });\n overlay.renderError({ title, message, detail, showRetry: false });\n}\n\n/**\n * Entry point installed inside the application under test. No-ops (negligible\n * overhead, per spec #34) unless a guide has actually been requested via\n * `options.guideUrl` or the `?trail=&release=` query params.\n */\nasync function init(options: TrailInitOptions = {}): Promise<TrailHandle | null> {\n const request = resolveGuideRequest(options);\n if (!request) return null;\n\n const result = await loadGuide(request.url);\n\n if (!result.success && result.kind === \"not-found\") {\n showStandaloneError(\"Trail Guide Not Found\", `${request.guideId}\\nRelease ${request.release}`);\n return null;\n }\n\n if (!result.success && result.kind === \"network-error\") {\n showStandaloneError(\"Unable to Load Trail Guide\", \"Check your network connection and try again.\");\n return null;\n }\n\n if (!result.success && result.kind === \"server-error\") {\n showStandaloneError(\"Unable to Load Trail Guide\", \"The guide server returned an error. Try again later.\");\n return null;\n }\n\n if (!result.success) {\n const detail = result.issues?.map((issue) => `${issue.path}: ${issue.message}`).join(\" | \");\n showStandaloneError(\"Invalid Trail Guide\", `${request.guideId} failed validation.`, detail);\n return null;\n }\n\n const checkpoint = loadCheckpoint(request.release, result.guide.id);\n const checkpointIndex = resolveCheckpointIndex(result.guide, checkpoint);\n if (checkpoint && checkpointIndex === null) clearCheckpoint();\n const startIndex = checkpointIndex ?? 0;\n\n return new TrailEngine({\n guide: result.guide,\n release: request.release,\n startIndex,\n });\n}\n\nexport const Trail = { init };\n"],"mappings":"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","names":["params"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trail-cli/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ndivhomakhuvha/trail.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@trail-cli/guide-schema": "workspace:*"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"jsdom": "^24.1.3",
|
|
35
|
+
"tsup": "^8.2.4",
|
|
36
|
+
"typescript": "^5.5.4"
|
|
37
|
+
}
|
|
38
|
+
}
|