torchlit 0.2.2 → 0.3.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.
Files changed (40) hide show
  1. package/README.md +19 -8
  2. package/dist/core/tour-service.d.ts +32 -0
  3. package/dist/core/tour-service.d.ts.map +1 -0
  4. package/dist/core/types.d.ts +32 -0
  5. package/dist/core/types.d.ts.map +1 -0
  6. package/dist/dom/deep-query.d.ts +2 -0
  7. package/dist/dom/deep-query.d.ts.map +1 -0
  8. package/dist/dom/positioning.d.ts +31 -0
  9. package/dist/dom/positioning.d.ts.map +1 -0
  10. package/dist/dom/scroll-manager.d.ts +4 -0
  11. package/dist/dom/scroll-manager.d.ts.map +1 -0
  12. package/dist/dom/target-resolver.d.ts +9 -0
  13. package/dist/dom/target-resolver.d.ts.map +1 -0
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/overlay/focus-manager.d.ts +8 -0
  19. package/dist/overlay/focus-manager.d.ts.map +1 -0
  20. package/dist/overlay/step-runner.d.ts +22 -0
  21. package/dist/overlay/step-runner.d.ts.map +1 -0
  22. package/dist/overlay/types.d.ts +8 -0
  23. package/dist/overlay/types.d.ts.map +1 -0
  24. package/dist/tour-overlay-CBkFKv12.js +1056 -0
  25. package/dist/tour-overlay-CBkFKv12.js.map +1 -0
  26. package/dist/tour-overlay.d.ts +11 -27
  27. package/dist/tour-overlay.d.ts.map +1 -1
  28. package/dist/tour-overlay.js +5 -948
  29. package/dist/tour-overlay.js.map +1 -1
  30. package/dist/tour-service.d.ts +2 -60
  31. package/dist/tour-service.d.ts.map +1 -1
  32. package/dist/tour-service.js +19 -48
  33. package/dist/tour-service.js.map +1 -1
  34. package/dist/types.d.ts +1 -105
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/utils/deep-query.d.ts +1 -20
  37. package/dist/utils/deep-query.d.ts.map +1 -1
  38. package/package.json +11 -3
  39. package/dist/deep-query-vkmcq1Dw.js +0 -16
  40. package/dist/deep-query-vkmcq1Dw.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tour-overlay-CBkFKv12.js","sources":["../src/dom/positioning.ts","../src/dom/scroll-manager.ts","../src/overlay/focus-manager.ts","../src/dom/deep-query.ts","../src/dom/target-resolver.ts","../src/overlay/step-runner.ts","../src/tour-overlay.ts"],"sourcesContent":["import type { TourPlacement } from '../types.js';\n\nexport const TOOLTIP_W = 320;\nexport const TOOLTIP_H_MAX = 270;\nexport const GAP = 16;\nexport const VIEWPORT_MARGIN = 24;\nexport const TOOLTIP_VERTICAL_OFFSET = 80;\n\nexport function fitsInViewport(\n rect: DOMRect,\n viewportHeight = window.innerHeight,\n): boolean {\n return rect.height + TOOLTIP_H_MAX + GAP * 2 < viewportHeight;\n}\n\nexport function bestPlacement(\n rect: DOMRect,\n preferred: TourPlacement,\n spotlightPadding: number,\n viewport = { width: window.innerWidth, height: window.innerHeight },\n): TourPlacement {\n const fits = (placement: TourPlacement): boolean => {\n switch (placement) {\n case 'bottom':\n return rect.bottom + spotlightPadding + GAP + TOOLTIP_H_MAX < viewport.height;\n case 'top':\n return rect.top - spotlightPadding - GAP - TOOLTIP_H_MAX > 0;\n case 'right':\n return rect.right + spotlightPadding + GAP + TOOLTIP_W < viewport.width;\n case 'left':\n return rect.left - spotlightPadding - GAP - TOOLTIP_W > 0;\n }\n };\n\n const opposite: Record<TourPlacement, TourPlacement> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n };\n\n const perpendicular: Record<TourPlacement, [TourPlacement, TourPlacement]> = {\n top: ['left', 'right'],\n bottom: ['left', 'right'],\n left: ['top', 'bottom'],\n right: ['top', 'bottom'],\n };\n\n if (fits(preferred)) return preferred;\n if (fits(opposite[preferred])) return opposite[preferred];\n\n for (const placement of perpendicular[preferred]) {\n if (fits(placement)) return placement;\n }\n\n return preferred;\n}\n\nexport function getTooltipPosition(\n rect: DOMRect,\n placement: TourPlacement,\n spotlightPadding: number,\n viewportHeight = window.innerHeight,\n): { top: number; left: number } {\n const visibleTop = Math.max(0, rect.top);\n const visibleBottom = Math.min(viewportHeight, rect.bottom);\n const visibleCenterY = (visibleTop + visibleBottom) / 2;\n\n switch (placement) {\n case 'right':\n return {\n top: visibleCenterY - TOOLTIP_VERTICAL_OFFSET,\n left: rect.right + spotlightPadding + GAP,\n };\n case 'left':\n return {\n top: visibleCenterY - TOOLTIP_VERTICAL_OFFSET,\n left: rect.left - spotlightPadding - GAP - TOOLTIP_W,\n };\n case 'bottom':\n return {\n top: rect.bottom + spotlightPadding + GAP,\n left: rect.left + rect.width / 2 - TOOLTIP_W / 2,\n };\n case 'top':\n return {\n top: rect.top - spotlightPadding - GAP,\n left: rect.left + rect.width / 2 - TOOLTIP_W / 2,\n };\n }\n}\n\nexport function clampToViewport(\n pos: { top: number; left: number },\n viewport = { width: window.innerWidth, height: window.innerHeight },\n): { top: number; left: number } {\n return {\n top: Math.max(\n VIEWPORT_MARGIN,\n Math.min(pos.top, viewport.height - TOOLTIP_H_MAX - VIEWPORT_MARGIN),\n ),\n left: Math.max(\n VIEWPORT_MARGIN,\n Math.min(pos.left, viewport.width - TOOLTIP_W - VIEWPORT_MARGIN),\n ),\n };\n}\n\nexport function getArrowClass(placement: TourPlacement): string {\n switch (placement) {\n case 'right':\n return 'arrow-right';\n case 'left':\n return 'arrow-left';\n case 'bottom':\n return 'arrow-bottom';\n case 'top':\n return 'arrow-top';\n default:\n return 'arrow-bottom';\n }\n}\n\nexport function getArrowOffset(\n targetRect: DOMRect,\n tooltipPos: { top: number; left: number },\n placement: TourPlacement,\n viewportHeight = window.innerHeight,\n): string {\n const arrowSize = 12;\n const minOffset = arrowSize + 8;\n\n if (placement === 'top' || placement === 'bottom') {\n const targetCenterX = targetRect.left + targetRect.width / 2;\n const offset = targetCenterX - tooltipPos.left;\n const clamped = Math.max(minOffset, Math.min(offset, TOOLTIP_W - minOffset));\n return `${clamped}px`;\n }\n\n const visibleTop = Math.max(0, targetRect.top);\n const visibleBottom = Math.min(viewportHeight, targetRect.bottom);\n const targetCenterY = (visibleTop + visibleBottom) / 2;\n const offset = targetCenterY - tooltipPos.top;\n const clamped = Math.max(minOffset, Math.min(offset, TOOLTIP_H_MAX - minOffset));\n return `${clamped}px`;\n}\n","import type { TourPlacement } from '../types.js';\nimport { GAP, TOOLTIP_H_MAX, fitsInViewport } from './positioning.js';\n\nexport function restoreScrollPosition(\n mode: 'restore' | 'top' | 'none',\n savedScrollY: number,\n): void {\n if (mode === 'restore') {\n window.scrollTo({ top: savedScrollY, behavior: 'smooth' });\n } else if (mode === 'top') {\n window.scrollTo({ top: 0, behavior: 'smooth' });\n }\n}\n\nexport function scrollAndSettle(\n element: Element,\n placement: TourPlacement,\n spotlightPadding: number,\n): Promise<void> {\n const initialRect = element.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n\n // Use the pre-scroll measurement only to decide fit and target offset.\n if (fitsInViewport(initialRect, viewportHeight)) {\n element.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'nearest',\n });\n } else {\n const desiredTop =\n placement === 'top'\n ? TOOLTIP_H_MAX + GAP + spotlightPadding\n : viewportHeight * 0.15;\n const scrollTarget = window.scrollY + initialRect.top - desiredTop;\n window.scrollTo({ top: Math.max(0, scrollTarget), behavior: 'smooth' });\n }\n\n return new Promise(resolve => {\n let lastTop = element.getBoundingClientRect().top;\n let stableFrames = 0;\n let rafId = 0;\n const maxWait = setTimeout(() => {\n cancelAnimationFrame(rafId);\n resolve();\n }, 1500);\n\n const poll = () => {\n const top = element.getBoundingClientRect().top;\n if (Math.abs(top - lastTop) < 1) {\n stableFrames += 1;\n } else {\n stableFrames = 0;\n }\n lastTop = top;\n\n if (stableFrames >= 3) {\n clearTimeout(maxWait);\n resolve();\n return;\n }\n\n rafId = requestAnimationFrame(poll);\n };\n\n rafId = requestAnimationFrame(poll);\n });\n}\n","export class FocusManager {\n private previouslyFocused: HTMLElement | null = null;\n\n capture(): void {\n if (document.activeElement instanceof HTMLElement) {\n this.previouslyFocused = document.activeElement;\n }\n }\n\n restore(): void {\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n }\n\n focusDialog(root: ShadowRoot | null): void {\n root\n ?.querySelector<HTMLElement>('.tour-tooltip, .tour-center-card')\n ?.focus();\n }\n\n trapFocus(event: KeyboardEvent, root: ShadowRoot | null): void {\n const container = root?.querySelector<HTMLElement>(\n '.tour-tooltip, .tour-center-card',\n );\n if (!container) return;\n\n const focusable = container.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = root?.activeElement;\n\n if (event.shiftKey) {\n if (activeElement === first) {\n event.preventDefault();\n last.focus();\n }\n return;\n }\n\n if (activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n}\n","export function deepQuery(\n selector: string,\n root: Element | Document | ShadowRoot = document.body,\n): Element | null {\n const found = root.querySelector(selector);\n if (found) return found;\n\n const children = root.querySelectorAll('*');\n for (const element of children) {\n if (element.shadowRoot) {\n const shadowResult = deepQuery(selector, element.shadowRoot);\n if (shadowResult) return shadowResult;\n }\n }\n\n return null;\n}\n","import type { TourStep } from '../types.js';\nimport { deepQuery } from './deep-query.js';\n\nconst DEFAULT_TARGET_ATTR = 'data-tour-id';\nconst DEFAULT_TIMEOUT = 3000;\n\nexport function resolveTargetSelector(\n targetId: string,\n targetAttribute = DEFAULT_TARGET_ATTR,\n): string {\n return `[${targetAttribute}=\"${targetId}\"]`;\n}\n\nexport function resolveTarget(\n targetId: string,\n targetAttribute = DEFAULT_TARGET_ATTR,\n root: Element | Document = document.body,\n): Element | null {\n if (!targetId || targetId === '_none_') return null;\n return deepQuery(resolveTargetSelector(targetId, targetAttribute), root);\n}\n\nexport async function waitForTarget(\n targetId: string,\n targetAttribute = DEFAULT_TARGET_ATTR,\n timeout = DEFAULT_TIMEOUT,\n): Promise<Element | null> {\n const existing = resolveTarget(targetId, targetAttribute);\n if (existing) return existing;\n\n return new Promise<Element | null>(resolve => {\n let resolved = false;\n const observer = new MutationObserver(() => {\n const element = resolveTarget(targetId, targetAttribute);\n if (!element) return;\n\n resolved = true;\n observer.disconnect();\n resolve(element);\n });\n\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n setTimeout(() => {\n if (resolved) return;\n\n observer.disconnect();\n resolve(resolveTarget(targetId, targetAttribute));\n }, timeout);\n });\n}\n\nexport function resolveStepTarget(\n step: Pick<TourStep, 'target'>,\n targetAttribute = DEFAULT_TARGET_ATTR,\n): { targetElement: Element | null; targetRect: DOMRect | null } {\n const targetElement = resolveTarget(step.target, targetAttribute);\n return {\n targetElement,\n targetRect: targetElement?.getBoundingClientRect() ?? null,\n };\n}\n","import type { TourSnapshot as CoreTourSnapshot } from '../core/types.js';\nimport { GAP, TOOLTIP_H_MAX } from '../dom/positioning.js';\nimport { scrollAndSettle } from '../dom/scroll-manager.js';\nimport { resolveStepTarget, waitForTarget } from '../dom/target-resolver.js';\nimport type { TourDefinition, TourStep } from '../types.js';\nimport type { ResolvedTourSnapshot } from './types.js';\n\nconst TARGET_CONTEXT_MARGIN = 32;\n\nexport interface StepRunnerOptions {\n getCurrentSnapshot: () => CoreTourSnapshot<TourStep> | null;\n getTour: (tourId: string) => TourDefinition | undefined;\n nextStep: () => void;\n spotlightPadding: number;\n targetAttribute: string;\n dispatchRouteChange: (route: string) => void;\n}\n\nexport class StepRunner {\n private autoAdvanceTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly options: StepRunnerOptions) {}\n\n clearAutoAdvance(): void {\n if (this.autoAdvanceTimer !== null) {\n clearTimeout(this.autoAdvanceTimer);\n this.autoAdvanceTimer = null;\n }\n }\n\n startAutoAdvance(ms: number): void {\n this.clearAutoAdvance();\n this.autoAdvanceTimer = setTimeout(() => {\n this.autoAdvanceTimer = null;\n this.options.nextStep();\n }, ms);\n }\n\n async prepareStep(\n snapshot: CoreTourSnapshot<TourStep>,\n ): Promise<ResolvedTourSnapshot | null> {\n if (snapshot.step.beforeShow) {\n try {\n await snapshot.step.beforeShow();\n } catch (error) {\n console.error('[torchlit] beforeShow hook failed:', error);\n }\n }\n\n if (snapshot.step.route) {\n this.options.dispatchRouteChange(snapshot.step.route);\n }\n\n if (snapshot.step.target && snapshot.step.target !== '_none_') {\n await waitForTarget(snapshot.step.target, this.options.targetAttribute);\n }\n\n const currentSnapshot = this.options.getCurrentSnapshot() ?? snapshot;\n const tour = this.options.getTour(currentSnapshot.tourId);\n if (!tour) return null;\n\n let resolved = this.resolveSnapshot(currentSnapshot, tour);\n\n if (resolved.targetElement && this.shouldScrollIntoView(resolved)) {\n await scrollAndSettle(\n resolved.targetElement,\n resolved.step.placement,\n this.options.spotlightPadding,\n );\n resolved = this.resolveSnapshot(\n this.options.getCurrentSnapshot() ?? currentSnapshot,\n tour,\n );\n }\n\n return resolved;\n }\n\n private resolveSnapshot(\n snapshot: CoreTourSnapshot<TourStep>,\n tour: TourDefinition,\n ): ResolvedTourSnapshot {\n const { targetElement, targetRect } = resolveStepTarget(\n snapshot.step,\n this.options.targetAttribute,\n );\n\n return {\n ...snapshot,\n tour,\n targetElement,\n targetRect,\n };\n }\n\n private shouldScrollIntoView(snapshot: ResolvedTourSnapshot): boolean {\n const rect = snapshot.targetRect;\n if (!rect) return false;\n\n const viewportHeight = window.innerHeight;\n const fits = rect.height + TOOLTIP_H_MAX + TARGET_CONTEXT_MARGIN < viewportHeight;\n const inView = fits\n ? rect.top >= 0 &&\n rect.bottom <= viewportHeight &&\n rect.left >= 0 &&\n rect.right <= window.innerWidth\n : snapshot.step.placement === 'top'\n ? rect.top >= TOOLTIP_H_MAX + GAP + this.options.spotlightPadding &&\n rect.top < viewportHeight\n : rect.top >= 0 && rect.top < viewportHeight;\n\n return !inView;\n }\n}\n","import { LitElement, html, css, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { keyed } from 'lit/directives/keyed.js';\nimport type { TourSnapshot as CoreTourSnapshot } from './core/types.js';\nimport {\n GAP,\n VIEWPORT_MARGIN,\n bestPlacement,\n clampToViewport,\n getArrowClass,\n getArrowOffset,\n getTooltipPosition,\n} from './dom/positioning.js';\nimport { restoreScrollPosition } from './dom/scroll-manager.js';\nimport { FocusManager } from './overlay/focus-manager.js';\nimport { StepRunner } from './overlay/step-runner.js';\nimport type { ResolvedTourSnapshot } from './overlay/types.js';\nimport type { TourService } from './tour-service.js';\nimport type { TourDefinition, TourPlacement, TourStep } from './types.js';\n\n/**\n * `<torchlit-overlay>` — Full-screen overlay that renders a spotlight cutout\n * around the current tour target, a tooltip with title / message / progress,\n * and navigation controls.\n *\n * Wire it to a `TourService` instance via the `service` property:\n *\n * ```html\n * <torchlit-overlay></torchlit-overlay>\n * ```\n * ```js\n * document.querySelector('torchlit-overlay').service = myTourService;\n * ```\n *\n * @fires tour-route-change - When a step has a `route` property, dispatched\n * with `{ route: string }` so the host app can switch views.\n *\n * @csspart backdrop - The semi-transparent overlay behind the spotlight.\n * @csspart spotlight - The cutout highlight around the target element.\n * @csspart tooltip - The floating tooltip card.\n * @csspart center-card - The centered card shown when there is no target.\n */\n@customElement('torchlit-overlay')\nexport class TorchlitOverlay extends LitElement {\n /* ── Styles ─────────────────────────────────────── */\n\n static override styles = css`\n :host {\n display: block;\n }\n\n /* ── Visually hidden (sr-only) ─────────────────── */\n\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ── Backdrop ──────────────────────────────────── */\n\n .tour-backdrop {\n position: fixed;\n inset: 0;\n z-index: 9998;\n pointer-events: auto;\n opacity: 0;\n transition: opacity 0.3s ease;\n }\n\n .tour-backdrop.visible {\n opacity: 1;\n }\n\n /* ── Spotlight (box-shadow cutout) ─────────────── */\n\n .tour-spotlight {\n position: fixed;\n z-index: 9999;\n border-radius: var(--tour-spotlight-radius, var(--radius-lg, 0.75rem));\n box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);\n transition: top 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n left 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n height 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: none;\n }\n\n /* Subtle pulsing ring around spotlight */\n .tour-spotlight::after {\n content: '';\n position: absolute;\n inset: -4px;\n border-radius: inherit;\n border: 2px solid var(--tour-primary, var(--primary, #F26122));\n opacity: 0.5;\n animation: spotlightPulse 2s ease-in-out infinite;\n }\n\n @keyframes spotlightPulse {\n 0%, 100% { opacity: 0.3; transform: scale(1); }\n 50% { opacity: 0.7; transform: scale(1.01); }\n }\n\n /* ── Tooltip ───────────────────────────────────── */\n\n .tour-tooltip {\n position: fixed;\n z-index: 10000;\n box-sizing: border-box;\n width: 320px;\n background: var(--tour-card, var(--card, #fff));\n border: 1px solid var(--tour-border, var(--border, #e5e5e5));\n border-radius: var(--tour-tooltip-radius, var(--radius-lg, 0.75rem));\n box-shadow: 0 20px 40px -8px rgba(0, 0, 0, 0.2),\n 0 8px 16px -4px rgba(0, 0, 0, 0.1);\n padding: 1.25rem;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(8px) scale(0.96);\n transition: opacity 0.25s ease, transform 0.25s ease,\n top 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n left 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .tour-tooltip:focus {\n outline: none;\n }\n\n .tour-tooltip.visible {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n /* Arrow — position along edge is set via inline --arrow-offset */\n .tour-arrow {\n position: absolute;\n width: 12px;\n height: 12px;\n background: var(--tour-card, var(--card, #fff));\n border: 1px solid var(--tour-border, var(--border, #e5e5e5));\n transform: rotate(45deg);\n }\n\n /* tooltip is above target → arrow at bottom of tooltip pointing down */\n .tour-arrow.arrow-top {\n bottom: -7px;\n left: var(--arrow-offset, 50%);\n margin-left: -6px;\n border-top: none;\n border-left: none;\n }\n\n /* tooltip is below target → arrow at top of tooltip pointing up */\n .tour-arrow.arrow-bottom {\n top: -7px;\n left: var(--arrow-offset, 50%);\n margin-left: -6px;\n border-bottom: none;\n border-right: none;\n }\n\n /* tooltip is right of target → arrow on left edge pointing left */\n .tour-arrow.arrow-left {\n right: -7px;\n top: var(--arrow-offset, 50%);\n margin-top: -6px;\n border-bottom: none;\n border-left: none;\n }\n\n /* tooltip is left of target → arrow on right edge pointing right */\n .tour-arrow.arrow-right {\n left: -7px;\n top: var(--arrow-offset, 50%);\n margin-top: -6px;\n border-top: none;\n border-right: none;\n }\n\n /* ── Tooltip content ──────────────────────────── */\n\n .tour-step-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--tour-primary, var(--primary, #F26122));\n margin-bottom: 0.5rem;\n }\n\n .tour-title {\n margin: 0 0 0.375rem;\n font-size: 1rem;\n font-weight: 600;\n color: var(--tour-foreground, var(--foreground, #1a1a1a));\n line-height: 1.3;\n }\n\n .tour-message {\n margin: 0 0 1rem;\n font-size: 0.8125rem;\n color: var(--tour-muted-foreground, var(--muted-foreground, #737373));\n line-height: 1.55;\n }\n\n /* ── Progress dots ────────────────────────────── */\n\n .tour-progress {\n display: flex;\n align-items: center;\n gap: 0.375rem;\n margin-bottom: 1rem;\n }\n\n .tour-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--tour-muted, var(--muted, #e5e5e5));\n transition: background 0.2s, transform 0.2s;\n }\n\n .tour-dot.active {\n background: var(--tour-primary, var(--primary, #F26122));\n transform: scale(1.3);\n }\n\n .tour-dot.completed {\n background: var(--tour-primary, var(--primary, #F26122));\n opacity: 0.5;\n }\n\n /* ── Auto-advance progress bar ────────────────── */\n\n .tour-auto-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n max-width: 100%;\n height: 3px;\n background: var(--tour-primary, var(--primary, #F26122));\n opacity: 0.7;\n border-radius: 0 0 var(--tour-tooltip-radius, var(--radius-lg, 0.75rem)) var(--tour-tooltip-radius, var(--radius-lg, 0.75rem));\n }\n\n @keyframes autoAdvanceFill {\n from { width: 0%; }\n to { width: 100%; }\n }\n\n /* ── Footer buttons ───────────────────────────── */\n\n .tour-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .tour-skip {\n font-size: 0.75rem;\n color: var(--tour-muted-foreground, var(--muted-foreground, #737373));\n background: none;\n border: none;\n cursor: pointer;\n padding: 0.25rem 0;\n transition: color 0.15s;\n }\n\n .tour-skip:hover {\n color: var(--tour-foreground, var(--foreground, #1a1a1a));\n }\n\n .tour-nav {\n display: flex;\n gap: 0.5rem;\n }\n\n .tour-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.4rem 0.875rem;\n font-size: 0.8125rem;\n font-weight: 500;\n border-radius: var(--tour-btn-radius, var(--radius-md, 0.5rem));\n border: 1px solid var(--tour-border, var(--border, #e5e5e5));\n background: var(--tour-background, var(--background, #fff));\n color: var(--tour-foreground, var(--foreground, #1a1a1a));\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .tour-btn:hover {\n background: var(--tour-muted, var(--muted, #f5f5f5));\n }\n\n .tour-btn:focus-visible {\n outline: 2px solid var(--tour-primary, var(--primary, #F26122));\n outline-offset: 2px;\n }\n\n .tour-btn.primary {\n background: var(--tour-primary, var(--primary, #F26122));\n color: var(--tour-primary-foreground, var(--primary-foreground, #fff));\n border-color: var(--tour-primary, var(--primary, #F26122));\n }\n\n .tour-btn.primary:hover {\n opacity: 0.9;\n }\n\n .tour-btn svg {\n width: 14px;\n height: 14px;\n }\n\n /* ── Welcome / no-target step ─────────────────── */\n\n .tour-center-card {\n position: fixed;\n z-index: 10000;\n box-sizing: border-box;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.96);\n width: 400px;\n max-width: calc(100vw - 2rem);\n background: var(--tour-card, var(--card, #fff));\n border: 1px solid var(--tour-border, var(--border, #e5e5e5));\n border-radius: var(--tour-card-radius, var(--radius-xl, 1rem));\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n padding: 2rem;\n text-align: center;\n pointer-events: auto;\n opacity: 0;\n transition: opacity 0.3s ease, transform 0.3s ease;\n }\n\n .tour-center-card:focus {\n outline: none;\n }\n\n .tour-center-card.visible {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n\n .tour-center-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 1rem;\n background: var(--tour-primary, var(--primary, #F26122));\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--tour-primary-foreground, var(--primary-foreground, #fff));\n }\n `;\n\n /* ── Properties ──────────────────────────────────── */\n\n /**\n * The `TourService` instance this overlay subscribes to.\n * Must be set before the overlay will render anything.\n */\n @property({ attribute: false })\n service!: TourService<TourStep>;\n\n @state() private snapshot: ResolvedTourSnapshot | null = null;\n @state() private visible = false;\n\n private unsubscribe?: () => void;\n private teardownTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly focusManager = new FocusManager();\n private stepRunner: StepRunner | null = null;\n private lastResolvedPlacement: TourPlacement = 'bottom';\n private scrollRafId = 0;\n private savedScrollY = 0;\n private activeTour: TourDefinition | null = null;\n private resolvedTargetElement: Element | null = null;\n private changeToken = 0;\n\n /* ── Lifecycle ──────────────────────────────────── */\n\n override connectedCallback() {\n super.connectedCallback();\n if (this.service) {\n this.attachService();\n }\n window.addEventListener('resize', this.handleResize);\n window.addEventListener('scroll', this.handleScroll, true);\n window.addEventListener('keydown', this.handleKeydown);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.unsubscribe?.();\n this.clearAutoAdvance();\n if (this.scrollRafId) cancelAnimationFrame(this.scrollRafId);\n if (this.teardownTimer) clearTimeout(this.teardownTimer);\n window.removeEventListener('resize', this.handleResize);\n window.removeEventListener('scroll', this.handleScroll, true);\n window.removeEventListener('keydown', this.handleKeydown);\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('service') && this.service) {\n this.unsubscribe?.();\n this.attachService();\n }\n\n if (this.visible && this.snapshot) {\n this.adjustTooltipPosition();\n this.updateComplete.then(() => {\n this.focusManager.focusDialog(this.shadowRoot);\n });\n }\n }\n\n /**\n * After rendering, measure the tooltip's actual height and correct\n * its position for 'top' placement (the only one that depends on\n * tooltip height). This eliminates hardcoded height estimates.\n */\n private adjustTooltipPosition() {\n if (this.lastResolvedPlacement !== 'top') return;\n\n const tooltip = this.shadowRoot?.querySelector<HTMLElement>('.tour-tooltip');\n const targetRect = this.snapshot?.targetRect;\n if (!tooltip || !targetRect) return;\n\n const PADDING = this.service?.spotlightPadding ?? 10;\n const actualHeight = tooltip.getBoundingClientRect().height;\n const correctTop = targetRect.top - PADDING - GAP - actualHeight;\n const clampedTop = Math.max(VIEWPORT_MARGIN, correctTop);\n\n tooltip.style.top = `${clampedTop}px`;\n }\n\n private attachService() {\n this.stepRunner = new StepRunner({\n getCurrentSnapshot: () => this.service.getSnapshot() as CoreTourSnapshot<TourStep> | null,\n getTour: tourId => this.getTourDefinition(tourId),\n nextStep: () => this.service.nextStep(),\n spotlightPadding: this.service.spotlightPadding,\n targetAttribute: this.service.targetAttribute,\n dispatchRouteChange: route => this.dispatchRouteChange(route),\n });\n\n this.unsubscribe = this.service.subscribe(snapshot => {\n void this.handleTourChange(snapshot as CoreTourSnapshot<TourStep> | null);\n });\n }\n\n private clearAutoAdvance() {\n this.stepRunner?.clearAutoAdvance();\n }\n\n private startAutoAdvance(ms: number) {\n this.stepRunner?.startAutoAdvance(ms);\n }\n\n private async handleTourChange(snapshot: CoreTourSnapshot<TourStep> | null) {\n const token = ++this.changeToken;\n this.clearAutoAdvance();\n if (this.teardownTimer) {\n clearTimeout(this.teardownTimer);\n this.teardownTimer = null;\n }\n\n if (!snapshot) {\n const endingTour = this.activeTour;\n this.visible = false;\n this.activeTour = null;\n this.resolvedTargetElement = null;\n this.teardownTimer = setTimeout(() => {\n if (token !== this.changeToken) return;\n\n this.snapshot = null;\n this.focusManager.restore();\n restoreScrollPosition(endingTour?.onEndScroll ?? 'restore', this.savedScrollY);\n }, 300);\n return;\n }\n\n const isNewTour = snapshot.tourId !== this.activeTour?.id;\n if (!this.activeTour) {\n this.focusManager.capture();\n }\n if (isNewTour) {\n this.savedScrollY = window.scrollY;\n }\n\n const resolved = await this.stepRunner?.prepareStep(snapshot);\n if (!resolved || token !== this.changeToken) return;\n\n this.activeTour = resolved.tour;\n this.snapshot = resolved;\n this.resolvedTargetElement = resolved.targetElement;\n\n requestAnimationFrame(() => {\n if (token !== this.changeToken) return;\n\n this.visible = true;\n if (resolved.step.autoAdvance) {\n this.startAutoAdvance(resolved.step.autoAdvance);\n }\n });\n }\n\n private dispatchRouteChange(route: string) {\n this.dispatchEvent(\n new CustomEvent('tour-route-change', {\n detail: { route },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private getTourDefinition(tourId: string): TourDefinition | undefined {\n return this.service?.getTour(tourId) as TourDefinition | undefined;\n }\n\n private refreshSnapshotFromTarget() {\n if (!this.snapshot) return;\n\n const targetElement = this.resolvedTargetElement?.isConnected\n ? this.resolvedTargetElement\n : null;\n\n this.snapshot = {\n ...this.snapshot,\n targetElement,\n targetRect: targetElement?.getBoundingClientRect() ?? null,\n };\n }\n\n private handleResize = () => {\n this.refreshSnapshotFromTarget();\n };\n\n private handleScroll = () => {\n if (!this.snapshot || this.scrollRafId) return;\n\n this.scrollRafId = requestAnimationFrame(() => {\n this.scrollRafId = 0;\n this.refreshSnapshotFromTarget();\n });\n };\n\n private handleKeydown = (e: KeyboardEvent) => {\n if (!this.snapshot || !this.service) return;\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.clearAutoAdvance();\n this.service.skipTour();\n } else if (e.key === 'ArrowRight' || e.key === 'Enter') {\n e.preventDefault();\n this.clearAutoAdvance();\n this.service.nextStep();\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.clearAutoAdvance();\n this.service.prevStep();\n } else if (e.key === 'Tab') {\n this.focusManager.trapFocus(e, this.shadowRoot);\n }\n };\n\n private handleBackdropClick = () => {\n this.clearAutoAdvance();\n this.service?.skipTour();\n };\n\n /**\n * Determine the best placement for the tooltip, flipping when the preferred\n * placement would clip the viewport. Tries: preferred → opposite → perpendicular.\n */\n private bestPlacement(rect: DOMRect, preferred: TourPlacement): TourPlacement {\n return bestPlacement(rect, preferred, this.service?.spotlightPadding ?? 10);\n }\n\n private getTooltipPosition(rect: DOMRect, placement: TourPlacement): { top: number; left: number } {\n return getTooltipPosition(rect, placement, this.service?.spotlightPadding ?? 10);\n }\n\n private clampToViewport(pos: { top: number; left: number }): { top: number; left: number } {\n return clampToViewport(pos);\n }\n\n private getArrowClass(placement: TourPlacement): string {\n return getArrowClass(placement);\n }\n\n /**\n * Compute the arrow's offset along the tooltip edge so it points at\n * the center of the target element, clamped to stay within the tooltip.\n */\n private getArrowOffset(\n targetRect: DOMRect,\n tooltipPos: { top: number; left: number },\n placement: TourPlacement,\n ): string {\n return getArrowOffset(targetRect, tooltipPos, placement);\n }\n\n /* ── Render ─────────────────────────────────────── */\n\n override render() {\n if (!this.snapshot) return html``;\n\n const { step, stepIndex, totalSteps, targetRect } = this.snapshot;\n\n // No target found — show centered card\n if (!targetRect) {\n return this.renderCenteredStep(step, stepIndex, totalSteps);\n }\n\n const PADDING = this.service?.spotlightPadding ?? 10;\n\n // Per-step spotlight border-radius override\n const spotlightRadius = step.spotlightBorderRadius\n ? `border-radius: ${step.spotlightBorderRadius};`\n : '';\n\n const spotlightStyle = `\n top: ${targetRect.top - PADDING}px;\n left: ${targetRect.left - PADDING}px;\n width: ${targetRect.width + PADDING * 2}px;\n height: ${targetRect.height + PADDING * 2}px;\n ${spotlightRadius}\n `;\n\n // Smart placement — flip if the preferred side clips\n const resolved = this.bestPlacement(targetRect, step.placement);\n this.lastResolvedPlacement = resolved;\n\n const tooltipPos = this.clampToViewport(\n this.getTooltipPosition(targetRect, resolved),\n );\n const arrowOffset = this.getArrowOffset(targetRect, tooltipPos, resolved);\n const tooltipStyle = `top: ${tooltipPos.top}px; left: ${tooltipPos.left}px;`;\n const stepLabel = `Step ${stepIndex + 1} of ${totalSteps}: ${step.title}`;\n\n return html`\n <!-- Screen reader announcement -->\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n ${stepLabel}\n </div>\n\n <div\n class=\"tour-backdrop ${this.visible ? 'visible' : ''}\"\n part=\"backdrop\"\n @click=${this.handleBackdropClick}\n ></div>\n\n <div class=\"tour-spotlight\" part=\"spotlight\" style=${spotlightStyle}></div>\n\n <div\n class=\"tour-tooltip ${this.visible ? 'visible' : ''}\"\n part=\"tooltip\"\n style=${tooltipStyle}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"${step.title}\"\n aria-describedby=\"tour-desc\"\n tabindex=\"-1\"\n >\n <div class=\"tour-arrow ${this.getArrowClass(resolved)}\" style=\"--arrow-offset: ${arrowOffset}\"></div>\n\n <div class=\"tour-step-badge\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"></path>\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\n </svg>\n Step ${stepIndex + 1} of ${totalSteps}\n </div>\n\n <h3 class=\"tour-title\">${step.title}</h3>\n <div class=\"tour-message\" id=\"tour-desc\">${step.message}</div>\n\n ${this.renderProgressDots(stepIndex, totalSteps)}\n ${this.renderFooter(stepIndex, totalSteps)}\n ${this.renderAutoProgress(step, stepIndex)}\n </div>\n `;\n }\n\n private renderProgressDots(current: number, total: number) {\n if (total <= 1) return nothing;\n return html`\n <div class=\"tour-progress\" role=\"group\" aria-label=\"Tour progress\">\n ${Array.from({ length: total }, (_, i) => html`\n <div\n class=\"tour-dot ${i === current ? 'active' : i < current ? 'completed' : ''}\"\n role=\"presentation\"\n ></div>\n `)}\n </div>\n `;\n }\n\n private renderFooter(\n stepIndex: number,\n totalSteps: number,\n finishLabel = 'Finish',\n finishAriaLabel = 'Finish tour',\n showNavIcons = true,\n ) {\n return html`\n <div class=\"tour-footer\">\n <button\n class=\"tour-skip\"\n aria-label=\"Skip tour\"\n @click=${() => { this.clearAutoAdvance(); this.service.skipTour(); }}\n >\n Skip tour\n </button>\n <div class=\"tour-nav\">\n ${stepIndex > 0 ? html`\n <button\n class=\"tour-btn\"\n aria-label=\"Go to previous step\"\n @click=${() => { this.clearAutoAdvance(); this.service.prevStep(); }}\n >\n ${showNavIcons ? html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <polyline points=\"15 18 9 12 15 6\"></polyline>\n </svg>\n ` : nothing}\n Back\n </button>\n ` : nothing}\n <button\n class=\"tour-btn primary\"\n aria-label=\"${stepIndex === totalSteps - 1 ? finishAriaLabel : 'Go to next step'}\"\n @click=${() => { this.clearAutoAdvance(); this.service.nextStep(); }}\n >\n ${stepIndex === totalSteps - 1 ? finishLabel : 'Next'}\n ${stepIndex < totalSteps - 1 ? html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n ` : showNavIcons ? html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n ` : nothing}\n </button>\n </div>\n </div>\n `;\n }\n\n private renderAutoProgress(step: TourStep, stepIndex: number) {\n if (!step.autoAdvance) return nothing;\n return keyed(stepIndex, html`\n <div\n class=\"tour-auto-progress\"\n style=\"animation: autoAdvanceFill ${step.autoAdvance}ms linear forwards;\"\n aria-hidden=\"true\"\n ></div>\n `);\n }\n\n private renderCenteredStep(step: TourStep, stepIndex: number, totalSteps: number) {\n const stepLabel = `Step ${stepIndex + 1} of ${totalSteps}: ${step.title}`;\n\n return html`\n <!-- Screen reader announcement -->\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n ${stepLabel}\n </div>\n\n <div\n class=\"tour-backdrop ${this.visible ? 'visible' : ''}\"\n part=\"backdrop\"\n @click=${this.handleBackdropClick}\n ></div>\n\n <div\n class=\"tour-center-card ${this.visible ? 'visible' : ''}\"\n part=\"center-card\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"${step.title}\"\n aria-describedby=\"tour-desc-center\"\n tabindex=\"-1\"\n >\n <div class=\"tour-center-icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"></path>\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"></line>\n </svg>\n </div>\n\n <h3 class=\"tour-title\">${step.title}</h3>\n <div class=\"tour-message\" id=\"tour-desc-center\">${step.message}</div>\n\n ${this.renderProgressDots(stepIndex, totalSteps)}\n ${this.renderFooter(stepIndex, totalSteps, \"Let's go!\", 'Start the tour', false)}\n ${this.renderAutoProgress(step, stepIndex)}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'torchlit-overlay': TorchlitOverlay;\n }\n}\n"],"names":["offset","clamped"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  import type { TourService } from './tour-service.js';
3
+ import type { TourStep } from './types.js';
3
4
  /**
4
5
  * `<torchlit-overlay>` — Full-screen overlay that renders a spotlight cutout
5
6
  * around the current tour target, a tooltip with title / message / progress,
@@ -28,16 +29,19 @@ export declare class TorchlitOverlay extends LitElement {
28
29
  * The `TourService` instance this overlay subscribes to.
29
30
  * Must be set before the overlay will render anything.
30
31
  */
31
- service: TourService;
32
+ service: TourService<TourStep>;
32
33
  private snapshot;
33
34
  private visible;
34
35
  private unsubscribe?;
35
- private previouslyFocused;
36
- private autoAdvanceTimer;
36
+ private teardownTimer;
37
+ private readonly focusManager;
38
+ private stepRunner;
37
39
  private lastResolvedPlacement;
38
40
  private scrollRafId;
39
41
  private savedScrollY;
40
- private activeTourId;
42
+ private activeTour;
43
+ private resolvedTargetElement;
44
+ private changeToken;
41
45
  connectedCallback(): void;
42
46
  disconnectedCallback(): void;
43
47
  updated(changed: Map<string, unknown>): void;
@@ -50,34 +54,14 @@ export declare class TorchlitOverlay extends LitElement {
50
54
  private attachService;
51
55
  private clearAutoAdvance;
52
56
  private startAutoAdvance;
53
- /**
54
- * Wait for a target element to appear in the DOM using a MutationObserver.
55
- * Resolves as soon as `deepQuery` finds the target, or after `timeout` ms.
56
- */
57
- private waitForTarget;
58
- /**
59
- * Whether the target element (plus its tooltip) fits comfortably inside the
60
- * viewport. When it doesn't, we only need the top of the target visible —
61
- * the tooltip tracks scroll, so the user can explore the rest naturally.
62
- */
63
- private fitsInViewport;
64
57
  private handleTourChange;
65
- /**
66
- * Scroll an element into view and wait for the scroll to finish.
67
- *
68
- * Small elements that fit (with their tooltip) are centered in the viewport.
69
- * Large elements are scrolled with a **placement-aware** offset so there is
70
- * room for the tooltip on the preferred side. When `placement` is `'top'`,
71
- * we reserve enough space above the target for the tooltip; for other
72
- * placements the tooltip goes below or beside, so a smaller offset suffices.
73
- */
74
- private scrollAndSettle;
58
+ private dispatchRouteChange;
59
+ private getTourDefinition;
60
+ private refreshSnapshotFromTarget;
75
61
  private handleResize;
76
- /** Throttled scroll handler — refreshes the snapshot once per frame. */
77
62
  private handleScroll;
78
63
  private handleKeydown;
79
64
  private handleBackdropClick;
80
- private trapFocus;
81
65
  /**
82
66
  * Determine the best placement for the tooltip, flipping when the preferred
83
67
  * placement would clip the viewport. Tries: preferred → opposite → perpendicular.
@@ -1 +1 @@
1
- {"version":3,"file":"tour-overlay.d.ts","sourceRoot":"","sources":["../src/tour-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAIrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAG7C,OAAgB,MAAM,0BAkUpB;IAIF;;;OAGG;IAEH,OAAO,EAAG,WAAW,CAAC;IAEb,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,qBAAqB,CAA2B;IACxD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAuB;IAIlC,iBAAiB;IAUjB,oBAAoB;IAUpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAoB9C;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,gBAAgB;IAUxB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAsCrB;;;;OAIG;IACH,OAAO,CAAC,cAAc;YAMR,gBAAgB;IA+F9B;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAmDvB,OAAO,CAAC,YAAY,CAIlB;IAEF,wEAAwE;IACxE,OAAO,CAAC,YAAY,CAQlB;IAEF,OAAO,CAAC,aAAa,CAmBnB;IAEF,OAAO,CAAC,mBAAmB,CAGzB;IAIF,OAAO,CAAC,SAAS;IA6BjB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAsCrB,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,aAAa;IAUrB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA2Bb,MAAM;IAiFf,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,YAAY;IAoDpB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,kBAAkB;CAyC3B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,eAAe,CAAC;KACrC;CACF"}
1
+ {"version":3,"file":"tour-overlay.d.ts","sourceRoot":"","sources":["../src/tour-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAiBrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAiC,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAG7C,OAAgB,MAAM,0BAkUpB;IAIF;;;OAGG;IAEH,OAAO,EAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEvB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,qBAAqB,CAA2B;IACxD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,WAAW,CAAK;IAIf,iBAAiB;IAUjB,oBAAoB;IAWpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAc9C;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,gBAAgB;YAIV,gBAAgB;IAgD9B,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,YAAY,CAElB;IAEF,OAAO,CAAC,YAAY,CAOlB;IAEF,OAAO,CAAC,aAAa,CAkBnB;IAEF,OAAO,CAAC,mBAAmB,CAGzB;IAEF;;;OAGG;IACH,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAUb,MAAM;IAiFf,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,YAAY;IAoDpB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,kBAAkB;CAyC3B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,eAAe,CAAC;KACrC;CACF"}