table-minimap 1.1.1 → 1.1.2

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,"file":"table-minimap.cjs","sources":["../src/TableMinimap.ts","../src/index.ts"],"sourcesContent":["import type {\n TableMinimapOptions,\n RequiredOptions,\n ColumnInfo,\n ScrollState,\n TableSelector,\n ZoomState,\n} from './types';\n\n/**\n * Default configuration options\n */\nconst DEFAULT_OPTIONS: RequiredOptions = {\n mode: 'columns',\n height: 40,\n position: 'bottom',\n fixedWidth: 300,\n fixedPosition: 'bottom-right',\n compact: false,\n draggable: true,\n showViewport: true,\n zoomable: false,\n minZoom: 1,\n maxZoom: 10,\n zoomSpeed: 0.1,\n};\n\n/** Compact floating minimap handle size in pixels */\nconst COMPACT_HANDLE_SIZE = 24;\n\n/** Visible dot size inside the compact handle in pixels */\nconst COMPACT_DOT_SIZE = 5;\n\n/** Delay before compact mode collapses after pointer leave */\nconst COMPACT_COLLAPSE_DELAY = 180;\n\n/**\n * TableMinimap - A framework-agnostic minimap component for large HTML tables\n *\n * @example\n * ```ts\n * import { TableMinimap } from 'table-minimap';\n * import 'table-minimap/style.css';\n *\n * const minimap = new TableMinimap('#my-table');\n *\n * // Or with options\n * const minimap = new TableMinimap('#my-table', {\n * mode: 'canvas',\n * height: 50,\n * position: 'top'\n * });\n *\n * // Cleanup\n * minimap.destroy();\n * ```\n */\nexport class TableMinimap {\n /** The target table element */\n private readonly table: HTMLTableElement;\n\n /** Configuration options */\n private readonly options: RequiredOptions;\n\n /** Whether compact fixed-overlay behavior is enabled */\n private readonly isCompactMode: boolean;\n\n /** Whether the compact minimap is currently collapsed */\n private isCompactCollapsed = false;\n\n /** Whether the compact minimap is currently expanding (transition in progress) */\n private isCompactExpanding = false;\n\n /** Timeout used to collapse compact mode after pointer leave */\n private compactCollapseTimer: number | null = null;\n\n /** The scrollable container (parent of table) */\n private scrollContainer: HTMLElement | null = null;\n\n /** Main minimap container element */\n private minimapEl: HTMLDivElement | null = null;\n\n /** Columns container for columns mode */\n private columnsEl: HTMLDivElement | null = null;\n\n /** Canvas element for canvas mode */\n private canvasEl: HTMLCanvasElement | null = null;\n\n /** Canvas 2D rendering context */\n private canvasCtx: CanvasRenderingContext2D | null = null;\n\n\n /** Viewport indicator element */\n private viewportEl: HTMLDivElement | null = null;\n\n /** Detected column information */\n private columns: ColumnInfo[] = [];\n\n /** Current scroll state */\n private scrollState: ScrollState = {\n scrollLeft: 0,\n scrollWidth: 0,\n clientWidth: 0,\n viewportRatio: 1,\n positionRatio: 0,\n };\n\n /** Current zoom state */\n private zoomState: ZoomState = {\n level: 1,\n panX: 0,\n isMinZoom: true,\n isMaxZoom: false,\n };\n\n /** Is the viewport being dragged */\n private isDragging = false;\n\n /** Is the canvas being panned (when zoomed) */\n private isPanning = false;\n\n /** Was just panning (to prevent click after pan) */\n private wasPanning = false;\n\n /** Pan start position */\n private panStartX = 0;\n\n /** Currently hovered column index (-1 = none) */\n private hoveredColumn = -1;\n\n /** Drag start X position */\n private dragStartX = 0;\n\n /** Drag start scroll position */\n private dragStartScrollLeft = 0;\n\n /** ResizeObserver instance */\n private resizeObserver: ResizeObserver | null = null;\n\n /** MutationObserver instance */\n private mutationObserver: MutationObserver | null = null;\n\n /** Bound event handlers for cleanup */\n private boundHandlers: {\n onScroll: () => void;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onMinimapClick: (e: MouseEvent) => void;\n onWheel: (e: WheelEvent) => void;\n onCanvasPointerDown: (e: PointerEvent) => void;\n onCanvasMouseMove: (e: MouseEvent) => void;\n onCanvasMouseLeave: () => void;\n onCompactFocusIn: () => void;\n onCompactFocusOut: () => void;\n onCompactKeyDown: (e: KeyboardEvent) => void;\n onDocumentClick: (e: MouseEvent) => void;\n };\n\n /** Animation frame ID for throttling */\n private rafId: number | null = null;\n\n /** Whether the instance has been destroyed */\n private isDestroyed = false;\n\n /**\n * Creates a new TableMinimap instance\n *\n * @param selector - CSS selector string or HTMLTableElement\n * @param options - Configuration options\n * @throws Error if table element is not found or invalid\n */\n constructor(selector: TableSelector, options: TableMinimapOptions = {}) {\n this.table = this.resolveTable(selector);\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.isCompactMode = this.options.compact && this.options.position === 'fixed';\n\n // Bind event handlers\n this.boundHandlers = {\n onScroll: this.onScroll.bind(this),\n onPointerDown: this.onPointerDown.bind(this),\n onPointerMove: this.onPointerMove.bind(this),\n onPointerUp: this.onPointerUp.bind(this),\n onMinimapClick: this.onMinimapClick.bind(this),\n onWheel: this.onWheel.bind(this),\n onCanvasPointerDown: this.onCanvasPointerDown.bind(this),\n onCanvasMouseMove: this.onCanvasMouseMove.bind(this),\n onCanvasMouseLeave: this.onCanvasMouseLeave.bind(this),\n onCompactFocusIn: this.onCompactFocusIn.bind(this),\n onCompactFocusOut: this.onCompactFocusOut.bind(this),\n onCompactKeyDown: this.onCompactKeyDown.bind(this),\n onDocumentClick: this.onDocumentClick.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Resolves the table element from a selector or element\n *\n * @param selector - CSS selector or HTMLTableElement\n * @returns The resolved table element\n * @throws Error if element is not found or not a table\n */\n private resolveTable(selector: TableSelector): HTMLTableElement {\n let element: HTMLTableElement | null;\n\n if (typeof selector === 'string') {\n element = document.querySelector<HTMLTableElement>(selector);\n if (!element) {\n throw new Error(\n `TableMinimap: No element found for selector \"${selector}\"`\n );\n }\n } else if (selector instanceof HTMLTableElement) {\n element = selector;\n } else {\n throw new Error(\n 'TableMinimap: Selector must be a CSS selector string or an HTMLTableElement'\n );\n }\n\n if (element.tagName !== 'TABLE') {\n throw new Error(\n `TableMinimap: Element must be a <table>, got <${element.tagName.toLowerCase()}>`\n );\n }\n\n return element;\n }\n\n /**\n * Initializes the minimap\n */\n private init(): void {\n this.scrollContainer = this.findScrollContainer();\n this.detectColumns();\n this.createMinimapElement();\n this.updateScrollState();\n this.render();\n this.attachEventListeners();\n this.setupObservers();\n }\n\n /**\n * Finds the nearest scrollable parent container\n *\n * @returns The scrollable container or the table's parent\n */\n private findScrollContainer(): HTMLElement {\n let parent = this.table.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowX = style.overflowX;\n const overflowY = style.overflow;\n\n if (\n overflowX === 'auto' ||\n overflowX === 'scroll' ||\n overflowY === 'auto' ||\n overflowY === 'scroll'\n ) {\n return parent;\n }\n\n // Check if content overflows\n if (parent.scrollWidth > parent.clientWidth) {\n return parent;\n }\n\n parent = parent.parentElement;\n }\n\n // Fallback to table's parent or body\n return this.table.parentElement || document.body;\n }\n\n /**\n * Detects table columns from thead or first row\n */\n private detectColumns(): void {\n this.columns = [];\n\n // Try thead th first\n const theadCells = this.table.querySelectorAll<HTMLTableCellElement>(\n 'thead th, thead td'\n );\n\n let cells: NodeListOf<HTMLTableCellElement> | HTMLTableCellElement[];\n\n if (theadCells.length > 0) {\n cells = theadCells;\n } else {\n // Fallback to first row cells\n const firstRow = this.table.querySelector('tr');\n if (firstRow) {\n cells = firstRow.querySelectorAll<HTMLTableCellElement>('th, td');\n } else {\n cells = [];\n }\n }\n\n const tableWidth = this.table.offsetWidth || 1;\n\n Array.from(cells).forEach((cell) => {\n // Handle colspan\n const colspan = cell.colSpan || 1;\n const cellWidth = cell.offsetWidth;\n\n for (let i = 0; i < colspan; i++) {\n const width = cellWidth / colspan;\n this.columns.push({\n index: this.columns.length,\n width,\n widthPercent: (width / tableWidth) * 100,\n });\n }\n });\n\n // Ensure at least one column\n if (this.columns.length === 0) {\n this.columns.push({\n index: 0,\n width: tableWidth,\n widthPercent: 100,\n });\n }\n }\n\n /**\n * Creates the minimap DOM element\n */\n private createMinimapElement(): void {\n // Create main container\n this.minimapEl = document.createElement('div');\n this.minimapEl.className = `tm-minimap tm-minimap--${this.options.position}`;\n this.minimapEl.style.setProperty('--tm-minimap-height', `${this.options.height}px`);\n\n // Set width and position class for fixed position\n if (this.options.position === 'fixed') {\n this.minimapEl.style.setProperty('--tm-minimap-width', `${this.options.fixedWidth}px`);\n this.minimapEl.classList.add(`tm-minimap--${this.options.fixedPosition}`);\n }\n\n if (this.isCompactMode) {\n this.minimapEl.classList.add('tm-minimap--compact', 'tm-minimap--compact-collapsed');\n this.minimapEl.style.setProperty('--tm-compact-dot-size', `${COMPACT_DOT_SIZE}px`);\n this.isCompactCollapsed = true;\n this.applyCompactDimensions(true);\n this.minimapEl.setAttribute('aria-expanded', 'false');\n } else {\n this.minimapEl.setAttribute('aria-expanded', 'true');\n }\n \n this.minimapEl.setAttribute('role', 'slider');\n this.minimapEl.setAttribute('aria-label', 'Table minimap navigation');\n this.minimapEl.setAttribute('aria-valuemin', '0');\n this.minimapEl.setAttribute('aria-valuemax', '100');\n this.minimapEl.setAttribute('tabindex', '0');\n\n // Create content based on mode\n if (this.options.mode === 'canvas') {\n this.createCanvasContent();\n } else {\n this.createColumnsContent();\n }\n\n // Create viewport indicator\n if (this.options.showViewport) {\n this.createViewportIndicator();\n }\n\n // Insert minimap\n this.insertMinimap();\n }\n\n /**\n * Creates columns-mode content\n */\n private createColumnsContent(): void {\n if (!this.minimapEl) return;\n\n this.columnsEl = document.createElement('div');\n this.columnsEl.className = 'tm-columns';\n\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n\n this.minimapEl.appendChild(this.columnsEl);\n }\n\n /**\n * Creates canvas-mode content\n */\n private createCanvasContent(): void {\n if (!this.minimapEl) return;\n\n this.canvasEl = document.createElement('canvas');\n this.canvasEl.className = 'tm-canvas';\n this.canvasCtx = this.canvasEl.getContext('2d');\n\n this.minimapEl.appendChild(this.canvasEl);\n }\n\n /**\n * Creates the viewport indicator element\n */\n private createViewportIndicator(): void {\n if (!this.minimapEl) return;\n\n this.viewportEl = document.createElement('div');\n this.viewportEl.className = 'tm-viewport';\n\n if (!this.options.draggable) {\n this.viewportEl.classList.add('tm-viewport--disabled');\n }\n\n this.minimapEl.appendChild(this.viewportEl);\n }\n\n /**\n * Inserts the minimap into the DOM\n */\n private insertMinimap(): void {\n if (!this.minimapEl || !this.scrollContainer) return;\n\n const parent = this.scrollContainer.parentElement;\n\n if (this.options.position === 'fixed') {\n // Fixed position: create a wrapper with relative positioning\n // Insert minimap after scroll container, but style it to overlay\n if (parent) {\n // Ensure parent has relative positioning for our fixed overlay\n const parentStyle = getComputedStyle(parent);\n if (parentStyle.position === 'static') {\n parent.style.position = 'relative';\n }\n\n // Insert after scroll container\n const nextSibling = this.scrollContainer.nextSibling;\n if (nextSibling) {\n parent.insertBefore(this.minimapEl, nextSibling);\n } else {\n parent.appendChild(this.minimapEl);\n }\n\n // Apply fixed positioning styles based on fixedPosition\n this.minimapEl.style.position = 'absolute';\n const offset = this.isCompactMode ? 8 : 12;\n const pos = this.options.fixedPosition;\n\n // Reset all positions first\n this.minimapEl.style.top = '';\n this.minimapEl.style.bottom = '';\n this.minimapEl.style.left = '';\n this.minimapEl.style.right = '';\n this.minimapEl.style.marginTop = '0';\n\n // Apply position based on fixedPosition option\n if (pos === 'top-left') {\n this.minimapEl.style.top = `${offset}px`;\n this.minimapEl.style.left = `${offset}px`;\n } else if (pos === 'top-right') {\n this.minimapEl.style.top = `${offset}px`;\n this.minimapEl.style.right = `${offset}px`;\n } else if (pos === 'bottom-left') {\n this.minimapEl.style.bottom = `${offset}px`;\n this.minimapEl.style.left = `${offset}px`;\n } else {\n // bottom-right (default)\n this.minimapEl.style.bottom = `${offset}px`;\n this.minimapEl.style.right = `${offset}px`;\n }\n }\n } else if (this.options.position === 'top') {\n // Insert before the scroll container (outside, above it)\n if (parent) {\n parent.insertBefore(this.minimapEl, this.scrollContainer);\n } else {\n // Fallback: insert as first child of scroll container\n this.scrollContainer.insertBefore(this.minimapEl, this.scrollContainer.firstChild);\n }\n } else {\n // Insert after the scroll container (outside, below it)\n if (parent) {\n const nextSibling = this.scrollContainer.nextSibling;\n if (nextSibling) {\n parent.insertBefore(this.minimapEl, nextSibling);\n } else {\n parent.appendChild(this.minimapEl);\n }\n } else {\n this.scrollContainer.appendChild(this.minimapEl);\n }\n }\n }\n\n /**\n * Updates the scroll state from the container\n */\n private updateScrollState(): void {\n if (!this.scrollContainer) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n\n this.scrollState = {\n scrollLeft,\n scrollWidth,\n clientWidth,\n viewportRatio: clientWidth / Math.max(scrollWidth, 1),\n positionRatio: scrollLeft / Math.max(scrollWidth - clientWidth, 1),\n };\n\n // Clamp values\n this.scrollState.viewportRatio = Math.min(1, Math.max(0, this.scrollState.viewportRatio));\n this.scrollState.positionRatio = Math.min(1, Math.max(0, this.scrollState.positionRatio));\n\n // Update ARIA values\n if (this.minimapEl) {\n this.minimapEl.setAttribute(\n 'aria-valuenow',\n String(Math.round(this.scrollState.positionRatio * 100))\n );\n }\n }\n\n /**\n * Renders the minimap\n */\n private render(): void {\n if (this.isDestroyed) return;\n\n if (this.isCompactMode && this.isCompactCollapsed) return;\n\n this.updateViewport();\n\n if (this.options.mode === 'canvas') {\n this.renderCanvas();\n }\n }\n\n /**\n * Canvas metrics for calculations - cached values to avoid repeated computations\n */\n private getCanvasMetrics() {\n const width = this.minimapEl?.offsetWidth ?? 0;\n const zoom = this.zoomState.level;\n const numCols = this.columns.length;\n const visibleRatio = 1 / zoom;\n const visibleCols = numCols * visibleRatio;\n const cellWidth = visibleCols > 0 ? width / visibleCols : 0;\n\n // Calculate panX based on scroll position\n let panX = 0;\n if (zoom > 1 && this.scrollContainer) {\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n const scrollRatio = scrollLeft / maxScroll;\n panX = scrollRatio * (1 - visibleRatio);\n }\n\n const startColFloat = panX * numCols;\n const startCol = Math.floor(startColFloat);\n const endCol = Math.min(Math.ceil(startColFloat + visibleCols) + 1, numCols);\n const xOffset = -(startColFloat - startCol) * cellWidth;\n\n return {\n width,\n zoom,\n numCols,\n visibleRatio,\n visibleCols,\n cellWidth,\n panX,\n startColFloat,\n startCol,\n endCol,\n xOffset,\n };\n }\n\n /**\n * Calculates column index from mouse X position\n */\n private getColumnAtX(mouseX: number): number {\n const { width, numCols, panX, visibleRatio } = this.getCanvasMetrics();\n if (numCols === 0 || width === 0) return -1;\n\n const relativeX = mouseX / width;\n const tableX = panX + relativeX * visibleRatio;\n const colIndex = Math.floor(tableX * numCols);\n\n return Math.max(0, Math.min(numCols - 1, colIndex));\n }\n\n /**\n * Updates the viewport indicator position and size\n * Shows the visible portion of the table (columns mode only)\n */\n private updateViewport(): void {\n if (!this.viewportEl || !this.minimapEl) return;\n\n // No viewport in canvas mode\n if (this.options.mode === 'canvas') {\n this.viewportEl.style.display = 'none';\n return;\n }\n\n const minimapWidth = this.minimapEl.offsetWidth;\n \n // Columns mode: viewport showing visible area\n const viewportWidth = Math.max(minimapWidth * this.scrollState.viewportRatio, 20);\n const maxLeft = minimapWidth - viewportWidth;\n const viewportLeft = maxLeft * this.scrollState.positionRatio;\n this.viewportEl.style.cssText = `width:${viewportWidth}px;left:${viewportLeft}px;display:block`;\n }\n\n /**\n * Renders the canvas-mode visualization with table preview\n */\n private renderCanvas(): void {\n if (!this.canvasEl || !this.canvasCtx || !this.minimapEl) return;\n\n const metrics = this.getCanvasMetrics();\n const height = this.options.height;\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas size with HiDPI support\n this.canvasEl.width = metrics.width * dpr;\n this.canvasEl.height = height * dpr;\n this.canvasEl.style.width = `${metrics.width}px`;\n this.canvasEl.style.height = `${height}px`;\n\n // Scale for HiDPI\n this.canvasCtx.scale(dpr, dpr);\n\n // Render table\n this.renderTableDirect(metrics, height);\n }\n\n /**\n * Renders the visible portion of the table directly onto the canvas\n */\n private renderTableDirect(\n metrics: ReturnType<typeof this.getCanvasMetrics>,\n height: number\n ): void {\n if (!this.canvasCtx) return;\n\n const ctx = this.canvasCtx;\n const { width, numCols, cellWidth, startCol, endCol, xOffset } = metrics;\n const rows = Array.from(this.table.querySelectorAll('tr'));\n const numRows = rows.length;\n\n if (numRows === 0 || numCols === 0) return;\n\n // Calculate dimensions\n const headerHeight = Math.min(height * 0.15, 30);\n const cellHeight = (height - headerHeight) / numRows;\n const fontSize = Math.min(cellHeight * 0.6, cellWidth * 0.15, 14);\n const headerFontSize = Math.min(headerHeight * 0.6, cellWidth * 0.15, 14);\n\n // Colors\n const colors = {\n bg: '#ffffff',\n headerBg: '#f1f5f9',\n border: '#e2e8f0',\n text: '#334155',\n headerText: '#1e293b',\n altRow: '#f8fafc',\n hoverFill: 'rgba(59, 130, 246, 0.08)',\n hoverStroke: 'rgba(59, 130, 246, 0.3)',\n };\n\n // Clear background\n ctx.fillStyle = colors.bg;\n ctx.fillRect(0, 0, width, height);\n\n // Draw header\n ctx.fillStyle = colors.headerBg;\n ctx.fillRect(0, 0, width, headerHeight);\n\n const headerRow = this.table.querySelector('thead tr') || rows[0];\n const headerCells = headerRow ? Array.from(headerRow.querySelectorAll('th, td')) : [];\n\n ctx.font = `bold ${headerFontSize}px system-ui, sans-serif`;\n ctx.textBaseline = 'middle';\n\n for (let col = startCol; col < endCol; col++) {\n const x = xOffset + (col - startCol) * cellWidth;\n if (x + cellWidth < 0 || x > width) continue;\n\n ctx.strokeStyle = colors.border;\n ctx.lineWidth = 1;\n ctx.strokeRect(x, 0, cellWidth, headerHeight);\n\n const text = headerCells[col]?.textContent?.trim() || `Col ${col + 1}`;\n ctx.fillStyle = colors.headerText;\n ctx.save();\n ctx.beginPath();\n ctx.rect(x + 2, 0, cellWidth - 4, headerHeight);\n ctx.clip();\n ctx.fillText(text, x + 4, headerHeight / 2);\n ctx.restore();\n }\n\n // Draw data rows\n ctx.font = `${fontSize}px system-ui, sans-serif`;\n\n for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n const row = rows[rowIndex];\n if (row.closest('thead')) continue;\n\n const y = headerHeight + rowIndex * cellHeight;\n if (y + cellHeight < 0 || y > height) continue;\n\n // Alternate row background\n if (rowIndex % 2 === 1) {\n ctx.fillStyle = colors.altRow;\n ctx.fillRect(0, y, width, cellHeight);\n }\n\n const cells = Array.from(row.querySelectorAll('th, td'));\n\n for (let col = startCol; col < endCol; col++) {\n const x = xOffset + (col - startCol) * cellWidth;\n if (x + cellWidth < 0 || x > width) continue;\n\n ctx.strokeStyle = colors.border;\n ctx.lineWidth = 0.5;\n ctx.strokeRect(x, y, cellWidth, cellHeight);\n\n const content = cells[col]?.textContent?.trim();\n if (content) {\n ctx.fillStyle = colors.text;\n ctx.save();\n ctx.beginPath();\n ctx.rect(x + 2, y, cellWidth - 4, cellHeight);\n ctx.clip();\n ctx.fillText(content, x + 4, y + cellHeight / 2);\n ctx.restore();\n }\n }\n }\n\n // Draw hover highlight\n if (this.hoveredColumn >= startCol && this.hoveredColumn < endCol) {\n const hoverX = xOffset + (this.hoveredColumn - startCol) * cellWidth;\n ctx.fillStyle = colors.hoverFill;\n ctx.fillRect(hoverX, 0, cellWidth, height);\n ctx.strokeStyle = colors.hoverStroke;\n ctx.lineWidth = 1;\n ctx.strokeRect(hoverX, 0, cellWidth, height);\n }\n }\n\n\n\n\n /**\n * Attaches event listeners\n */\n private attachEventListeners(): void {\n if (!this.scrollContainer || !this.minimapEl) return;\n\n // Scroll event on container\n this.scrollContainer.addEventListener('scroll', this.boundHandlers.onScroll, {\n passive: true,\n });\n\n // Click on minimap to jump\n this.minimapEl.addEventListener('click', this.boundHandlers.onMinimapClick);\n\n if (this.isCompactMode) {\n this.minimapEl.addEventListener('focusin', this.boundHandlers.onCompactFocusIn);\n this.minimapEl.addEventListener('focusout', this.boundHandlers.onCompactFocusOut);\n this.minimapEl.addEventListener('keydown', this.boundHandlers.onCompactKeyDown);\n document.addEventListener('click', this.boundHandlers.onDocumentClick);\n }\n\n // Drag events on viewport\n if (this.options.draggable && this.viewportEl) {\n this.viewportEl.addEventListener('pointerdown', this.boundHandlers.onPointerDown);\n }\n\n // Zoom events on canvas (wheel) - also listen on viewport so zoom works when hovering over it\n if (this.options.zoomable && this.options.mode === 'canvas' && this.canvasEl) {\n this.canvasEl.addEventListener('wheel', this.boundHandlers.onWheel, { passive: false });\n this.canvasEl.addEventListener('pointerdown', this.boundHandlers.onCanvasPointerDown);\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'pointer';\n\n // Also listen on viewport for wheel events\n if (this.viewportEl) {\n this.viewportEl.addEventListener('wheel', this.boundHandlers.onWheel, { passive: false });\n }\n }\n\n // Hover events on canvas for column highlighting\n if (this.options.mode === 'canvas' && this.canvasEl) {\n this.canvasEl.addEventListener('mousemove', this.boundHandlers.onCanvasMouseMove);\n this.canvasEl.addEventListener('mouseleave', this.boundHandlers.onCanvasMouseLeave);\n }\n\n // Global pointer events for dragging\n document.addEventListener('pointermove', this.boundHandlers.onPointerMove);\n document.addEventListener('pointerup', this.boundHandlers.onPointerUp);\n }\n\n /**\n * Handles scroll events on the container\n */\n private onScroll(): void {\n if (this.isDragging) return;\n\n // Throttle with requestAnimationFrame\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.updateScrollState();\n this.updateViewport();\n\n // Re-render canvas\n if (this.options.mode === 'canvas') {\n this.render();\n }\n\n this.rafId = null;\n });\n }\n\n /**\n * Handles click on the minimap to jump to position\n *\n * @param e - Mouse event\n */\n private onMinimapClick(e: MouseEvent): void {\n if (!this.minimapEl || !this.scrollContainer) return;\n\n if (this.isCompactMode && this.isCompactCollapsed) {\n e.preventDefault();\n this.expandCompact();\n return;\n }\n\n // Ignore clicks during expansion transition, dragging, panning\n if (this.isCompactExpanding || this.isDragging || this.isPanning || this.wasPanning) return;\n\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = scrollWidth - clientWidth;\n\n // Get click position relative to minimap\n const rect = this.minimapEl.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n\n // Canvas mode: scroll to center the clicked column\n if (this.options.mode === 'canvas') {\n const clickedColumn = this.getColumnAtX(clickX);\n\n if (clickedColumn >= 0) {\n const numCols = this.columns.length;\n const colWidth = scrollWidth / numCols;\n const colCenter = (clickedColumn + 0.5) * colWidth;\n const targetScroll = colCenter - clientWidth / 2;\n\n this.scrollContainer.scrollTo({\n left: Math.max(0, Math.min(maxScroll, targetScroll)),\n behavior: 'smooth',\n });\n }\n return;\n }\n\n // Columns mode: scroll to clicked position (percentage-based)\n const clickRatio = clickX / rect.width;\n const targetScroll = clickRatio * maxScroll;\n \n this.scrollContainer.scrollTo({\n left: Math.max(0, Math.min(maxScroll, targetScroll)),\n behavior: 'smooth',\n });\n }\n\n /**\n * Handles pointer down on viewport for drag start\n *\n * @param e - Pointer event\n */\n private onPointerDown(e: PointerEvent): void {\n if (!this.viewportEl || !this.scrollContainer) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n this.isDragging = true;\n this.dragStartX = e.clientX;\n this.dragStartScrollLeft = this.scrollContainer.scrollLeft;\n\n this.viewportEl.classList.add('tm-viewport--dragging');\n this.viewportEl.setPointerCapture(e.pointerId);\n }\n\n /**\n * Handles pointer move during drag\n *\n * @param e - Pointer event\n */\n private onPointerMove(e: PointerEvent): void {\n // Check if we should start panning (threshold check for potential pan)\n if (this.isPotentialPan && !this.isPanning && this.canvasEl && this.zoomState.level > 1) {\n const deltaX = Math.abs(e.clientX - this.panStartX);\n const PAN_THRESHOLD = 3; // pixels before we consider it a drag vs click\n\n if (deltaX > PAN_THRESHOLD) {\n this.isPanning = true;\n this.canvasEl.style.cursor = 'grabbing';\n }\n }\n\n // Handle canvas dragging (scrolls the table)\n if (this.isPanning && this.canvasEl && this.minimapEl && this.scrollContainer) {\n e.preventDefault();\n\n const deltaX = e.clientX - this.panStartX;\n const minimapWidth = this.minimapEl.offsetWidth;\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = scrollWidth - clientWidth;\n\n // Convert minimap movement to scroll movement\n // When zoomed, movement on minimap represents more scroll distance\n const scrollDelta = (deltaX / minimapWidth) * maxScroll * this.zoomState.level;\n const newScrollLeft = this.dragStartScrollLeft + scrollDelta;\n\n // Apply scroll\n this.scrollContainer.scrollLeft = Math.max(0, Math.min(maxScroll, newScrollLeft));\n\n // Update state and re-render\n this.updateScrollState();\n this.updateViewport();\n this.render();\n return;\n }\n\n\n // Handle viewport dragging\n if (!this.isDragging || !this.minimapEl || !this.scrollContainer) return;\n\n e.preventDefault();\n\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const minimapWidth = this.minimapEl.offsetWidth;\n const maxScroll = scrollWidth - clientWidth;\n\n // Scroll based on drag delta\n const deltaX = e.clientX - this.dragStartX;\n const scrollDelta = (deltaX / minimapWidth) * maxScroll;\n const newScrollLeft = this.dragStartScrollLeft + scrollDelta;\n\n this.scrollContainer.scrollLeft = Math.max(0, Math.min(maxScroll, newScrollLeft));\n this.updateScrollState();\n this.updateViewport();\n }\n\n /**\n * Handles pointer up to end drag\n *\n * @param e - Pointer event\n */\n private onPointerUp(e: PointerEvent): void {\n // Handle potential pan that was actually a click\n if (this.isPotentialPan && !this.isPanning && this.canvasEl && this.minimapEl) {\n this.isPotentialPan = false;\n\n if (this.canvasEl.hasPointerCapture(e.pointerId)) {\n this.canvasEl.releasePointerCapture(e.pointerId);\n }\n\n // Simulate a click on the minimap at this position\n const clickEvent = new MouseEvent('click', {\n clientX: e.clientX,\n clientY: e.clientY,\n bubbles: true,\n });\n this.minimapEl.dispatchEvent(clickEvent);\n return;\n }\n\n this.isPotentialPan = false;\n\n // End canvas panning\n if (this.isPanning && this.canvasEl) {\n this.isPanning = false;\n this.wasPanning = true;\n\n if (this.canvasEl.hasPointerCapture(e.pointerId)) {\n this.canvasEl.releasePointerCapture(e.pointerId);\n }\n\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'pointer';\n\n // Reset wasPanning after a short delay to allow click event to be ignored\n setTimeout(() => {\n this.wasPanning = false;\n }, 100);\n }\n\n // End viewport dragging\n if (this.isDragging) {\n this.isDragging = false;\n\n if (this.viewportEl) {\n this.viewportEl.classList.remove('tm-viewport--dragging');\n this.viewportEl.releasePointerCapture(e.pointerId);\n }\n }\n }\n\n /**\n * Handles wheel events for zoom\n *\n * @param e - Wheel event\n */\n private onWheel(e: WheelEvent): void {\n if (!this.options.zoomable || this.options.mode !== 'canvas') return;\n if (!this.canvasEl || !this.scrollContainer || !this.minimapEl) return;\n\n e.preventDefault();\n\n const oldZoom = this.zoomState.level;\n const delta = -e.deltaY * this.options.zoomSpeed;\n const newZoom = Math.max(\n this.options.minZoom,\n Math.min(this.options.maxZoom, oldZoom + delta)\n );\n\n if (newZoom === oldZoom) return;\n\n // Get mouse position relative to canvas\n const rect = this.canvasEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const width = this.minimapEl.offsetWidth;\n const relativeX = mouseX / width; // 0-1 position in canvas\n\n // Calculate the table position (0-1) under the mouse BEFORE zoom\n const oldVisibleRatio = 1 / oldZoom;\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n const oldScrollRatio = scrollLeft / maxScroll;\n const oldPanX = oldZoom > 1 ? oldScrollRatio * (1 - oldVisibleRatio) : 0;\n const tableX = oldPanX + relativeX * oldVisibleRatio; // Position in table (0-1)\n\n // Update zoom level\n this.zoomState = {\n level: newZoom,\n panX: 0,\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\n // Calculate new scroll position to keep tableX under the mouse\n const newVisibleRatio = 1 / newZoom;\n\n if (newZoom > 1) {\n // newPanX + relativeX * newVisibleRatio = tableX\n // newPanX = tableX - relativeX * newVisibleRatio\n // newScrollRatio * (1 - newVisibleRatio) = newPanX\n // newScrollRatio = newPanX / (1 - newVisibleRatio)\n const newPanX = tableX - relativeX * newVisibleRatio;\n const newScrollRatio = newPanX / (1 - newVisibleRatio);\n const newScrollLeft = Math.max(0, Math.min(maxScroll, newScrollRatio * maxScroll));\n\n this.scrollContainer.scrollLeft = newScrollLeft;\n }\n\n this.updateScrollState();\n this.render();\n }\n\n /** Whether we started a potential pan (waiting to see if it's a click or drag) */\n private isPotentialPan = false;\n\n /**\n * Handles pointer down on canvas for drag start (scrolls table when zoomed)\n *\n * @param e - Pointer event\n */\n private onCanvasPointerDown(e: PointerEvent): void {\n if (!this.canvasEl || !this.scrollContainer) return;\n\n // At any zoom level, track potential pan/click\n this.isPotentialPan = true;\n this.panStartX = e.clientX;\n this.dragStartScrollLeft = this.scrollContainer.scrollLeft;\n\n // Only capture for panning at zoom > 1\n if (this.zoomState.level > 1) {\n e.preventDefault();\n this.canvasEl.setPointerCapture(e.pointerId);\n }\n }\n\n /**\n * Handles mouse move on canvas for column hover highlighting\n */\n private onCanvasMouseMove(e: MouseEvent): void {\n if (!this.canvasEl || this.isPanning) return;\n\n const rect = this.canvasEl.getBoundingClientRect();\n const newHoveredColumn = this.getColumnAtX(e.clientX - rect.left);\n\n if (newHoveredColumn !== this.hoveredColumn) {\n this.hoveredColumn = newHoveredColumn;\n this.canvasEl.style.cursor = newHoveredColumn >= 0 ? 'pointer' : (this.zoomState.level > 1 ? 'grab' : 'default');\n this.render();\n }\n }\n\n /**\n * Handles mouse leave on canvas to clear hover state\n */\n private onCanvasMouseLeave(): void {\n if (this.hoveredColumn !== -1) {\n this.hoveredColumn = -1;\n if (this.canvasEl) {\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'default';\n }\n this.render();\n }\n }\n\n /**\n * Expands the compact minimap and clears any pending collapse.\n */\n private expandCompact(): void {\n if (!this.isCompactMode || !this.minimapEl || this.isCompactExpanding) return;\n\n this.clearCompactCollapseTimer();\n this.isCompactExpanding = true;\n this.applyCompactDimensions(false);\n \n // Wait for CSS transition to complete before rendering\n // This ensures correct dimensions are used for viewport calculation\n setTimeout(() => {\n this.isCompactExpanding = false;\n if (!this.isDestroyed && !this.isCompactCollapsed) {\n this.updateScrollState();\n this.render();\n }\n }, 200); // Slightly longer than transition duration (180ms)\n }\n\n /**\n * Collapses the compact minimap to the small dot handle.\n */\n private collapseCompact(): void {\n if (!this.isCompactMode || !this.minimapEl) return;\n\n this.applyCompactDimensions(true);\n }\n\n /**\n * Applies compact sizing/state to the minimap.\n */\n private applyCompactDimensions(collapsed: boolean): void {\n if (!this.minimapEl || !this.isCompactMode) return;\n\n this.isCompactCollapsed = collapsed;\n\n if (collapsed) {\n this.minimapEl.classList.add('tm-minimap--compact-collapsed');\n this.minimapEl.classList.remove('tm-minimap--compact-expanded');\n this.minimapEl.style.setProperty('--tm-minimap-width', `${COMPACT_HANDLE_SIZE}px`);\n this.minimapEl.style.setProperty('--tm-minimap-height', `${COMPACT_HANDLE_SIZE}px`);\n this.minimapEl.setAttribute('aria-expanded', 'false');\n return;\n }\n\n this.minimapEl.classList.remove('tm-minimap--compact-collapsed');\n this.minimapEl.classList.add('tm-minimap--compact-expanded');\n this.minimapEl.style.setProperty('--tm-minimap-width', `${this.options.fixedWidth}px`);\n this.minimapEl.style.setProperty('--tm-minimap-height', `${this.options.height}px`);\n this.minimapEl.setAttribute('aria-expanded', 'true');\n }\n\n /**\n * Clears a pending compact collapse timer.\n */\n private clearCompactCollapseTimer(): void {\n if (this.compactCollapseTimer === null) return;\n\n clearTimeout(this.compactCollapseTimer);\n this.compactCollapseTimer = null;\n }\n\n /**\n * Schedules the compact minimap to collapse.\n */\n private scheduleCompactCollapse(delay = COMPACT_COLLAPSE_DELAY): void {\n if (!this.isCompactMode) return;\n\n this.clearCompactCollapseTimer();\n this.compactCollapseTimer = window.setTimeout(() => {\n this.collapseCompact();\n this.compactCollapseTimer = null;\n }, delay);\n }\n\n /**\n * Handles document click for closing compact mode when clicking outside.\n */\n private onDocumentClick(e: MouseEvent): void {\n if (!this.isCompactMode || !this.minimapEl || this.isCompactCollapsed) return;\n\n // Check if click is outside the minimap\n if (!this.minimapEl.contains(e.target as Node)) {\n this.collapseCompact();\n }\n }\n\n /**\n * Handles focus entering compact mode.\n */\n private onCompactFocusIn(): void {\n if (!this.isCompactMode) return;\n\n this.expandCompact();\n }\n\n /**\n * Handles focus leaving compact mode.\n */\n private onCompactFocusOut(): void {\n if (!this.isCompactMode) return;\n\n this.scheduleCompactCollapse(0);\n }\n\n /**\n * Keyboard interactions for compact mode.\n */\n private onCompactKeyDown(e: KeyboardEvent): void {\n if (!this.isCompactMode) return;\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.collapseCompact();\n return;\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (this.isCompactCollapsed) {\n this.expandCompact();\n } else {\n this.collapseCompact();\n }\n }\n }\n\n /**\n * Sets up ResizeObserver and MutationObserver\n */\n private setupObservers(): void {\n // ResizeObserver for responsive updates\n this.resizeObserver = new ResizeObserver(() => {\n this.onResize();\n });\n\n if (this.scrollContainer) {\n this.resizeObserver.observe(this.scrollContainer);\n }\n this.resizeObserver.observe(this.table);\n\n // MutationObserver for table structure changes\n this.mutationObserver = new MutationObserver((mutations) => {\n const hasStructuralChanges = mutations.some(\n (m) => m.type === 'childList' || m.attributeName === 'colspan'\n );\n\n if (hasStructuralChanges) {\n this.onTableMutation();\n }\n });\n\n this.mutationObserver.observe(this.table, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['colspan'],\n });\n }\n\n /**\n * Handles resize events\n */\n private onResize(): void {\n if (this.isDestroyed) return;\n\n // Debounce resize handling\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n this.rafId = requestAnimationFrame(() => {\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n // Rebuild columns if in columns mode\n if (this.options.mode === 'columns' && this.columnsEl && this.minimapEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n\n this.rafId = null;\n });\n }\n\n /**\n * Handles table mutation events\n */\n private onTableMutation(): void {\n if (this.isDestroyed) return;\n\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n // Rebuild columns if in columns mode\n if (this.options.mode === 'columns' && this.columnsEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n }\n\n /**\n * Gets the current scroll state\n *\n * @returns Current scroll state\n */\n public getScrollState(): ScrollState {\n return { ...this.scrollState };\n }\n\n /**\n * Gets the detected columns\n *\n * @returns Array of column information\n */\n public getColumns(): ColumnInfo[] {\n return [...this.columns];\n }\n\n /**\n * Scrolls to a specific column\n *\n * @param columnIndex - Zero-based column index\n * @param smooth - Use smooth scrolling\n */\n public scrollToColumn(columnIndex: number, smooth = true): void {\n if (!this.scrollContainer || columnIndex < 0 || columnIndex >= this.columns.length) {\n return;\n }\n\n const cellsBefore = this.columns.slice(0, columnIndex);\n const offsetLeft = cellsBefore.reduce((sum, col) => sum + col.width, 0);\n\n this.scrollContainer.scrollTo({\n left: offsetLeft,\n behavior: smooth ? 'smooth' : 'auto',\n });\n }\n\n /**\n * Forces a refresh of the minimap\n */\n public refresh(): void {\n if (this.isDestroyed) return;\n\n this.scrollContainer = this.findScrollContainer();\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n if (this.options.mode === 'columns' && this.columnsEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n }\n\n /**\n * Gets the current zoom state (canvas mode only)\n *\n * @returns Current zoom state\n */\n public getZoomState(): ZoomState {\n return { ...this.zoomState };\n }\n\n /**\n * Sets the zoom level programmatically (canvas mode only)\n *\n * @param level - Zoom level (1 = no zoom)\n * @param panX - Optional pan position (0-1), controls which part of table is visible\n */\n public setZoom(level: number, panX?: number): void {\n if (this.isDestroyed || this.options.mode !== 'canvas' || !this.scrollContainer) return;\n\n const newZoom = Math.max(\n this.options.minZoom,\n Math.min(this.options.maxZoom, level)\n );\n\n const visibleRange = 1 / newZoom;\n const maxPanX = 1 - visibleRange;\n\n let newPanX = panX !== undefined ? panX : 0;\n newPanX = Math.max(0, Math.min(maxPanX, newPanX));\n\n this.zoomState = {\n level: newZoom,\n panX: 0, // Not used - panX is derived from scroll position\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\n // Set scroll position to match the desired panX\n if (newZoom > 1 && newPanX > 0) {\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n // panX = scrollRatio * (1 - visibleRatio)\n // scrollRatio = panX / (1 - visibleRatio)\n const scrollRatio = newPanX / (1 - visibleRange);\n this.scrollContainer.scrollLeft = Math.max(0, Math.min(maxScroll, scrollRatio * maxScroll));\n } else if (newZoom <= 1) {\n this.scrollContainer.scrollLeft = 0;\n }\n\n this.updateScrollState();\n this.render();\n }\n\n /**\n * Resets zoom to default (shows full table overview)\n */\n public resetZoom(): void {\n this.setZoom(1, 0);\n }\n\n /**\n * Zooms to a specific column range (canvas mode only)\n *\n * @param startCol - Start column index\n * @param endCol - End column index\n */\n public zoomToColumns(startCol: number, endCol: number): void {\n if (this.isDestroyed || this.options.mode !== 'canvas') return;\n\n const numCols = this.columns.length;\n if (numCols === 0) return;\n\n // Clamp column indices\n const start = Math.max(0, Math.min(numCols - 1, startCol));\n const end = Math.max(start + 1, Math.min(numCols, endCol));\n\n const colRange = end - start;\n const zoom = numCols / colRange;\n const panX = start / numCols;\n\n this.setZoom(zoom, panX);\n }\n\n /**\n * Destroys the minimap instance and cleans up resources\n */\n public destroy(): void {\n if (this.isDestroyed) return;\n this.isDestroyed = true;\n\n this.clearCompactCollapseTimer();\n\n // Cancel any pending animation frame\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Remove event listeners\n if (this.scrollContainer) {\n this.scrollContainer.removeEventListener('scroll', this.boundHandlers.onScroll);\n }\n\n if (this.minimapEl) {\n this.minimapEl.removeEventListener('click', this.boundHandlers.onMinimapClick);\n this.minimapEl.removeEventListener('focusin', this.boundHandlers.onCompactFocusIn);\n this.minimapEl.removeEventListener('focusout', this.boundHandlers.onCompactFocusOut);\n this.minimapEl.removeEventListener('keydown', this.boundHandlers.onCompactKeyDown);\n }\n\n document.removeEventListener('click', this.boundHandlers.onDocumentClick);\n\n if (this.viewportEl) {\n this.viewportEl.removeEventListener('pointerdown', this.boundHandlers.onPointerDown);\n this.viewportEl.removeEventListener('wheel', this.boundHandlers.onWheel);\n }\n\n if (this.canvasEl) {\n this.canvasEl.removeEventListener('wheel', this.boundHandlers.onWheel);\n this.canvasEl.removeEventListener('pointerdown', this.boundHandlers.onCanvasPointerDown);\n this.canvasEl.removeEventListener('mousemove', this.boundHandlers.onCanvasMouseMove);\n this.canvasEl.removeEventListener('mouseleave', this.boundHandlers.onCanvasMouseLeave);\n }\n\n document.removeEventListener('pointermove', this.boundHandlers.onPointerMove);\n document.removeEventListener('pointerup', this.boundHandlers.onPointerUp);\n\n // Disconnect observers\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n // Remove DOM elements\n if (this.minimapEl && this.minimapEl.parentNode) {\n this.minimapEl.parentNode.removeChild(this.minimapEl);\n }\n\n // Clear references\n this.minimapEl = null;\n this.columnsEl = null;\n this.canvasEl = null;\n this.canvasCtx = null;\n this.viewportEl = null;\n this.scrollContainer = null;\n this.columns = [];\n }\n}\n","/**\n * Table Minimap - A framework-agnostic minimap component for large HTML tables\n *\n * @packageDocumentation\n */\n\nexport { TableMinimap } from './TableMinimap';\nexport type {\n TableMinimapOptions,\n ColumnInfo,\n ScrollState,\n CellData,\n TableSelector,\n ZoomState,\n} from './types';\n\n// Auto-inject styles into DOM\nimport styles from './styles.css?inline';\n\nlet stylesInjected = false;\n\nexport function injectStyles(): void {\n if (stylesInjected || typeof document === 'undefined') return;\n\n const style = document.createElement('style');\n style.id = 'table-minimap-styles';\n style.textContent = styles;\n document.head.appendChild(style);\n stylesInjected = true;\n}\n\n// Auto-inject on import (can be tree-shaken if not used)\ninjectStyles();\n\n"],"names":["DEFAULT_OPTIONS","COMPACT_HANDLE_SIZE","COMPACT_DOT_SIZE","COMPACT_COLLAPSE_DELAY","TableMinimap","selector","options","__publicField","element","parent","style","overflowX","overflowY","theadCells","cells","firstRow","tableWidth","cell","colspan","cellWidth","i","width","colEl","nextSibling","offset","pos","scrollLeft","scrollWidth","clientWidth","_a","zoom","numCols","visibleRatio","visibleCols","panX","maxScroll","startColFloat","startCol","endCol","xOffset","mouseX","relativeX","tableX","colIndex","minimapWidth","viewportWidth","viewportLeft","metrics","height","dpr","ctx","rows","numRows","headerHeight","cellHeight","fontSize","headerFontSize","colors","headerRow","headerCells","col","x","text","_b","rowIndex","row","y","content","_d","_c","hoverX","e","rect","clickX","clickedColumn","colWidth","targetScroll","deltaX","scrollDelta","newScrollLeft","clickEvent","oldZoom","delta","newZoom","oldVisibleRatio","oldScrollRatio","newVisibleRatio","newScrollRatio","newHoveredColumn","collapsed","delay","mutations","m","columnIndex","smooth","offsetLeft","sum","level","visibleRange","maxPanX","newPanX","scrollRatio","start","colRange","stylesInjected","injectStyles","styles"],"mappings":"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"}
1
+ {"version":3,"file":"table-minimap.cjs","sources":["../src/TableMinimap.ts","../src/index.ts"],"sourcesContent":["import type {\n TableMinimapOptions,\n RequiredOptions,\n ColumnInfo,\n ScrollState,\n TableSelector,\n ZoomState,\n} from './types';\n\n/**\n * Default configuration options\n */\nconst DEFAULT_OPTIONS: RequiredOptions = {\n mode: 'columns',\n height: 40,\n position: 'bottom',\n fixedWidth: 300,\n fixedPosition: 'bottom-right',\n compact: false,\n draggable: true,\n showViewport: true,\n zoomable: false,\n minZoom: 1,\n maxZoom: 10,\n zoomSpeed: 0.1,\n};\n\n/** Compact floating minimap handle size in pixels */\nconst COMPACT_HANDLE_SIZE = 24;\n\n/** Visible dot size inside the compact handle in pixels */\nconst COMPACT_DOT_SIZE = 5;\n\n/** Delay before compact mode collapses after pointer leave */\nconst COMPACT_COLLAPSE_DELAY = 180;\n\n/** Delay used to distinguish single click navigation from double-click repositioning */\nconst DOUBLE_CLICK_DELAY = 180;\n\n/** Fixed corner positions used when cycling the minimap by double-click */\nconst FIXED_POSITIONS: RequiredOptions['fixedPosition'][] = [\n 'bottom-right',\n 'bottom-left',\n 'top-left',\n 'top-right',\n];\n\n/** Pixels before a canvas pointer interaction is treated as panning instead of click */\nconst CANVAS_PAN_THRESHOLD = 3;\n\n/** Multiplier for canvas drag-to-scroll movement; lower values feel smoother */\nconst CANVAS_PAN_SENSITIVITY = 0.85;\n\n/**\n * TableMinimap - A framework-agnostic minimap component for large HTML tables\n *\n * @example\n * ```ts\n * import { TableMinimap } from 'table-minimap';\n * import 'table-minimap/style.css';\n *\n * const minimap = new TableMinimap('#my-table');\n *\n * // Or with options\n * const minimap = new TableMinimap('#my-table', {\n * mode: 'canvas',\n * height: 50,\n * position: 'top'\n * });\n *\n * // Cleanup\n * minimap.destroy();\n * ```\n */\nexport class TableMinimap {\n /** The target table element */\n private readonly table: HTMLTableElement;\n\n /** Configuration options */\n private readonly options: RequiredOptions;\n\n /** Whether compact fixed-overlay behavior is enabled */\n private readonly isCompactMode: boolean;\n\n /** Whether the compact minimap is currently collapsed */\n private isCompactCollapsed = false;\n\n /** Whether the compact minimap is currently expanding (transition in progress) */\n private isCompactExpanding = false;\n\n /** Timeout used to collapse compact mode after pointer leave */\n private compactCollapseTimer: number | null = null;\n\n /** Timeout used to delay fixed minimap click navigation until double-click is ruled out */\n private minimapClickTimer: number | null = null;\n\n /** The scrollable container (parent of table) */\n private scrollContainer: HTMLElement | null = null;\n\n /** Main minimap container element */\n private minimapEl: HTMLDivElement | null = null;\n\n /** Columns container for columns mode */\n private columnsEl: HTMLDivElement | null = null;\n\n /** Canvas element for canvas mode */\n private canvasEl: HTMLCanvasElement | null = null;\n\n /** Canvas 2D rendering context */\n private canvasCtx: CanvasRenderingContext2D | null = null;\n\n\n /** Viewport indicator element */\n private viewportEl: HTMLDivElement | null = null;\n\n /** Detected column information */\n private columns: ColumnInfo[] = [];\n\n /** Current scroll state */\n private scrollState: ScrollState = {\n scrollLeft: 0,\n scrollWidth: 0,\n clientWidth: 0,\n viewportRatio: 1,\n positionRatio: 0,\n };\n\n /** Current zoom state */\n private zoomState: ZoomState = {\n level: 1,\n panX: 0,\n isMinZoom: true,\n isMaxZoom: false,\n };\n\n /** Is the viewport being dragged */\n private isDragging = false;\n\n /** Is the canvas being panned (when zoomed) */\n private isPanning = false;\n\n /** Was just panning (to prevent click after pan) */\n private wasPanning = false;\n\n /** Pan start position */\n private panStartX = 0;\n\n /** Last pointer X waiting to be applied during canvas panning */\n private pendingPanClientX: number | null = null;\n\n /** Currently hovered column index (-1 = none) */\n private hoveredColumn = -1;\n\n /** Drag start X position */\n private dragStartX = 0;\n\n /** Drag start scroll position */\n private dragStartScrollLeft = 0;\n\n /** ResizeObserver instance */\n private resizeObserver: ResizeObserver | null = null;\n\n /** MutationObserver instance */\n private mutationObserver: MutationObserver | null = null;\n\n /** Bound event handlers for cleanup */\n private boundHandlers: {\n onScroll: () => void;\n onPointerDown: (e: PointerEvent) => void;\n onPointerMove: (e: PointerEvent) => void;\n onPointerUp: (e: PointerEvent) => void;\n onMinimapClick: (e: MouseEvent) => void;\n onMinimapDoubleClick: (e: MouseEvent) => void;\n onWheel: (e: WheelEvent) => void;\n onCanvasPointerDown: (e: PointerEvent) => void;\n onCanvasMouseMove: (e: MouseEvent) => void;\n onCanvasMouseLeave: () => void;\n onCompactFocusIn: () => void;\n onCompactFocusOut: () => void;\n onCompactKeyDown: (e: KeyboardEvent) => void;\n onDocumentClick: (e: MouseEvent) => void;\n };\n\n /** Animation frame ID for throttling */\n private rafId: number | null = null;\n\n /** Animation frame ID for throttling canvas panning */\n private canvasPanRafId: number | null = null;\n\n /** Whether the instance has been destroyed */\n private isDestroyed = false;\n\n /**\n * Creates a new TableMinimap instance\n *\n * @param selector - CSS selector string or HTMLTableElement\n * @param options - Configuration options\n * @throws Error if table element is not found or invalid\n */\n constructor(selector: TableSelector, options: TableMinimapOptions = {}) {\n this.table = this.resolveTable(selector);\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.isCompactMode = this.options.compact && this.options.position === 'fixed';\n\n // Bind event handlers\n this.boundHandlers = {\n onScroll: this.onScroll.bind(this),\n onPointerDown: this.onPointerDown.bind(this),\n onPointerMove: this.onPointerMove.bind(this),\n onPointerUp: this.onPointerUp.bind(this),\n onMinimapClick: this.onMinimapClick.bind(this),\n onMinimapDoubleClick: this.onMinimapDoubleClick.bind(this),\n onWheel: this.onWheel.bind(this),\n onCanvasPointerDown: this.onCanvasPointerDown.bind(this),\n onCanvasMouseMove: this.onCanvasMouseMove.bind(this),\n onCanvasMouseLeave: this.onCanvasMouseLeave.bind(this),\n onCompactFocusIn: this.onCompactFocusIn.bind(this),\n onCompactFocusOut: this.onCompactFocusOut.bind(this),\n onCompactKeyDown: this.onCompactKeyDown.bind(this),\n onDocumentClick: this.onDocumentClick.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Resolves the table element from a selector or element\n *\n * @param selector - CSS selector or HTMLTableElement\n * @returns The resolved table element\n * @throws Error if element is not found or not a table\n */\n private resolveTable(selector: TableSelector): HTMLTableElement {\n let element: HTMLTableElement | null;\n\n if (typeof selector === 'string') {\n element = document.querySelector<HTMLTableElement>(selector);\n if (!element) {\n throw new Error(\n `TableMinimap: No element found for selector \"${selector}\"`\n );\n }\n } else if (selector instanceof HTMLTableElement) {\n element = selector;\n } else {\n throw new Error(\n 'TableMinimap: Selector must be a CSS selector string or an HTMLTableElement'\n );\n }\n\n if (element.tagName !== 'TABLE') {\n throw new Error(\n `TableMinimap: Element must be a <table>, got <${element.tagName.toLowerCase()}>`\n );\n }\n\n return element;\n }\n\n /**\n * Initializes the minimap\n */\n private init(): void {\n this.scrollContainer = this.findScrollContainer();\n this.detectColumns();\n this.createMinimapElement();\n this.updateScrollState();\n this.render();\n this.attachEventListeners();\n this.setupObservers();\n }\n\n /**\n * Finds the nearest scrollable parent container\n *\n * @returns The scrollable container or the table's parent\n */\n private findScrollContainer(): HTMLElement {\n let parent = this.table.parentElement;\n\n while (parent) {\n const style = getComputedStyle(parent);\n const overflowX = style.overflowX;\n const overflowY = style.overflow;\n\n if (\n overflowX === 'auto' ||\n overflowX === 'scroll' ||\n overflowY === 'auto' ||\n overflowY === 'scroll'\n ) {\n return parent;\n }\n\n // Check if content overflows\n if (parent.scrollWidth > parent.clientWidth) {\n return parent;\n }\n\n parent = parent.parentElement;\n }\n\n // Fallback to table's parent or body\n return this.table.parentElement || document.body;\n }\n\n /**\n * Detects table columns from thead or first row\n */\n private detectColumns(): void {\n this.columns = [];\n\n // Try thead th first\n const theadCells = this.table.querySelectorAll<HTMLTableCellElement>(\n 'thead th, thead td'\n );\n\n let cells: NodeListOf<HTMLTableCellElement> | HTMLTableCellElement[];\n\n if (theadCells.length > 0) {\n cells = theadCells;\n } else {\n // Fallback to first row cells\n const firstRow = this.table.querySelector('tr');\n if (firstRow) {\n cells = firstRow.querySelectorAll<HTMLTableCellElement>('th, td');\n } else {\n cells = [];\n }\n }\n\n const tableWidth = this.table.offsetWidth || 1;\n\n Array.from(cells).forEach((cell) => {\n // Handle colspan\n const colspan = cell.colSpan || 1;\n const cellWidth = cell.offsetWidth;\n\n for (let i = 0; i < colspan; i++) {\n const width = cellWidth / colspan;\n this.columns.push({\n index: this.columns.length,\n width,\n widthPercent: (width / tableWidth) * 100,\n });\n }\n });\n\n // Ensure at least one column\n if (this.columns.length === 0) {\n this.columns.push({\n index: 0,\n width: tableWidth,\n widthPercent: 100,\n });\n }\n }\n\n /**\n * Creates the minimap DOM element\n */\n private createMinimapElement(): void {\n // Create main container\n this.minimapEl = document.createElement('div');\n this.minimapEl.className = `tm-minimap tm-minimap--${this.options.position}`;\n this.minimapEl.style.setProperty('--tm-minimap-height', `${this.options.height}px`);\n\n // Set width and position class for fixed position\n if (this.options.position === 'fixed') {\n this.minimapEl.style.setProperty('--tm-minimap-width', `${this.options.fixedWidth}px`);\n this.minimapEl.title = 'Double-click to move minimap to the next corner';\n }\n\n if (this.isCompactMode) {\n this.minimapEl.classList.add('tm-minimap--compact', 'tm-minimap--compact-collapsed');\n this.minimapEl.style.setProperty('--tm-compact-dot-size', `${COMPACT_DOT_SIZE}px`);\n this.isCompactCollapsed = true;\n this.applyCompactDimensions(true);\n this.minimapEl.setAttribute('aria-expanded', 'false');\n } else {\n this.minimapEl.setAttribute('aria-expanded', 'true');\n }\n \n this.minimapEl.setAttribute('role', 'slider');\n this.minimapEl.setAttribute('aria-label', 'Table minimap navigation');\n this.minimapEl.setAttribute('aria-valuemin', '0');\n this.minimapEl.setAttribute('aria-valuemax', '100');\n this.minimapEl.setAttribute('tabindex', '0');\n\n // Create content based on mode\n if (this.options.mode === 'canvas') {\n this.createCanvasContent();\n } else {\n this.createColumnsContent();\n }\n\n // Create viewport indicator\n if (this.options.showViewport) {\n this.createViewportIndicator();\n }\n\n // Insert minimap\n this.insertMinimap();\n }\n\n /**\n * Creates columns-mode content\n */\n private createColumnsContent(): void {\n if (!this.minimapEl) return;\n\n this.columnsEl = document.createElement('div');\n this.columnsEl.className = 'tm-columns';\n\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n\n this.minimapEl.appendChild(this.columnsEl);\n }\n\n /**\n * Creates canvas-mode content\n */\n private createCanvasContent(): void {\n if (!this.minimapEl) return;\n\n this.canvasEl = document.createElement('canvas');\n this.canvasEl.className = 'tm-canvas';\n this.canvasCtx = this.canvasEl.getContext('2d');\n\n this.minimapEl.appendChild(this.canvasEl);\n }\n\n /**\n * Creates the viewport indicator element\n */\n private createViewportIndicator(): void {\n if (!this.minimapEl) return;\n\n this.viewportEl = document.createElement('div');\n this.viewportEl.className = 'tm-viewport';\n\n if (!this.options.draggable) {\n this.viewportEl.classList.add('tm-viewport--disabled');\n }\n\n this.minimapEl.appendChild(this.viewportEl);\n }\n\n /**\n * Inserts the minimap into the DOM\n */\n private insertMinimap(): void {\n if (!this.minimapEl || !this.scrollContainer) return;\n\n const parent = this.scrollContainer.parentElement;\n\n if (this.options.position === 'fixed') {\n // Fixed position: create a wrapper with relative positioning\n // Insert minimap after scroll container, but style it to overlay\n if (parent) {\n // Ensure parent has relative positioning for our fixed overlay\n const parentStyle = getComputedStyle(parent);\n if (parentStyle.position === 'static') {\n parent.style.position = 'relative';\n }\n\n // Insert after scroll container\n const nextSibling = this.scrollContainer.nextSibling;\n if (nextSibling) {\n parent.insertBefore(this.minimapEl, nextSibling);\n } else {\n parent.appendChild(this.minimapEl);\n }\n\n // Apply fixed positioning styles based on fixedPosition\n this.minimapEl.style.position = 'absolute';\n this.applyFixedPosition();\n }\n } else if (this.options.position === 'top') {\n // Insert before the scroll container (outside, above it)\n if (parent) {\n parent.insertBefore(this.minimapEl, this.scrollContainer);\n } else {\n // Fallback: insert as first child of scroll container\n this.scrollContainer.insertBefore(this.minimapEl, this.scrollContainer.firstChild);\n }\n } else {\n // Insert after the scroll container (outside, below it)\n if (parent) {\n const nextSibling = this.scrollContainer.nextSibling;\n if (nextSibling) {\n parent.insertBefore(this.minimapEl, nextSibling);\n } else {\n parent.appendChild(this.minimapEl);\n }\n } else {\n this.scrollContainer.appendChild(this.minimapEl);\n }\n }\n }\n\n /**\n * Applies the configured fixed corner position to the minimap element.\n */\n private applyFixedPosition(): void {\n if (!this.minimapEl || this.options.position !== 'fixed') return;\n\n const offset = this.isCompactMode ? 8 : 12;\n const pos = this.options.fixedPosition;\n\n FIXED_POSITIONS.forEach((fixedPosition) => {\n this.minimapEl!.classList.remove(`tm-minimap--${fixedPosition}`);\n });\n this.minimapEl.classList.add(`tm-minimap--${pos}`);\n\n // Reset all positions first\n this.minimapEl.style.top = '';\n this.minimapEl.style.bottom = '';\n this.minimapEl.style.left = '';\n this.minimapEl.style.right = '';\n this.minimapEl.style.marginTop = '0';\n\n // Apply position based on fixedPosition option\n if (pos === 'top-left') {\n this.minimapEl.style.top = `${offset}px`;\n this.minimapEl.style.left = `${offset}px`;\n } else if (pos === 'top-right') {\n this.minimapEl.style.top = `${offset}px`;\n this.minimapEl.style.right = `${offset}px`;\n } else if (pos === 'bottom-left') {\n this.minimapEl.style.bottom = `${offset}px`;\n this.minimapEl.style.left = `${offset}px`;\n } else {\n // bottom-right (default)\n this.minimapEl.style.bottom = `${offset}px`;\n this.minimapEl.style.right = `${offset}px`;\n }\n }\n\n /**\n * Moves fixed minimaps to the next configured corner.\n */\n private cycleFixedPosition(): void {\n if (this.options.position !== 'fixed') return;\n\n const currentIndex = FIXED_POSITIONS.indexOf(this.options.fixedPosition);\n const nextIndex = currentIndex >= 0 ? (currentIndex + 1) % FIXED_POSITIONS.length : 0;\n this.options.fixedPosition = FIXED_POSITIONS[nextIndex];\n this.applyFixedPosition();\n }\n\n /**\n * Updates the scroll state from the container\n */\n private updateScrollState(): void {\n if (!this.scrollContainer) return;\n\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n\n this.scrollState = {\n scrollLeft,\n scrollWidth,\n clientWidth,\n viewportRatio: clientWidth / Math.max(scrollWidth, 1),\n positionRatio: scrollLeft / Math.max(scrollWidth - clientWidth, 1),\n };\n\n // Clamp values\n this.scrollState.viewportRatio = Math.min(1, Math.max(0, this.scrollState.viewportRatio));\n this.scrollState.positionRatio = Math.min(1, Math.max(0, this.scrollState.positionRatio));\n\n // Update ARIA values\n if (this.minimapEl) {\n this.minimapEl.setAttribute(\n 'aria-valuenow',\n String(Math.round(this.scrollState.positionRatio * 100))\n );\n }\n }\n\n /**\n * Renders the minimap\n */\n private render(): void {\n if (this.isDestroyed) return;\n\n if (this.isCompactMode && this.isCompactCollapsed) return;\n\n this.updateViewport();\n\n if (this.options.mode === 'canvas') {\n this.renderCanvas();\n }\n }\n\n /**\n * Canvas metrics for calculations - cached values to avoid repeated computations\n */\n private getCanvasMetrics() {\n const width = this.minimapEl?.offsetWidth ?? 0;\n const zoom = this.zoomState.level;\n const numCols = this.columns.length;\n const visibleRatio = 1 / zoom;\n const visibleCols = numCols * visibleRatio;\n const cellWidth = visibleCols > 0 ? width / visibleCols : 0;\n\n // Calculate panX based on scroll position\n let panX = 0;\n if (zoom > 1 && this.scrollContainer) {\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n const scrollRatio = scrollLeft / maxScroll;\n panX = scrollRatio * (1 - visibleRatio);\n }\n\n const startColFloat = panX * numCols;\n const startCol = Math.floor(startColFloat);\n const endCol = Math.min(Math.ceil(startColFloat + visibleCols) + 1, numCols);\n const xOffset = -(startColFloat - startCol) * cellWidth;\n\n return {\n width,\n zoom,\n numCols,\n visibleRatio,\n visibleCols,\n cellWidth,\n panX,\n startColFloat,\n startCol,\n endCol,\n xOffset,\n };\n }\n\n /**\n * Calculates column index from mouse X position\n */\n private getColumnAtX(mouseX: number): number {\n const { width, numCols, panX, visibleRatio } = this.getCanvasMetrics();\n if (numCols === 0 || width === 0) return -1;\n\n const relativeX = mouseX / width;\n const tableX = panX + relativeX * visibleRatio;\n const colIndex = Math.floor(tableX * numCols);\n\n return Math.max(0, Math.min(numCols - 1, colIndex));\n }\n\n /**\n * Updates the viewport indicator position and size\n * Shows the visible portion of the table (columns mode only)\n */\n private updateViewport(): void {\n if (!this.viewportEl || !this.minimapEl) return;\n\n // No viewport in canvas mode\n if (this.options.mode === 'canvas') {\n this.viewportEl.style.display = 'none';\n return;\n }\n\n const minimapWidth = this.minimapEl.offsetWidth;\n \n // Columns mode: viewport showing visible area\n const viewportWidth = Math.max(minimapWidth * this.scrollState.viewportRatio, 20);\n const maxLeft = minimapWidth - viewportWidth;\n const viewportLeft = maxLeft * this.scrollState.positionRatio;\n this.viewportEl.style.cssText = `width:${viewportWidth}px;left:${viewportLeft}px;display:block`;\n }\n\n /**\n * Renders the canvas-mode visualization with table preview\n */\n private renderCanvas(): void {\n if (!this.canvasEl || !this.canvasCtx || !this.minimapEl) return;\n\n const metrics = this.getCanvasMetrics();\n const height = this.options.height;\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas size with HiDPI support\n this.canvasEl.width = metrics.width * dpr;\n this.canvasEl.height = height * dpr;\n this.canvasEl.style.width = `${metrics.width}px`;\n this.canvasEl.style.height = `${height}px`;\n\n // Scale for HiDPI\n this.canvasCtx.scale(dpr, dpr);\n\n // Render table\n this.renderTableDirect(metrics, height);\n }\n\n /**\n * Renders the visible portion of the table directly onto the canvas\n */\n private renderTableDirect(\n metrics: ReturnType<typeof this.getCanvasMetrics>,\n height: number\n ): void {\n if (!this.canvasCtx) return;\n\n const ctx = this.canvasCtx;\n const { width, numCols, cellWidth, startCol, endCol, xOffset } = metrics;\n const rows = Array.from(this.table.querySelectorAll('tr'));\n const numRows = rows.length;\n\n if (numRows === 0 || numCols === 0) return;\n\n // Calculate dimensions\n const headerHeight = Math.min(height * 0.15, 30);\n const cellHeight = (height - headerHeight) / numRows;\n const fontSize = Math.min(cellHeight * 0.6, cellWidth * 0.15, 14);\n const headerFontSize = Math.min(headerHeight * 0.6, cellWidth * 0.15, 14);\n\n // Colors\n const colors = {\n bg: '#ffffff',\n headerBg: '#f1f5f9',\n border: '#e2e8f0',\n text: '#334155',\n headerText: '#1e293b',\n altRow: '#f8fafc',\n hoverFill: 'rgba(59, 130, 246, 0.08)',\n hoverStroke: 'rgba(59, 130, 246, 0.3)',\n };\n\n // Clear background\n ctx.fillStyle = colors.bg;\n ctx.fillRect(0, 0, width, height);\n\n // Draw header\n ctx.fillStyle = colors.headerBg;\n ctx.fillRect(0, 0, width, headerHeight);\n\n const headerRow = this.table.querySelector('thead tr') || rows[0];\n const headerCells = headerRow ? Array.from(headerRow.querySelectorAll('th, td')) : [];\n\n ctx.font = `bold ${headerFontSize}px system-ui, sans-serif`;\n ctx.textBaseline = 'middle';\n\n for (let col = startCol; col < endCol; col++) {\n const x = xOffset + (col - startCol) * cellWidth;\n if (x + cellWidth < 0 || x > width) continue;\n\n ctx.strokeStyle = colors.border;\n ctx.lineWidth = 1;\n ctx.strokeRect(x, 0, cellWidth, headerHeight);\n\n const text = headerCells[col]?.textContent?.trim() || `Col ${col + 1}`;\n ctx.fillStyle = colors.headerText;\n ctx.save();\n ctx.beginPath();\n ctx.rect(x + 2, 0, cellWidth - 4, headerHeight);\n ctx.clip();\n ctx.fillText(text, x + 4, headerHeight / 2);\n ctx.restore();\n }\n\n // Draw data rows\n ctx.font = `${fontSize}px system-ui, sans-serif`;\n\n for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n const row = rows[rowIndex];\n if (row.closest('thead')) continue;\n\n const y = headerHeight + rowIndex * cellHeight;\n if (y + cellHeight < 0 || y > height) continue;\n\n // Alternate row background\n if (rowIndex % 2 === 1) {\n ctx.fillStyle = colors.altRow;\n ctx.fillRect(0, y, width, cellHeight);\n }\n\n const cells = Array.from(row.querySelectorAll('th, td'));\n\n for (let col = startCol; col < endCol; col++) {\n const x = xOffset + (col - startCol) * cellWidth;\n if (x + cellWidth < 0 || x > width) continue;\n\n ctx.strokeStyle = colors.border;\n ctx.lineWidth = 0.5;\n ctx.strokeRect(x, y, cellWidth, cellHeight);\n\n const content = cells[col]?.textContent?.trim();\n if (content) {\n ctx.fillStyle = colors.text;\n ctx.save();\n ctx.beginPath();\n ctx.rect(x + 2, y, cellWidth - 4, cellHeight);\n ctx.clip();\n ctx.fillText(content, x + 4, y + cellHeight / 2);\n ctx.restore();\n }\n }\n }\n\n // Draw hover highlight\n if (this.hoveredColumn >= startCol && this.hoveredColumn < endCol) {\n const hoverX = xOffset + (this.hoveredColumn - startCol) * cellWidth;\n ctx.fillStyle = colors.hoverFill;\n ctx.fillRect(hoverX, 0, cellWidth, height);\n ctx.strokeStyle = colors.hoverStroke;\n ctx.lineWidth = 1;\n ctx.strokeRect(hoverX, 0, cellWidth, height);\n }\n }\n\n\n\n\n /**\n * Attaches event listeners\n */\n private attachEventListeners(): void {\n if (!this.scrollContainer || !this.minimapEl) return;\n\n // Scroll event on container\n this.scrollContainer.addEventListener('scroll', this.boundHandlers.onScroll, {\n passive: true,\n });\n\n // Click on minimap to jump\n this.minimapEl.addEventListener('click', this.boundHandlers.onMinimapClick);\n this.minimapEl.addEventListener('dblclick', this.boundHandlers.onMinimapDoubleClick);\n\n if (this.isCompactMode) {\n this.minimapEl.addEventListener('focusin', this.boundHandlers.onCompactFocusIn);\n this.minimapEl.addEventListener('focusout', this.boundHandlers.onCompactFocusOut);\n this.minimapEl.addEventListener('keydown', this.boundHandlers.onCompactKeyDown);\n document.addEventListener('click', this.boundHandlers.onDocumentClick);\n }\n\n // Drag events on viewport\n if (this.options.draggable && this.viewportEl) {\n this.viewportEl.addEventListener('pointerdown', this.boundHandlers.onPointerDown);\n }\n\n // Zoom events on canvas (wheel) - also listen on viewport so zoom works when hovering over it\n if (this.options.zoomable && this.options.mode === 'canvas' && this.canvasEl) {\n this.canvasEl.addEventListener('wheel', this.boundHandlers.onWheel, { passive: false });\n this.canvasEl.addEventListener('pointerdown', this.boundHandlers.onCanvasPointerDown);\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'pointer';\n\n // Also listen on viewport for wheel events\n if (this.viewportEl) {\n this.viewportEl.addEventListener('wheel', this.boundHandlers.onWheel, { passive: false });\n }\n }\n\n // Hover events on canvas for column highlighting\n if (this.options.mode === 'canvas' && this.canvasEl) {\n this.canvasEl.addEventListener('mousemove', this.boundHandlers.onCanvasMouseMove);\n this.canvasEl.addEventListener('mouseleave', this.boundHandlers.onCanvasMouseLeave);\n }\n\n // Global pointer events for dragging\n document.addEventListener('pointermove', this.boundHandlers.onPointerMove);\n document.addEventListener('pointerup', this.boundHandlers.onPointerUp);\n }\n\n /**\n * Handles scroll events on the container\n */\n private onScroll(): void {\n if (this.isDragging) return;\n\n // Throttle with requestAnimationFrame\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.updateScrollState();\n this.updateViewport();\n\n // Re-render canvas\n if (this.options.mode === 'canvas') {\n this.render();\n }\n\n this.rafId = null;\n });\n }\n\n /**\n * Handles click on the minimap to jump to position\n *\n * @param e - Mouse event\n */\n private onMinimapClick(e: MouseEvent): void {\n if (!this.minimapEl || !this.scrollContainer) return;\n\n if (this.options.position === 'fixed') {\n if (e.detail > 1) return;\n\n const clientX = e.clientX;\n this.clearMinimapClickTimer();\n this.minimapClickTimer = window.setTimeout(() => {\n this.minimapClickTimer = null;\n this.handleMinimapClick(clientX);\n }, DOUBLE_CLICK_DELAY);\n return;\n }\n\n this.handleMinimapClick(e.clientX);\n }\n\n /**\n * Handles double-click on fixed minimaps to move them to the next corner.\n *\n * @param e - Mouse event\n */\n private onMinimapDoubleClick(e: MouseEvent): void {\n if (this.options.position !== 'fixed') return;\n\n e.preventDefault();\n e.stopPropagation();\n this.clearMinimapClickTimer();\n this.cycleFixedPosition();\n }\n\n /**\n * Clears a pending delayed minimap click.\n */\n private clearMinimapClickTimer(): void {\n if (this.minimapClickTimer === null) return;\n\n clearTimeout(this.minimapClickTimer);\n this.minimapClickTimer = null;\n }\n\n /**\n * Handles single-click minimap navigation.\n *\n * @param clientX - Click position in viewport coordinates\n */\n private handleMinimapClick(clientX: number): void {\n if (!this.minimapEl || !this.scrollContainer) return;\n\n if (this.isCompactMode && this.isCompactCollapsed) {\n this.expandCompact();\n return;\n }\n\n // Ignore clicks during expansion transition, dragging, panning\n if (this.isCompactExpanding || this.isDragging || this.isPanning || this.wasPanning) return;\n\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = scrollWidth - clientWidth;\n\n // Get click position relative to minimap\n const rect = this.minimapEl.getBoundingClientRect();\n const clickX = clientX - rect.left;\n\n // Canvas mode: scroll to center the clicked column\n if (this.options.mode === 'canvas') {\n const clickedColumn = this.getColumnAtX(clickX);\n\n if (clickedColumn >= 0) {\n const numCols = this.columns.length;\n const colWidth = scrollWidth / numCols;\n const colCenter = (clickedColumn + 0.5) * colWidth;\n const targetScroll = colCenter - clientWidth / 2;\n\n this.scrollContainer.scrollTo({\n left: Math.max(0, Math.min(maxScroll, targetScroll)),\n behavior: 'smooth',\n });\n }\n return;\n }\n\n // Columns mode: scroll to clicked position (percentage-based)\n const clickRatio = clickX / rect.width;\n const targetScroll = clickRatio * maxScroll;\n \n this.scrollContainer.scrollTo({\n left: Math.max(0, Math.min(maxScroll, targetScroll)),\n behavior: 'smooth',\n });\n }\n\n /**\n * Handles pointer down on viewport for drag start\n *\n * @param e - Pointer event\n */\n private onPointerDown(e: PointerEvent): void {\n if (!this.viewportEl || !this.scrollContainer) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n this.isDragging = true;\n this.dragStartX = e.clientX;\n this.dragStartScrollLeft = this.scrollContainer.scrollLeft;\n\n this.viewportEl.classList.add('tm-viewport--dragging');\n this.viewportEl.setPointerCapture(e.pointerId);\n }\n\n /**\n * Handles pointer move during drag\n *\n * @param e - Pointer event\n */\n private onPointerMove(e: PointerEvent): void {\n // Check if we should start panning (threshold check for potential pan)\n if (this.isPotentialPan && !this.isPanning && this.canvasEl && this.zoomState.level > 1) {\n const deltaX = Math.abs(e.clientX - this.panStartX);\n\n if (deltaX > CANVAS_PAN_THRESHOLD) {\n this.isPanning = true;\n this.canvasEl.style.cursor = 'grabbing';\n }\n }\n\n // Handle canvas dragging (scrolls the table)\n if (this.isPanning && this.canvasEl && this.minimapEl && this.scrollContainer) {\n e.preventDefault();\n this.pendingPanClientX = e.clientX;\n this.scheduleCanvasPan();\n return;\n }\n\n\n // Handle viewport dragging\n if (!this.isDragging || !this.minimapEl || !this.scrollContainer) return;\n\n e.preventDefault();\n\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const minimapWidth = this.minimapEl.offsetWidth;\n const maxScroll = scrollWidth - clientWidth;\n\n // Scroll based on drag delta\n const deltaX = e.clientX - this.dragStartX;\n const scrollDelta = (deltaX / minimapWidth) * maxScroll;\n const newScrollLeft = this.dragStartScrollLeft + scrollDelta;\n\n this.scrollContainer.scrollLeft = Math.max(0, Math.min(maxScroll, newScrollLeft));\n this.updateScrollState();\n this.updateViewport();\n }\n\n /**\n * Schedules canvas panning work for the next animation frame.\n */\n private scheduleCanvasPan(): void {\n if (this.canvasPanRafId !== null) return;\n\n this.canvasPanRafId = requestAnimationFrame(() => {\n this.canvasPanRafId = null;\n this.applyCanvasPan();\n });\n }\n\n /**\n * Applies pending canvas pan movement using a dampened scroll ratio.\n */\n private applyCanvasPan(): void {\n if (\n !this.isPanning ||\n this.pendingPanClientX === null ||\n !this.minimapEl ||\n !this.scrollContainer\n ) {\n return;\n }\n\n const deltaX = this.panStartX - this.pendingPanClientX;\n const minimapWidth = Math.max(this.minimapEl.offsetWidth, 1);\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 0);\n const visibleRatio = 1 / Math.max(this.zoomState.level, 1);\n\n // In zoomed canvas mode the minimap represents only the visible slice.\n // Invert pointer delta so dragging left/right moves the table in the same perceived direction.\n // Scaling by visibleRatio makes left/right panning much less jumpy at high zoom levels.\n const scrollDelta =\n (deltaX / minimapWidth) * maxScroll * visibleRatio * CANVAS_PAN_SENSITIVITY;\n\n this.scrollContainer.scrollLeft = Math.max(\n 0,\n Math.min(maxScroll, this.dragStartScrollLeft + scrollDelta)\n );\n\n this.updateScrollState();\n this.updateViewport();\n this.render();\n }\n\n /**\n * Cancels any pending canvas pan frame.\n */\n private clearCanvasPanFrame(): void {\n if (this.canvasPanRafId === null) return;\n\n cancelAnimationFrame(this.canvasPanRafId);\n this.canvasPanRafId = null;\n }\n\n /**\n * Handles pointer up to end drag\n *\n * @param e - Pointer event\n */\n private onPointerUp(e: PointerEvent): void {\n // Handle potential pan that was actually a click\n if (this.isPotentialPan && !this.isPanning && this.canvasEl && this.minimapEl) {\n this.isPotentialPan = false;\n this.pendingPanClientX = null;\n\n if (this.canvasEl.hasPointerCapture(e.pointerId)) {\n this.canvasEl.releasePointerCapture(e.pointerId);\n }\n\n // Simulate a click on the minimap at this position\n const clickEvent = new MouseEvent('click', {\n clientX: e.clientX,\n clientY: e.clientY,\n bubbles: true,\n });\n this.minimapEl.dispatchEvent(clickEvent);\n return;\n }\n\n this.isPotentialPan = false;\n\n // End canvas panning\n if (this.isPanning && this.canvasEl) {\n this.applyCanvasPan();\n this.clearCanvasPanFrame();\n this.pendingPanClientX = null;\n this.isPanning = false;\n this.wasPanning = true;\n\n if (this.canvasEl.hasPointerCapture(e.pointerId)) {\n this.canvasEl.releasePointerCapture(e.pointerId);\n }\n\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'pointer';\n\n // Reset wasPanning after a short delay to allow click event to be ignored\n setTimeout(() => {\n this.wasPanning = false;\n }, 100);\n }\n\n // End viewport dragging\n if (this.isDragging) {\n this.isDragging = false;\n\n if (this.viewportEl) {\n this.viewportEl.classList.remove('tm-viewport--dragging');\n this.viewportEl.releasePointerCapture(e.pointerId);\n }\n }\n }\n\n /**\n * Handles wheel events for zoom\n *\n * @param e - Wheel event\n */\n private onWheel(e: WheelEvent): void {\n if (!this.options.zoomable || this.options.mode !== 'canvas') return;\n if (!this.canvasEl || !this.scrollContainer || !this.minimapEl) return;\n\n e.preventDefault();\n\n const oldZoom = this.zoomState.level;\n const delta = -e.deltaY * this.options.zoomSpeed;\n const newZoom = Math.max(\n this.options.minZoom,\n Math.min(this.options.maxZoom, oldZoom + delta)\n );\n\n if (newZoom === oldZoom) return;\n\n // Get mouse position relative to canvas\n const rect = this.canvasEl.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const width = this.minimapEl.offsetWidth;\n const relativeX = mouseX / width; // 0-1 position in canvas\n\n // Calculate the table position (0-1) under the mouse BEFORE zoom\n const oldVisibleRatio = 1 / oldZoom;\n const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n const oldScrollRatio = scrollLeft / maxScroll;\n const oldPanX = oldZoom > 1 ? oldScrollRatio * (1 - oldVisibleRatio) : 0;\n const tableX = oldPanX + relativeX * oldVisibleRatio; // Position in table (0-1)\n\n // Update zoom level\n this.zoomState = {\n level: newZoom,\n panX: 0,\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\n // Calculate new scroll position to keep tableX under the mouse\n const newVisibleRatio = 1 / newZoom;\n\n if (newZoom > 1) {\n // newPanX + relativeX * newVisibleRatio = tableX\n // newPanX = tableX - relativeX * newVisibleRatio\n // newScrollRatio * (1 - newVisibleRatio) = newPanX\n // newScrollRatio = newPanX / (1 - newVisibleRatio)\n const newPanX = tableX - relativeX * newVisibleRatio;\n const newScrollRatio = newPanX / (1 - newVisibleRatio);\n const newScrollLeft = Math.max(0, Math.min(maxScroll, newScrollRatio * maxScroll));\n\n this.scrollContainer.scrollLeft = newScrollLeft;\n }\n\n this.updateScrollState();\n this.render();\n }\n\n /** Whether we started a potential pan (waiting to see if it's a click or drag) */\n private isPotentialPan = false;\n\n /**\n * Handles pointer down on canvas for drag start (scrolls table when zoomed)\n *\n * @param e - Pointer event\n */\n private onCanvasPointerDown(e: PointerEvent): void {\n if (!this.canvasEl || !this.scrollContainer) return;\n\n // At any zoom level, track potential pan/click\n this.isPotentialPan = true;\n this.panStartX = e.clientX;\n this.dragStartScrollLeft = this.scrollContainer.scrollLeft;\n\n // Only capture for panning at zoom > 1\n if (this.zoomState.level > 1) {\n e.preventDefault();\n this.canvasEl.setPointerCapture(e.pointerId);\n }\n }\n\n /**\n * Handles mouse move on canvas for column hover highlighting\n */\n private onCanvasMouseMove(e: MouseEvent): void {\n if (!this.canvasEl || this.isPanning) return;\n\n const rect = this.canvasEl.getBoundingClientRect();\n const newHoveredColumn = this.getColumnAtX(e.clientX - rect.left);\n\n if (newHoveredColumn !== this.hoveredColumn) {\n this.hoveredColumn = newHoveredColumn;\n this.canvasEl.style.cursor = newHoveredColumn >= 0 ? 'pointer' : (this.zoomState.level > 1 ? 'grab' : 'default');\n this.render();\n }\n }\n\n /**\n * Handles mouse leave on canvas to clear hover state\n */\n private onCanvasMouseLeave(): void {\n if (this.hoveredColumn !== -1) {\n this.hoveredColumn = -1;\n if (this.canvasEl) {\n this.canvasEl.style.cursor = this.zoomState.level > 1 ? 'grab' : 'default';\n }\n this.render();\n }\n }\n\n /**\n * Expands the compact minimap and clears any pending collapse.\n */\n private expandCompact(): void {\n if (!this.isCompactMode || !this.minimapEl || this.isCompactExpanding) return;\n\n this.clearCompactCollapseTimer();\n this.isCompactExpanding = true;\n this.applyCompactDimensions(false);\n \n // Wait for CSS transition to complete before rendering\n // This ensures correct dimensions are used for viewport calculation\n setTimeout(() => {\n this.isCompactExpanding = false;\n if (!this.isDestroyed && !this.isCompactCollapsed) {\n this.updateScrollState();\n this.render();\n }\n }, 200); // Slightly longer than transition duration (180ms)\n }\n\n /**\n * Collapses the compact minimap to the small dot handle.\n */\n private collapseCompact(): void {\n if (!this.isCompactMode || !this.minimapEl) return;\n\n this.applyCompactDimensions(true);\n }\n\n /**\n * Applies compact sizing/state to the minimap.\n */\n private applyCompactDimensions(collapsed: boolean): void {\n if (!this.minimapEl || !this.isCompactMode) return;\n\n this.isCompactCollapsed = collapsed;\n\n if (collapsed) {\n this.minimapEl.classList.add('tm-minimap--compact-collapsed');\n this.minimapEl.classList.remove('tm-minimap--compact-expanded');\n this.minimapEl.style.setProperty('--tm-minimap-width', `${COMPACT_HANDLE_SIZE}px`);\n this.minimapEl.style.setProperty('--tm-minimap-height', `${COMPACT_HANDLE_SIZE}px`);\n this.minimapEl.setAttribute('aria-expanded', 'false');\n return;\n }\n\n this.minimapEl.classList.remove('tm-minimap--compact-collapsed');\n this.minimapEl.classList.add('tm-minimap--compact-expanded');\n this.minimapEl.style.setProperty('--tm-minimap-width', `${this.options.fixedWidth}px`);\n this.minimapEl.style.setProperty('--tm-minimap-height', `${this.options.height}px`);\n this.minimapEl.setAttribute('aria-expanded', 'true');\n }\n\n /**\n * Clears a pending compact collapse timer.\n */\n private clearCompactCollapseTimer(): void {\n if (this.compactCollapseTimer === null) return;\n\n clearTimeout(this.compactCollapseTimer);\n this.compactCollapseTimer = null;\n }\n\n /**\n * Schedules the compact minimap to collapse.\n */\n private scheduleCompactCollapse(delay = COMPACT_COLLAPSE_DELAY): void {\n if (!this.isCompactMode) return;\n\n this.clearCompactCollapseTimer();\n this.compactCollapseTimer = window.setTimeout(() => {\n this.collapseCompact();\n this.compactCollapseTimer = null;\n }, delay);\n }\n\n /**\n * Handles document click for closing compact mode when clicking outside.\n */\n private onDocumentClick(e: MouseEvent): void {\n if (!this.isCompactMode || !this.minimapEl || this.isCompactCollapsed) return;\n\n // Check if click is outside the minimap\n if (!this.minimapEl.contains(e.target as Node)) {\n this.collapseCompact();\n }\n }\n\n /**\n * Handles focus entering compact mode.\n */\n private onCompactFocusIn(): void {\n if (!this.isCompactMode) return;\n\n this.expandCompact();\n }\n\n /**\n * Handles focus leaving compact mode.\n */\n private onCompactFocusOut(): void {\n if (!this.isCompactMode) return;\n\n this.scheduleCompactCollapse(0);\n }\n\n /**\n * Keyboard interactions for compact mode.\n */\n private onCompactKeyDown(e: KeyboardEvent): void {\n if (!this.isCompactMode) return;\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.collapseCompact();\n return;\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (this.isCompactCollapsed) {\n this.expandCompact();\n } else {\n this.collapseCompact();\n }\n }\n }\n\n /**\n * Sets up ResizeObserver and MutationObserver\n */\n private setupObservers(): void {\n // ResizeObserver for responsive updates\n this.resizeObserver = new ResizeObserver(() => {\n this.onResize();\n });\n\n if (this.scrollContainer) {\n this.resizeObserver.observe(this.scrollContainer);\n }\n this.resizeObserver.observe(this.table);\n\n // MutationObserver for table structure changes\n this.mutationObserver = new MutationObserver((mutations) => {\n const hasStructuralChanges = mutations.some(\n (m) => m.type === 'childList' || m.attributeName === 'colspan'\n );\n\n if (hasStructuralChanges) {\n this.onTableMutation();\n }\n });\n\n this.mutationObserver.observe(this.table, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['colspan'],\n });\n }\n\n /**\n * Handles resize events\n */\n private onResize(): void {\n if (this.isDestroyed) return;\n\n // Debounce resize handling\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n\n this.rafId = requestAnimationFrame(() => {\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n // Rebuild columns if in columns mode\n if (this.options.mode === 'columns' && this.columnsEl && this.minimapEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n\n this.rafId = null;\n });\n }\n\n /**\n * Handles table mutation events\n */\n private onTableMutation(): void {\n if (this.isDestroyed) return;\n\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n // Rebuild columns if in columns mode\n if (this.options.mode === 'columns' && this.columnsEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n }\n\n /**\n * Gets the current scroll state\n *\n * @returns Current scroll state\n */\n public getScrollState(): ScrollState {\n return { ...this.scrollState };\n }\n\n /**\n * Gets the detected columns\n *\n * @returns Array of column information\n */\n public getColumns(): ColumnInfo[] {\n return [...this.columns];\n }\n\n /**\n * Scrolls to a specific column\n *\n * @param columnIndex - Zero-based column index\n * @param smooth - Use smooth scrolling\n */\n public scrollToColumn(columnIndex: number, smooth = true): void {\n if (!this.scrollContainer || columnIndex < 0 || columnIndex >= this.columns.length) {\n return;\n }\n\n const cellsBefore = this.columns.slice(0, columnIndex);\n const offsetLeft = cellsBefore.reduce((sum, col) => sum + col.width, 0);\n\n this.scrollContainer.scrollTo({\n left: offsetLeft,\n behavior: smooth ? 'smooth' : 'auto',\n });\n }\n\n /**\n * Forces a refresh of the minimap\n */\n public refresh(): void {\n if (this.isDestroyed) return;\n\n this.scrollContainer = this.findScrollContainer();\n this.detectColumns();\n this.updateScrollState();\n\n this.render();\n\n if (this.options.mode === 'columns' && this.columnsEl) {\n this.columnsEl.innerHTML = '';\n this.columns.forEach(() => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n this.columnsEl!.appendChild(colEl);\n });\n }\n }\n\n /**\n * Gets the current zoom state (canvas mode only)\n *\n * @returns Current zoom state\n */\n public getZoomState(): ZoomState {\n return { ...this.zoomState };\n }\n\n /**\n * Sets the zoom level programmatically (canvas mode only)\n *\n * @param level - Zoom level (1 = no zoom)\n * @param panX - Optional pan position (0-1), controls which part of table is visible\n */\n public setZoom(level: number, panX?: number): void {\n if (this.isDestroyed || this.options.mode !== 'canvas' || !this.scrollContainer) return;\n\n const newZoom = Math.max(\n this.options.minZoom,\n Math.min(this.options.maxZoom, level)\n );\n\n const visibleRange = 1 / newZoom;\n const maxPanX = 1 - visibleRange;\n\n let newPanX = panX !== undefined ? panX : 0;\n newPanX = Math.max(0, Math.min(maxPanX, newPanX));\n\n this.zoomState = {\n level: newZoom,\n panX: 0, // Not used - panX is derived from scroll position\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\n // Set scroll position to match the desired panX\n if (newZoom > 1 && newPanX > 0) {\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const maxScroll = Math.max(scrollWidth - clientWidth, 1);\n // panX = scrollRatio * (1 - visibleRatio)\n // scrollRatio = panX / (1 - visibleRatio)\n const scrollRatio = newPanX / (1 - visibleRange);\n this.scrollContainer.scrollLeft = Math.max(0, Math.min(maxScroll, scrollRatio * maxScroll));\n } else if (newZoom <= 1) {\n this.scrollContainer.scrollLeft = 0;\n }\n\n this.updateScrollState();\n this.render();\n }\n\n /**\n * Resets zoom to default (shows full table overview)\n */\n public resetZoom(): void {\n this.setZoom(1, 0);\n }\n\n /**\n * Zooms to a specific column range (canvas mode only)\n *\n * @param startCol - Start column index\n * @param endCol - End column index\n */\n public zoomToColumns(startCol: number, endCol: number): void {\n if (this.isDestroyed || this.options.mode !== 'canvas') return;\n\n const numCols = this.columns.length;\n if (numCols === 0) return;\n\n // Clamp column indices\n const start = Math.max(0, Math.min(numCols - 1, startCol));\n const end = Math.max(start + 1, Math.min(numCols, endCol));\n\n const colRange = end - start;\n const zoom = numCols / colRange;\n const panX = start / numCols;\n\n this.setZoom(zoom, panX);\n }\n\n /**\n * Destroys the minimap instance and cleans up resources\n */\n public destroy(): void {\n if (this.isDestroyed) return;\n this.isDestroyed = true;\n\n this.clearCompactCollapseTimer();\n this.clearMinimapClickTimer();\n this.clearCanvasPanFrame();\n this.pendingPanClientX = null;\n\n // Cancel any pending animation frame\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n // Remove event listeners\n if (this.scrollContainer) {\n this.scrollContainer.removeEventListener('scroll', this.boundHandlers.onScroll);\n }\n\n if (this.minimapEl) {\n this.minimapEl.removeEventListener('click', this.boundHandlers.onMinimapClick);\n this.minimapEl.removeEventListener('dblclick', this.boundHandlers.onMinimapDoubleClick);\n this.minimapEl.removeEventListener('focusin', this.boundHandlers.onCompactFocusIn);\n this.minimapEl.removeEventListener('focusout', this.boundHandlers.onCompactFocusOut);\n this.minimapEl.removeEventListener('keydown', this.boundHandlers.onCompactKeyDown);\n }\n\n document.removeEventListener('click', this.boundHandlers.onDocumentClick);\n\n if (this.viewportEl) {\n this.viewportEl.removeEventListener('pointerdown', this.boundHandlers.onPointerDown);\n this.viewportEl.removeEventListener('wheel', this.boundHandlers.onWheel);\n }\n\n if (this.canvasEl) {\n this.canvasEl.removeEventListener('wheel', this.boundHandlers.onWheel);\n this.canvasEl.removeEventListener('pointerdown', this.boundHandlers.onCanvasPointerDown);\n this.canvasEl.removeEventListener('mousemove', this.boundHandlers.onCanvasMouseMove);\n this.canvasEl.removeEventListener('mouseleave', this.boundHandlers.onCanvasMouseLeave);\n }\n\n document.removeEventListener('pointermove', this.boundHandlers.onPointerMove);\n document.removeEventListener('pointerup', this.boundHandlers.onPointerUp);\n\n // Disconnect observers\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n // Remove DOM elements\n if (this.minimapEl && this.minimapEl.parentNode) {\n this.minimapEl.parentNode.removeChild(this.minimapEl);\n }\n\n // Clear references\n this.minimapEl = null;\n this.columnsEl = null;\n this.canvasEl = null;\n this.canvasCtx = null;\n this.viewportEl = null;\n this.scrollContainer = null;\n this.columns = [];\n }\n}\n","/**\n * Table Minimap - A framework-agnostic minimap component for large HTML tables\n *\n * @packageDocumentation\n */\n\nexport { TableMinimap } from './TableMinimap';\nexport type {\n TableMinimapOptions,\n ColumnInfo,\n ScrollState,\n CellData,\n TableSelector,\n ZoomState,\n} from './types';\n\n// Auto-inject styles into DOM\nimport styles from './styles.css?inline';\n\nlet stylesInjected = false;\n\nexport function injectStyles(): void {\n if (stylesInjected || typeof document === 'undefined') return;\n\n const style = document.createElement('style');\n style.id = 'table-minimap-styles';\n style.textContent = styles;\n document.head.appendChild(style);\n stylesInjected = true;\n}\n\n// Auto-inject on import (can be tree-shaken if not used)\ninjectStyles();\n\n"],"names":["DEFAULT_OPTIONS","COMPACT_HANDLE_SIZE","COMPACT_DOT_SIZE","COMPACT_COLLAPSE_DELAY","DOUBLE_CLICK_DELAY","FIXED_POSITIONS","CANVAS_PAN_THRESHOLD","CANVAS_PAN_SENSITIVITY","TableMinimap","selector","options","__publicField","element","parent","style","overflowX","overflowY","theadCells","cells","firstRow","tableWidth","cell","colspan","cellWidth","i","width","colEl","nextSibling","offset","pos","fixedPosition","currentIndex","nextIndex","scrollLeft","scrollWidth","clientWidth","_a","zoom","numCols","visibleRatio","visibleCols","panX","maxScroll","startColFloat","startCol","endCol","xOffset","mouseX","relativeX","tableX","colIndex","minimapWidth","viewportWidth","viewportLeft","metrics","height","dpr","ctx","rows","numRows","headerHeight","cellHeight","fontSize","headerFontSize","colors","headerRow","headerCells","col","x","text","_b","rowIndex","row","y","content","_d","_c","hoverX","e","clientX","rect","clickX","clickedColumn","colWidth","targetScroll","scrollDelta","newScrollLeft","deltaX","clickEvent","oldZoom","delta","newZoom","oldVisibleRatio","oldScrollRatio","newVisibleRatio","newScrollRatio","newHoveredColumn","collapsed","delay","mutations","m","columnIndex","smooth","offsetLeft","sum","level","visibleRange","maxPanX","newPanX","scrollRatio","start","colRange","stylesInjected","injectStyles","styles"],"mappings":"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"}