gitmaps 1.0.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 (145) hide show
  1. package/README.md +265 -122
  2. package/app/[...slug]/page.client.tsx +1 -0
  3. package/app/[...slug]/page.tsx +6 -0
  4. package/app/[owner]/[repo]/page.client.tsx +5 -0
  5. package/app/[slug]/page.client.tsx +5 -0
  6. package/app/analytics.db +0 -0
  7. package/app/api/analytics/route.ts +64 -0
  8. package/app/api/auth/positions/route.ts +95 -33
  9. package/app/api/build-info/route.ts +19 -0
  10. package/app/api/chat/route.ts +13 -2
  11. package/app/api/manifest.json/route.ts +20 -0
  12. package/app/api/og-image/route.ts +14 -0
  13. package/app/api/pwa-icon/route.ts +14 -0
  14. package/app/api/repo/clone-stream/route.ts +20 -12
  15. package/app/api/repo/file-content/route.ts +73 -20
  16. package/app/api/repo/imports/route.ts +21 -3
  17. package/app/api/repo/list/route.ts +30 -0
  18. package/app/api/repo/load/route.test.ts +62 -0
  19. package/app/api/repo/load/route.ts +41 -1
  20. package/app/api/repo/pdf-thumb/route.ts +127 -0
  21. package/app/api/repo/resolve-slug/route.ts +51 -0
  22. package/app/api/repo/tree/route.ts +188 -104
  23. package/app/api/repo/upload/route.ts +6 -9
  24. package/app/api/sw.js/route.ts +70 -0
  25. package/app/api/version/route.ts +26 -0
  26. package/app/galaxy-canvas/page.client.tsx +2 -0
  27. package/app/galaxy-canvas/page.tsx +5 -0
  28. package/app/globals.css +5844 -4694
  29. package/app/icon.png +0 -0
  30. package/app/layout.tsx +1284 -467
  31. package/app/lib/auto-arrange.test.ts +158 -0
  32. package/app/lib/auto-arrange.ts +147 -0
  33. package/app/lib/canvas-export.ts +358 -358
  34. package/app/lib/canvas-text.ts +4 -72
  35. package/app/lib/canvas.ts +625 -564
  36. package/app/lib/card-arrangement.ts +21 -7
  37. package/app/lib/card-context-menu.tsx +2 -2
  38. package/app/lib/card-groups.ts +9 -2
  39. package/app/lib/cards.tsx +1361 -914
  40. package/app/lib/chat.tsx +65 -9
  41. package/app/lib/code-editor.ts +86 -2
  42. package/app/lib/connections.tsx +34 -43
  43. package/app/lib/context.test.ts +32 -0
  44. package/app/lib/context.ts +19 -3
  45. package/app/lib/cursor-sharing.ts +34 -0
  46. package/app/lib/events.tsx +76 -73
  47. package/app/lib/export-canvas.ts +287 -0
  48. package/app/lib/file-card-plugin.ts +148 -134
  49. package/app/lib/file-modal.tsx +49 -0
  50. package/app/lib/file-preview.ts +486 -400
  51. package/app/lib/github-import.test.ts +424 -0
  52. package/app/lib/global-search.ts +48 -27
  53. package/app/lib/initial-route-hydration.test.ts +283 -0
  54. package/app/lib/initial-route-hydration.ts +202 -0
  55. package/app/lib/landing-reset.test.ts +99 -0
  56. package/app/lib/landing-reset.ts +106 -0
  57. package/app/lib/landing-shell.test.ts +75 -0
  58. package/app/lib/large-repo-optimization.ts +37 -0
  59. package/app/lib/layers.tsx +17 -18
  60. package/app/lib/layout-snapshots.ts +320 -0
  61. package/app/lib/loading.test.ts +69 -0
  62. package/app/lib/loading.tsx +160 -45
  63. package/app/lib/mount-cleanup.test.ts +52 -0
  64. package/app/lib/mount-cleanup.ts +34 -0
  65. package/app/lib/mount-init.test.ts +123 -0
  66. package/app/lib/mount-init.ts +107 -0
  67. package/app/lib/mount-lifecycle.test.ts +39 -0
  68. package/app/lib/mount-lifecycle.ts +12 -0
  69. package/app/lib/mount-route-wiring.test.ts +87 -0
  70. package/app/lib/mount-route-wiring.ts +84 -0
  71. package/app/lib/multi-repo.ts +14 -0
  72. package/app/lib/onboarding-tutorial.ts +278 -0
  73. package/app/lib/perf-overlay.ts +78 -0
  74. package/app/lib/positions.ts +191 -122
  75. package/app/lib/recent-commits.test.ts +869 -0
  76. package/app/lib/recent-commits.ts +227 -0
  77. package/app/lib/repo-handoff.test.ts +23 -0
  78. package/app/lib/repo-handoff.ts +16 -0
  79. package/app/lib/repo-progressive.ts +119 -0
  80. package/app/lib/repo-select.test.ts +61 -0
  81. package/app/lib/repo-select.ts +74 -0
  82. package/app/lib/repo.tsx +1383 -977
  83. package/app/lib/role.ts +228 -0
  84. package/app/lib/route-catchall.test.ts +27 -0
  85. package/app/lib/route-repo-entry.test.ts +95 -0
  86. package/app/lib/route-repo-entry.ts +36 -0
  87. package/app/lib/router-contract.test.ts +22 -0
  88. package/app/lib/router-contract.ts +19 -0
  89. package/app/lib/shared-layout.test.ts +86 -0
  90. package/app/lib/shared-layout.ts +82 -0
  91. package/app/lib/shortcuts-panel.ts +2 -0
  92. package/app/lib/status-bar.test.ts +118 -0
  93. package/app/lib/status-bar.ts +365 -128
  94. package/app/lib/sync-controls.test.ts +43 -0
  95. package/app/lib/sync-controls.tsx +303 -0
  96. package/app/lib/test-dom.ts +145 -0
  97. package/app/lib/test-fixtures/router-contract/[...slug]/page.tsx +3 -0
  98. package/app/lib/test-fixtures/router-contract/api/health/route.ts +3 -0
  99. package/app/lib/test-fixtures/router-contract/api/version/route.ts +3 -0
  100. package/app/lib/test-fixtures/router-contract/galaxy-canvas/page.tsx +3 -0
  101. package/app/lib/test-fixtures/router-contract/page.tsx +3 -0
  102. package/app/lib/transclusion-smoke.test.ts +163 -0
  103. package/app/lib/tutorial.ts +301 -0
  104. package/app/lib/version.ts +93 -0
  105. package/app/lib/viewport-culling.ts +740 -728
  106. package/app/lib/virtual-files.ts +456 -0
  107. package/app/lib/webgl-text.ts +189 -0
  108. package/app/lib/{galaxydraw-bridge.ts → xydraw-bridge.ts} +485 -477
  109. package/app/lib/{galaxydraw.test.ts → xydraw.test.ts} +228 -229
  110. package/app/og-image.png +0 -0
  111. package/app/page.client.tsx +70 -215
  112. package/app/page.tsx +27 -92
  113. package/app/state/machine.js +13 -0
  114. package/banner.png +0 -0
  115. package/package.json +17 -8
  116. package/server.ts +11 -1
  117. package/app/api/connections/route.ts +0 -72
  118. package/app/api/positions/route.ts +0 -80
  119. package/app/api/repo/browse/route.ts +0 -55
  120. package/app/lib/pr-review.ts +0 -374
  121. package/packages/galaxydraw/README.md +0 -296
  122. package/packages/galaxydraw/banner.png +0 -0
  123. package/packages/galaxydraw/demo/build-static.ts +0 -100
  124. package/packages/galaxydraw/demo/client.ts +0 -154
  125. package/packages/galaxydraw/demo/dist/client.js +0 -8
  126. package/packages/galaxydraw/demo/index.html +0 -256
  127. package/packages/galaxydraw/demo/server.ts +0 -96
  128. package/packages/galaxydraw/dist/index.js +0 -984
  129. package/packages/galaxydraw/dist/index.js.map +0 -16
  130. package/packages/galaxydraw/node_modules/.bin/tsc.bunx +0 -0
  131. package/packages/galaxydraw/node_modules/.bin/tsc.exe +0 -0
  132. package/packages/galaxydraw/node_modules/.bin/tsserver.bunx +0 -0
  133. package/packages/galaxydraw/node_modules/.bin/tsserver.exe +0 -0
  134. package/packages/galaxydraw/package.json +0 -49
  135. package/packages/galaxydraw/perf.test.ts +0 -284
  136. package/packages/galaxydraw/src/core/cards.ts +0 -435
  137. package/packages/galaxydraw/src/core/engine.ts +0 -339
  138. package/packages/galaxydraw/src/core/events.ts +0 -81
  139. package/packages/galaxydraw/src/core/layout.ts +0 -136
  140. package/packages/galaxydraw/src/core/minimap.ts +0 -216
  141. package/packages/galaxydraw/src/core/state.ts +0 -177
  142. package/packages/galaxydraw/src/core/viewport.ts +0 -106
  143. package/packages/galaxydraw/src/galaxydraw.css +0 -166
  144. package/packages/galaxydraw/src/index.ts +0 -40
  145. package/packages/galaxydraw/tsconfig.json +0 -30
