gitmaps 1.1.17 → 1.1.18

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/app/analytics.db CHANGED
Binary file
@@ -170,6 +170,12 @@ function getSavedScrollTop(ctx: CanvasContext, path: string): number {
170
170
  return saved?.x || 0;
171
171
  }
172
172
 
173
+ function resolvePreviewFile(ctx: CanvasContext, path: string, fallback?: any) {
174
+ const commitFile = ctx.commitFilesData?.find(f => f.path === path) || null;
175
+ const allFile = ctx.allFilesData?.find(f => f.path === path) || null;
176
+ return commitFile || fallback || allFile || null;
177
+ }
178
+
173
179
  /**
174
180
  * Create a lightweight pill placeholder for a file.
175
181
  * ~3 DOM nodes vs ~100+ for a full card = massive perf win at low zoom.
@@ -206,9 +212,14 @@ function createPillCard(ctx: CanvasContext, file: any, path: string, x: number,
206
212
 
207
213
  const diffOverlay = document.createElement('div');
208
214
  diffOverlay.className = 'file-pill-diff-overlay';
209
- diffOverlay.style.cssText = 'position:absolute;top:10px;right:15px;bottom:10px;width:12px;pointer-events:none;z-index:2;';
215
+ diffOverlay.style.cssText = 'position:absolute;top:10px;right:26px;bottom:10px;width:12px;pointer-events:none;z-index:2;';
210
216
  pill.appendChild(diffOverlay);
211
217
 
218
+ const scrollOverlay = document.createElement('div');
219
+ scrollOverlay.className = 'file-pill-scroll-overlay';
220
+ scrollOverlay.style.cssText = 'position:absolute;top:10px;right:15px;bottom:10px;width:9px;pointer-events:auto;z-index:3;';
221
+ pill.appendChild(scrollOverlay);
222
+
212
223
  (pill as any)._fileData = file;
213
224
  updatePillCardLayout(ctx, pill, zoom, isChanged);
214
225
 
@@ -229,7 +240,8 @@ function updatePillCardLayout(ctx: CanvasContext, pill: HTMLElement, zoom: numbe
229
240
  const path = pill.dataset.path || '';
230
241
  const canvas = pill.querySelector('.file-pill-canvas') as HTMLCanvasElement | null;
231
242
  const diffOverlay = pill.querySelector('.file-pill-diff-overlay') as HTMLElement | null;
232
- const file = (pill as any)._fileData || ctx.allFilesData?.find(f => f.path === path) || ctx.commitFilesData?.find(f => f.path === path) || null;
243
+ const scrollOverlay = pill.querySelector('.file-pill-scroll-overlay') as HTMLElement | null;
244
+ const file = resolvePreviewFile(ctx, path, (pill as any)._fileData);
233
245
  const changed = isChanged ?? pill.dataset.changed === 'true';
234
246
  const scrollTop = getSavedScrollTop(ctx, path);
235
247
  pill.dataset.zoomBucket = zoom.toFixed(3);
@@ -247,25 +259,27 @@ function updatePillCardLayout(ctx: CanvasContext, pill: HTMLElement, zoom: numbe
247
259
  isChanged: changed,
248
260
  });
249
261
 
262
+ const metrics = getPreviewScrollMetrics(file, h, zoom, scrollTop);
263
+
250
264
  if (diffOverlay) {
251
- const metrics = getPreviewScrollMetrics(file, h, zoom, scrollTop);
252
265
  const markers = collectPreviewDiffMarkers(file, metrics.totalLines);
253
266
  diffOverlay.innerHTML = '';
254
267
  diffOverlay.style.top = `${metrics.trackPadding}px`;
255
268
  diffOverlay.style.bottom = `${metrics.trackPadding}px`;
256
- diffOverlay.style.right = '15px';
269
+ diffOverlay.style.right = '26px';
257
270
  diffOverlay.style.width = '12px';
258
271
  diffOverlay.style.pointerEvents = 'auto';
259
272
 
260
273
  for (const marker of markers) {
261
274
  const btn = document.createElement('button');
262
- const markerHeight = marker.height === 1 ? metrics.trackHeight : 8;
275
+ const markerHeight = marker.height === 1 ? metrics.trackHeight : 10;
263
276
  const y = marker.height === 1 ? 0 : marker.ratio * Math.max(0, metrics.trackHeight - markerHeight);
264
277
  btn.type = 'button';
265
278
  btn.className = 'file-pill-diff-marker';
266
279
  btn.title = marker.color === '#22c55e' ? 'Jump to added lines' : 'Jump to deleted lines';
267
- btn.style.cssText = `position:absolute;left:0;width:12px;height:${markerHeight}px;top:${y}px;border:none;border-radius:3px;background:${marker.color};box-shadow:0 0 0 1px rgba(255,255,255,0.18),0 0 10px ${marker.color}66;cursor:pointer;padding:0;pointer-events:auto;`;
280
+ btn.style.cssText = `position:absolute;left:0;width:12px;height:${markerHeight}px;top:${y}px;border:none;border-radius:3px;background:${marker.color};box-shadow:0 0 0 1px rgba(255,255,255,0.28),0 0 10px ${marker.color}88;cursor:pointer;padding:0;pointer-events:auto;opacity:1;`;
268
281
  btn.addEventListener('mousedown', (e) => {
282
+ e.preventDefault();
269
283
  e.stopPropagation();
270
284
  });
271
285
  btn.addEventListener('click', (e) => {
@@ -285,6 +299,71 @@ function updatePillCardLayout(ctx: CanvasContext, pill: HTMLElement, zoom: numbe
285
299
  diffOverlay.appendChild(btn);
286
300
  }
287
301
  }
302
+
303
+ if (scrollOverlay) {
304
+ scrollOverlay.innerHTML = '';
305
+ scrollOverlay.style.top = `${metrics.trackPadding}px`;
306
+ scrollOverlay.style.bottom = `${metrics.trackPadding}px`;
307
+
308
+ const track = document.createElement('button');
309
+ track.type = 'button';
310
+ track.className = 'file-pill-scroll-track';
311
+ track.title = 'Scroll preview';
312
+ track.style.cssText = `position:absolute;inset:0;border:none;border-radius:999px;background:rgba(255,255,255,0.08);padding:0;cursor:pointer;`;
313
+ track.addEventListener('mousedown', (e) => {
314
+ e.preventDefault();
315
+ e.stopPropagation();
316
+ const rect = track.getBoundingClientRect();
317
+ const thumbHeight = Math.max(18, metrics.thumbHeight);
318
+ const localY = Math.max(0, Math.min(rect.height, e.clientY - rect.top));
319
+ const thumbCenter = localY - thumbHeight / 2;
320
+ const ratio = rect.height > thumbHeight ? Math.max(0, Math.min(1, thumbCenter / (rect.height - thumbHeight))) : 0;
321
+ const next = ratio * metrics.maxScroll;
322
+ const key = `scroll:${path}`;
323
+ const existing = ctx.positions.get(key) || {};
324
+ ctx.positions.set(key, { ...existing, x: next, y: existing.y || 0 });
325
+ try {
326
+ const { debounceSaveScroll } = require('./cards');
327
+ debounceSaveScroll(ctx, path, next);
328
+ } catch { }
329
+ updatePillCardLayout(ctx, pill, zoom, changed);
330
+ });
331
+ scrollOverlay.appendChild(track);
332
+
333
+ const thumb = document.createElement('div');
334
+ thumb.className = 'file-pill-scroll-thumb';
335
+ thumb.style.cssText = `position:absolute;left:0;width:9px;height:${metrics.thumbHeight}px;top:${Math.max(0, metrics.thumbY - metrics.trackPadding)}px;border-radius:999px;background:rgba(196,181,253,0.98);box-shadow:0 0 0 1px rgba(255,255,255,0.24),0 4px 12px rgba(0,0,0,0.35);cursor:grab;`;
336
+ thumb.addEventListener('mousedown', (e) => {
337
+ e.preventDefault();
338
+ e.stopPropagation();
339
+ const startY = e.clientY;
340
+ const startScroll = scrollTop;
341
+ const dragTravel = Math.max(1, metrics.trackHeight - metrics.thumbHeight);
342
+ const maxScroll = Math.max(0, metrics.maxScroll);
343
+
344
+ const onMove = (moveEvent: MouseEvent) => {
345
+ moveEvent.preventDefault();
346
+ const deltaY = moveEvent.clientY - startY;
347
+ const next = maxScroll > 0 ? Math.max(0, Math.min(maxScroll, startScroll + (deltaY / dragTravel) * maxScroll)) : 0;
348
+ const key = `scroll:${path}`;
349
+ const existing = ctx.positions.get(key) || {};
350
+ ctx.positions.set(key, { ...existing, x: next, y: existing.y || 0 });
351
+ updatePillCardLayout(ctx, pill, zoom, changed);
352
+ };
353
+ const onUp = () => {
354
+ const finalScroll = getSavedScrollTop(ctx, path);
355
+ try {
356
+ const { debounceSaveScroll } = require('./cards');
357
+ debounceSaveScroll(ctx, path, finalScroll);
358
+ } catch { }
359
+ window.removeEventListener('mousemove', onMove);
360
+ window.removeEventListener('mouseup', onUp);
361
+ };
362
+ window.addEventListener('mousemove', onMove);
363
+ window.addEventListener('mouseup', onUp);
364
+ });
365
+ scrollOverlay.appendChild(thumb);
366
+ }
288
367
  }
289
368
 
290
369
  /**
@@ -528,7 +607,7 @@ export function performViewportCulling(ctx: CanvasContext) {
528
607
  );
529
608
 
530
609
  if (inView) {
531
- const file = ctx.allFilesData?.find(f => f.path === path) || ctx.commitFilesData?.find(f => f.path === path) || null;
610
+ const file = resolvePreviewFile(ctx, path);
532
611
  const pill = createPillCard(ctx, file, path, x, y, w, h, isChanged, zoom, true);
533
612
  if (isChanged) pill.dataset.changed = 'true';
534
613
  ctx.canvas.appendChild(pill);
@@ -707,7 +786,7 @@ export function setupPillInteraction(ctx: CanvasContext) {
707
786
  const path = pill.dataset.path || '';
708
787
  if (!path) return;
709
788
 
710
- const file = (pill as any)._fileData || ctx.allFilesData?.find(f => f.path === path) || ctx.commitFilesData?.find(f => f.path === path) || null;
789
+ const file = resolvePreviewFile(ctx, path, (pill as any)._fileData);
711
790
  const zoom = ctx.snap().context.zoom || 1;
712
791
  const height = parseFloat(pill.style.height) || 700;
713
792
  const current = getSavedScrollTop(ctx, path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitmaps",
3
- "version": "1.1.17",
3
+ "version": "1.1.18",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "gitmaps": "cli.ts"