table-minimap 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +668 -0
- package/dist/index.d.ts +396 -0
- package/dist/shadcn.css +138 -0
- package/dist/style.css +1 -0
- package/dist/table-minimap.cjs +2 -0
- package/dist/table-minimap.cjs.map +1 -0
- package/dist/table-minimap.js +626 -0
- package/dist/table-minimap.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-minimap.cjs","sources":["../src/TableMinimap.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 draggable: true,\n showViewport: true,\n zoomable: false,\n minZoom: 1,\n maxZoom: 10,\n zoomSpeed: 0.1,\n};\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 /** 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 /** Currently focused/clicked column index (-1 = none) */\n private focusedColumn = -1;\n\n\n /** Drag start 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 };\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\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 };\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.height = `${this.options.height}px`;\n \n // Set width for fixed position\n if (this.options.position === 'fixed') {\n this.minimapEl.style.width = `${this.options.fixedWidth}px`;\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((col) => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n colEl.style.width = `${col.widthPercent}%`;\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\n this.minimapEl.style.position = 'absolute';\n this.minimapEl.style.bottom = '12px';\n this.minimapEl.style.right = '12px';\n this.minimapEl.style.marginTop = '0';\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 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 * In canvas mode, the viewport shows the focused (clicked) column\n */\n private updateViewport(): void {\n if (!this.viewportEl || !this.minimapEl) return;\n\n // Canvas mode: show focused column\n if (this.options.mode === 'canvas') {\n if (this.focusedColumn >= 0 && this.columns.length > 0) {\n const { cellWidth, startColFloat } = this.getCanvasMetrics();\n const colPosInCanvas = (this.focusedColumn - startColFloat) * cellWidth;\n\n this.viewportEl.style.cssText = `width:${cellWidth}px;left:${colPosInCanvas}px;display:block`;\n } else {\n this.viewportEl.style.display = 'none';\n }\n return;\n }\n\n // Columns mode: standard viewport\n const minimapWidth = this.minimapEl.offsetWidth;\n const viewportWidth = Math.max(minimapWidth * this.scrollState.viewportRatio, 20);\n const maxLeft = minimapWidth - viewportWidth;\n const viewportLeft = maxLeft * this.scrollState.positionRatio;\n\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 // 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 to update viewport position\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 // Ignore clicks during dragging, panning, or right after panning\n if (this.isDragging || this.isPanning || this.wasPanning) return;\n\n // Ignore clicks on viewport\n if (e.target === this.viewportEl) return;\n\n const { scrollWidth, clientWidth } = this.scrollContainer;\n const numCols = this.columns.length;\n\n // If we have a hovered column (from canvas mode), scroll to that column and set focus\n if (this.hoveredColumn >= 0 && numCols > 0) {\n // Set the focused column\n this.focusedColumn = this.hoveredColumn;\n\n // Calculate the scroll position to center the hovered column\n const colWidth = scrollWidth / numCols;\n const colCenter = (this.hoveredColumn + 0.5) * colWidth;\n const targetScroll = colCenter - clientWidth / 2;\n\n // Clamp to valid scroll range\n const maxScroll = scrollWidth - clientWidth;\n const clampedScroll = Math.max(0, Math.min(maxScroll, targetScroll));\n\n this.scrollContainer.scrollTo({\n left: clampedScroll,\n behavior: 'smooth',\n });\n\n // Update viewport to show focused column\n this.updateViewport();\n return;\n }\n\n // Fallback: calculate position from click coordinates\n const rect = this.minimapEl.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const clickRatio = clickX / rect.width; // 0-1 position within minimap\n\n const zoom = this.zoomState.level;\n\n let targetRatio: number;\n\n if (zoom > 1) {\n // When zoomed: the minimap shows a portion of the table\n // Calculate which portion based on current scroll position\n const scrollLeft = this.scrollContainer.scrollLeft;\n const scrollRatio = scrollLeft / Math.max(scrollWidth - clientWidth, 1);\n const visibleRatio = 1 / zoom;\n const panX = scrollRatio * (1 - visibleRatio);\n\n // Convert click within zoomed view to full table position\n targetRatio = panX + clickRatio * visibleRatio;\n } else {\n // Not zoomed: direct mapping\n targetRatio = clickRatio;\n }\n\n // Calculate target scroll position (center the clicked position)\n const targetPosition = targetRatio * scrollWidth;\n const targetScroll = targetPosition - clientWidth / 2;\n\n // Clamp to valid scroll range\n const maxScroll = scrollWidth - clientWidth;\n const clampedScroll = Math.max(0, Math.min(maxScroll, targetScroll));\n\n this.scrollContainer.scrollTo({\n left: clampedScroll,\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 deltaX = e.clientX - this.dragStartX;\n const minimapWidth = this.minimapEl.offsetWidth;\n const scrollableWidth =\n this.scrollContainer.scrollWidth - this.scrollContainer.clientWidth;\n\n // Convert minimap delta to scroll delta\n const scrollDelta = (deltaX / minimapWidth) * scrollableWidth;\n const newScrollLeft = this.dragStartScrollLeft + scrollDelta;\n\n // Apply scroll\n this.scrollContainer.scrollLeft = Math.max(\n 0,\n Math.min(scrollableWidth, newScrollLeft)\n );\n\n // Update state immediately\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\n e.preventDefault();\n\n const delta = -e.deltaY * this.options.zoomSpeed;\n const newZoom = Math.max(\n this.options.minZoom,\n Math.min(this.options.maxZoom, this.zoomState.level + delta)\n );\n\n // Just update zoom level - panX is derived from scroll position\n this.zoomState = {\n level: newZoom,\n panX: 0, // Not used anymore - derived from scroll position\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\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 * 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((col) => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n colEl.style.width = `${col.widthPercent}%`;\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((col) => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n colEl.style.width = `${col.widthPercent}%`;\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((col) => {\n const colEl = document.createElement('div');\n colEl.className = 'tm-column';\n colEl.style.width = `${col.widthPercent}%`;\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)\n */\n public setZoom(level: number, panX?: number): void {\n if (this.isDestroyed || this.options.mode !== 'canvas') 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 : this.zoomState.panX;\n newPanX = Math.max(0, Math.min(maxPanX, newPanX));\n\n this.zoomState = {\n level: newZoom,\n panX: newZoom > 1 ? newPanX : 0,\n isMinZoom: newZoom <= this.options.minZoom,\n isMaxZoom: newZoom >= this.options.maxZoom,\n };\n\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 // 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 }\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"],"names":["DEFAULT_OPTIONS","TableMinimap","selector","options","__publicField","element","parent","style","overflowX","overflowY","theadCells","cells","firstRow","tableWidth","cell","colspan","cellWidth","i","width","col","colEl","nextSibling","scrollLeft","scrollWidth","clientWidth","_a","zoom","numCols","visibleRatio","visibleCols","panX","maxScroll","startColFloat","startCol","endCol","xOffset","mouseX","relativeX","tableX","colIndex","colPosInCanvas","minimapWidth","viewportWidth","viewportLeft","metrics","height","dpr","ctx","rows","numRows","headerHeight","cellHeight","fontSize","headerFontSize","colors","headerRow","headerCells","x","text","_b","rowIndex","row","y","content","_d","_c","hoverX","e","colWidth","targetScroll","clampedScroll","rect","clickRatio","targetRatio","scrollRatio","deltaX","scrollDelta","newScrollLeft","scrollableWidth","clickEvent","delta","newZoom","newHoveredColumn","mutations","m","columnIndex","smooth","offsetLeft","sum","level","maxPanX","newPanX","start","colRange"],"mappings":"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"}
|