webdrive 1.0.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/LICENSE +21 -0
- package/README.md +620 -0
- package/dist/index.cjs +1426 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +267 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.js +1395 -0
- package/dist/index.js.map +1 -0
- package/dist/webdrive.css +310 -0
- package/package.json +55 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/EventEmitter.ts","../src/storage/StorageManager.ts","../src/dom/DOMUtils.ts","../src/dom/Overlay.ts","../src/dom/Popover.ts","../src/dom/Highlight.ts","../src/accessibility/AccessibilityManager.ts","../src/positioning/PositionEngine.ts","../src/core/TourController.ts","../src/core/WebDrive.ts"],"sourcesContent":["export { WebDrive } from \"./core/WebDrive\";\nexport { TourController } from \"./core/TourController\";\nexport { EventEmitter } from \"./core/EventEmitter\";\nexport { StorageManager } from \"./storage/StorageManager\";\nexport { calculatePopoverPosition } from \"./positioning/PositionEngine\";\n\nexport type {\n WebDriveOptions,\n WebDriveStep,\n WebDriveStorage,\n WebDriveEvents,\n Position,\n Alignment,\n MissingElementBehavior,\n PopoverPositionResult,\n CalculatePositionParams,\n} from \"./types\";\n\nimport { WebDrive } from \"./core/WebDrive\";\nexport default WebDrive;\n","import { WebDriveEvents } from \"../types\";\n\ntype AnyHandler = (data: unknown) => void;\n\nexport class EventEmitter {\n private events: Map<keyof WebDriveEvents, Set<AnyHandler>> = new Map();\n\n on<K extends keyof WebDriveEvents>(\n event: K,\n handler: (data: WebDriveEvents[K]) => void\n ): void {\n let handlers = this.events.get(event);\n if (!handlers) {\n handlers = new Set();\n this.events.set(event, handlers);\n }\n handlers.add(handler as AnyHandler);\n }\n\n off<K extends keyof WebDriveEvents>(\n event: K,\n handler: (data: WebDriveEvents[K]) => void\n ): void {\n const handlers = this.events.get(event);\n if (handlers) {\n handlers.delete(handler as AnyHandler);\n if (handlers.size === 0) {\n this.events.delete(event);\n }\n }\n }\n\n emit<K extends keyof WebDriveEvents>(\n event: K,\n ...args: WebDriveEvents[K] extends void ? [] : [WebDriveEvents[K]]\n ): void {\n const handlers = this.events.get(event);\n if (handlers) {\n const data = args[0];\n for (const handler of Array.from(handlers)) {\n try {\n handler(data);\n } catch (error) {\n console.error(`[WebDrive] Error in \"${String(event)}\" event handler:`, error);\n }\n }\n }\n }\n\n removeAllListeners(): void {\n this.events.clear();\n }\n}\n","import { WebDriveStorage } from \"../types\";\n\n/**\n * In-memory fallback storage when localStorage is unavailable or in SSR.\n */\nclass MemoryStorage implements WebDriveStorage {\n private memory = new Map<string, string>();\n\n getItem(key: string): string | null {\n return this.memory.get(key) ?? null;\n }\n\n setItem(key: string, value: string): void {\n this.memory.set(key, value);\n }\n\n removeItem(key: string): void {\n this.memory.delete(key);\n }\n\n clear(): void {\n this.memory.clear();\n }\n}\n\n/**\n * Default browser localStorage adapter with try/catch safeguard.\n */\nclass LocalStorageAdapter implements WebDriveStorage {\n private fallback = new MemoryStorage();\n\n private isAvailable(): boolean {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return false;\n }\n try {\n const testKey = \"__webdrive_storage_test__\";\n window.localStorage.setItem(testKey, \"1\");\n window.localStorage.removeItem(testKey);\n return true;\n } catch {\n return false;\n }\n }\n\n getItem(key: string): string | null {\n if (!this.isAvailable()) {\n return this.fallback.getItem(key);\n }\n try {\n return window.localStorage.getItem(key);\n } catch {\n return this.fallback.getItem(key);\n }\n }\n\n setItem(key: string, value: string): void {\n if (!this.isAvailable()) {\n this.fallback.setItem(key, value);\n return;\n }\n try {\n window.localStorage.setItem(key, value);\n } catch {\n this.fallback.setItem(key, value);\n }\n }\n\n removeItem(key: string): void {\n if (!this.isAvailable()) {\n this.fallback.removeItem(key);\n return;\n }\n try {\n window.localStorage.removeItem(key);\n } catch {\n this.fallback.removeItem(key);\n }\n }\n}\n\nexport class StorageManager {\n private storage: WebDriveStorage;\n private readonly prefix = \"webdrive:tour:\";\n\n constructor(customStorage?: WebDriveStorage) {\n this.storage = customStorage ?? new LocalStorageAdapter();\n }\n\n private getKey(id: string): string {\n return `${this.prefix}${id}`;\n }\n\n async isCompleted(id: string): Promise<boolean> {\n if (!id) return false;\n const value = await this.storage.getItem(this.getKey(id));\n return value === \"completed\" || value === \"true\";\n }\n\n async markCompleted(id: string): Promise<void> {\n if (!id) return;\n await this.storage.setItem(this.getKey(id), \"completed\");\n }\n\n async reset(id: string): Promise<void> {\n if (!id) return;\n await this.storage.removeItem(this.getKey(id));\n }\n\n async resetAll(): Promise<void> {\n if (typeof window !== \"undefined\" && window.localStorage) {\n try {\n const keysToRemove: string[] = [];\n for (let i = 0; i < window.localStorage.length; i++) {\n const key = window.localStorage.key(i);\n if (key && key.startsWith(this.prefix)) {\n keysToRemove.push(key);\n }\n }\n for (const key of keysToRemove) {\n window.localStorage.removeItem(key);\n }\n } catch {\n // Ignore localStorage access errors\n }\n }\n }\n}\n","/**\n * Resolves a target selector string or HTMLElement to an actual HTMLElement in the DOM.\n */\nexport function resolveElement(\n target: string | HTMLElement | null | undefined\n): HTMLElement | null {\n if (!target) return null;\n\n if (typeof target === \"string\") {\n if (typeof document === \"undefined\") return null;\n try {\n const el = document.querySelector<HTMLElement>(target);\n if (!el) {\n console.warn(`[WebDrive] Target element \"${target}\" was not found.`);\n return null;\n }\n return el;\n } catch (error) {\n console.warn(`[WebDrive] Invalid selector \"${target}\":`, error);\n return null;\n }\n }\n\n if (typeof HTMLElement !== \"undefined\" && target instanceof HTMLElement) {\n return target;\n }\n\n return null;\n}\n\n/**\n * Safely scrolls an element into view with center alignment.\n */\nexport function scrollIntoViewSafely(\n element: HTMLElement,\n smooth: boolean = true\n): void {\n if (!element || typeof element.scrollIntoView !== \"function\") return;\n\n try {\n element.scrollIntoView({\n behavior: smooth ? \"smooth\" : \"auto\",\n block: \"center\",\n inline: \"nearest\",\n });\n } catch {\n try {\n // Fallback for older browsers\n element.scrollIntoView(true);\n } catch {\n // Ignore scroll failures\n }\n }\n}\n\nexport interface BoundingBox {\n top: number;\n left: number;\n width: number;\n height: number;\n right: number;\n bottom: number;\n}\n\n/**\n * Calculates bounding rectangle for an element with padding applied.\n */\nexport function getElementBoundingBox(\n element: HTMLElement,\n padding: number = 0\n): BoundingBox {\n const rect = element.getBoundingClientRect();\n\n const top = rect.top - padding;\n const left = rect.left - padding;\n const width = rect.width + padding * 2;\n const height = rect.height + padding * 2;\n\n return {\n top,\n left,\n width,\n height,\n right: left + width,\n bottom: top + height,\n };\n}\n\n/**\n * Retrieves all focusable elements within a container.\n */\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n const selector = [\n 'a[href]:not([tabindex=\"-1\"])',\n 'button:not([disabled]):not([tabindex=\"-1\"])',\n 'textarea:not([disabled]):not([tabindex=\"-1\"])',\n 'input:not([disabled]):not([tabindex=\"-1\"])',\n 'select:not([disabled]):not([tabindex=\"-1\"])',\n '[tabindex]:not([tabindex=\"-1\"])',\n ].join(\", \");\n\n return Array.from(container.querySelectorAll<HTMLElement>(selector)).filter(\n (el) => el.offsetParent !== null || el.getClientRects().length > 0\n );\n}\n\n/**\n * Safely removes a node from the DOM.\n */\nexport function removeElement(el: Element | null | undefined): void {\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n}\n","import { HighlightRect } from \"./Highlight\";\nimport { removeElement } from \"./DOMUtils\";\n\nexport interface OverlayConfig {\n enabled?: boolean;\n opacity?: number;\n color?: string;\n zIndex?: number;\n animate?: boolean;\n allowClose?: boolean;\n onOverlayClick?: () => void;\n}\n\nexport class Overlay {\n private rootElement: HTMLElement | null = null;\n private cutoutRect: SVGRectElement | null = null;\n private stageElement: HTMLElement | null = null;\n private maskId: string;\n private config: OverlayConfig;\n\n constructor(config: OverlayConfig = {}) {\n this.config = {\n enabled: config.enabled ?? true,\n opacity: config.opacity ?? 0.6,\n color: config.color,\n zIndex: config.zIndex ?? 100000,\n animate: config.animate ?? true,\n allowClose: config.allowClose ?? true,\n onOverlayClick: config.onOverlayClick,\n };\n this.maskId = `webdrive-mask-${Math.random().toString(36).slice(2, 9)}`;\n }\n\n mount(): void {\n if (typeof document === \"undefined\") return;\n if (this.rootElement && this.rootElement.isConnected) return;\n\n // Create root container\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-webdrive-root\", \"\");\n root.className = \"webdrive-root\";\n root.style.setProperty(\"--webdrive-z-index\", String(this.config.zIndex));\n if (this.config.opacity !== undefined) {\n root.style.setProperty(\"--webdrive-overlay-opacity\", String(this.config.opacity));\n }\n if (this.config.color) {\n root.style.setProperty(\"--webdrive-overlay\", this.config.color);\n }\n\n // Create SVG overlay with cutout mask\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"data-webdrive-overlay\", \"\");\n svg.setAttribute(\"class\", \"webdrive-overlay\");\n svg.setAttribute(\"width\", \"100%\");\n svg.setAttribute(\"height\", \"100%\");\n if (!this.config.enabled) {\n svg.style.display = \"none\";\n }\n\n const defs = document.createElementNS(\"http://www.w3.org/2000/svg\", \"defs\");\n const mask = document.createElementNS(\"http://www.w3.org/2000/svg\", \"mask\");\n mask.setAttribute(\"id\", this.maskId);\n\n // Full opaque white background in mask (visible overlay)\n const maskBg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n maskBg.setAttribute(\"x\", \"0\");\n maskBg.setAttribute(\"y\", \"0\");\n maskBg.setAttribute(\"width\", \"100%\");\n maskBg.setAttribute(\"height\", \"100%\");\n maskBg.setAttribute(\"fill\", \"#ffffff\");\n\n // Transparent black cutout in mask (cutout hole)\n const cutout = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n cutout.setAttribute(\"data-webdrive-cutout\", \"\");\n cutout.setAttribute(\"class\", \"webdrive-cutout\");\n cutout.setAttribute(\"x\", \"0\");\n cutout.setAttribute(\"y\", \"0\");\n cutout.setAttribute(\"width\", \"0\");\n cutout.setAttribute(\"height\", \"0\");\n cutout.setAttribute(\"rx\", \"4\");\n cutout.setAttribute(\"ry\", \"4\");\n cutout.setAttribute(\"fill\", \"#000000\");\n\n mask.appendChild(maskBg);\n mask.appendChild(cutout);\n defs.appendChild(mask);\n svg.appendChild(defs);\n\n // Overlay rect that uses the mask\n const overlayRect = document.createElementNS(\n \"http://www.w3.org/2000/svg\",\n \"rect\"\n );\n overlayRect.setAttribute(\"x\", \"0\");\n overlayRect.setAttribute(\"y\", \"0\");\n overlayRect.setAttribute(\"width\", \"100%\");\n overlayRect.setAttribute(\"height\", \"100%\");\n overlayRect.setAttribute(\"fill\", \"currentColor\");\n overlayRect.setAttribute(\"mask\", `url(#${this.maskId})`);\n svg.appendChild(overlayRect);\n\n // Stage element (transparent boundary container over target)\n const stage = document.createElement(\"div\");\n stage.setAttribute(\"data-webdrive-stage\", \"\");\n stage.className = \"webdrive-stage\";\n\n // Overlay click listener\n if (this.config.allowClose && this.config.onOverlayClick) {\n svg.addEventListener(\"click\", (e) => {\n // Only trigger if clicked directly on overlay backdrop, not through the stage\n if (e.target === svg || e.target === overlayRect) {\n this.config.onOverlayClick?.();\n }\n });\n }\n\n root.appendChild(svg);\n root.appendChild(stage);\n document.body.appendChild(root);\n\n this.rootElement = root;\n this.cutoutRect = cutout;\n this.stageElement = stage;\n }\n\n update(rect: HighlightRect, animate: boolean = true): void {\n if (!this.cutoutRect || !this.stageElement) {\n this.mount();\n }\n\n if (this.cutoutRect && this.stageElement) {\n if (!animate || !this.config.animate) {\n this.cutoutRect.style.transition = \"none\";\n this.stageElement.style.transition = \"none\";\n } else {\n this.cutoutRect.style.transition = \"\";\n this.stageElement.style.transition = \"\";\n }\n\n this.cutoutRect.setAttribute(\"x\", String(rect.left));\n this.cutoutRect.setAttribute(\"y\", String(rect.top));\n this.cutoutRect.setAttribute(\"width\", String(Math.max(0, rect.width)));\n this.cutoutRect.setAttribute(\"height\", String(Math.max(0, rect.height)));\n this.cutoutRect.setAttribute(\"rx\", String(rect.radius));\n this.cutoutRect.setAttribute(\"ry\", String(rect.radius));\n\n this.stageElement.style.left = `${rect.left}px`;\n this.stageElement.style.top = `${rect.top}px`;\n this.stageElement.style.width = `${Math.max(0, rect.width)}px`;\n this.stageElement.style.height = `${Math.max(0, rect.height)}px`;\n this.stageElement.style.borderRadius = `${rect.radius}px`;\n }\n }\n\n getRootElement(): HTMLElement | null {\n if (!this.rootElement || !this.rootElement.isConnected) {\n this.mount();\n }\n return this.rootElement;\n }\n\n getStageElement(): HTMLElement | null {\n return this.stageElement;\n }\n\n destroy(): void {\n removeElement(this.rootElement);\n this.rootElement = null;\n this.cutoutRect = null;\n this.stageElement = null;\n }\n}\n","import { WebDriveStep, PopoverPositionResult } from \"../types\";\nimport { removeElement } from \"./DOMUtils\";\n\nexport interface PopoverCallbacks {\n onPrev: () => void;\n onNext: () => void;\n onClose: () => void;\n}\n\nexport interface PopoverConfig {\n allowClose?: boolean;\n showProgress?: boolean;\n showButtons?: boolean;\n nextButtonText?: string;\n previousButtonText?: string;\n doneButtonText?: string;\n closeButtonText?: string;\n renderProgress?: (current: number, total: number) => string;\n}\n\nexport class Popover {\n private element: HTMLElement | null = null;\n private headerEl: HTMLElement | null = null;\n private titleEl: HTMLElement | null = null;\n private closeBtn: HTMLButtonElement | null = null;\n private contentEl: HTMLElement | null = null;\n private footerEl: HTMLElement | null = null;\n private prevBtn: HTMLButtonElement | null = null;\n private nextBtn: HTMLButtonElement | null = null;\n private progressEl: HTMLElement | null = null;\n private arrowEl: HTMLElement | null = null;\n\n private callbacks: PopoverCallbacks;\n private config: PopoverConfig;\n\n constructor(callbacks: PopoverCallbacks, config: PopoverConfig = {}) {\n this.callbacks = callbacks;\n this.config = config;\n }\n\n mount(container: HTMLElement): void {\n if (this.element && this.element.isConnected) return;\n\n const popover = document.createElement(\"div\");\n popover.setAttribute(\"data-webdrive-popover\", \"\");\n popover.className = \"webdrive-popover\";\n popover.setAttribute(\"role\", \"dialog\");\n popover.setAttribute(\"aria-modal\", \"true\");\n popover.setAttribute(\"aria-labelledby\", \"webdrive-title\");\n popover.setAttribute(\"aria-describedby\", \"webdrive-description\");\n popover.setAttribute(\"tabindex\", \"-1\");\n\n // Header\n const header = document.createElement(\"div\");\n header.setAttribute(\"data-webdrive-header\", \"\");\n header.className = \"webdrive-header\";\n\n const title = document.createElement(\"h2\");\n title.setAttribute(\"data-webdrive-title\", \"\");\n title.id = \"webdrive-title\";\n title.className = \"webdrive-title\";\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.setAttribute(\"data-webdrive-close\", \"\");\n closeBtn.setAttribute(\"type\", \"button\");\n closeBtn.className = \"webdrive-close\";\n closeBtn.innerHTML = \"×\";\n closeBtn.setAttribute(\"aria-label\", this.config.closeButtonText || \"Close tour\");\n closeBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.callbacks.onClose();\n });\n\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n // Content\n const content = document.createElement(\"div\");\n content.setAttribute(\"data-webdrive-content\", \"\");\n content.id = \"webdrive-description\";\n content.className = \"webdrive-content\";\n\n // Footer\n const footer = document.createElement(\"div\");\n footer.setAttribute(\"data-webdrive-footer\", \"\");\n footer.className = \"webdrive-footer\";\n\n const prevBtn = document.createElement(\"button\");\n prevBtn.setAttribute(\"data-webdrive-prev\", \"\");\n prevBtn.setAttribute(\"type\", \"button\");\n prevBtn.className = \"webdrive-button webdrive-prev\";\n prevBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.callbacks.onPrev();\n });\n\n const progress = document.createElement(\"div\");\n progress.setAttribute(\"data-webdrive-progress\", \"\");\n progress.className = \"webdrive-progress\";\n\n const nextBtn = document.createElement(\"button\");\n nextBtn.setAttribute(\"data-webdrive-next\", \"\");\n nextBtn.setAttribute(\"type\", \"button\");\n nextBtn.className = \"webdrive-button webdrive-next\";\n nextBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.callbacks.onNext();\n });\n\n footer.appendChild(prevBtn);\n footer.appendChild(progress);\n footer.appendChild(nextBtn);\n\n // Arrow\n const arrow = document.createElement(\"div\");\n arrow.setAttribute(\"data-webdrive-arrow\", \"\");\n arrow.className = \"webdrive-arrow\";\n\n popover.appendChild(header);\n popover.appendChild(content);\n popover.appendChild(footer);\n popover.appendChild(arrow);\n\n container.appendChild(popover);\n\n this.element = popover;\n this.headerEl = header;\n this.titleEl = title;\n this.closeBtn = closeBtn;\n this.contentEl = content;\n this.footerEl = footer;\n this.prevBtn = prevBtn;\n this.nextBtn = nextBtn;\n this.progressEl = progress;\n this.arrowEl = arrow;\n }\n\n renderStep(\n step: WebDriveStep,\n stepIndex: number,\n totalSteps: number\n ): void {\n if (!this.element) return;\n\n // 1. Title\n if (this.titleEl) {\n if (step.title) {\n this.titleEl.textContent = step.title;\n this.titleEl.style.display = \"\";\n } else {\n this.titleEl.textContent = \"\";\n this.titleEl.style.display = \"none\";\n }\n }\n\n // 2. Close Button\n const showClose =\n step.showCloseButton !== undefined\n ? step.showCloseButton\n : this.config.allowClose !== false;\n\n if (this.closeBtn) {\n this.closeBtn.style.display = showClose ? \"\" : \"none\";\n const closeText =\n step.closeButtonText || this.config.closeButtonText || \"Close tour\";\n this.closeBtn.setAttribute(\"aria-label\", closeText);\n }\n\n // 3. Header visibility\n if (this.headerEl) {\n if (!step.title && !showClose) {\n this.headerEl.style.display = \"none\";\n } else {\n this.headerEl.style.display = \"\";\n }\n }\n\n // 4. Content (HTML or text)\n if (this.contentEl) {\n if (step.content) {\n this.contentEl.innerHTML = step.content;\n } else if (step.description) {\n this.contentEl.textContent = step.description;\n } else {\n this.contentEl.textContent = \"\";\n }\n }\n\n // 5. Progress Indicator\n const showProgress =\n this.config.showProgress !== false && totalSteps > 1;\n if (this.progressEl) {\n if (showProgress) {\n this.progressEl.style.display = \"\";\n if (this.config.renderProgress) {\n this.progressEl.textContent = this.config.renderProgress(\n stepIndex + 1,\n totalSteps\n );\n } else {\n this.progressEl.textContent = `${stepIndex + 1} / ${totalSteps}`;\n }\n } else {\n this.progressEl.style.display = \"none\";\n }\n }\n\n // 6. Previous Button\n const isFirstStep = stepIndex === 0;\n const showPrev =\n step.showPreviousButton !== undefined\n ? step.showPreviousButton\n : this.config.showButtons !== false;\n\n if (this.prevBtn) {\n if (!showPrev) {\n this.prevBtn.style.display = \"none\";\n } else {\n this.prevBtn.style.display = \"\";\n this.prevBtn.disabled = isFirstStep;\n this.prevBtn.textContent =\n step.previousButtonText ||\n this.config.previousButtonText ||\n \"Previous\";\n if (isFirstStep) {\n this.prevBtn.setAttribute(\"aria-disabled\", \"true\");\n } else {\n this.prevBtn.removeAttribute(\"aria-disabled\");\n }\n }\n }\n\n // 7. Next / Done Button\n const isLastStep = stepIndex === totalSteps - 1;\n const showNext =\n step.showNextButton !== undefined\n ? step.showNextButton\n : this.config.showButtons !== false;\n\n if (this.nextBtn) {\n if (!showNext) {\n this.nextBtn.style.display = \"none\";\n } else {\n this.nextBtn.style.display = \"\";\n if (isLastStep) {\n this.nextBtn.textContent =\n step.doneButtonText ||\n this.config.doneButtonText ||\n \"Done\";\n } else {\n this.nextBtn.textContent =\n step.nextButtonText ||\n this.config.nextButtonText ||\n \"Next\";\n }\n }\n }\n\n // 8. Footer visibility\n if (this.footerEl) {\n const showFooter =\n showPrev || showNext || showProgress;\n this.footerEl.style.display = showFooter ? \"\" : \"none\";\n }\n }\n\n applyPosition(pos: PopoverPositionResult, animate: boolean = true): void {\n if (!this.element) return;\n\n if (!animate) {\n this.element.style.transition = \"none\";\n } else {\n this.element.style.transition = \"\";\n }\n\n this.element.style.left = `${pos.left}px`;\n this.element.style.top = `${pos.top}px`;\n this.element.setAttribute(\"data-placement\", pos.placement);\n this.element.setAttribute(\"data-alignment\", pos.alignment);\n\n if (this.arrowEl) {\n this.arrowEl.setAttribute(\"data-arrow-placement\", pos.arrowPlacement || \"top\");\n if (pos.arrowLeft !== undefined) {\n this.arrowEl.style.left = `${pos.arrowLeft}px`;\n } else {\n this.arrowEl.style.left = \"\";\n }\n if (pos.arrowTop !== undefined) {\n this.arrowEl.style.top = `${pos.arrowTop}px`;\n } else {\n this.arrowEl.style.top = \"\";\n }\n }\n }\n\n getElement(): HTMLElement | null {\n return this.element;\n }\n\n getNextButton(): HTMLButtonElement | null {\n return this.nextBtn;\n }\n\n getDimensions(): { width: number; height: number } {\n if (!this.element) {\n return { width: 320, height: 180 };\n }\n const rect = this.element.getBoundingClientRect();\n return {\n width: rect.width || 320,\n height: rect.height || 180,\n };\n }\n\n destroy(): void {\n removeElement(this.element);\n this.element = null;\n this.headerEl = null;\n this.titleEl = null;\n this.closeBtn = null;\n this.contentEl = null;\n this.footerEl = null;\n this.prevBtn = null;\n this.nextBtn = null;\n this.progressEl = null;\n this.arrowEl = null;\n }\n}\n","import { BoundingBox, getElementBoundingBox } from \"./DOMUtils\";\n\nexport interface HighlightRect extends BoundingBox {\n radius: number;\n}\n\nexport class Highlight {\n private currentElement: HTMLElement | null = null;\n private padding: number = 0;\n private radius: number = 4;\n\n setTarget(element: HTMLElement, padding: number = 8, radius: number = 4): HighlightRect {\n this.currentElement = element;\n this.padding = padding;\n this.radius = radius;\n return this.getRect();\n }\n\n getRect(): HighlightRect {\n if (!this.currentElement || !this.currentElement.isConnected) {\n return {\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n right: 0,\n bottom: 0,\n radius: this.radius,\n };\n }\n\n const box = getElementBoundingBox(this.currentElement, this.padding);\n return {\n ...box,\n radius: this.radius,\n };\n }\n\n getElement(): HTMLElement | null {\n return this.currentElement;\n }\n\n clear(): void {\n this.currentElement = null;\n }\n}\n","import { getFocusableElements } from \"../dom/DOMUtils\";\n\nexport interface AccessibilityConfig {\n keyboardNavigation?: boolean;\n closeOnEscape?: boolean;\n}\n\nexport interface AccessibilityCallbacks {\n onNext: () => void;\n onPrev: () => void;\n onClose: () => void;\n}\n\nexport class AccessibilityManager {\n private previousActiveElement: HTMLElement | null = null;\n private keydownListener: ((e: KeyboardEvent) => void) | null = null;\n private config: AccessibilityConfig;\n private popoverElement: HTMLElement | null = null;\n\n constructor(config: AccessibilityConfig = {}) {\n this.config = {\n keyboardNavigation: config.keyboardNavigation ?? true,\n closeOnEscape: config.closeOnEscape ?? true,\n };\n }\n\n saveActiveElement(): void {\n if (\n typeof document !== \"undefined\" &&\n document.activeElement instanceof HTMLElement\n ) {\n this.previousActiveElement = document.activeElement;\n }\n }\n\n attach(\n popover: HTMLElement,\n callbacks: AccessibilityCallbacks\n ): void {\n this.popoverElement = popover;\n\n if (this.keydownListener) {\n this.detach();\n }\n\n this.keydownListener = (e: KeyboardEvent) => {\n // 1. Close on Escape\n if (\n (this.config.closeOnEscape !== false || this.config.keyboardNavigation) &&\n (e.key === \"Escape\" || e.key === \"Esc\")\n ) {\n e.preventDefault();\n callbacks.onClose();\n return;\n }\n\n // 2. Keyboard Navigation (ArrowRight / ArrowLeft)\n if (this.config.keyboardNavigation) {\n if (e.key === \"ArrowRight\") {\n e.preventDefault();\n callbacks.onNext();\n return;\n }\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n callbacks.onPrev();\n return;\n }\n }\n\n // 3. Tab focus trap inside popover\n if (e.key === \"Tab\" && this.popoverElement) {\n const focusables = getFocusableElements(this.popoverElement);\n if (focusables.length === 0) {\n e.preventDefault();\n return;\n }\n\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last?.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first?.focus();\n }\n }\n }\n };\n\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", this.keydownListener);\n }\n }\n\n focusPopover(preferredElement?: HTMLElement | null): void {\n if (preferredElement && typeof preferredElement.focus === \"function\") {\n preferredElement.focus();\n return;\n }\n\n if (this.popoverElement) {\n const focusables = getFocusableElements(this.popoverElement);\n if (focusables.length > 0 && focusables[0]) {\n focusables[0].focus();\n } else {\n this.popoverElement.focus();\n }\n }\n }\n\n restoreFocus(): void {\n if (\n this.previousActiveElement &&\n this.previousActiveElement.isConnected &&\n typeof this.previousActiveElement.focus === \"function\"\n ) {\n try {\n this.previousActiveElement.focus();\n } catch {\n // Ignore focus restore failure\n }\n }\n this.previousActiveElement = null;\n }\n\n detach(): void {\n if (typeof window !== \"undefined\" && this.keydownListener) {\n window.removeEventListener(\"keydown\", this.keydownListener);\n }\n this.keydownListener = null;\n this.popoverElement = null;\n }\n}\n","import {\n Position,\n Alignment,\n CalculatePositionParams,\n PopoverPositionResult,\n} from \"../types\";\n\n/**\n * Calculates raw coordinates for a given placement and alignment without collision adjustments.\n */\nfunction getRawPosition(\n target: { top: number; left: number; width: number; height: number },\n popover: { width: number; height: number },\n placement: Position,\n alignment: Alignment,\n offset: number\n): { top: number; left: number } {\n let top = 0;\n let left = 0;\n\n // Primary placement\n switch (placement) {\n case \"top\":\n top = target.top - popover.height - offset;\n break;\n case \"bottom\":\n top = target.top + target.height + offset;\n break;\n case \"left\":\n left = target.left - popover.width - offset;\n break;\n case \"right\":\n left = target.left + target.width + offset;\n break;\n }\n\n // Cross-axis alignment\n if (placement === \"top\" || placement === \"bottom\") {\n switch (alignment) {\n case \"start\":\n left = target.left;\n break;\n case \"center\":\n left = target.left + (target.width - popover.width) / 2;\n break;\n case \"end\":\n left = target.left + target.width - popover.width;\n break;\n }\n } else {\n // left or right\n switch (alignment) {\n case \"start\":\n top = target.top;\n break;\n case \"center\":\n top = target.top + (target.height - popover.height) / 2;\n break;\n case \"end\":\n top = target.top + target.height - popover.height;\n break;\n }\n }\n\n return { top, left };\n}\n\n/**\n * Checks if a candidate position fits within the viewport bounds.\n */\nfunction fitsInViewport(\n pos: { top: number; left: number },\n popover: { width: number; height: number },\n vw: number,\n vh: number,\n padding: number\n): boolean {\n return (\n pos.left >= padding &&\n pos.top >= padding &&\n pos.left + popover.width <= vw - padding &&\n pos.top + popover.height <= vh - padding\n );\n}\n\n/**\n * Calculates visible area score of a popover placed at pos inside viewport.\n */\nfunction getVisibleArea(\n pos: { top: number; left: number },\n popover: { width: number; height: number },\n vw: number,\n vh: number,\n padding: number\n): number {\n const visibleLeft = Math.max(padding, pos.left);\n const visibleTop = Math.max(padding, pos.top);\n const visibleRight = Math.min(vw - padding, pos.left + popover.width);\n const visibleBottom = Math.min(vh - padding, pos.top + popover.height);\n\n const visibleW = Math.max(0, visibleRight - visibleLeft);\n const visibleH = Math.max(0, visibleBottom - visibleTop);\n\n return visibleW * visibleH;\n}\n\n/**\n * Order of fallback placements to try when the requested placement overflows.\n */\nfunction getFallbackPlacements(preferred: Position): Position[] {\n switch (preferred) {\n case \"right\":\n return [\"right\", \"left\", \"bottom\", \"top\"];\n case \"left\":\n return [\"left\", \"right\", \"bottom\", \"top\"];\n case \"bottom\":\n return [\"bottom\", \"top\", \"right\", \"left\"];\n case \"top\":\n return [\"top\", \"bottom\", \"right\", \"left\"];\n }\n}\n\n/**\n * Computes optimal popover position, handles viewport collision, fallback, clamping,\n * and arrow positioning.\n */\nexport function calculatePopoverPosition(\n params: CalculatePositionParams\n): PopoverPositionResult {\n const {\n targetRect,\n popoverRect,\n placement: preferredPlacement = \"bottom\",\n alignment = \"center\",\n offset = 12,\n viewportPadding = 12,\n arrowSize = 8,\n } = params;\n\n const vw =\n params.viewportWidth ??\n (typeof window !== \"undefined\" ? window.innerWidth : 1024);\n const vh =\n params.viewportHeight ??\n (typeof window !== \"undefined\" ? window.innerHeight : 768);\n\n const placementsToTest = getFallbackPlacements(preferredPlacement);\n\n let chosenPlacement: Position = preferredPlacement;\n let chosenPos = getRawPosition(\n targetRect,\n popoverRect,\n preferredPlacement,\n alignment,\n offset\n );\n\n let foundFit = false;\n\n for (const p of placementsToTest) {\n const rawPos = getRawPosition(\n targetRect,\n popoverRect,\n p,\n alignment,\n offset\n );\n if (fitsInViewport(rawPos, popoverRect, vw, vh, viewportPadding)) {\n chosenPlacement = p;\n chosenPos = rawPos;\n foundFit = true;\n break;\n }\n }\n\n // If no placement completely fits without overflow, pick the placement with highest visible area\n if (!foundFit) {\n let bestPlacement = preferredPlacement;\n let bestScore = -1;\n let bestPos = chosenPos;\n\n for (const p of placementsToTest) {\n const rawPos = getRawPosition(\n targetRect,\n popoverRect,\n p,\n alignment,\n offset\n );\n const score = getVisibleArea(\n rawPos,\n popoverRect,\n vw,\n vh,\n viewportPadding\n );\n if (score > bestScore) {\n bestScore = score;\n bestPlacement = p;\n bestPos = rawPos;\n }\n }\n chosenPlacement = bestPlacement;\n chosenPos = bestPos;\n }\n\n // Clamp within viewport margins\n const minLeft = viewportPadding;\n const maxLeft = Math.max(viewportPadding, vw - popoverRect.width - viewportPadding);\n const minTop = viewportPadding;\n const maxTop = Math.max(viewportPadding, vh - popoverRect.height - viewportPadding);\n\n const clampedLeft = Math.max(minLeft, Math.min(chosenPos.left, maxLeft));\n const clampedTop = Math.max(minTop, Math.min(chosenPos.top, maxTop));\n\n // Compute arrow position relative to popover\n const targetCenterX = targetRect.left + targetRect.width / 2;\n const targetCenterY = targetRect.top + targetRect.height / 2;\n\n let arrowTop: number | undefined;\n let arrowLeft: number | undefined;\n let arrowPlacement: Position = \"top\";\n\n const minArrowOffset = arrowSize + 8;\n\n switch (chosenPlacement) {\n case \"top\":\n // Arrow is at the bottom of the popover, pointing down to target\n arrowPlacement = \"bottom\";\n arrowTop = popoverRect.height;\n arrowLeft = Math.max(\n minArrowOffset,\n Math.min(\n targetCenterX - clampedLeft,\n popoverRect.width - minArrowOffset\n )\n );\n break;\n case \"bottom\":\n // Arrow is at the top of the popover, pointing up to target\n arrowPlacement = \"top\";\n arrowTop = -arrowSize;\n arrowLeft = Math.max(\n minArrowOffset,\n Math.min(\n targetCenterX - clampedLeft,\n popoverRect.width - minArrowOffset\n )\n );\n break;\n case \"left\":\n // Arrow is at the right of the popover, pointing right to target\n arrowPlacement = \"right\";\n arrowLeft = popoverRect.width;\n arrowTop = Math.max(\n minArrowOffset,\n Math.min(\n targetCenterY - clampedTop,\n popoverRect.height - minArrowOffset\n )\n );\n break;\n case \"right\":\n // Arrow is at the left of the popover, pointing left to target\n arrowPlacement = \"left\";\n arrowLeft = -arrowSize;\n arrowTop = Math.max(\n minArrowOffset,\n Math.min(\n targetCenterY - clampedTop,\n popoverRect.height - minArrowOffset\n )\n );\n break;\n }\n\n return {\n top: Math.round(clampedTop),\n left: Math.round(clampedLeft),\n placement: chosenPlacement,\n alignment,\n arrowTop: arrowTop !== undefined ? Math.round(arrowTop) : undefined,\n arrowLeft: arrowLeft !== undefined ? Math.round(arrowLeft) : undefined,\n arrowPlacement,\n };\n}\n","import {\n WebDriveOptions,\n WebDriveStep,\n MissingElementBehavior,\n} from \"../types\";\nimport { EventEmitter } from \"./EventEmitter\";\nimport { StorageManager } from \"../storage/StorageManager\";\nimport { Overlay } from \"../dom/Overlay\";\nimport { Popover } from \"../dom/Popover\";\nimport { Highlight } from \"../dom/Highlight\";\nimport { AccessibilityManager } from \"../accessibility/AccessibilityManager\";\nimport {\n resolveElement,\n scrollIntoViewSafely,\n} from \"../dom/DOMUtils\";\nimport { calculatePopoverPosition } from \"../positioning/PositionEngine\";\n\nexport class TourController {\n private options: WebDriveOptions;\n private emitter: EventEmitter;\n private storage: StorageManager;\n private overlay: Overlay;\n private popover: Popover;\n private highlight: Highlight;\n private accessibility: AccessibilityManager;\n\n private currentStepIndex: number = -1;\n private tourActive: boolean = false;\n private destroyed: boolean = false;\n\n private resizeListener: (() => void) | null = null;\n private scrollListener: (() => void) | null = null;\n private rafId: number | null = null;\n\n private waitObserver: MutationObserver | null = null;\n private waitTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n options: WebDriveOptions,\n emitter: EventEmitter,\n storage: StorageManager\n ) {\n this.options = {\n animate: true,\n smoothScroll: true,\n overlay: true,\n overlayOpacity: 0.6,\n zIndex: 100000,\n stagePadding: 8,\n stageRadius: 6,\n keyboardNavigation: true,\n closeOnEscape: true,\n showButtons: true,\n showProgress: true,\n allowClose: true,\n missingElementBehavior: \"skip\",\n missingElementWaitTimeout: 3000,\n ...options,\n };\n\n this.emitter = emitter;\n this.storage = storage;\n this.highlight = new Highlight();\n\n this.overlay = new Overlay({\n enabled: this.options.overlay !== false,\n opacity: this.options.overlayOpacity,\n color: this.options.overlayColor,\n zIndex: this.options.zIndex,\n animate: this.options.animate,\n allowClose: this.options.allowClose,\n onOverlayClick: () => this.stop(),\n });\n\n this.popover = new Popover(\n {\n onPrev: () => this.previous(),\n onNext: () => this.next(),\n onClose: () => this.stop(),\n },\n {\n allowClose: this.options.allowClose,\n showProgress: this.options.showProgress,\n showButtons: this.options.showButtons,\n nextButtonText: this.options.nextButtonText,\n previousButtonText: this.options.previousButtonText,\n doneButtonText: this.options.doneButtonText,\n closeButtonText: this.options.closeButtonText,\n renderProgress: this.options.renderProgress,\n }\n );\n\n this.accessibility = new AccessibilityManager({\n keyboardNavigation: this.options.keyboardNavigation,\n closeOnEscape: this.options.closeOnEscape,\n });\n }\n\n async start(startIndex: number = 0): Promise<void> {\n if (this.destroyed) {\n console.warn(\"[WebDrive] Cannot start a destroyed tour instance.\");\n return;\n }\n\n if (this.tourActive) {\n return;\n }\n\n if (!this.options.steps || this.options.steps.length === 0) {\n console.warn(\"[WebDrive] Cannot start tour without steps.\");\n return;\n }\n\n // If remember option is enabled, check if tour was already completed\n if (this.options.remember && this.options.id) {\n const alreadyDone = await this.storage.isCompleted(this.options.id);\n if (alreadyDone) {\n return;\n }\n }\n\n this.tourActive = true;\n this.accessibility.saveActiveElement();\n\n // Mount overlay and popover\n this.overlay.mount();\n const rootEl = this.overlay.getRootElement();\n if (rootEl) {\n this.popover.mount(rootEl);\n }\n\n // Attach keyboard and accessibility manager\n const popoverEl = this.popover.getElement();\n if (popoverEl) {\n this.accessibility.attach(popoverEl, {\n onNext: () => this.next(),\n onPrev: () => this.previous(),\n onClose: () => this.stop(),\n });\n }\n\n // Setup responsive resize and scroll listeners\n this.setupViewportListeners();\n\n // Fire onStart\n this.emitter.emit(\"start\");\n this.options.onStart?.();\n\n // Jump to initial step\n await this.goTo(startIndex);\n }\n\n async stop(): Promise<void> {\n if (!this.tourActive) return;\n\n this.cleanupWaiting();\n await this.triggerStepLeave();\n\n this.tourActive = false;\n this.currentStepIndex = -1;\n this.highlight.clear();\n\n this.removeViewportListeners();\n this.accessibility.detach();\n this.accessibility.restoreFocus();\n\n this.overlay.destroy();\n this.popover.destroy();\n\n this.emitter.emit(\"close\");\n this.options.onClose?.();\n }\n\n async complete(): Promise<void> {\n if (!this.tourActive) return;\n\n this.cleanupWaiting();\n await this.triggerStepLeave();\n\n if (this.options.remember && this.options.id) {\n await this.storage.markCompleted(this.options.id);\n }\n\n this.tourActive = false;\n this.currentStepIndex = -1;\n this.highlight.clear();\n\n this.removeViewportListeners();\n this.accessibility.detach();\n this.accessibility.restoreFocus();\n\n this.overlay.destroy();\n this.popover.destroy();\n\n this.emitter.emit(\"complete\");\n this.options.onComplete?.();\n }\n\n async next(): Promise<void> {\n if (!this.tourActive) return;\n const nextIdx = this.currentStepIndex + 1;\n if (nextIdx >= this.options.steps.length) {\n await this.complete();\n } else {\n await this.goTo(nextIdx, \"forward\");\n }\n }\n\n async previous(): Promise<void> {\n if (!this.tourActive) return;\n const prevIdx = this.currentStepIndex - 1;\n if (prevIdx >= 0) {\n await this.goTo(prevIdx, \"backward\");\n }\n }\n\n async goTo(index: number, direction: \"forward\" | \"backward\" = \"forward\"): Promise<void> {\n if (!this.tourActive || this.destroyed) return;\n\n if (index < 0 || index >= this.options.steps.length) {\n return;\n }\n\n this.cleanupWaiting();\n\n const step = this.options.steps[index];\n if (!step) return;\n\n // Resolve target element\n let targetEl = resolveElement(step.element);\n\n if (!targetEl) {\n const behavior: MissingElementBehavior =\n this.options.missingElementBehavior ?? \"skip\";\n\n if (behavior === \"stop\") {\n console.warn(`[WebDrive] Stopping tour because element \"${String(step.element)}\" was not found.`);\n await this.stop();\n return;\n }\n\n if (behavior === \"wait\") {\n targetEl = await this.waitForElement(\n step.element,\n this.options.missingElementWaitTimeout ?? 3000\n );\n\n if (!targetEl) {\n console.warn(`[WebDrive] Timeout waiting for element \"${String(step.element)}\". Skipping.`);\n await this.advanceFromMissing(index, direction);\n return;\n }\n } else {\n // \"skip\"\n console.warn(`[WebDrive] Skipping step ${index} because element \"${String(step.element)}\" was not found.`);\n await this.advanceFromMissing(index, direction);\n return;\n }\n }\n\n // Leave previous step\n await this.triggerStepLeave();\n\n this.currentStepIndex = index;\n\n // Scroll into view if smoothScroll is enabled\n if (this.options.smoothScroll !== false) {\n scrollIntoViewSafely(targetEl, this.options.animate !== false);\n }\n\n // Compute highlight geometry\n const padding = step.padding ?? this.options.stagePadding ?? 8;\n const radius = this.options.stageRadius ?? 6;\n const highlightRect = this.highlight.setTarget(targetEl, padding, radius);\n\n // Update overlay cutout and stage\n this.overlay.update(highlightRect, this.options.animate !== false);\n\n // Render popover\n this.popover.renderStep(step, index, this.options.steps.length);\n\n // Position popover\n this.updatePosition();\n\n // Route focus to popover for accessibility\n const nextBtn = this.popover.getNextButton();\n this.accessibility.focusPopover(nextBtn);\n\n // Execute step onEnter hook\n try {\n await step.onEnter?.();\n } catch (error) {\n console.error(`[WebDrive] Error in step ${index} onEnter:`, error);\n }\n\n // Emit stepChange event\n this.emitter.emit(\"stepChange\", { step, index });\n this.options.onStepChange?.(step, index);\n }\n\n refresh(): void {\n if (!this.tourActive || this.currentStepIndex === -1) return;\n\n if (this.rafId !== null && typeof cancelAnimationFrame !== \"undefined\") {\n cancelAnimationFrame(this.rafId);\n }\n\n if (typeof requestAnimationFrame !== \"undefined\") {\n this.rafId = requestAnimationFrame(() => {\n this.syncUI();\n });\n } else {\n this.syncUI();\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.cleanupWaiting();\n this.removeViewportListeners();\n\n if (this.tourActive) {\n this.tourActive = false;\n this.accessibility.detach();\n this.accessibility.restoreFocus();\n this.overlay.destroy();\n this.popover.destroy();\n }\n\n this.emitter.emit(\"destroy\");\n this.options.onDestroy?.();\n this.emitter.removeAllListeners();\n }\n\n isActive(): boolean {\n return this.tourActive;\n }\n\n getCurrentStep(): WebDriveStep | null {\n if (!this.tourActive || this.currentStepIndex === -1) {\n return null;\n }\n return this.options.steps[this.currentStepIndex] ?? null;\n }\n\n getCurrentStepIndex(): number {\n return this.currentStepIndex;\n }\n\n private syncUI(): void {\n if (!this.tourActive || this.currentStepIndex === -1) return;\n\n const targetEl = this.highlight.getElement();\n if (!targetEl || !targetEl.isConnected) {\n return;\n }\n\n const highlightRect = this.highlight.getRect();\n this.overlay.update(highlightRect, false);\n this.updatePosition(false);\n }\n\n private updatePosition(animate: boolean = true): void {\n const step = this.getCurrentStep();\n if (!step) return;\n\n const highlightRect = this.highlight.getRect();\n const popoverDim = this.popover.getDimensions();\n\n const positionResult = calculatePopoverPosition({\n targetRect: highlightRect,\n popoverRect: popoverDim,\n placement: step.position ?? \"bottom\",\n alignment: step.align ?? \"center\",\n offset: step.offset ?? 12,\n });\n\n this.popover.applyPosition(positionResult, animate && (this.options.animate !== false));\n }\n\n private async triggerStepLeave(): Promise<void> {\n if (this.currentStepIndex >= 0 && this.currentStepIndex < this.options.steps.length) {\n const prevStep = this.options.steps[this.currentStepIndex];\n if (prevStep?.onLeave) {\n try {\n await prevStep.onLeave();\n } catch (error) {\n console.error(`[WebDrive] Error in step ${this.currentStepIndex} onLeave:`, error);\n }\n }\n }\n }\n\n private async advanceFromMissing(currentIndex: number, direction: \"forward\" | \"backward\"): Promise<void> {\n if (direction === \"forward\") {\n const nextIdx = currentIndex + 1;\n if (nextIdx >= this.options.steps.length) {\n await this.complete();\n } else {\n await this.goTo(nextIdx, \"forward\");\n }\n } else {\n const prevIdx = currentIndex - 1;\n if (prevIdx < 0) {\n await this.stop();\n } else {\n await this.goTo(prevIdx, \"backward\");\n }\n }\n }\n\n private waitForElement(\n target: string | HTMLElement,\n timeoutMs: number\n ): Promise<HTMLElement | null> {\n return new Promise((resolve) => {\n const existing = resolveElement(target);\n if (existing) {\n resolve(existing);\n return;\n }\n\n if (typeof MutationObserver === \"undefined\" || typeof document === \"undefined\") {\n resolve(null);\n return;\n }\n\n this.waitObserver = new MutationObserver(() => {\n const found = resolveElement(target);\n if (found) {\n this.cleanupWaiting();\n resolve(found);\n }\n });\n\n this.waitObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n this.waitTimeoutId = setTimeout(() => {\n this.cleanupWaiting();\n resolve(resolveElement(target));\n }, timeoutMs);\n });\n }\n\n private cleanupWaiting(): void {\n if (this.waitObserver) {\n this.waitObserver.disconnect();\n this.waitObserver = null;\n }\n if (this.waitTimeoutId !== null) {\n clearTimeout(this.waitTimeoutId);\n this.waitTimeoutId = null;\n }\n }\n\n private setupViewportListeners(): void {\n if (typeof window === \"undefined\") return;\n\n this.resizeListener = () => this.refresh();\n this.scrollListener = () => this.refresh();\n\n window.addEventListener(\"resize\", this.resizeListener, { passive: true });\n window.addEventListener(\"scroll\", this.scrollListener, { passive: true, capture: true });\n }\n\n private removeViewportListeners(): void {\n if (typeof window === \"undefined\") return;\n\n if (this.resizeListener) {\n window.removeEventListener(\"resize\", this.resizeListener);\n this.resizeListener = null;\n }\n\n if (this.scrollListener) {\n window.removeEventListener(\"scroll\", this.scrollListener, true);\n this.scrollListener = null;\n }\n\n if (this.rafId !== null && typeof cancelAnimationFrame !== \"undefined\") {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n }\n}\n","import {\n WebDriveOptions,\n WebDriveStep,\n WebDriveEvents,\n} from \"../types\";\nimport { EventEmitter } from \"./EventEmitter\";\nimport { StorageManager } from \"../storage/StorageManager\";\nimport { TourController } from \"./TourController\";\n\nexport class WebDrive {\n private options: WebDriveOptions;\n private emitter: EventEmitter;\n private storage: StorageManager;\n private controller: TourController | null = null;\n\n constructor(options: WebDriveOptions) {\n this.options = { ...options };\n this.emitter = new EventEmitter();\n this.storage = new StorageManager(this.options.storage);\n\n // Only initialize DOM controller if running in a browser environment\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n this.controller = new TourController(\n this.options,\n this.emitter,\n this.storage\n );\n\n if (this.options.autoStart) {\n // Auto-start asynchronously on the next event loop tick\n setTimeout(() => {\n this.start();\n }, 0);\n }\n }\n }\n\n private ensureController(): TourController | null {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return null;\n }\n if (!this.controller) {\n this.controller = new TourController(\n this.options,\n this.emitter,\n this.storage\n );\n }\n return this.controller;\n }\n\n async start(startIndex: number = 0): Promise<void> {\n const ctrl = this.ensureController();\n if (ctrl) {\n await ctrl.start(startIndex);\n }\n }\n\n async stop(): Promise<void> {\n const ctrl = this.ensureController();\n if (ctrl) {\n await ctrl.stop();\n }\n }\n\n async next(): Promise<void> {\n const ctrl = this.ensureController();\n if (ctrl) {\n await ctrl.next();\n }\n }\n\n async previous(): Promise<void> {\n const ctrl = this.ensureController();\n if (ctrl) {\n await ctrl.previous();\n }\n }\n\n async goTo(index: number): Promise<void> {\n const ctrl = this.ensureController();\n if (ctrl) {\n await ctrl.goTo(index);\n }\n }\n\n refresh(): void {\n const ctrl = this.ensureController();\n if (ctrl) {\n ctrl.refresh();\n }\n }\n\n destroy(): void {\n if (this.controller) {\n this.controller.destroy();\n this.controller = null;\n }\n }\n\n isActive(): boolean {\n return this.controller ? this.controller.isActive() : false;\n }\n\n getCurrentStep(): WebDriveStep | null {\n return this.controller ? this.controller.getCurrentStep() : null;\n }\n\n getCurrentStepIndex(): number {\n return this.controller ? this.controller.getCurrentStepIndex() : -1;\n }\n\n async hasCompleted(): Promise<boolean> {\n if (!this.options.id) return false;\n return this.storage.isCompleted(this.options.id);\n }\n\n async reset(): Promise<void> {\n if (!this.options.id) return;\n await this.storage.reset(this.options.id);\n }\n\n async resetAll(): Promise<void> {\n await this.storage.resetAll();\n }\n\n on<K extends keyof WebDriveEvents>(\n event: K,\n callback: (data: WebDriveEvents[K]) => void\n ): this {\n this.emitter.on(event, callback);\n return this;\n }\n\n off<K extends keyof WebDriveEvents>(\n event: K,\n callback: (data: WebDriveEvents[K]) => void\n ): this {\n this.emitter.off(event, callback);\n return this;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placement options for the popover relative to the target element.
|
|
3
|
+
*/
|
|
4
|
+
type Position = "top" | "right" | "bottom" | "left";
|
|
5
|
+
/**
|
|
6
|
+
* Alignment of the popover along the target element's axis.
|
|
7
|
+
*/
|
|
8
|
+
type Alignment = "start" | "center" | "end";
|
|
9
|
+
/**
|
|
10
|
+
* Strategy to use when a target element is not immediately present in the DOM.
|
|
11
|
+
* - "skip": skips the step and advances to the next available step.
|
|
12
|
+
* - "stop": halts the tour safely.
|
|
13
|
+
* - "wait": observes DOM mutations until the element appears or timeout expires.
|
|
14
|
+
*/
|
|
15
|
+
type MissingElementBehavior = "skip" | "stop" | "wait";
|
|
16
|
+
/**
|
|
17
|
+
* Step configuration interface for WebDrive.
|
|
18
|
+
*/
|
|
19
|
+
interface WebDriveStep {
|
|
20
|
+
/** Target element selector or DOM HTMLElement */
|
|
21
|
+
element: string | HTMLElement;
|
|
22
|
+
/** Title displayed in the popover header */
|
|
23
|
+
title?: string;
|
|
24
|
+
/** Plain text description rendered inside the popover content */
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Optional HTML content for rich formatting */
|
|
27
|
+
content?: string;
|
|
28
|
+
/** Preferred popover position relative to target */
|
|
29
|
+
position?: Position;
|
|
30
|
+
/** Popover alignment relative to target */
|
|
31
|
+
align?: Alignment;
|
|
32
|
+
/** Padding around the highlighted element in pixels */
|
|
33
|
+
padding?: number;
|
|
34
|
+
/** Distance between the popover and the highlighted target in pixels */
|
|
35
|
+
offset?: number;
|
|
36
|
+
/** Whether to show the Next / Finish button on this step */
|
|
37
|
+
showNextButton?: boolean;
|
|
38
|
+
/** Whether to show the Previous button on this step */
|
|
39
|
+
showPreviousButton?: boolean;
|
|
40
|
+
/** Whether to show the Close button on this step */
|
|
41
|
+
showCloseButton?: boolean;
|
|
42
|
+
/** Custom text for Next button on this step */
|
|
43
|
+
nextButtonText?: string;
|
|
44
|
+
/** Custom text for Previous button on this step */
|
|
45
|
+
previousButtonText?: string;
|
|
46
|
+
/** Custom text for Done/Finish button on this step */
|
|
47
|
+
doneButtonText?: string;
|
|
48
|
+
/** Custom text for Close button on this step */
|
|
49
|
+
closeButtonText?: string;
|
|
50
|
+
/** Callback invoked when entering this step */
|
|
51
|
+
onEnter?: () => void | Promise<void>;
|
|
52
|
+
/** Callback invoked when leaving this step */
|
|
53
|
+
onLeave?: () => void | Promise<void>;
|
|
54
|
+
/** Allows future extensibility without breaking the public API */
|
|
55
|
+
[key: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Custom storage adapter interface for tour completion persistence.
|
|
59
|
+
*/
|
|
60
|
+
interface WebDriveStorage {
|
|
61
|
+
getItem: (key: string) => string | null | Promise<string | null>;
|
|
62
|
+
setItem: (key: string, value: string) => void | Promise<void>;
|
|
63
|
+
removeItem: (key: string) => void | Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Global configuration options for WebDrive.
|
|
67
|
+
*/
|
|
68
|
+
interface WebDriveOptions {
|
|
69
|
+
/** Unique ID for the tour (used for storage persistence) */
|
|
70
|
+
id?: string;
|
|
71
|
+
/** Sequence of tour steps */
|
|
72
|
+
steps: WebDriveStep[];
|
|
73
|
+
/** Automatically start the tour upon instantiation if not already completed */
|
|
74
|
+
autoStart?: boolean;
|
|
75
|
+
/** Show step counter progress indicator (e.g., "2 / 5") */
|
|
76
|
+
showProgress?: boolean;
|
|
77
|
+
/** Allow user to close the tour via close button or backdrop click */
|
|
78
|
+
allowClose?: boolean;
|
|
79
|
+
/** Animate transitions between steps */
|
|
80
|
+
animate?: boolean;
|
|
81
|
+
/** Smoothly scroll target elements into view */
|
|
82
|
+
smoothScroll?: boolean;
|
|
83
|
+
/** Display darkened backdrop overlay */
|
|
84
|
+
overlay?: boolean;
|
|
85
|
+
/** Opacity of the backdrop overlay (0.0 to 1.0) */
|
|
86
|
+
overlayOpacity?: number;
|
|
87
|
+
/** Color of the backdrop overlay (CSS color string) */
|
|
88
|
+
overlayColor?: string;
|
|
89
|
+
/** Custom base z-index for the tour overlay and popover */
|
|
90
|
+
zIndex?: number;
|
|
91
|
+
/** Default padding around highlighted elements in pixels */
|
|
92
|
+
stagePadding?: number;
|
|
93
|
+
/** Border radius for the highlighted cutout area in pixels */
|
|
94
|
+
stageRadius?: number;
|
|
95
|
+
/** Enable keyboard navigation (ArrowRight, ArrowLeft, Escape) */
|
|
96
|
+
keyboardNavigation?: boolean;
|
|
97
|
+
/** Close tour when pressing Escape key */
|
|
98
|
+
closeOnEscape?: boolean;
|
|
99
|
+
/** Show navigation buttons in popover footer */
|
|
100
|
+
showButtons?: boolean;
|
|
101
|
+
/** Text for Next button */
|
|
102
|
+
nextButtonText?: string;
|
|
103
|
+
/** Text for Previous button */
|
|
104
|
+
previousButtonText?: string;
|
|
105
|
+
/** Text for Done/Finish button */
|
|
106
|
+
doneButtonText?: string;
|
|
107
|
+
/** Text for Close button */
|
|
108
|
+
closeButtonText?: string;
|
|
109
|
+
/** Persist completed state in storage so tour doesn't repeat */
|
|
110
|
+
remember?: boolean;
|
|
111
|
+
/** Custom storage provider (defaults to window.localStorage with memory fallback) */
|
|
112
|
+
storage?: WebDriveStorage;
|
|
113
|
+
/** Behavior when a target element is not found */
|
|
114
|
+
missingElementBehavior?: MissingElementBehavior;
|
|
115
|
+
/** Maximum time in milliseconds to wait for a missing element if behavior is "wait" */
|
|
116
|
+
missingElementWaitTimeout?: number;
|
|
117
|
+
/** Custom renderer for progress text */
|
|
118
|
+
renderProgress?: (current: number, total: number) => string;
|
|
119
|
+
/** Callback invoked when the tour starts */
|
|
120
|
+
onStart?: () => void;
|
|
121
|
+
/** Callback invoked when moving to a new step */
|
|
122
|
+
onStepChange?: (step: WebDriveStep, index: number) => void;
|
|
123
|
+
/** Callback invoked when the tour completes the final step */
|
|
124
|
+
onComplete?: () => void;
|
|
125
|
+
/** Callback invoked when the tour is closed before completion or via close button */
|
|
126
|
+
onClose?: () => void;
|
|
127
|
+
/** Callback invoked when the tour is destroyed */
|
|
128
|
+
onDestroy?: () => void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Event map for strongly typed WebDrive event emitter.
|
|
132
|
+
*/
|
|
133
|
+
interface WebDriveEvents {
|
|
134
|
+
start: void;
|
|
135
|
+
stepChange: {
|
|
136
|
+
step: WebDriveStep;
|
|
137
|
+
index: number;
|
|
138
|
+
};
|
|
139
|
+
complete: void;
|
|
140
|
+
close: void;
|
|
141
|
+
destroy: void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Result returned by the positioning calculation engine.
|
|
145
|
+
*/
|
|
146
|
+
interface PopoverPositionResult {
|
|
147
|
+
top: number;
|
|
148
|
+
left: number;
|
|
149
|
+
placement: Position;
|
|
150
|
+
alignment: Alignment;
|
|
151
|
+
arrowTop?: number;
|
|
152
|
+
arrowLeft?: number;
|
|
153
|
+
arrowPlacement?: Position;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Parameters for the popover positioning calculation.
|
|
157
|
+
*/
|
|
158
|
+
interface CalculatePositionParams {
|
|
159
|
+
targetRect: {
|
|
160
|
+
top: number;
|
|
161
|
+
left: number;
|
|
162
|
+
width: number;
|
|
163
|
+
height: number;
|
|
164
|
+
right?: number;
|
|
165
|
+
bottom?: number;
|
|
166
|
+
};
|
|
167
|
+
popoverRect: {
|
|
168
|
+
width: number;
|
|
169
|
+
height: number;
|
|
170
|
+
};
|
|
171
|
+
placement?: Position;
|
|
172
|
+
alignment?: Alignment;
|
|
173
|
+
offset?: number;
|
|
174
|
+
viewportPadding?: number;
|
|
175
|
+
arrowSize?: number;
|
|
176
|
+
viewportWidth?: number;
|
|
177
|
+
viewportHeight?: number;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
declare class WebDrive {
|
|
181
|
+
private options;
|
|
182
|
+
private emitter;
|
|
183
|
+
private storage;
|
|
184
|
+
private controller;
|
|
185
|
+
constructor(options: WebDriveOptions);
|
|
186
|
+
private ensureController;
|
|
187
|
+
start(startIndex?: number): Promise<void>;
|
|
188
|
+
stop(): Promise<void>;
|
|
189
|
+
next(): Promise<void>;
|
|
190
|
+
previous(): Promise<void>;
|
|
191
|
+
goTo(index: number): Promise<void>;
|
|
192
|
+
refresh(): void;
|
|
193
|
+
destroy(): void;
|
|
194
|
+
isActive(): boolean;
|
|
195
|
+
getCurrentStep(): WebDriveStep | null;
|
|
196
|
+
getCurrentStepIndex(): number;
|
|
197
|
+
hasCompleted(): Promise<boolean>;
|
|
198
|
+
reset(): Promise<void>;
|
|
199
|
+
resetAll(): Promise<void>;
|
|
200
|
+
on<K extends keyof WebDriveEvents>(event: K, callback: (data: WebDriveEvents[K]) => void): this;
|
|
201
|
+
off<K extends keyof WebDriveEvents>(event: K, callback: (data: WebDriveEvents[K]) => void): this;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
declare class EventEmitter {
|
|
205
|
+
private events;
|
|
206
|
+
on<K extends keyof WebDriveEvents>(event: K, handler: (data: WebDriveEvents[K]) => void): void;
|
|
207
|
+
off<K extends keyof WebDriveEvents>(event: K, handler: (data: WebDriveEvents[K]) => void): void;
|
|
208
|
+
emit<K extends keyof WebDriveEvents>(event: K, ...args: WebDriveEvents[K] extends void ? [] : [WebDriveEvents[K]]): void;
|
|
209
|
+
removeAllListeners(): void;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
declare class StorageManager {
|
|
213
|
+
private storage;
|
|
214
|
+
private readonly prefix;
|
|
215
|
+
constructor(customStorage?: WebDriveStorage);
|
|
216
|
+
private getKey;
|
|
217
|
+
isCompleted(id: string): Promise<boolean>;
|
|
218
|
+
markCompleted(id: string): Promise<void>;
|
|
219
|
+
reset(id: string): Promise<void>;
|
|
220
|
+
resetAll(): Promise<void>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
declare class TourController {
|
|
224
|
+
private options;
|
|
225
|
+
private emitter;
|
|
226
|
+
private storage;
|
|
227
|
+
private overlay;
|
|
228
|
+
private popover;
|
|
229
|
+
private highlight;
|
|
230
|
+
private accessibility;
|
|
231
|
+
private currentStepIndex;
|
|
232
|
+
private tourActive;
|
|
233
|
+
private destroyed;
|
|
234
|
+
private resizeListener;
|
|
235
|
+
private scrollListener;
|
|
236
|
+
private rafId;
|
|
237
|
+
private waitObserver;
|
|
238
|
+
private waitTimeoutId;
|
|
239
|
+
constructor(options: WebDriveOptions, emitter: EventEmitter, storage: StorageManager);
|
|
240
|
+
start(startIndex?: number): Promise<void>;
|
|
241
|
+
stop(): Promise<void>;
|
|
242
|
+
complete(): Promise<void>;
|
|
243
|
+
next(): Promise<void>;
|
|
244
|
+
previous(): Promise<void>;
|
|
245
|
+
goTo(index: number, direction?: "forward" | "backward"): Promise<void>;
|
|
246
|
+
refresh(): void;
|
|
247
|
+
destroy(): void;
|
|
248
|
+
isActive(): boolean;
|
|
249
|
+
getCurrentStep(): WebDriveStep | null;
|
|
250
|
+
getCurrentStepIndex(): number;
|
|
251
|
+
private syncUI;
|
|
252
|
+
private updatePosition;
|
|
253
|
+
private triggerStepLeave;
|
|
254
|
+
private advanceFromMissing;
|
|
255
|
+
private waitForElement;
|
|
256
|
+
private cleanupWaiting;
|
|
257
|
+
private setupViewportListeners;
|
|
258
|
+
private removeViewportListeners;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Computes optimal popover position, handles viewport collision, fallback, clamping,
|
|
263
|
+
* and arrow positioning.
|
|
264
|
+
*/
|
|
265
|
+
declare function calculatePopoverPosition(params: CalculatePositionParams): PopoverPositionResult;
|
|
266
|
+
|
|
267
|
+
export { type Alignment, type CalculatePositionParams, EventEmitter, type MissingElementBehavior, type PopoverPositionResult, type Position, StorageManager, TourController, WebDrive, type WebDriveEvents, type WebDriveOptions, type WebDriveStep, type WebDriveStorage, calculatePopoverPosition, WebDrive as default };
|