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
package/README.md
ADDED
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
# Table Minimap
|
|
2
|
+
|
|
3
|
+
A framework-agnostic minimap component for navigating large HTML tables. Inspired by VS Code's minimap, this library provides a visual overview of wide tables and enables drag-to-scroll navigation.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🎯 **Framework Agnostic** - Works with vanilla JS, React, Vue, Angular, or any framework
|
|
12
|
+
- 📦 **Zero Dependencies** - No external runtime dependencies
|
|
13
|
+
- 🌳 **Tree Shakable** - ESM + CommonJS outputs
|
|
14
|
+
- 🎨 **Two Render Modes** - Simple columns or VS Code-like canvas preview
|
|
15
|
+
- 📱 **Touch Support** - Mouse, touch, and pointer events
|
|
16
|
+
- 🔄 **Auto Updates** - Responds to resize, scroll, and DOM mutations
|
|
17
|
+
- ♿ **Accessible** - ARIA attributes and keyboard navigation support
|
|
18
|
+
- 🎭 **Themeable** - CSS custom properties for easy customization
|
|
19
|
+
- 🎨 **shadcn/ui Ready** - Dedicated theme using shadcn CSS variables
|
|
20
|
+
- 📏 **TypeScript** - Fully typed with declaration files
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install table-minimap
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
yarn add table-minimap
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add table-minimap
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { TableMinimap } from 'table-minimap';
|
|
40
|
+
import 'table-minimap/style.css';
|
|
41
|
+
|
|
42
|
+
// Using a CSS selector
|
|
43
|
+
const minimap = new TableMinimap('#my-table');
|
|
44
|
+
|
|
45
|
+
// Or using a DOM element
|
|
46
|
+
const table = document.querySelector('table');
|
|
47
|
+
const minimap = new TableMinimap(table);
|
|
48
|
+
|
|
49
|
+
// Don't forget to cleanup when done
|
|
50
|
+
minimap.destroy();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
### Basic Usage
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<div class="table-container" style="overflow-x: auto;">
|
|
59
|
+
<table id="my-table">
|
|
60
|
+
<thead>
|
|
61
|
+
<tr>
|
|
62
|
+
<th>Column 1</th>
|
|
63
|
+
<th>Column 2</th>
|
|
64
|
+
<!-- ... more columns ... -->
|
|
65
|
+
</tr>
|
|
66
|
+
</thead>
|
|
67
|
+
<tbody>
|
|
68
|
+
<!-- ... rows ... -->
|
|
69
|
+
</tbody>
|
|
70
|
+
</table>
|
|
71
|
+
</div>
|
|
72
|
+
<!-- Minimap will be inserted after the container -->
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { TableMinimap } from 'table-minimap';
|
|
77
|
+
import 'table-minimap/style.css';
|
|
78
|
+
|
|
79
|
+
const minimap = new TableMinimap('#my-table');
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### With Configuration
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const minimap = new TableMinimap('#my-table', {
|
|
86
|
+
mode: 'canvas', // 'columns' | 'canvas'
|
|
87
|
+
height: 50, // Height in pixels
|
|
88
|
+
position: 'bottom', // 'top' | 'bottom'
|
|
89
|
+
draggable: true, // Enable drag navigation
|
|
90
|
+
showViewport: true, // Show viewport indicator
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Canvas Mode (VS Code-like)
|
|
95
|
+
|
|
96
|
+
Canvas mode renders a compressed pixel preview of the entire table:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const minimap = new TableMinimap('#data-table', {
|
|
100
|
+
mode: 'canvas',
|
|
101
|
+
height: 60,
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Darker pixels indicate cells with more content
|
|
106
|
+
- Empty cells appear lighter
|
|
107
|
+
- Provides a visual "density map" of your data
|
|
108
|
+
|
|
109
|
+
### Canvas Mode with Zoom
|
|
110
|
+
|
|
111
|
+
Enable zoom functionality in canvas mode for detailed inspection:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const minimap = new TableMinimap('#data-table', {
|
|
115
|
+
mode: 'canvas',
|
|
116
|
+
height: 80,
|
|
117
|
+
zoomable: true,
|
|
118
|
+
minZoom: 1,
|
|
119
|
+
maxZoom: 10,
|
|
120
|
+
zoomSpeed: 0.1,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Programmatic zoom control
|
|
124
|
+
minimap.setZoom(3, 0.5); // Zoom to 3x at center
|
|
125
|
+
minimap.zoomToColumns(5, 15); // Zoom to columns 5-15
|
|
126
|
+
minimap.resetZoom(); // Reset to full view
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Zoom Controls:**
|
|
130
|
+
- **Scroll wheel** on minimap to zoom in/out
|
|
131
|
+
- **Drag** the canvas when zoomed to pan
|
|
132
|
+
- A position indicator appears at the bottom when zoomed
|
|
133
|
+
|
|
134
|
+
### Position Options
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// Minimap above the table
|
|
138
|
+
const minimap = new TableMinimap('#my-table', {
|
|
139
|
+
position: 'top',
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Minimap below the table (default)
|
|
143
|
+
const minimap = new TableMinimap('#my-table', {
|
|
144
|
+
position: 'bottom',
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
### Options Interface
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
interface TableMinimapOptions {
|
|
154
|
+
/**
|
|
155
|
+
* Rendering mode
|
|
156
|
+
* - "columns": Simple column segments (default)
|
|
157
|
+
* - "canvas": VS Code-like pixel preview
|
|
158
|
+
*/
|
|
159
|
+
mode?: 'columns' | 'canvas';
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Height of the minimap in pixels
|
|
163
|
+
* @default 40
|
|
164
|
+
*/
|
|
165
|
+
height?: number;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Position relative to the table
|
|
169
|
+
* @default "bottom"
|
|
170
|
+
*/
|
|
171
|
+
position?: 'top' | 'bottom';
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Enable drag navigation
|
|
175
|
+
* @default true
|
|
176
|
+
*/
|
|
177
|
+
draggable?: boolean;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Show viewport indicator
|
|
181
|
+
* @default true
|
|
182
|
+
*/
|
|
183
|
+
showViewport?: boolean;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Enable zoom in canvas mode (scroll wheel)
|
|
187
|
+
* @default false
|
|
188
|
+
*/
|
|
189
|
+
zoomable?: boolean;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Minimum zoom level
|
|
193
|
+
* @default 1
|
|
194
|
+
*/
|
|
195
|
+
minZoom?: number;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Maximum zoom level
|
|
199
|
+
* @default 10
|
|
200
|
+
*/
|
|
201
|
+
maxZoom?: number;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Zoom speed multiplier
|
|
205
|
+
* @default 0.1
|
|
206
|
+
*/
|
|
207
|
+
zoomSpeed?: number;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Default Values
|
|
212
|
+
|
|
213
|
+
| Option | Default |
|
|
214
|
+
|--------|---------|
|
|
215
|
+
| `mode` | `'columns'` |
|
|
216
|
+
| `height` | `40` |
|
|
217
|
+
| `position` | `'bottom'` |
|
|
218
|
+
| `draggable` | `true` |
|
|
219
|
+
| `showViewport` | `true` |
|
|
220
|
+
| `zoomable` | `false` |
|
|
221
|
+
| `minZoom` | `1` |
|
|
222
|
+
| `maxZoom` | `10` |
|
|
223
|
+
| `zoomSpeed` | `0.1` |
|
|
224
|
+
|
|
225
|
+
## API Reference
|
|
226
|
+
|
|
227
|
+
### Constructor
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
new TableMinimap(selector: string | HTMLTableElement, options?: TableMinimapOptions)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Parameters:**
|
|
234
|
+
- `selector` - CSS selector string or HTMLTableElement
|
|
235
|
+
- `options` - Optional configuration object
|
|
236
|
+
|
|
237
|
+
**Throws:**
|
|
238
|
+
- Error if element is not found
|
|
239
|
+
- Error if element is not a `<table>`
|
|
240
|
+
|
|
241
|
+
### Methods
|
|
242
|
+
|
|
243
|
+
#### `destroy(): void`
|
|
244
|
+
|
|
245
|
+
Removes the minimap and cleans up all event listeners, observers, and DOM elements. Always call this when the table is removed from the DOM.
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
minimap.destroy();
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### `refresh(): void`
|
|
252
|
+
|
|
253
|
+
Forces a refresh of the minimap. Useful after programmatic table modifications.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// After dynamically updating table content
|
|
257
|
+
minimap.refresh();
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### `getScrollState(): ScrollState`
|
|
261
|
+
|
|
262
|
+
Returns the current scroll state.
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
const state = minimap.getScrollState();
|
|
266
|
+
console.log(state);
|
|
267
|
+
// {
|
|
268
|
+
// scrollLeft: 200,
|
|
269
|
+
// scrollWidth: 2000,
|
|
270
|
+
// clientWidth: 500,
|
|
271
|
+
// viewportRatio: 0.25,
|
|
272
|
+
// positionRatio: 0.13
|
|
273
|
+
// }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### `getColumns(): ColumnInfo[]`
|
|
277
|
+
|
|
278
|
+
Returns information about detected columns.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
const columns = minimap.getColumns();
|
|
282
|
+
console.log(columns);
|
|
283
|
+
// [
|
|
284
|
+
// { index: 0, width: 120, widthPercent: 6 },
|
|
285
|
+
// { index: 1, width: 80, widthPercent: 4 },
|
|
286
|
+
// ...
|
|
287
|
+
// ]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### `scrollToColumn(columnIndex: number, smooth?: boolean): void`
|
|
291
|
+
|
|
292
|
+
Scrolls the table to bring a specific column into view.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Scroll to column 10 with smooth animation
|
|
296
|
+
minimap.scrollToColumn(10, true);
|
|
297
|
+
|
|
298
|
+
// Instant scroll
|
|
299
|
+
minimap.scrollToColumn(10, false);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### `getZoomState(): ZoomState`
|
|
303
|
+
|
|
304
|
+
Returns the current zoom state (canvas mode only).
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const zoom = minimap.getZoomState();
|
|
308
|
+
console.log(zoom);
|
|
309
|
+
// {
|
|
310
|
+
// level: 2.5,
|
|
311
|
+
// panX: 0.3,
|
|
312
|
+
// isMinZoom: false,
|
|
313
|
+
// isMaxZoom: false
|
|
314
|
+
// }
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### `setZoom(level: number, panX?: number): void`
|
|
318
|
+
|
|
319
|
+
Sets the zoom level programmatically (canvas mode only).
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
// Zoom to 3x at current position
|
|
323
|
+
minimap.setZoom(3);
|
|
324
|
+
|
|
325
|
+
// Zoom to 5x centered at 50% of table width
|
|
326
|
+
minimap.setZoom(5, 0.5);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### `resetZoom(): void`
|
|
330
|
+
|
|
331
|
+
Resets zoom to show the full table overview.
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
minimap.resetZoom();
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### `zoomToColumns(startCol: number, endCol: number): void`
|
|
338
|
+
|
|
339
|
+
Zooms to show a specific column range (canvas mode only).
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// Zoom to show columns 10-20
|
|
343
|
+
minimap.zoomToColumns(10, 20);
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Styling
|
|
347
|
+
|
|
348
|
+
### CSS Custom Properties
|
|
349
|
+
|
|
350
|
+
Override these CSS variables to customize the minimap appearance:
|
|
351
|
+
|
|
352
|
+
```css
|
|
353
|
+
:root {
|
|
354
|
+
--tm-background: #f5f5f5;
|
|
355
|
+
--tm-border: #e0e0e0;
|
|
356
|
+
--tm-viewport-color: rgba(0, 120, 212, 0.3);
|
|
357
|
+
--tm-viewport-border: rgba(0, 120, 212, 0.8);
|
|
358
|
+
--tm-height: 40px;
|
|
359
|
+
--tm-column-color: #d0d0d0;
|
|
360
|
+
--tm-column-gap: 1px;
|
|
361
|
+
--tm-border-radius: 4px;
|
|
362
|
+
--tm-canvas-empty: #f0f0f0;
|
|
363
|
+
--tm-canvas-filled: #606060;
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Dark Mode
|
|
368
|
+
|
|
369
|
+
The library automatically supports `prefers-color-scheme: dark`:
|
|
370
|
+
|
|
371
|
+
```css
|
|
372
|
+
@media (prefers-color-scheme: dark) {
|
|
373
|
+
:root {
|
|
374
|
+
--tm-background: #2d2d2d;
|
|
375
|
+
--tm-border: #404040;
|
|
376
|
+
--tm-viewport-color: rgba(100, 180, 255, 0.25);
|
|
377
|
+
--tm-viewport-border: rgba(100, 180, 255, 0.7);
|
|
378
|
+
--tm-column-color: #505050;
|
|
379
|
+
--tm-canvas-empty: #3a3a3a;
|
|
380
|
+
--tm-canvas-filled: #a0a0a0;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### CSS Classes
|
|
386
|
+
|
|
387
|
+
| Class | Description |
|
|
388
|
+
|-------|-------------|
|
|
389
|
+
| `.tm-minimap` | Main container |
|
|
390
|
+
| `.tm-minimap--top` | Applied when position is 'top' |
|
|
391
|
+
| `.tm-minimap--bottom` | Applied when position is 'bottom' |
|
|
392
|
+
| `.tm-columns` | Columns container (columns mode) |
|
|
393
|
+
| `.tm-column` | Individual column segment |
|
|
394
|
+
| `.tm-canvas` | Canvas element (canvas mode) |
|
|
395
|
+
| `.tm-viewport` | Viewport indicator |
|
|
396
|
+
| `.tm-viewport--dragging` | Applied during drag |
|
|
397
|
+
| `.tm-viewport--disabled` | Applied when draggable is false |
|
|
398
|
+
|
|
399
|
+
### Custom Theme Example
|
|
400
|
+
|
|
401
|
+
```css
|
|
402
|
+
/* Blue theme */
|
|
403
|
+
.tm-minimap {
|
|
404
|
+
--tm-background: #e3f2fd;
|
|
405
|
+
--tm-border: #bbdefb;
|
|
406
|
+
--tm-viewport-color: rgba(25, 118, 210, 0.3);
|
|
407
|
+
--tm-viewport-border: #1976d2;
|
|
408
|
+
--tm-column-color: #90caf9;
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### shadcn/ui Integration
|
|
413
|
+
|
|
414
|
+
For projects using [shadcn/ui](https://ui.shadcn.com/), import the dedicated stylesheet that uses shadcn's CSS variables:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { TableMinimap } from 'table-minimap';
|
|
418
|
+
import 'table-minimap/shadcn.css'; // Use shadcn theme instead of style.css
|
|
419
|
+
|
|
420
|
+
const minimap = new TableMinimap('#my-table');
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
The shadcn theme automatically uses your project's color scheme:
|
|
424
|
+
|
|
425
|
+
| Minimap Variable | shadcn Variable |
|
|
426
|
+
|------------------|-----------------|
|
|
427
|
+
| `--tm-background` | `--muted` |
|
|
428
|
+
| `--tm-border` | `--border` |
|
|
429
|
+
| `--tm-viewport-color` | `--primary` (with opacity) |
|
|
430
|
+
| `--tm-viewport-border` | `--primary` |
|
|
431
|
+
| `--tm-column-color` | `--muted-foreground` |
|
|
432
|
+
| `--tm-border-radius` | `--radius` |
|
|
433
|
+
|
|
434
|
+
This ensures the minimap matches your shadcn/ui theme including dark mode support.
|
|
435
|
+
|
|
436
|
+
#### shadcn/ui + React Example
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
'use client';
|
|
440
|
+
|
|
441
|
+
import { useEffect, useRef } from 'react';
|
|
442
|
+
import { TableMinimap } from 'table-minimap';
|
|
443
|
+
import 'table-minimap/shadcn.css';
|
|
444
|
+
|
|
445
|
+
import {
|
|
446
|
+
Table,
|
|
447
|
+
TableBody,
|
|
448
|
+
TableCell,
|
|
449
|
+
TableHead,
|
|
450
|
+
TableHeader,
|
|
451
|
+
TableRow,
|
|
452
|
+
} from '@/components/ui/table';
|
|
453
|
+
|
|
454
|
+
export function DataTableWithMinimap({ data }: { data: any[] }) {
|
|
455
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
456
|
+
const minimapRef = useRef<TableMinimap | null>(null);
|
|
457
|
+
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
const table = containerRef.current?.querySelector('table');
|
|
460
|
+
if (table) {
|
|
461
|
+
minimapRef.current = new TableMinimap(table as HTMLTableElement, {
|
|
462
|
+
mode: 'columns',
|
|
463
|
+
height: 36,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return () => {
|
|
468
|
+
minimapRef.current?.destroy();
|
|
469
|
+
};
|
|
470
|
+
}, []);
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<div ref={containerRef} className="overflow-x-auto rounded-md border">
|
|
474
|
+
<Table>
|
|
475
|
+
<TableHeader>
|
|
476
|
+
<TableRow>
|
|
477
|
+
{/* Your headers */}
|
|
478
|
+
</TableRow>
|
|
479
|
+
</TableHeader>
|
|
480
|
+
<TableBody>
|
|
481
|
+
{/* Your rows */}
|
|
482
|
+
</TableBody>
|
|
483
|
+
</Table>
|
|
484
|
+
</div>
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Framework Integration
|
|
490
|
+
|
|
491
|
+
### React
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
import { useEffect, useRef } from 'react';
|
|
495
|
+
import { TableMinimap } from 'table-minimap';
|
|
496
|
+
import 'table-minimap/style.css';
|
|
497
|
+
|
|
498
|
+
function DataTable() {
|
|
499
|
+
const tableRef = useRef<HTMLTableElement>(null);
|
|
500
|
+
const minimapRef = useRef<TableMinimap | null>(null);
|
|
501
|
+
|
|
502
|
+
useEffect(() => {
|
|
503
|
+
if (tableRef.current) {
|
|
504
|
+
minimapRef.current = new TableMinimap(tableRef.current);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return () => {
|
|
508
|
+
minimapRef.current?.destroy();
|
|
509
|
+
};
|
|
510
|
+
}, []);
|
|
511
|
+
|
|
512
|
+
return (
|
|
513
|
+
<div style={{ overflowX: 'auto' }}>
|
|
514
|
+
<table ref={tableRef}>
|
|
515
|
+
{/* ... */}
|
|
516
|
+
</table>
|
|
517
|
+
</div>
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Vue 3
|
|
523
|
+
|
|
524
|
+
```vue
|
|
525
|
+
<script setup lang="ts">
|
|
526
|
+
import { ref, onMounted, onUnmounted } from 'vue';
|
|
527
|
+
import { TableMinimap } from 'table-minimap';
|
|
528
|
+
import 'table-minimap/style.css';
|
|
529
|
+
|
|
530
|
+
const tableRef = ref<HTMLTableElement | null>(null);
|
|
531
|
+
let minimap: TableMinimap | null = null;
|
|
532
|
+
|
|
533
|
+
onMounted(() => {
|
|
534
|
+
if (tableRef.value) {
|
|
535
|
+
minimap = new TableMinimap(tableRef.value);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
onUnmounted(() => {
|
|
540
|
+
minimap?.destroy();
|
|
541
|
+
});
|
|
542
|
+
</script>
|
|
543
|
+
|
|
544
|
+
<template>
|
|
545
|
+
<div style="overflow-x: auto;">
|
|
546
|
+
<table ref="tableRef">
|
|
547
|
+
<!-- ... -->
|
|
548
|
+
</table>
|
|
549
|
+
</div>
|
|
550
|
+
</template>
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Angular
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
import { Component, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
|
|
557
|
+
import { TableMinimap } from 'table-minimap';
|
|
558
|
+
import 'table-minimap/style.css';
|
|
559
|
+
|
|
560
|
+
@Component({
|
|
561
|
+
selector: 'app-data-table',
|
|
562
|
+
template: `
|
|
563
|
+
<div style="overflow-x: auto;">
|
|
564
|
+
<table #tableElement>
|
|
565
|
+
<!-- ... -->
|
|
566
|
+
</table>
|
|
567
|
+
</div>
|
|
568
|
+
`
|
|
569
|
+
})
|
|
570
|
+
export class DataTableComponent implements AfterViewInit, OnDestroy {
|
|
571
|
+
@ViewChild('tableElement') tableRef!: ElementRef<HTMLTableElement>;
|
|
572
|
+
private minimap: TableMinimap | null = null;
|
|
573
|
+
|
|
574
|
+
ngAfterViewInit() {
|
|
575
|
+
this.minimap = new TableMinimap(this.tableRef.nativeElement);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
ngOnDestroy() {
|
|
579
|
+
this.minimap?.destroy();
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## Development
|
|
585
|
+
|
|
586
|
+
### Setup
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
git clone https://github.com/your-username/table-minimap.git
|
|
590
|
+
cd table-minimap
|
|
591
|
+
npm install
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Development Server
|
|
595
|
+
|
|
596
|
+
```bash
|
|
597
|
+
npm run dev
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
Opens the demo at `http://localhost:5173`
|
|
601
|
+
|
|
602
|
+
### Build
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
npm run build
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
Outputs to `dist/`:
|
|
609
|
+
- `table-minimap.js` (ESM)
|
|
610
|
+
- `table-minimap.cjs` (CommonJS)
|
|
611
|
+
- `style.css`
|
|
612
|
+
- `index.d.ts` (TypeScript declarations)
|
|
613
|
+
|
|
614
|
+
### Project Structure
|
|
615
|
+
|
|
616
|
+
```
|
|
617
|
+
table-minimap/
|
|
618
|
+
├── src/
|
|
619
|
+
│ ├── TableMinimap.ts # Main component class
|
|
620
|
+
│ ├── styles.css # Default styles
|
|
621
|
+
│ ├── types.ts # TypeScript interfaces
|
|
622
|
+
│ └── index.ts # Public exports
|
|
623
|
+
├── demo/
|
|
624
|
+
│ ├── index.html # Demo page
|
|
625
|
+
│ └── main.ts # Demo script
|
|
626
|
+
├── dist/ # Build output
|
|
627
|
+
├── package.json
|
|
628
|
+
├── tsconfig.json
|
|
629
|
+
├── vite.config.ts
|
|
630
|
+
└── README.md
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
## Publishing
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
# Ensure build is up to date
|
|
637
|
+
npm run build
|
|
638
|
+
|
|
639
|
+
# Publish to npm
|
|
640
|
+
npm publish
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## Browser Support
|
|
644
|
+
|
|
645
|
+
- Chrome (latest)
|
|
646
|
+
- Firefox (latest)
|
|
647
|
+
- Safari (latest)
|
|
648
|
+
- Edge (latest)
|
|
649
|
+
|
|
650
|
+
Requires:
|
|
651
|
+
- `ResizeObserver`
|
|
652
|
+
- `MutationObserver`
|
|
653
|
+
- `PointerEvents`
|
|
654
|
+
|
|
655
|
+
## License
|
|
656
|
+
|
|
657
|
+
MIT © [Your Name]
|
|
658
|
+
|
|
659
|
+
## Contributing
|
|
660
|
+
|
|
661
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
662
|
+
|
|
663
|
+
1. Fork the repository
|
|
664
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
665
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
666
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
667
|
+
5. Open a Pull Request
|
|
668
|
+
|