@@ -1,134 +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
- return card;
51
- },
52
-
53
- onResize(card: HTMLElement, width: number, height: number) {
54
- // Dispatch the resize event that cards.tsx already listens for
55
- const path = card.dataset.path;
56
- if (path) {
57
- card.dispatchEvent(new CustomEvent('card-resized', {
58
- detail: { path, width, height },
59
- }));
60
- }
61
- },
62
-
63
- onDestroy(card: HTMLElement) {
64
- // Clean up any scroll timers or event listeners
65
- // The card DOM is removed by CardManager, but we should
66
- // clean up any overlays or attached state
67
- },
68
-
69
- consumesWheel(target: HTMLElement): boolean {
70
- // File card bodies are scrollable — pass wheel events through
71
- return !!target.closest('.file-card-body');
72
- },
73
-
74
- consumesMouse(target: HTMLElement): boolean {
75
- // Buttons, links, and interactive elements within cards
76
- // should receive mouse events directly
77
- return !!(
78
- target.closest('button') ||
79
- target.closest('a') ||
80
- target.closest('.connect-btn') ||
81
- target.closest('.line-num') ||
82
- target.closest('.diff-hunk-header')
83
- );
84
- },
85
- };
86
- }
87
-
88
- /**
89
- * Plugin for rendering commit diff cards on the canvas.
90
- * Used by the "commit diff" view.
91
- */
92
- export function createDiffCardPlugin(): CardPlugin {
93
- return {
94
- type: DIFF_CARD_TYPE,
95
-
96
- render(data: CardData): HTMLElement {
97
- const { file, ctx, commitHash } = data.meta || {};
98
- if (!file || !ctx) {
99
- const el = document.createElement('div');
100
- el.className = 'file-card';
101
- el.textContent = 'Missing diff data';
102
- return el;
103
- }
104
-
105
- const { createFileCard } = require('./cards');
106
- const card = createFileCard(ctx, file, data.x, data.y, commitHash, true);
107
- return card;
108
- },
109
-
110
- onResize(card: HTMLElement, width: number, height: number) {
111
- const path = card.dataset.path;
112
- if (path) {
113
- card.dispatchEvent(new CustomEvent('card-resized', {
114
- detail: { path, width, height },
115
- }));
116
- }
117
- },
118
-
119
- onDestroy() { },
120
-
121
- consumesWheel(target: HTMLElement): boolean {
122
- return !!target.closest('.file-card-body');
123
- },
124
-
125
- consumesMouse(target: HTMLElement): boolean {
126
- return !!(
127
- target.closest('button') ||
128
- target.closest('a') ||
129
- target.closest('.connect-btn') ||
130
- target.closest('.diff-hunk-header')
131
- );
132
- },
133
- };
134
- }
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(() => {