diffhub 0.1.0 → 0.1.2

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 (189) hide show
  1. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  2. package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
  3. package/.next/standalone/apps/web/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/apps/web/.next/required-server-files.json +4 -4
  5. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  6. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/standalone/apps/web/.next/server/app/_not-found/page.js +1 -1
  13. package/.next/standalone/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  16. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +17 -16
  17. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +17 -16
  18. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  19. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +6 -5
  20. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  21. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  22. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/standalone/apps/web/.next/server/app/api/comments/route.js +1 -1
  24. package/.next/standalone/apps/web/.next/server/app/api/comments/route.js.nft.json +1 -1
  25. package/.next/standalone/apps/web/.next/server/app/api/diff/route.js +2 -2
  26. package/.next/standalone/apps/web/.next/server/app/api/diff/route.js.nft.json +1 -1
  27. package/.next/standalone/apps/web/.next/server/app/api/discard/route.js +2 -2
  28. package/.next/standalone/apps/web/.next/server/app/api/discard/route.js.nft.json +1 -1
  29. package/.next/standalone/apps/web/.next/server/app/api/file/route.js +2 -2
  30. package/.next/standalone/apps/web/.next/server/app/api/file/route.js.nft.json +1 -1
  31. package/.next/standalone/apps/web/.next/server/app/api/files/route.js +2 -2
  32. package/.next/standalone/apps/web/.next/server/app/api/files/route.js.nft.json +1 -1
  33. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  34. package/.next/standalone/apps/web/.next/server/app/index.rsc +16 -15
  35. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  36. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +16 -15
  37. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +4 -4
  38. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +6 -5
  39. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  40. package/.next/standalone/apps/web/.next/server/app/page/react-loadable-manifest.json +2 -2
  41. package/.next/standalone/apps/web/.next/server/app/page.js +2 -2
  42. package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
  43. package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__05ejtyr._.js +3 -0
  45. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0e2dp4h._.js +3 -0
  46. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0egk6ui._.js +3 -0
  47. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0i6i-~n._.js +3 -0
  48. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0sv4hr9._.js +3 -0
  49. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0t.tl18._.js +3 -0
  50. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__06b81~v._.js → [root-of-the-server]__0giwc4b._.js} +2 -2
  51. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0jit913._.js +3 -0
  52. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0v19a7g._.js +3 -0
  53. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0f40lcw._.js +3 -0
  54. package/.next/standalone/apps/web/.next/server/chunks/ssr/_0oc3qg_._.js +3 -3
  55. package/.next/standalone/apps/web/.next/server/chunks/ssr/{apps_web_0b_ykcu._.js → _0qo42r0._.js} +2 -2
  56. package/.next/standalone/apps/web/.next/server/chunks/ssr/{apps_web_08kf15u._.js → apps_web_0758ax4._.js} +2 -2
  57. package/.next/standalone/apps/web/.next/server/chunks/ssr/node_modules_0v8w2j~._.js +70 -0
  58. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
  59. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  60. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  61. package/.next/standalone/apps/web/.next/server/server-reference-manifest.js +1 -1
  62. package/.next/standalone/apps/web/.next/server/server-reference-manifest.json +1 -1
  63. package/.next/standalone/apps/web/.next/static/chunks/00zp83w4g1v1r.js +16 -0
  64. package/.next/standalone/apps/web/.next/static/chunks/042ip11u2i2z6.js +138 -0
  65. package/.next/standalone/apps/web/.next/static/chunks/07ndp5x2cvqo..css +3 -0
  66. package/.next/standalone/apps/web/.next/static/chunks/085s9eg867ha-.js +1 -0
  67. package/.next/standalone/apps/web/.next/static/chunks/0_vmme_k_ff_u.js +67 -0
  68. package/.next/standalone/apps/web/.next/static/chunks/0ap~_hc7r17_6.js +1 -0
  69. package/.next/standalone/apps/web/.next/static/chunks/0nt5-rwas5thn.js +67 -0
  70. package/.next/standalone/apps/web/.next/static/chunks/0p~3-4_.v0cft.js +1 -0
  71. package/.next/standalone/apps/web/.next/static/chunks/0wx-2dr44ql-g.js +1 -0
  72. package/.next/standalone/apps/web/.next/static/chunks/{0syypqto3~pe_.js → 0y0o261rjun_2.js} +8 -8
  73. package/.next/standalone/apps/web/.next/static/chunks/0y5z3t-z1c8ks.js.map +5 -0
  74. package/.next/standalone/apps/web/.next/static/chunks/17b.xoi.b6rcl.js +1 -0
  75. package/.next/standalone/apps/web/.next/static/chunks/turbopack-0_n_4n~_4no2a.js +1 -0
  76. package/.next/standalone/apps/web/.next/static/chunks/turbopack-worker-0sjn--fhq~1cg.js +1 -0
  77. package/.next/standalone/apps/web/.next/static/media/diffs.worker.09unk0quktc_5.ts +1 -0
  78. package/.next/standalone/apps/web/package.json +12 -2
  79. package/.next/standalone/apps/web/server.js +1 -1
  80. package/README.md +10 -3
  81. package/bin/diffhub.mjs +1 -1
  82. package/package.json +12 -2
  83. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__05vwx85._.js +0 -3
  84. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__09vmjc2._.js +0 -3
  85. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0etmu4u._.js +0 -3
  86. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0g-_a7n._.js +0 -3
  87. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0mshgfw._.js +0 -3
  88. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0qixima._.js +0 -3
  89. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0khyzju._.js +0 -3
  90. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0l2mjim._.js +0 -70
  91. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0q2lon0._.js +0 -3
  92. package/.next/standalone/apps/web/.next/server/chunks/ssr/_059a1m-._.js +0 -3
  93. package/.next/standalone/apps/web/.next/static/chunks/0.ae0sud8tm7k.js +0 -204
  94. package/.next/standalone/apps/web/.next/static/chunks/0di~ntk7iivm4.js +0 -1
  95. package/.next/standalone/apps/web/.next/static/chunks/0pklg0nmdvay8.js +0 -1
  96. package/.next/standalone/apps/web/.next/static/chunks/0up9_7hiwl_dt.js +0 -1
  97. package/.next/standalone/apps/web/.next/static/chunks/0~984a88e4rp9.js +0 -204
  98. package/.next/standalone/apps/web/.next/static/chunks/13y8355z8m13w.js +0 -1
  99. package/.next/standalone/apps/web/.next/static/chunks/14gfmthe5zcf..js +0 -16
  100. package/.next/standalone/apps/web/.next/static/chunks/15--1d_raviej.css +0 -3
  101. package/.next/standalone/apps/web/AGENTS.md +0 -60
  102. package/.next/standalone/apps/web/CLAUDE.md +0 -1
  103. package/.next/standalone/apps/web/README.md +0 -78
  104. package/.next/standalone/apps/web/app/api/comments/route.ts +0 -20
  105. package/.next/standalone/apps/web/app/api/diff/route.ts +0 -15
  106. package/.next/standalone/apps/web/app/api/discard/route.ts +0 -15
  107. package/.next/standalone/apps/web/app/api/file/route.ts +0 -17
  108. package/.next/standalone/apps/web/app/api/files/route.ts +0 -14
  109. package/.next/standalone/apps/web/app/api/open/route.ts +0 -64
  110. package/.next/standalone/apps/web/app/favicon.ico +0 -0
  111. package/.next/standalone/apps/web/app/globals.css +0 -214
  112. package/.next/standalone/apps/web/app/layout.tsx +0 -52
  113. package/.next/standalone/apps/web/app/page.tsx +0 -6
  114. package/.next/standalone/apps/web/bin/diffhub.mjs +0 -147
  115. package/.next/standalone/apps/web/components/ContextMenu.tsx +0 -161
  116. package/.next/standalone/apps/web/components/DiffApp.tsx +0 -363
  117. package/.next/standalone/apps/web/components/DiffViewer.tsx +0 -565
  118. package/.next/standalone/apps/web/components/FileDiffHeader.tsx +0 -119
  119. package/.next/standalone/apps/web/components/FileList.tsx +0 -438
  120. package/.next/standalone/apps/web/components/KeyboardShortcutsDialog.tsx +0 -79
  121. package/.next/standalone/apps/web/components/SidebarHelpMenu.tsx +0 -86
  122. package/.next/standalone/apps/web/components/StatusBar.tsx +0 -212
  123. package/.next/standalone/apps/web/components/icons/file-status-icons.tsx +0 -48
  124. package/.next/standalone/apps/web/components/theme-provider.tsx +0 -12
  125. package/.next/standalone/apps/web/components/ui/button.tsx +0 -90
  126. package/.next/standalone/apps/web/components/ui/empty.tsx +0 -82
  127. package/.next/standalone/apps/web/components/ui/input.tsx +0 -18
  128. package/.next/standalone/apps/web/components/ui/kbd.tsx +0 -14
  129. package/.next/standalone/apps/web/components/ui/separator.tsx +0 -23
  130. package/.next/standalone/apps/web/components/ui/sheet.tsx +0 -109
  131. package/.next/standalone/apps/web/components/ui/sidebar.tsx +0 -700
  132. package/.next/standalone/apps/web/components/ui/skeleton.tsx +0 -9
  133. package/.next/standalone/apps/web/components/ui/toggle.tsx +0 -35
  134. package/.next/standalone/apps/web/components/ui/tooltip.tsx +0 -52
  135. package/.next/standalone/apps/web/components.json +0 -27
  136. package/.next/standalone/apps/web/lib/comments.ts +0 -52
  137. package/.next/standalone/apps/web/lib/export-comments.ts +0 -13
  138. package/.next/standalone/apps/web/lib/git.ts +0 -201
  139. package/.next/standalone/apps/web/lib/use-mobile.ts +0 -19
  140. package/.next/standalone/apps/web/lib/utils.ts +0 -5
  141. package/.next/standalone/apps/web/next.config.ts +0 -19
  142. package/.next/standalone/apps/web/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +0 -0
  143. package/.next/standalone/apps/web/node_modules/@img/sharp-darwin-arm64/package.json +0 -40
  144. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/README.md +0 -46
  145. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/lib/glib-2.0/include/glibconfig.h +0 -220
  146. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/lib/index.js +0 -1
  147. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.8.17.3.dylib +0 -0
  148. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/package.json +0 -36
  149. package/.next/standalone/apps/web/node_modules/@img/sharp-libvips-darwin-arm64/versions.json +0 -30
  150. package/.next/standalone/apps/web/oxfmt.config.ts +0 -6
  151. package/.next/standalone/apps/web/oxlint.config.ts +0 -13
  152. package/.next/standalone/apps/web/postcss.config.mjs +0 -7
  153. package/.next/standalone/apps/web/public/file.svg +0 -1
  154. package/.next/standalone/apps/web/public/glide-variable-italic.woff2 +0 -0
  155. package/.next/standalone/apps/web/public/glide-variable.woff2 +0 -0
  156. package/.next/standalone/apps/web/public/globe.svg +0 -1
  157. package/.next/standalone/apps/web/public/next.svg +0 -1
  158. package/.next/standalone/apps/web/public/operator-mono-book-italic.woff2 +0 -0
  159. package/.next/standalone/apps/web/public/operator-mono-book.woff2 +0 -0
  160. package/.next/standalone/apps/web/public/operator-mono-medium-italic.woff2 +0 -0
  161. package/.next/standalone/apps/web/public/operator-mono-medium.woff2 +0 -0
  162. package/.next/standalone/apps/web/public/vercel.svg +0 -1
  163. package/.next/standalone/apps/web/public/window.svg +0 -1
  164. package/.next/standalone/apps/web/tsconfig.json +0 -34
  165. package/.next/standalone/apps/web/tsconfig.tsbuildinfo +0 -1
  166. /package/.next/standalone/apps/web/.next/static/{x0qhb6ReQoZ53hlmgg2-_ → mAVCL4HCmtJwT35feBPdK}/_buildManifest.js +0 -0
  167. /package/.next/standalone/apps/web/.next/static/{x0qhb6ReQoZ53hlmgg2-_ → mAVCL4HCmtJwT35feBPdK}/_clientMiddlewareManifest.js +0 -0
  168. /package/.next/standalone/apps/web/.next/static/{x0qhb6ReQoZ53hlmgg2-_ → mAVCL4HCmtJwT35feBPdK}/_ssgManifest.js +0 -0
  169. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/classes/comparator.js +0 -0
  170. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/classes/range.js +0 -0
  171. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/classes/semver.js +0 -0
  172. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/cmp.js +0 -0
  173. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/coerce.js +0 -0
  174. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/compare.js +0 -0
  175. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/eq.js +0 -0
  176. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/gt.js +0 -0
  177. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/gte.js +0 -0
  178. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/lt.js +0 -0
  179. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/lte.js +0 -0
  180. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/neq.js +0 -0
  181. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/parse.js +0 -0
  182. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/functions/satisfies.js +0 -0
  183. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/constants.js +0 -0
  184. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/debug.js +0 -0
  185. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/identifiers.js +0 -0
  186. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/lrucache.js +0 -0
  187. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/parse-options.js +0 -0
  188. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/internal/re.js +0 -0
  189. /package/.next/standalone/{apps/web/node_modules → node_modules}/semver/package.json +0 -0
