saccade 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/react/Saccade.tsx","../src/react/SaccadeContext.tsx","../src/core/timing.ts","../src/core/recorder.ts","../src/core/scrubber.ts","../src/core/export.ts","../src/core/engine.ts","../src/react/SaccadePanel.tsx","../src/react/Timeline.tsx","../src/react/SpeedControl.tsx","../src/react/constants.ts","../src/react/useTimeline.ts","../src/react/useSpeed.ts","../src/react/styles.ts"],"sourcesContent":["// React components\nexport { Saccade, type SaccadeProps, type SaccadePosition } from './react/Saccade'\nexport { SaccadeProvider, useSaccadeEngine } from './react/SaccadeContext'\nexport { useTimeline } from './react/useTimeline'\nexport { useSpeed } from './react/useSpeed'\n\n// Core engine (re-export for convenience)\nexport { SaccadeEngine, type SaccadeState } from './core/engine'\n\n// Types\nexport type {\n AnimationInfo,\n ExportFilter,\n FrameSnapshot,\n OutputDetailLevel,\n Rect,\n TimelineCapture,\n TimelineExport\n} from './core/types'\n","import { useRef, useState, useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { SaccadeProvider } from './SaccadeContext'\nimport { SaccadePanel } from './SaccadePanel'\nimport { PANEL_STYLES } from './styles'\n\nexport type SaccadePosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n\nexport type SaccadeProps = {\n /** Panel position. Default: 'bottom-left' */\n position?: SaccadePosition\n}\n\nexport function Saccade({ position = 'bottom-left' }: SaccadeProps) {\n const hostRef = useRef<HTMLDivElement>(null)\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n\n useEffect(() => {\n const host = hostRef.current\n if (!host || host.shadowRoot) {\n if (host?.shadowRoot) setShadowRoot(host.shadowRoot)\n return\n }\n\n const shadow = host.attachShadow({ mode: 'open' })\n\n // Inject styles into shadow root\n const style = document.createElement('style')\n style.textContent = PANEL_STYLES\n shadow.appendChild(style)\n\n // Create mount point\n const mount = document.createElement('div')\n shadow.appendChild(mount)\n\n setShadowRoot(shadow)\n }, [])\n\n const positionOffset = position === 'top-left' ? { top: 20, left: 20 }\n : position === 'top-right' ? { top: 20, right: 20 }\n : position === 'bottom-left' ? { bottom: 20, left: 20 }\n : { bottom: 20, right: 20 }\n\n return (\n <div\n ref={hostRef}\n data-lapse-panel=\"\"\n style={{\n position: 'fixed',\n zIndex: 2147483647, // max int — must sit above the scrub blocker (z-index: 999999)\n pointerEvents: 'auto',\n ...positionOffset\n }}\n >\n {shadowRoot && createPortal(\n <SaccadeProvider>\n <SaccadePanel />\n </SaccadeProvider>,\n shadowRoot.lastElementChild || shadowRoot\n )}\n </div>\n )\n}\n","import { createContext, useContext, useRef, type ReactNode } from 'react'\nimport { SaccadeEngine } from '../core/engine'\n\nconst SaccadeContext = createContext<SaccadeEngine | null>(null)\n\nexport function SaccadeProvider({ children }: { children: ReactNode }) {\n const engineRef = useRef<SaccadeEngine | null>(null)\n if (!engineRef.current) {\n engineRef.current = new SaccadeEngine()\n }\n return (\n <SaccadeContext.Provider value={engineRef.current}>\n {children}\n </SaccadeContext.Provider>\n )\n}\n\nexport function useSaccadeEngine(): SaccadeEngine {\n const engine = useContext(SaccadeContext)\n if (!engine) throw new Error('useSaccadeEngine must be used within <SaccadeProvider>')\n return engine\n}\n","/**\n * Timing controller — patches all JS timing APIs to respect a speed factor.\n *\n * At 0.5x speed, a 100ms setTimeout becomes 200ms real time, and\n * performance.now() / rAF timestamps advance at half rate.\n */\n\nexport class TimingController {\n private speed = 1\n private realBaseline: number\n private virtualBaseline = 0\n private intervalMap = new Map<number, { handler: TimerHandler; delay: number; realId: number }>()\n private nextIntervalId = 1_000_000\n private mediaObserver: MutationObserver | null = null\n private animObserver: number | null = null\n private _origAnimate: typeof Element.prototype.animate | null = null\n private installed = false\n\n // Preserved originals\n private _raf: typeof requestAnimationFrame\n private _caf: typeof cancelAnimationFrame\n private _setTimeout: typeof setTimeout\n private _clearTimeout: typeof clearTimeout\n private _setInterval: typeof setInterval\n private _clearInterval: typeof clearInterval\n private _perfNow: () => number\n private _dateNow: () => number\n\n constructor() {\n this._raf = requestAnimationFrame.bind(window)\n this._caf = cancelAnimationFrame.bind(window)\n this._setTimeout = setTimeout.bind(window)\n this._clearTimeout = clearTimeout.bind(window)\n this._setInterval = setInterval.bind(window)\n this._clearInterval = clearInterval.bind(window)\n this._perfNow = performance.now.bind(performance)\n this._dateNow = Date.now\n this.realBaseline = this._perfNow()\n }\n\n private getVirtualTime(): number {\n const realElapsed = this._perfNow() - this.realBaseline\n return this.virtualBaseline + realElapsed * this.speed\n }\n\n private reanchor(): void {\n const virtualNow = this.getVirtualTime()\n this.realBaseline = this._perfNow()\n this.virtualBaseline = virtualNow\n }\n\n /** Install timing patches. Safe to call multiple times. */\n install(): void {\n if (this.installed) return\n this.installed = true\n\n const self = this\n\n // Expose original rAF for the recorder's capture loop\n ;(window as any).__LAPSE_ORIGINAL_RAF__ = this._raf\n\n // Intercept Element.prototype.animate to set playbackRate on creation\n const origAnimate = Element.prototype.animate\n this._origAnimate = origAnimate\n Element.prototype.animate = function (...args: Parameters<typeof origAnimate>) {\n const anim = origAnimate.apply(this, args)\n if (self.speed !== 1) {\n anim.playbackRate = self.speed || 0.001\n }\n return anim\n }\n\n // performance.now()\n performance.now = () => self.getVirtualTime()\n\n // Date.now()\n const dateBaseline = this._dateNow()\n Date.now = () => dateBaseline + self.getVirtualTime()\n\n // requestAnimationFrame\n window.requestAnimationFrame = (callback: FrameRequestCallback): number => {\n return self._raf(() => {\n callback(self.getVirtualTime())\n })\n }\n window.cancelAnimationFrame = this._caf\n\n // setTimeout\n window.setTimeout = ((handler: TimerHandler, delay?: number, ...args: any[]): number => {\n const scaledDelay = (delay ?? 0) / (self.speed || 1)\n return self._setTimeout(handler, scaledDelay, ...args) as unknown as number\n }) as typeof window.setTimeout\n\n window.clearTimeout = this._clearTimeout\n\n // setInterval — re-register on each tick to pick up speed changes\n window.setInterval = ((handler: TimerHandler, delay?: number, ...args: any[]): number => {\n const id = self.nextIntervalId++\n const baseDelay = delay ?? 0\n\n function tick() {\n const scaledDelay = baseDelay / (self.speed || 1)\n const realId = self._setTimeout(() => {\n if (typeof handler === 'function') {\n ;(handler as Function)(...args)\n }\n if (self.intervalMap.has(id)) tick()\n }, scaledDelay) as unknown as number\n const entry = self.intervalMap.get(id)\n if (entry) entry.realId = realId\n }\n\n self.intervalMap.set(id, { handler, delay: baseDelay, realId: 0 })\n tick()\n return id\n }) as typeof window.setInterval\n\n window.clearInterval = ((id?: number): void => {\n if (id == null) return\n const entry = self.intervalMap.get(id)\n if (entry) {\n self._clearTimeout(entry.realId as any)\n self.intervalMap.delete(id)\n } else {\n self._clearInterval(id)\n }\n }) as typeof window.clearInterval\n\n // Media elements\n this.mediaObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (node instanceof HTMLVideoElement || node instanceof HTMLAudioElement) {\n node.playbackRate = self.speed\n }\n }\n }\n })\n if (document.body) {\n this.mediaObserver.observe(document.body, { childList: true, subtree: true })\n }\n }\n\n /** Set playback speed. Requires install() first. */\n setSpeed(newSpeed: number): void {\n if (!this.installed) this.install()\n this.reanchor()\n this.speed = newSpeed\n // Patch existing media elements\n document.querySelectorAll('video, audio').forEach((el) => {\n ;(el as HTMLMediaElement).playbackRate = newSpeed\n })\n // Set playbackRate on all running CSS transitions and animations\n this.patchAnimations()\n }\n\n /** Patch playbackRate on all active CSS transitions/animations via WAAPI. */\n private patchAnimations(): void {\n try {\n const anims = document.getAnimations()\n for (const anim of anims) {\n // Skip animations on Lapse's own UI\n const target = (anim.effect as KeyframeEffect)?.target as HTMLElement | null\n if (target?.closest?.('[data-lapse-panel]')) continue\n anim.playbackRate = this.speed || 0.001 // 0 pauses, use near-zero instead\n }\n } catch {}\n\n // Also watch for new animations starting\n if (!this.animObserver) {\n this.animObserver = this._setInterval(() => {\n if (!this.installed) return\n try {\n const anims = document.getAnimations()\n for (const anim of anims) {\n const target = (anim.effect as KeyframeEffect)?.target as HTMLElement | null\n if (target?.closest?.('[data-lapse-panel]')) continue\n if (anim.playbackRate !== this.speed) {\n anim.playbackRate = this.speed || 0.001\n }\n }\n } catch {}\n }, 100) as unknown as number\n }\n }\n\n getSpeed(): number {\n return this.speed\n }\n\n /** Restore all patched APIs to originals. */\n destroy(): void {\n if (!this.installed) return\n\n performance.now = this._perfNow\n Date.now = this._dateNow\n window.requestAnimationFrame = this._raf\n window.cancelAnimationFrame = this._caf\n window.setTimeout = this._setTimeout\n window.clearTimeout = this._clearTimeout\n window.setInterval = this._setInterval\n window.clearInterval = this._clearInterval\n\n // Clear all managed intervals\n for (const [, entry] of this.intervalMap) {\n this._clearTimeout(entry.realId as any)\n }\n this.intervalMap.clear()\n\n if (this._origAnimate) {\n Element.prototype.animate = this._origAnimate\n this._origAnimate = null\n }\n\n this.mediaObserver?.disconnect()\n this.mediaObserver = null\n\n if (this.animObserver != null) {\n this._clearInterval(this.animObserver as any)\n this.animObserver = null\n }\n\n // Restore playbackRate on all animations\n try {\n for (const anim of document.getAnimations()) {\n anim.playbackRate = 1\n }\n } catch {}\n\n delete (window as any).__LAPSE_ORIGINAL_RAF__\n this.installed = false\n }\n}\n","import type {\n AnimationInfo,\n ElementSnapshot,\n FrameAnimation,\n FrameSnapshot,\n PropertySnapshot,\n Rect,\n TimelineCapture,\n} from './types'\n\n// ---------------------------------------------------------------------------\n// Augment Window for Lapse internals\n// ---------------------------------------------------------------------------\n\ndeclare global {\n interface Window {\n __LAPSE_ORIGINAL_RAF__?: typeof requestAnimationFrame\n }\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Visual-only properties — safe to override without affecting layout. */\nconst SAFE_PROPS = [\n 'opacity', 'transform', 'background-color', 'color', 'border-color',\n 'box-shadow', 'border-radius', 'filter', 'clip-path',\n 'scale', 'rotate', 'translate',\n 'outline-color', 'outline-width', 'outline-offset', 'outline-style',\n 'text-decoration-color',\n 'fill', 'stroke', 'stroke-dasharray', 'stroke-dashoffset',\n 'visibility', 'pointer-events',\n]\n\n/** Properties that affect layout — snapshot only, applied only on animated elements. */\nconst LAYOUT_PROPS = [\n 'width', 'height', 'top', 'left', 'right', 'bottom',\n 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'max-height', 'max-width', 'min-height', 'min-width',\n 'display',\n]\n\nconst SNAPSHOT_PROPS = [...SAFE_PROPS, ...LAYOUT_PROPS]\n\nconst SAFE_PROPS_SET = new Set(SAFE_PROPS)\n\nconst SNAPSHOT_ATTRS = [\n 'data-state', 'data-checked', 'data-disabled', 'data-highlighted',\n 'data-orientation', 'data-active', 'data-selected', 'data-open',\n 'data-closed', 'data-side', 'data-align', 'data-focus', 'data-hover',\n 'data-at-boundary', 'data-scrubbing',\n 'aria-checked', 'aria-selected', 'aria-expanded', 'aria-pressed',\n 'aria-hidden', 'aria-disabled', 'aria-valuenow', 'aria-valuemin', 'aria-valuemax',\n 'aria-invalid',\n 'checked', 'disabled', 'hidden', 'value',\n 'class', 'style',\n]\n\nconst STATE_SELECTORS = [\n '[data-state]', '[aria-checked]', '[aria-selected]', '[aria-expanded]',\n '[aria-pressed]', '[role=\"radio\"]', '[role=\"checkbox\"]', '[role=\"switch\"]',\n '[role=\"tab\"]', '[role=\"tabpanel\"]', '[role=\"option\"]', '[role=\"slider\"]',\n '[role=\"menuitem\"]', '[role=\"menuitemcheckbox\"]', '[role=\"menuitemradio\"]',\n '[type=\"radio\"]', '[type=\"checkbox\"]', '[type=\"range\"]',\n 'input', 'button', 'select', 'textarea',\n '[data-radix-collection-item]',\n '[data-slot=\"slider-thumb\"]', '[data-slot=\"slider-track\"]',\n].join(',')\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a stable structural selector for `el` (up to 5 ancestors).\n * Used as the element identity key throughout recording & scrubbing.\n */\nfunction getSelector(el: Element): string | null {\n if (!el || !el.tagName) return null\n const parts: string[] = []\n let current: Element | null = el\n for (let i = 0; i < 5 && current && current.tagName && current.tagName !== 'HTML'; i++) {\n const tag = current.tagName.toLowerCase()\n const parent: Element | null = current.parentElement\n if (parent) {\n const siblings = Array.from(parent.children)\n const idx = siblings.indexOf(current) + 1\n parts.unshift(tag + ':nth-child(' + idx + ')')\n } else {\n parts.unshift(tag)\n }\n current = parent\n }\n return parts.join(' > ')\n}\n\nfunction getReadableSelector(el: Element): string {\n if (!el || !el.tagName) return 'unknown'\n if (el.id) return '#' + el.id\n const tag = el.tagName.toLowerCase()\n const classes = Array.from(el.classList || []).slice(0, 3).map((c) => '.' + c).join('')\n return tag + classes\n}\n\nfunction getElementLabel(el: Element): string {\n if (!el) return 'unknown'\n const ariaLabel = el.getAttribute('aria-label')\n if (ariaLabel) return ariaLabel\n const text = (el.textContent || '').trim()\n if (text && text.length < 40 && text.length > 0) return text\n const label = el.closest('label') || el.closest('[aria-label]')\n if (label) {\n const lt = label.getAttribute('aria-label') || (label.textContent || '').trim()\n if (lt && lt.length < 40) return lt\n }\n const state = el.getAttribute('data-state')\n const role = el.getAttribute('role')\n if (role && state) return role + ' (' + state + ')'\n if (role) return role\n return getReadableSelector(el)\n}\n\n/**\n * Parenthesis-aware comma split — keeps `cubic-bezier(...)` as atomic tokens.\n */\nfunction cssSplit(str: string): string[] {\n const parts: string[] = []\n let depth = 0\n let start = 0\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '(') depth++\n else if (str[i] === ')') depth--\n else if (str[i] === ',' && depth === 0) {\n parts.push(str.slice(start, i).trim())\n start = i + 1\n }\n }\n parts.push(str.slice(start).trim())\n return parts\n}\n\n// ---------------------------------------------------------------------------\n// TimelineRecorder\n// ---------------------------------------------------------------------------\n\nexport class TimelineRecorder {\n // ---- Recording state ----------------------------------------------------\n private recording = false\n private startTime = 0\n private boundingBox: Rect | null = null\n\n /** Structural-selector -> live DOM element. */\n readonly elements = new Map<string, HTMLElement>()\n /** Animation id -> info. */\n readonly animations = new Map<string, AnimationInfo>()\n /** Original inline style per element (captured on first encounter). */\n private originalStyles = new Map<string, string>()\n /** Captured frames. */\n private frames: FrameSnapshot[] = []\n\n // ---- Portal management --------------------------------------------------\n private activePortals = new Map<string, { element: HTMLElement }>()\n private portalIdCounter = 0\n private currentPortalIds = new Set<string>()\n private capturedPortals = new Set<string>()\n\n // ---- JS animation detection (Phase 2) -----------------------------------\n private prevInlineStyles = new Map<string, Record<string, string>>()\n private jsAnimStartTimes = new Map<string, number>()\n private jsAnimLastSeen = new Map<string, number>()\n private jsAnimFromValues = new Map<string, string>()\n private jsAnimChangeCount = new Map<string, number>()\n\n // ---- Interaction state --------------------------------------------------\n private currentHoverEls = new Set<string>()\n private currentFocusSel: string | null = null\n private currentPointer = { x: 0, y: 0, buttons: 0 }\n\n // ---- Observers & listeners ----------------------------------------------\n private attrObserver: MutationObserver | null = null\n private portalObserver: MutationObserver | null = null\n private exitObserver: MutationObserver | null = null\n\n private onMouseOver: ((e: MouseEvent) => void) | null = null\n private onMouseOut: ((e: MouseEvent) => void) | null = null\n private onFocusIn: ((e: FocusEvent) => void) | null = null\n private onFocusOut: (() => void) | null = null\n private onPointerMove: ((e: PointerEvent) => void) | null = null\n private onPointerDown: ((e: PointerEvent) => void) | null = null\n private onPointerUp: ((e: PointerEvent) => void) | null = null\n\n // ---- WAAPI interception --------------------------------------------------\n /** Animations captured via Element.prototype.animate monkey-patch. */\n readonly interceptedAnimations: { animation: Animation; target: Element }[] = []\n\n // ---- Recording limits ---------------------------------------------------\n private static readonly MAX_DURATION_MS = 60_000\n private static readonly MAX_FRAMES = 3600\n private hiddenSince: number | null = null\n private onVisibilityChange: (() => void) | null = null\n /** Set to true when the capture loop self-terminates due to limits. */\n autoStopped = false\n /** Called when recording auto-stops. Set by the engine. */\n onAutoStop: (() => void) | null = null\n\n // ---- Saved originals (for restoration) ----------------------------------\n private _removeChild: typeof Node.prototype.removeChild | null = null\n private _remove: typeof Element.prototype.remove | null = null\n private _elementAnimate: typeof Element.prototype.animate | null = null\n\n // ---- DOM elements injected during stop ----------------------------------\n /** `<style>` that disables all transitions/animations after recording. */\n noTransitionsEl: HTMLStyleElement | null = null\n /** Full-screen overlay blocking interaction during scrub. */\n blockerEl: HTMLDivElement | null = null\n /** `<style>` with cloned :hover / :focus rules rewritten as `[data-lapse-*]`. */\n lapseStyleEl: HTMLStyleElement | null = null\n\n // ---- Unpatched rAF reference --------------------------------------------\n private get _raf(): typeof requestAnimationFrame {\n return (window as any).__LAPSE_ORIGINAL_RAF__ || requestAnimationFrame\n }\n\n // =========================================================================\n // Public API — helpers exposed for the scrubber\n // =========================================================================\n\n getSelector = getSelector\n\n get SAFE_PROPS_SET(): Set<string> {\n return SAFE_PROPS_SET\n }\n\n get capturedPortalIds(): Set<string> {\n return this.capturedPortals\n }\n\n // =========================================================================\n // startRecording\n // =========================================================================\n\n startRecording(boundingBox?: Rect | null): void {\n if (this.recording) return\n\n // Reset state\n this.recording = true\n this.autoStopped = false\n this.hiddenSince = null\n this.startTime = performance.now()\n this.frames = []\n this.animations.clear()\n this.elements.clear()\n this.originalStyles.clear()\n this.boundingBox = boundingBox || null\n this.activePortals.clear()\n this.portalIdCounter = 0\n this.currentPortalIds.clear()\n this.capturedPortals.clear()\n this.prevInlineStyles.clear()\n this.jsAnimStartTimes.clear()\n this.jsAnimLastSeen.clear()\n this.jsAnimFromValues.clear()\n this.jsAnimChangeCount.clear()\n this.currentHoverEls.clear()\n this.currentFocusSel = null\n this.currentPointer = { x: 0, y: 0, buttons: 0 }\n\n // Visibility tracking — auto-stop when tab hidden >5s\n this.onVisibilityChange = () => {\n if (!this.recording) return\n if (document.hidden) {\n this.hiddenSince = performance.now()\n } else {\n this.hiddenSince = null\n }\n }\n document.addEventListener('visibilitychange', this.onVisibilityChange)\n\n // ------------------------------------------------------------------\n // Element tracking\n // ------------------------------------------------------------------\n\n const trackElement = (el: Element): void => {\n if (!el || !(el as HTMLElement).tagName) return\n // Skip elements inside the Lapse panel\n if ((el as HTMLElement).closest?.('[data-lapse-panel]')) return\n const sel = getSelector(el)\n if (!sel) return\n const isNew = !this.elements.has(sel)\n this.elements.set(sel, el as HTMLElement)\n if (isNew) {\n this.originalStyles.set(sel, el.getAttribute('style') || '')\n }\n }\n\n const trackTree = (root: Element): void => {\n if (!root || !root.querySelectorAll) return\n trackElement(root)\n for (const child of root.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n\n const isInBounds = (el: Element): boolean => {\n if ((el as HTMLElement).closest?.('[data-lapse-panel]')) return false\n if (!this.boundingBox) return true\n const r = el.getBoundingClientRect()\n const bb = this.boundingBox\n return (\n r.x < bb.x + bb.width &&\n r.x + r.width > bb.x &&\n r.y < bb.y + bb.height &&\n r.y + r.height > bb.y\n )\n }\n\n // ------------------------------------------------------------------\n // Pre-scan: track all interactive elements and their groups\n // ------------------------------------------------------------------\n\n try {\n const stateEls = document.querySelectorAll(STATE_SELECTORS)\n for (const el of stateEls) {\n if (!isInBounds(el)) continue\n trackElement(el)\n for (const child of el.querySelectorAll('*')) {\n trackElement(child)\n }\n const parent = el.parentElement\n if (parent) {\n trackElement(parent)\n for (const sibling of parent.children) {\n trackElement(sibling)\n for (const child of sibling.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n }\n }\n } catch (_) {\n // Selector may fail in edge cases — not critical\n }\n\n // ------------------------------------------------------------------\n // Observers\n // ------------------------------------------------------------------\n\n // 1. Attribute-change observer\n this.attrObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.target instanceof HTMLElement) {\n trackElement(m.target)\n const parent = m.target.parentElement\n if (parent) {\n for (const sibling of parent.children) {\n trackElement(sibling)\n for (const child of sibling.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n }\n }\n }\n })\n this.attrObserver.observe(document.body, {\n attributes: true,\n attributeFilter: [\n 'data-state', 'data-highlighted', 'data-hover', 'data-focus',\n 'data-active', 'data-selected', 'data-open', 'data-closed',\n 'data-at-boundary', 'data-scrubbing',\n 'aria-checked', 'aria-selected', 'aria-expanded', 'aria-valuenow',\n 'aria-invalid', 'class', 'style',\n ],\n subtree: true,\n })\n\n // 2. Portal management — intercept DOM removal to keep portals alive\n this._removeChild = Node.prototype.removeChild\n const savedRemoveChild = this._removeChild\n const self = this\n\n Node.prototype.removeChild = function <T extends Node>(child: T): T {\n if (\n self.recording &&\n child instanceof HTMLElement &&\n child.hasAttribute('data-lapse-portal-id')\n ) {\n child.style.display = 'none'\n child.setAttribute('data-lapse-portal-hidden', '')\n const id = child.getAttribute('data-lapse-portal-id')\n if (id) self.currentPortalIds.delete(id)\n return child\n }\n return savedRemoveChild.call(this, child) as T\n }\n\n this._remove = Element.prototype.remove\n const savedRemove = this._remove\n\n Element.prototype.remove = function (this: Element) {\n if (\n self.recording &&\n this instanceof HTMLElement &&\n this.hasAttribute('data-lapse-portal-id')\n ) {\n this.style.display = 'none'\n this.setAttribute('data-lapse-portal-hidden', '')\n const id = this.getAttribute('data-lapse-portal-id')\n if (id) self.currentPortalIds.delete(id)\n return\n }\n return savedRemove.call(this)\n }\n\n // Intercept Element.prototype.animate to track WAAPI animations\n this._elementAnimate = Element.prototype.animate\n const savedAnimate = this._elementAnimate\n\n Element.prototype.animate = function (\n this: Element,\n keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n options?: number | KeyframeAnimationOptions,\n ): Animation {\n const anim = savedAnimate.call(this, keyframes, options)\n\n // Track the target element and capture the animation\n if (self.recording && this instanceof HTMLElement && isInBounds(this)) {\n trackElement(this)\n self.interceptedAnimations.push({ animation: anim, target: this })\n }\n\n return anim\n }\n\n // Watch for new portals being added\n this.portalObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n for (const node of m.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (node.parentElement !== document.body) continue\n if (node.hasAttribute('data-lapse-portal-id')) continue // already tracked\n\n const isPortal =\n node.hasAttribute('data-radix-popper-content-wrapper') ||\n node.hasAttribute('data-radix-portal') ||\n node.getAttribute('role') === 'dialog' ||\n node.getAttribute('role') === 'alertdialog' ||\n node.querySelector(\n '[role=\"menu\"], [role=\"dialog\"], [role=\"alertdialog\"], ' +\n '[role=\"listbox\"], [role=\"tooltip\"], [data-radix-popper-content-wrapper]',\n ) ||\n node.hasAttribute('data-state') ||\n (node.style &&\n (node.style.position === 'fixed' || node.style.position === 'absolute')) ||\n getComputedStyle(node).position === 'fixed'\n\n if (!isPortal) continue\n\n const id = '__lapse_portal_' + this.portalIdCounter++\n node.setAttribute('data-lapse-portal-id', id)\n this.activePortals.set(id, { element: node })\n this.currentPortalIds.add(id)\n this.capturedPortals.add(id)\n trackTree(node)\n }\n }\n })\n this.portalObserver.observe(document.body, { childList: true })\n\n // Exit-animation observer — catch any tracked element being removed\n this.exitObserver = new MutationObserver((mutations) => {\n if (!this.recording) return\n for (const m of mutations) {\n for (const node of m.removedNodes) {\n if (!(node instanceof HTMLElement)) continue\n const sel = getSelector(node)\n if (sel && this.elements.has(sel)) {\n if (!node.isConnected) {\n node.style.display = 'none'\n node.setAttribute('data-lapse-exit-captured', '')\n ;(m.target || document.body).appendChild(node)\n }\n }\n }\n }\n })\n this.exitObserver.observe(document.body, { childList: true, subtree: true })\n\n // ------------------------------------------------------------------\n // 3. Mouse hover tracking\n // ------------------------------------------------------------------\n\n this.onMouseOver = (e: MouseEvent) => {\n if (!this.recording) return\n this.currentHoverEls.clear()\n let el = e.target as HTMLElement | null\n while (el && el !== document.body) {\n const sel = getSelector(el)\n if (sel) {\n this.currentHoverEls.add(sel)\n trackElement(el)\n }\n el = el.parentElement\n }\n }\n\n this.onMouseOut = (e: MouseEvent) => {\n if (!this.recording) return\n if (!e.relatedTarget || !document.body.contains(e.relatedTarget as Node)) {\n this.currentHoverEls.clear()\n }\n }\n\n document.addEventListener('mouseover', this.onMouseOver, true)\n document.addEventListener('mouseout', this.onMouseOut, true)\n\n // ------------------------------------------------------------------\n // 4. Focus tracking\n // ------------------------------------------------------------------\n\n this.onFocusIn = (e: FocusEvent) => {\n if (!this.recording) return\n const el = e.target as HTMLElement | null\n if (el && el !== document.body) {\n const sel = getSelector(el)\n this.currentFocusSel = sel\n trackElement(el)\n let parent = el.parentElement\n while (parent && parent !== document.body) {\n trackElement(parent)\n parent = parent.parentElement\n }\n }\n }\n\n this.onFocusOut = () => {\n if (!this.recording) return\n this.currentFocusSel = null\n }\n\n document.addEventListener('focusin', this.onFocusIn, true)\n document.addEventListener('focusout', this.onFocusOut, true)\n\n // ------------------------------------------------------------------\n // 5. Pointer position tracking (sliders, scrubbers)\n // ------------------------------------------------------------------\n\n this.onPointerMove = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: e.buttons }\n }\n\n this.onPointerDown = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: e.buttons }\n }\n\n this.onPointerUp = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: 0 }\n }\n\n document.addEventListener('pointermove', this.onPointerMove, true)\n document.addEventListener('pointerdown', this.onPointerDown, true)\n document.addEventListener('pointerup', this.onPointerUp, true)\n\n // ------------------------------------------------------------------\n // Capture loop\n // ------------------------------------------------------------------\n\n const captureFrame = (): void => {\n if (!this.recording) return\n\n const time = performance.now() - this.startTime\n\n // Auto-stop: max duration, max frames, or tab hidden >5s\n if (\n time >= TimelineRecorder.MAX_DURATION_MS ||\n this.frames.length >= TimelineRecorder.MAX_FRAMES ||\n (this.hiddenSince && performance.now() - this.hiddenSince > 5000)\n ) {\n this.recording = false\n this.autoStopped = true\n this.onAutoStop?.()\n return\n }\n\n const anims = document.getAnimations()\n const frameAnims: FrameAnimation[] = []\n\n for (const a of anims) {\n const target = (a.effect as KeyframeEffect)?.target as HTMLElement | null\n if (!target) continue\n if (!isInBounds(target)) continue\n\n const uniqueSelector = getSelector(target)\n if (!uniqueSelector) continue\n const readableSelector = getReadableSelector(target)\n\n trackElement(target)\n\n const timing = (a.effect as KeyframeEffect)?.getTiming?.() || {}\n const duration =\n typeof timing.duration === 'number' ? timing.duration : 0\n const delay = timing.delay || 0\n const easing = timing.easing || 'linear'\n\n let name = ''\n let type = 'WebAnimation'\n if (\n a.constructor.name === 'CSSTransition' ||\n (a as any).transitionProperty\n ) {\n name = (a as any).transitionProperty || ''\n type = 'CSSTransition'\n } else if (\n a.constructor.name === 'CSSAnimation' ||\n (a as any).animationName\n ) {\n name = (a as any).animationName || ''\n type = 'CSSAnimation'\n }\n\n const id = type + ':' + name + ':' + uniqueSelector\n\n if (!this.animations.has(id)) {\n const keyframes = (a.effect as KeyframeEffect)?.getKeyframes?.() || []\n let source: string | null = null\n\n if (type === 'CSSAnimation' && keyframes.length > 0) {\n const kfLines = keyframes\n .map((kf) => {\n const offset = Math.round((kf.offset ?? 0) * 100) + '%'\n const props = Object.entries(kf)\n .filter(\n ([k]) =>\n !['offset', 'easing', 'composite', 'computedOffset'].includes(k),\n )\n .map(\n ([k, v]) =>\n k.replace(/([A-Z])/g, '-$1').toLowerCase() + ': ' + v,\n )\n .join('; ')\n return ' ' + offset + ' { ' + props + ' }'\n })\n .join('\\n')\n source =\n '@keyframes ' + (name || 'anonymous') + ' {\\n' + kfLines + '\\n}'\n } else if (type === 'CSSTransition') {\n source = 'transition: ' + name + ' ' + duration + 'ms ' + easing\n }\n\n // Resolve CSS custom properties used in transitions\n const resolvedVars: Record<string, string> = {}\n try {\n const cs = getComputedStyle(target)\n const style = target.getAttribute('style') || ''\n const allRules: string[] = []\n for (const sheet of document.styleSheets) {\n try {\n for (const rule of sheet.cssRules) {\n if (\n (rule as CSSStyleRule).selectorText &&\n target.matches((rule as CSSStyleRule).selectorText)\n ) {\n allRules.push(rule.cssText)\n }\n }\n } catch (_) {\n // Cross-origin stylesheet — skip\n }\n }\n const allCssText = allRules.join(' ') + ' ' + style\n const varRegex = /var\\(\\s*(--[a-zA-Z0-9-]+)/g\n let varMatch: RegExpExecArray | null\n while ((varMatch = varRegex.exec(allCssText)) !== null) {\n const varName = varMatch[1]\n const resolved = cs.getPropertyValue(varName).trim()\n if (resolved) {\n resolvedVars[varName] = resolved\n }\n }\n } catch (_) {\n // Non-critical\n }\n\n // Diff expected vs actual transition timing\n let conflicts: string[] | null = null\n if (type === 'CSSTransition') {\n try {\n const cs = getComputedStyle(target)\n\n const tProps = cssSplit(cs.transitionProperty)\n const tDurations = cssSplit(cs.transitionDuration).map(\n (s) => parseFloat(s) * 1000,\n )\n const tEasings = cssSplit(cs.transitionTimingFunction)\n const tDelays = cssSplit(cs.transitionDelay).map(\n (s) => parseFloat(s) * 1000,\n )\n\n let idx = tProps.indexOf(name)\n if (idx === -1 && tProps.includes('all'))\n idx = tProps.indexOf('all')\n\n if (idx >= 0) {\n const declaredDuration =\n tDurations[idx % tDurations.length] || 0\n const declaredEasing =\n tEasings[idx % tEasings.length] || 'ease'\n const declaredDelay = tDelays[idx % tDelays.length] || 0\n\n const diffs: string[] = []\n if (Math.abs(declaredDuration - duration) > 1) {\n diffs.push(\n 'duration: declared ' +\n declaredDuration +\n 'ms, actual ' +\n duration +\n 'ms',\n )\n }\n if (declaredEasing !== easing) {\n const normDeclared = declaredEasing.replace(/\\s/g, '')\n const normActual = easing.replace(/\\s/g, '')\n if (normDeclared !== normActual) {\n diffs.push(\n 'easing: declared ' +\n declaredEasing +\n ', actual ' +\n easing,\n )\n }\n }\n if (Math.abs(declaredDelay - delay) > 1) {\n diffs.push(\n 'delay: declared ' +\n declaredDelay +\n 'ms, actual ' +\n delay +\n 'ms',\n )\n }\n if (diffs.length > 0) {\n conflicts = diffs\n }\n }\n } catch (_) {\n // Non-critical\n }\n }\n\n this.animations.set(id, {\n id,\n name,\n selector: readableSelector,\n elementLabel: getElementLabel(target),\n duration,\n delay,\n easing,\n type,\n source,\n resolvedVars:\n Object.keys(resolvedVars).length > 0 ? resolvedVars : null,\n conflicts,\n })\n }\n\n // Capture per-frame property values\n const keyframes = (a.effect as KeyframeEffect)?.getKeyframes?.() || []\n const animatedProps = new Set<string>()\n for (const kf of keyframes) {\n for (const key of Object.keys(kf)) {\n if (\n !['offset', 'easing', 'composite', 'computedOffset'].includes(key)\n ) {\n animatedProps.add(key)\n }\n }\n }\n\n const computedStyle = getComputedStyle(target)\n const properties: PropertySnapshot[] = []\n for (const prop of animatedProps) {\n const kebab = prop.replace(/([A-Z])/g, '-$1').toLowerCase()\n const value = computedStyle.getPropertyValue(kebab) || ''\n if (value) {\n const from = (keyframes[0] as any)?.[prop] || null\n const to =\n (keyframes[keyframes.length - 1] as any)?.[prop] || null\n properties.push({ property: kebab, value, from, to })\n }\n }\n\n const currentTime = (a.currentTime as number) ?? 0\n const progress =\n duration > 0\n ? Math.max(0, Math.min(1, currentTime / duration))\n : 0\n frameAnims.push({ animationId: id, currentTime, progress, properties })\n }\n\n // Phase 2: Detect JS-driven animations (rAF, Framer Motion springs, etc.)\n // Compare inline style properties between frames for tracked elements\n // that don't have a corresponding WAAPI animation\n const waapiAnimatedIds = new Set<string>()\n for (const fa of frameAnims) {\n const parts = fa.animationId.split(':')\n waapiAnimatedIds.add(parts[parts.length - 1])\n }\n\n const JS_TRACK_PROPS = ['transform', 'opacity', 'left', 'top', 'right', 'bottom', 'background']\n // Also track which properties are already covered by WAAPI per element\n const waapiAnimatedProps = new Map<string, Set<string>>()\n for (const fa of frameAnims) {\n const parts = fa.animationId.split(':')\n const elKey = parts[parts.length - 1]\n if (!waapiAnimatedProps.has(elKey)) waapiAnimatedProps.set(elKey, new Set())\n const propName = parts[1] // type:propName:selector\n if (propName) waapiAnimatedProps.get(elKey)!.add(propName)\n }\n\n for (const [elId, el] of this.elements) {\n if (!el.isConnected) continue\n const hasWaapi = waapiAnimatedIds.has(elId)\n const waapiProps = waapiAnimatedProps.get(elId)\n\n const currentInline: Record<string, string> = {}\n let hasAnyInline = false\n for (const prop of JS_TRACK_PROPS) {\n const camel = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase())\n const val = (el.style as any)[camel]\n if (val) {\n currentInline[prop] = val\n hasAnyInline = true\n }\n }\n if (!hasAnyInline) {\n this.prevInlineStyles.set(elId, currentInline)\n continue\n }\n\n const prevInline = this.prevInlineStyles.get(elId) || {}\n this.prevInlineStyles.set(elId, currentInline)\n\n for (const p of JS_TRACK_PROPS) {\n const cur = currentInline[p] || ''\n const prev = prevInline[p] || ''\n // Skip if this property is already tracked via WAAPI on this element\n const propCoveredByWaapi = waapiProps?.has(p) || waapiProps?.has(p.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()))\n if (cur && cur !== prev && !propCoveredByWaapi) {\n const jsId = 'JSAnimation:' + p + ':' + elId\n\n // Track how many frames this property has been changing\n this.jsAnimChangeCount.set(jsId, (this.jsAnimChangeCount.get(jsId) || 0) + 1)\n\n if (!this.jsAnimStartTimes.has(jsId)) {\n this.jsAnimStartTimes.set(jsId, time)\n this.jsAnimFromValues.set(jsId, prev || cur)\n }\n this.jsAnimLastSeen.set(jsId, time)\n\n // Only register as animation after 3+ frames of continuous change\n // (single frame changes are React state toggles, not animations)\n if (this.jsAnimChangeCount.get(jsId)! < 3) continue\n\n if (!this.animations.has(jsId)) {\n const readableSel = getReadableSelector(el)\n this.animations.set(jsId, {\n id: jsId,\n name: p,\n selector: readableSel,\n elementLabel: getElementLabel(el),\n duration: 0,\n delay: 0,\n easing: 'JS-driven',\n type: 'JSAnimation',\n source: 'Detected: inline style animation (JS library or requestAnimationFrame)',\n resolvedVars: null,\n conflicts: null,\n })\n }\n\n // Update duration as animation progresses\n const startT = this.jsAnimStartTimes.get(jsId)!\n const anim = this.animations.get(jsId)!\n anim.duration = time - startT\n\n const fromVal = this.jsAnimFromValues.get(jsId) || ''\n const elapsed = time - startT\n const estimatedDuration = Math.max(anim.duration, 300)\n const prog = Math.min(1, elapsed / estimatedDuration)\n frameAnims.push({\n animationId: jsId,\n currentTime: elapsed,\n progress: prog,\n properties: [{\n property: p,\n value: cur,\n from: fromVal,\n to: cur\n }]\n })\n }\n }\n }\n\n // Snapshot computed styles, attributes, and inline styles for all tracked elements\n const elementSnapshots: Record<string, ElementSnapshot> = {}\n for (const [sel, el] of this.elements) {\n if (!el.isConnected) continue\n const cs = getComputedStyle(el)\n const snap: ElementSnapshot = { __styles: {}, __attrs: {} }\n for (const prop of SNAPSHOT_PROPS) {\n snap.__styles[prop] = cs.getPropertyValue(prop)\n }\n for (const attr of SNAPSHOT_ATTRS) {\n if (attr === 'checked') {\n snap.__attrs[attr] = (el as HTMLInputElement).checked\n ? 'true'\n : null\n } else if (attr === 'class') {\n snap.__attrs[attr] = el.className\n } else if (attr === 'style') {\n snap.__attrs[attr] = el.getAttribute('style') || ''\n } else if (attr === 'value') {\n snap.__attrs[attr] =\n (el as HTMLInputElement).value !== undefined\n ? String((el as HTMLInputElement).value)\n : null\n } else {\n snap.__attrs[attr] = el.getAttribute(attr)\n }\n }\n // Pseudo-element opacity\n try {\n snap.__afterOpacity = getComputedStyle(el, '::after').getPropertyValue(\n 'opacity',\n )\n snap.__beforeOpacity = getComputedStyle(\n el,\n '::before',\n ).getPropertyValue('opacity')\n } catch (_) {\n // Non-critical\n }\n elementSnapshots[sel] = snap\n }\n\n // Check for hidden portals whose display was 'none' but are still\n // tracked — mark them as visible if they were un-hidden by React\n for (const [id, portal] of this.activePortals) {\n if (\n portal.element?.isConnected &&\n !portal.element.hasAttribute('data-lapse-portal-hidden')\n ) {\n this.currentPortalIds.add(id)\n }\n }\n\n this.frames.push({\n time,\n animations: frameAnims,\n elementSnapshots,\n activePortalIds: [...this.currentPortalIds],\n hoveredSels: [...this.currentHoverEls],\n focusSel: this.currentFocusSel,\n pointer: { ...this.currentPointer },\n scrollPositions: {},\n })\n\n this._raf(captureFrame)\n }\n\n this._raf(captureFrame)\n }\n\n // =========================================================================\n // stopRecording\n // =========================================================================\n\n stopRecording(): TimelineCapture {\n if (!this.recording) {\n return {\n startTime: 0,\n endTime: 0,\n duration: 0,\n animations: [],\n frames: [],\n boundingBox: null,\n }\n }\n\n this.recording = false\n\n // ------------------------------------------------------------------\n // Restore patched prototypes\n // ------------------------------------------------------------------\n\n if (this._removeChild) Node.prototype.removeChild = this._removeChild\n if (this._remove) Element.prototype.remove = this._remove\n if (this._elementAnimate) Element.prototype.animate = this._elementAnimate\n\n // ------------------------------------------------------------------\n // Disconnect observers & remove event listeners\n // ------------------------------------------------------------------\n\n this.attrObserver?.disconnect()\n this.portalObserver?.disconnect()\n this.exitObserver?.disconnect()\n if (this.onVisibilityChange) {\n document.removeEventListener('visibilitychange', this.onVisibilityChange)\n this.onVisibilityChange = null\n }\n\n if (this.onMouseOver)\n document.removeEventListener('mouseover', this.onMouseOver, true)\n if (this.onMouseOut)\n document.removeEventListener('mouseout', this.onMouseOut, true)\n if (this.onFocusIn)\n document.removeEventListener('focusin', this.onFocusIn, true)\n if (this.onFocusOut)\n document.removeEventListener('focusout', this.onFocusOut, true)\n if (this.onPointerMove)\n document.removeEventListener('pointermove', this.onPointerMove, true)\n if (this.onPointerDown)\n document.removeEventListener('pointerdown', this.onPointerDown, true)\n if (this.onPointerUp)\n document.removeEventListener('pointerup', this.onPointerUp, true)\n\n // ------------------------------------------------------------------\n // Cancel all running animations\n // ------------------------------------------------------------------\n\n try {\n for (const anim of document.getAnimations()) {\n // Don't cancel animations on the Lapse panel itself\n const target = (anim.effect as KeyframeEffect)?.target as HTMLElement | null\n if (target?.closest?.('[data-lapse-panel]')) continue\n anim.cancel()\n }\n } catch (_) {\n // Non-critical\n }\n\n // ------------------------------------------------------------------\n // Inject no-transitions style\n // ------------------------------------------------------------------\n\n const noTransitions = document.createElement('style')\n noTransitions.id = '__lapse-no-transitions'\n noTransitions.textContent =\n '*, *::before, *::after { transition: none !important; animation: none !important; }'\n document.head.appendChild(noTransitions)\n this.noTransitionsEl = noTransitions\n\n // ------------------------------------------------------------------\n // Add interaction blocker overlay\n // ------------------------------------------------------------------\n\n const blocker = document.createElement('div')\n blocker.id = '__lapse-scrub-blocker'\n blocker.style.cssText =\n 'position:fixed;inset:0;z-index:999999;cursor:not-allowed;background:transparent;'\n blocker.title = 'Clear the timeline to interact with the page'\n document.body.appendChild(blocker)\n this.blockerEl = blocker\n\n // ------------------------------------------------------------------\n // Clone :hover / :focus CSS rules (deferred — don't block the return)\n // ------------------------------------------------------------------\n\n setTimeout(() => {\n try {\n const lapseStyle = document.createElement('style')\n lapseStyle.id = '__lapse-state-rules'\n\n // Only walk CSSOM rules (avoids reading huge Tailwind <style> textContent)\n const hoverFocusRules: string[] = []\n for (const sheet of document.styleSheets) {\n try {\n const walk = (rules: CSSRuleList) => {\n for (const rule of rules) {\n if ((rule as CSSGroupingRule).cssRules) {\n walk((rule as CSSGroupingRule).cssRules)\n continue\n }\n const t = rule.cssText\n if (t && (t.includes(':hover') || t.includes(':focus'))) {\n hoverFocusRules.push(t)\n }\n }\n }\n walk(sheet.cssRules)\n } catch (_) {\n // Cross-origin stylesheet — skip\n }\n }\n\n // Clone individual rules (no regex on giant CSS blobs)\n const parts: string[] = []\n for (const ruleText of hoverFocusRules) {\n const braceIdx = ruleText.indexOf('{')\n if (braceIdx === -1) continue\n const selector = ruleText.slice(0, braceIdx).trim()\n const bodyEnd = ruleText.lastIndexOf('}')\n const body = ruleText.slice(braceIdx + 1, bodyEnd).trim()\n if (!body) continue\n\n const newBody = body.replace(\n /([^;:]+):\\s*([^;]+)(;|$)/g,\n (m, prop: string, val: string, end: string) => {\n if (val.includes('!important')) return m\n return prop + ': ' + val.trim() + ' !important' + end\n },\n )\n\n if (selector.includes(':hover')) {\n parts.push(selector.replace(/:hover/g, '[data-lapse-hover]') + ' { ' + newBody + ' }')\n }\n if (selector.includes(':focus-visible')) {\n parts.push(selector.replace(/:focus-visible/g, '[data-lapse-focus]') + ' { ' + newBody + ' }')\n } else if (selector.includes(':focus-within')) {\n parts.push(selector.replace(/:focus-within/g, ':has([data-lapse-focus])') + ' { ' + newBody + ' }')\n } else if (selector.includes(':focus')) {\n parts.push(selector.replace(/:focus(?!-)/g, '[data-lapse-focus]') + ' { ' + newBody + ' }')\n }\n }\n\n lapseStyle.textContent = parts.join('\\n')\n document.head.appendChild(lapseStyle)\n this.lapseStyleEl = lapseStyle\n } catch (_) {\n // Non-critical\n }\n }, 0)\n\n // ------------------------------------------------------------------\n // Apply frame 0 snapshot to reset visual state (safe props only)\n // ------------------------------------------------------------------\n\n if (this.frames.length > 0) {\n const frame0 = this.frames[0]\n if (frame0.elementSnapshots) {\n for (const [sel, snap] of Object.entries(frame0.elementSnapshots)) {\n const el = this.elements.get(sel)\n if (!el || !el.isConnected) continue\n if (snap.__styles) {\n for (const [prop, value] of Object.entries(snap.__styles)) {\n if (SAFE_PROPS_SET.has(prop)) {\n el.style.setProperty(prop, value, 'important')\n }\n }\n }\n if (snap.__attrs) {\n for (const [attr, value] of Object.entries(snap.__attrs)) {\n if (attr === 'checked') {\n ;(el as HTMLInputElement).checked = value === 'true'\n } else if (attr === 'class' && value != null) {\n el.className = value\n } else if (attr === 'style') {\n // Skip — handled by __styles\n } else if (attr === 'value' && value != null) {\n ;(el as HTMLInputElement).value = value\n } else if (value == null) {\n el.removeAttribute(attr)\n } else {\n el.setAttribute(attr, value)\n }\n }\n }\n }\n }\n }\n\n // ------------------------------------------------------------------\n // Build and return the capture\n // ------------------------------------------------------------------\n\n const duration =\n this.frames.length > 0\n ? this.frames[this.frames.length - 1].time\n : 0\n\n const capture: TimelineCapture = {\n startTime: this.startTime,\n endTime: performance.now(),\n duration,\n animations: Array.from(this.animations.values()),\n frames: this.frames,\n boundingBox: this.boundingBox,\n }\n\n return capture\n }\n}\n","import type { FrameSnapshot, ElementSnapshot } from './types'\n\n/**\n * Represents a WAAPI Animation intercepted during recording.\n * The recorder monkey-patches Element.prototype.animate to capture these.\n */\nexport interface InterceptedAnimation {\n animation: Animation\n target: Element\n}\n\n/**\n * State handed from the recorder after stopRecording().\n * This is everything the scrubber needs to replay frames.\n */\nexport interface ScrubberState {\n /** Selector string -> live DOM element */\n elements: Map<string, HTMLElement>\n /** Captured frame snapshots from the recording */\n frames: FrameSnapshot[]\n /** All portal IDs ever captured (for show/hide management) */\n capturedPortals: Set<string>\n /** WAAPI animations intercepted via Element.prototype.animate patch */\n interceptedAnimations: InterceptedAnimation[]\n /** Set of CSS properties that are safe (visual-only, no layout side-effects) */\n SAFE_PROPS_SET: Set<string>\n}\n\n/**\n * Timeline scrubber — applies captured frame snapshots to the live DOM.\n *\n * Ported from the inline JS that the Electron version injected via\n * executeJavaScript() in timeline-controller.ts (seekTo / releaseAnimations).\n */\nexport class TimelineScrubber {\n private elements: Map<string, HTMLElement>\n private frames: FrameSnapshot[]\n private capturedPortals: Set<string>\n private interceptedAnimations: InterceptedAnimation[]\n private SAFE_PROPS_SET: Set<string>\n\n /** Saved originals for restore on release */\n private _originalAnimate: typeof Element.prototype.animate | null = null\n private _originalRaf: typeof requestAnimationFrame | null = null\n private _originalRemoveChild: typeof Node.prototype.removeChild | null = null\n private _originalRemove: typeof Element.prototype.remove | null = null\n\n constructor(state: ScrubberState) {\n this.elements = state.elements\n this.frames = state.frames\n this.capturedPortals = state.capturedPortals\n this.interceptedAnimations = state.interceptedAnimations\n this.SAFE_PROPS_SET = state.SAFE_PROPS_SET\n\n // Stash originals that the recorder may have patched\n this._originalAnimate = (window as any).__LAPSE_ORIGINAL_ANIMATE__ ?? null\n this._originalRaf = (window as any).__LAPSE_ORIGINAL_RAF__ ?? null\n this._originalRemoveChild = (window as any).__LAPSE_TIMELINE__?._removeChild ?? null\n this._originalRemove = (window as any).__LAPSE_TIMELINE__?._remove ?? null\n }\n\n // ---------------------------------------------------------------------------\n // Selector helper — mirrors the recorder's getSelector so we can look up\n // elements by the same key the recorder used in frame.animations[].animationId\n // ---------------------------------------------------------------------------\n\n private getSelector(el: Element): string | null {\n if (!el || !(el as HTMLElement).tagName) return null\n const parts: string[] = []\n let current: Element | null = el\n for (let i = 0; i < 5 && current && current.tagName && current.tagName !== 'HTML'; i++) {\n const tag = current.tagName.toLowerCase()\n const parent: Element | null = current.parentElement\n if (parent) {\n const siblings = Array.from(parent.children)\n const idx = siblings.indexOf(current) + 1\n parts.unshift(`${tag}:nth-child(${idx})`)\n } else {\n parts.unshift(tag)\n }\n current = parent\n }\n return parts.join(' > ')\n }\n\n // ---------------------------------------------------------------------------\n // seekTo — scrub the DOM to match a specific timestamp\n // ---------------------------------------------------------------------------\n\n seekTo(timeMs: number): void {\n if (!this.frames.length) return\n\n // Binary search for closest frame\n let lo = 0\n let hi = this.frames.length - 1\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (this.frames[mid].time < timeMs) lo = mid + 1\n else hi = mid\n }\n const frame = this.frames[lo]\n if (!frame || !frame.elementSnapshots) return\n\n // -----------------------------------------------------------------------\n // Clear state markers\n // -----------------------------------------------------------------------\n document.querySelectorAll('[data-lapse-hover]').forEach((el) => {\n el.removeAttribute('data-lapse-hover')\n })\n document.querySelectorAll('[data-lapse-focus]').forEach((el) => {\n el.removeAttribute('data-lapse-focus')\n })\n\n // -----------------------------------------------------------------------\n // Manage portals — show/hide original elements kept in DOM via removal\n // intercept. All portals get pointer-events:none during scrub.\n // -----------------------------------------------------------------------\n const activeIds = new Set(frame.activePortalIds || [])\n for (const id of this.capturedPortals) {\n const portalEl = document.querySelector(\n `[data-lapse-portal-id=\"${id}\"]`\n ) as HTMLElement | null\n if (!portalEl) continue\n if (activeIds.has(id)) {\n portalEl.style.removeProperty('display')\n portalEl.removeAttribute('data-lapse-portal-hidden')\n } else {\n portalEl.style.setProperty('display', 'none', 'important')\n }\n }\n\n // -----------------------------------------------------------------------\n // Apply hover markers\n // -----------------------------------------------------------------------\n const hoveredSels = frame.hoveredSels || []\n for (const sel of hoveredSels) {\n const el = this.elements.get(sel)\n if (el && el.isConnected) el.setAttribute('data-lapse-hover', '')\n }\n\n // -----------------------------------------------------------------------\n // Apply focus marker (+ ancestors for :focus-within)\n // -----------------------------------------------------------------------\n if (frame.focusSel) {\n const focusEl = this.elements.get(frame.focusSel)\n if (focusEl && focusEl.isConnected) {\n focusEl.setAttribute('data-lapse-focus', '')\n let parent = focusEl.parentElement\n while (parent && parent !== document.body) {\n parent.setAttribute('data-lapse-focus', '')\n parent = parent.parentElement\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Cancel intercepted WAAPI animations — pause + seek to match frame time\n // -----------------------------------------------------------------------\n for (const entry of this.interceptedAnimations) {\n try {\n const anim = entry.animation\n if (anim.playState !== 'finished') {\n anim.pause()\n }\n anim.currentTime = timeMs\n } catch {\n // Animation may have been garbage collected\n }\n }\n\n // -----------------------------------------------------------------------\n // Apply element snapshots\n // -----------------------------------------------------------------------\n for (const [sel, snap] of Object.entries(frame.elementSnapshots)) {\n const el = this.elements.get(sel)\n if (!el || !el.isConnected) continue\n if (el.closest?.('[data-lapse-panel]')) continue\n\n // Check if this element has any active animation at this frame\n const hasAnimation = (frame.animations || []).some(\n (a) =>\n a.animationId.endsWith(':' + sel) ||\n a.animationId.includes(':' + sel.split(' > ').pop())\n )\n\n // Apply computed styles — visual (safe) props always,\n // layout props only if the element has active animations\n const snapTyped = snap as ElementSnapshot\n if (snapTyped.__styles) {\n for (const [prop, value] of Object.entries(snapTyped.__styles)) {\n if (this.SAFE_PROPS_SET.has(prop) || hasAnimation) {\n el.style.setProperty(prop, value, 'important')\n }\n }\n }\n\n // Apply non-style attributes (class, data-*, aria-*, checked, etc.)\n if (snapTyped.__attrs) {\n for (const [attr, value] of Object.entries(snapTyped.__attrs)) {\n if (attr === 'checked') {\n ;(el as HTMLInputElement).checked = value === 'true'\n } else if (attr === 'class') {\n if (value != null) el.className = value\n } else if (attr === 'style') {\n // For elements with React-managed inline styles (segmented control pill,\n // sliders), apply the captured inline style, then re-apply transition:none\n // and our computed overrides on top\n if (value) {\n el.setAttribute('style', value)\n el.style.transition = 'none'\n // Re-apply computed style overrides on top\n if (snapTyped.__styles) {\n for (const [prop, val] of Object.entries(snapTyped.__styles)) {\n el.style.setProperty(prop, val, 'important')\n }\n }\n }\n } else if (attr === 'value') {\n if (value != null) (el as HTMLInputElement).value = value\n } else if (value == null) {\n el.removeAttribute(attr)\n } else {\n el.setAttribute(attr, value)\n }\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Override stale snapshot values with accurate WAAPI mid-transition data.\n // frame.animations[].properties have correct mid-transition values from\n // getComputedStyle on getAnimations() targets (which ARE mid-transition).\n // The element snapshots may have stale base values for some elements.\n // -----------------------------------------------------------------------\n for (const anim of frame.animations || []) {\n const firstColon = anim.animationId.indexOf(':')\n const secondColon = anim.animationId.indexOf(':', firstColon + 1)\n const animSel =\n secondColon >= 0 ? anim.animationId.substring(secondColon + 1) : ''\n const animEl = this.elements.get(animSel)\n if (!animEl || !animEl.isConnected) continue\n for (const prop of anim.properties || []) {\n if (prop.value) {\n animEl.style.setProperty(prop.property, prop.value, 'important')\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Clean up indicator overrides on checkboxes/radios.\n // For indicator elements without active animations at this frame,\n // remove stale inline overrides so CSS cascade from data-state takes effect.\n // -----------------------------------------------------------------------\n const animatedSels = new Set<string>()\n for (const anim of frame.animations || []) {\n const fc = anim.animationId.indexOf(':')\n const sc = anim.animationId.indexOf(':', fc + 1)\n if (sc >= 0) animatedSels.add(anim.animationId.substring(sc + 1))\n }\n document\n .querySelectorAll('.checkbox-indicator, .radio-indicator')\n .forEach((rawEl) => {\n const el = rawEl as HTMLElement\n const sel = this.getSelector(el)\n if (sel && !animatedSels.has(sel)) {\n el.style.removeProperty('opacity')\n el.style.removeProperty('transform')\n el.style.removeProperty('filter')\n el.style.removeProperty('stroke-dashoffset')\n }\n })\n }\n\n // ---------------------------------------------------------------------------\n // release — tear down all scrub state and restore the page to normal\n // ---------------------------------------------------------------------------\n\n release(): void {\n // Cancel intercepted WAAPI animations\n for (const entry of this.interceptedAnimations) {\n try {\n entry.animation.cancel()\n } catch {\n // Already finished or GC'd\n }\n }\n this.interceptedAnimations.length = 0\n\n // Restore Element.prototype.animate if we patched it\n if (this._originalAnimate) {\n Element.prototype.animate = this._originalAnimate\n this._originalAnimate = null\n delete (window as any).__LAPSE_ORIGINAL_ANIMATE__\n }\n\n // Restore requestAnimationFrame if we patched it\n if (this._originalRaf) {\n window.requestAnimationFrame = this._originalRaf\n this._originalRaf = null\n delete (window as any).__LAPSE_ORIGINAL_RAF__\n }\n\n // Remove global transition/animation override style\n const tl = (window as any).__LAPSE_TIMELINE__\n if (tl?.noTransitionsEl) {\n tl.noTransitionsEl.remove()\n }\n const noTrans = document.getElementById('__lapse-no-transitions')\n if (noTrans) noTrans.remove()\n\n // Remove interaction blocker\n const blocker = document.getElementById('__lapse-scrub-blocker')\n if (blocker) blocker.remove()\n if (tl?.blockerEl) tl.blockerEl.remove()\n\n // Remove cloned state rules style (hover/focus rule clones)\n const stateRules = document.getElementById('__lapse-state-rules')\n if (stateRules) stateRules.remove()\n if (tl?.lapseStyleEl) tl.lapseStyleEl.remove()\n\n // Restore original DOM removal methods\n if (this._originalRemoveChild) {\n Node.prototype.removeChild = this._originalRemoveChild\n this._originalRemoveChild = null\n } else if (tl?._removeChild) {\n Node.prototype.removeChild = tl._removeChild\n }\n\n if (this._originalRemove) {\n Element.prototype.remove = this._originalRemove\n this._originalRemove = null\n } else if (tl?._remove) {\n Element.prototype.remove = tl._remove\n }\n\n // Remove exit-captured elements (re-inserted hidden during recording)\n document.querySelectorAll('[data-lapse-exit-captured]').forEach((el) => {\n el.remove()\n })\n\n // Clean up data-lapse-* attributes from all elements\n document.querySelectorAll('[data-lapse-id]').forEach((el) => {\n el.removeAttribute('data-lapse-id')\n })\n document.querySelectorAll('[data-lapse-hover]').forEach((el) => {\n el.removeAttribute('data-lapse-hover')\n })\n document.querySelectorAll('[data-lapse-focus]').forEach((el) => {\n el.removeAttribute('data-lapse-focus')\n })\n document.querySelectorAll('[data-lapse-portal-id]').forEach((el) => {\n el.removeAttribute('data-lapse-portal-id')\n el.removeAttribute('data-lapse-portal-hidden')\n })\n\n // Clear the global timeline object\n delete (window as any).__LAPSE_TIMELINE__\n\n // Clear local references\n this.elements.clear()\n this.frames.length = 0\n this.capturedPortals.clear()\n }\n}\n","import type {\n AnimationInfo,\n ExportFilter,\n FrameSnapshot,\n OutputDetailLevel,\n TimelineExport\n} from './types'\n\nexport function getFrameAtTime(frames: FrameSnapshot[], timeMs: number): FrameSnapshot | null {\n if (frames.length === 0) return null\n let lo = 0\n let hi = frames.length - 1\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (frames[mid].time < timeMs) lo = mid + 1\n else hi = mid\n }\n return frames[lo]\n}\n\nexport function generateExport(\n animations: AnimationInfo[],\n frames: FrameSnapshot[],\n timeMs: number,\n filter: ExportFilter = 'active'\n): TimelineExport {\n const frame = getFrameAtTime(frames, timeMs)\n const duration = frames.at(-1)?.time ?? 0\n\n const filteredAnims = animations.filter((anim) => {\n if (filter === 'all-animations') return true\n if (filter === 'active') {\n const frameAnim = frame?.animations.find((a) => a.animationId === anim.id)\n if (!frameAnim || frameAnim.progress <= 0 || frameAnim.progress >= 1) return false\n if (frameAnim.properties.length > 0) {\n const hasRealChange = frameAnim.properties.some(\n (p) => p.from && p.to && p.from !== p.to\n )\n if (!hasRealChange) return false\n }\n return true\n }\n return true\n })\n\n const animExports = filteredAnims.map((anim) => {\n // Find this animation in the current frame, or fall back to the last frame it appeared in\n let frameAnim = frame?.animations.find((a) => a.animationId === anim.id)\n let status: 'active' | 'completed' | 'upcoming' = frameAnim ? 'active' : 'completed'\n\n if (!frameAnim) {\n // Search backwards for the last frame this animation appeared in\n for (let i = frames.length - 1; i >= 0; i--) {\n if (frames[i].time > timeMs) continue\n const found = frames[i].animations.find((a) => a.animationId === anim.id)\n if (found) { frameAnim = found; break }\n }\n // If still not found, search forward (animation hasn't started yet)\n if (!frameAnim) {\n for (let i = 0; i < frames.length; i++) {\n if (frames[i].time < timeMs) continue\n const found = frames[i].animations.find((a) => a.animationId === anim.id)\n if (found) { frameAnim = found; status = 'upcoming'; break }\n }\n }\n }\n\n const progressLabel = status === 'active'\n ? `${Math.round((frameAnim?.progress ?? 0) * 100)}%`\n : status === 'completed' ? 'done' : 'upcoming'\n\n return {\n element: anim.selector,\n elementLabel: anim.elementLabel || anim.selector,\n name: anim.name || anim.type,\n type: anim.type,\n timing: `${Math.round(anim.duration)}ms ${anim.easing}${anim.delay ? ` (delay: ${Math.round(anim.delay)}ms)` : ''}`,\n progress: progressLabel,\n properties: (frameAnim?.properties ?? []).map((p) => ({\n property: p.property,\n value: p.value,\n range: p.from && p.to ? `${p.from} \\u2192 ${p.to}` : ''\n })),\n source: anim.source,\n resolvedVars: anim.resolvedVars,\n conflicts: anim.conflicts\n }\n })\n\n const hoveredElements = Array.isArray(frame?.hoveredSels)\n ? frame.hoveredSels.map(String)\n : []\n const focusedElement = frame?.focusSel ? String(frame.focusSel) : null\n\n return {\n timestamp: `${Math.round(timeMs)}ms into ${Math.round(duration)}ms recording`,\n duration: `${Math.round(duration)}ms`,\n scrubPosition: timeMs,\n hoveredElements,\n focusedElement,\n animations: animExports\n }\n}\n\nexport function formatExportForLLM(exp: TimelineExport, detail: OutputDetailLevel = 'standard'): string {\n const lines: string[] = []\n\n // Group animations by element\n const grouped = new Map<string, { label: string; selector: string; anims: typeof exp.animations }>()\n for (const anim of exp.animations) {\n const key = (anim.elementLabel || '') + '|||' + anim.element\n if (!grouped.has(key)) {\n grouped.set(key, { label: anim.elementLabel || '', selector: anim.element, anims: [] })\n }\n grouped.get(key)!.anims.push(anim)\n }\n\n // Helper: skip no-change properties\n function isRealChange(prop: { range: string }): boolean {\n if (!prop.range) return true\n const [from, to] = prop.range.split(' \\u2192 ')\n return !(from && to && from.trim() === to.trim())\n }\n\n // ── Compact ──────────────────────────────────────────────────────────\n if (detail === 'compact') {\n lines.push(`# Animation State at ${exp.timestamp}`)\n lines.push('')\n for (const [, group] of grouped) {\n const label = group.label && group.label !== group.selector\n ? `**${group.label}** \\`${group.selector}\\``\n : `\\`${group.selector}\\``\n const cssAnims = group.anims.filter((a) => a.type !== 'JSAnimation')\n const jsAnims = group.anims.filter((a) => a.type === 'JSAnimation')\n\n if (cssAnims.length > 0) {\n const props = new Set<string>()\n for (const a of cssAnims) a.properties.filter(isRealChange).forEach((p) => props.add(p.property))\n const timing = cssAnims[0]?.timing || ''\n const progress = cssAnims[0]?.progress || ''\n const progressStr = progress && progress !== 'unknown' ? ` @ ${progress}` : ''\n lines.push(`- ${label}: ${[...props].join(', ')} (${timing}${progressStr})`)\n }\n if (jsAnims.length > 0) {\n const props = new Set<string>()\n for (const a of jsAnims) a.properties.filter(isRealChange).forEach((p) => props.add(p.property))\n if (props.size > 0) lines.push(`- ${label}: ${[...props].join(', ')} (JS)`)\n }\n }\n return lines.join('\\n')\n }\n\n // ── Standard / Detailed / Forensic ───────────────────────────────────\n lines.push(`# Animation State at ${exp.timestamp}`)\n lines.push('')\n\n // Forensic: environment info\n if (detail === 'forensic') {\n lines.push('**Environment:**')\n lines.push(`- Viewport: ${window.innerWidth}\\u00d7${window.innerHeight}`)\n lines.push(`- URL: ${window.location.href}`)\n lines.push(`- User Agent: ${navigator.userAgent}`)\n lines.push(`- Timestamp: ${new Date().toISOString()}`)\n lines.push(`- Device Pixel Ratio: ${window.devicePixelRatio}`)\n lines.push('')\n }\n\n // Interaction state (standard+)\n if (exp.hoveredElements.length > 0 || exp.focusedElement) {\n lines.push('**Interaction state:**')\n if (exp.hoveredElements.length > 0) {\n const deepest = exp.hoveredElements[exp.hoveredElements.length - 1] || exp.hoveredElements[0]\n lines.push(`- Hovered: \\`${deepest}\\``)\n }\n if (exp.focusedElement) {\n lines.push(`- Focused: \\`${exp.focusedElement}\\``)\n }\n lines.push('')\n }\n\n if (exp.animations.length === 0 && exp.hoveredElements.length === 0 && !exp.focusedElement) {\n lines.push('No active animations or interactions at this position.')\n return lines.join('\\n')\n }\n\n if (exp.animations.length === 0) {\n return lines.join('\\n')\n }\n\n for (const [, group] of grouped) {\n const label = group.label && group.label !== group.selector ? `\"${group.label}\" ` : ''\n const cssAnims = group.anims.filter((a) => a.type !== 'JSAnimation')\n const jsAnims = group.anims.filter((a) => a.type === 'JSAnimation')\n\n // Collect CSS property lines\n const cssPropLines: string[] = []\n if (cssAnims.length > 0) {\n const seenProps = new Set<string>()\n for (const anim of cssAnims) {\n const progressStr = anim.progress !== 'unknown' ? ` @ ${anim.progress}` : ''\n for (const prop of anim.properties) {\n if (seenProps.has(prop.property)) continue\n if (!isRealChange(prop)) continue\n seenProps.add(prop.property)\n let line = `- \\`${prop.property}\\`: ${prop.value}`\n if (prop.range) line += ` [${prop.range}]`\n line += ` (${anim.timing}${progressStr})`\n cssPropLines.push(line)\n }\n }\n }\n\n // Collect JS property lines\n const jsPropLines: string[] = []\n if (jsAnims.length > 0) {\n const seenProps = new Set<string>()\n for (const anim of jsAnims) {\n for (const prop of anim.properties) {\n if (seenProps.has(prop.property)) continue\n if (!isRealChange(prop)) continue\n seenProps.add(prop.property)\n jsPropLines.push(`- \\`${prop.property}\\`: ${prop.value}`)\n }\n }\n }\n\n // Skip group entirely if nothing to show\n if (cssPropLines.length === 0 && jsPropLines.length === 0) continue\n\n lines.push(`## ${label}\\`${group.selector}\\``)\n lines.push('')\n\n if (cssPropLines.length > 0) {\n const transitionSet = new Set(cssAnims.map((a) => `${a.name} ${a.timing}`))\n lines.push(`Transitions: ${[...transitionSet].join(', ')}`)\n lines.push('')\n for (const line of cssPropLines) lines.push(line)\n\n if (detail === 'detailed' || detail === 'forensic') {\n const allVars: Record<string, string> = {}\n for (const anim of cssAnims) {\n if (anim.resolvedVars) Object.assign(allVars, anim.resolvedVars)\n }\n if (Object.keys(allVars).length > 0) {\n lines.push('')\n lines.push('CSS variables:')\n for (const [name, value] of Object.entries(allVars)) {\n lines.push(`- \\`${name}\\`: ${value}`)\n }\n }\n\n for (const anim of cssAnims) {\n if (anim.source) {\n lines.push('')\n lines.push('```css')\n lines.push(anim.source)\n lines.push('```')\n break\n }\n }\n }\n }\n\n if (jsPropLines.length > 0) {\n if (cssPropLines.length > 0) lines.push('')\n for (const line of jsPropLines) lines.push(line)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n","import { TimingController } from './timing'\nimport { TimelineRecorder } from './recorder'\nimport { TimelineScrubber, type ScrubberState } from './scrubber'\nimport { generateExport, formatExportForLLM } from './export'\nimport type {\n ExportFilter,\n OutputDetailLevel,\n Rect,\n TimelineCapture,\n TimelineExport\n} from './types'\n\nexport type SaccadeState = 'idle' | 'recording' | 'scrubbing'\n\nexport class SaccadeEngine {\n private timing = new TimingController()\n private recorder = new TimelineRecorder()\n private scrubber: TimelineScrubber | null = null\n private capture: TimelineCapture | null = null\n private _state: SaccadeState = 'idle'\n private listeners = new Set<() => void>()\n\n get state(): SaccadeState {\n return this._state\n }\n\n getCapture(): TimelineCapture | null {\n return this.capture\n }\n\n // -- Speed control --------------------------------------------------------\n\n setSpeed(speed: number): void {\n this.timing.setSpeed(speed)\n }\n\n getSpeed(): number {\n return this.timing.getSpeed()\n }\n\n // -- Timeline recording ---------------------------------------------------\n\n startRecording(boundingBox?: Rect | null): void {\n if (this._state !== 'idle') return\n this.timing.install()\n this.recorder.onAutoStop = () => this.stopRecording()\n this.recorder.startRecording(boundingBox)\n this._state = 'recording'\n this.notify()\n }\n\n stopRecording(): TimelineCapture {\n if (this._state !== 'recording') {\n return {\n startTime: 0, endTime: 0, duration: 0,\n animations: [], frames: [], boundingBox: null\n }\n }\n\n let capture: TimelineCapture\n try {\n capture = this.recorder.stopRecording()\n } catch (e) {\n console.error('[Saccade] stopRecording failed:', e)\n // Clean up any artifacts the recorder injected before the error\n document.getElementById('__lapse-scrub-blocker')?.remove()\n document.getElementById('__lapse-no-transitions')?.remove()\n document.getElementById('__lapse-state-rules')?.remove()\n this._state = 'idle'\n this.notify()\n return {\n startTime: 0, endTime: 0, duration: 0,\n animations: [], frames: [], boundingBox: null\n }\n }\n\n this.capture = capture\n\n // Create scrubber with recorder's state\n const scrubberState: ScrubberState = {\n elements: this.recorder.elements,\n frames: capture.frames,\n capturedPortals: this.recorder.capturedPortalIds,\n interceptedAnimations: this.recorder.interceptedAnimations,\n SAFE_PROPS_SET: this.recorder.SAFE_PROPS_SET\n }\n this.scrubber = new TimelineScrubber(scrubberState)\n\n this._state = 'scrubbing'\n this.notify()\n return capture\n }\n\n // -- Scrubbing ------------------------------------------------------------\n\n seekTo(timeMs: number): void {\n this.scrubber?.seekTo(timeMs)\n }\n\n release(): void {\n this.scrubber?.release()\n this.scrubber = null\n this.capture = null\n this._state = 'idle'\n this.notify()\n }\n\n // -- Export ---------------------------------------------------------------\n\n generateExport(timeMs: number, filter: ExportFilter = 'active'): TimelineExport | null {\n if (!this.capture) return null\n return generateExport(\n this.capture.animations,\n this.capture.frames,\n timeMs,\n filter\n )\n }\n\n exportForLLM(timeMs: number, filter: ExportFilter = 'active', detail: OutputDetailLevel = 'standard'): string {\n const exp = this.generateExport(timeMs, filter)\n if (!exp) return ''\n return formatExportForLLM(exp, detail)\n }\n\n // -- State subscription ---------------------------------------------------\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener()\n }\n }\n\n // -- Cleanup --------------------------------------------------------------\n\n destroy(): void {\n this.scrubber?.release()\n this.scrubber = null\n this.capture = null\n this.timing.destroy()\n this._state = 'idle'\n }\n}\n","import { useRef, useCallback } from 'react'\nimport { Timeline } from './Timeline'\nimport { SpeedControl } from './SpeedControl'\nimport { useTimeline } from './useTimeline'\nimport { useSpeed } from './useSpeed'\n\nexport function SaccadePanel() {\n const timeline = useTimeline()\n const { speed, isPaused, setSpeed, togglePause } = useSpeed()\n const panelRef = useRef<HTMLDivElement>(null)\n const warmTimeout = useRef<ReturnType<typeof setTimeout>>(null)\n\n // When mouse enters a tooltipped element, mark the panel as \"warm\"\n // so subsequent tooltips appear instantly. Goes cold 300ms after leaving.\n const handleMouseOver = useCallback((e: React.MouseEvent) => {\n const target = (e.target as HTMLElement).closest?.('[data-tooltip]')\n if (target && panelRef.current) {\n panelRef.current.classList.add('lapse-tooltip-warm')\n if (warmTimeout.current) clearTimeout(warmTimeout.current)\n }\n }, [])\n\n const handleMouseOut = useCallback((e: React.MouseEvent) => {\n const related = e.relatedTarget as HTMLElement | null\n const stillOnTooltip = related?.closest?.('[data-tooltip]')\n if (!stillOnTooltip) {\n warmTimeout.current = setTimeout(() => {\n panelRef.current?.classList.remove('lapse-tooltip-warm')\n }, 300)\n }\n }, [])\n\n return (\n <div\n ref={panelRef}\n className=\"lapse-panel\"\n onMouseOver={handleMouseOver}\n onMouseOut={handleMouseOut}\n >\n <Timeline\n state={timeline.state}\n capture={timeline.capture}\n scrubTime={timeline.scrubTime}\n copied={timeline.copied}\n exportFilter={timeline.exportFilter}\n onSetExportFilter={timeline.setExportFilter}\n onStartRecording={() => timeline.startRecording()}\n onStopRecording={timeline.stopRecording}\n onSeek={timeline.seek}\n onRelease={timeline.release}\n onExportLLM={() => timeline.exportLLM()}\n detailLevel={timeline.detailLevel}\n onCycleDetailLevel={timeline.cycleDetailLevel}\n />\n {timeline.state !== 'scrubbing' && (\n <div className={`lapse-speed-wrap ${timeline.state === 'recording' ? 'lapse-speed-wrap--hidden' : ''}`}>\n <SpeedControl\n speed={speed}\n isPaused={isPaused}\n onSetSpeed={setSpeed}\n onTogglePause={togglePause}\n />\n </div>\n )}\n </div>\n )\n}\n","import { useCallback, useRef, useState, useEffect, type MouseEvent, type CSSProperties } from 'react'\nimport type { ExportFilter, OutputDetailLevel, TimelineCapture } from '../core/types'\nimport type { SaccadeState } from '../core/engine'\n\nconst DETAIL_LEVELS: OutputDetailLevel[] = ['compact', 'standard', 'detailed', 'forensic']\nconst DETAIL_LABELS: Record<OutputDetailLevel, string> = {\n compact: 'Compact',\n standard: 'Standard',\n detailed: 'Detailed',\n forensic: 'Forensic',\n}\n\nfunction CopyCheckIcon({ copied }: { copied: boolean }) {\n // Copy square: x=2 y=7 w=7 h=7 rx=1.5 stroke=2, center (5.5, 10.5)\n // Target circle: centered at (8,8), rx=6.5 (midpoint of 5.5–7.5 ring), w/h=13, stroke=2\n const spring = 'cubic-bezier(0.34, 1.15, 0.64, 1)'\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n {/* Back L-shape — fades out */}\n <path\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n d=\"M7 4v-.5A1.5 1.5 0 0 1 8.5 2h4A1.5 1.5 0 0 1 14 3.5v4A1.5 1.5 0 0 1 12.5 9H12\"\n style={{\n opacity: copied ? 0 : 1,\n transition: copied\n ? 'opacity 0.1s ease-out'\n : 'opacity 0.15s ease-out 0.18s',\n }}\n />\n {/* Square → circle morph */}\n <rect\n stroke={copied ? '#33C664' : 'currentColor'}\n fill=\"none\"\n style={{\n x: copied ? 1.5 : 2,\n y: copied ? 1.5 : 7,\n width: copied ? 13 : 7,\n height: copied ? 13 : 7,\n rx: copied ? 6.5 : 1.5,\n ry: copied ? 6.5 : 1.5,\n strokeWidth: 2,\n transition: copied\n ? `x 0.28s ${spring}, y 0.28s ${spring}, width 0.28s ${spring}, height 0.28s ${spring}, rx 0.28s ${spring}, ry 0.28s ${spring}`\n : 'x 0.22s ease-in-out, y 0.22s ease-in-out, width 0.22s ease-in-out, height 0.22s ease-in-out, rx 0.22s ease-in-out, ry 0.22s ease-in-out',\n } as React.CSSProperties}\n />\n {/* Checkmark — draws in at exact target coordinates */}\n <path\n d=\"m5.5 8.5 2 1.5 2.75-3.75\"\n stroke={copied ? '#33C664' : 'currentColor'}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n style={{\n strokeDasharray: 12,\n strokeDashoffset: copied ? 0 : 12,\n opacity: copied ? 1 : 0,\n transition: copied\n ? 'stroke-dashoffset 0.25s ease-out 0.1s, opacity 0.08s ease-out 0.08s'\n : 'stroke-dashoffset 0.12s ease-in, opacity 0.08s ease-in',\n }}\n />\n </svg>\n )\n}\n\nconst DETAIL_BRIGHT_COUNT: Record<OutputDetailLevel, number> = {\n compact: 1,\n standard: 2,\n detailed: 3,\n forensic: 4,\n}\n\nfunction DetailIcon({ level }: { level: OutputDetailLevel }) {\n const bright = DETAIL_BRIGHT_COUNT[level]\n // Lines at y=2, y=6, y=10, y=14 (top to bottom)\n const ys = [2, 6, 10, 14]\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n {ys.map((y, i) => (\n <path\n key={y}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth=\"2\"\n d=\"M2 0h12\"\n transform={`translate(0, ${y})`}\n style={{\n opacity: i < bright ? 1 : 0.4,\n transition: 'opacity 0.2s ease-out',\n }}\n />\n ))}\n </svg>\n )\n}\n\ntype TimelineProps = {\n state: SaccadeState\n capture: TimelineCapture | null\n scrubTime: number\n copied: boolean\n exportFilter: ExportFilter\n onSetExportFilter: (f: ExportFilter) => void\n onStartRecording: () => void\n onStopRecording: () => void\n onSeek: (timeMs: number) => void\n onRelease: () => void\n onExportLLM: () => void\n detailLevel: OutputDetailLevel\n onCycleDetailLevel: () => void\n}\n\nexport function Timeline({\n state,\n capture,\n scrubTime,\n copied,\n onStartRecording,\n onStopRecording,\n onSeek,\n onRelease,\n onExportLLM,\n detailLevel,\n onCycleDetailLevel\n}: TimelineProps) {\n const scrubberRef = useRef<HTMLDivElement>(null)\n const isDragging = useRef(false)\n const [hasLeftRecord, setHasLeftRecord] = useState(false)\n\n useEffect(() => {\n if (state === 'recording') setHasLeftRecord(false)\n }, [state])\n\n const handleScrub = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n if (!capture || !scrubberRef.current) return\n const rect = scrubberRef.current.getBoundingClientRect()\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n onSeek(x * capture.duration)\n },\n [capture, onSeek]\n )\n\n const handleMouseDown = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n isDragging.current = true\n handleScrub(e)\n\n const handleMouseMove = (e: globalThis.MouseEvent) => {\n if (!isDragging.current || !capture || !scrubberRef.current) return\n const rect = scrubberRef.current.getBoundingClientRect()\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n onSeek(x * capture.duration)\n }\n\n const handleMouseUp = () => {\n isDragging.current = false\n window.removeEventListener('mousemove', handleMouseMove)\n window.removeEventListener('mouseup', handleMouseUp)\n }\n\n window.addEventListener('mousemove', handleMouseMove)\n window.addEventListener('mouseup', handleMouseUp)\n },\n [capture, handleScrub, onSeek]\n )\n\n const progress = capture && capture.duration > 0 ? scrubTime / capture.duration : 0\n const isScrubbing = state === 'scrubbing'\n const isRecording = state === 'recording'\n\n function handleMainClick() {\n if (state === 'idle') onStartRecording()\n else if (state === 'recording') onStopRecording()\n else if (state === 'scrubbing') onRelease()\n }\n\n const tooltip = state === 'idle' ? 'Record' : state === 'recording' ? 'Stop' : 'Clear'\n\n return (\n <>\n {/* Main button — morphs between record / recording / close */}\n <button\n onClick={handleMainClick}\n className={`lapse-btn lapse-btn-icon lapse-main-btn ${isRecording ? 'lapse-record-btn--active' : ''}`}\n data-tooltip={tooltip}\n onMouseLeave={isRecording ? () => setHasLeftRecord(true) : undefined}\n >\n {/* Record icon (ring) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${state === 'idle' ? 'lapse-morph-icon--active' : ''}`}\n >\n <path fill=\"currentColor\" d=\"M8 .5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15Zm0 2a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z\"/>\n </svg>\n\n {/* Recording icon (filled circle / square) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${isRecording ? 'lapse-morph-icon--active' : ''}`}\n >\n <rect\n x={hasLeftRecord ? '1.5' : '0.5'}\n y={hasLeftRecord ? '1.5' : '0.5'}\n width={hasLeftRecord ? '13' : '15'}\n height={hasLeftRecord ? '13' : '15'}\n rx={hasLeftRecord ? '3' : '7.5'}\n fill=\"currentColor\"\n className=\"lapse-record-shape\"\n />\n </svg>\n\n {/* Clear icon (undo arrow) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${isScrubbing ? 'lapse-morph-icon--active' : ''}`}\n >\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"m5.5 3-3 3m0 0h7a3.5 3.5 0 1 1 0 7h-2m-5-7 3 3\"/>\n </svg>\n </button>\n\n {/* Scrub content — expands when scrubbing */}\n <div className={`lapse-scrub-wrap ${isScrubbing ? 'lapse-scrub-wrap--visible' : ''}`}>\n <div className=\"lapse-scrub-inner\">\n {/* Scrub track */}\n <div\n ref={scrubberRef}\n onMouseDown={handleMouseDown}\n className=\"lapse-scrub-track\"\n >\n {capture && capture.duration > 0 && (() => {\n const seen = new Set<string>()\n const times: number[] = []\n for (const frame of capture.frames) {\n if (!frame.animations) continue\n for (const fa of frame.animations) {\n if (!seen.has(fa.animationId)) {\n seen.add(fa.animationId)\n times.push(frame.time)\n }\n }\n }\n times.sort((a, b) => a - b)\n const clusters: { time: number; count: number }[] = []\n for (const t of times) {\n const last = clusters[clusters.length - 1]\n if (last && t - last.time < 200) {\n last.count++\n } else {\n clusters.push({ time: t, count: 1 })\n }\n }\n return clusters.map((c, i) => (\n <div\n key={i}\n className=\"lapse-scrub-marker\"\n style={{ left: `${(c.time / capture.duration) * 100}%` }}\n />\n ))\n })()}\n\n <div className=\"lapse-scrub-fill\" style={{ width: `calc(${progress * 100}% + 4px)` }} />\n <div className=\"lapse-scrub-playhead\" style={{ left: `clamp(4px, ${progress * 100}%, calc(100% - 4px))` }} />\n\n <div className=\"lapse-scrub-label\">\n <span>{Math.round(scrubTime)}ms / {Math.round(capture?.duration ?? 0)}ms</span>\n </div>\n </div>\n\n {/* Detail level */}\n <button\n onClick={onCycleDetailLevel}\n className=\"lapse-btn lapse-btn-icon\"\n data-tooltip={DETAIL_LABELS[detailLevel]}\n >\n <DetailIcon level={detailLevel} />\n </button>\n\n {/* Export */}\n <button onClick={onExportLLM} className=\"lapse-btn lapse-btn-icon\" data-tooltip={copied ? 'Copied!' : 'Copy'}>\n <CopyCheckIcon copied={copied} />\n </button>\n </div>\n </div>\n </>\n )\n}\n","import { useRef, useCallback } from 'react'\nimport { formatSpeed } from './constants'\n\nconst SPEEDS = [1, 0.75, 0.5, 0.25, 0.1] as const\n\n// Angles matching the original icon hand positions (clockwise from 12 o'clock)\nconst SPEED_ANGLES: Record<number, number> = {\n 0.1: 225, // 7 o'clock\n 0.25: 315, // 10 o'clock\n 0.5: 0, // 12 o'clock\n 0.75: 45, // 2 o'clock\n 1: 135, // 4 o'clock\n}\n\n// Hand paths extracted from original icons (drawn at 12 o'clock / 0°)\n// These are the exact hand shapes — we rotate the <g> to position them\n// Original hand path at 12 o'clock (0.5x icon):\nconst HAND_PATH = 'm0 2a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1Z'\n\n// Actually, the hands are all different shapes at different angles in your icons.\n// To keep the exact icon shapes, I'll overlay all 5 hand paths and show/hide the active one.\n// The circle ring stays static, only the hand swaps.\n\n// Hand paths from the original icons (everything after the circle ring path)\nconst HAND_PATHS: Record<number, string> = {\n 0.1: 'M7.293 5.293a1 1 0 1 1 1.414 1.414l-1.5 1.5a1 1 0 1 1-1.414-1.414l1.5-1.5Z',\n 0.25: 'M5.793 5.794a1 1 0 0 1 1.414 0l1.5 1.499a1 1 0 0 1-1.414 1.414l-1.5-1.499a1 1 0 0 1 0-1.414Z',\n 0.5: 'M8 5a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1Z',\n 0.75: 'M8.793 5.293a1 1 0 0 1 1.414 1.414l-1.5 1.5a1 1 0 0 1-1.414-1.414l1.5-1.5Z',\n 1: 'M7.293 8.293a1 1 0 0 1 1.414 0l1.5 1.5a1 1 0 1 1-1.414 1.414l-1.5-1.5a1 1 0 0 1 0-1.414Z',\n}\n\ntype SpeedControlProps = {\n speed: number\n isPaused: boolean\n onSetSpeed: (speed: number) => void\n onTogglePause: () => void\n}\n\nexport function SpeedControl({ speed, isPaused, onSetSpeed, onTogglePause }: SpeedControlProps) {\n const currentIndex = SPEEDS.findIndex((s) => Math.abs(speed - s) < 0.001)\n const activeIndex = currentIndex >= 0 ? currentIndex : 0\n const prevAngleRef = useRef(SPEED_ANGLES[SPEEDS[activeIndex]])\n const cumulativeRef = useRef(SPEED_ANGLES[SPEEDS[activeIndex]])\n const directionRef = useRef<1 | -1>(1) // 1 = going down (slowing), -1 = going up (speeding)\n const forceClockwiseRef = useRef(false)\n\n function cycle() {\n if (isPaused) {\n onTogglePause()\n return\n }\n let next = activeIndex + directionRef.current\n // Bounce at ends\n if (next >= SPEEDS.length) {\n directionRef.current = -1\n next = activeIndex - 1\n } else if (next < 0) {\n directionRef.current = 1\n next = activeIndex + 1\n }\n onSetSpeed(SPEEDS[next])\n }\n\n // Calculate rotation — shortest path normally, forced direction for pause/hold\n const targetAngle = isPaused ? 180 : (SPEED_ANGLES[SPEEDS[activeIndex]] ?? 135)\n if (targetAngle !== prevAngleRef.current) {\n let delta = targetAngle - prevAngleRef.current\n if (isPaused) {\n // Anticlockwise — drops to 6 o'clock\n while (delta >= 0) delta -= 360\n } else if (forceClockwiseRef.current) {\n // Hold reset — always clockwise\n while (delta <= 0) delta += 360\n forceClockwiseRef.current = false\n } else {\n // Shortest path\n while (delta > 180) delta -= 360\n while (delta < -180) delta += 360\n }\n cumulativeRef.current += delta\n prevAngleRef.current = targetAngle\n }\n\n // Press-and-hold to jump back to 1x\n const holdTimerRef = useRef<ReturnType<typeof setTimeout>>(null)\n const didHoldRef = useRef(false)\n\n const startHold = useCallback(() => {\n didHoldRef.current = false\n holdTimerRef.current = setTimeout(() => {\n didHoldRef.current = true\n forceClockwiseRef.current = true\n directionRef.current = 1\n onSetSpeed(1)\n }, 240)\n }, [onSetSpeed])\n\n const endHold = useCallback(() => {\n if (holdTimerRef.current) clearTimeout(holdTimerRef.current)\n holdTimerRef.current = null\n }, [])\n\n const handleClick = useCallback(() => {\n if (didHoldRef.current) {\n didHoldRef.current = false\n return\n }\n cycle()\n }, [cycle])\n\n const currentSpeed = SPEEDS[activeIndex]\n\n return (\n <div className=\"lapse-speed\">\n <button\n onClick={onTogglePause}\n className=\"lapse-btn lapse-btn-icon lapse-playpause\"\n data-tooltip={isPaused ? 'Play' : 'Pause'}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className={`lapse-playpause-icon ${isPaused ? 'lapse-playpause-icon--active' : ''}`} style={{ marginLeft: 1 }}>\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"2\" d=\"M3 12.821V3.18a1 1 0 0 1 1.476-.88l8.9 4.822a1 1 0 0 1 0 1.758l-8.9 4.821A1 1 0 0 1 3 12.821Z\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className={`lapse-playpause-icon ${!isPaused ? 'lapse-playpause-icon--active' : ''}`}>\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"2\" d=\"M3.5 2.5v11m9-11v11\"/>\n </svg>\n </button>\n\n <button\n onClick={handleClick}\n onMouseDown={startHold}\n onMouseUp={endHold}\n onMouseLeave={endHold}\n className=\"lapse-speed-cycle\"\n data-tooltip={formatSpeed(speed)}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"lapse-speed-clock\">\n {/* Circle ring — static */}\n <path fill=\"currentColor\" d=\"M8 .5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15Zm0 2a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z\" />\n {/* Hand — rotated to match position, always clockwise */}\n <g style={{ transform: `rotate(${cumulativeRef.current}deg)`, transformOrigin: '8px 8px', transition: 'transform 0.4s cubic-bezier(0, 0.55, 0.45, 1)' }}>\n {/* Use the 12 o'clock hand (0.5x), rotation handles positioning */}\n <path fill=\"currentColor\" d={HAND_PATHS[0.5]} />\n </g>\n </svg>\n </button>\n </div>\n )\n}\n","export const SPEED_PRESETS = [0.1, 0.25, 0.5, 0.75, 1] as const\n\nexport const SPEED_MIN = 0.05\nexport const SPEED_MAX = 5\n\nexport function formatSpeed(speed: number): string {\n if (speed >= 0.1) return `${speed}\\u00d7`\n return `${speed.toFixed(2)}\\u00d7`\n}\n","import { useState, useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useSaccadeEngine } from './SaccadeContext'\nimport type { ExportFilter, OutputDetailLevel, Rect, TimelineCapture } from '../core/types'\nimport type { SaccadeState } from '../core/engine'\n\nconst DETAIL_LEVELS: OutputDetailLevel[] = ['compact', 'standard', 'detailed', 'forensic']\n\nexport function useTimeline() {\n const engine = useSaccadeEngine()\n\n const state = useSyncExternalStore(\n (cb) => engine.subscribe(cb),\n () => engine.state\n ) as SaccadeState\n\n const [capture, setCapture] = useState<TimelineCapture | null>(null)\n const [scrubTime, setScrubTime] = useState(0)\n const [copied, setCopied] = useState(false)\n const [exportFilter, setExportFilter] = useState<ExportFilter>('all-animations')\n const [detailLevel, setDetailLevel] = useState<OutputDetailLevel>('standard')\n const copiedTimeout = useRef<ReturnType<typeof setTimeout>>(null)\n\n // Throttle seek calls to one per animation frame\n const pendingSeek = useRef<number | null>(null)\n const rafId = useRef<number>(0)\n\n // Sync capture from engine when auto-stop transitions state to scrubbing\n useEffect(() => {\n if (state === 'scrubbing' && !capture) {\n const engineCapture = engine.getCapture()\n if (engineCapture) {\n setCapture(engineCapture)\n setScrubTime(0)\n }\n } else if (state === 'idle') {\n setCapture(null)\n setScrubTime(0)\n }\n }, [state, capture, engine])\n\n const startRecording = useCallback(\n (boundingBox?: Rect | null) => {\n setCapture(null)\n setScrubTime(0)\n engine.startRecording(boundingBox)\n },\n [engine]\n )\n\n const stopRecording = useCallback(() => {\n try {\n const result = engine.stopRecording()\n setCapture(result)\n setScrubTime(0)\n } catch (e) {\n console.error('[Saccade] stopRecording failed:', e)\n }\n }, [engine])\n\n const seek = useCallback(\n (timeMs: number) => {\n setScrubTime(timeMs)\n pendingSeek.current = timeMs\n if (!rafId.current) {\n rafId.current = requestAnimationFrame(() => {\n rafId.current = 0\n if (pendingSeek.current !== null) {\n engine.seekTo(pendingSeek.current)\n pendingSeek.current = null\n }\n })\n }\n },\n [engine]\n )\n\n const release = useCallback(() => {\n if (rafId.current) { cancelAnimationFrame(rafId.current); rafId.current = 0 }\n pendingSeek.current = null\n engine.release()\n setCapture(null)\n setScrubTime(0)\n }, [engine])\n\n const cycleDetailLevel = useCallback(() => {\n setDetailLevel((prev) => {\n const idx = DETAIL_LEVELS.indexOf(prev)\n return DETAIL_LEVELS[(idx + 1) % DETAIL_LEVELS.length]\n })\n }, [])\n\n const exportLLM = useCallback(\n (filter?: ExportFilter) => {\n if (!capture) return ''\n const f = filter || exportFilter || 'active'\n const t = Number(scrubTime) || 0\n const text = engine.exportForLLM(t, f, detailLevel)\n navigator.clipboard.writeText(text).catch(() => {})\n setCopied(true)\n if (copiedTimeout.current) clearTimeout(copiedTimeout.current)\n copiedTimeout.current = setTimeout(() => setCopied(false), 2000)\n return text\n },\n [engine, capture, scrubTime, exportFilter, detailLevel]\n )\n\n return {\n state,\n capture,\n scrubTime,\n copied,\n exportFilter,\n setExportFilter,\n detailLevel,\n cycleDetailLevel,\n startRecording,\n stopRecording,\n seek,\n release,\n exportLLM\n }\n}\n","import { useState, useCallback, useEffect } from 'react'\nimport { useSaccadeEngine } from './SaccadeContext'\nimport { SPEED_PRESETS, SPEED_MIN, SPEED_MAX } from './constants'\n\nexport function useSpeed() {\n const engine = useSaccadeEngine()\n const [speed, setSpeedState] = useState(1)\n const [previousSpeed, setPreviousSpeed] = useState(1)\n const [isPaused, setIsPaused] = useState(false)\n\n const setSpeed = useCallback(\n (value: number) => {\n const clamped = Math.max(SPEED_MIN, Math.min(SPEED_MAX, value))\n setSpeedState(clamped)\n setIsPaused(false)\n setPreviousSpeed(clamped)\n engine.setSpeed(clamped)\n },\n [engine]\n )\n\n const togglePause = useCallback(() => {\n if (isPaused) {\n setSpeedState(previousSpeed)\n setIsPaused(false)\n engine.setSpeed(previousSpeed)\n } else {\n setPreviousSpeed(speed)\n setSpeedState(0)\n setIsPaused(true)\n engine.setSpeed(0)\n }\n }, [engine, isPaused, previousSpeed, speed])\n\n const stepDown = useCallback(() => {\n const currentIndex = SPEED_PRESETS.findIndex((p) => p >= speed)\n const nextIndex = Math.max(0, (currentIndex <= 0 ? 1 : currentIndex) - 1)\n setSpeed(SPEED_PRESETS[nextIndex])\n }, [speed, setSpeed])\n\n const stepUp = useCallback(() => {\n const currentIndex = SPEED_PRESETS.findIndex((p) => p > speed)\n const nextIndex = Math.min(\n SPEED_PRESETS.length - 1,\n currentIndex < 0 ? SPEED_PRESETS.length - 1 : currentIndex\n )\n setSpeed(SPEED_PRESETS[nextIndex])\n }, [speed, setSpeed])\n\n // Keyboard shortcuts\n useEffect(() => {\n function handleKeyDown(e: KeyboardEvent) {\n if (e.target instanceof HTMLInputElement) return\n switch (e.key) {\n case '[':\n stepDown()\n break\n case ']':\n stepUp()\n break\n case '\\\\':\n setSpeed(1)\n break\n case 's':\n togglePause()\n break\n }\n }\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [stepDown, stepUp, setSpeed, togglePause])\n\n return { speed, isPaused, setSpeed, togglePause }\n}\n","/** Panel styles injected into the Shadow DOM. */\nexport const PANEL_STYLES = /* css */ `\n :host {\n --lapse-bg: #1a1a1a;\n --lapse-surface: #2a2a2a;\n --lapse-border: #3a3a3a;\n --lapse-text: #e5e5e5;\n --lapse-text-muted: #888;\n --lapse-accent: #6d9fff;\n --lapse-speed-active: #5b8def;\n --lapse-danger: #ff6b6b;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: var(--lapse-text);\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* Tooltips */\n [data-tooltip] {\n position: relative;\n }\n [data-tooltip]::after {\n content: attr(data-tooltip);\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%) translateY(2px) scale(0.96);\n padding: 4px 10px;\n border-radius: 6px;\n background: #0d0d0d;\n border: 0.5px solid var(--lapse-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n color: var(--lapse-text);\n font-size: 11px;\n font-weight: 500;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.15s ease-out 0.65s, transform 0.15s ease-out 0.65s;\n }\n [data-tooltip]:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0) scale(1);\n }\n /* Warm: when panel already has a tooltip showing, new ones appear instantly */\n .lapse-panel.lapse-tooltip-warm [data-tooltip]::after {\n transition-duration: 0s;\n transition-delay: 0s;\n }\n\n /* Panel container */\n .lapse-panel {\n display: flex;\n align-items: center;\n gap: 0;\n background: var(--lapse-bg);\n border: 0.5px solid var(--lapse-border);\n border-radius: 999px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1);\n overflow: visible;\n }\n\n /* Buttons */\n .lapse-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 12px;\n border: none;\n border-radius: 999px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.15s, color 0.15s;\n }\n\n .lapse-btn-surface {\n background: transparent;\n color: var(--lapse-text-muted);\n }\n .lapse-btn-surface:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n\n .lapse-btn-recording {\n background: rgba(239, 68, 68, 0.1);\n color: #f87171;\n }\n .lapse-btn-recording:hover { background: rgba(239, 68, 68, 0.2); }\n\n .lapse-btn-accent {\n background: rgba(109, 159, 255, 0.2);\n color: var(--lapse-accent);\n font-size: 13px;\n }\n .lapse-btn-accent:hover { background: rgba(109, 159, 255, 0.3); }\n\n .lapse-btn-icon {\n width: 32px;\n height: 32px;\n padding: 0;\n justify-content: center;\n background: transparent;\n color: var(--lapse-text-muted);\n border: none;\n border-radius: 999px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n .lapse-btn-icon:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n .lapse-record-btn--active:hover {\n color: #ef4444;\n }\n\n /* Main button — icon morphing (record / recording / close) */\n .lapse-main-btn {\n position: relative;\n }\n\n .lapse-morph-icon {\n position: absolute;\n opacity: 0;\n scale: 0.4;\n filter: blur(6px);\n transition: opacity 0.2s ease, scale 0.2s ease, filter 0.2s ease;\n display: block;\n }\n .lapse-morph-icon--active {\n opacity: 1;\n scale: 1;\n filter: blur(0);\n }\n\n .lapse-record-shape {\n animation: lapse-pulse 1.5s ease-in-out infinite;\n transition: x 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n y 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n width 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n height 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n rx 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n\n .lapse-record-btn--active {\n color: #ef4444;\n }\n\n @keyframes lapse-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n /* Scrub content — expands when entering scrubbing state */\n .lapse-scrub-wrap {\n display: grid;\n grid-template-columns: 0fr;\n margin-left: 0;\n transition: grid-template-columns 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n margin-left 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-scrub-wrap > * {\n min-width: 0;\n }\n .lapse-scrub-wrap--visible {\n grid-template-columns: 1fr;\n margin-left: 6px;\n }\n\n .lapse-scrub-inner {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .lapse-scrub-inner > * {\n transform-origin: left center;\n transition: opacity 0.6s cubic-bezier(0.19, 1, 0.22, 1) 0.05s,\n transform 0.6s cubic-bezier(0.19, 1, 0.22, 1) 0.05s,\n filter 0.8s cubic-bezier(0.19, 1, 0.22, 1) 0.05s;\n }\n .lapse-scrub-wrap:not(.lapse-scrub-wrap--visible) .lapse-scrub-inner > * {\n opacity: 0;\n transform: scale(0.85);\n filter: blur(10px);\n transition-delay: 0ms;\n transition-duration: 0.15s;\n }\n\n /* Spinner */\n .lapse-spinner {\n width: 10px;\n height: 10px;\n animation: lapse-spin 1s linear infinite;\n }\n .lapse-spinner-track { opacity: 0.25; }\n .lapse-spinner-head { opacity: 0.75; }\n\n @keyframes lapse-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n /* Scrubber */\n .lapse-scrub-track {\n position: relative;\n height: 32px;\n width: 200px;\n cursor: pointer;\n border-radius: 6px;\n background: var(--lapse-surface);\n user-select: none;\n overflow: hidden;\n }\n\n .lapse-scrub-marker {\n position: absolute;\n top: 0;\n height: 100%;\n width: 1px;\n background: rgba(109, 159, 255, 0.5);\n pointer-events: none;\n }\n\n .lapse-scrub-fill {\n position: absolute;\n inset: 0;\n right: auto;\n background: rgba(109, 159, 255, 0.1);\n pointer-events: none;\n }\n\n .lapse-scrub-playhead {\n position: absolute;\n top: 4px;\n bottom: 4px;\n width: 2px;\n border-radius: 1px;\n background: var(--lapse-accent);\n transform: translateX(-50%);\n pointer-events: none;\n }\n\n .lapse-scrub-label {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n padding-bottom: 2px;\n pointer-events: none;\n }\n .lapse-scrub-label span {\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n color: var(--lapse-text-muted);\n }\n\n /* Filter buttons */\n .lapse-filter-group {\n display: flex;\n border-radius: 6px;\n background: var(--lapse-surface);\n overflow: hidden;\n }\n\n .lapse-filter-btn {\n height: 32px;\n padding: 0 8px;\n border: none;\n background: transparent;\n font-size: 13px;\n font-weight: 500;\n color: var(--lapse-text-muted);\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n .lapse-filter-btn:hover { color: var(--lapse-text); }\n .lapse-filter-btn--active {\n background: rgba(109, 159, 255, 0.2);\n color: var(--lapse-accent);\n }\n\n /* Chevron */\n .lapse-chevron {\n transition: transform 0.2s;\n }\n .lapse-chevron--open {\n transform: rotate(90deg);\n }\n\n /* Animation tags */\n .lapse-anim-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .lapse-anim-tag {\n background: rgba(109, 159, 255, 0.1);\n color: var(--lapse-accent);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 13px;\n }\n\n /* Speed control wrapper — collapses when recording */\n .lapse-speed-wrap {\n display: grid;\n grid-template-columns: 1fr;\n margin-left: 6px;\n transition: grid-template-columns 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n margin-left 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-speed-wrap > * {\n min-width: 0;\n }\n .lapse-speed-wrap--hidden {\n grid-template-columns: 0fr;\n margin-left: 0;\n pointer-events: none;\n }\n .lapse-speed-wrap .lapse-speed {\n transition: transform 0.6s cubic-bezier(0.19, 1, 0.22, 1),\n filter 0.8s cubic-bezier(0.19, 1, 0.22, 1),\n opacity 0.6s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-speed-wrap--hidden .lapse-speed {\n transform: translateX(-8px) scale(0.4);\n filter: blur(10px);\n opacity: 0;\n }\n\n /* Speed control */\n .lapse-speed {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n /* Speed cycle button */\n .lapse-speed-cycle {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 8px;\n border: none;\n border-radius: 999px;\n background: transparent;\n color: var(--lapse-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n white-space: nowrap;\n }\n .lapse-speed-cycle:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n\n /* Play/pause transition */\n .lapse-playpause {\n position: relative;\n }\n\n .lapse-playpause-icon {\n position: absolute;\n opacity: 0;\n scale: 0.4;\n filter: blur(6px);\n transition: opacity 0.2s ease, scale 0.2s ease, filter 0.2s ease;\n display: block;\n }\n\n .lapse-playpause-icon--active {\n opacity: 1;\n scale: 1;\n filter: blur(0);\n }\n\n .lapse-speed-cycle svg {\n display: block;\n }\n`\n"],"mappings":"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","names":["import_react","keyframes","import_react","import_react","import_jsx_runtime","e","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/react/Saccade.tsx","../src/react/SaccadeContext.tsx","../src/core/timing.ts","../src/core/recorder.ts","../src/core/scrubber.ts","../src/core/export.ts","../src/core/engine.ts","../src/react/SaccadePanel.tsx","../src/react/Timeline.tsx","../src/react/SpeedControl.tsx","../src/react/constants.ts","../src/react/useTimeline.ts","../src/react/useSpeed.ts","../src/react/styles.ts"],"sourcesContent":["// React components\nexport { Saccade, type SaccadeProps, type SaccadePosition } from './react/Saccade'\nexport { SaccadeProvider, useSaccadeEngine } from './react/SaccadeContext'\nexport { useTimeline } from './react/useTimeline'\nexport { useSpeed } from './react/useSpeed'\n\n// Core engine (re-export for convenience)\nexport { SaccadeEngine, type SaccadeState } from './core/engine'\n\n// Types\nexport type {\n AnimationInfo,\n ExportFilter,\n FrameSnapshot,\n OutputDetailLevel,\n Rect,\n TimelineCapture,\n TimelineExport\n} from './core/types'\n","import { useRef, useState, useEffect } from 'react'\nimport { createPortal } from 'react-dom'\nimport { SaccadeProvider } from './SaccadeContext'\nimport { SaccadePanel } from './SaccadePanel'\nimport { PANEL_STYLES } from './styles'\n\nexport type SaccadePosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n\nexport type SaccadeProps = {\n /** Panel position. Default: 'bottom-left' */\n position?: SaccadePosition\n}\n\nexport function Saccade({ position = 'bottom-left' }: SaccadeProps) {\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n const hostRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n // Create host element directly on document.body so it's always in the\n // root stacking context — guarantees z-index beats the scrub blocker\n // regardless of ancestor stacking contexts in the consumer app.\n const host = document.createElement('div')\n host.setAttribute('data-lapse-panel', '')\n\n const positionOffset = position === 'top-left' ? 'top:20px;left:20px'\n : position === 'top-right' ? 'top:20px;right:20px'\n : position === 'bottom-left' ? 'bottom:20px;left:20px'\n : 'bottom:20px;right:20px'\n\n host.style.cssText = `position:fixed;z-index:2147483647;pointer-events:auto;${positionOffset}`\n document.body.appendChild(host)\n hostRef.current = host\n\n const shadow = host.attachShadow({ mode: 'open' })\n\n const style = document.createElement('style')\n style.textContent = PANEL_STYLES\n shadow.appendChild(style)\n\n const mount = document.createElement('div')\n shadow.appendChild(mount)\n\n setShadowRoot(shadow)\n\n return () => {\n host.remove()\n hostRef.current = null\n }\n }, [position])\n\n if (!shadowRoot) return null\n\n return createPortal(\n <SaccadeProvider>\n <SaccadePanel />\n </SaccadeProvider>,\n shadowRoot.lastElementChild || shadowRoot\n )\n}\n","import { createContext, useContext, useRef, type ReactNode } from 'react'\nimport { SaccadeEngine } from '../core/engine'\n\nconst SaccadeContext = createContext<SaccadeEngine | null>(null)\n\nexport function SaccadeProvider({ children }: { children: ReactNode }) {\n const engineRef = useRef<SaccadeEngine | null>(null)\n if (!engineRef.current) {\n engineRef.current = new SaccadeEngine()\n }\n return (\n <SaccadeContext.Provider value={engineRef.current}>\n {children}\n </SaccadeContext.Provider>\n )\n}\n\nexport function useSaccadeEngine(): SaccadeEngine {\n const engine = useContext(SaccadeContext)\n if (!engine) throw new Error('useSaccadeEngine must be used within <SaccadeProvider>')\n return engine\n}\n","/**\n * Timing controller — patches all JS timing APIs to respect a speed factor.\n *\n * At 0.5x speed, a 100ms setTimeout becomes 200ms real time, and\n * performance.now() / rAF timestamps advance at half rate.\n */\n\n/** Tracks developer-intended vs saccade-applied playbackRate per Animation. */\ninterface TrackedAnimation {\n original: number\n applied: number\n}\n\n/** Tracks developer-intended vs saccade-applied playbackRate per media element. */\ninterface TrackedMedia {\n original: number\n applied: number\n}\n\n/** Browser-valid playbackRate range for media elements. */\nconst MEDIA_RATE_MIN = 0.0625\nconst MEDIA_RATE_MAX = 16\n\n/** Near-zero divisor for speed=0 timers (effectively infinite delay). */\nconst ZERO_SPEED_DIVISOR = 0.0001\n\nexport class TimingController {\n private speed = 1\n private realBaseline: number\n private virtualBaseline = 0\n private dateRealBaseline: number\n private dateVirtualBaseline: number\n private intervalMap = new Map<number, { handler: TimerHandler; delay: number; realId: number }>()\n private nextIntervalId = 1_000_000\n private _origAnimate: typeof Element.prototype.animate | null = null\n private installed = false\n private animPollId = 0\n\n // WeakMap tracking for animations and media\n private trackedAnims = new WeakMap<Animation, TrackedAnimation>()\n private trackedMedia = new WeakMap<HTMLMediaElement, TrackedMedia>()\n\n // Preserved originals\n private _raf: typeof requestAnimationFrame\n private _caf: typeof cancelAnimationFrame\n private _setTimeout: typeof setTimeout\n private _clearTimeout: typeof clearTimeout\n private _setInterval: typeof setInterval\n private _clearInterval: typeof clearInterval\n private _perfNow: () => number\n private _dateNow: () => number\n\n constructor() {\n this._raf = requestAnimationFrame.bind(window)\n this._caf = cancelAnimationFrame.bind(window)\n this._setTimeout = setTimeout.bind(window)\n this._clearTimeout = clearTimeout.bind(window)\n this._setInterval = setInterval.bind(window)\n this._clearInterval = clearInterval.bind(window)\n this._perfNow = performance.now.bind(performance)\n this._dateNow = Date.now\n this.realBaseline = this._perfNow()\n this.dateRealBaseline = this._dateNow()\n this.dateVirtualBaseline = this.dateRealBaseline\n }\n\n private getVirtualTime(): number {\n const realElapsed = this._perfNow() - this.realBaseline\n return this.virtualBaseline + realElapsed * this.speed\n }\n\n private getVirtualDateNow(): number {\n const realElapsed = this._dateNow() - this.dateRealBaseline\n return this.dateVirtualBaseline + realElapsed * this.speed\n }\n\n private reanchor(): void {\n const virtualNow = this.getVirtualTime()\n this.realBaseline = this._perfNow()\n this.virtualBaseline = virtualNow\n\n const virtualDateNow = this.getVirtualDateNow()\n this.dateRealBaseline = this._dateNow()\n this.dateVirtualBaseline = virtualDateNow\n }\n\n /** Effective speed divisor — avoids division by zero at speed=0. */\n private get speedDivisor(): number {\n return this.speed || ZERO_SPEED_DIVISOR\n }\n\n /** Install timing patches. Safe to call multiple times. */\n install(): void {\n if (this.installed) return\n // Global singleton guard — prevent double-patching if multiple instances exist\n if ((window as any).__saccadeInstalled) return\n ;(window as any).__saccadeInstalled = true\n this.installed = true\n\n const self = this\n\n // Expose original rAF for the recorder's capture loop\n ;(window as any).__LAPSE_ORIGINAL_RAF__ = this._raf\n\n // Intercept Element.prototype.animate to set playbackRate on creation\n const origAnimate = Element.prototype.animate\n this._origAnimate = origAnimate\n Element.prototype.animate = function (...args: Parameters<typeof origAnimate>) {\n const anim = origAnimate.apply(this, args)\n if (self.speed !== 1) {\n const originalRate = anim.playbackRate\n const applied = originalRate * (self.speed || 0.001)\n anim.playbackRate = applied\n self.trackedAnims.set(anim, { original: originalRate, applied })\n }\n return anim\n }\n\n // performance.now()\n performance.now = () => self.getVirtualTime()\n\n // Date.now() — separate virtual clock (critical for Framer Motion)\n Date.now = () => self.getVirtualDateNow()\n\n // requestAnimationFrame — suppress user callbacks at speed=0\n window.requestAnimationFrame = (callback: FrameRequestCallback): number => {\n return self._raf(() => {\n if (self.speed === 0) {\n // Re-enqueue without calling — keeps the loop alive for resume\n window.requestAnimationFrame(callback)\n return\n }\n callback(self.getVirtualTime())\n })\n }\n window.cancelAnimationFrame = this._caf\n\n // setTimeout — freeze at speed=0 via near-infinite delay\n window.setTimeout = ((handler: TimerHandler, delay?: number, ...args: any[]): number => {\n const scaledDelay = (delay ?? 0) / self.speedDivisor\n return self._setTimeout(handler, scaledDelay, ...args) as unknown as number\n }) as typeof window.setTimeout\n\n window.clearTimeout = this._clearTimeout\n\n // setInterval — re-register on each tick to pick up speed changes\n window.setInterval = ((handler: TimerHandler, delay?: number, ...args: any[]): number => {\n const id = self.nextIntervalId++\n const baseDelay = delay ?? 0\n\n function tick() {\n const scaledDelay = baseDelay / self.speedDivisor\n const realId = self._setTimeout(() => {\n if (typeof handler === 'function') {\n ;(handler as Function)(...args)\n }\n if (self.intervalMap.has(id)) tick()\n }, scaledDelay) as unknown as number\n const entry = self.intervalMap.get(id)\n if (entry) entry.realId = realId\n }\n\n self.intervalMap.set(id, { handler, delay: baseDelay, realId: 0 })\n tick()\n return id\n }) as typeof window.setInterval\n\n window.clearInterval = ((id?: number): void => {\n if (id == null) return\n const entry = self.intervalMap.get(id)\n if (entry) {\n self._clearTimeout(entry.realId as any)\n self.intervalMap.delete(id)\n } else {\n self._clearInterval(id)\n }\n }) as typeof window.clearInterval\n\n // Start per-frame polling for animations and media\n this.startAnimationPoll()\n }\n\n /** Set playback speed. Requires install() first. */\n setSpeed(newSpeed: number): void {\n if (!this.installed) this.install()\n this.reanchor()\n this.speed = newSpeed\n // Immediately sync all animations and media\n this.patchAnimations()\n this.patchMedia()\n // GSAP integration\n this.patchGSAP()\n }\n\n getSpeed(): number {\n return this.speed\n }\n\n // ---------------------------------------------------------------------------\n // Animation polling — per-frame via original rAF\n // ---------------------------------------------------------------------------\n\n private startAnimationPoll(): void {\n const poll = () => {\n if (!this.installed) return\n this.patchAnimations()\n this.patchMedia()\n this.animPollId = this._raf(poll)\n }\n this.animPollId = this._raf(poll)\n }\n\n /** Patch playbackRate on all active animations via WAAPI. */\n private patchAnimations(): void {\n try {\n const anims = document.getAnimations()\n for (const anim of anims) {\n // Skip animations on saccade's own UI\n const target = (anim.effect as KeyframeEffect)?.target as HTMLElement | null\n if (target?.closest?.('[data-lapse-panel]')) continue\n // Skip excluded elements\n if (target?.closest?.('[data-saccade-exclude]')) continue\n\n const effectiveSpeed = this.speed || 0.001\n\n let tracked = this.trackedAnims.get(anim)\n if (!tracked) {\n // First time seeing this animation — record its original rate\n tracked = { original: anim.playbackRate, applied: anim.playbackRate }\n this.trackedAnims.set(anim, tracked)\n } else if (anim.playbackRate !== tracked.applied) {\n // Developer changed the rate since we last set it — respect their intent\n tracked.original = anim.playbackRate\n }\n\n const desired = tracked.original * effectiveSpeed\n if (anim.playbackRate !== desired) {\n anim.playbackRate = desired\n tracked.applied = desired\n }\n }\n } catch {}\n }\n\n /** Patch playbackRate on all video/audio elements. */\n private patchMedia(): void {\n try {\n document.querySelectorAll('video, audio').forEach((node) => {\n const el = node as HTMLMediaElement\n if (el.closest?.('[data-lapse-panel]')) return\n if (el.closest?.('[data-saccade-exclude]')) return\n\n let tracked = this.trackedMedia.get(el)\n if (!tracked) {\n tracked = { original: el.playbackRate, applied: el.playbackRate }\n this.trackedMedia.set(el, tracked)\n } else if (el.playbackRate !== tracked.applied) {\n tracked.original = el.playbackRate\n }\n\n const desired = Math.min(MEDIA_RATE_MAX, Math.max(MEDIA_RATE_MIN, tracked.original * (this.speed || MEDIA_RATE_MIN)))\n if (el.playbackRate !== desired) {\n el.playbackRate = desired\n tracked.applied = desired\n }\n })\n } catch {}\n }\n\n /** Sync GSAP's global timeline if present. */\n private patchGSAP(): void {\n try {\n const gsap = (window as any).gsap\n if (gsap?.globalTimeline) {\n gsap.globalTimeline.timeScale(this.speed || 0.001)\n }\n } catch {}\n }\n\n // ---------------------------------------------------------------------------\n // Cleanup\n // ---------------------------------------------------------------------------\n\n /** Restore all patched APIs to originals. */\n destroy(): void {\n if (!this.installed) return\n\n performance.now = this._perfNow\n Date.now = this._dateNow\n window.requestAnimationFrame = this._raf\n window.cancelAnimationFrame = this._caf\n window.setTimeout = this._setTimeout\n window.clearTimeout = this._clearTimeout\n window.setInterval = this._setInterval\n window.clearInterval = this._clearInterval\n\n // Clear all managed intervals\n for (const [, entry] of this.intervalMap) {\n this._clearTimeout(entry.realId as any)\n }\n this.intervalMap.clear()\n\n if (this._origAnimate) {\n Element.prototype.animate = this._origAnimate\n this._origAnimate = null\n }\n\n // Stop animation poll\n if (this.animPollId) {\n this._caf(this.animPollId)\n this.animPollId = 0\n }\n\n // Restore playbackRate on all animations\n try {\n for (const anim of document.getAnimations()) {\n const tracked = this.trackedAnims.get(anim)\n anim.playbackRate = tracked?.original ?? 1\n }\n } catch {}\n\n // Restore media playbackRate\n try {\n document.querySelectorAll('video, audio').forEach((node) => {\n const el = node as HTMLMediaElement\n const tracked = this.trackedMedia.get(el)\n el.playbackRate = tracked?.original ?? 1\n })\n } catch {}\n\n // Restore GSAP\n try {\n const gsap = (window as any).gsap\n if (gsap?.globalTimeline) gsap.globalTimeline.timeScale(1)\n } catch {}\n\n delete (window as any).__LAPSE_ORIGINAL_RAF__\n delete (window as any).__saccadeInstalled\n this.installed = false\n }\n}\n","import type {\n AnimationInfo,\n ElementSnapshot,\n FrameAnimation,\n FrameSnapshot,\n PropertySnapshot,\n Rect,\n TimelineCapture,\n} from './types'\n\n// ---------------------------------------------------------------------------\n// Augment Window for Lapse internals\n// ---------------------------------------------------------------------------\n\ndeclare global {\n interface Window {\n __LAPSE_ORIGINAL_RAF__?: typeof requestAnimationFrame\n }\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Visual-only properties — safe to override without affecting layout. */\nconst SAFE_PROPS = [\n 'opacity', 'transform', 'background-color', 'color', 'border-color',\n 'box-shadow', 'border-radius', 'filter', 'clip-path',\n 'scale', 'rotate', 'translate',\n 'outline-color', 'outline-width', 'outline-offset', 'outline-style',\n 'text-decoration-color',\n 'fill', 'stroke', 'stroke-dasharray', 'stroke-dashoffset',\n 'visibility', 'pointer-events',\n]\n\n/** Properties that affect layout — snapshot only, applied only on animated elements. */\nconst LAYOUT_PROPS = [\n 'width', 'height', 'top', 'left', 'right', 'bottom',\n 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',\n 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',\n 'max-height', 'max-width', 'min-height', 'min-width',\n 'display',\n]\n\nconst SNAPSHOT_PROPS = [...SAFE_PROPS, ...LAYOUT_PROPS]\n\nconst SAFE_PROPS_SET = new Set(SAFE_PROPS)\n\nconst SNAPSHOT_ATTRS = [\n 'data-state', 'data-checked', 'data-disabled', 'data-highlighted',\n 'data-orientation', 'data-active', 'data-selected', 'data-open',\n 'data-closed', 'data-side', 'data-align', 'data-focus', 'data-hover',\n 'data-at-boundary', 'data-scrubbing',\n 'data-starting-style', 'data-ending-style', 'data-panel-open', 'data-hidden',\n 'aria-checked', 'aria-selected', 'aria-expanded', 'aria-pressed',\n 'aria-hidden', 'aria-disabled', 'aria-valuenow', 'aria-valuemin', 'aria-valuemax',\n 'aria-invalid',\n 'checked', 'disabled', 'hidden', 'inert', 'value',\n 'class', 'style',\n]\n\nconst STATE_SELECTORS = [\n '[data-state]', '[aria-checked]', '[aria-selected]', '[aria-expanded]',\n '[aria-pressed]', '[role=\"radio\"]', '[role=\"checkbox\"]', '[role=\"switch\"]',\n '[role=\"tab\"]', '[role=\"tabpanel\"]', '[role=\"option\"]', '[role=\"slider\"]',\n '[role=\"menuitem\"]', '[role=\"menuitemcheckbox\"]', '[role=\"menuitemradio\"]',\n '[type=\"radio\"]', '[type=\"checkbox\"]', '[type=\"range\"]',\n 'input', 'button', 'select', 'textarea',\n '[data-radix-collection-item]',\n '[data-slot=\"slider-thumb\"]', '[data-slot=\"slider-track\"]',\n].join(',')\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a stable structural selector for `el` (up to 5 ancestors).\n * Used as the element identity key throughout recording & scrubbing.\n */\nfunction getSelector(el: Element): string | null {\n if (!el || !el.tagName) return null\n const parts: string[] = []\n let current: Element | null = el\n for (let i = 0; i < 5 && current && current.tagName && current.tagName !== 'HTML'; i++) {\n const tag = current.tagName.toLowerCase()\n const parent: Element | null = current.parentElement\n if (parent) {\n const siblings = Array.from(parent.children)\n const idx = siblings.indexOf(current) + 1\n parts.unshift(tag + ':nth-child(' + idx + ')')\n } else {\n parts.unshift(tag)\n }\n current = parent\n }\n return parts.join(' > ')\n}\n\nfunction getReadableSelector(el: Element): string {\n if (!el || !el.tagName) return 'unknown'\n if (el.id) return '#' + el.id\n const tag = el.tagName.toLowerCase()\n const classes = Array.from(el.classList || []).slice(0, 3).map((c) => '.' + c).join('')\n return tag + classes\n}\n\nfunction getElementLabel(el: Element): string {\n if (!el) return 'unknown'\n const ariaLabel = el.getAttribute('aria-label')\n if (ariaLabel) return ariaLabel\n const text = (el.textContent || '').trim()\n if (text && text.length < 40 && text.length > 0) return text\n const label = el.closest('label') || el.closest('[aria-label]')\n if (label) {\n const lt = label.getAttribute('aria-label') || (label.textContent || '').trim()\n if (lt && lt.length < 40) return lt\n }\n const state = el.getAttribute('data-state')\n const role = el.getAttribute('role')\n if (role && state) return role + ' (' + state + ')'\n if (role) return role\n return getReadableSelector(el)\n}\n\n/**\n * Parenthesis-aware comma split — keeps `cubic-bezier(...)` as atomic tokens.\n */\nfunction cssSplit(str: string): string[] {\n const parts: string[] = []\n let depth = 0\n let start = 0\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '(') depth++\n else if (str[i] === ')') depth--\n else if (str[i] === ',' && depth === 0) {\n parts.push(str.slice(start, i).trim())\n start = i + 1\n }\n }\n parts.push(str.slice(start).trim())\n return parts\n}\n\n// ---------------------------------------------------------------------------\n// TimelineRecorder\n// ---------------------------------------------------------------------------\n\nexport class TimelineRecorder {\n // ---- Recording state ----------------------------------------------------\n private recording = false\n private startTime = 0\n private boundingBox: Rect | null = null\n\n /** Structural-selector -> live DOM element. */\n readonly elements = new Map<string, HTMLElement>()\n /** Animation id -> info. */\n readonly animations = new Map<string, AnimationInfo>()\n /** Original inline style per element (captured on first encounter). */\n private originalStyles = new Map<string, string>()\n /** Captured frames. */\n private frames: FrameSnapshot[] = []\n\n // ---- Portal management --------------------------------------------------\n private activePortals = new Map<string, { element: HTMLElement }>()\n private portalIdCounter = 0\n private currentPortalIds = new Set<string>()\n private capturedPortals = new Set<string>()\n\n // ---- JS animation detection (Phase 2) -----------------------------------\n private prevInlineStyles = new Map<string, Record<string, string>>()\n private jsAnimStartTimes = new Map<string, number>()\n private jsAnimLastSeen = new Map<string, number>()\n private jsAnimFromValues = new Map<string, string>()\n private jsAnimChangeCount = new Map<string, number>()\n\n // ---- Interaction state --------------------------------------------------\n private currentHoverEls = new Set<string>()\n private currentFocusSel: string | null = null\n private currentPointer = { x: 0, y: 0, buttons: 0 }\n\n // ---- Observers & listeners ----------------------------------------------\n private attrObserver: MutationObserver | null = null\n private portalObserver: MutationObserver | null = null\n private exitObserver: MutationObserver | null = null\n\n private onMouseOver: ((e: MouseEvent) => void) | null = null\n private onMouseOut: ((e: MouseEvent) => void) | null = null\n private onFocusIn: ((e: FocusEvent) => void) | null = null\n private onFocusOut: (() => void) | null = null\n private onPointerMove: ((e: PointerEvent) => void) | null = null\n private onPointerDown: ((e: PointerEvent) => void) | null = null\n private onPointerUp: ((e: PointerEvent) => void) | null = null\n\n // ---- WAAPI interception --------------------------------------------------\n /** Animations captured via Element.prototype.animate monkey-patch. */\n readonly interceptedAnimations: { animation: Animation; target: Element }[] = []\n\n // ---- Seekable WAAPI clones (created in stopRecording for scrubbing) -----\n readonly seekableClones = new Map<string, { animation: Animation; element: HTMLElement; effect: KeyframeEffect }>()\n\n // ---- Recording limits ---------------------------------------------------\n private static readonly MAX_DURATION_MS = 60_000\n private static readonly MAX_FRAMES = 3600\n private hiddenSince: number | null = null\n private onVisibilityChange: (() => void) | null = null\n /** Set to true when the capture loop self-terminates due to limits. */\n autoStopped = false\n /** Called when recording auto-stops. Set by the engine. */\n onAutoStop: (() => void) | null = null\n\n // ---- Saved originals (for restoration) ----------------------------------\n private _removeChild: typeof Node.prototype.removeChild | null = null\n private _remove: typeof Element.prototype.remove | null = null\n private _elementAnimate: typeof Element.prototype.animate | null = null\n\n // ---- DOM elements injected during stop ----------------------------------\n /** `<style>` that disables all transitions/animations after recording. */\n noTransitionsEl: HTMLStyleElement | null = null\n /** Full-screen overlay blocking interaction during scrub. */\n blockerEl: HTMLDivElement | null = null\n /** `<style>` with cloned :hover / :focus rules rewritten as `[data-lapse-*]`. */\n lapseStyleEl: HTMLStyleElement | null = null\n\n // ---- Unpatched rAF reference --------------------------------------------\n private get _raf(): typeof requestAnimationFrame {\n return (window as any).__LAPSE_ORIGINAL_RAF__ || requestAnimationFrame\n }\n\n // =========================================================================\n // Public API — helpers exposed for the scrubber\n // =========================================================================\n\n getSelector = getSelector\n\n get SAFE_PROPS_SET(): Set<string> {\n return SAFE_PROPS_SET\n }\n\n get capturedPortalIds(): Set<string> {\n return this.capturedPortals\n }\n\n // =========================================================================\n // startRecording\n // =========================================================================\n\n startRecording(boundingBox?: Rect | null): void {\n if (this.recording) return\n\n // Reset state\n this.recording = true\n this.autoStopped = false\n this.hiddenSince = null\n this.startTime = performance.now()\n this.frames = []\n this.animations.clear()\n this.elements.clear()\n this.originalStyles.clear()\n this.boundingBox = boundingBox || null\n this.activePortals.clear()\n this.portalIdCounter = 0\n this.currentPortalIds.clear()\n this.capturedPortals.clear()\n this.seekableClones.clear()\n this.prevInlineStyles.clear()\n this.jsAnimStartTimes.clear()\n this.jsAnimLastSeen.clear()\n this.jsAnimFromValues.clear()\n this.jsAnimChangeCount.clear()\n this.currentHoverEls.clear()\n this.currentFocusSel = null\n this.currentPointer = { x: 0, y: 0, buttons: 0 }\n\n // Visibility tracking — auto-stop when tab hidden >5s\n this.onVisibilityChange = () => {\n if (!this.recording) return\n if (document.hidden) {\n this.hiddenSince = performance.now()\n } else {\n this.hiddenSince = null\n }\n }\n document.addEventListener('visibilitychange', this.onVisibilityChange)\n\n // ------------------------------------------------------------------\n // Element tracking\n // ------------------------------------------------------------------\n\n const trackElement = (el: Element): void => {\n if (!el || !(el as HTMLElement).tagName) return\n // Skip elements inside the Lapse panel\n if ((el as HTMLElement).closest?.('[data-lapse-panel]')) return\n const sel = getSelector(el)\n if (!sel) return\n const isNew = !this.elements.has(sel)\n this.elements.set(sel, el as HTMLElement)\n if (isNew) {\n this.originalStyles.set(sel, el.getAttribute('style') || '')\n }\n }\n\n const trackTree = (root: Element): void => {\n if (!root || !root.querySelectorAll) return\n trackElement(root)\n for (const child of root.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n\n const isInBounds = (el: Element): boolean => {\n if ((el as HTMLElement).closest?.('[data-lapse-panel]')) return false\n if (!this.boundingBox) return true\n const r = el.getBoundingClientRect()\n const bb = this.boundingBox\n return (\n r.x < bb.x + bb.width &&\n r.x + r.width > bb.x &&\n r.y < bb.y + bb.height &&\n r.y + r.height > bb.y\n )\n }\n\n // ------------------------------------------------------------------\n // Pre-scan: track all interactive elements and their groups\n // ------------------------------------------------------------------\n\n try {\n const stateEls = document.querySelectorAll(STATE_SELECTORS)\n for (const el of stateEls) {\n if (!isInBounds(el)) continue\n trackElement(el)\n for (const child of el.querySelectorAll('*')) {\n trackElement(child)\n }\n const parent = el.parentElement\n if (parent) {\n trackElement(parent)\n for (const sibling of parent.children) {\n trackElement(sibling)\n for (const child of sibling.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n }\n }\n } catch (_) {\n // Selector may fail in edge cases — not critical\n }\n\n // ------------------------------------------------------------------\n // Observers\n // ------------------------------------------------------------------\n\n // 1. Attribute-change observer\n this.attrObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n if (m.target instanceof HTMLElement) {\n trackElement(m.target)\n const parent = m.target.parentElement\n if (parent) {\n for (const sibling of parent.children) {\n trackElement(sibling)\n for (const child of sibling.querySelectorAll('*')) {\n trackElement(child)\n }\n }\n }\n }\n }\n })\n this.attrObserver.observe(document.body, {\n attributes: true,\n attributeFilter: [\n 'data-state', 'data-highlighted', 'data-hover', 'data-focus',\n 'data-active', 'data-selected', 'data-open', 'data-closed',\n 'data-at-boundary', 'data-scrubbing',\n 'aria-checked', 'aria-selected', 'aria-expanded', 'aria-valuenow',\n 'aria-invalid', 'class', 'style',\n ],\n subtree: true,\n })\n\n // 2. Portal management — intercept DOM removal to keep portals alive\n this._removeChild = Node.prototype.removeChild\n const savedRemoveChild = this._removeChild\n const self = this\n\n Node.prototype.removeChild = function <T extends Node>(child: T): T {\n if (\n self.recording &&\n child instanceof HTMLElement &&\n child.hasAttribute('data-lapse-portal-id')\n ) {\n child.style.display = 'none'\n child.setAttribute('data-lapse-portal-hidden', '')\n const id = child.getAttribute('data-lapse-portal-id')\n if (id) self.currentPortalIds.delete(id)\n return child\n }\n return savedRemoveChild.call(this, child) as T\n }\n\n this._remove = Element.prototype.remove\n const savedRemove = this._remove\n\n Element.prototype.remove = function (this: Element) {\n if (\n self.recording &&\n this instanceof HTMLElement &&\n this.hasAttribute('data-lapse-portal-id')\n ) {\n this.style.display = 'none'\n this.setAttribute('data-lapse-portal-hidden', '')\n const id = this.getAttribute('data-lapse-portal-id')\n if (id) self.currentPortalIds.delete(id)\n return\n }\n return savedRemove.call(this)\n }\n\n // Intercept Element.prototype.animate to track WAAPI animations\n this._elementAnimate = Element.prototype.animate\n const savedAnimate = this._elementAnimate\n\n Element.prototype.animate = function (\n this: Element,\n keyframes: Keyframe[] | PropertyIndexedKeyframes | null,\n options?: number | KeyframeAnimationOptions,\n ): Animation {\n const anim = savedAnimate.call(this, keyframes, options)\n\n // Track the target element and capture the animation\n if (self.recording && this instanceof HTMLElement && isInBounds(this)) {\n trackElement(this)\n self.interceptedAnimations.push({ animation: anim, target: this })\n }\n\n return anim\n }\n\n // Watch for new portals being added\n this.portalObserver = new MutationObserver((mutations) => {\n for (const m of mutations) {\n for (const node of m.addedNodes) {\n if (!(node instanceof HTMLElement)) continue\n if (node.parentElement !== document.body) continue\n if (node.hasAttribute('data-lapse-portal-id')) continue // already tracked\n\n const isPortal =\n node.hasAttribute('data-radix-popper-content-wrapper') ||\n node.hasAttribute('data-radix-portal') ||\n node.getAttribute('role') === 'dialog' ||\n node.getAttribute('role') === 'alertdialog' ||\n node.querySelector(\n '[role=\"menu\"], [role=\"dialog\"], [role=\"alertdialog\"], ' +\n '[role=\"listbox\"], [role=\"tooltip\"], [data-radix-popper-content-wrapper]',\n ) ||\n node.hasAttribute('data-state') ||\n (node.style &&\n (node.style.position === 'fixed' || node.style.position === 'absolute')) ||\n getComputedStyle(node).position === 'fixed'\n\n if (!isPortal) continue\n\n const id = '__lapse_portal_' + this.portalIdCounter++\n node.setAttribute('data-lapse-portal-id', id)\n this.activePortals.set(id, { element: node })\n this.currentPortalIds.add(id)\n this.capturedPortals.add(id)\n trackTree(node)\n }\n }\n })\n this.portalObserver.observe(document.body, { childList: true })\n\n // Exit-animation observer — catch any tracked element being removed\n this.exitObserver = new MutationObserver((mutations) => {\n if (!this.recording) return\n for (const m of mutations) {\n for (const node of m.removedNodes) {\n if (!(node instanceof HTMLElement)) continue\n const sel = getSelector(node)\n if (sel && this.elements.has(sel)) {\n if (!node.isConnected) {\n node.style.display = 'none'\n node.setAttribute('data-lapse-exit-captured', '')\n ;(m.target || document.body).appendChild(node)\n }\n }\n }\n }\n })\n this.exitObserver.observe(document.body, { childList: true, subtree: true })\n\n // ------------------------------------------------------------------\n // 3. Mouse hover tracking\n // ------------------------------------------------------------------\n\n this.onMouseOver = (e: MouseEvent) => {\n if (!this.recording) return\n this.currentHoverEls.clear()\n let el = e.target as HTMLElement | null\n while (el && el !== document.body) {\n const sel = getSelector(el)\n if (sel) {\n this.currentHoverEls.add(sel)\n trackElement(el)\n }\n el = el.parentElement\n }\n }\n\n this.onMouseOut = (e: MouseEvent) => {\n if (!this.recording) return\n if (!e.relatedTarget || !document.body.contains(e.relatedTarget as Node)) {\n this.currentHoverEls.clear()\n }\n }\n\n document.addEventListener('mouseover', this.onMouseOver, true)\n document.addEventListener('mouseout', this.onMouseOut, true)\n\n // ------------------------------------------------------------------\n // 4. Focus tracking\n // ------------------------------------------------------------------\n\n this.onFocusIn = (e: FocusEvent) => {\n if (!this.recording) return\n const el = e.target as HTMLElement | null\n if (el && el !== document.body) {\n const sel = getSelector(el)\n this.currentFocusSel = sel\n trackElement(el)\n let parent = el.parentElement\n while (parent && parent !== document.body) {\n trackElement(parent)\n parent = parent.parentElement\n }\n }\n }\n\n this.onFocusOut = () => {\n if (!this.recording) return\n this.currentFocusSel = null\n }\n\n document.addEventListener('focusin', this.onFocusIn, true)\n document.addEventListener('focusout', this.onFocusOut, true)\n\n // ------------------------------------------------------------------\n // 5. Pointer position tracking (sliders, scrubbers)\n // ------------------------------------------------------------------\n\n this.onPointerMove = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: e.buttons }\n }\n\n this.onPointerDown = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: e.buttons }\n }\n\n this.onPointerUp = (e: PointerEvent) => {\n if (!this.recording) return\n this.currentPointer = { x: e.clientX, y: e.clientY, buttons: 0 }\n }\n\n document.addEventListener('pointermove', this.onPointerMove, true)\n document.addEventListener('pointerdown', this.onPointerDown, true)\n document.addEventListener('pointerup', this.onPointerUp, true)\n\n // ------------------------------------------------------------------\n // Capture loop\n // ------------------------------------------------------------------\n\n const captureFrame = (): void => {\n if (!this.recording) return\n\n const time = performance.now() - this.startTime\n\n // Auto-stop: max duration, max frames, or tab hidden >5s\n if (\n time >= TimelineRecorder.MAX_DURATION_MS ||\n this.frames.length >= TimelineRecorder.MAX_FRAMES ||\n (this.hiddenSince && performance.now() - this.hiddenSince > 5000)\n ) {\n this.recording = false\n this.autoStopped = true\n this.onAutoStop?.()\n return\n }\n\n const anims = document.getAnimations()\n const frameAnims: FrameAnimation[] = []\n\n for (const a of anims) {\n const target = (a.effect as KeyframeEffect)?.target as HTMLElement | null\n if (!target) continue\n if (!isInBounds(target)) continue\n\n const uniqueSelector = getSelector(target)\n if (!uniqueSelector) continue\n const readableSelector = getReadableSelector(target)\n\n trackElement(target)\n\n const timing = (a.effect as KeyframeEffect)?.getTiming?.() || {}\n const duration =\n typeof timing.duration === 'number' ? timing.duration : 0\n const delay = timing.delay || 0\n const easing = timing.easing || 'linear'\n\n let name = ''\n let type = 'WebAnimation'\n if (\n a.constructor.name === 'CSSTransition' ||\n (a as any).transitionProperty\n ) {\n name = (a as any).transitionProperty || ''\n type = 'CSSTransition'\n } else if (\n a.constructor.name === 'CSSAnimation' ||\n (a as any).animationName\n ) {\n name = (a as any).animationName || ''\n type = 'CSSAnimation'\n }\n\n const id = type + ':' + name + ':' + uniqueSelector\n\n if (!this.animations.has(id)) {\n const keyframes = (a.effect as KeyframeEffect)?.getKeyframes?.() || []\n let source: string | null = null\n\n if (type === 'CSSAnimation' && keyframes.length > 0) {\n const kfLines = keyframes\n .map((kf) => {\n const offset = Math.round((kf.offset ?? 0) * 100) + '%'\n const props = Object.entries(kf)\n .filter(\n ([k]) =>\n !['offset', 'easing', 'composite', 'computedOffset'].includes(k),\n )\n .map(\n ([k, v]) =>\n k.replace(/([A-Z])/g, '-$1').toLowerCase() + ': ' + v,\n )\n .join('; ')\n return ' ' + offset + ' { ' + props + ' }'\n })\n .join('\\n')\n source =\n '@keyframes ' + (name || 'anonymous') + ' {\\n' + kfLines + '\\n}'\n } else if (type === 'CSSTransition') {\n source = 'transition: ' + name + ' ' + duration + 'ms ' + easing\n }\n\n // Resolve CSS custom properties used in transitions\n const resolvedVars: Record<string, string> = {}\n try {\n const cs = getComputedStyle(target)\n const style = target.getAttribute('style') || ''\n const allRules: string[] = []\n for (const sheet of document.styleSheets) {\n try {\n for (const rule of sheet.cssRules) {\n if (\n (rule as CSSStyleRule).selectorText &&\n target.matches((rule as CSSStyleRule).selectorText)\n ) {\n allRules.push(rule.cssText)\n }\n }\n } catch (_) {\n // Cross-origin stylesheet — skip\n }\n }\n const allCssText = allRules.join(' ') + ' ' + style\n const varRegex = /var\\(\\s*(--[a-zA-Z0-9-]+)/g\n let varMatch: RegExpExecArray | null\n while ((varMatch = varRegex.exec(allCssText)) !== null) {\n const varName = varMatch[1]\n const resolved = cs.getPropertyValue(varName).trim()\n if (resolved) {\n resolvedVars[varName] = resolved\n }\n }\n } catch (_) {\n // Non-critical\n }\n\n // Diff expected vs actual transition timing\n let conflicts: string[] | null = null\n if (type === 'CSSTransition') {\n try {\n const cs = getComputedStyle(target)\n\n const tProps = cssSplit(cs.transitionProperty)\n const tDurations = cssSplit(cs.transitionDuration).map(\n (s) => parseFloat(s) * 1000,\n )\n const tEasings = cssSplit(cs.transitionTimingFunction)\n const tDelays = cssSplit(cs.transitionDelay).map(\n (s) => parseFloat(s) * 1000,\n )\n\n let idx = tProps.indexOf(name)\n if (idx === -1 && tProps.includes('all'))\n idx = tProps.indexOf('all')\n\n if (idx >= 0) {\n const declaredDuration =\n tDurations[idx % tDurations.length] || 0\n const declaredEasing =\n tEasings[idx % tEasings.length] || 'ease'\n const declaredDelay = tDelays[idx % tDelays.length] || 0\n\n const diffs: string[] = []\n if (Math.abs(declaredDuration - duration) > 1) {\n diffs.push(\n 'duration: declared ' +\n declaredDuration +\n 'ms, actual ' +\n duration +\n 'ms',\n )\n }\n if (declaredEasing !== easing) {\n const normDeclared = declaredEasing.replace(/\\s/g, '')\n const normActual = easing.replace(/\\s/g, '')\n if (normDeclared !== normActual) {\n diffs.push(\n 'easing: declared ' +\n declaredEasing +\n ', actual ' +\n easing,\n )\n }\n }\n if (Math.abs(declaredDelay - delay) > 1) {\n diffs.push(\n 'delay: declared ' +\n declaredDelay +\n 'ms, actual ' +\n delay +\n 'ms',\n )\n }\n if (diffs.length > 0) {\n conflicts = diffs\n }\n }\n } catch (_) {\n // Non-critical\n }\n }\n\n // Clean keyframes for WAAPI clone creation (strip internal props)\n const cleanedKeyframes = keyframes.map((kf) => {\n const clean: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(kf)) {\n if (k !== 'computedOffset' && k !== 'composite') clean[k] = v\n }\n return clean as Keyframe\n })\n\n this.animations.set(id, {\n id,\n name,\n selector: readableSelector,\n elementLabel: getElementLabel(target),\n duration,\n delay,\n easing,\n type,\n source,\n resolvedVars:\n Object.keys(resolvedVars).length > 0 ? resolvedVars : null,\n conflicts,\n rawKeyframes: cleanedKeyframes,\n rawTiming: { ...timing, fill: 'both' as FillMode },\n })\n }\n\n // Capture per-frame property values\n const keyframes = (a.effect as KeyframeEffect)?.getKeyframes?.() || []\n const animatedProps = new Set<string>()\n for (const kf of keyframes) {\n for (const key of Object.keys(kf)) {\n if (\n !['offset', 'easing', 'composite', 'computedOffset'].includes(key)\n ) {\n animatedProps.add(key)\n }\n }\n }\n\n const computedStyle = getComputedStyle(target)\n const properties: PropertySnapshot[] = []\n for (const prop of animatedProps) {\n const kebab = prop.replace(/([A-Z])/g, '-$1').toLowerCase()\n const value = computedStyle.getPropertyValue(kebab) || ''\n if (value) {\n const from = (keyframes[0] as any)?.[prop] || null\n const to =\n (keyframes[keyframes.length - 1] as any)?.[prop] || null\n properties.push({ property: kebab, value, from, to })\n }\n }\n\n const currentTime = (a.currentTime as number) ?? 0\n const progress =\n duration > 0\n ? Math.max(0, Math.min(1, currentTime / duration))\n : 0\n frameAnims.push({ animationId: id, currentTime, progress, properties })\n }\n\n // Phase 2: Detect JS-driven animations (rAF, Framer Motion springs, etc.)\n // Compare inline style properties between frames for tracked elements\n // that don't have a corresponding WAAPI animation\n const waapiAnimatedIds = new Set<string>()\n for (const fa of frameAnims) {\n const parts = fa.animationId.split(':')\n waapiAnimatedIds.add(parts[parts.length - 1])\n }\n\n const JS_TRACK_PROPS = ['transform', 'opacity', 'left', 'top', 'right', 'bottom', 'background']\n // Also track which properties are already covered by WAAPI per element\n const waapiAnimatedProps = new Map<string, Set<string>>()\n for (const fa of frameAnims) {\n const parts = fa.animationId.split(':')\n const elKey = parts[parts.length - 1]\n if (!waapiAnimatedProps.has(elKey)) waapiAnimatedProps.set(elKey, new Set())\n const propName = parts[1] // type:propName:selector\n if (propName) waapiAnimatedProps.get(elKey)!.add(propName)\n }\n\n for (const [elId, el] of this.elements) {\n if (!el.isConnected) continue\n const hasWaapi = waapiAnimatedIds.has(elId)\n const waapiProps = waapiAnimatedProps.get(elId)\n\n const currentInline: Record<string, string> = {}\n let hasAnyInline = false\n for (const prop of JS_TRACK_PROPS) {\n const camel = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase())\n const val = (el.style as any)[camel]\n if (val) {\n currentInline[prop] = val\n hasAnyInline = true\n }\n }\n if (!hasAnyInline) {\n this.prevInlineStyles.set(elId, currentInline)\n continue\n }\n\n const prevInline = this.prevInlineStyles.get(elId) || {}\n this.prevInlineStyles.set(elId, currentInline)\n\n for (const p of JS_TRACK_PROPS) {\n const cur = currentInline[p] || ''\n const prev = prevInline[p] || ''\n // Skip if this property is already tracked via WAAPI on this element\n const propCoveredByWaapi = waapiProps?.has(p) || waapiProps?.has(p.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase()))\n if (cur && cur !== prev && !propCoveredByWaapi) {\n const jsId = 'JSAnimation:' + p + ':' + elId\n\n // Track how many frames this property has been changing\n this.jsAnimChangeCount.set(jsId, (this.jsAnimChangeCount.get(jsId) || 0) + 1)\n\n if (!this.jsAnimStartTimes.has(jsId)) {\n this.jsAnimStartTimes.set(jsId, time)\n this.jsAnimFromValues.set(jsId, prev || cur)\n }\n this.jsAnimLastSeen.set(jsId, time)\n\n // Only register as animation after 3+ frames of continuous change\n // (single frame changes are React state toggles, not animations)\n if (this.jsAnimChangeCount.get(jsId)! < 3) continue\n\n if (!this.animations.has(jsId)) {\n const readableSel = getReadableSelector(el)\n this.animations.set(jsId, {\n id: jsId,\n name: p,\n selector: readableSel,\n elementLabel: getElementLabel(el),\n duration: 0,\n delay: 0,\n easing: 'JS-driven',\n type: 'JSAnimation',\n source: 'Detected: inline style animation (JS library or requestAnimationFrame)',\n resolvedVars: null,\n conflicts: null,\n })\n }\n\n // Update duration as animation progresses\n const startT = this.jsAnimStartTimes.get(jsId)!\n const anim = this.animations.get(jsId)!\n anim.duration = time - startT\n\n const fromVal = this.jsAnimFromValues.get(jsId) || ''\n const elapsed = time - startT\n const estimatedDuration = Math.max(anim.duration, 300)\n const prog = Math.min(1, elapsed / estimatedDuration)\n frameAnims.push({\n animationId: jsId,\n currentTime: elapsed,\n progress: prog,\n properties: [{\n property: p,\n value: cur,\n from: fromVal,\n to: cur\n }]\n })\n }\n }\n }\n\n // Snapshot computed styles, attributes, and inline styles for all tracked elements\n const elementSnapshots: Record<string, ElementSnapshot> = {}\n for (const [sel, el] of this.elements) {\n if (!el.isConnected) continue\n const cs = getComputedStyle(el)\n const snap: ElementSnapshot = { __styles: {}, __attrs: {} }\n for (const prop of SNAPSHOT_PROPS) {\n snap.__styles[prop] = cs.getPropertyValue(prop)\n }\n for (const attr of SNAPSHOT_ATTRS) {\n if (attr === 'checked') {\n snap.__attrs[attr] = (el as HTMLInputElement).checked\n ? 'true'\n : null\n } else if (attr === 'class') {\n snap.__attrs[attr] = el.className\n } else if (attr === 'style') {\n snap.__attrs[attr] = el.getAttribute('style') || ''\n } else if (attr === 'value') {\n snap.__attrs[attr] =\n (el as HTMLInputElement).value !== undefined\n ? String((el as HTMLInputElement).value)\n : null\n } else {\n snap.__attrs[attr] = el.getAttribute(attr)\n }\n }\n // Pseudo-element opacity\n try {\n snap.__afterOpacity = getComputedStyle(el, '::after').getPropertyValue(\n 'opacity',\n )\n snap.__beforeOpacity = getComputedStyle(\n el,\n '::before',\n ).getPropertyValue('opacity')\n } catch (_) {\n // Non-critical\n }\n elementSnapshots[sel] = snap\n }\n\n // Check for hidden portals whose display was 'none' but are still\n // tracked — mark them as visible if they were un-hidden by React\n for (const [id, portal] of this.activePortals) {\n if (\n portal.element?.isConnected &&\n !portal.element.hasAttribute('data-lapse-portal-hidden')\n ) {\n this.currentPortalIds.add(id)\n }\n }\n\n this.frames.push({\n time,\n animations: frameAnims,\n elementSnapshots,\n activePortalIds: [...this.currentPortalIds],\n hoveredSels: [...this.currentHoverEls],\n focusSel: this.currentFocusSel,\n pointer: { ...this.currentPointer },\n scrollPositions: {},\n })\n\n this._raf(captureFrame)\n }\n\n this._raf(captureFrame)\n }\n\n // =========================================================================\n // stopRecording\n // =========================================================================\n\n stopRecording(): TimelineCapture {\n if (!this.recording) {\n return {\n startTime: 0,\n endTime: 0,\n duration: 0,\n animations: [],\n frames: [],\n boundingBox: null,\n }\n }\n\n this.recording = false\n\n // ------------------------------------------------------------------\n // Restore patched prototypes\n // ------------------------------------------------------------------\n\n if (this._removeChild) Node.prototype.removeChild = this._removeChild\n if (this._remove) Element.prototype.remove = this._remove\n if (this._elementAnimate) Element.prototype.animate = this._elementAnimate\n\n // ------------------------------------------------------------------\n // Disconnect observers & remove event listeners\n // ------------------------------------------------------------------\n\n this.attrObserver?.disconnect()\n this.portalObserver?.disconnect()\n this.exitObserver?.disconnect()\n if (this.onVisibilityChange) {\n document.removeEventListener('visibilitychange', this.onVisibilityChange)\n this.onVisibilityChange = null\n }\n\n if (this.onMouseOver)\n document.removeEventListener('mouseover', this.onMouseOver, true)\n if (this.onMouseOut)\n document.removeEventListener('mouseout', this.onMouseOut, true)\n if (this.onFocusIn)\n document.removeEventListener('focusin', this.onFocusIn, true)\n if (this.onFocusOut)\n document.removeEventListener('focusout', this.onFocusOut, true)\n if (this.onPointerMove)\n document.removeEventListener('pointermove', this.onPointerMove, true)\n if (this.onPointerDown)\n document.removeEventListener('pointerdown', this.onPointerDown, true)\n if (this.onPointerUp)\n document.removeEventListener('pointerup', this.onPointerUp, true)\n\n // ------------------------------------------------------------------\n // Cancel all running animations\n // ------------------------------------------------------------------\n\n try {\n for (const anim of document.getAnimations()) {\n // Don't cancel animations on the Lapse panel itself\n const target = (anim.effect as KeyframeEffect)?.target as HTMLElement | null\n if (target?.closest?.('[data-lapse-panel]')) continue\n anim.cancel()\n }\n } catch (_) {\n // Non-critical\n }\n\n // ------------------------------------------------------------------\n // Inject no-transitions style\n // ------------------------------------------------------------------\n\n const noTransitions = document.createElement('style')\n noTransitions.id = '__lapse-no-transitions'\n noTransitions.textContent =\n '*, *::before, *::after { transition: none !important; animation: none !important; }'\n document.head.appendChild(noTransitions)\n this.noTransitionsEl = noTransitions\n\n // ------------------------------------------------------------------\n // Add interaction blocker overlay\n // ------------------------------------------------------------------\n\n const blocker = document.createElement('div')\n blocker.id = '__lapse-scrub-blocker'\n blocker.style.cssText =\n 'position:fixed;inset:0;z-index:999999;cursor:not-allowed;background:transparent;'\n blocker.title = 'Clear the timeline to interact with the page'\n document.body.appendChild(blocker)\n this.blockerEl = blocker\n\n // ------------------------------------------------------------------\n // Clone :hover / :focus CSS rules (deferred — don't block the return)\n // ------------------------------------------------------------------\n\n setTimeout(() => {\n try {\n const lapseStyle = document.createElement('style')\n lapseStyle.id = '__lapse-state-rules'\n\n // Only walk CSSOM rules (avoids reading huge Tailwind <style> textContent)\n const hoverFocusRules: string[] = []\n for (const sheet of document.styleSheets) {\n try {\n const walk = (rules: CSSRuleList) => {\n for (const rule of rules) {\n if ((rule as CSSGroupingRule).cssRules) {\n walk((rule as CSSGroupingRule).cssRules)\n continue\n }\n const t = rule.cssText\n if (t && (t.includes(':hover') || t.includes(':focus'))) {\n hoverFocusRules.push(t)\n }\n }\n }\n walk(sheet.cssRules)\n } catch (_) {\n // Cross-origin stylesheet — skip\n }\n }\n\n // Clone individual rules (no regex on giant CSS blobs)\n const parts: string[] = []\n for (const ruleText of hoverFocusRules) {\n const braceIdx = ruleText.indexOf('{')\n if (braceIdx === -1) continue\n const selector = ruleText.slice(0, braceIdx).trim()\n const bodyEnd = ruleText.lastIndexOf('}')\n const body = ruleText.slice(braceIdx + 1, bodyEnd).trim()\n if (!body) continue\n\n const newBody = body.replace(\n /([^;:]+):\\s*([^;]+)(;|$)/g,\n (m, prop: string, val: string, end: string) => {\n if (val.includes('!important')) return m\n return prop + ': ' + val.trim() + ' !important' + end\n },\n )\n\n if (selector.includes(':hover')) {\n parts.push(selector.replace(/:hover/g, '[data-lapse-hover]') + ' { ' + newBody + ' }')\n }\n if (selector.includes(':focus-visible')) {\n parts.push(selector.replace(/:focus-visible/g, '[data-lapse-focus]') + ' { ' + newBody + ' }')\n } else if (selector.includes(':focus-within')) {\n parts.push(selector.replace(/:focus-within/g, ':has([data-lapse-focus])') + ' { ' + newBody + ' }')\n } else if (selector.includes(':focus')) {\n parts.push(selector.replace(/:focus(?!-)/g, '[data-lapse-focus]') + ' { ' + newBody + ' }')\n }\n }\n\n lapseStyle.textContent = parts.join('\\n')\n document.head.appendChild(lapseStyle)\n this.lapseStyleEl = lapseStyle\n } catch (_) {\n // Non-critical\n }\n }, 0)\n\n // ------------------------------------------------------------------\n // Create seekable WAAPI clones for each recorded animation\n // ------------------------------------------------------------------\n\n this.seekableClones.clear()\n for (const [animId, animInfo] of this.animations) {\n if (!animInfo.rawKeyframes?.length || !animInfo.rawTiming) continue\n if (animInfo.type === 'JSAnimation') continue\n\n // Extract element selector from animId (format: \"type:name:selector\")\n const firstColon = animId.indexOf(':')\n const secondColon = animId.indexOf(':', firstColon + 1)\n const elSelector = secondColon >= 0 ? animId.substring(secondColon + 1) : ''\n const el = this.elements.get(elSelector)\n if (!el?.isConnected) continue\n\n try {\n const clone = el.animate(animInfo.rawKeyframes, {\n ...animInfo.rawTiming,\n fill: 'both' as FillMode,\n })\n clone.pause()\n clone.currentTime = 0\n this.seekableClones.set(animId, {\n animation: clone,\n element: el,\n effect: clone.effect as KeyframeEffect,\n })\n } catch (_) {\n // Keyframes may be invalid for re-creation\n }\n }\n\n // ------------------------------------------------------------------\n // Build and return the capture\n // ------------------------------------------------------------------\n\n const duration =\n this.frames.length > 0\n ? this.frames[this.frames.length - 1].time\n : 0\n\n const capture: TimelineCapture = {\n startTime: this.startTime,\n endTime: performance.now(),\n duration,\n animations: Array.from(this.animations.values()),\n frames: this.frames,\n boundingBox: this.boundingBox,\n }\n\n return capture\n }\n}\n","import type { FrameSnapshot, ElementSnapshot, FrameAnimation } from './types'\n\n/**\n * Represents a WAAPI Animation intercepted during recording.\n * The recorder monkey-patches Element.prototype.animate to capture these.\n */\nexport interface InterceptedAnimation {\n animation: Animation\n target: Element\n}\n\n/** A seekable WAAPI clone created from recorded keyframes. */\nexport interface SeekableClone {\n animation: Animation\n element: HTMLElement\n effect: KeyframeEffect\n}\n\n/**\n * State handed from the recorder after stopRecording().\n * This is everything the scrubber needs to replay frames.\n */\nexport interface ScrubberState {\n /** Selector string -> live DOM element */\n elements: Map<string, HTMLElement>\n /** Captured frame snapshots from the recording */\n frames: FrameSnapshot[]\n /** All portal IDs ever captured (for show/hide management) */\n capturedPortals: Set<string>\n /** WAAPI animations intercepted via Element.prototype.animate patch */\n interceptedAnimations: InterceptedAnimation[]\n /** Set of CSS properties that are safe (visual-only, no layout side-effects) */\n SAFE_PROPS_SET: Set<string>\n /** Seekable WAAPI clones created from recorded animation keyframes */\n seekableClones: Map<string, SeekableClone>\n}\n\n/**\n * Timeline scrubber — seeks through recorded animation state using WAAPI.\n *\n * Instead of applying computed styles as inline overrides (which breaks\n * Tailwind/class-driven layouts), this scrubber creates paused WAAPI\n * animation clones and seeks them via animation.currentTime. The browser\n * computes exact intermediate values natively — the same mechanism Chrome\n * DevTools uses for its Animation panel.\n */\nexport class TimelineScrubber {\n private elements: Map<string, HTMLElement>\n private frames: FrameSnapshot[]\n private capturedPortals: Set<string>\n private interceptedAnimations: InterceptedAnimation[]\n private seekableClones: Map<string, SeekableClone>\n\n /** Precomputed frame range per animation for O(1) before/after lookup. */\n private animFrameRanges = new Map<string, { first: number; last: number }>()\n\n /** Saved originals for restore on release */\n private _originalAnimate: typeof Element.prototype.animate | null = null\n private _originalRaf: typeof requestAnimationFrame | null = null\n private _originalRemoveChild: typeof Node.prototype.removeChild | null = null\n private _originalRemove: typeof Element.prototype.remove | null = null\n\n constructor(state: ScrubberState) {\n this.elements = state.elements\n this.frames = state.frames\n this.capturedPortals = state.capturedPortals\n this.interceptedAnimations = state.interceptedAnimations\n this.seekableClones = state.seekableClones\n\n // Stash originals that the recorder may have patched\n this._originalAnimate = (window as any).__LAPSE_ORIGINAL_ANIMATE__ ?? null\n this._originalRaf = (window as any).__LAPSE_ORIGINAL_RAF__ ?? null\n this._originalRemoveChild = (window as any).__LAPSE_TIMELINE__?._removeChild ?? null\n this._originalRemove = (window as any).__LAPSE_TIMELINE__?._remove ?? null\n\n // Precompute frame ranges for each animation\n for (let i = 0; i < this.frames.length; i++) {\n for (const fa of this.frames[i].animations) {\n const range = this.animFrameRanges.get(fa.animationId)\n if (!range) {\n this.animFrameRanges.set(fa.animationId, { first: i, last: i })\n } else {\n range.last = i\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // seekTo — scrub to a specific timestamp using WAAPI-native seeking\n // ---------------------------------------------------------------------------\n\n seekTo(timeMs: number): void {\n if (!this.frames.length) return\n\n // Binary search for closest frame\n let lo = 0\n let hi = this.frames.length - 1\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (this.frames[mid].time < timeMs) lo = mid + 1\n else hi = mid\n }\n const frame = this.frames[lo]\n if (!frame || !frame.elementSnapshots) return\n\n // -----------------------------------------------------------------------\n // Clear state markers\n // -----------------------------------------------------------------------\n document.querySelectorAll('[data-lapse-hover]').forEach((el) => {\n el.removeAttribute('data-lapse-hover')\n })\n document.querySelectorAll('[data-lapse-focus]').forEach((el) => {\n el.removeAttribute('data-lapse-focus')\n })\n\n // -----------------------------------------------------------------------\n // Manage portals\n // -----------------------------------------------------------------------\n const activeIds = new Set(frame.activePortalIds || [])\n for (const id of this.capturedPortals) {\n const portalEl = document.querySelector(\n `[data-lapse-portal-id=\"${id}\"]`\n ) as HTMLElement | null\n if (!portalEl) continue\n if (activeIds.has(id)) {\n portalEl.style.removeProperty('display')\n portalEl.removeAttribute('data-lapse-portal-hidden')\n } else {\n portalEl.style.setProperty('display', 'none', 'important')\n }\n }\n\n // -----------------------------------------------------------------------\n // Apply hover markers\n // -----------------------------------------------------------------------\n const hoveredSels = frame.hoveredSels || []\n for (const sel of hoveredSels) {\n const el = this.elements.get(sel)\n if (el && el.isConnected) el.setAttribute('data-lapse-hover', '')\n }\n\n // -----------------------------------------------------------------------\n // Apply focus marker (+ ancestors for :focus-within)\n // -----------------------------------------------------------------------\n if (frame.focusSel) {\n const focusEl = this.elements.get(frame.focusSel)\n if (focusEl && focusEl.isConnected) {\n focusEl.setAttribute('data-lapse-focus', '')\n let parent = focusEl.parentElement\n while (parent && parent !== document.body) {\n parent.setAttribute('data-lapse-focus', '')\n parent = parent.parentElement\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // WAAPI-native seeking: set currentTime on seekable clones\n // The browser computes exact intermediate values including easing,\n // layout properties, and the full CSS cascade — no inline overrides.\n // -----------------------------------------------------------------------\n\n const activeAnimIds = new Map<string, FrameAnimation>()\n for (const fa of frame.animations || []) {\n activeAnimIds.set(fa.animationId, fa)\n }\n\n for (const [animId, clone] of this.seekableClones) {\n const frameAnim = activeAnimIds.get(animId)\n try {\n if (frameAnim) {\n // Animation is active at this frame — ensure effect is attached and seek\n if (!clone.animation.effect) {\n clone.animation.effect = clone.effect\n }\n clone.animation.currentTime = frameAnim.currentTime\n } else {\n // Animation is not active — check if before or after its range\n const range = this.animFrameRanges.get(animId)\n if (!range || lo < range.first) {\n // Before animation starts — detach effect so element shows base CSS\n clone.animation.effect = null\n } else {\n // After animation ends — show final state\n if (!clone.animation.effect) {\n clone.animation.effect = clone.effect\n }\n const timing = clone.effect.getTiming()\n const endTime =\n (typeof timing.duration === 'number' ? timing.duration : 0) +\n (timing.delay || 0)\n clone.animation.currentTime = endTime\n }\n }\n } catch {\n // Animation may have been GC'd\n }\n }\n\n // -----------------------------------------------------------------------\n // Seek intercepted WAAPI animations (JS-created, e.g. Framer Motion)\n // -----------------------------------------------------------------------\n for (const entry of this.interceptedAnimations) {\n try {\n const anim = entry.animation\n if (anim.playState !== 'finished') {\n anim.pause()\n }\n anim.currentTime = timeMs\n } catch {\n // Animation may have been garbage collected\n }\n }\n\n // -----------------------------------------------------------------------\n // Apply discrete attributes (data-state, aria-*, checked, value, etc.)\n // These are state changes that CSS animations cannot represent.\n // Skip class and style — WAAPI clones handle animated visual properties,\n // and class/style clobber framework-managed state.\n // -----------------------------------------------------------------------\n for (const [sel, snap] of Object.entries(frame.elementSnapshots)) {\n const el = this.elements.get(sel)\n if (!el || !el.isConnected) continue\n if (el.closest?.('[data-lapse-panel]')) continue\n\n const snapTyped = snap as ElementSnapshot\n if (snapTyped.__attrs) {\n for (const [attr, value] of Object.entries(snapTyped.__attrs)) {\n if (attr === 'class' || attr === 'style') continue\n if (attr === 'checked') {\n ;(el as HTMLInputElement).checked = value === 'true'\n } else if (attr === 'value') {\n if (value != null) (el as HTMLInputElement).value = value\n } else if (value == null) {\n el.removeAttribute(attr)\n } else {\n el.setAttribute(attr, value)\n }\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // JS animation fallback: apply inline style overrides for JS-driven\n // animations (detected as 'JSAnimation' type) which don't have WAAPI\n // keyframes. Only applies to the specific properties they animate.\n // -----------------------------------------------------------------------\n for (const fa of frame.animations || []) {\n if (!fa.animationId.startsWith('JSAnimation:')) continue\n const firstColon = fa.animationId.indexOf(':')\n const secondColon = fa.animationId.indexOf(':', firstColon + 1)\n const elSel = secondColon >= 0 ? fa.animationId.substring(secondColon + 1) : ''\n const el = this.elements.get(elSel)\n if (!el || !el.isConnected) continue\n for (const prop of fa.properties) {\n if (prop.value) {\n el.style.setProperty(prop.property, prop.value, 'important')\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // release — tear down all scrub state and restore the page to normal\n // ---------------------------------------------------------------------------\n\n release(): void {\n // Cancel seekable WAAPI clones\n for (const [, clone] of this.seekableClones) {\n try {\n clone.animation.cancel()\n } catch {\n // Already finished or GC'd\n }\n }\n this.seekableClones.clear()\n\n // Cancel intercepted WAAPI animations\n for (const entry of this.interceptedAnimations) {\n try {\n entry.animation.cancel()\n } catch {\n // Already finished or GC'd\n }\n }\n this.interceptedAnimations.length = 0\n\n // Restore Element.prototype.animate if we patched it\n if (this._originalAnimate) {\n Element.prototype.animate = this._originalAnimate\n this._originalAnimate = null\n delete (window as any).__LAPSE_ORIGINAL_ANIMATE__\n }\n\n // Restore requestAnimationFrame if we patched it\n if (this._originalRaf) {\n window.requestAnimationFrame = this._originalRaf\n this._originalRaf = null\n delete (window as any).__LAPSE_ORIGINAL_RAF__\n }\n\n // Remove global transition/animation override style\n const tl = (window as any).__LAPSE_TIMELINE__\n if (tl?.noTransitionsEl) {\n tl.noTransitionsEl.remove()\n }\n const noTrans = document.getElementById('__lapse-no-transitions')\n if (noTrans) noTrans.remove()\n\n // Remove interaction blocker\n const blocker = document.getElementById('__lapse-scrub-blocker')\n if (blocker) blocker.remove()\n if (tl?.blockerEl) tl.blockerEl.remove()\n\n // Remove cloned state rules style (hover/focus rule clones)\n const stateRules = document.getElementById('__lapse-state-rules')\n if (stateRules) stateRules.remove()\n if (tl?.lapseStyleEl) tl.lapseStyleEl.remove()\n\n // Restore original DOM removal methods\n if (this._originalRemoveChild) {\n Node.prototype.removeChild = this._originalRemoveChild\n this._originalRemoveChild = null\n } else if (tl?._removeChild) {\n Node.prototype.removeChild = tl._removeChild\n }\n\n if (this._originalRemove) {\n Element.prototype.remove = this._originalRemove\n this._originalRemove = null\n } else if (tl?._remove) {\n Element.prototype.remove = tl._remove\n }\n\n // Remove exit-captured elements (re-inserted hidden during recording)\n document.querySelectorAll('[data-lapse-exit-captured]').forEach((el) => {\n el.remove()\n })\n\n // Clean up data-lapse-* attributes from all elements\n document.querySelectorAll('[data-lapse-id]').forEach((el) => {\n el.removeAttribute('data-lapse-id')\n })\n document.querySelectorAll('[data-lapse-hover]').forEach((el) => {\n el.removeAttribute('data-lapse-hover')\n })\n document.querySelectorAll('[data-lapse-focus]').forEach((el) => {\n el.removeAttribute('data-lapse-focus')\n })\n document.querySelectorAll('[data-lapse-portal-id]').forEach((el) => {\n el.removeAttribute('data-lapse-portal-id')\n el.removeAttribute('data-lapse-portal-hidden')\n })\n\n // Clear the global timeline object\n delete (window as any).__LAPSE_TIMELINE__\n\n // Clear local references\n this.elements.clear()\n this.frames.length = 0\n this.capturedPortals.clear()\n this.animFrameRanges.clear()\n }\n}\n","import type {\n AnimationInfo,\n ExportFilter,\n FrameSnapshot,\n OutputDetailLevel,\n TimelineExport\n} from './types'\n\nexport function getFrameAtTime(frames: FrameSnapshot[], timeMs: number): FrameSnapshot | null {\n if (frames.length === 0) return null\n let lo = 0\n let hi = frames.length - 1\n while (lo < hi) {\n const mid = (lo + hi) >> 1\n if (frames[mid].time < timeMs) lo = mid + 1\n else hi = mid\n }\n return frames[lo]\n}\n\nexport function generateExport(\n animations: AnimationInfo[],\n frames: FrameSnapshot[],\n timeMs: number,\n filter: ExportFilter = 'active'\n): TimelineExport {\n const frame = getFrameAtTime(frames, timeMs)\n const duration = frames.at(-1)?.time ?? 0\n\n const filteredAnims = animations.filter((anim) => {\n if (filter === 'all-animations') return true\n if (filter === 'active') {\n const frameAnim = frame?.animations.find((a) => a.animationId === anim.id)\n if (!frameAnim || frameAnim.progress <= 0 || frameAnim.progress >= 1) return false\n if (frameAnim.properties.length > 0) {\n const hasRealChange = frameAnim.properties.some(\n (p) => p.from && p.to && p.from !== p.to\n )\n if (!hasRealChange) return false\n }\n return true\n }\n return true\n })\n\n const animExports = filteredAnims.map((anim) => {\n // Find this animation in the current frame, or fall back to the last frame it appeared in\n let frameAnim = frame?.animations.find((a) => a.animationId === anim.id)\n let status: 'active' | 'completed' | 'upcoming' = frameAnim ? 'active' : 'completed'\n\n if (!frameAnim) {\n // Search backwards for the last frame this animation appeared in\n for (let i = frames.length - 1; i >= 0; i--) {\n if (frames[i].time > timeMs) continue\n const found = frames[i].animations.find((a) => a.animationId === anim.id)\n if (found) { frameAnim = found; break }\n }\n // If still not found, search forward (animation hasn't started yet)\n if (!frameAnim) {\n for (let i = 0; i < frames.length; i++) {\n if (frames[i].time < timeMs) continue\n const found = frames[i].animations.find((a) => a.animationId === anim.id)\n if (found) { frameAnim = found; status = 'upcoming'; break }\n }\n }\n }\n\n const progressLabel = status === 'active'\n ? `${Math.round((frameAnim?.progress ?? 0) * 100)}%`\n : status === 'completed' ? 'done' : 'upcoming'\n\n return {\n element: anim.selector,\n elementLabel: anim.elementLabel || anim.selector,\n name: anim.name || anim.type,\n type: anim.type,\n timing: `${Math.round(anim.duration)}ms ${anim.easing}${anim.delay ? ` (delay: ${Math.round(anim.delay)}ms)` : ''}`,\n progress: progressLabel,\n properties: (frameAnim?.properties ?? []).map((p) => ({\n property: p.property,\n value: p.value,\n range: p.from && p.to ? `${p.from} \\u2192 ${p.to}` : ''\n })),\n source: anim.source,\n resolvedVars: anim.resolvedVars,\n conflicts: anim.conflicts\n }\n })\n\n const hoveredElements = Array.isArray(frame?.hoveredSels)\n ? frame.hoveredSels.map(String)\n : []\n const focusedElement = frame?.focusSel ? String(frame.focusSel) : null\n\n return {\n timestamp: `${Math.round(timeMs)}ms into ${Math.round(duration)}ms recording`,\n duration: `${Math.round(duration)}ms`,\n scrubPosition: timeMs,\n hoveredElements,\n focusedElement,\n animations: animExports\n }\n}\n\nexport function formatExportForLLM(exp: TimelineExport, detail: OutputDetailLevel = 'standard'): string {\n const lines: string[] = []\n\n // Group animations by element\n const grouped = new Map<string, { label: string; selector: string; anims: typeof exp.animations }>()\n for (const anim of exp.animations) {\n const key = (anim.elementLabel || '') + '|||' + anim.element\n if (!grouped.has(key)) {\n grouped.set(key, { label: anim.elementLabel || '', selector: anim.element, anims: [] })\n }\n grouped.get(key)!.anims.push(anim)\n }\n\n // Helper: skip no-change properties\n function isRealChange(prop: { range: string }): boolean {\n if (!prop.range) return true\n const [from, to] = prop.range.split(' \\u2192 ')\n return !(from && to && from.trim() === to.trim())\n }\n\n // ── Compact ──────────────────────────────────────────────────────────\n if (detail === 'compact') {\n lines.push(`# Animation State at ${exp.timestamp}`)\n lines.push('')\n for (const [, group] of grouped) {\n const label = group.label && group.label !== group.selector\n ? `**${group.label}** \\`${group.selector}\\``\n : `\\`${group.selector}\\``\n const cssAnims = group.anims.filter((a) => a.type !== 'JSAnimation')\n const jsAnims = group.anims.filter((a) => a.type === 'JSAnimation')\n\n if (cssAnims.length > 0) {\n const props = new Set<string>()\n for (const a of cssAnims) a.properties.filter(isRealChange).forEach((p) => props.add(p.property))\n const timing = cssAnims[0]?.timing || ''\n const progress = cssAnims[0]?.progress || ''\n const progressStr = progress && progress !== 'unknown' ? ` @ ${progress}` : ''\n lines.push(`- ${label}: ${[...props].join(', ')} (${timing}${progressStr})`)\n }\n if (jsAnims.length > 0) {\n const props = new Set<string>()\n for (const a of jsAnims) a.properties.filter(isRealChange).forEach((p) => props.add(p.property))\n if (props.size > 0) lines.push(`- ${label}: ${[...props].join(', ')} (JS)`)\n }\n }\n return lines.join('\\n')\n }\n\n // ── Standard / Detailed / Forensic ───────────────────────────────────\n lines.push(`# Animation State at ${exp.timestamp}`)\n lines.push('')\n\n // Forensic: environment info\n if (detail === 'forensic') {\n lines.push('**Environment:**')\n lines.push(`- Viewport: ${window.innerWidth}\\u00d7${window.innerHeight}`)\n lines.push(`- URL: ${window.location.href}`)\n lines.push(`- User Agent: ${navigator.userAgent}`)\n lines.push(`- Timestamp: ${new Date().toISOString()}`)\n lines.push(`- Device Pixel Ratio: ${window.devicePixelRatio}`)\n lines.push('')\n }\n\n // Interaction state (standard+)\n if (exp.hoveredElements.length > 0 || exp.focusedElement) {\n lines.push('**Interaction state:**')\n if (exp.hoveredElements.length > 0) {\n const deepest = exp.hoveredElements[exp.hoveredElements.length - 1] || exp.hoveredElements[0]\n lines.push(`- Hovered: \\`${deepest}\\``)\n }\n if (exp.focusedElement) {\n lines.push(`- Focused: \\`${exp.focusedElement}\\``)\n }\n lines.push('')\n }\n\n if (exp.animations.length === 0 && exp.hoveredElements.length === 0 && !exp.focusedElement) {\n lines.push('No active animations or interactions at this position.')\n return lines.join('\\n')\n }\n\n if (exp.animations.length === 0) {\n return lines.join('\\n')\n }\n\n for (const [, group] of grouped) {\n const label = group.label && group.label !== group.selector ? `\"${group.label}\" ` : ''\n const cssAnims = group.anims.filter((a) => a.type !== 'JSAnimation')\n const jsAnims = group.anims.filter((a) => a.type === 'JSAnimation')\n\n // Collect CSS property lines\n const cssPropLines: string[] = []\n if (cssAnims.length > 0) {\n const seenProps = new Set<string>()\n for (const anim of cssAnims) {\n const progressStr = anim.progress !== 'unknown' ? ` @ ${anim.progress}` : ''\n for (const prop of anim.properties) {\n if (seenProps.has(prop.property)) continue\n if (!isRealChange(prop)) continue\n seenProps.add(prop.property)\n let line = `- \\`${prop.property}\\`: ${prop.value}`\n if (prop.range) line += ` [${prop.range}]`\n line += ` (${anim.timing}${progressStr})`\n cssPropLines.push(line)\n }\n }\n }\n\n // Collect JS property lines\n const jsPropLines: string[] = []\n if (jsAnims.length > 0) {\n const seenProps = new Set<string>()\n for (const anim of jsAnims) {\n for (const prop of anim.properties) {\n if (seenProps.has(prop.property)) continue\n if (!isRealChange(prop)) continue\n seenProps.add(prop.property)\n jsPropLines.push(`- \\`${prop.property}\\`: ${prop.value}`)\n }\n }\n }\n\n // Skip group entirely if nothing to show\n if (cssPropLines.length === 0 && jsPropLines.length === 0) continue\n\n lines.push(`## ${label}\\`${group.selector}\\``)\n lines.push('')\n\n if (cssPropLines.length > 0) {\n const transitionSet = new Set(cssAnims.map((a) => `${a.name} ${a.timing}`))\n lines.push(`Transitions: ${[...transitionSet].join(', ')}`)\n lines.push('')\n for (const line of cssPropLines) lines.push(line)\n\n if (detail === 'detailed' || detail === 'forensic') {\n const allVars: Record<string, string> = {}\n for (const anim of cssAnims) {\n if (anim.resolvedVars) Object.assign(allVars, anim.resolvedVars)\n }\n if (Object.keys(allVars).length > 0) {\n lines.push('')\n lines.push('CSS variables:')\n for (const [name, value] of Object.entries(allVars)) {\n lines.push(`- \\`${name}\\`: ${value}`)\n }\n }\n\n for (const anim of cssAnims) {\n if (anim.source) {\n lines.push('')\n lines.push('```css')\n lines.push(anim.source)\n lines.push('```')\n break\n }\n }\n }\n }\n\n if (jsPropLines.length > 0) {\n if (cssPropLines.length > 0) lines.push('')\n for (const line of jsPropLines) lines.push(line)\n }\n\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n","import { TimingController } from './timing'\nimport { TimelineRecorder } from './recorder'\nimport { TimelineScrubber, type ScrubberState } from './scrubber'\nimport { generateExport, formatExportForLLM } from './export'\nimport type {\n ExportFilter,\n OutputDetailLevel,\n Rect,\n TimelineCapture,\n TimelineExport\n} from './types'\n\nexport type SaccadeState = 'idle' | 'recording' | 'scrubbing'\n\nexport class SaccadeEngine {\n private timing = new TimingController()\n private recorder = new TimelineRecorder()\n private scrubber: TimelineScrubber | null = null\n private capture: TimelineCapture | null = null\n private _state: SaccadeState = 'idle'\n private listeners = new Set<() => void>()\n\n get state(): SaccadeState {\n return this._state\n }\n\n getCapture(): TimelineCapture | null {\n return this.capture\n }\n\n // -- Speed control --------------------------------------------------------\n\n setSpeed(speed: number): void {\n this.timing.setSpeed(speed)\n }\n\n getSpeed(): number {\n return this.timing.getSpeed()\n }\n\n // -- Timeline recording ---------------------------------------------------\n\n startRecording(boundingBox?: Rect | null): void {\n if (this._state !== 'idle') return\n this.timing.install()\n this.recorder.onAutoStop = () => this.stopRecording()\n this.recorder.startRecording(boundingBox)\n this._state = 'recording'\n this.notify()\n }\n\n stopRecording(): TimelineCapture {\n if (this._state !== 'recording') {\n return {\n startTime: 0, endTime: 0, duration: 0,\n animations: [], frames: [], boundingBox: null\n }\n }\n\n let capture: TimelineCapture\n try {\n capture = this.recorder.stopRecording()\n } catch (e) {\n if (typeof console !== 'undefined') console.error('[Saccade] stopRecording failed:', e)\n // Clean up any artifacts the recorder injected before the error\n document.getElementById('__lapse-scrub-blocker')?.remove()\n document.getElementById('__lapse-no-transitions')?.remove()\n document.getElementById('__lapse-state-rules')?.remove()\n this._state = 'idle'\n this.notify()\n return {\n startTime: 0, endTime: 0, duration: 0,\n animations: [], frames: [], boundingBox: null\n }\n }\n\n this.capture = capture\n\n // Create scrubber with recorder's state\n const scrubberState: ScrubberState = {\n elements: this.recorder.elements,\n frames: capture.frames,\n capturedPortals: this.recorder.capturedPortalIds,\n interceptedAnimations: this.recorder.interceptedAnimations,\n SAFE_PROPS_SET: this.recorder.SAFE_PROPS_SET,\n seekableClones: this.recorder.seekableClones,\n }\n this.scrubber = new TimelineScrubber(scrubberState)\n\n this._state = 'scrubbing'\n this.notify()\n return capture\n }\n\n // -- Scrubbing ------------------------------------------------------------\n\n seekTo(timeMs: number): void {\n this.scrubber?.seekTo(timeMs)\n }\n\n release(): void {\n this.scrubber?.release()\n this.scrubber = null\n this.capture = null\n this._state = 'idle'\n this.notify()\n }\n\n // -- Export ---------------------------------------------------------------\n\n generateExport(timeMs: number, filter: ExportFilter = 'active'): TimelineExport | null {\n if (!this.capture) return null\n return generateExport(\n this.capture.animations,\n this.capture.frames,\n timeMs,\n filter\n )\n }\n\n exportForLLM(timeMs: number, filter: ExportFilter = 'active', detail: OutputDetailLevel = 'standard'): string {\n const exp = this.generateExport(timeMs, filter)\n if (!exp) return ''\n return formatExportForLLM(exp, detail)\n }\n\n // -- State subscription ---------------------------------------------------\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => this.listeners.delete(listener)\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener()\n }\n }\n\n // -- Cleanup --------------------------------------------------------------\n\n destroy(): void {\n this.scrubber?.release()\n this.scrubber = null\n this.capture = null\n this.timing.destroy()\n this._state = 'idle'\n }\n}\n","import { useRef, useCallback } from 'react'\nimport { Timeline } from './Timeline'\nimport { SpeedControl } from './SpeedControl'\nimport { useTimeline } from './useTimeline'\nimport { useSpeed } from './useSpeed'\n\nexport function SaccadePanel() {\n const timeline = useTimeline()\n const { speed, isPaused, setSpeed, togglePause } = useSpeed()\n const panelRef = useRef<HTMLDivElement>(null)\n const warmTimeout = useRef<ReturnType<typeof setTimeout>>(null)\n\n // When mouse enters a tooltipped element, mark the panel as \"warm\"\n // so subsequent tooltips appear instantly. Goes cold 300ms after leaving.\n const handleMouseOver = useCallback((e: React.MouseEvent) => {\n const target = (e.target as HTMLElement).closest?.('[data-tooltip]')\n if (target && panelRef.current) {\n panelRef.current.classList.add('lapse-tooltip-warm')\n if (warmTimeout.current) clearTimeout(warmTimeout.current)\n }\n }, [])\n\n const handleMouseOut = useCallback((e: React.MouseEvent) => {\n const related = e.relatedTarget as HTMLElement | null\n const stillOnTooltip = related?.closest?.('[data-tooltip]')\n if (!stillOnTooltip) {\n warmTimeout.current = setTimeout(() => {\n panelRef.current?.classList.remove('lapse-tooltip-warm')\n }, 300)\n }\n }, [])\n\n return (\n <div\n ref={panelRef}\n className=\"lapse-panel\"\n onMouseOver={handleMouseOver}\n onMouseOut={handleMouseOut}\n >\n <Timeline\n state={timeline.state}\n capture={timeline.capture}\n scrubTime={timeline.scrubTime}\n copied={timeline.copied}\n exportFilter={timeline.exportFilter}\n onSetExportFilter={timeline.setExportFilter}\n onStartRecording={() => timeline.startRecording()}\n onStopRecording={timeline.stopRecording}\n onSeek={timeline.seek}\n onRelease={timeline.release}\n onExportLLM={() => timeline.exportLLM()}\n detailLevel={timeline.detailLevel}\n onCycleDetailLevel={timeline.cycleDetailLevel}\n />\n {timeline.state !== 'scrubbing' && (\n <div className={`lapse-speed-wrap ${timeline.state === 'recording' ? 'lapse-speed-wrap--hidden' : ''}`}>\n <SpeedControl\n speed={speed}\n isPaused={isPaused}\n onSetSpeed={setSpeed}\n onTogglePause={togglePause}\n />\n </div>\n )}\n </div>\n )\n}\n","import { useCallback, useRef, useState, useEffect, type MouseEvent, type CSSProperties } from 'react'\nimport type { ExportFilter, OutputDetailLevel, TimelineCapture } from '../core/types'\nimport type { SaccadeState } from '../core/engine'\n\nconst DETAIL_LEVELS: OutputDetailLevel[] = ['compact', 'standard', 'detailed', 'forensic']\nconst DETAIL_LABELS: Record<OutputDetailLevel, string> = {\n compact: 'Compact',\n standard: 'Standard',\n detailed: 'Detailed',\n forensic: 'Forensic',\n}\n\nfunction CopyCheckIcon({ copied }: { copied: boolean }) {\n // Copy square: x=2 y=7 w=7 h=7 rx=1.5 stroke=2, center (5.5, 10.5)\n // Target circle: centered at (8,8), rx=6.5 (midpoint of 5.5–7.5 ring), w/h=13, stroke=2\n const spring = 'cubic-bezier(0.34, 1.15, 0.64, 1)'\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n {/* Back L-shape — fades out */}\n <path\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n d=\"M7 4v-.5A1.5 1.5 0 0 1 8.5 2h4A1.5 1.5 0 0 1 14 3.5v4A1.5 1.5 0 0 1 12.5 9H12\"\n style={{\n opacity: copied ? 0 : 1,\n transition: copied\n ? 'opacity 0.1s ease-out'\n : 'opacity 0.15s ease-out 0.18s',\n }}\n />\n {/* Square → circle morph */}\n <rect\n stroke={copied ? '#33C664' : 'currentColor'}\n fill=\"none\"\n style={{\n x: copied ? 1.5 : 2,\n y: copied ? 1.5 : 7,\n width: copied ? 13 : 7,\n height: copied ? 13 : 7,\n rx: copied ? 6.5 : 1.5,\n ry: copied ? 6.5 : 1.5,\n strokeWidth: 2,\n transition: copied\n ? `x 0.28s ${spring}, y 0.28s ${spring}, width 0.28s ${spring}, height 0.28s ${spring}, rx 0.28s ${spring}, ry 0.28s ${spring}`\n : 'x 0.22s ease-in-out, y 0.22s ease-in-out, width 0.22s ease-in-out, height 0.22s ease-in-out, rx 0.22s ease-in-out, ry 0.22s ease-in-out',\n } as React.CSSProperties}\n />\n {/* Checkmark — draws in at exact target coordinates */}\n <path\n d=\"m5.5 8.5 2 1.5 2.75-3.75\"\n stroke={copied ? '#33C664' : 'currentColor'}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n style={{\n strokeDasharray: 12,\n strokeDashoffset: copied ? 0 : 12,\n opacity: copied ? 1 : 0,\n transition: copied\n ? 'stroke-dashoffset 0.25s ease-out 0.1s, opacity 0.08s ease-out 0.08s'\n : 'stroke-dashoffset 0.12s ease-in, opacity 0.08s ease-in',\n }}\n />\n </svg>\n )\n}\n\nconst DETAIL_BRIGHT_COUNT: Record<OutputDetailLevel, number> = {\n compact: 1,\n standard: 2,\n detailed: 3,\n forensic: 4,\n}\n\nfunction DetailIcon({ level }: { level: OutputDetailLevel }) {\n const bright = DETAIL_BRIGHT_COUNT[level]\n // Lines at y=2, y=6, y=10, y=14 (top to bottom)\n const ys = [2, 6, 10, 14]\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n {ys.map((y, i) => (\n <path\n key={y}\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth=\"2\"\n d=\"M2 0h12\"\n transform={`translate(0, ${y})`}\n style={{\n opacity: i < bright ? 1 : 0.4,\n transition: 'opacity 0.2s ease-out',\n }}\n />\n ))}\n </svg>\n )\n}\n\ntype TimelineProps = {\n state: SaccadeState\n capture: TimelineCapture | null\n scrubTime: number\n copied: boolean\n exportFilter: ExportFilter\n onSetExportFilter: (f: ExportFilter) => void\n onStartRecording: () => void\n onStopRecording: () => void\n onSeek: (timeMs: number) => void\n onRelease: () => void\n onExportLLM: () => void\n detailLevel: OutputDetailLevel\n onCycleDetailLevel: () => void\n}\n\nexport function Timeline({\n state,\n capture,\n scrubTime,\n copied,\n onStartRecording,\n onStopRecording,\n onSeek,\n onRelease,\n onExportLLM,\n detailLevel,\n onCycleDetailLevel\n}: TimelineProps) {\n const scrubberRef = useRef<HTMLDivElement>(null)\n const isDragging = useRef(false)\n const [hasLeftRecord, setHasLeftRecord] = useState(false)\n\n useEffect(() => {\n if (state === 'recording') setHasLeftRecord(false)\n }, [state])\n\n const handleScrub = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n if (!capture || !scrubberRef.current) return\n const rect = scrubberRef.current.getBoundingClientRect()\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n onSeek(x * capture.duration)\n },\n [capture, onSeek]\n )\n\n const handleMouseDown = useCallback(\n (e: MouseEvent<HTMLDivElement>) => {\n isDragging.current = true\n handleScrub(e)\n\n const handleMouseMove = (e: globalThis.MouseEvent) => {\n if (!isDragging.current || !capture || !scrubberRef.current) return\n const rect = scrubberRef.current.getBoundingClientRect()\n const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))\n onSeek(x * capture.duration)\n }\n\n const handleMouseUp = () => {\n isDragging.current = false\n window.removeEventListener('mousemove', handleMouseMove)\n window.removeEventListener('mouseup', handleMouseUp)\n }\n\n window.addEventListener('mousemove', handleMouseMove)\n window.addEventListener('mouseup', handleMouseUp)\n },\n [capture, handleScrub, onSeek]\n )\n\n const progress = capture && capture.duration > 0 ? scrubTime / capture.duration : 0\n const isScrubbing = state === 'scrubbing'\n const isRecording = state === 'recording'\n\n function handleMainClick() {\n if (state === 'idle') onStartRecording()\n else if (state === 'recording') onStopRecording()\n else if (state === 'scrubbing') onRelease()\n }\n\n const tooltip = state === 'idle' ? 'Record' : state === 'recording' ? 'Stop' : 'Clear'\n\n return (\n <>\n {/* Main button — morphs between record / recording / close */}\n <button\n onClick={handleMainClick}\n className={`lapse-btn lapse-btn-icon lapse-main-btn ${isRecording ? 'lapse-record-btn--active' : ''}`}\n data-tooltip={tooltip}\n onMouseLeave={isRecording ? () => setHasLeftRecord(true) : undefined}\n >\n {/* Record icon (ring) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${state === 'idle' ? 'lapse-morph-icon--active' : ''}`}\n >\n <path fill=\"currentColor\" d=\"M8 .5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15Zm0 2a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z\"/>\n </svg>\n\n {/* Recording icon (filled circle / square) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${isRecording ? 'lapse-morph-icon--active' : ''}`}\n >\n <rect\n x={hasLeftRecord ? '1.5' : '0.5'}\n y={hasLeftRecord ? '1.5' : '0.5'}\n width={hasLeftRecord ? '13' : '15'}\n height={hasLeftRecord ? '13' : '15'}\n rx={hasLeftRecord ? '3' : '7.5'}\n fill=\"currentColor\"\n className=\"lapse-record-shape\"\n />\n </svg>\n\n {/* Clear icon (undo arrow) */}\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n className={`lapse-morph-icon ${isScrubbing ? 'lapse-morph-icon--active' : ''}`}\n >\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"m5.5 3-3 3m0 0h7a3.5 3.5 0 1 1 0 7h-2m-5-7 3 3\"/>\n </svg>\n </button>\n\n {/* Scrub content — expands when scrubbing */}\n <div className={`lapse-scrub-wrap ${isScrubbing ? 'lapse-scrub-wrap--visible' : ''}`}>\n <div className=\"lapse-scrub-inner\">\n {/* Scrub track */}\n <div\n ref={scrubberRef}\n onMouseDown={handleMouseDown}\n className=\"lapse-scrub-track\"\n >\n {capture && capture.duration > 0 && (() => {\n const seen = new Set<string>()\n const times: number[] = []\n for (const frame of capture.frames) {\n if (!frame.animations) continue\n for (const fa of frame.animations) {\n if (!seen.has(fa.animationId)) {\n seen.add(fa.animationId)\n times.push(frame.time)\n }\n }\n }\n times.sort((a, b) => a - b)\n const clusters: { time: number; count: number }[] = []\n for (const t of times) {\n const last = clusters[clusters.length - 1]\n if (last && t - last.time < 200) {\n last.count++\n } else {\n clusters.push({ time: t, count: 1 })\n }\n }\n return clusters.map((c, i) => (\n <div\n key={i}\n className=\"lapse-scrub-marker\"\n style={{ left: `${(c.time / capture.duration) * 100}%` }}\n />\n ))\n })()}\n\n <div className=\"lapse-scrub-fill\" style={{ width: `calc(${progress * 100}% + 4px)` }} />\n <div className=\"lapse-scrub-playhead\" style={{ left: `clamp(4px, ${progress * 100}%, calc(100% - 4px))` }} />\n\n <div className=\"lapse-scrub-label\">\n <span>{Math.round(scrubTime)}ms / {Math.round(capture?.duration ?? 0)}ms</span>\n </div>\n </div>\n\n {/* Detail level */}\n <button\n onClick={onCycleDetailLevel}\n className=\"lapse-btn lapse-btn-icon\"\n data-tooltip={DETAIL_LABELS[detailLevel]}\n >\n <DetailIcon level={detailLevel} />\n </button>\n\n {/* Export */}\n <button onClick={onExportLLM} className=\"lapse-btn lapse-btn-icon\" data-tooltip={copied ? 'Copied!' : 'Copy'}>\n <CopyCheckIcon copied={copied} />\n </button>\n </div>\n </div>\n </>\n )\n}\n","import { useRef, useCallback } from 'react'\nimport { formatSpeed } from './constants'\n\nconst SPEEDS = [1, 0.75, 0.5, 0.25, 0.1] as const\n\n// Angles matching the original icon hand positions (clockwise from 12 o'clock)\nconst SPEED_ANGLES: Record<number, number> = {\n 0.1: 225, // 7 o'clock\n 0.25: 315, // 10 o'clock\n 0.5: 0, // 12 o'clock\n 0.75: 45, // 2 o'clock\n 1: 135, // 4 o'clock\n}\n\n// Hand paths extracted from original icons (drawn at 12 o'clock / 0°)\n// These are the exact hand shapes — we rotate the <g> to position them\n// Original hand path at 12 o'clock (0.5x icon):\nconst HAND_PATH = 'm0 2a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1Z'\n\n// Actually, the hands are all different shapes at different angles in your icons.\n// To keep the exact icon shapes, I'll overlay all 5 hand paths and show/hide the active one.\n// The circle ring stays static, only the hand swaps.\n\n// Hand paths from the original icons (everything after the circle ring path)\nconst HAND_PATHS: Record<number, string> = {\n 0.1: 'M7.293 5.293a1 1 0 1 1 1.414 1.414l-1.5 1.5a1 1 0 1 1-1.414-1.414l1.5-1.5Z',\n 0.25: 'M5.793 5.794a1 1 0 0 1 1.414 0l1.5 1.499a1 1 0 0 1-1.414 1.414l-1.5-1.499a1 1 0 0 1 0-1.414Z',\n 0.5: 'M8 5a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V6a1 1 0 0 1 1-1Z',\n 0.75: 'M8.793 5.293a1 1 0 0 1 1.414 1.414l-1.5 1.5a1 1 0 0 1-1.414-1.414l1.5-1.5Z',\n 1: 'M7.293 8.293a1 1 0 0 1 1.414 0l1.5 1.5a1 1 0 1 1-1.414 1.414l-1.5-1.5a1 1 0 0 1 0-1.414Z',\n}\n\ntype SpeedControlProps = {\n speed: number\n isPaused: boolean\n onSetSpeed: (speed: number) => void\n onTogglePause: () => void\n}\n\nexport function SpeedControl({ speed, isPaused, onSetSpeed, onTogglePause }: SpeedControlProps) {\n const currentIndex = SPEEDS.findIndex((s) => Math.abs(speed - s) < 0.001)\n const activeIndex = currentIndex >= 0 ? currentIndex : 0\n const prevAngleRef = useRef(SPEED_ANGLES[SPEEDS[activeIndex]])\n const cumulativeRef = useRef(SPEED_ANGLES[SPEEDS[activeIndex]])\n const directionRef = useRef<1 | -1>(1) // 1 = going down (slowing), -1 = going up (speeding)\n const forceClockwiseRef = useRef(false)\n\n function cycle() {\n if (isPaused) {\n onTogglePause()\n return\n }\n let next = activeIndex + directionRef.current\n // Bounce at ends\n if (next >= SPEEDS.length) {\n directionRef.current = -1\n next = activeIndex - 1\n } else if (next < 0) {\n directionRef.current = 1\n next = activeIndex + 1\n }\n onSetSpeed(SPEEDS[next])\n }\n\n // Calculate rotation — shortest path normally, forced direction for pause/hold\n const targetAngle = isPaused ? 180 : (SPEED_ANGLES[SPEEDS[activeIndex]] ?? 135)\n if (targetAngle !== prevAngleRef.current) {\n let delta = targetAngle - prevAngleRef.current\n if (isPaused) {\n // Anticlockwise — drops to 6 o'clock\n while (delta >= 0) delta -= 360\n } else if (forceClockwiseRef.current) {\n // Hold reset — always clockwise\n while (delta <= 0) delta += 360\n forceClockwiseRef.current = false\n } else {\n // Shortest path\n while (delta > 180) delta -= 360\n while (delta < -180) delta += 360\n }\n cumulativeRef.current += delta\n prevAngleRef.current = targetAngle\n }\n\n // Press-and-hold to jump back to 1x\n const holdTimerRef = useRef<ReturnType<typeof setTimeout>>(null)\n const didHoldRef = useRef(false)\n\n const startHold = useCallback(() => {\n didHoldRef.current = false\n holdTimerRef.current = setTimeout(() => {\n didHoldRef.current = true\n forceClockwiseRef.current = true\n directionRef.current = 1\n onSetSpeed(1)\n }, 240)\n }, [onSetSpeed])\n\n const endHold = useCallback(() => {\n if (holdTimerRef.current) clearTimeout(holdTimerRef.current)\n holdTimerRef.current = null\n }, [])\n\n const handleClick = useCallback(() => {\n if (didHoldRef.current) {\n didHoldRef.current = false\n return\n }\n cycle()\n }, [cycle])\n\n const currentSpeed = SPEEDS[activeIndex]\n\n return (\n <div className=\"lapse-speed\">\n <button\n onClick={onTogglePause}\n className=\"lapse-btn lapse-btn-icon lapse-playpause\"\n data-tooltip={isPaused ? 'Play' : 'Pause'}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className={`lapse-playpause-icon ${isPaused ? 'lapse-playpause-icon--active' : ''}`} style={{ marginLeft: 1 }}>\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"2\" d=\"M3 12.821V3.18a1 1 0 0 1 1.476-.88l8.9 4.822a1 1 0 0 1 0 1.758l-8.9 4.821A1 1 0 0 1 3 12.821Z\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className={`lapse-playpause-icon ${!isPaused ? 'lapse-playpause-icon--active' : ''}`}>\n <path stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"2\" d=\"M3.5 2.5v11m9-11v11\"/>\n </svg>\n </button>\n\n <button\n onClick={handleClick}\n onMouseDown={startHold}\n onMouseUp={endHold}\n onMouseLeave={endHold}\n className=\"lapse-speed-cycle\"\n data-tooltip={formatSpeed(speed)}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"lapse-speed-clock\">\n {/* Circle ring — static */}\n <path fill=\"currentColor\" d=\"M8 .5a7.5 7.5 0 1 1 0 15 7.5 7.5 0 0 1 0-15Zm0 2a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11Z\" />\n {/* Hand — rotated to match position, always clockwise */}\n <g style={{ transform: `rotate(${cumulativeRef.current}deg)`, transformOrigin: '8px 8px', transition: 'transform 0.4s cubic-bezier(0, 0.55, 0.45, 1)' }}>\n {/* Use the 12 o'clock hand (0.5x), rotation handles positioning */}\n <path fill=\"currentColor\" d={HAND_PATHS[0.5]} />\n </g>\n </svg>\n </button>\n </div>\n )\n}\n","export const SPEED_PRESETS = [0.1, 0.25, 0.5, 0.75, 1] as const\n\nexport const SPEED_MIN = 0.05\nexport const SPEED_MAX = 5\n\nexport function formatSpeed(speed: number): string {\n if (speed >= 0.1) return `${speed}\\u00d7`\n return `${speed.toFixed(2)}\\u00d7`\n}\n","import { useState, useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\nimport { useSaccadeEngine } from './SaccadeContext'\nimport type { ExportFilter, OutputDetailLevel, Rect, TimelineCapture } from '../core/types'\nimport type { SaccadeState } from '../core/engine'\n\nconst DETAIL_LEVELS: OutputDetailLevel[] = ['compact', 'standard', 'detailed', 'forensic']\n\nexport function useTimeline() {\n const engine = useSaccadeEngine()\n\n const state = useSyncExternalStore(\n (cb) => engine.subscribe(cb),\n () => engine.state\n ) as SaccadeState\n\n const [capture, setCapture] = useState<TimelineCapture | null>(null)\n const [scrubTime, setScrubTime] = useState(0)\n const [copied, setCopied] = useState(false)\n const [exportFilter, setExportFilter] = useState<ExportFilter>('all-animations')\n const [detailLevel, setDetailLevel] = useState<OutputDetailLevel>('standard')\n const copiedTimeout = useRef<ReturnType<typeof setTimeout>>(null)\n\n // Throttle seek calls to one per animation frame\n const pendingSeek = useRef<number | null>(null)\n const rafId = useRef<number>(0)\n\n // Sync capture from engine when auto-stop transitions state to scrubbing\n useEffect(() => {\n if (state === 'scrubbing' && !capture) {\n const engineCapture = engine.getCapture()\n if (engineCapture) {\n setCapture(engineCapture)\n setScrubTime(0)\n }\n } else if (state === 'idle') {\n setCapture(null)\n setScrubTime(0)\n }\n }, [state, capture, engine])\n\n const startRecording = useCallback(\n (boundingBox?: Rect | null) => {\n setCapture(null)\n setScrubTime(0)\n engine.startRecording(boundingBox)\n },\n [engine]\n )\n\n const stopRecording = useCallback(() => {\n try {\n const result = engine.stopRecording()\n setCapture(result)\n setScrubTime(0)\n } catch (e) {\n console.error('[Saccade] stopRecording failed:', e)\n }\n }, [engine])\n\n const seek = useCallback(\n (timeMs: number) => {\n setScrubTime(timeMs)\n pendingSeek.current = timeMs\n if (!rafId.current) {\n rafId.current = requestAnimationFrame(() => {\n rafId.current = 0\n if (pendingSeek.current !== null) {\n engine.seekTo(pendingSeek.current)\n pendingSeek.current = null\n }\n })\n }\n },\n [engine]\n )\n\n const release = useCallback(() => {\n if (rafId.current) { cancelAnimationFrame(rafId.current); rafId.current = 0 }\n pendingSeek.current = null\n engine.release()\n setCapture(null)\n setScrubTime(0)\n }, [engine])\n\n const cycleDetailLevel = useCallback(() => {\n setDetailLevel((prev) => {\n const idx = DETAIL_LEVELS.indexOf(prev)\n return DETAIL_LEVELS[(idx + 1) % DETAIL_LEVELS.length]\n })\n }, [])\n\n const exportLLM = useCallback(\n (filter?: ExportFilter) => {\n if (!capture) return ''\n const f = filter || exportFilter || 'active'\n const t = Number(scrubTime) || 0\n const text = engine.exportForLLM(t, f, detailLevel)\n navigator.clipboard.writeText(text).catch(() => {})\n setCopied(true)\n if (copiedTimeout.current) clearTimeout(copiedTimeout.current)\n copiedTimeout.current = setTimeout(() => setCopied(false), 2000)\n return text\n },\n [engine, capture, scrubTime, exportFilter, detailLevel]\n )\n\n return {\n state,\n capture,\n scrubTime,\n copied,\n exportFilter,\n setExportFilter,\n detailLevel,\n cycleDetailLevel,\n startRecording,\n stopRecording,\n seek,\n release,\n exportLLM\n }\n}\n","import { useState, useCallback, useEffect } from 'react'\nimport { useSaccadeEngine } from './SaccadeContext'\nimport { SPEED_PRESETS, SPEED_MIN, SPEED_MAX } from './constants'\n\nexport function useSpeed() {\n const engine = useSaccadeEngine()\n const [speed, setSpeedState] = useState(1)\n const [previousSpeed, setPreviousSpeed] = useState(1)\n const [isPaused, setIsPaused] = useState(false)\n\n const setSpeed = useCallback(\n (value: number) => {\n const clamped = Math.max(SPEED_MIN, Math.min(SPEED_MAX, value))\n setSpeedState(clamped)\n setIsPaused(false)\n setPreviousSpeed(clamped)\n engine.setSpeed(clamped)\n },\n [engine]\n )\n\n const togglePause = useCallback(() => {\n if (isPaused) {\n setSpeedState(previousSpeed)\n setIsPaused(false)\n engine.setSpeed(previousSpeed)\n } else {\n setPreviousSpeed(speed)\n setSpeedState(0)\n setIsPaused(true)\n engine.setSpeed(0)\n }\n }, [engine, isPaused, previousSpeed, speed])\n\n const stepDown = useCallback(() => {\n const currentIndex = SPEED_PRESETS.findIndex((p) => p >= speed)\n const nextIndex = Math.max(0, (currentIndex <= 0 ? 1 : currentIndex) - 1)\n setSpeed(SPEED_PRESETS[nextIndex])\n }, [speed, setSpeed])\n\n const stepUp = useCallback(() => {\n const currentIndex = SPEED_PRESETS.findIndex((p) => p > speed)\n const nextIndex = Math.min(\n SPEED_PRESETS.length - 1,\n currentIndex < 0 ? SPEED_PRESETS.length - 1 : currentIndex\n )\n setSpeed(SPEED_PRESETS[nextIndex])\n }, [speed, setSpeed])\n\n // Keyboard shortcuts\n useEffect(() => {\n function handleKeyDown(e: KeyboardEvent) {\n if (e.target instanceof HTMLInputElement) return\n switch (e.key) {\n case '[':\n stepDown()\n break\n case ']':\n stepUp()\n break\n case '\\\\':\n setSpeed(1)\n break\n case 's':\n togglePause()\n break\n }\n }\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [stepDown, stepUp, setSpeed, togglePause])\n\n return { speed, isPaused, setSpeed, togglePause }\n}\n","/** Panel styles injected into the Shadow DOM. */\nexport const PANEL_STYLES = /* css */ `\n :host {\n --lapse-bg: #1a1a1a;\n --lapse-surface: #2a2a2a;\n --lapse-border: #3a3a3a;\n --lapse-text: #e5e5e5;\n --lapse-text-muted: #888;\n --lapse-accent: #6d9fff;\n --lapse-speed-active: #5b8def;\n --lapse-danger: #ff6b6b;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: var(--lapse-text);\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* Tooltips */\n [data-tooltip] {\n position: relative;\n }\n [data-tooltip]::after {\n content: attr(data-tooltip);\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%) translateY(2px) scale(0.96);\n padding: 4px 10px;\n border-radius: 6px;\n background: #0d0d0d;\n border: 0.5px solid var(--lapse-border);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n color: var(--lapse-text);\n font-size: 11px;\n font-weight: 500;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.15s ease-out 0.65s, transform 0.15s ease-out 0.65s;\n }\n [data-tooltip]:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0) scale(1);\n }\n /* Warm: when panel already has a tooltip showing, new ones appear instantly */\n .lapse-panel.lapse-tooltip-warm [data-tooltip]::after {\n transition-duration: 0s;\n transition-delay: 0s;\n }\n\n /* Panel container */\n .lapse-panel {\n display: flex;\n align-items: center;\n gap: 0;\n background: var(--lapse-bg);\n border: 0.5px solid var(--lapse-border);\n border-radius: 999px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1);\n overflow: visible;\n }\n\n /* Buttons */\n .lapse-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 12px;\n border: none;\n border-radius: 999px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.15s, color 0.15s;\n }\n\n .lapse-btn-surface {\n background: transparent;\n color: var(--lapse-text-muted);\n }\n .lapse-btn-surface:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n\n .lapse-btn-recording {\n background: rgba(239, 68, 68, 0.1);\n color: #f87171;\n }\n .lapse-btn-recording:hover { background: rgba(239, 68, 68, 0.2); }\n\n .lapse-btn-accent {\n background: rgba(109, 159, 255, 0.2);\n color: var(--lapse-accent);\n font-size: 13px;\n }\n .lapse-btn-accent:hover { background: rgba(109, 159, 255, 0.3); }\n\n .lapse-btn-icon {\n width: 32px;\n height: 32px;\n padding: 0;\n justify-content: center;\n background: transparent;\n color: var(--lapse-text-muted);\n border: none;\n border-radius: 999px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n .lapse-btn-icon:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n .lapse-record-btn--active:hover {\n color: #ef4444;\n }\n\n /* Main button — icon morphing (record / recording / close) */\n .lapse-main-btn {\n position: relative;\n }\n\n .lapse-morph-icon {\n position: absolute;\n opacity: 0;\n scale: 0.4;\n filter: blur(6px);\n transition: opacity 0.2s ease, scale 0.2s ease, filter 0.2s ease;\n display: block;\n }\n .lapse-morph-icon--active {\n opacity: 1;\n scale: 1;\n filter: blur(0);\n }\n\n .lapse-record-shape {\n animation: lapse-pulse 1.5s ease-in-out infinite;\n transition: x 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n y 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n width 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n height 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n rx 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n\n .lapse-record-btn--active {\n color: #ef4444;\n }\n\n @keyframes lapse-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n /* Scrub content — expands when entering scrubbing state */\n .lapse-scrub-wrap {\n display: grid;\n grid-template-columns: 0fr;\n margin-left: 0;\n transition: grid-template-columns 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n margin-left 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-scrub-wrap > * {\n min-width: 0;\n }\n .lapse-scrub-wrap--visible {\n grid-template-columns: 1fr;\n margin-left: 6px;\n }\n\n .lapse-scrub-inner {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .lapse-scrub-inner > * {\n transform-origin: left center;\n transition: opacity 0.6s cubic-bezier(0.19, 1, 0.22, 1) 0.05s,\n transform 0.6s cubic-bezier(0.19, 1, 0.22, 1) 0.05s,\n filter 0.8s cubic-bezier(0.19, 1, 0.22, 1) 0.05s;\n }\n .lapse-scrub-wrap:not(.lapse-scrub-wrap--visible) .lapse-scrub-inner > * {\n opacity: 0;\n transform: scale(0.85);\n filter: blur(10px);\n transition-delay: 0ms;\n transition-duration: 0.15s;\n }\n\n /* Spinner */\n .lapse-spinner {\n width: 10px;\n height: 10px;\n animation: lapse-spin 1s linear infinite;\n }\n .lapse-spinner-track { opacity: 0.25; }\n .lapse-spinner-head { opacity: 0.75; }\n\n @keyframes lapse-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n\n /* Scrubber */\n .lapse-scrub-track {\n position: relative;\n height: 32px;\n width: 200px;\n cursor: pointer;\n border-radius: 6px;\n background: var(--lapse-surface);\n user-select: none;\n overflow: hidden;\n }\n\n .lapse-scrub-marker {\n position: absolute;\n top: 0;\n height: 100%;\n width: 1px;\n background: rgba(109, 159, 255, 0.5);\n pointer-events: none;\n }\n\n .lapse-scrub-fill {\n position: absolute;\n inset: 0;\n right: auto;\n background: rgba(109, 159, 255, 0.1);\n pointer-events: none;\n }\n\n .lapse-scrub-playhead {\n position: absolute;\n top: 4px;\n bottom: 4px;\n width: 2px;\n border-radius: 1px;\n background: var(--lapse-accent);\n transform: translateX(-50%);\n pointer-events: none;\n }\n\n .lapse-scrub-label {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: flex-end;\n justify-content: center;\n padding-bottom: 2px;\n pointer-events: none;\n }\n .lapse-scrub-label span {\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n color: var(--lapse-text-muted);\n }\n\n /* Filter buttons */\n .lapse-filter-group {\n display: flex;\n border-radius: 6px;\n background: var(--lapse-surface);\n overflow: hidden;\n }\n\n .lapse-filter-btn {\n height: 32px;\n padding: 0 8px;\n border: none;\n background: transparent;\n font-size: 13px;\n font-weight: 500;\n color: var(--lapse-text-muted);\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n .lapse-filter-btn:hover { color: var(--lapse-text); }\n .lapse-filter-btn--active {\n background: rgba(109, 159, 255, 0.2);\n color: var(--lapse-accent);\n }\n\n /* Chevron */\n .lapse-chevron {\n transition: transform 0.2s;\n }\n .lapse-chevron--open {\n transform: rotate(90deg);\n }\n\n /* Animation tags */\n .lapse-anim-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .lapse-anim-tag {\n background: rgba(109, 159, 255, 0.1);\n color: var(--lapse-accent);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 13px;\n }\n\n /* Speed control wrapper — collapses when recording */\n .lapse-speed-wrap {\n display: grid;\n grid-template-columns: 1fr;\n margin-left: 6px;\n transition: grid-template-columns 0.4s cubic-bezier(0.19, 1, 0.22, 1),\n margin-left 0.4s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-speed-wrap > * {\n min-width: 0;\n }\n .lapse-speed-wrap--hidden {\n grid-template-columns: 0fr;\n margin-left: 0;\n pointer-events: none;\n }\n .lapse-speed-wrap .lapse-speed {\n transition: transform 0.6s cubic-bezier(0.19, 1, 0.22, 1),\n filter 0.8s cubic-bezier(0.19, 1, 0.22, 1),\n opacity 0.6s cubic-bezier(0.19, 1, 0.22, 1);\n }\n .lapse-speed-wrap--hidden .lapse-speed {\n transform: translateX(-8px) scale(0.4);\n filter: blur(10px);\n opacity: 0;\n }\n\n /* Speed control */\n .lapse-speed {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n /* Speed cycle button */\n .lapse-speed-cycle {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 32px;\n padding: 0 8px;\n border: none;\n border-radius: 999px;\n background: transparent;\n color: var(--lapse-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n white-space: nowrap;\n }\n .lapse-speed-cycle:hover {\n background: var(--lapse-surface);\n color: var(--lapse-text);\n }\n\n /* Play/pause transition */\n .lapse-playpause {\n position: relative;\n }\n\n .lapse-playpause-icon {\n position: absolute;\n opacity: 0;\n scale: 0.4;\n filter: blur(6px);\n transition: opacity 0.2s ease, scale 0.2s ease, filter 0.2s ease;\n display: block;\n }\n\n .lapse-playpause-icon--active {\n opacity: 1;\n scale: 1;\n filter: blur(0);\n }\n\n .lapse-speed-cycle svg {\n display: block;\n }\n`\n"],"mappings":"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","names":["import_react","keyframes","import_react","import_react","import_jsx_runtime","e","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","import_jsx_runtime"]}