gitmaps 1.1.0 → 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.
Files changed (121) hide show
  1. package/README.md +267 -118
  2. package/app/[...slug]/page.client.tsx +1 -0
  3. package/app/[...slug]/page.tsx +6 -0
  4. package/app/analytics.db +0 -0
  5. package/app/api/analytics/route.ts +64 -0
  6. package/app/api/auth/positions/route.ts +95 -33
  7. package/app/api/build-info/route.ts +19 -0
  8. package/app/api/chat/route.ts +13 -2
  9. package/app/api/og-image/route.ts +14 -0
  10. package/app/api/repo/file-content/route.ts +73 -20
  11. package/app/api/repo/load/route.test.ts +62 -0
  12. package/app/api/repo/load/route.ts +41 -1
  13. package/app/api/repo/pdf-thumb/route.ts +127 -0
  14. package/app/api/repo/resolve-slug/route.ts +51 -0
  15. package/app/api/repo/tree/route.ts +188 -104
  16. package/app/api/version/route.ts +26 -0
  17. package/app/globals.css +5706 -4938
  18. package/app/layout.tsx +1279 -490
  19. package/app/lib/auto-arrange.test.ts +158 -0
  20. package/app/lib/auto-arrange.ts +147 -0
  21. package/app/lib/canvas-export.ts +358 -358
  22. package/app/lib/canvas.ts +625 -564
  23. package/app/lib/cards.tsx +1361 -916
  24. package/app/lib/chat.tsx +65 -9
  25. package/app/lib/code-editor.ts +86 -2
  26. package/app/lib/context.test.ts +32 -0
  27. package/app/lib/context.ts +19 -3
  28. package/app/lib/cursor-sharing.ts +34 -0
  29. package/app/lib/events.tsx +71 -93
  30. package/app/lib/export-canvas.ts +287 -0
  31. package/app/lib/file-card-plugin.ts +148 -148
  32. package/app/lib/file-modal.tsx +49 -0
  33. package/app/lib/file-preview.ts +486 -427
  34. package/app/lib/github-import.test.ts +424 -0
  35. package/app/lib/initial-route-hydration.test.ts +283 -0
  36. package/app/lib/initial-route-hydration.ts +202 -0
  37. package/app/lib/landing-reset.test.ts +99 -0
  38. package/app/lib/landing-reset.ts +106 -0
  39. package/app/lib/landing-shell.test.ts +75 -0
  40. package/app/lib/large-repo-optimization.ts +37 -0
  41. package/app/lib/layout-snapshots.ts +320 -0
  42. package/app/lib/loading.test.ts +69 -0
  43. package/app/lib/loading.tsx +160 -45
  44. package/app/lib/mount-cleanup.test.ts +52 -0
  45. package/app/lib/mount-cleanup.ts +34 -0
  46. package/app/lib/mount-init.test.ts +123 -0
  47. package/app/lib/mount-init.ts +107 -0
  48. package/app/lib/mount-lifecycle.test.ts +39 -0
  49. package/app/lib/mount-lifecycle.ts +12 -0
  50. package/app/lib/mount-route-wiring.test.ts +87 -0
  51. package/app/lib/mount-route-wiring.ts +84 -0
  52. package/app/lib/multi-repo.ts +14 -0
  53. package/app/lib/onboarding-tutorial.ts +278 -0
  54. package/app/lib/positions.ts +190 -121
  55. package/app/lib/recent-commits.test.ts +869 -0
  56. package/app/lib/recent-commits.ts +227 -0
  57. package/app/lib/repo-handoff.test.ts +23 -0
  58. package/app/lib/repo-handoff.ts +16 -0
  59. package/app/lib/repo-progressive.ts +119 -0
  60. package/app/lib/repo-select.test.ts +61 -0
  61. package/app/lib/repo-select.ts +74 -0
  62. package/app/lib/repo.tsx +1383 -987
  63. package/app/lib/role.ts +228 -0
  64. package/app/lib/route-catchall.test.ts +27 -0
  65. package/app/lib/route-repo-entry.test.ts +95 -0
  66. package/app/lib/route-repo-entry.ts +36 -0
  67. package/app/lib/router-contract.test.ts +22 -0
  68. package/app/lib/router-contract.ts +19 -0
  69. package/app/lib/shared-layout.test.ts +86 -0
  70. package/app/lib/shared-layout.ts +82 -0
  71. package/app/lib/status-bar.test.ts +118 -0
  72. package/app/lib/status-bar.ts +365 -128
  73. package/app/lib/sync-controls.test.ts +43 -0
  74. package/app/lib/sync-controls.tsx +303 -0
  75. package/app/lib/test-dom.ts +145 -0
  76. package/app/lib/test-fixtures/router-contract/[...slug]/page.tsx +3 -0
  77. package/app/lib/test-fixtures/router-contract/api/health/route.ts +3 -0
  78. package/app/lib/test-fixtures/router-contract/api/version/route.ts +3 -0
  79. package/app/lib/test-fixtures/router-contract/galaxy-canvas/page.tsx +3 -0
  80. package/app/lib/test-fixtures/router-contract/page.tsx +3 -0
  81. package/app/lib/transclusion-smoke.test.ts +163 -0
  82. package/app/lib/tutorial.ts +301 -0
  83. package/app/lib/version.ts +93 -0
  84. package/app/lib/viewport-culling.ts +740 -735
  85. package/app/lib/virtual-files.ts +456 -0
  86. package/app/lib/webgl-text.ts +189 -0
  87. package/app/lib/{galaxydraw-bridge.ts → xydraw-bridge.ts} +485 -482
  88. package/app/lib/{galaxydraw.test.ts → xydraw.test.ts} +228 -229
  89. package/app/og-image.png +0 -0
  90. package/app/page.client.tsx +70 -269
  91. package/app/page.tsx +15 -16
  92. package/app/state/machine.js +13 -0
  93. package/package.json +16 -7
  94. package/server.ts +10 -0
  95. package/app/[owner]/[repo]/page.tsx +0 -6
  96. package/app/[slug]/page.tsx +0 -6
  97. package/packages/galaxydraw/README.md +0 -296
  98. package/packages/galaxydraw/banner.png +0 -0
  99. package/packages/galaxydraw/demo/build-static.ts +0 -100
  100. package/packages/galaxydraw/demo/client.ts +0 -154
  101. package/packages/galaxydraw/demo/dist/client.js +0 -8
  102. package/packages/galaxydraw/demo/index.html +0 -256
  103. package/packages/galaxydraw/demo/server.ts +0 -96
  104. package/packages/galaxydraw/dist/index.js +0 -984
  105. package/packages/galaxydraw/dist/index.js.map +0 -16
  106. package/packages/galaxydraw/node_modules/.bin/tsc.bunx +0 -0
  107. package/packages/galaxydraw/node_modules/.bin/tsc.exe +0 -0
  108. package/packages/galaxydraw/node_modules/.bin/tsserver.bunx +0 -0
  109. package/packages/galaxydraw/node_modules/.bin/tsserver.exe +0 -0
  110. package/packages/galaxydraw/package.json +0 -49
  111. package/packages/galaxydraw/perf.test.ts +0 -284
  112. package/packages/galaxydraw/src/core/cards.ts +0 -435
  113. package/packages/galaxydraw/src/core/engine.ts +0 -339
  114. package/packages/galaxydraw/src/core/events.ts +0 -81
  115. package/packages/galaxydraw/src/core/layout.ts +0 -136
  116. package/packages/galaxydraw/src/core/minimap.ts +0 -216
  117. package/packages/galaxydraw/src/core/state.ts +0 -177
  118. package/packages/galaxydraw/src/core/viewport.ts +0 -106
  119. package/packages/galaxydraw/src/galaxydraw.css +0 -166
  120. package/packages/galaxydraw/src/index.ts +0 -40
  121. package/packages/galaxydraw/tsconfig.json +0 -30
