table-minimap 1.0.7 → 1.1.1
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/LICENSE +22 -0
- package/README.md +7 -0
- package/dist/index.d.ts +11 -6
- package/dist/shadcn.css +16 -2
- package/dist/table-minimap.cjs +1 -1
- package/dist/table-minimap.cjs.map +1 -1
- package/dist/table-minimap.js +124 -121
- package/dist/table-minimap.js.map +1 -1
- package/package.json +1 -1
package/dist/table-minimap.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var n = (
|
|
4
|
-
const
|
|
1
|
+
var X = Object.defineProperty;
|
|
2
|
+
var z = (v, t, e) => t in v ? X(v, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : v[t] = e;
|
|
3
|
+
var n = (v, t, e) => z(v, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
const H = {
|
|
5
5
|
mode: "columns",
|
|
6
6
|
height: 40,
|
|
7
7
|
position: "bottom",
|
|
8
8
|
fixedWidth: 300,
|
|
9
|
+
fixedPosition: "bottom-right",
|
|
9
10
|
compact: !1,
|
|
10
11
|
draggable: !0,
|
|
11
12
|
showViewport: !0,
|
|
@@ -31,6 +32,8 @@ class F {
|
|
|
31
32
|
n(this, "isCompactMode");
|
|
32
33
|
/** Whether the compact minimap is currently collapsed */
|
|
33
34
|
n(this, "isCompactCollapsed", !1);
|
|
35
|
+
/** Whether the compact minimap is currently expanding (transition in progress) */
|
|
36
|
+
n(this, "isCompactExpanding", !1);
|
|
34
37
|
/** Timeout used to collapse compact mode after pointer leave */
|
|
35
38
|
n(this, "compactCollapseTimer", null);
|
|
36
39
|
/** The scrollable container (parent of table) */
|
|
@@ -72,9 +75,7 @@ class F {
|
|
|
72
75
|
n(this, "panStartX", 0);
|
|
73
76
|
/** Currently hovered column index (-1 = none) */
|
|
74
77
|
n(this, "hoveredColumn", -1);
|
|
75
|
-
/**
|
|
76
|
-
n(this, "focusedColumn", -1);
|
|
77
|
-
/** Drag start position */
|
|
78
|
+
/** Drag start X position */
|
|
78
79
|
n(this, "dragStartX", 0);
|
|
79
80
|
/** Drag start scroll position */
|
|
80
81
|
n(this, "dragStartScrollLeft", 0);
|
|
@@ -90,7 +91,7 @@ class F {
|
|
|
90
91
|
n(this, "isDestroyed", !1);
|
|
91
92
|
/** Whether we started a potential pan (waiting to see if it's a click or drag) */
|
|
92
93
|
n(this, "isPotentialPan", !1);
|
|
93
|
-
this.table = this.resolveTable(t), this.options = { ...
|
|
94
|
+
this.table = this.resolveTable(t), this.options = { ...H, ...e }, this.isCompactMode = this.options.compact && this.options.position === "fixed", this.boundHandlers = {
|
|
94
95
|
onScroll: this.onScroll.bind(this),
|
|
95
96
|
onPointerDown: this.onPointerDown.bind(this),
|
|
96
97
|
onPointerMove: this.onPointerMove.bind(this),
|
|
@@ -170,9 +171,9 @@ class F {
|
|
|
170
171
|
}
|
|
171
172
|
const i = this.table.offsetWidth || 1;
|
|
172
173
|
Array.from(e).forEach((o) => {
|
|
173
|
-
const
|
|
174
|
-
for (let
|
|
175
|
-
const l = s /
|
|
174
|
+
const a = o.colSpan || 1, s = o.offsetWidth;
|
|
175
|
+
for (let r = 0; r < a; r++) {
|
|
176
|
+
const l = s / a;
|
|
176
177
|
this.columns.push({
|
|
177
178
|
index: this.columns.length,
|
|
178
179
|
width: l,
|
|
@@ -189,15 +190,15 @@ class F {
|
|
|
189
190
|
* Creates the minimap DOM element
|
|
190
191
|
*/
|
|
191
192
|
createMinimapElement() {
|
|
192
|
-
this.minimapEl = document.createElement("div"), this.minimapEl.className = `tm-minimap tm-minimap--${this.options.position}`, this.minimapEl.style.setProperty("--tm-minimap-height", `${this.options.height}px`), this.options.position === "fixed" && this.minimapEl.style.setProperty("--tm-minimap-width", `${this.options.fixedWidth}px`), this.isCompactMode ? (this.minimapEl.classList.add("tm-minimap--compact", "tm-minimap--compact-collapsed"), this.minimapEl.style.setProperty("--tm-compact-dot-size", `${A}px`), this.isCompactCollapsed = !0, this.applyCompactDimensions(!0), this.minimapEl.setAttribute("aria-expanded", "false")) : this.minimapEl.setAttribute("aria-expanded", "true"), this.minimapEl.setAttribute("role", "slider"), this.minimapEl.setAttribute("aria-label", "Table minimap navigation"), this.minimapEl.setAttribute("aria-valuemin", "0"), this.minimapEl.setAttribute("aria-valuemax", "100"), this.minimapEl.setAttribute("tabindex", "0"), this.options.mode === "canvas" ? this.createCanvasContent() : this.createColumnsContent(), this.options.showViewport && this.createViewportIndicator(), this.insertMinimap();
|
|
193
|
+
this.minimapEl = document.createElement("div"), this.minimapEl.className = `tm-minimap tm-minimap--${this.options.position}`, this.minimapEl.style.setProperty("--tm-minimap-height", `${this.options.height}px`), this.options.position === "fixed" && (this.minimapEl.style.setProperty("--tm-minimap-width", `${this.options.fixedWidth}px`), this.minimapEl.classList.add(`tm-minimap--${this.options.fixedPosition}`)), this.isCompactMode ? (this.minimapEl.classList.add("tm-minimap--compact", "tm-minimap--compact-collapsed"), this.minimapEl.style.setProperty("--tm-compact-dot-size", `${A}px`), this.isCompactCollapsed = !0, this.applyCompactDimensions(!0), this.minimapEl.setAttribute("aria-expanded", "false")) : this.minimapEl.setAttribute("aria-expanded", "true"), this.minimapEl.setAttribute("role", "slider"), this.minimapEl.setAttribute("aria-label", "Table minimap navigation"), this.minimapEl.setAttribute("aria-valuemin", "0"), this.minimapEl.setAttribute("aria-valuemax", "100"), this.minimapEl.setAttribute("tabindex", "0"), this.options.mode === "canvas" ? this.createCanvasContent() : this.createColumnsContent(), this.options.showViewport && this.createViewportIndicator(), this.insertMinimap();
|
|
193
194
|
}
|
|
194
195
|
/**
|
|
195
196
|
* Creates columns-mode content
|
|
196
197
|
*/
|
|
197
198
|
createColumnsContent() {
|
|
198
|
-
this.minimapEl && (this.columnsEl = document.createElement("div"), this.columnsEl.className = "tm-columns", this.columns.forEach((
|
|
199
|
-
const
|
|
200
|
-
|
|
199
|
+
this.minimapEl && (this.columnsEl = document.createElement("div"), this.columnsEl.className = "tm-columns", this.columns.forEach(() => {
|
|
200
|
+
const t = document.createElement("div");
|
|
201
|
+
t.className = "tm-column", this.columnsEl.appendChild(t);
|
|
201
202
|
}), this.minimapEl.appendChild(this.columnsEl));
|
|
202
203
|
}
|
|
203
204
|
/**
|
|
@@ -223,8 +224,8 @@ class F {
|
|
|
223
224
|
getComputedStyle(t).position === "static" && (t.style.position = "relative");
|
|
224
225
|
const i = this.scrollContainer.nextSibling;
|
|
225
226
|
i ? t.insertBefore(this.minimapEl, i) : t.appendChild(this.minimapEl), this.minimapEl.style.position = "absolute";
|
|
226
|
-
const o = this.isCompactMode ? 8 : 12;
|
|
227
|
-
this.minimapEl.style.bottom = `${o}px`, this.minimapEl.style.right = `${o}px`, this.minimapEl.style.
|
|
227
|
+
const o = this.isCompactMode ? 8 : 12, a = this.options.fixedPosition;
|
|
228
|
+
this.minimapEl.style.top = "", this.minimapEl.style.bottom = "", this.minimapEl.style.left = "", this.minimapEl.style.right = "", this.minimapEl.style.marginTop = "0", a === "top-left" ? (this.minimapEl.style.top = `${o}px`, this.minimapEl.style.left = `${o}px`) : a === "top-right" ? (this.minimapEl.style.top = `${o}px`, this.minimapEl.style.right = `${o}px`) : a === "bottom-left" ? (this.minimapEl.style.bottom = `${o}px`, this.minimapEl.style.left = `${o}px`) : (this.minimapEl.style.bottom = `${o}px`, this.minimapEl.style.right = `${o}px`);
|
|
228
229
|
}
|
|
229
230
|
} else if (this.options.position === "top")
|
|
230
231
|
t ? t.insertBefore(this.minimapEl, this.scrollContainer) : this.scrollContainer.insertBefore(this.minimapEl, this.scrollContainer.firstChild);
|
|
@@ -261,25 +262,25 @@ class F {
|
|
|
261
262
|
* Canvas metrics for calculations - cached values to avoid repeated computations
|
|
262
263
|
*/
|
|
263
264
|
getCanvasMetrics() {
|
|
264
|
-
var
|
|
265
|
-
const t = ((
|
|
266
|
-
let
|
|
265
|
+
var p;
|
|
266
|
+
const t = ((p = this.minimapEl) == null ? void 0 : p.offsetWidth) ?? 0, e = this.zoomState.level, i = this.columns.length, o = 1 / e, a = i * o, s = a > 0 ? t / a : 0;
|
|
267
|
+
let r = 0;
|
|
267
268
|
if (e > 1 && this.scrollContainer) {
|
|
268
|
-
const { scrollLeft:
|
|
269
|
-
|
|
269
|
+
const { scrollLeft: m, scrollWidth: E, clientWidth: g } = this.scrollContainer, u = Math.max(E - g, 1);
|
|
270
|
+
r = m / u * (1 - o);
|
|
270
271
|
}
|
|
271
|
-
const l =
|
|
272
|
+
const l = r * i, c = Math.floor(l), h = Math.min(Math.ceil(l + a) + 1, i), f = -(l - c) * s;
|
|
272
273
|
return {
|
|
273
274
|
width: t,
|
|
274
275
|
zoom: e,
|
|
275
276
|
numCols: i,
|
|
276
277
|
visibleRatio: o,
|
|
277
|
-
visibleCols:
|
|
278
|
+
visibleCols: a,
|
|
278
279
|
cellWidth: s,
|
|
279
|
-
panX:
|
|
280
|
+
panX: r,
|
|
280
281
|
startColFloat: l,
|
|
281
|
-
startCol:
|
|
282
|
-
endCol:
|
|
282
|
+
startCol: c,
|
|
283
|
+
endCol: h,
|
|
283
284
|
xOffset: f
|
|
284
285
|
};
|
|
285
286
|
}
|
|
@@ -287,23 +288,19 @@ class F {
|
|
|
287
288
|
* Calculates column index from mouse X position
|
|
288
289
|
*/
|
|
289
290
|
getColumnAtX(t) {
|
|
290
|
-
const { width: e, numCols: i, panX: o, visibleRatio:
|
|
291
|
+
const { width: e, numCols: i, panX: o, visibleRatio: a } = this.getCanvasMetrics();
|
|
291
292
|
if (i === 0 || e === 0) return -1;
|
|
292
|
-
const s = t / e,
|
|
293
|
+
const s = t / e, r = o + s * a, l = Math.floor(r * i);
|
|
293
294
|
return Math.max(0, Math.min(i - 1, l));
|
|
294
295
|
}
|
|
295
296
|
/**
|
|
296
297
|
* Updates the viewport indicator position and size
|
|
297
|
-
*
|
|
298
|
+
* Shows the visible portion of the table (columns mode only)
|
|
298
299
|
*/
|
|
299
300
|
updateViewport() {
|
|
300
301
|
if (!this.viewportEl || !this.minimapEl) return;
|
|
301
302
|
if (this.options.mode === "canvas") {
|
|
302
|
-
|
|
303
|
-
const { cellWidth: r, startColFloat: s } = this.getCanvasMetrics(), a = (this.focusedColumn - s) * r;
|
|
304
|
-
this.viewportEl.style.cssText = `width:${r}px;left:${a}px;display:block`;
|
|
305
|
-
} else
|
|
306
|
-
this.viewportEl.style.display = "none";
|
|
303
|
+
this.viewportEl.style.display = "none";
|
|
307
304
|
return;
|
|
308
305
|
}
|
|
309
306
|
const t = this.minimapEl.offsetWidth, e = Math.max(t * this.scrollState.viewportRatio, 20), o = (t - e) * this.scrollState.positionRatio;
|
|
@@ -321,11 +318,11 @@ class F {
|
|
|
321
318
|
* Renders the visible portion of the table directly onto the canvas
|
|
322
319
|
*/
|
|
323
320
|
renderTableDirect(t, e) {
|
|
324
|
-
var
|
|
321
|
+
var S, y, P, k;
|
|
325
322
|
if (!this.canvasCtx) return;
|
|
326
|
-
const i = this.canvasCtx, { width: o, numCols:
|
|
327
|
-
if (f === 0 ||
|
|
328
|
-
const
|
|
323
|
+
const i = this.canvasCtx, { width: o, numCols: a, cellWidth: s, startCol: r, endCol: l, xOffset: c } = t, h = Array.from(this.table.querySelectorAll("tr")), f = h.length;
|
|
324
|
+
if (f === 0 || a === 0) return;
|
|
325
|
+
const p = Math.min(e * 0.15, 30), m = (e - p) / f, E = Math.min(m * 0.6, s * 0.15, 14), g = Math.min(p * 0.6, s * 0.15, 14), u = {
|
|
329
326
|
bg: "#ffffff",
|
|
330
327
|
headerBg: "#f1f5f9",
|
|
331
328
|
border: "#e2e8f0",
|
|
@@ -335,35 +332,35 @@ class F {
|
|
|
335
332
|
hoverFill: "rgba(59, 130, 246, 0.08)",
|
|
336
333
|
hoverStroke: "rgba(59, 130, 246, 0.3)"
|
|
337
334
|
};
|
|
338
|
-
i.fillStyle =
|
|
339
|
-
const
|
|
335
|
+
i.fillStyle = u.bg, i.fillRect(0, 0, o, e), i.fillStyle = u.headerBg, i.fillRect(0, 0, o, p);
|
|
336
|
+
const x = this.table.querySelector("thead tr") || h[0], L = x ? Array.from(x.querySelectorAll("th, td")) : [];
|
|
340
337
|
i.font = `bold ${g}px system-ui, sans-serif`, i.textBaseline = "middle";
|
|
341
|
-
for (let
|
|
342
|
-
const
|
|
343
|
-
if (
|
|
344
|
-
i.strokeStyle =
|
|
345
|
-
const
|
|
346
|
-
i.fillStyle =
|
|
338
|
+
for (let d = r; d < l; d++) {
|
|
339
|
+
const b = c + (d - r) * s;
|
|
340
|
+
if (b + s < 0 || b > o) continue;
|
|
341
|
+
i.strokeStyle = u.border, i.lineWidth = 1, i.strokeRect(b, 0, s, p);
|
|
342
|
+
const C = ((y = (S = L[d]) == null ? void 0 : S.textContent) == null ? void 0 : y.trim()) || `Col ${d + 1}`;
|
|
343
|
+
i.fillStyle = u.headerText, i.save(), i.beginPath(), i.rect(b + 2, 0, s - 4, p), i.clip(), i.fillText(C, b + 4, p / 2), i.restore();
|
|
347
344
|
}
|
|
348
345
|
i.font = `${E}px system-ui, sans-serif`;
|
|
349
|
-
for (let
|
|
350
|
-
const
|
|
351
|
-
if (
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
const
|
|
356
|
-
for (let
|
|
357
|
-
const
|
|
358
|
-
if (
|
|
359
|
-
i.strokeStyle =
|
|
360
|
-
const
|
|
361
|
-
|
|
346
|
+
for (let d = 0; d < h.length; d++) {
|
|
347
|
+
const b = h[d];
|
|
348
|
+
if (b.closest("thead")) continue;
|
|
349
|
+
const C = p + d * m;
|
|
350
|
+
if (C + m < 0 || C > e) continue;
|
|
351
|
+
d % 2 === 1 && (i.fillStyle = u.altRow, i.fillRect(0, C, o, m));
|
|
352
|
+
const R = Array.from(b.querySelectorAll("th, td"));
|
|
353
|
+
for (let M = r; M < l; M++) {
|
|
354
|
+
const w = c + (M - r) * s;
|
|
355
|
+
if (w + s < 0 || w > o) continue;
|
|
356
|
+
i.strokeStyle = u.border, i.lineWidth = 0.5, i.strokeRect(w, C, s, m);
|
|
357
|
+
const D = (k = (P = R[M]) == null ? void 0 : P.textContent) == null ? void 0 : k.trim();
|
|
358
|
+
D && (i.fillStyle = u.text, i.save(), i.beginPath(), i.rect(w + 2, C, s - 4, m), i.clip(), i.fillText(D, w + 4, C + m / 2), i.restore());
|
|
362
359
|
}
|
|
363
360
|
}
|
|
364
|
-
if (this.hoveredColumn >=
|
|
365
|
-
const
|
|
366
|
-
i.fillStyle =
|
|
361
|
+
if (this.hoveredColumn >= r && this.hoveredColumn < l) {
|
|
362
|
+
const d = c + (this.hoveredColumn - r) * s;
|
|
363
|
+
i.fillStyle = u.hoverFill, i.fillRect(d, 0, s, e), i.strokeStyle = u.hoverStroke, i.lineWidth = 1, i.strokeRect(d, 0, s, e);
|
|
367
364
|
}
|
|
368
365
|
}
|
|
369
366
|
/**
|
|
@@ -393,27 +390,22 @@ class F {
|
|
|
393
390
|
t.preventDefault(), this.expandCompact();
|
|
394
391
|
return;
|
|
395
392
|
}
|
|
396
|
-
if (this.
|
|
397
|
-
const { scrollWidth: e, clientWidth: i } = this.scrollContainer, o = this.
|
|
398
|
-
if (this.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
393
|
+
if (this.isCompactExpanding || this.isDragging || this.isPanning || this.wasPanning) return;
|
|
394
|
+
const { scrollWidth: e, clientWidth: i } = this.scrollContainer, o = e - i, a = this.minimapEl.getBoundingClientRect(), s = t.clientX - a.left;
|
|
395
|
+
if (this.options.mode === "canvas") {
|
|
396
|
+
const c = this.getColumnAtX(s);
|
|
397
|
+
if (c >= 0) {
|
|
398
|
+
const h = this.columns.length, f = e / h, m = (c + 0.5) * f - i / 2;
|
|
399
|
+
this.scrollContainer.scrollTo({
|
|
400
|
+
left: Math.max(0, Math.min(o, m)),
|
|
401
|
+
behavior: "smooth"
|
|
402
|
+
});
|
|
403
|
+
}
|
|
405
404
|
return;
|
|
406
405
|
}
|
|
407
|
-
const
|
|
408
|
-
let d;
|
|
409
|
-
if (l > 1) {
|
|
410
|
-
const g = this.scrollContainer.scrollLeft / Math.max(e - i, 1), c = 1 / l;
|
|
411
|
-
d = g * (1 - c) + a * c;
|
|
412
|
-
} else
|
|
413
|
-
d = a;
|
|
414
|
-
const f = d * e - i / 2, m = e - i, p = Math.max(0, Math.min(m, f));
|
|
406
|
+
const l = s / a.width * o;
|
|
415
407
|
this.scrollContainer.scrollTo({
|
|
416
|
-
left:
|
|
408
|
+
left: Math.max(0, Math.min(o, l)),
|
|
417
409
|
behavior: "smooth"
|
|
418
410
|
});
|
|
419
411
|
}
|
|
@@ -433,17 +425,14 @@ class F {
|
|
|
433
425
|
onPointerMove(t) {
|
|
434
426
|
if (this.isPotentialPan && !this.isPanning && this.canvasEl && this.zoomState.level > 1 && Math.abs(t.clientX - this.panStartX) > 3 && (this.isPanning = !0, this.canvasEl.style.cursor = "grabbing"), this.isPanning && this.canvasEl && this.minimapEl && this.scrollContainer) {
|
|
435
427
|
t.preventDefault();
|
|
436
|
-
const
|
|
437
|
-
this.scrollContainer.scrollLeft = Math.max(0, Math.min(
|
|
428
|
+
const c = t.clientX - this.panStartX, h = this.minimapEl.offsetWidth, { scrollWidth: f, clientWidth: p } = this.scrollContainer, m = f - p, E = c / h * m * this.zoomState.level, g = this.dragStartScrollLeft + E;
|
|
429
|
+
this.scrollContainer.scrollLeft = Math.max(0, Math.min(m, g)), this.updateScrollState(), this.updateViewport(), this.render();
|
|
438
430
|
return;
|
|
439
431
|
}
|
|
440
432
|
if (!this.isDragging || !this.minimapEl || !this.scrollContainer) return;
|
|
441
433
|
t.preventDefault();
|
|
442
|
-
const e
|
|
443
|
-
this.scrollContainer.scrollLeft = Math.max(
|
|
444
|
-
0,
|
|
445
|
-
Math.min(o, s)
|
|
446
|
-
), this.updateScrollState(), this.updateViewport();
|
|
434
|
+
const { scrollWidth: e, clientWidth: i } = this.scrollContainer, o = this.minimapEl.offsetWidth, a = e - i, r = (t.clientX - this.dragStartX) / o * a, l = this.dragStartScrollLeft + r;
|
|
435
|
+
this.scrollContainer.scrollLeft = Math.max(0, Math.min(a, l)), this.updateScrollState(), this.updateViewport();
|
|
447
436
|
}
|
|
448
437
|
/**
|
|
449
438
|
* Handles pointer up to end drag
|
|
@@ -471,19 +460,26 @@ class F {
|
|
|
471
460
|
* @param e - Wheel event
|
|
472
461
|
*/
|
|
473
462
|
onWheel(t) {
|
|
474
|
-
if (!this.options.zoomable || this.options.mode !== "canvas") return;
|
|
463
|
+
if (!this.options.zoomable || this.options.mode !== "canvas" || !this.canvasEl || !this.scrollContainer || !this.minimapEl) return;
|
|
475
464
|
t.preventDefault();
|
|
476
|
-
const e = -t.deltaY * this.options.zoomSpeed,
|
|
465
|
+
const e = this.zoomState.level, i = -t.deltaY * this.options.zoomSpeed, o = Math.max(
|
|
477
466
|
this.options.minZoom,
|
|
478
|
-
Math.min(this.options.maxZoom,
|
|
467
|
+
Math.min(this.options.maxZoom, e + i)
|
|
479
468
|
);
|
|
469
|
+
if (o === e) return;
|
|
470
|
+
const a = this.canvasEl.getBoundingClientRect(), s = t.clientX - a.left, r = this.minimapEl.offsetWidth, l = s / r, c = 1 / e, { scrollLeft: h, scrollWidth: f, clientWidth: p } = this.scrollContainer, m = Math.max(f - p, 1), E = h / m, u = (e > 1 ? E * (1 - c) : 0) + l * c;
|
|
480
471
|
this.zoomState = {
|
|
481
|
-
level:
|
|
472
|
+
level: o,
|
|
482
473
|
panX: 0,
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
474
|
+
isMinZoom: o <= this.options.minZoom,
|
|
475
|
+
isMaxZoom: o >= this.options.maxZoom
|
|
476
|
+
};
|
|
477
|
+
const x = 1 / o;
|
|
478
|
+
if (o > 1) {
|
|
479
|
+
const S = (u - l * x) / (1 - x), y = Math.max(0, Math.min(m, S * m));
|
|
480
|
+
this.scrollContainer.scrollLeft = y;
|
|
481
|
+
}
|
|
482
|
+
this.updateScrollState(), this.render();
|
|
487
483
|
}
|
|
488
484
|
/**
|
|
489
485
|
* Handles pointer down on canvas for drag start (scrolls table when zoomed)
|
|
@@ -511,7 +507,9 @@ class F {
|
|
|
511
507
|
* Expands the compact minimap and clears any pending collapse.
|
|
512
508
|
*/
|
|
513
509
|
expandCompact() {
|
|
514
|
-
!this.isCompactMode || !this.minimapEl || (this.clearCompactCollapseTimer(), this.applyCompactDimensions(!1),
|
|
510
|
+
!this.isCompactMode || !this.minimapEl || this.isCompactExpanding || (this.clearCompactCollapseTimer(), this.isCompactExpanding = !0, this.applyCompactDimensions(!1), setTimeout(() => {
|
|
511
|
+
this.isCompactExpanding = !1, !this.isDestroyed && !this.isCompactCollapsed && (this.updateScrollState(), this.render());
|
|
512
|
+
}, 200));
|
|
515
513
|
}
|
|
516
514
|
/**
|
|
517
515
|
* Collapses the compact minimap to the small dot handle.
|
|
@@ -597,9 +595,9 @@ class F {
|
|
|
597
595
|
*/
|
|
598
596
|
onResize() {
|
|
599
597
|
this.isDestroyed || (this.rafId !== null && cancelAnimationFrame(this.rafId), this.rafId = requestAnimationFrame(() => {
|
|
600
|
-
this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && this.minimapEl && (this.columnsEl.innerHTML = "", this.columns.forEach((
|
|
601
|
-
const
|
|
602
|
-
|
|
598
|
+
this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && this.minimapEl && (this.columnsEl.innerHTML = "", this.columns.forEach(() => {
|
|
599
|
+
const t = document.createElement("div");
|
|
600
|
+
t.className = "tm-column", this.columnsEl.appendChild(t);
|
|
603
601
|
})), this.rafId = null;
|
|
604
602
|
}));
|
|
605
603
|
}
|
|
@@ -607,9 +605,9 @@ class F {
|
|
|
607
605
|
* Handles table mutation events
|
|
608
606
|
*/
|
|
609
607
|
onTableMutation() {
|
|
610
|
-
this.isDestroyed || (this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && (this.columnsEl.innerHTML = "", this.columns.forEach((
|
|
611
|
-
const
|
|
612
|
-
|
|
608
|
+
this.isDestroyed || (this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && (this.columnsEl.innerHTML = "", this.columns.forEach(() => {
|
|
609
|
+
const t = document.createElement("div");
|
|
610
|
+
t.className = "tm-column", this.columnsEl.appendChild(t);
|
|
613
611
|
})));
|
|
614
612
|
}
|
|
615
613
|
/**
|
|
@@ -637,7 +635,7 @@ class F {
|
|
|
637
635
|
scrollToColumn(t, e = !0) {
|
|
638
636
|
if (!this.scrollContainer || t < 0 || t >= this.columns.length)
|
|
639
637
|
return;
|
|
640
|
-
const o = this.columns.slice(0, t).reduce((
|
|
638
|
+
const o = this.columns.slice(0, t).reduce((a, s) => a + s.width, 0);
|
|
641
639
|
this.scrollContainer.scrollTo({
|
|
642
640
|
left: o,
|
|
643
641
|
behavior: e ? "smooth" : "auto"
|
|
@@ -647,9 +645,9 @@ class F {
|
|
|
647
645
|
* Forces a refresh of the minimap
|
|
648
646
|
*/
|
|
649
647
|
refresh() {
|
|
650
|
-
this.isDestroyed || (this.scrollContainer = this.findScrollContainer(), this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && (this.columnsEl.innerHTML = "", this.columns.forEach((
|
|
651
|
-
const
|
|
652
|
-
|
|
648
|
+
this.isDestroyed || (this.scrollContainer = this.findScrollContainer(), this.detectColumns(), this.updateScrollState(), this.render(), this.options.mode === "columns" && this.columnsEl && (this.columnsEl.innerHTML = "", this.columns.forEach(() => {
|
|
649
|
+
const t = document.createElement("div");
|
|
650
|
+
t.className = "tm-column", this.columnsEl.appendChild(t);
|
|
653
651
|
})));
|
|
654
652
|
}
|
|
655
653
|
/**
|
|
@@ -664,21 +662,26 @@ class F {
|
|
|
664
662
|
* Sets the zoom level programmatically (canvas mode only)
|
|
665
663
|
*
|
|
666
664
|
* @param level - Zoom level (1 = no zoom)
|
|
667
|
-
* @param panX - Optional pan position (0-1)
|
|
665
|
+
* @param panX - Optional pan position (0-1), controls which part of table is visible
|
|
668
666
|
*/
|
|
669
667
|
setZoom(t, e) {
|
|
670
|
-
if (this.isDestroyed || this.options.mode !== "canvas") return;
|
|
668
|
+
if (this.isDestroyed || this.options.mode !== "canvas" || !this.scrollContainer) return;
|
|
671
669
|
const i = Math.max(
|
|
672
670
|
this.options.minZoom,
|
|
673
671
|
Math.min(this.options.maxZoom, t)
|
|
674
|
-
),
|
|
675
|
-
let s = e !== void 0 ? e :
|
|
676
|
-
s = Math.max(0, Math.min(
|
|
672
|
+
), o = 1 / i, a = 1 - o;
|
|
673
|
+
let s = e !== void 0 ? e : 0;
|
|
674
|
+
if (s = Math.max(0, Math.min(a, s)), this.zoomState = {
|
|
677
675
|
level: i,
|
|
678
|
-
panX:
|
|
676
|
+
panX: 0,
|
|
677
|
+
// Not used - panX is derived from scroll position
|
|
679
678
|
isMinZoom: i <= this.options.minZoom,
|
|
680
679
|
isMaxZoom: i >= this.options.maxZoom
|
|
681
|
-
},
|
|
680
|
+
}, i > 1 && s > 0) {
|
|
681
|
+
const { scrollWidth: r, clientWidth: l } = this.scrollContainer, c = Math.max(r - l, 1), h = s / (1 - o);
|
|
682
|
+
this.scrollContainer.scrollLeft = Math.max(0, Math.min(c, h * c));
|
|
683
|
+
} else i <= 1 && (this.scrollContainer.scrollLeft = 0);
|
|
684
|
+
this.updateScrollState(), this.render();
|
|
682
685
|
}
|
|
683
686
|
/**
|
|
684
687
|
* Resets zoom to default (shows full table overview)
|
|
@@ -696,8 +699,8 @@ class F {
|
|
|
696
699
|
if (this.isDestroyed || this.options.mode !== "canvas") return;
|
|
697
700
|
const i = this.columns.length;
|
|
698
701
|
if (i === 0) return;
|
|
699
|
-
const o = Math.max(0, Math.min(i - 1, t)), s = Math.max(o + 1, Math.min(i, e)) - o,
|
|
700
|
-
this.setZoom(
|
|
702
|
+
const o = Math.max(0, Math.min(i - 1, t)), s = Math.max(o + 1, Math.min(i, e)) - o, r = i / s, l = o / i;
|
|
703
|
+
this.setZoom(r, l);
|
|
701
704
|
}
|
|
702
705
|
/**
|
|
703
706
|
* Destroys the minimap instance and cleans up resources
|
|
@@ -706,12 +709,12 @@ class F {
|
|
|
706
709
|
this.isDestroyed || (this.isDestroyed = !0, this.clearCompactCollapseTimer(), this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null), this.scrollContainer && this.scrollContainer.removeEventListener("scroll", this.boundHandlers.onScroll), this.minimapEl && (this.minimapEl.removeEventListener("click", this.boundHandlers.onMinimapClick), this.minimapEl.removeEventListener("focusin", this.boundHandlers.onCompactFocusIn), this.minimapEl.removeEventListener("focusout", this.boundHandlers.onCompactFocusOut), this.minimapEl.removeEventListener("keydown", this.boundHandlers.onCompactKeyDown)), document.removeEventListener("click", this.boundHandlers.onDocumentClick), this.viewportEl && (this.viewportEl.removeEventListener("pointerdown", this.boundHandlers.onPointerDown), this.viewportEl.removeEventListener("wheel", this.boundHandlers.onWheel)), this.canvasEl && (this.canvasEl.removeEventListener("wheel", this.boundHandlers.onWheel), this.canvasEl.removeEventListener("pointerdown", this.boundHandlers.onCanvasPointerDown), this.canvasEl.removeEventListener("mousemove", this.boundHandlers.onCanvasMouseMove), this.canvasEl.removeEventListener("mouseleave", this.boundHandlers.onCanvasMouseLeave)), document.removeEventListener("pointermove", this.boundHandlers.onPointerMove), document.removeEventListener("pointerup", this.boundHandlers.onPointerUp), this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.mutationObserver && (this.mutationObserver.disconnect(), this.mutationObserver = null), this.minimapEl && this.minimapEl.parentNode && this.minimapEl.parentNode.removeChild(this.minimapEl), this.minimapEl = null, this.columnsEl = null, this.canvasEl = null, this.canvasCtx = null, this.viewportEl = null, this.scrollContainer = null, this.columns = []);
|
|
707
710
|
}
|
|
708
711
|
}
|
|
709
|
-
const I = ':root{--tm-background: #e3f2fd;--tm-border: #90caf9;--tm-viewport-color: rgba(25, 118, 210, .3);--tm-viewport-border: #1976d2;--tm-height: 40px;--tm-column-color: #64b5f6;--tm-column-gap: 1px;--tm-border-radius: 4px;--tm-canvas-empty: #bbdefb;--tm-canvas-filled: #1565c0;--tm-compact-dot-size: 5px;--tm-compact-transition-duration: .18s}@media (prefers-color-scheme: dark){:root{--tm-background: #1a237e;--tm-border: #3949ab;--tm-viewport-color: rgba(100, 180, 255, .3);--tm-viewport-border: #64b5f6;--tm-column-color: #3f51b5;--tm-canvas-empty: #283593;--tm-canvas-filled: #90caf9}}.tm-minimap{position:relative;width:var(--tm-minimap-width, 100%);height:var(--tm-minimap-height, var(--tm-height));background:var(--tm-background);border:1px solid var(--tm-border);border-radius:var(--tm-border-radius);box-sizing:border-box;overflow:hidden;user-select:none;-webkit-user-select:none;cursor:pointer;transition:width var(--tm-compact-transition-duration) ease-in-out,height var(--tm-compact-transition-duration) ease-in-out,opacity var(--tm-compact-transition-duration) ease-in-out,transform var(--tm-compact-transition-duration) ease-in-out,background-color var(--tm-compact-transition-duration) ease-in-out,border-color var(--tm-compact-transition-duration) ease-in-out,box-shadow var(--tm-compact-transition-duration) ease-in-out;will-change:width,height,opacity,transform}.tm-minimap--top{margin-bottom:8px}.tm-minimap--bottom{margin-top:8px}.tm-minimap--fixed{z-index:100;box-shadow:0 4px 12px #00000026;border-radius:8px}.tm-minimap--compact-collapsed{border-radius:999px}.tm-minimap--compact-expanded{border-radius:8px}.tm-minimap--compact>*{transition:opacity var(--tm-compact-transition-duration) ease-in-out}.tm-minimap--compact-collapsed{background:color-mix(in srgb,var(--tm-background) 60%,transparent);border-color:color-mix(in srgb,var(--tm-border) 45%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--tm-border) 20%,transparent);opacity:.
|
|
710
|
-
let
|
|
712
|
+
const I = ':root{--tm-background: #e3f2fd;--tm-border: #90caf9;--tm-viewport-color: rgba(25, 118, 210, .3);--tm-viewport-border: #1976d2;--tm-height: 40px;--tm-column-color: #64b5f6;--tm-column-gap: 1px;--tm-border-radius: 4px;--tm-canvas-empty: #bbdefb;--tm-canvas-filled: #1565c0;--tm-compact-dot-size: 5px;--tm-compact-transition-duration: .18s}@media (prefers-color-scheme: dark){:root{--tm-background: #1a237e;--tm-border: #3949ab;--tm-viewport-color: rgba(100, 180, 255, .3);--tm-viewport-border: #64b5f6;--tm-column-color: #3f51b5;--tm-canvas-empty: #283593;--tm-canvas-filled: #90caf9}}.tm-minimap{position:relative;width:var(--tm-minimap-width, 100%);height:var(--tm-minimap-height, var(--tm-height));background:var(--tm-background);border:1px solid var(--tm-border);border-radius:var(--tm-border-radius);box-sizing:border-box;overflow:hidden;user-select:none;-webkit-user-select:none;cursor:pointer;transition:width var(--tm-compact-transition-duration) ease-in-out,height var(--tm-compact-transition-duration) ease-in-out,opacity var(--tm-compact-transition-duration) ease-in-out,transform var(--tm-compact-transition-duration) ease-in-out,background-color var(--tm-compact-transition-duration) ease-in-out,border-color var(--tm-compact-transition-duration) ease-in-out,box-shadow var(--tm-compact-transition-duration) ease-in-out;will-change:width,height,opacity,transform}.tm-minimap--top{margin-bottom:8px}.tm-minimap--bottom{margin-top:8px}.tm-minimap--fixed{z-index:100;background:color-mix(in srgb,var(--tm-background) 72%,transparent);border-color:color-mix(in srgb,var(--tm-border) 72%,transparent);box-shadow:0 4px 12px #00000026;border-radius:8px;opacity:.78;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.tm-minimap--fixed:hover,.tm-minimap--fixed:focus-within{opacity:.96}.tm-minimap--compact-collapsed{border-radius:999px}.tm-minimap--compact-expanded{border-radius:8px}.tm-minimap--compact>*{transition:opacity var(--tm-compact-transition-duration) ease-in-out}.tm-minimap--compact-collapsed{background:color-mix(in srgb,var(--tm-background) 60%,transparent);border-color:color-mix(in srgb,var(--tm-border) 45%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--tm-border) 20%,transparent);opacity:.72;transform:translate(2px,2px)}.tm-minimap--compact-collapsed>*{opacity:0;pointer-events:none}.tm-minimap--compact-collapsed:after{content:"";position:absolute;right:calc((var(--tm-minimap-width, 24px) - var(--tm-compact-dot-size)) / 2);bottom:calc((var(--tm-minimap-height, 24px) - var(--tm-compact-dot-size)) / 2);width:var(--tm-compact-dot-size);height:var(--tm-compact-dot-size);border-radius:999px;background:color-mix(in srgb,var(--tm-viewport-border) 72%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--tm-viewport-border) 24%,transparent);opacity:.78;pointer-events:none;transition:opacity var(--tm-compact-transition-duration) ease-in-out,transform var(--tm-compact-transition-duration) ease-in-out,background-color var(--tm-compact-transition-duration) ease-in-out}.tm-minimap--compact-expanded{transform:translate(0)}.tm-minimap--compact-expanded:after{opacity:0;transform:scale(.7)}.tm-columns{display:flex;align-items:stretch;height:100%;gap:var(--tm-column-gap);padding:4px;box-sizing:border-box}.tm-column{flex:1 1 0;min-width:0;height:100%;background:var(--tm-column-color);border-radius:2px;transition:background-color .15s ease;cursor:pointer}.tm-column:hover{background:color-mix(in srgb,var(--tm-column-color) 80%,black)}.tm-canvas{width:100%;height:100%;display:block;cursor:pointer}.tm-viewport{position:absolute;top:0;height:100%;background:var(--tm-viewport-color);border-left:2px solid var(--tm-viewport-border);border-right:2px solid var(--tm-viewport-border);box-sizing:border-box;cursor:grab;transition:background-color .15s ease;z-index:10}.tm-viewport:hover{background:color-mix(in srgb,var(--tm-viewport-color) 100%,black 10%)}.tm-viewport--dragging{cursor:grabbing;background:color-mix(in srgb,var(--tm-viewport-color) 100%,black 20%);transition:none}.tm-viewport--disabled{cursor:default;pointer-events:none}.tm-minimap:focus-visible{outline:2px solid var(--tm-viewport-border);outline-offset:2px}.tm-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}';
|
|
713
|
+
let W = !1;
|
|
711
714
|
function Z() {
|
|
712
|
-
if (
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
+
if (W || typeof document > "u") return;
|
|
716
|
+
const v = document.createElement("style");
|
|
717
|
+
v.id = "table-minimap-styles", v.textContent = I, document.head.appendChild(v), W = !0;
|
|
715
718
|
}
|
|
716
719
|
Z();
|
|
717
720
|
export {
|