@@ -1,214 +0,0 @@
1
- @import "tailwindcss";
2
- @import "tw-animate-css";
3
- @import "shadcn/tailwind.css";
4
-
5
- @custom-variant dark (&:is(.dark *));
6
-
7
- @theme inline {
8
- --color-background: var(--background);
9
- --color-foreground: var(--foreground);
10
- --font-sans: var(--font-glide), ui-sans-serif, system-ui, sans-serif;
11
- --font-mono: var(--font-operator-mono), ui-monospace, monospace;
12
- --font-heading: var(--font-glide), ui-sans-serif, system-ui, sans-serif;
13
- --color-sidebar-ring: var(--sidebar-ring);
14
- --color-sidebar-border: var(--sidebar-border);
15
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
16
- --color-sidebar-accent: var(--sidebar-accent);
17
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
18
- --color-sidebar-primary: var(--sidebar-primary);
19
- --color-sidebar-foreground: var(--sidebar-foreground);
20
- --color-sidebar: var(--sidebar);
21
- --color-chart-5: var(--chart-5);
22
- --color-chart-4: var(--chart-4);
23
- --color-chart-3: var(--chart-3);
24
- --color-chart-2: var(--chart-2);
25
- --color-chart-1: var(--chart-1);
26
- --color-ring: var(--ring);
27
- --color-input: var(--input);
28
- --color-border: var(--border);
29
- --color-destructive: var(--destructive);
30
- --color-accent-foreground: var(--accent-foreground);
31
- --color-accent: var(--accent);
32
- --color-muted-foreground: var(--muted-foreground);
33
- --color-muted: var(--muted);
34
- --color-secondary-foreground: var(--secondary-foreground);
35
- --color-secondary: var(--secondary);
36
- --color-primary-foreground: var(--primary-foreground);
37
- --color-primary: var(--primary);
38
- --color-popover-foreground: var(--popover-foreground);
39
- --color-popover: var(--popover);
40
- --color-card-foreground: var(--card-foreground);
41
- --color-card: var(--card);
42
- --radius-sm: calc(var(--radius) * 0.6);
43
- --radius-md: calc(var(--radius) * 0.8);
44
- --radius-lg: var(--radius);
45
- --radius-xl: calc(var(--radius) * 1.4);
46
- --radius-2xl: calc(var(--radius) * 1.8);
47
- --radius-3xl: calc(var(--radius) * 2.2);
48
- --radius-4xl: calc(var(--radius) * 2.6);
49
- /* Diff-specific semantic tokens */
50
- --color-diff-green: var(--diff-green);
51
- --color-diff-purple: var(--diff-purple);
52
- --color-diff-selected: var(--diff-selected);
53
- --color-diff-success: var(--diff-success);
54
- }
55
-
56
- :root {
57
- --background: oklch(1 0 0);
58
- --foreground: oklch(0.145 0 0);
59
- --card: oklch(1 0 0);
60
- --card-foreground: oklch(0.145 0 0);
61
- --popover: oklch(1 0 0);
62
- --popover-foreground: oklch(0.145 0 0);
63
- --primary: oklch(0.205 0 0);
64
- --primary-foreground: oklch(0.985 0 0);
65
- --secondary: oklch(0.97 0 0);
66
- --secondary-foreground: oklch(0.205 0 0);
67
- --muted: oklch(0.97 0 0);
68
- --muted-foreground: oklch(0.556 0 0);
69
- --accent: oklch(0.97 0 0);
70
- --accent-foreground: oklch(0.205 0 0);
71
- --destructive: oklch(0.577 0.245 27.325);
72
- --border: oklch(0.922 0 0);
73
- --input: oklch(0.922 0 0);
74
- --ring: oklch(0.708 0 0);
75
- --chart-1: oklch(0.87 0 0);
76
- --chart-2: oklch(0.556 0 0);
77
- --chart-3: oklch(0.439 0 0);
78
- --chart-4: oklch(0.371 0 0);
79
- --chart-5: oklch(0.269 0 0);
80
- --radius: 0.625rem;
81
- --sidebar: oklch(0.985 0 0);
82
- --sidebar-foreground: oklch(0.145 0 0);
83
- --sidebar-primary: oklch(0.205 0 0);
84
- --sidebar-primary-foreground: oklch(0.985 0 0);
85
- --sidebar-accent: oklch(0.97 0 0);
86
- --sidebar-accent-foreground: oklch(0.205 0 0);
87
- --sidebar-border: oklch(0.922 0 0);
88
- --sidebar-ring: oklch(0.708 0 0);
89
- /* Diff-specific tokens */
90
- --diff-green: oklch(0.696 0.17 145);
91
- --diff-purple: oklch(0.78 0.12 300);
92
- --diff-selected: oklch(0.93 0 0);
93
- --diff-success: oklch(0.573 0.15 145);
94
- }
95
-
96
- .dark {
97
- --background: oklch(0.145 0 0);
98
- --foreground: oklch(0.985 0 0);
99
- --card: oklch(0.205 0 0);
100
- --card-foreground: oklch(0.985 0 0);
101
- --popover: oklch(0.205 0 0);
102
- --popover-foreground: oklch(0.985 0 0);
103
- --primary: oklch(0.922 0 0);
104
- --primary-foreground: oklch(0.205 0 0);
105
- --secondary: oklch(0.269 0 0);
106
- --secondary-foreground: oklch(0.985 0 0);
107
- --muted: oklch(0.269 0 0);
108
- --muted-foreground: oklch(0.708 0 0);
109
- --accent: oklch(0.269 0 0);
110
- --accent-foreground: oklch(0.985 0 0);
111
- --destructive: oklch(0.704 0.191 22.216);
112
- --border: oklch(1 0 0 / 10%);
113
- --input: oklch(1 0 0 / 15%);
114
- --ring: oklch(0.556 0 0);
115
- --chart-1: oklch(0.87 0 0);
116
- --chart-2: oklch(0.556 0 0);
117
- --chart-3: oklch(0.439 0 0);
118
- --chart-4: oklch(0.371 0 0);
119
- --chart-5: oklch(0.269 0 0);
120
- --sidebar: oklch(0.205 0 0);
121
- --sidebar-foreground: oklch(0.985 0 0);
122
- --sidebar-primary: oklch(0.922 0 0);
123
- --sidebar-primary-foreground: oklch(0.985 0 0);
124
- --sidebar-accent: oklch(0.269 0 0);
125
- --sidebar-accent-foreground: oklch(0.985 0 0);
126
- --sidebar-border: oklch(1 0 0 / 10%);
127
- --sidebar-ring: oklch(0.556 0 0);
128
- /* Diff-specific tokens */
129
- --diff-green: oklch(0.696 0.15 145);
130
- --diff-purple: oklch(0.78 0.12 300);
131
- --diff-selected: oklch(0.269 0 0);
132
- --diff-success: oklch(0.573 0.15 145);
133
- }
134
-
135
- @layer base {
136
- * {
137
- @apply border-border outline-ring/50;
138
- }
139
- body {
140
- @apply bg-background text-foreground font-sans;
141
- }
142
-
143
- kbd {
144
- display: inline-flex;
145
- align-items: center;
146
- justify-content: center;
147
- min-width: 16px;
148
- padding: 1px 4px;
149
- border-radius: 4px;
150
- border: 1px solid var(--border);
151
- background: var(--muted);
152
- font-size: 10px;
153
- font-family: var(--font-mono);
154
- line-height: 1.4;
155
- color: var(--muted-foreground);
156
- }
157
-
158
- /*
159
- * Gutter "+" button: the library renders a light-DOM slot wrapper with
160
- * inline styles `position:absolute; top:0; bottom:0` but NO width. We use
161
- * a fixed pixel size so the button is always visible regardless of parent.
162
- */
163
- .diffhub-gutter-btn {
164
- display: flex;
165
- align-items: center;
166
- justify-content: center;
167
- width: 20px;
168
- height: 20px;
169
- border: none;
170
- border-radius: 3px;
171
- background: var(--primary);
172
- color: var(--primary-foreground);
173
- font-size: 14px;
174
- font-weight: bold;
175
- line-height: 1;
176
- cursor: pointer;
177
- animation: diffhub-gutter-in 0.08s ease-out both;
178
- }
179
-
180
- .diffhub-gutter-btn:hover {
181
- background: color-mix(in srgb, var(--primary) 85%, black);
182
- }
183
-
184
- @keyframes diffhub-gutter-in {
185
- from {
186
- opacity: 0;
187
- }
188
- to {
189
- opacity: 1;
190
- }
191
- }
192
- }
193
-
194
- @keyframes diffhub-menu-in {
195
- from {
196
- opacity: 0;
197
- transform: translateY(-4px) scale(0.97);
198
- }
199
- to {
200
- opacity: 1;
201
- transform: translateY(0) scale(1);
202
- }
203
- }
204
-
205
- .diffhub-menu-animate {
206
- animation: diffhub-menu-in 120ms ease-out forwards;
207
- }
208
-
209
- /* ── Hunk expand separator ──────────────────────────────────────────────── */
210
- /*
211
- @pierre/diffs renders expand buttons inside Shadow DOM — global CSS cannot
212
- reach them. The library provides its own expand-button styling. No overrides
213
- are needed here.
214
- */
@@ -1,52 +0,0 @@
1
- import { Agentation } from "agentation";
2
- import type { Metadata } from "next";
3
- import localFont from "next/font/local";
4
- import { ThemeProvider } from "@/components/theme-provider";
5
- import "./globals.css";
6
-
7
- const glide = localFont({
8
- display: "swap",
9
- src: [
10
- { path: "../public/glide-variable.woff2", style: "normal" },
11
- { path: "../public/glide-variable-italic.woff2", style: "italic" },
12
- ],
13
- variable: "--font-glide",
14
- weight: "400 900",
15
- });
16
-
17
- const operatorMono = localFont({
18
- display: "swap",
19
- src: [
20
- { path: "../public/operator-mono-book.woff2", style: "normal", weight: "400" },
21
- { path: "../public/operator-mono-book-italic.woff2", style: "italic", weight: "400" },
22
- { path: "../public/operator-mono-medium.woff2", style: "normal", weight: "500" },
23
- { path: "../public/operator-mono-medium-italic.woff2", style: "italic", weight: "500" },
24
- ],
25
- variable: "--font-operator-mono",
26
- });
27
-
28
- export const metadata: Metadata = {
29
- description: "GitHub PR-style local diff viewer",
30
- title: "diffhub",
31
- };
32
-
33
- export default function RootLayout({
34
- children,
35
- }: Readonly<{
36
- children: React.ReactNode;
37
- }>) {
38
- return (
39
- <html
40
- lang="en"
41
- className={`${glide.variable} ${operatorMono.variable} h-full`}
42
- suppressHydrationWarning
43
- >
44
- <body className="h-full overflow-hidden bg-background antialiased">
45
- <ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange>
46
- {children}
47
- {process.env.NODE_ENV === "development" && <Agentation />}
48
- </ThemeProvider>
49
- </body>
50
- </html>
51
- );
52
- }
@@ -1,6 +0,0 @@
1
- import { DiffApp } from "@/components/DiffApp";
2
-
3
- export default function Home() {
4
- const repoPath = process.env.CMUX_DIFF_REPO ?? process.cwd();
5
- return <DiffApp repoPath={repoPath} />;
6
- }
@@ -1,147 +0,0 @@
1
- #!/usr/bin/env node
2
- import { program } from "commander";
3
- import { spawn } from "node:child_process";
4
- import { existsSync } from "node:fs";
5
- import { createServer } from "node:net";
6
- import { join, resolve } from "node:path";
7
-
8
- const __dirname = import.meta.dirname;
9
-
10
- // Fast-fail on unsupported Node.js versions
11
- const nodeMajor = Number.parseInt(process.version.slice(1).split(".")[0], 10);
12
- if (nodeMajor < 18) {
13
- process.stderr.write(`❌ diffhub requires Node.js 18+. You have ${process.version}.\n`);
14
- process.stderr.write(` Download: https://nodejs.org\n`);
15
- process.exit(1);
16
- }
17
-
18
- // -- Port utilities ----------------------------------------------------------
19
-
20
- // oxlint-disable-next-line promise/avoid-new
21
- const findFreePort = async (start) => {
22
- for (let p = start; p < start + 10; p += 1) {
23
- // oxlint-disable-next-line promise/avoid-new
24
- const free = await new Promise((_resolve) => {
25
- const s = createServer();
26
- s.listen(p, () => {
27
- s.close();
28
- _resolve(true);
29
- });
30
- s.on("error", () => _resolve(false));
31
- });
32
- if (free) {
33
- return p;
34
- }
35
- }
36
- return start;
37
- };
38
-
39
- const waitForServer = async (port, maxMs = 15_000) => {
40
- const deadline = Date.now() + maxMs;
41
- while (Date.now() < deadline) {
42
- try {
43
- const res = await fetch(`http://127.0.0.1:${port}`);
44
- if (res.ok || res.status === 404) {
45
- return true;
46
- }
47
- } catch {
48
- // empty
49
- }
50
- // oxlint-disable-next-line promise/avoid-new
51
- await new Promise((_resolve) => {
52
- setTimeout(_resolve, 300);
53
- });
54
- }
55
- return false;
56
- };
57
-
58
- // -- CLI setup ---------------------------------------------------------------
59
-
60
- program
61
- .name("diffhub")
62
- .description("GitHub PR-style local diff viewer")
63
- .version("0.1.0")
64
- .option("-p, --port <port>", "Port to serve on", "2047")
65
- .option("-r, --repo <path>", "Git repository path (defaults to cwd)")
66
- .option("-b, --base <branch>", "Base branch to diff against (defaults to main/master)")
67
- .option("--no-open", "Don't open browser automatically")
68
- .parse(process.argv);
69
-
70
- const opts = program.opts();
71
- const repoPath = resolve(opts.repo ?? process.cwd());
72
- const baseBranch = opts.base ?? "";
73
-
74
- // Verify it's a git repo
75
- if (!existsSync(join(repoPath, ".git"))) {
76
- console.error(`❌ Not a git repository: ${repoPath}`);
77
- console.error(` Run from inside a git repo, or pass --repo:`);
78
- console.error(` diffhub --repo /path/to/your-repo`);
79
- process.exit(1);
80
- }
81
-
82
- // outputFileTracingRoot is set to the monorepo root, so Next.js places the server at
83
- // .next/standalone/apps/web/server.js (mirroring the workspace path).
84
- const appDir = resolve(__dirname, "..");
85
- const serverPath = join(appDir, ".next", "standalone", "apps", "web", "server.js");
86
-
87
- if (!existsSync(serverPath)) {
88
- console.error("❌ No production build found.");
89
- console.error(" Run: npm run build");
90
- process.exit(1);
91
- }
92
-
93
- const standaloneDir = resolve(serverPath, "..");
94
- const port = await findFreePort(Number.parseInt(opts.port, 10));
95
-
96
- // -- Startup banner ----------------------------------------------------------
97
-
98
- console.log(` diffhub\n`);
99
- console.log(` Repo ${repoPath}`);
100
- if (baseBranch) {
101
- console.log(` Base ${baseBranch}`);
102
- }
103
- console.log(` URL http://localhost:${port}`);
104
- console.log(`\n Press Ctrl+C to stop\n`);
105
-
106
- // -- Start server ------------------------------------------------------------
107
-
108
- const server = spawn("node", ["server.js"], {
109
- cwd: standaloneDir,
110
- env: {
111
- ...process.env,
112
- DIFFHUB_REPO: repoPath,
113
- ...(baseBranch ? { DIFFHUB_BASE: baseBranch } : {}),
114
- HOSTNAME: "127.0.0.1",
115
- NODE_ENV: "production",
116
- PORT: String(port),
117
- },
118
- stdio: "inherit",
119
- });
120
-
121
- server.on("error", (err) => {
122
- console.error("Failed to start server:", err.message);
123
- process.exit(1);
124
- });
125
-
126
- // -- Open browser when ready -------------------------------------------------
127
-
128
- if (opts.open !== false) {
129
- const url = `http://localhost:${port}`;
130
- const ready = await waitForServer(port);
131
- if (ready) {
132
- const opener =
133
- { darwin: "open", linux: "xdg-open", win32: "start" }[process.platform] ?? "xdg-open";
134
- spawn(opener, [url], {
135
- detached: true,
136
- shell: process.platform === "win32",
137
- stdio: "ignore",
138
- }).unref();
139
- }
140
- }
141
-
142
- // -- Graceful shutdown -------------------------------------------------------
143
-
144
- process.on("SIGINT", () => {
145
- server.kill();
146
- process.exit(0);
147
- });
@@ -1,161 +0,0 @@
1
- "use client";
2
-
3
- import { useEffect, useRef, useState } from "react";
4
- import {
5
- FolderOpenIcon,
6
- CodeLinesIcon,
7
- CodeBracketsIcon,
8
- CopySimpleIcon,
9
- CheckIcon,
10
- ArrowUndoDownIcon,
11
- } from "blode-icons-react";
12
-
13
- interface ContextMenuProps {
14
- x: number;
15
- y: number;
16
- filePath: string;
17
- repoPath: string;
18
- onClose: () => void;
19
- onDiscard?: () => Promise<void>;
20
- }
21
-
22
- const APPS = [
23
- { icon: FolderOpenIcon, key: "finder", label: "Finder" },
24
- { icon: CodeLinesIcon, key: "zed", label: "Zed" },
25
- { icon: CodeLinesIcon, key: "vscode", label: "VS Code" },
26
- { icon: CodeLinesIcon, key: "xcode", label: "Xcode" },
27
- { icon: CodeBracketsIcon, key: "ghostty", label: "Ghostty" },
28
- { icon: CodeBracketsIcon, key: "terminal", label: "Terminal" },
29
- ] as const;
30
-
31
- type AppKey = (typeof APPS)[number]["key"];
32
-
33
- export const ContextMenu = ({ x, y, filePath, repoPath, onClose, onDiscard }: ContextMenuProps) => {
34
- const ref = useRef<HTMLDivElement>(null);
35
- const [copied, setCopied] = useState(false);
36
- const [discarding, setDiscarding] = useState(false);
37
-
38
- useEffect(() => {
39
- const handleClick = (e: MouseEvent) => {
40
- if (ref.current && !ref.current.contains(e.target as Node)) {
41
- onClose();
42
- }
43
- };
44
- const handleKey = (e: KeyboardEvent) => {
45
- if (e.key === "Escape") {
46
- onClose();
47
- }
48
- };
49
- document.addEventListener("mousedown", handleClick);
50
- document.addEventListener("keydown", handleKey);
51
- return () => {
52
- document.removeEventListener("mousedown", handleClick);
53
- document.removeEventListener("keydown", handleKey);
54
- };
55
- }, [onClose]);
56
-
57
- const openIn = async (app: AppKey) => {
58
- const fullPath = `${repoPath}/${filePath}`;
59
- try {
60
- await fetch("/api/open", {
61
- body: JSON.stringify({ app, path: fullPath }),
62
- headers: { "Content-Type": "application/json" },
63
- method: "POST",
64
- });
65
- } catch {
66
- // best-effort — still close the menu
67
- }
68
- onClose();
69
- };
70
-
71
- // oxlint-disable-next-line react-perf/jsx-no-new-function-as-prop
72
- const handleDiscard = async () => {
73
- if (!onDiscard || discarding) {
74
- return;
75
- }
76
- setDiscarding(true);
77
- try {
78
- await onDiscard();
79
- onClose();
80
- } finally {
81
- setDiscarding(false);
82
- }
83
- };
84
-
85
- // oxlint-disable-next-line react-perf/jsx-no-new-function-as-prop
86
- const copyPath = async () => {
87
- const fullPath = `${repoPath}/${filePath}`;
88
- try {
89
- await navigator.clipboard.writeText(fullPath);
90
- setCopied(true);
91
- setTimeout(() => {
92
- setCopied(false);
93
- onClose();
94
- }, 1200);
95
- } catch {
96
- onClose();
97
- }
98
- };
99
-
100
- // Adjust position to stay in viewport
101
- const style: React.CSSProperties = {
102
- left: Math.min(x, window.innerWidth - 200),
103
- position: "fixed",
104
- top: Math.min(y, window.innerHeight - 300),
105
- zIndex: 1000,
106
- };
107
-
108
- return (
109
- <div
110
- ref={ref}
111
- style={style}
112
- className="diffhub-menu-animate min-w-[160px] rounded-lg border border-border bg-popover shadow-xl dark:shadow-none py-1 text-sm"
113
- >
114
- {/* File path header */}
115
- <div className="px-3 py-1.5 text-xs text-muted-foreground border-b border-border mb-1 font-mono truncate max-w-[200px]">
116
- {filePath.split("/").pop()}
117
- </div>
118
-
119
- {APPS.map(({ key, label, icon: Icon }) => (
120
- <button
121
- type="button"
122
- key={key}
123
- // oxlint-disable-next-line react-perf/jsx-no-new-function-as-prop
124
- onClick={() => openIn(key)}
125
- className="flex w-full items-center gap-2.5 px-3 py-1.5 text-foreground hover:bg-secondary transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50"
126
- >
127
- <Icon size={14} className="text-muted-foreground" />
128
- {label}
129
- </button>
130
- ))}
131
-
132
- <div className="border-t border-border mt-1 pt-1">
133
- <button
134
- type="button"
135
- // oxlint-disable-next-line react-perf/jsx-no-new-function-as-prop
136
- onClick={copyPath}
137
- className="flex w-full items-center gap-2.5 px-3 py-1.5 text-foreground hover:bg-secondary transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50"
138
- >
139
- {copied ? (
140
- <CheckIcon size={14} className="text-diff-green" />
141
- ) : (
142
- <CopySimpleIcon size={14} className="text-muted-foreground" />
143
- )}
144
- {copied ? "Copied!" : "Copy path"}
145
- </button>
146
- {onDiscard && (
147
- <button
148
- type="button"
149
- // oxlint-disable-next-line react-perf/jsx-no-new-function-as-prop
150
- onClick={handleDiscard}
151
- disabled={discarding}
152
- className="flex w-full items-center gap-2.5 px-3 py-1.5 text-destructive hover:bg-destructive/10 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/50 disabled:opacity-50"
153
- >
154
- <ArrowUndoDownIcon size={14} className={discarding ? "animate-spin" : ""} />
155
- Discard changes
156
- </button>
157
- )}
158
- </div>
159
- </div>
160
- );
161
- };