@@ -1,148 +1,148 @@
1
- // @ts-nocheck
2
- /**
3
- * FileCardPlugin — bridges galaxydraw's CardPlugin interface with
4
- * the existing file card rendering in cards.tsx.
5
- *
6
- * Phase 4 of the GalaxyDraw migration:
7
- * - Wraps createAllFileCard() and createFileCard() as a CardPlugin
8
- * - Enables CardManager to handle drag, resize, z-order, selection
9
- * - Enables ViewportCuller to handle virtualized rendering
10
- *
11
- * The plugin doesn't replace cards.tsx — it delegates to it.
12
- * This allows incremental migration without breaking the existing flow.
13
- */
14
-
15
- import type { CardPlugin, CardData } from '../../packages/galaxydraw/src/core/cards';
16
-
17
- // ─── File Card Plugin ─────────────────────────────────────
18
-
19
- export const FILE_CARD_TYPE = 'file';
20
- export const DIFF_CARD_TYPE = 'diff';
21
-
22
- /**
23
- * Plugin for rendering source code file cards on the canvas.
24
- * Used by the "working tree" (all files) view.
25
- *
26
- * The render() method receives a CardData where:
27
- * - meta.file: the file data object (path, name, content, etc.)
28
- * - meta.ctx: the CanvasContext for interaction setup
29
- * - meta.savedSize: optional saved dimensions
30
- */
31
- export function createFileCardPlugin(): CardPlugin {
32
- return {
33
- type: FILE_CARD_TYPE,
34
-
35
- render(data: CardData): HTMLElement {
36
- const { file, ctx, savedSize } = data.meta || {};
37
- if (!file || !ctx) {
38
- // Fallback: empty placeholder card
39
- const el = document.createElement('div');
40
- el.className = 'file-card';
41
- el.textContent = 'Missing file data';
42
- return el;
43
- }
44
-
45
- // Dynamically import to avoid circular dependencies
46
- // The actual rendering is still in cards.tsx
47
- // skipInteraction=true: CardManager handles drag/resize/z-order
48
- const { createAllFileCard } = require('./cards');
49
- const card = createAllFileCard(ctx, file, data.x, data.y, savedSize, true);
50
-
51
- const { isDirCollapsed } = require('./card-groups');
52
- const fileDir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/')) : '.';
53
- if (isDirCollapsed(fileDir)) {
54
- card.style.display = 'none';
55
- }
56
-
57
- return card;
58
- },
59
-
60
- onResize(card: HTMLElement, width: number, height: number) {
61
- // Dispatch the resize event that cards.tsx already listens for
62
- const path = card.dataset.path;
63
- if (path) {
64
- card.dispatchEvent(new CustomEvent('card-resized', {
65
- detail: { path, width, height },
66
- }));
67
- }
68
- },
69
-
70
- onDestroy(card: HTMLElement) {
71
- // Clean up any scroll timers or event listeners
72
- // The card DOM is removed by CardManager, but we should
73
- // clean up any overlays or attached state
74
- },
75
-
76
- consumesWheel(target: HTMLElement): boolean {
77
- // File card bodies are scrollable — pass wheel events through
78
- return !!target.closest('.file-card-body');
79
- },
80
-
81
- consumesMouse(target: HTMLElement): boolean {
82
- // Buttons, links, and interactive elements within cards
83
- // should receive mouse events directly
84
- return !!(
85
- target.closest('button') ||
86
- target.closest('a') ||
87
- target.closest('.connect-btn') ||
88
- target.closest('.line-num') ||
89
- target.closest('.diff-hunk-header')
90
- );
91
- },
92
- };
93
- }
94
-
95
- /**
96
- * Plugin for rendering commit diff cards on the canvas.
97
- * Used by the "commit diff" view.
98
- */
99
- export function createDiffCardPlugin(): CardPlugin {
100
- return {
101
- type: DIFF_CARD_TYPE,
102
-
103
- render(data: CardData): HTMLElement {
104
- const { file, ctx, commitHash } = data.meta || {};
105
- if (!file || !ctx) {
106
- const el = document.createElement('div');
107
- el.className = 'file-card';
108
- el.textContent = 'Missing diff data';
109
- return el;
110
- }
111
-
112
- const { createFileCard } = require('./cards');
113
- const card = createFileCard(ctx, file, data.x, data.y, commitHash, true);
114
-
115
- const { isDirCollapsed } = require('./card-groups');
116
- const fileDir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/')) : '.';
117
- if (isDirCollapsed(fileDir)) {
118
- card.style.display = 'none';
119
- }
120
-
121
- return card;
122
- },
123
-
124
- onResize(card: HTMLElement, width: number, height: number) {
125
- const path = card.dataset.path;
126
- if (path) {
127
- card.dispatchEvent(new CustomEvent('card-resized', {
128
- detail: { path, width, height },
129
- }));
130
- }
131
- },
132
-
133
- onDestroy() { },
134
-
135
- consumesWheel(target: HTMLElement): boolean {
136
- return !!target.closest('.file-card-body');
137
- },
138
-
139
- consumesMouse(target: HTMLElement): boolean {
140
- return !!(
141
- target.closest('button') ||
142
- target.closest('a') ||
143
- target.closest('.connect-btn') ||
144
- target.closest('.diff-hunk-header')
145
- );
146
- },
147
- };
148
- }
1
+ // @ts-nocheck
2
+ /**
3
+ * FileCardPlugin — bridges xydraw's CardPlugin interface with
4
+ * the existing file card rendering in cards.tsx.
5
+ *
6
+ * Phase 4 of the GalaxyDraw migration:
7
+ * - Wraps createAllFileCard() and createFileCard() as a CardPlugin
8
+ * - Enables CardManager to handle drag, resize, z-order, selection
9
+ * - Enables ViewportCuller to handle virtualized rendering
10
+ *
11
+ * The plugin doesn't replace cards.tsx — it delegates to it.
12
+ * This allows incremental migration without breaking the existing flow.
13
+ */
14
+
15
+ import type { CardPlugin, CardData } from '../../packages/galaxydraw/src/core/cards';
16
+
17
+ // ─── File Card Plugin ─────────────────────────────────────
18
+
19
+ export const FILE_CARD_TYPE = 'file';
20
+ export const DIFF_CARD_TYPE = 'diff';
21
+
22
+ /**
23
+ * Plugin for rendering source code file cards on the canvas.
24
+ * Used by the "working tree" (all files) view.
25
+ *
26
+ * The render() method receives a CardData where:
27
+ * - meta.file: the file data object (path, name, content, etc.)
28
+ * - meta.ctx: the CanvasContext for interaction setup
29
+ * - meta.savedSize: optional saved dimensions
30
+ */
31
+ export function createFileCardPlugin(): CardPlugin {
32
+ return {
33
+ type: FILE_CARD_TYPE,
34
+
35
+ render(data: CardData): HTMLElement {
36
+ const { file, ctx, savedSize } = data.meta || {};
37
+ if (!file || !ctx) {
38
+ // Fallback: empty placeholder card
39
+ const el = document.createElement('div');
40
+ el.className = 'file-card';
41
+ el.textContent = 'Missing file data';
42
+ return el;
43
+ }
44
+
45
+ // Dynamically import to avoid circular dependencies
46
+ // The actual rendering is still in cards.tsx
47
+ // skipInteraction=true: CardManager handles drag/resize/z-order
48
+ const { createAllFileCard } = require('./cards');
49
+ const card = createAllFileCard(ctx, file, data.x, data.y, savedSize, true);
50
+
51
+ const { isDirCollapsed } = require('./card-groups');
52
+ const fileDir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/')) : '.';
53
+ if (isDirCollapsed(fileDir)) {
54
+ card.style.display = 'none';
55
+ }
56
+
57
+ return card;
58
+ },
59
+
60
+ onResize(card: HTMLElement, width: number, height: number) {
61
+ // Dispatch the resize event that cards.tsx already listens for
62
+ const path = card.dataset.path;
63
+ if (path) {
64
+ card.dispatchEvent(new CustomEvent('card-resized', {
65
+ detail: { path, width, height },
66
+ }));
67
+ }
68
+ },
69
+
70
+ onDestroy(card: HTMLElement) {
71
+ // Clean up any scroll timers or event listeners
72
+ // The card DOM is removed by CardManager, but we should
73
+ // clean up any overlays or attached state
74
+ },
75
+
76
+ consumesWheel(target: HTMLElement): boolean {
77
+ // File card bodies are scrollable — pass wheel events through
78
+ return !!target.closest('.file-card-body');
79
+ },
80
+
81
+ consumesMouse(target: HTMLElement): boolean {
82
+ // Buttons, links, and interactive elements within cards
83
+ // should receive mouse events directly
84
+ return !!(
85
+ target.closest('button') ||
86
+ target.closest('a') ||
87
+ target.closest('.connect-btn') ||
88
+ target.closest('.line-num') ||
89
+ target.closest('.diff-hunk-header')
90
+ );
91
+ },
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Plugin for rendering commit diff cards on the canvas.
97
+ * Used by the "commit diff" view.
98
+ */
99
+ export function createDiffCardPlugin(): CardPlugin {
100
+ return {
101
+ type: DIFF_CARD_TYPE,
102
+
103
+ render(data: CardData): HTMLElement {
104
+ const { file, ctx, commitHash } = data.meta || {};
105
+ if (!file || !ctx) {
106
+ const el = document.createElement('div');
107
+ el.className = 'file-card';
108
+ el.textContent = 'Missing diff data';
109
+ return el;
110
+ }
111
+
112
+ const { createFileCard } = require('./cards');
113
+ const card = createFileCard(ctx, file, data.x, data.y, commitHash, true);
114
+
115
+ const { isDirCollapsed } = require('./card-groups');
116
+ const fileDir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/')) : '.';
117
+ if (isDirCollapsed(fileDir)) {
118
+ card.style.display = 'none';
119
+ }
120
+
121
+ return card;
122
+ },
123
+
124
+ onResize(card: HTMLElement, width: number, height: number) {
125
+ const path = card.dataset.path;
126
+ if (path) {
127
+ card.dispatchEvent(new CustomEvent('card-resized', {
128
+ detail: { path, width, height },
129
+ }));
130
+ }
131
+ },
132
+
133
+ onDestroy() { },
134
+
135
+ consumesWheel(target: HTMLElement): boolean {
136
+ return !!target.closest('.file-card-body');
137
+ },
138
+
139
+ consumesMouse(target: HTMLElement): boolean {
140
+ return !!(
141
+ target.closest('button') ||
142
+ target.closest('a') ||
143
+ target.closest('.connect-btn') ||
144
+ target.closest('.diff-hunk-header')
145
+ );
146
+ },
147
+ };
148
+ }
@@ -14,6 +14,7 @@ import { renderBreadcrumbs } from './breadcrumbs';
14
14
  import { renderSymbolOutline } from './symbol-outline';
15
15
  import { loadDraft, clearDraft, startAutoSave, stopAutoSave } from './auto-save';
16
16
  import { isEditingAllowed, getProductionEditorNotice } from './production-mode';
17
+ import { onEditorSync, broadcastEditorSync, type EditorSyncData } from './cursor-sharing';
17
18
 
18
19
  // ─── File expand modal ──────────────────────────────────
19
20
  export function openFileModal(ctx: CanvasContext, file: any, initialView?: string, initialLine?: number) {
@@ -76,6 +77,41 @@ export function openFileModal(ctx: CanvasContext, file: any, initialView?: strin
76
77
  let onNavKey: ((e: KeyboardEvent) => void) | null = null;
77
78
  let originalContent = file.content || '';
78
79
 
80
+ let editorSyncCleanup: (() => void) | null = null;
81
+ const remoteCursorsMap = new Map<string, EditorSyncData>();
82
+ let typingTimeouts = new Map<string, any>();
83
+
84
+ editorSyncCleanup = onEditorSync(data => {
85
+ // use Active Tab's path instead of initial file path incase it switched
86
+ const activeTab = getActiveTab();
87
+ const activePath = activeTab ? activeTab.path : file.path;
88
+
89
+ if (data.file === activePath && currentView === 'edit') {
90
+ remoteCursorsMap.set(data.peerId, data);
91
+
92
+ if (data.typing) {
93
+ if (typingTimeouts.has(data.peerId)) clearTimeout(typingTimeouts.get(data.peerId));
94
+ typingTimeouts.set(data.peerId, setTimeout(() => {
95
+ const cursor = remoteCursorsMap.get(data.peerId);
96
+ if (cursor) {
97
+ cursor.typing = false;
98
+ updateRemoteCursors();
99
+ }
100
+ }, 1000));
101
+ }
102
+
103
+ updateRemoteCursors();
104
+ }
105
+ });
106
+
107
+ function updateRemoteCursors() {
108
+ const editContainer = document.getElementById('modalEditContainer');
109
+ const editor = (editContainer as any)?._cmEditor;
110
+ if (editor) {
111
+ editor.setRemoteCursors(Array.from(remoteCursorsMap.values()));
112
+ }
113
+ }
114
+
79
115
  function hasUnsavedChanges(): boolean {
80
116
  if (currentView !== 'edit') return false;
81
117
  const editContainer = document.getElementById('modalEditContainer');
@@ -97,6 +133,11 @@ export function openFileModal(ctx: CanvasContext, file: any, initialView?: strin
97
133
  document.removeEventListener('keydown', onEsc);
98
134
  if (onNavKey) document.removeEventListener('keydown', onNavKey);
99
135
 
136
+ if (editorSyncCleanup) {
137
+ editorSyncCleanup();
138
+ editorSyncCleanup = null;
139
+ }
140
+
100
141
  // Stop auto-save timer
101
142
  stopAutoSave();
102
143
 
@@ -445,12 +486,20 @@ export function openFileModal(ctx: CanvasContext, file: any, initialView?: strin
445
486
  onCursorMove: (line, col) => {
446
487
  if (lineInfo) lineInfo.textContent = `Line ${line}, Col ${col}`;
447
488
  },
489
+ onSelectionChange: (selections, isTyping) => {
490
+ const activeTab = getActiveTab();
491
+ const activePath = activeTab ? activeTab.path : file.path;
492
+ broadcastEditorSync(activePath, selections, isTyping);
493
+ }
448
494
  });
449
495
 
450
496
  // Store editor reference for content access
451
497
  (editContainer as any)._cmEditor = editor;
452
498
  editor.focus();
453
499
 
500
+ // Reapply any known remote cursors for this new view
501
+ updateRemoteCursors();
502
+
454
503
  // Scroll to initial line if provided (preserves canvas view position)
455
504
  if (initialLine && initialLine > 1) {
456
505
  requestAnimationFrame(() => {