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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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","../src/index.ts"],"sourcesContent":["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 = \"&times;\";\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","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"],"mappings":";AAIO,IAAM,eAAN,MAAmB;AAAA,EAAnB;AACL,SAAQ,SAAqD,oBAAI,IAAI;AAAA;AAAA,EAErE,GACE,OACA,SACM;AACN,QAAI,WAAW,KAAK,OAAO,IAAI,KAAK;AACpC,QAAI,CAAC,UAAU;AACb,iBAAW,oBAAI,IAAI;AACnB,WAAK,OAAO,IAAI,OAAO,QAAQ;AAAA,IACjC;AACA,aAAS,IAAI,OAAqB;AAAA,EACpC;AAAA,EAEA,IACE,OACA,SACM;AACN,UAAM,WAAW,KAAK,OAAO,IAAI,KAAK;AACtC,QAAI,UAAU;AACZ,eAAS,OAAO,OAAqB;AACrC,UAAI,SAAS,SAAS,GAAG;AACvB,aAAK,OAAO,OAAO,KAAK;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KACE,UACG,MACG;AACN,UAAM,WAAW,KAAK,OAAO,IAAI,KAAK;AACtC,QAAI,UAAU;AACZ,YAAM,OAAO,KAAK,CAAC;AACnB,iBAAW,WAAW,MAAM,KAAK,QAAQ,GAAG;AAC1C,YAAI;AACF,kBAAQ,IAAI;AAAA,QACd,SAAS,OAAO;AACd,kBAAQ,MAAM,wBAAwB,OAAO,KAAK,CAAC,oBAAoB,KAAK;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,qBAA2B;AACzB,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;;;AC/CA,IAAM,gBAAN,MAA+C;AAAA,EAA/C;AACE,SAAQ,SAAS,oBAAI,IAAoB;AAAA;AAAA,EAEzC,QAAQ,KAA4B;AAClC,WAAO,KAAK,OAAO,IAAI,GAAG,KAAK;AAAA,EACjC;AAAA,EAEA,QAAQ,KAAa,OAAqB;AACxC,SAAK,OAAO,IAAI,KAAK,KAAK;AAAA,EAC5B;AAAA,EAEA,WAAW,KAAmB;AAC5B,SAAK,OAAO,OAAO,GAAG;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;AAKA,IAAM,sBAAN,MAAqD;AAAA,EAArD;AACE,SAAQ,WAAW,IAAI,cAAc;AAAA;AAAA,EAE7B,cAAuB;AAC7B,QAAI,OAAO,WAAW,eAAe,CAAC,OAAO,cAAc;AACzD,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,UAAU;AAChB,aAAO,aAAa,QAAQ,SAAS,GAAG;AACxC,aAAO,aAAa,WAAW,OAAO;AACtC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,QAAQ,KAA4B;AAClC,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,aAAO,KAAK,SAAS,QAAQ,GAAG;AAAA,IAClC;AACA,QAAI;AACF,aAAO,OAAO,aAAa,QAAQ,GAAG;AAAA,IACxC,QAAQ;AACN,aAAO,KAAK,SAAS,QAAQ,GAAG;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,QAAQ,KAAa,OAAqB;AACxC,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,WAAK,SAAS,QAAQ,KAAK,KAAK;AAChC;AAAA,IACF;AACA,QAAI;AACF,aAAO,aAAa,QAAQ,KAAK,KAAK;AAAA,IACxC,QAAQ;AACN,WAAK,SAAS,QAAQ,KAAK,KAAK;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,WAAW,KAAmB;AAC5B,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,WAAK,SAAS,WAAW,GAAG;AAC5B;AAAA,IACF;AACA,QAAI;AACF,aAAO,aAAa,WAAW,GAAG;AAAA,IACpC,QAAQ;AACN,WAAK,SAAS,WAAW,GAAG;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,eAAiC;AAF7C,SAAiB,SAAS;AAGxB,SAAK,UAAU,iBAAiB,IAAI,oBAAoB;AAAA,EAC1D;AAAA,EAEQ,OAAO,IAAoB;AACjC,WAAO,GAAG,KAAK,MAAM,GAAG,EAAE;AAAA,EAC5B;AAAA,EAEA,MAAM,YAAY,IAA8B;AAC9C,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,QAAQ,MAAM,KAAK,QAAQ,QAAQ,KAAK,OAAO,EAAE,CAAC;AACxD,WAAO,UAAU,eAAe,UAAU;AAAA,EAC5C;AAAA,EAEA,MAAM,cAAc,IAA2B;AAC7C,QAAI,CAAC,GAAI;AACT,UAAM,KAAK,QAAQ,QAAQ,KAAK,OAAO,EAAE,GAAG,WAAW;AAAA,EACzD;AAAA,EAEA,MAAM,MAAM,IAA2B;AACrC,QAAI,CAAC,GAAI;AACT,UAAM,KAAK,QAAQ,WAAW,KAAK,OAAO,EAAE,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAM,WAA0B;AAC9B,QAAI,OAAO,WAAW,eAAe,OAAO,cAAc;AACxD,UAAI;AACF,cAAM,eAAyB,CAAC;AAChC,iBAAS,IAAI,GAAG,IAAI,OAAO,aAAa,QAAQ,KAAK;AACnD,gBAAM,MAAM,OAAO,aAAa,IAAI,CAAC;AACrC,cAAI,OAAO,IAAI,WAAW,KAAK,MAAM,GAAG;AACtC,yBAAa,KAAK,GAAG;AAAA,UACvB;AAAA,QACF;AACA,mBAAW,OAAO,cAAc;AAC9B,iBAAO,aAAa,WAAW,GAAG;AAAA,QACpC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;AC5HO,SAAS,eACd,QACoB;AACpB,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,OAAO,WAAW,UAAU;AAC9B,QAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAI;AACF,YAAM,KAAK,SAAS,cAA2B,MAAM;AACrD,UAAI,CAAC,IAAI;AACP,gBAAQ,KAAK,8BAA8B,MAAM,kBAAkB;AACnE,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,KAAK,gCAAgC,MAAM,MAAM,KAAK;AAC9D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,OAAO,gBAAgB,eAAe,kBAAkB,aAAa;AACvE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,qBACd,SACA,SAAkB,MACZ;AACN,MAAI,CAAC,WAAW,OAAO,QAAQ,mBAAmB,WAAY;AAE9D,MAAI;AACF,YAAQ,eAAe;AAAA,MACrB,UAAU,SAAS,WAAW;AAAA,MAC9B,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,QAAQ;AACN,QAAI;AAEF,cAAQ,eAAe,IAAI;AAAA,IAC7B,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAcO,SAAS,sBACd,SACA,UAAkB,GACL;AACb,QAAM,OAAO,QAAQ,sBAAsB;AAE3C,QAAM,MAAM,KAAK,MAAM;AACvB,QAAM,OAAO,KAAK,OAAO;AACzB,QAAM,QAAQ,KAAK,QAAQ,UAAU;AACrC,QAAM,SAAS,KAAK,SAAS,UAAU;AAEvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,OAAO;AAAA,IACd,QAAQ,MAAM;AAAA,EAChB;AACF;AAKO,SAAS,qBAAqB,WAAuC;AAC1E,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,SAAO,MAAM,KAAK,UAAU,iBAA8B,QAAQ,CAAC,EAAE;AAAA,IACnE,CAAC,OAAO,GAAG,iBAAiB,QAAQ,GAAG,eAAe,EAAE,SAAS;AAAA,EACnE;AACF;AAKO,SAAS,cAAc,IAAsC;AAClE,MAAI,MAAM,GAAG,YAAY;AACvB,OAAG,WAAW,YAAY,EAAE;AAAA,EAC9B;AACF;;;ACpGO,IAAM,UAAN,MAAc;AAAA,EAOnB,YAAY,SAAwB,CAAC,GAAG;AANxC,SAAQ,cAAkC;AAC1C,SAAQ,aAAoC;AAC5C,SAAQ,eAAmC;AAKzC,SAAK,SAAS;AAAA,MACZ,SAAS,OAAO,WAAW;AAAA,MAC3B,SAAS,OAAO,WAAW;AAAA,MAC3B,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO,UAAU;AAAA,MACzB,SAAS,OAAO,WAAW;AAAA,MAC3B,YAAY,OAAO,cAAc;AAAA,MACjC,gBAAgB,OAAO;AAAA,IACzB;AACA,SAAK,SAAS,iBAAiB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACvE;AAAA,EAEA,QAAc;AACZ,QAAI,OAAO,aAAa,YAAa;AACrC,QAAI,KAAK,eAAe,KAAK,YAAY,YAAa;AAGtD,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,aAAa,sBAAsB,EAAE;AAC1C,SAAK,YAAY;AACjB,SAAK,MAAM,YAAY,sBAAsB,OAAO,KAAK,OAAO,MAAM,CAAC;AACvE,QAAI,KAAK,OAAO,YAAY,QAAW;AACrC,WAAK,MAAM,YAAY,8BAA8B,OAAO,KAAK,OAAO,OAAO,CAAC;AAAA,IAClF;AACA,QAAI,KAAK,OAAO,OAAO;AACrB,WAAK,MAAM,YAAY,sBAAsB,KAAK,OAAO,KAAK;AAAA,IAChE;AAGA,UAAM,MAAM,SAAS,gBAAgB,8BAA8B,KAAK;AACxE,QAAI,aAAa,yBAAyB,EAAE;AAC5C,QAAI,aAAa,SAAS,kBAAkB;AAC5C,QAAI,aAAa,SAAS,MAAM;AAChC,QAAI,aAAa,UAAU,MAAM;AACjC,QAAI,CAAC,KAAK,OAAO,SAAS;AACxB,UAAI,MAAM,UAAU;AAAA,IACtB;AAEA,UAAM,OAAO,SAAS,gBAAgB,8BAA8B,MAAM;AAC1E,UAAM,OAAO,SAAS,gBAAgB,8BAA8B,MAAM;AAC1E,SAAK,aAAa,MAAM,KAAK,MAAM;AAGnC,UAAM,SAAS,SAAS,gBAAgB,8BAA8B,MAAM;AAC5E,WAAO,aAAa,KAAK,GAAG;AAC5B,WAAO,aAAa,KAAK,GAAG;AAC5B,WAAO,aAAa,SAAS,MAAM;AACnC,WAAO,aAAa,UAAU,MAAM;AACpC,WAAO,aAAa,QAAQ,SAAS;AAGrC,UAAM,SAAS,SAAS,gBAAgB,8BAA8B,MAAM;AAC5E,WAAO,aAAa,wBAAwB,EAAE;AAC9C,WAAO,aAAa,SAAS,iBAAiB;AAC9C,WAAO,aAAa,KAAK,GAAG;AAC5B,WAAO,aAAa,KAAK,GAAG;AAC5B,WAAO,aAAa,SAAS,GAAG;AAChC,WAAO,aAAa,UAAU,GAAG;AACjC,WAAO,aAAa,MAAM,GAAG;AAC7B,WAAO,aAAa,MAAM,GAAG;AAC7B,WAAO,aAAa,QAAQ,SAAS;AAErC,SAAK,YAAY,MAAM;AACvB,SAAK,YAAY,MAAM;AACvB,SAAK,YAAY,IAAI;AACrB,QAAI,YAAY,IAAI;AAGpB,UAAM,cAAc,SAAS;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AACA,gBAAY,aAAa,KAAK,GAAG;AACjC,gBAAY,aAAa,KAAK,GAAG;AACjC,gBAAY,aAAa,SAAS,MAAM;AACxC,gBAAY,aAAa,UAAU,MAAM;AACzC,gBAAY,aAAa,QAAQ,cAAc;AAC/C,gBAAY,aAAa,QAAQ,QAAQ,KAAK,MAAM,GAAG;AACvD,QAAI,YAAY,WAAW;AAG3B,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,aAAa,uBAAuB,EAAE;AAC5C,UAAM,YAAY;AAGlB,QAAI,KAAK,OAAO,cAAc,KAAK,OAAO,gBAAgB;AACxD,UAAI,iBAAiB,SAAS,CAAC,MAAM;AAEnC,YAAI,EAAE,WAAW,OAAO,EAAE,WAAW,aAAa;AAChD,eAAK,OAAO,iBAAiB;AAAA,QAC/B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,SAAK,YAAY,GAAG;AACpB,SAAK,YAAY,KAAK;AACtB,aAAS,KAAK,YAAY,IAAI;AAE9B,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,OAAO,MAAqB,UAAmB,MAAY;AACzD,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,cAAc;AAC1C,WAAK,MAAM;AAAA,IACb;AAEA,QAAI,KAAK,cAAc,KAAK,cAAc;AACxC,UAAI,CAAC,WAAW,CAAC,KAAK,OAAO,SAAS;AACpC,aAAK,WAAW,MAAM,aAAa;AACnC,aAAK,aAAa,MAAM,aAAa;AAAA,MACvC,OAAO;AACL,aAAK,WAAW,MAAM,aAAa;AACnC,aAAK,aAAa,MAAM,aAAa;AAAA,MACvC;AAEA,WAAK,WAAW,aAAa,KAAK,OAAO,KAAK,IAAI,CAAC;AACnD,WAAK,WAAW,aAAa,KAAK,OAAO,KAAK,GAAG,CAAC;AAClD,WAAK,WAAW,aAAa,SAAS,OAAO,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC;AACrE,WAAK,WAAW,aAAa,UAAU,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC,CAAC;AACvE,WAAK,WAAW,aAAa,MAAM,OAAO,KAAK,MAAM,CAAC;AACtD,WAAK,WAAW,aAAa,MAAM,OAAO,KAAK,MAAM,CAAC;AAEtD,WAAK,aAAa,MAAM,OAAO,GAAG,KAAK,IAAI;AAC3C,WAAK,aAAa,MAAM,MAAM,GAAG,KAAK,GAAG;AACzC,WAAK,aAAa,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC;AAC1D,WAAK,aAAa,MAAM,SAAS,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,CAAC;AAC5D,WAAK,aAAa,MAAM,eAAe,GAAG,KAAK,MAAM;AAAA,IACvD;AAAA,EACF;AAAA,EAEA,iBAAqC;AACnC,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,YAAY,aAAa;AACtD,WAAK,MAAM;AAAA,IACb;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAsC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,kBAAc,KAAK,WAAW;AAC9B,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,eAAe;AAAA,EACtB;AACF;;;ACvJO,IAAM,UAAN,MAAc;AAAA,EAenB,YAAY,WAA6B,SAAwB,CAAC,GAAG;AAdrE,SAAQ,UAA8B;AACtC,SAAQ,WAA+B;AACvC,SAAQ,UAA8B;AACtC,SAAQ,WAAqC;AAC7C,SAAQ,YAAgC;AACxC,SAAQ,WAA+B;AACvC,SAAQ,UAAoC;AAC5C,SAAQ,UAAoC;AAC5C,SAAQ,aAAiC;AACzC,SAAQ,UAA8B;AAMpC,SAAK,YAAY;AACjB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,WAA8B;AAClC,QAAI,KAAK,WAAW,KAAK,QAAQ,YAAa;AAE9C,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,aAAa,yBAAyB,EAAE;AAChD,YAAQ,YAAY;AACpB,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,aAAa,cAAc,MAAM;AACzC,YAAQ,aAAa,mBAAmB,gBAAgB;AACxD,YAAQ,aAAa,oBAAoB,sBAAsB;AAC/D,YAAQ,aAAa,YAAY,IAAI;AAGrC,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,aAAa,wBAAwB,EAAE;AAC9C,WAAO,YAAY;AAEnB,UAAM,QAAQ,SAAS,cAAc,IAAI;AACzC,UAAM,aAAa,uBAAuB,EAAE;AAC5C,UAAM,KAAK;AACX,UAAM,YAAY;AAElB,UAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,aAAS,aAAa,uBAAuB,EAAE;AAC/C,aAAS,aAAa,QAAQ,QAAQ;AACtC,aAAS,YAAY;AACrB,aAAS,YAAY;AACrB,aAAS,aAAa,cAAc,KAAK,OAAO,mBAAmB,YAAY;AAC/E,aAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,QAAE,gBAAgB;AAClB,WAAK,UAAU,QAAQ;AAAA,IACzB,CAAC;AAED,WAAO,YAAY,KAAK;AACxB,WAAO,YAAY,QAAQ;AAG3B,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,aAAa,yBAAyB,EAAE;AAChD,YAAQ,KAAK;AACb,YAAQ,YAAY;AAGpB,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,aAAa,wBAAwB,EAAE;AAC9C,WAAO,YAAY;AAEnB,UAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,YAAQ,aAAa,sBAAsB,EAAE;AAC7C,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,YAAY;AACpB,YAAQ,iBAAiB,SAAS,CAAC,MAAM;AACvC,QAAE,gBAAgB;AAClB,WAAK,UAAU,OAAO;AAAA,IACxB,CAAC;AAED,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,aAAa,0BAA0B,EAAE;AAClD,aAAS,YAAY;AAErB,UAAM,UAAU,SAAS,cAAc,QAAQ;AAC/C,YAAQ,aAAa,sBAAsB,EAAE;AAC7C,YAAQ,aAAa,QAAQ,QAAQ;AACrC,YAAQ,YAAY;AACpB,YAAQ,iBAAiB,SAAS,CAAC,MAAM;AACvC,QAAE,gBAAgB;AAClB,WAAK,UAAU,OAAO;AAAA,IACxB,CAAC;AAED,WAAO,YAAY,OAAO;AAC1B,WAAO,YAAY,QAAQ;AAC3B,WAAO,YAAY,OAAO;AAG1B,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,aAAa,uBAAuB,EAAE;AAC5C,UAAM,YAAY;AAElB,YAAQ,YAAY,MAAM;AAC1B,YAAQ,YAAY,OAAO;AAC3B,YAAQ,YAAY,MAAM;AAC1B,YAAQ,YAAY,KAAK;AAEzB,cAAU,YAAY,OAAO;AAE7B,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,WACE,MACA,WACA,YACM;AACN,QAAI,CAAC,KAAK,QAAS;AAGnB,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,OAAO;AACd,aAAK,QAAQ,cAAc,KAAK;AAChC,aAAK,QAAQ,MAAM,UAAU;AAAA,MAC/B,OAAO;AACL,aAAK,QAAQ,cAAc;AAC3B,aAAK,QAAQ,MAAM,UAAU;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,YACJ,KAAK,oBAAoB,SACrB,KAAK,kBACL,KAAK,OAAO,eAAe;AAEjC,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,MAAM,UAAU,YAAY,KAAK;AAC/C,YAAM,YACJ,KAAK,mBAAmB,KAAK,OAAO,mBAAmB;AACzD,WAAK,SAAS,aAAa,cAAc,SAAS;AAAA,IACpD;AAGA,QAAI,KAAK,UAAU;AACjB,UAAI,CAAC,KAAK,SAAS,CAAC,WAAW;AAC7B,aAAK,SAAS,MAAM,UAAU;AAAA,MAChC,OAAO;AACL,aAAK,SAAS,MAAM,UAAU;AAAA,MAChC;AAAA,IACF;AAGA,QAAI,KAAK,WAAW;AAClB,UAAI,KAAK,SAAS;AAChB,aAAK,UAAU,YAAY,KAAK;AAAA,MAClC,WAAW,KAAK,aAAa;AAC3B,aAAK,UAAU,cAAc,KAAK;AAAA,MACpC,OAAO;AACL,aAAK,UAAU,cAAc;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,eACJ,KAAK,OAAO,iBAAiB,SAAS,aAAa;AACrD,QAAI,KAAK,YAAY;AACnB,UAAI,cAAc;AAChB,aAAK,WAAW,MAAM,UAAU;AAChC,YAAI,KAAK,OAAO,gBAAgB;AAC9B,eAAK,WAAW,cAAc,KAAK,OAAO;AAAA,YACxC,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF,OAAO;AACL,eAAK,WAAW,cAAc,GAAG,YAAY,CAAC,MAAM,UAAU;AAAA,QAChE;AAAA,MACF,OAAO;AACL,aAAK,WAAW,MAAM,UAAU;AAAA,MAClC;AAAA,IACF;AAGA,UAAM,cAAc,cAAc;AAClC,UAAM,WACJ,KAAK,uBAAuB,SACxB,KAAK,qBACL,KAAK,OAAO,gBAAgB;AAElC,QAAI,KAAK,SAAS;AAChB,UAAI,CAAC,UAAU;AACb,aAAK,QAAQ,MAAM,UAAU;AAAA,MAC/B,OAAO;AACL,aAAK,QAAQ,MAAM,UAAU;AAC7B,aAAK,QAAQ,WAAW;AACxB,aAAK,QAAQ,cACX,KAAK,sBACL,KAAK,OAAO,sBACZ;AACF,YAAI,aAAa;AACf,eAAK,QAAQ,aAAa,iBAAiB,MAAM;AAAA,QACnD,OAAO;AACL,eAAK,QAAQ,gBAAgB,eAAe;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAGA,UAAM,aAAa,cAAc,aAAa;AAC9C,UAAM,WACJ,KAAK,mBAAmB,SACpB,KAAK,iBACL,KAAK,OAAO,gBAAgB;AAElC,QAAI,KAAK,SAAS;AAChB,UAAI,CAAC,UAAU;AACb,aAAK,QAAQ,MAAM,UAAU;AAAA,MAC/B,OAAO;AACL,aAAK,QAAQ,MAAM,UAAU;AAC7B,YAAI,YAAY;AACd,eAAK,QAAQ,cACX,KAAK,kBACL,KAAK,OAAO,kBACZ;AAAA,QACJ,OAAO;AACL,eAAK,QAAQ,cACX,KAAK,kBACL,KAAK,OAAO,kBACZ;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,UAAU;AACjB,YAAM,aACJ,YAAY,YAAY;AAC1B,WAAK,SAAS,MAAM,UAAU,aAAa,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAc,KAA4B,UAAmB,MAAY;AACvE,QAAI,CAAC,KAAK,QAAS;AAEnB,QAAI,CAAC,SAAS;AACZ,WAAK,QAAQ,MAAM,aAAa;AAAA,IAClC,OAAO;AACL,WAAK,QAAQ,MAAM,aAAa;AAAA,IAClC;AAEA,SAAK,QAAQ,MAAM,OAAO,GAAG,IAAI,IAAI;AACrC,SAAK,QAAQ,MAAM,MAAM,GAAG,IAAI,GAAG;AACnC,SAAK,QAAQ,aAAa,kBAAkB,IAAI,SAAS;AACzD,SAAK,QAAQ,aAAa,kBAAkB,IAAI,SAAS;AAEzD,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,aAAa,wBAAwB,IAAI,kBAAkB,KAAK;AAC7E,UAAI,IAAI,cAAc,QAAW;AAC/B,aAAK,QAAQ,MAAM,OAAO,GAAG,IAAI,SAAS;AAAA,MAC5C,OAAO;AACL,aAAK,QAAQ,MAAM,OAAO;AAAA,MAC5B;AACA,UAAI,IAAI,aAAa,QAAW;AAC9B,aAAK,QAAQ,MAAM,MAAM,GAAG,IAAI,QAAQ;AAAA,MAC1C,OAAO;AACL,aAAK,QAAQ,MAAM,MAAM;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAA0C;AACxC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAmD;AACjD,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IACnC;AACA,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,WAAO;AAAA,MACL,OAAO,KAAK,SAAS;AAAA,MACrB,QAAQ,KAAK,UAAU;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,kBAAc,KAAK,OAAO;AAC1B,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AACF;;;ACjUO,IAAM,YAAN,MAAgB;AAAA,EAAhB;AACL,SAAQ,iBAAqC;AAC7C,SAAQ,UAAkB;AAC1B,SAAQ,SAAiB;AAAA;AAAA,EAEzB,UAAU,SAAsB,UAAkB,GAAG,SAAiB,GAAkB;AACtF,SAAK,iBAAiB;AACtB,SAAK,UAAU;AACf,SAAK,SAAS;AACd,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,UAAyB;AACvB,QAAI,CAAC,KAAK,kBAAkB,CAAC,KAAK,eAAe,aAAa;AAC5D,aAAO;AAAA,QACL,KAAK;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAEA,UAAM,MAAM,sBAAsB,KAAK,gBAAgB,KAAK,OAAO;AACnE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,aAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAc;AACZ,SAAK,iBAAiB;AAAA,EACxB;AACF;;;AChCO,IAAM,uBAAN,MAA2B;AAAA,EAMhC,YAAY,SAA8B,CAAC,GAAG;AAL9C,SAAQ,wBAA4C;AACpD,SAAQ,kBAAuD;AAE/D,SAAQ,iBAAqC;AAG3C,SAAK,SAAS;AAAA,MACZ,oBAAoB,OAAO,sBAAsB;AAAA,MACjD,eAAe,OAAO,iBAAiB;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,oBAA0B;AACxB,QACE,OAAO,aAAa,eACpB,SAAS,yBAAyB,aAClC;AACA,WAAK,wBAAwB,SAAS;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,OACE,SACA,WACM;AACN,SAAK,iBAAiB;AAEtB,QAAI,KAAK,iBAAiB;AACxB,WAAK,OAAO;AAAA,IACd;AAEA,SAAK,kBAAkB,CAAC,MAAqB;AAE3C,WACG,KAAK,OAAO,kBAAkB,SAAS,KAAK,OAAO,wBACnD,EAAE,QAAQ,YAAY,EAAE,QAAQ,QACjC;AACA,UAAE,eAAe;AACjB,kBAAU,QAAQ;AAClB;AAAA,MACF;AAGA,UAAI,KAAK,OAAO,oBAAoB;AAClC,YAAI,EAAE,QAAQ,cAAc;AAC1B,YAAE,eAAe;AACjB,oBAAU,OAAO;AACjB;AAAA,QACF;AACA,YAAI,EAAE,QAAQ,aAAa;AACzB,YAAE,eAAe;AACjB,oBAAU,OAAO;AACjB;AAAA,QACF;AAAA,MACF;AAGA,UAAI,EAAE,QAAQ,SAAS,KAAK,gBAAgB;AAC1C,cAAM,aAAa,qBAAqB,KAAK,cAAc;AAC3D,YAAI,WAAW,WAAW,GAAG;AAC3B,YAAE,eAAe;AACjB;AAAA,QACF;AAEA,cAAM,QAAQ,WAAW,CAAC;AAC1B,cAAM,OAAO,WAAW,WAAW,SAAS,CAAC;AAE7C,YAAI,EAAE,UAAU;AACd,cAAI,SAAS,kBAAkB,OAAO;AACpC,cAAE,eAAe;AACjB,kBAAM,MAAM;AAAA,UACd;AAAA,QACF,OAAO;AACL,cAAI,SAAS,kBAAkB,MAAM;AACnC,cAAE,eAAe;AACjB,mBAAO,MAAM;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,iBAAiB,WAAW,KAAK,eAAe;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,aAAa,kBAA6C;AACxD,QAAI,oBAAoB,OAAO,iBAAiB,UAAU,YAAY;AACpE,uBAAiB,MAAM;AACvB;AAAA,IACF;AAEA,QAAI,KAAK,gBAAgB;AACvB,YAAM,aAAa,qBAAqB,KAAK,cAAc;AAC3D,UAAI,WAAW,SAAS,KAAK,WAAW,CAAC,GAAG;AAC1C,mBAAW,CAAC,EAAE,MAAM;AAAA,MACtB,OAAO;AACL,aAAK,eAAe,MAAM;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAqB;AACnB,QACE,KAAK,yBACL,KAAK,sBAAsB,eAC3B,OAAO,KAAK,sBAAsB,UAAU,YAC5C;AACA,UAAI;AACF,aAAK,sBAAsB,MAAM;AAAA,MACnC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEA,SAAe;AACb,QAAI,OAAO,WAAW,eAAe,KAAK,iBAAiB;AACzD,aAAO,oBAAoB,WAAW,KAAK,eAAe;AAAA,IAC5D;AACA,SAAK,kBAAkB;AACvB,SAAK,iBAAiB;AAAA,EACxB;AACF;;;AChIA,SAAS,eACP,QACA,SACA,WACA,WACA,QAC+B;AAC/B,MAAI,MAAM;AACV,MAAI,OAAO;AAGX,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,YAAM,OAAO,MAAM,QAAQ,SAAS;AACpC;AAAA,IACF,KAAK;AACH,YAAM,OAAO,MAAM,OAAO,SAAS;AACnC;AAAA,IACF,KAAK;AACH,aAAO,OAAO,OAAO,QAAQ,QAAQ;AACrC;AAAA,IACF,KAAK;AACH,aAAO,OAAO,OAAO,OAAO,QAAQ;AACpC;AAAA,EACJ;AAGA,MAAI,cAAc,SAAS,cAAc,UAAU;AACjD,YAAQ,WAAW;AAAA,MACjB,KAAK;AACH,eAAO,OAAO;AACd;AAAA,MACF,KAAK;AACH,eAAO,OAAO,QAAQ,OAAO,QAAQ,QAAQ,SAAS;AACtD;AAAA,MACF,KAAK;AACH,eAAO,OAAO,OAAO,OAAO,QAAQ,QAAQ;AAC5C;AAAA,IACJ;AAAA,EACF,OAAO;AAEL,YAAQ,WAAW;AAAA,MACjB,KAAK;AACH,cAAM,OAAO;AACb;AAAA,MACF,KAAK;AACH,cAAM,OAAO,OAAO,OAAO,SAAS,QAAQ,UAAU;AACtD;AAAA,MACF,KAAK;AACH,cAAM,OAAO,MAAM,OAAO,SAAS,QAAQ;AAC3C;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,KAAK;AACrB;AAKA,SAAS,eACP,KACA,SACA,IACA,IACA,SACS;AACT,SACE,IAAI,QAAQ,WACZ,IAAI,OAAO,WACX,IAAI,OAAO,QAAQ,SAAS,KAAK,WACjC,IAAI,MAAM,QAAQ,UAAU,KAAK;AAErC;AAKA,SAAS,eACP,KACA,SACA,IACA,IACA,SACQ;AACR,QAAM,cAAc,KAAK,IAAI,SAAS,IAAI,IAAI;AAC9C,QAAM,aAAa,KAAK,IAAI,SAAS,IAAI,GAAG;AAC5C,QAAM,eAAe,KAAK,IAAI,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK;AACpE,QAAM,gBAAgB,KAAK,IAAI,KAAK,SAAS,IAAI,MAAM,QAAQ,MAAM;AAErE,QAAM,WAAW,KAAK,IAAI,GAAG,eAAe,WAAW;AACvD,QAAM,WAAW,KAAK,IAAI,GAAG,gBAAgB,UAAU;AAEvD,SAAO,WAAW;AACpB;AAKA,SAAS,sBAAsB,WAAiC;AAC9D,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,CAAC,SAAS,QAAQ,UAAU,KAAK;AAAA,IAC1C,KAAK;AACH,aAAO,CAAC,QAAQ,SAAS,UAAU,KAAK;AAAA,IAC1C,KAAK;AACH,aAAO,CAAC,UAAU,OAAO,SAAS,MAAM;AAAA,IAC1C,KAAK;AACH,aAAO,CAAC,OAAO,UAAU,SAAS,MAAM;AAAA,EAC5C;AACF;AAMO,SAAS,yBACd,QACuB;AACvB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,WAAW,qBAAqB;AAAA,IAChC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACd,IAAI;AAEJ,QAAM,KACJ,OAAO,kBACN,OAAO,WAAW,cAAc,OAAO,aAAa;AACvD,QAAM,KACJ,OAAO,mBACN,OAAO,WAAW,cAAc,OAAO,cAAc;AAExD,QAAM,mBAAmB,sBAAsB,kBAAkB;AAEjE,MAAI,kBAA4B;AAChC,MAAI,YAAY;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,WAAW;AAEf,aAAW,KAAK,kBAAkB;AAChC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,eAAe,QAAQ,aAAa,IAAI,IAAI,eAAe,GAAG;AAChE,wBAAkB;AAClB,kBAAY;AACZ,iBAAW;AACX;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,UAAU;AACb,QAAI,gBAAgB;AACpB,QAAI,YAAY;AAChB,QAAI,UAAU;AAEd,eAAW,KAAK,kBAAkB;AAChC,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,wBAAgB;AAChB,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,sBAAkB;AAClB,gBAAY;AAAA,EACd;AAGA,QAAM,UAAU;AAChB,QAAM,UAAU,KAAK,IAAI,iBAAiB,KAAK,YAAY,QAAQ,eAAe;AAClF,QAAM,SAAS;AACf,QAAM,SAAS,KAAK,IAAI,iBAAiB,KAAK,YAAY,SAAS,eAAe;AAElF,QAAM,cAAc,KAAK,IAAI,SAAS,KAAK,IAAI,UAAU,MAAM,OAAO,CAAC;AACvE,QAAM,aAAa,KAAK,IAAI,QAAQ,KAAK,IAAI,UAAU,KAAK,MAAM,CAAC;AAGnE,QAAM,gBAAgB,WAAW,OAAO,WAAW,QAAQ;AAC3D,QAAM,gBAAgB,WAAW,MAAM,WAAW,SAAS;AAE3D,MAAI;AACJ,MAAI;AACJ,MAAI,iBAA2B;AAE/B,QAAM,iBAAiB,YAAY;AAEnC,UAAQ,iBAAiB;AAAA,IACvB,KAAK;AAEH,uBAAiB;AACjB,iBAAW,YAAY;AACvB,kBAAY,KAAK;AAAA,QACf;AAAA,QACA,KAAK;AAAA,UACH,gBAAgB;AAAA,UAChB,YAAY,QAAQ;AAAA,QACtB;AAAA,MACF;AACA;AAAA,IACF,KAAK;AAEH,uBAAiB;AACjB,iBAAW,CAAC;AACZ,kBAAY,KAAK;AAAA,QACf;AAAA,QACA,KAAK;AAAA,UACH,gBAAgB;AAAA,UAChB,YAAY,QAAQ;AAAA,QACtB;AAAA,MACF;AACA;AAAA,IACF,KAAK;AAEH,uBAAiB;AACjB,kBAAY,YAAY;AACxB,iBAAW,KAAK;AAAA,QACd;AAAA,QACA,KAAK;AAAA,UACH,gBAAgB;AAAA,UAChB,YAAY,SAAS;AAAA,QACvB;AAAA,MACF;AACA;AAAA,IACF,KAAK;AAEH,uBAAiB;AACjB,kBAAY,CAAC;AACb,iBAAW,KAAK;AAAA,QACd;AAAA,QACA,KAAK;AAAA,UACH,gBAAgB;AAAA,UAChB,YAAY,SAAS;AAAA,QACvB;AAAA,MACF;AACA;AAAA,EACJ;AAEA,SAAO;AAAA,IACL,KAAK,KAAK,MAAM,UAAU;AAAA,IAC1B,MAAM,KAAK,MAAM,WAAW;AAAA,IAC5B,WAAW;AAAA,IACX;AAAA,IACA,UAAU,aAAa,SAAY,KAAK,MAAM,QAAQ,IAAI;AAAA,IAC1D,WAAW,cAAc,SAAY,KAAK,MAAM,SAAS,IAAI;AAAA,IAC7D;AAAA,EACF;AACF;;;AC5QO,IAAM,iBAAN,MAAqB;AAAA,EAoB1B,YACE,SACA,SACA,SACA;AAfF,SAAQ,mBAA2B;AACnC,SAAQ,aAAsB;AAC9B,SAAQ,YAAqB;AAE7B,SAAQ,iBAAsC;AAC9C,SAAQ,iBAAsC;AAC9C,SAAQ,QAAuB;AAE/B,SAAQ,eAAwC;AAChD,SAAQ,gBAAsD;AAO5D,SAAK,UAAU;AAAA,MACb,SAAS;AAAA,MACT,cAAc;AAAA,MACd,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,wBAAwB;AAAA,MACxB,2BAA2B;AAAA,MAC3B,GAAG;AAAA,IACL;AAEA,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,YAAY,IAAI,UAAU;AAE/B,SAAK,UAAU,IAAI,QAAQ;AAAA,MACzB,SAAS,KAAK,QAAQ,YAAY;AAAA,MAClC,SAAS,KAAK,QAAQ;AAAA,MACtB,OAAO,KAAK,QAAQ;AAAA,MACpB,QAAQ,KAAK,QAAQ;AAAA,MACrB,SAAS,KAAK,QAAQ;AAAA,MACtB,YAAY,KAAK,QAAQ;AAAA,MACzB,gBAAgB,MAAM,KAAK,KAAK;AAAA,IAClC,CAAC;AAED,SAAK,UAAU,IAAI;AAAA,MACjB;AAAA,QACE,QAAQ,MAAM,KAAK,SAAS;AAAA,QAC5B,QAAQ,MAAM,KAAK,KAAK;AAAA,QACxB,SAAS,MAAM,KAAK,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,QACE,YAAY,KAAK,QAAQ;AAAA,QACzB,cAAc,KAAK,QAAQ;AAAA,QAC3B,aAAa,KAAK,QAAQ;AAAA,QAC1B,gBAAgB,KAAK,QAAQ;AAAA,QAC7B,oBAAoB,KAAK,QAAQ;AAAA,QACjC,gBAAgB,KAAK,QAAQ;AAAA,QAC7B,iBAAiB,KAAK,QAAQ;AAAA,QAC9B,gBAAgB,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACF;AAEA,SAAK,gBAAgB,IAAI,qBAAqB;AAAA,MAC5C,oBAAoB,KAAK,QAAQ;AAAA,MACjC,eAAe,KAAK,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAM,aAAqB,GAAkB;AACjD,QAAI,KAAK,WAAW;AAClB,cAAQ,KAAK,oDAAoD;AACjE;AAAA,IACF;AAEA,QAAI,KAAK,YAAY;AACnB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,QAAQ,SAAS,KAAK,QAAQ,MAAM,WAAW,GAAG;AAC1D,cAAQ,KAAK,6CAA6C;AAC1D;AAAA,IACF;AAGA,QAAI,KAAK,QAAQ,YAAY,KAAK,QAAQ,IAAI;AAC5C,YAAM,cAAc,MAAM,KAAK,QAAQ,YAAY,KAAK,QAAQ,EAAE;AAClE,UAAI,aAAa;AACf;AAAA,MACF;AAAA,IACF;AAEA,SAAK,aAAa;AAClB,SAAK,cAAc,kBAAkB;AAGrC,SAAK,QAAQ,MAAM;AACnB,UAAM,SAAS,KAAK,QAAQ,eAAe;AAC3C,QAAI,QAAQ;AACV,WAAK,QAAQ,MAAM,MAAM;AAAA,IAC3B;AAGA,UAAM,YAAY,KAAK,QAAQ,WAAW;AAC1C,QAAI,WAAW;AACb,WAAK,cAAc,OAAO,WAAW;AAAA,QACnC,QAAQ,MAAM,KAAK,KAAK;AAAA,QACxB,QAAQ,MAAM,KAAK,SAAS;AAAA,QAC5B,SAAS,MAAM,KAAK,KAAK;AAAA,MAC3B,CAAC;AAAA,IACH;AAGA,SAAK,uBAAuB;AAG5B,SAAK,QAAQ,KAAK,OAAO;AACzB,SAAK,QAAQ,UAAU;AAGvB,UAAM,KAAK,KAAK,UAAU;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,WAAY;AAEtB,SAAK,eAAe;AACpB,UAAM,KAAK,iBAAiB;AAE5B,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,UAAU,MAAM;AAErB,SAAK,wBAAwB;AAC7B,SAAK,cAAc,OAAO;AAC1B,SAAK,cAAc,aAAa;AAEhC,SAAK,QAAQ,QAAQ;AACrB,SAAK,QAAQ,QAAQ;AAErB,SAAK,QAAQ,KAAK,OAAO;AACzB,SAAK,QAAQ,UAAU;AAAA,EACzB;AAAA,EAEA,MAAM,WAA0B;AAC9B,QAAI,CAAC,KAAK,WAAY;AAEtB,SAAK,eAAe;AACpB,UAAM,KAAK,iBAAiB;AAE5B,QAAI,KAAK,QAAQ,YAAY,KAAK,QAAQ,IAAI;AAC5C,YAAM,KAAK,QAAQ,cAAc,KAAK,QAAQ,EAAE;AAAA,IAClD;AAEA,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,UAAU,MAAM;AAErB,SAAK,wBAAwB;AAC7B,SAAK,cAAc,OAAO;AAC1B,SAAK,cAAc,aAAa;AAEhC,SAAK,QAAQ,QAAQ;AACrB,SAAK,QAAQ,QAAQ;AAErB,SAAK,QAAQ,KAAK,UAAU;AAC5B,SAAK,QAAQ,aAAa;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,UAAU,KAAK,mBAAmB;AACxC,QAAI,WAAW,KAAK,QAAQ,MAAM,QAAQ;AACxC,YAAM,KAAK,SAAS;AAAA,IACtB,OAAO;AACL,YAAM,KAAK,KAAK,SAAS,SAAS;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,MAAM,WAA0B;AAC9B,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,UAAU,KAAK,mBAAmB;AACxC,QAAI,WAAW,GAAG;AAChB,YAAM,KAAK,KAAK,SAAS,UAAU;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAAe,YAAoC,WAA0B;AACtF,QAAI,CAAC,KAAK,cAAc,KAAK,UAAW;AAExC,QAAI,QAAQ,KAAK,SAAS,KAAK,QAAQ,MAAM,QAAQ;AACnD;AAAA,IACF;AAEA,SAAK,eAAe;AAEpB,UAAM,OAAO,KAAK,QAAQ,MAAM,KAAK;AACrC,QAAI,CAAC,KAAM;AAGX,QAAI,WAAW,eAAe,KAAK,OAAO;AAE1C,QAAI,CAAC,UAAU;AACb,YAAM,WACJ,KAAK,QAAQ,0BAA0B;AAEzC,UAAI,aAAa,QAAQ;AACvB,gBAAQ,KAAK,6CAA6C,OAAO,KAAK,OAAO,CAAC,kBAAkB;AAChG,cAAM,KAAK,KAAK;AAChB;AAAA,MACF;AAEA,UAAI,aAAa,QAAQ;AACvB,mBAAW,MAAM,KAAK;AAAA,UACpB,KAAK;AAAA,UACL,KAAK,QAAQ,6BAA6B;AAAA,QAC5C;AAEA,YAAI,CAAC,UAAU;AACb,kBAAQ,KAAK,2CAA2C,OAAO,KAAK,OAAO,CAAC,cAAc;AAC1F,gBAAM,KAAK,mBAAmB,OAAO,SAAS;AAC9C;AAAA,QACF;AAAA,MACF,OAAO;AAEL,gBAAQ,KAAK,4BAA4B,KAAK,qBAAqB,OAAO,KAAK,OAAO,CAAC,kBAAkB;AACzG,cAAM,KAAK,mBAAmB,OAAO,SAAS;AAC9C;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,iBAAiB;AAE5B,SAAK,mBAAmB;AAGxB,QAAI,KAAK,QAAQ,iBAAiB,OAAO;AACvC,2BAAqB,UAAU,KAAK,QAAQ,YAAY,KAAK;AAAA,IAC/D;AAGA,UAAM,UAAU,KAAK,WAAW,KAAK,QAAQ,gBAAgB;AAC7D,UAAM,SAAS,KAAK,QAAQ,eAAe;AAC3C,UAAM,gBAAgB,KAAK,UAAU,UAAU,UAAU,SAAS,MAAM;AAGxE,SAAK,QAAQ,OAAO,eAAe,KAAK,QAAQ,YAAY,KAAK;AAGjE,SAAK,QAAQ,WAAW,MAAM,OAAO,KAAK,QAAQ,MAAM,MAAM;AAG9D,SAAK,eAAe;AAGpB,UAAM,UAAU,KAAK,QAAQ,cAAc;AAC3C,SAAK,cAAc,aAAa,OAAO;AAGvC,QAAI;AACF,YAAM,KAAK,UAAU;AAAA,IACvB,SAAS,OAAO;AACd,cAAQ,MAAM,4BAA4B,KAAK,aAAa,KAAK;AAAA,IACnE;AAGA,SAAK,QAAQ,KAAK,cAAc,EAAE,MAAM,MAAM,CAAC;AAC/C,SAAK,QAAQ,eAAe,MAAM,KAAK;AAAA,EACzC;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,cAAc,KAAK,qBAAqB,GAAI;AAEtD,QAAI,KAAK,UAAU,QAAQ,OAAO,yBAAyB,aAAa;AACtE,2BAAqB,KAAK,KAAK;AAAA,IACjC;AAEA,QAAI,OAAO,0BAA0B,aAAa;AAChD,WAAK,QAAQ,sBAAsB,MAAM;AACvC,aAAK,OAAO;AAAA,MACd,CAAC;AAAA,IACH,OAAO;AACL,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,UAAW;AACpB,SAAK,YAAY;AAEjB,SAAK,eAAe;AACpB,SAAK,wBAAwB;AAE7B,QAAI,KAAK,YAAY;AACnB,WAAK,aAAa;AAClB,WAAK,cAAc,OAAO;AAC1B,WAAK,cAAc,aAAa;AAChC,WAAK,QAAQ,QAAQ;AACrB,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAEA,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,QAAQ,YAAY;AACzB,SAAK,QAAQ,mBAAmB;AAAA,EAClC;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAsC;AACpC,QAAI,CAAC,KAAK,cAAc,KAAK,qBAAqB,IAAI;AACpD,aAAO;AAAA,IACT;AACA,WAAO,KAAK,QAAQ,MAAM,KAAK,gBAAgB,KAAK;AAAA,EACtD;AAAA,EAEA,sBAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,SAAe;AACrB,QAAI,CAAC,KAAK,cAAc,KAAK,qBAAqB,GAAI;AAEtD,UAAM,WAAW,KAAK,UAAU,WAAW;AAC3C,QAAI,CAAC,YAAY,CAAC,SAAS,aAAa;AACtC;AAAA,IACF;AAEA,UAAM,gBAAgB,KAAK,UAAU,QAAQ;AAC7C,SAAK,QAAQ,OAAO,eAAe,KAAK;AACxC,SAAK,eAAe,KAAK;AAAA,EAC3B;AAAA,EAEQ,eAAe,UAAmB,MAAY;AACpD,UAAM,OAAO,KAAK,eAAe;AACjC,QAAI,CAAC,KAAM;AAEX,UAAM,gBAAgB,KAAK,UAAU,QAAQ;AAC7C,UAAM,aAAa,KAAK,QAAQ,cAAc;AAE9C,UAAM,iBAAiB,yBAAyB;AAAA,MAC9C,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,WAAW,KAAK,YAAY;AAAA,MAC5B,WAAW,KAAK,SAAS;AAAA,MACzB,QAAQ,KAAK,UAAU;AAAA,IACzB,CAAC;AAED,SAAK,QAAQ,cAAc,gBAAgB,WAAY,KAAK,QAAQ,YAAY,KAAM;AAAA,EACxF;AAAA,EAEA,MAAc,mBAAkC;AAC9C,QAAI,KAAK,oBAAoB,KAAK,KAAK,mBAAmB,KAAK,QAAQ,MAAM,QAAQ;AACnF,YAAM,WAAW,KAAK,QAAQ,MAAM,KAAK,gBAAgB;AACzD,UAAI,UAAU,SAAS;AACrB,YAAI;AACF,gBAAM,SAAS,QAAQ;AAAA,QACzB,SAAS,OAAO;AACd,kBAAQ,MAAM,4BAA4B,KAAK,gBAAgB,aAAa,KAAK;AAAA,QACnF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,cAAsB,WAAkD;AACvG,QAAI,cAAc,WAAW;AAC3B,YAAM,UAAU,eAAe;AAC/B,UAAI,WAAW,KAAK,QAAQ,MAAM,QAAQ;AACxC,cAAM,KAAK,SAAS;AAAA,MACtB,OAAO;AACL,cAAM,KAAK,KAAK,SAAS,SAAS;AAAA,MACpC;AAAA,IACF,OAAO;AACL,YAAM,UAAU,eAAe;AAC/B,UAAI,UAAU,GAAG;AACf,cAAM,KAAK,KAAK;AAAA,MAClB,OAAO;AACL,cAAM,KAAK,KAAK,SAAS,UAAU;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eACN,QACA,WAC6B;AAC7B,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,WAAW,eAAe,MAAM;AACtC,UAAI,UAAU;AACZ,gBAAQ,QAAQ;AAChB;AAAA,MACF;AAEA,UAAI,OAAO,qBAAqB,eAAe,OAAO,aAAa,aAAa;AAC9E,gBAAQ,IAAI;AACZ;AAAA,MACF;AAEA,WAAK,eAAe,IAAI,iBAAiB,MAAM;AAC7C,cAAM,QAAQ,eAAe,MAAM;AACnC,YAAI,OAAO;AACT,eAAK,eAAe;AACpB,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AAED,WAAK,aAAa,QAAQ,SAAS,MAAM;AAAA,QACvC,WAAW;AAAA,QACX,SAAS;AAAA,MACX,CAAC;AAED,WAAK,gBAAgB,WAAW,MAAM;AACpC,aAAK,eAAe;AACpB,gBAAQ,eAAe,MAAM,CAAC;AAAA,MAChC,GAAG,SAAS;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,WAAW;AAC7B,WAAK,eAAe;AAAA,IACtB;AACA,QAAI,KAAK,kBAAkB,MAAM;AAC/B,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,yBAA+B;AACrC,QAAI,OAAO,WAAW,YAAa;AAEnC,SAAK,iBAAiB,MAAM,KAAK,QAAQ;AACzC,SAAK,iBAAiB,MAAM,KAAK,QAAQ;AAEzC,WAAO,iBAAiB,UAAU,KAAK,gBAAgB,EAAE,SAAS,KAAK,CAAC;AACxE,WAAO,iBAAiB,UAAU,KAAK,gBAAgB,EAAE,SAAS,MAAM,SAAS,KAAK,CAAC;AAAA,EACzF;AAAA,EAEQ,0BAAgC;AACtC,QAAI,OAAO,WAAW,YAAa;AAEnC,QAAI,KAAK,gBAAgB;AACvB,aAAO,oBAAoB,UAAU,KAAK,cAAc;AACxD,WAAK,iBAAiB;AAAA,IACxB;AAEA,QAAI,KAAK,gBAAgB;AACvB,aAAO,oBAAoB,UAAU,KAAK,gBAAgB,IAAI;AAC9D,WAAK,iBAAiB;AAAA,IACxB;AAEA,QAAI,KAAK,UAAU,QAAQ,OAAO,yBAAyB,aAAa;AACtE,2BAAqB,KAAK,KAAK;AAC/B,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;;;AC/dO,IAAM,WAAN,MAAe;AAAA,EAMpB,YAAY,SAA0B;AAFtC,SAAQ,aAAoC;AAG1C,SAAK,UAAU,EAAE,GAAG,QAAQ;AAC5B,SAAK,UAAU,IAAI,aAAa;AAChC,SAAK,UAAU,IAAI,eAAe,KAAK,QAAQ,OAAO;AAGtD,QAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,WAAK,aAAa,IAAI;AAAA,QACpB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,UAAI,KAAK,QAAQ,WAAW;AAE1B,mBAAW,MAAM;AACf,eAAK,MAAM;AAAA,QACb,GAAG,CAAC;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBAA0C;AAChD,QAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAK,YAAY;AACpB,WAAK,aAAa,IAAI;AAAA,QACpB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,MAAM,aAAqB,GAAkB;AACjD,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,YAAM,KAAK,MAAM,UAAU;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,YAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,YAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,WAA0B;AAC9B,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAA8B;AACvC,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,YAAM,KAAK,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,UAAM,OAAO,KAAK,iBAAiB;AACnC,QAAI,MAAM;AACR,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,YAAY;AACnB,WAAK,WAAW,QAAQ;AACxB,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK,aAAa,KAAK,WAAW,SAAS,IAAI;AAAA,EACxD;AAAA,EAEA,iBAAsC;AACpC,WAAO,KAAK,aAAa,KAAK,WAAW,eAAe,IAAI;AAAA,EAC9D;AAAA,EAEA,sBAA8B;AAC5B,WAAO,KAAK,aAAa,KAAK,WAAW,oBAAoB,IAAI;AAAA,EACnE;AAAA,EAEA,MAAM,eAAiC;AACrC,QAAI,CAAC,KAAK,QAAQ,GAAI,QAAO;AAC7B,WAAO,KAAK,QAAQ,YAAY,KAAK,QAAQ,EAAE;AAAA,EACjD;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,CAAC,KAAK,QAAQ,GAAI;AACtB,UAAM,KAAK,QAAQ,MAAM,KAAK,QAAQ,EAAE;AAAA,EAC1C;AAAA,EAEA,MAAM,WAA0B;AAC9B,UAAM,KAAK,QAAQ,SAAS;AAAA,EAC9B;AAAA,EAEA,GACE,OACA,UACM;AACN,SAAK,QAAQ,GAAG,OAAO,QAAQ;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,IACE,OACA,UACM;AACN,SAAK,QAAQ,IAAI,OAAO,QAAQ;AAChC,WAAO;AAAA,EACT;AACF;;;AC1HA,IAAO,gBAAQ;","names":[]}
@@ -0,0 +1,310 @@
1
+ :root {
2
+ --webdrive-background: #ffffff;
3
+ --webdrive-foreground: #111827;
4
+ --webdrive-border: #e5e7eb;
5
+ --webdrive-primary: #18181b;
6
+ --webdrive-primary-foreground: #ffffff;
7
+ --webdrive-muted: #6b7280;
8
+ --webdrive-overlay: rgba(0, 0, 0, 0.6);
9
+ --webdrive-overlay-opacity: 0.6;
10
+ --webdrive-radius: 0.5rem;
11
+ --webdrive-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
12
+ --webdrive-z-index: 100000;
13
+ --webdrive-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
14
+ --webdrive-transition-duration: 0.28s;
15
+ --webdrive-transition-timing: cubic-bezier(0.16, 1, 0.3, 1);
16
+ }
17
+
18
+ .dark,
19
+ [data-theme="dark"] {
20
+ --webdrive-background: #18181b;
21
+ --webdrive-foreground: #f4f4f5;
22
+ --webdrive-border: #27272a;
23
+ --webdrive-primary: #fafafa;
24
+ --webdrive-primary-foreground: #18181b;
25
+ --webdrive-muted: #a1a1aa;
26
+ --webdrive-overlay: rgba(0, 0, 0, 0.75);
27
+ --webdrive-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
28
+ }
29
+
30
+ @media (prefers-color-scheme: dark) {
31
+ :root:not([data-theme="light"]) {
32
+ --webdrive-background: #18181b;
33
+ --webdrive-foreground: #f4f4f5;
34
+ --webdrive-border: #27272a;
35
+ --webdrive-primary: #fafafa;
36
+ --webdrive-primary-foreground: #18181b;
37
+ --webdrive-muted: #a1a1aa;
38
+ --webdrive-overlay: rgba(0, 0, 0, 0.75);
39
+ --webdrive-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
40
+ }
41
+ }
42
+
43
+ /* Root isolation container */
44
+ .webdrive-root,
45
+ [data-webdrive-root] {
46
+ position: fixed;
47
+ inset: 0;
48
+ z-index: var(--webdrive-z-index);
49
+ pointer-events: none;
50
+ font-family: var(--webdrive-font-family);
51
+ box-sizing: border-box;
52
+ }
53
+
54
+ .webdrive-root *,
55
+ [data-webdrive-root] * {
56
+ box-sizing: border-box;
57
+ }
58
+
59
+ /* Fullscreen SVG Overlay */
60
+ .webdrive-overlay,
61
+ [data-webdrive-overlay] {
62
+ position: fixed;
63
+ inset: 0;
64
+ width: 100vw;
65
+ height: 100vh;
66
+ pointer-events: auto;
67
+ color: var(--webdrive-overlay);
68
+ opacity: var(--webdrive-overlay-opacity);
69
+ transition: opacity var(--webdrive-transition-duration) ease;
70
+ }
71
+
72
+ /* Cutout transition */
73
+ .webdrive-cutout,
74
+ [data-webdrive-cutout] {
75
+ transition:
76
+ x var(--webdrive-transition-duration) var(--webdrive-transition-timing),
77
+ y var(--webdrive-transition-duration) var(--webdrive-transition-timing),
78
+ width var(--webdrive-transition-duration) var(--webdrive-transition-timing),
79
+ height var(--webdrive-transition-duration) var(--webdrive-transition-timing),
80
+ rx var(--webdrive-transition-duration) var(--webdrive-transition-timing),
81
+ ry var(--webdrive-transition-duration) var(--webdrive-transition-timing);
82
+ }
83
+
84
+ /* Stage - highlight bounding box */
85
+ .webdrive-stage,
86
+ [data-webdrive-stage] {
87
+ position: fixed;
88
+ pointer-events: none;
89
+ border-radius: var(--webdrive-radius);
90
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.4), 0 0 16px rgba(0, 0, 0, 0.2);
91
+ transition:
92
+ top var(--webdrive-transition-duration) var(--webdrive-transition-timing),
93
+ left var(--webdrive-transition-duration) var(--webdrive-transition-timing),
94
+ width var(--webdrive-transition-duration) var(--webdrive-transition-timing),
95
+ height var(--webdrive-transition-duration) var(--webdrive-transition-timing),
96
+ border-radius var(--webdrive-transition-duration) var(--webdrive-transition-timing);
97
+ }
98
+
99
+ /* Popover Dialog Card */
100
+ .webdrive-popover,
101
+ [data-webdrive-popover] {
102
+ position: fixed;
103
+ pointer-events: auto;
104
+ width: max-content;
105
+ max-width: min(calc(100vw - 24px), 360px);
106
+ min-width: 260px;
107
+ background-color: var(--webdrive-background);
108
+ color: var(--webdrive-foreground);
109
+ border: 1px solid var(--webdrive-border);
110
+ border-radius: var(--webdrive-radius);
111
+ box-shadow: var(--webdrive-shadow);
112
+ padding: 16px;
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: 12px;
116
+ z-index: calc(var(--webdrive-z-index) + 10);
117
+ outline: none;
118
+ transition:
119
+ top var(--webdrive-transition-duration) var(--webdrive-transition-timing),
120
+ left var(--webdrive-transition-duration) var(--webdrive-transition-timing);
121
+ }
122
+
123
+ /* Header */
124
+ .webdrive-header,
125
+ [data-webdrive-header] {
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: space-between;
129
+ gap: 8px;
130
+ }
131
+
132
+ .webdrive-title,
133
+ [data-webdrive-title] {
134
+ margin: 0;
135
+ font-size: 1rem;
136
+ font-weight: 600;
137
+ line-height: 1.3;
138
+ color: var(--webdrive-foreground);
139
+ }
140
+
141
+ /* Close button */
142
+ .webdrive-close,
143
+ [data-webdrive-close] {
144
+ background: transparent;
145
+ border: none;
146
+ color: var(--webdrive-muted);
147
+ cursor: pointer;
148
+ padding: 4px;
149
+ margin: -4px;
150
+ border-radius: calc(var(--webdrive-radius) - 2px);
151
+ font-size: 1.25rem;
152
+ line-height: 1;
153
+ display: inline-flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ width: 28px;
157
+ height: 28px;
158
+ transition: color 0.15s ease, background-color 0.15s ease;
159
+ }
160
+
161
+ .webdrive-close:hover,
162
+ [data-webdrive-close]:hover {
163
+ color: var(--webdrive-foreground);
164
+ background-color: rgba(125, 125, 125, 0.1);
165
+ }
166
+
167
+ .webdrive-close:focus-visible,
168
+ [data-webdrive-close]:focus-visible {
169
+ outline: 2px solid var(--webdrive-primary);
170
+ outline-offset: 1px;
171
+ }
172
+
173
+ /* Content Area */
174
+ .webdrive-content,
175
+ [data-webdrive-content] {
176
+ font-size: 0.875rem;
177
+ line-height: 1.5;
178
+ color: var(--webdrive-foreground);
179
+ overflow-wrap: break-word;
180
+ word-break: break-word;
181
+ }
182
+
183
+ /* Footer Controls */
184
+ .webdrive-footer,
185
+ [data-webdrive-footer] {
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: space-between;
189
+ gap: 8px;
190
+ margin-top: 4px;
191
+ padding-top: 8px;
192
+ }
193
+
194
+ /* Progress Indicator */
195
+ .webdrive-progress,
196
+ [data-webdrive-progress] {
197
+ font-size: 0.75rem;
198
+ color: var(--webdrive-muted);
199
+ font-variant-numeric: tabular-nums;
200
+ user-select: none;
201
+ }
202
+
203
+ /* Navigation Buttons */
204
+ .webdrive-button,
205
+ [data-webdrive-prev],
206
+ [data-webdrive-next] {
207
+ display: inline-flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ padding: 6px 14px;
211
+ font-size: 0.8125rem;
212
+ font-weight: 500;
213
+ line-height: 1.2;
214
+ border-radius: calc(var(--webdrive-radius) - 2px);
215
+ cursor: pointer;
216
+ border: 1px solid transparent;
217
+ transition: background-color 0.15s ease, opacity 0.15s ease, border-color 0.15s ease;
218
+ user-select: none;
219
+ }
220
+
221
+ .webdrive-button:focus-visible,
222
+ [data-webdrive-prev]:focus-visible,
223
+ [data-webdrive-next]:focus-visible {
224
+ outline: 2px solid var(--webdrive-primary);
225
+ outline-offset: 2px;
226
+ }
227
+
228
+ .webdrive-prev,
229
+ [data-webdrive-prev] {
230
+ background-color: transparent;
231
+ border-color: var(--webdrive-border);
232
+ color: var(--webdrive-foreground);
233
+ }
234
+
235
+ .webdrive-prev:hover:not(:disabled),
236
+ [data-webdrive-prev]:hover:not(:disabled) {
237
+ background-color: rgba(125, 125, 125, 0.08);
238
+ }
239
+
240
+ .webdrive-prev:disabled,
241
+ [data-webdrive-prev]:disabled {
242
+ opacity: 0.35;
243
+ cursor: not-allowed;
244
+ }
245
+
246
+ .webdrive-next,
247
+ [data-webdrive-next] {
248
+ background-color: var(--webdrive-primary);
249
+ color: var(--webdrive-primary-foreground);
250
+ border-color: var(--webdrive-primary);
251
+ margin-left: auto;
252
+ }
253
+
254
+ .webdrive-next:hover:not(:disabled),
255
+ [data-webdrive-next]:hover:not(:disabled) {
256
+ opacity: 0.9;
257
+ }
258
+
259
+ /* Directional Arrow */
260
+ .webdrive-arrow,
261
+ [data-webdrive-arrow] {
262
+ position: absolute;
263
+ width: 10px;
264
+ height: 10px;
265
+ background-color: var(--webdrive-background);
266
+ border: 1px solid var(--webdrive-border);
267
+ transform: rotate(45deg);
268
+ pointer-events: none;
269
+ }
270
+
271
+ [data-arrow-placement="top"] {
272
+ top: -6px;
273
+ border-bottom: none;
274
+ border-right: none;
275
+ }
276
+
277
+ [data-arrow-placement="bottom"] {
278
+ bottom: -6px;
279
+ border-top: none;
280
+ border-left: none;
281
+ }
282
+
283
+ [data-arrow-placement="left"] {
284
+ left: -6px;
285
+ border-top: none;
286
+ border-right: none;
287
+ }
288
+
289
+ [data-arrow-placement="right"] {
290
+ right: -6px;
291
+ border-bottom: none;
292
+ border-left: none;
293
+ }
294
+
295
+ /* Responsive adjustments for mobile screens */
296
+ @media (max-width: 480px) {
297
+ .webdrive-popover,
298
+ [data-webdrive-popover] {
299
+ max-width: calc(100vw - 20px);
300
+ padding: 12px;
301
+ font-size: 0.8125rem;
302
+ }
303
+
304
+ .webdrive-button,
305
+ [data-webdrive-prev],
306
+ [data-webdrive-next] {
307
+ padding: 6px 10px;
308
+ font-size: 0.75rem;
309
+ }
310
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "webdrive",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Production-ready, accessible, framework-agnostic TypeScript UI tour and onboarding walkthrough library",
6
+ "author": "webdrive",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "tour",
10
+ "onboarding",
11
+ "walkthrough",
12
+ "guide",
13
+ "tooltip",
14
+ "popover",
15
+ "framework-agnostic",
16
+ "typescript",
17
+ "driver",
18
+ "product-tour"
19
+ ],
20
+ "main": "./dist/index.cjs",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js",
27
+ "require": "./dist/index.cjs"
28
+ },
29
+ "./styles.css": "./dist/webdrive.css"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "sideEffects": [
37
+ "*.css"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "typecheck": "tsc --noEmit",
43
+ "test": "vitest run",
44
+ "test:watch": "vitest",
45
+ "test:coverage": "vitest run --coverage",
46
+ "prepublishOnly": "npm run typecheck && npm test && npm run build"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^22.13.5",
50
+ "jsdom": "^26.0.0",
51
+ "tsup": "^8.4.0",
52
+ "typescript": "^5.7.3",
53
+ "vitest": "^3.0.7"
54
+ }
55
+ }