nebulosity 1.0.0 → 1.1.0

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 (180) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +11 -11
  3. package/.next/diagnostics/route-bundle-stats.json +10 -10
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/prerender-manifest.json +5 -5
  6. package/.next/server/app/_global-error/page/build-manifest.json +3 -3
  7. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page/build-manifest.json +3 -3
  14. package/.next/server/app/_not-found/page/next-font-manifest.json +2 -3
  15. package/.next/server/app/_not-found/page.js +3 -2
  16. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/_not-found.html +1 -1
  18. package/.next/server/app/_not-found.rsc +27 -20
  19. package/.next/server/app/_not-found.segments/_full.segment.rsc +27 -20
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +34 -26
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/server/app/index.html +1 -1
  23. package/.next/server/app/index.rsc +29 -23
  24. package/.next/server/app/index.segments/__PAGE__.segment.rsc +33 -24
  25. package/.next/server/app/index.segments/_full.segment.rsc +29 -23
  26. package/.next/server/app/index.segments/_tree.segment.rsc +4 -5
  27. package/.next/server/app/page/build-manifest.json +3 -3
  28. package/.next/server/app/page/next-font-manifest.json +2 -3
  29. package/.next/server/app/page.js +4 -4
  30. package/.next/server/app/page_client-reference-manifest.js +1 -1
  31. package/.next/server/chunks/[root-of-the-server]__06blyow8irfw3._.js +3 -3
  32. package/.next/server/chunks/[root-of-the-server]__0bmqko-d8fd5k._.js +3 -3
  33. package/.next/server/chunks/[root-of-the-server]__0cmmlmvta4i0g._.js +3 -3
  34. package/.next/server/chunks/[root-of-the-server]__0jgr1dt1j95ku._.js +3 -3
  35. package/.next/server/chunks/[root-of-the-server]__0m0n163465-zb._.js +3 -3
  36. package/.next/server/chunks/[root-of-the-server]__0p7epsgp2b5m3._.js +3 -3
  37. package/.next/server/chunks/[root-of-the-server]__1i5e5sqg45ens._.js +3 -3
  38. package/.next/server/chunks/[root-of-the-server]__1vjt0neva-819._.js +3 -3
  39. package/.next/server/chunks/_0uqus0ehnijt-._.js +1 -1
  40. package/.next/server/chunks/lib_background_start_ts_11u_1uu8b9yuy._.js +1 -1
  41. package/.next/server/chunks/ssr/[root-of-the-server]__0_3l5tdzqy-td._.js +3 -0
  42. package/.next/server/chunks/ssr/[root-of-the-server]__10ockmlli-lun._.js +3 -0
  43. package/.next/server/chunks/ssr/{[root-of-the-server]__0dyligeswbb47._.js → [root-of-the-server]__16-gclvix9mjd._.js} +1 -1
  44. package/.next/server/chunks/ssr/[root-of-the-server]__1auodc3c0rppy._.js +3 -0
  45. package/.next/server/chunks/ssr/[root-of-the-server]__1cf6qt9agg_9-._.js +3 -3
  46. package/.next/server/chunks/ssr/[root-of-the-server]__1i9r59yk4i69p._.js +3 -0
  47. package/.next/server/chunks/ssr/[root-of-the-server]__1l3qp8u9yc_ig._.js +3 -0
  48. package/.next/server/chunks/ssr/_1p-0wsx9qfm68._.js +13 -0
  49. package/.next/server/chunks/ssr/app_map_18iu6j19jsqmu._.js +3 -0
  50. package/.next/server/chunks/ssr/node_modules_next_dist_1r3iqtbm45lqp._.js +3 -0
  51. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0q-w892nagajq.js +3 -0
  52. package/.next/server/middleware-build-manifest.js +11 -11
  53. package/.next/server/next-font-manifest.js +1 -1
  54. package/.next/server/next-font-manifest.json +4 -6
  55. package/.next/server/pages/404.html +1 -1
  56. package/.next/server/pages/500.html +1 -1
  57. package/.next/server/preview-props.json +3 -3
  58. package/.next/server/server-reference-manifest.js +1 -1
  59. package/.next/server/server-reference-manifest.json +1 -1
  60. package/.next/static/chunks/{1rljem7o1jtdo.js → 18kfexnrqek07.js} +1 -1
  61. package/.next/static/chunks/1hwbgd4nvvhg8.js +1 -0
  62. package/.next/static/chunks/25r4lkkf1shfo.css +3 -0
  63. package/.next/static/chunks/35ubvk2ivdjgs.js +1 -0
  64. package/.next/static/chunks/3ieqvmcg3hofj.js +31 -0
  65. package/.next/static/chunks/3w00e1w2125pp.js +11 -0
  66. package/.next/static/media/733da6bd8dac84c8-s.3hlisc-pwq13z.woff2 +0 -0
  67. package/.next/static/media/784318cea1dfcfa4-s.0-oo9_1x_xmvg.woff2 +0 -0
  68. package/.next/static/media/7e114457660b62ed-s.36fqqi66-3tjb.woff2 +0 -0
  69. package/.next/static/media/85e86a88f68a624a-s.357dd_6abeqge.woff2 +0 -0
  70. package/.next/static/media/9a321a2c78eff0b5-s.p.1bkzbscqrt8rl.woff2 +0 -0
  71. package/.next/static/media/9fecbd3e5ea9bccb-s.3_z45zcoc-xoz.woff2 +0 -0
  72. package/.next/static/media/c64053b510252f55-s.1kd-r_s9smv5m.woff2 +0 -0
  73. package/.next/static/media/c6a5c2fdc12da45c-s.p.17-aodiw50953.woff2 +0 -0
  74. package/.next/static/media/f263782c6a4bddee-s.1gyfqm5yhhzs7.woff2 +0 -0
  75. package/.next/trace +1 -1
  76. package/.next/trace-build +1 -1
  77. package/README.md +13 -4
  78. package/app/globals.css +91 -54
  79. package/app/layout.tsx +20 -11
  80. package/app/map/BackButton.tsx +5 -5
  81. package/app/map/BoxActions.tsx +20 -12
  82. package/app/map/Breadcrumb.tsx +132 -46
  83. package/app/map/DetailPanel.tsx +408 -297
  84. package/app/map/Explorer.tsx +268 -0
  85. package/app/map/Header.tsx +105 -0
  86. package/app/map/HelpDialog.tsx +37 -34
  87. package/app/map/Legend.tsx +19 -75
  88. package/app/map/LineCard.tsx +187 -0
  89. package/app/map/MapBox.tsx +73 -38
  90. package/app/map/MapCanvas.tsx +344 -115
  91. package/app/map/MapToolbar.tsx +377 -0
  92. package/app/map/MapView.tsx +217 -213
  93. package/app/map/RepoMenu.tsx +13 -12
  94. package/app/map/RoutedEdge.tsx +48 -16
  95. package/app/map/SearchPalette.tsx +6 -6
  96. package/app/map/SourceViewer.tsx +19 -17
  97. package/app/map/StatusBar.tsx +166 -0
  98. package/app/map/embed.ts +22 -2
  99. package/app/map/emphasis.ts +94 -8
  100. package/app/map/explorerRows.ts +85 -0
  101. package/app/map/flowNodes.ts +12 -7
  102. package/app/map/format.ts +2 -2
  103. package/app/map/history.ts +4 -3
  104. package/app/map/inspector.ts +113 -0
  105. package/app/map/labels.ts +66 -7
  106. package/app/map/narrow.ts +165 -85
  107. package/app/map/opening.ts +16 -0
  108. package/app/map/portals.ts +2 -2
  109. package/app/map/routes.ts +1060 -55
  110. package/app/map/runs.ts +108 -0
  111. package/app/map/shell.ts +91 -0
  112. package/app/map/shortcuts.ts +2 -1
  113. package/app/map/summaries.ts +41 -5
  114. package/app/map/text.ts +9 -1
  115. package/app/map/theme.ts +197 -0
  116. package/app/map/useDismiss.ts +20 -6
  117. package/app/map/useEditorBridge.ts +12 -1
  118. package/app/map/useThemeKind.ts +28 -0
  119. package/app/map/useWindowSize.ts +37 -0
  120. package/app/map/viewport.ts +134 -16
  121. package/app/map/weights.ts +80 -0
  122. package/app/page.tsx +3 -5
  123. package/lib/background/child.ts +2 -0
  124. package/lib/background/service.ts +26 -10
  125. package/lib/contracts.ts +25 -2
  126. package/lib/db/migrations/0011_plain_summaries_prompt_version.sql +1 -0
  127. package/lib/db/migrations/meta/0011_snapshot.json +1498 -0
  128. package/lib/db/migrations/meta/_journal.json +7 -0
  129. package/lib/db/schema.ts +2 -1
  130. package/lib/db/store/map.ts +6 -0
  131. package/lib/db/store/summaries.ts +14 -8
  132. package/lib/engine/describe.ts +2 -0
  133. package/lib/index/summarize/budget.ts +5 -2
  134. package/lib/index/summarize/claude.ts +19 -4
  135. package/lib/index/summarize/compare.ts +2 -2
  136. package/lib/index/summarize/plan.ts +73 -13
  137. package/lib/index/summarize/preview.ts +12 -9
  138. package/lib/index/summarize/prompts.ts +122 -25
  139. package/lib/index/summarize/run.ts +48 -18
  140. package/lib/index/summarize/snapshot.ts +7 -2
  141. package/lib/index/summarize/status.ts +3 -2
  142. package/lib/tools/text.ts +3 -2
  143. package/mcp/server.ts +1 -1
  144. package/package.json +4 -2
  145. package/scripts/commands/summarize-command.ts +27 -9
  146. package/.next/server/chunks/ssr/[root-of-the-server]__0ekw8p2ramybv._.js +0 -3
  147. package/.next/server/chunks/ssr/[root-of-the-server]__0fwbsqt9e2tr-._.js +0 -3
  148. package/.next/server/chunks/ssr/[root-of-the-server]__17_rqmx62cz59._.js +0 -3
  149. package/.next/server/chunks/ssr/[root-of-the-server]__1zfp6sltse4hf._.js +0 -3
  150. package/.next/server/chunks/ssr/_1d2woi6toj_0_._.js +0 -3
  151. package/.next/server/chunks/ssr/_1wfc1zz26g5ji._.js +0 -9
  152. package/.next/server/chunks/ssr/app_0gw6epmxyea3q._.js +0 -3
  153. package/.next/server/chunks/ssr/node_modules_@swc_helpers_cjs__interop_require_default_cjs_1ztp13a5szri_._.js +0 -3
  154. package/.next/server/chunks/ssr/node_modules_next_dist_1c5t_vsn6u8fr._.js +0 -3
  155. package/.next/static/chunks/02x9pxyl2d8om.css +0 -3
  156. package/.next/static/chunks/0p-0bv2dzer18.js +0 -7
  157. package/.next/static/chunks/10u7p2gj02qay.js +0 -1
  158. package/.next/static/chunks/31qp8jfkw0x2h.js +0 -31
  159. package/.next/static/media/123d516c9baeb953-s.1qc6dx89jd2qv.woff2 +0 -0
  160. package/.next/static/media/41ba59f553543ecf-s.3cb5lpr2l6xud.woff2 +0 -0
  161. package/.next/static/media/44ed10da57ebfb0e-s.2y65deuc30pmy.woff2 +0 -0
  162. package/.next/static/media/48eea41d8317494f-s.p.0wiir8udbzjvx.woff2 +0 -0
  163. package/.next/static/media/49b1d53681a91a99-s.1yd4_i3e35931.woff2 +0 -0
  164. package/.next/static/media/67bba87670b402d1-s.1u30mmyq6lnsd.woff2 +0 -0
  165. package/.next/static/media/6fca7e74603dd412-s.02z5rrbg5nt92.woff2 +0 -0
  166. package/.next/static/media/73263b2957b73100-s.2qt3tdwt-y9x_.woff2 +0 -0
  167. package/.next/static/media/7ac0b1cd3e695dd0-s.1i-sca43-qwng.woff2 +0 -0
  168. package/.next/static/media/916cd8a3bde3edf8-s.p.0oace-s_gkfks.woff2 +0 -0
  169. package/.next/static/media/a45aa1001bf9176f-s.2vemzm0itqzfy.woff2 +0 -0
  170. package/.next/static/media/a74d2542cc4c775f-s.29yke99gs9qpn.woff2 +0 -0
  171. package/.next/static/media/ab664c0e419cc841-s.3cvcemwuzoywn.woff2 +0 -0
  172. package/.next/static/media/c1b11b726b36a5e5-s.2rixgazldzomk.woff2 +0 -0
  173. package/.next/static/media/d6c1ff7e86974212-s.p.40sczeszzbjw1.woff2 +0 -0
  174. package/.next/static/media/faab88e4be272d29-s.0rgnxg2b64rzs.woff2 +0 -0
  175. package/app/map/ActivityBar.tsx +0 -81
  176. package/app/map/StatusPill.tsx +0 -93
  177. package/app/map/TopBar.tsx +0 -84
  178. /package/.next/static/{prDi039MhjlFqDOOwZ4aR → of6twfEZ3j95xtfQB_NSL}/_buildManifest.js +0 -0
  179. /package/.next/static/{prDi039MhjlFqDOOwZ4aR → of6twfEZ3j95xtfQB_NSL}/_clientMiddlewareManifest.js +0 -0
  180. /package/.next/static/{prDi039MhjlFqDOOwZ4aR → of6twfEZ3j95xtfQB_NSL}/_ssgManifest.js +0 -0
@@ -1,31 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,[55682,(e,t,r)=>{r._=function(e){return e&&e.__esModule?e:{default:e}}},90809,(e,t,r)=>{function n(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,r=new WeakMap;return(n=function(e){return e?r:t})(e)}r._=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var r=n(t);if(r&&r.has(e))return r.get(e);var o={__proto__:null},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var u in e)if("default"!==u&&Object.prototype.hasOwnProperty.call(e,u)){var a=i?Object.getOwnPropertyDescriptor(e,u):null;a&&(a.get||a.set)?Object.defineProperty(o,u,a):o[u]=e[u]}return o.default=e,r&&r.set(e,o),o}},47167,(e,t,r)=>{var n,o;t.exports=(null==(n=e.g.process)?void 0:n.env)&&"object"==typeof(null==(o=e.g.process)?void 0:o.env)?e.g.process:e.r(35451)},18576,(e,t,r)=>{Object.defineProperty(r,"__esModule",{value:!0});var n={WarningIcon:function(){return s},errorStyles:function(){return u},errorThemeCss:function(){return a}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});e.r(55682);let i=e.r(43476);e.r(71645);let u={container:{fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",display:"flex",alignItems:"center",justifyContent:"center"},card:{marginTop:"-32px",maxWidth:"325px",padding:"32px 28px",textAlign:"left"},icon:{marginBottom:"24px"},title:{fontSize:"24px",fontWeight:500,letterSpacing:"-0.02em",lineHeight:"32px",margin:"0 0 12px 0",color:"var(--next-error-title)"},message:{fontSize:"14px",fontWeight:400,lineHeight:"21px",margin:"0 0 20px 0",color:"var(--next-error-message)"},form:{margin:0},buttonGroup:{display:"flex",gap:"8px",alignItems:"center"},button:{display:"inline-flex",alignItems:"center",justifyContent:"center",height:"32px",padding:"0 12px",fontSize:"14px",fontWeight:500,lineHeight:"20px",borderRadius:"6px",cursor:"pointer",color:"var(--next-error-btn-text)",background:"var(--next-error-btn-bg)",border:"var(--next-error-btn-border)"},buttonSecondary:{display:"inline-flex",alignItems:"center",justifyContent:"center",height:"32px",padding:"0 12px",fontSize:"14px",fontWeight:500,lineHeight:"20px",borderRadius:"6px",cursor:"pointer",color:"var(--next-error-btn-secondary-text)",background:"var(--next-error-btn-secondary-bg)",border:"var(--next-error-btn-secondary-border)"},digestFooter:{position:"fixed",bottom:"32px",left:"0",right:"0",textAlign:"center",fontFamily:'ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace',fontSize:"12px",lineHeight:"18px",fontWeight:400,margin:"0",color:"var(--next-error-digest)"}},a=`
2
- :root {
3
- --next-error-bg: #fff;
4
- --next-error-text: #171717;
5
- --next-error-title: #171717;
6
- --next-error-message: #171717;
7
- --next-error-digest: #666666;
8
- --next-error-btn-text: #fff;
9
- --next-error-btn-bg: #171717;
10
- --next-error-btn-border: none;
11
- --next-error-btn-secondary-text: #171717;
12
- --next-error-btn-secondary-bg: transparent;
13
- --next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);
14
- }
15
- @media (prefers-color-scheme: dark) {
16
- :root {
17
- --next-error-bg: #0a0a0a;
18
- --next-error-text: #ededed;
19
- --next-error-title: #ededed;
20
- --next-error-message: #ededed;
21
- --next-error-digest: #a0a0a0;
22
- --next-error-btn-text: #0a0a0a;
23
- --next-error-btn-bg: #ededed;
24
- --next-error-btn-border: none;
25
- --next-error-btn-secondary-text: #ededed;
26
- --next-error-btn-secondary-bg: transparent;
27
- --next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);
28
- }
29
- }
30
- body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }
31
- `.replace(/\n\s*/g,"");function s(){return(0,i.jsx)("svg",{width:"32",height:"32",viewBox:"-0.2 -1.5 32 32",fill:"none",style:u.icon,children:(0,i.jsx)("path",{d:"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z",fill:"var(--next-error-title)"})})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},68027,(e,t,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"default",{enumerable:!0,get:function(){return u}}),e.r(55682);let n=e.r(43476);e.r(71645);let o=e.r(12354),i=e.r(18576),u=function({error:e}){let t=e?.digest,r=!!t;return(0,o.handleISRError)({error:e}),(0,n.jsxs)("html",{id:"__next_error__",children:[(0,n.jsx)("head",{children:(0,n.jsx)("style",{dangerouslySetInnerHTML:{__html:i.errorThemeCss}})}),(0,n.jsxs)("body",{children:[(0,n.jsx)("div",{style:i.errorStyles.container,children:(0,n.jsxs)("div",{style:i.errorStyles.card,children:[(0,n.jsx)(i.WarningIcon,{}),(0,n.jsx)("h1",{style:i.errorStyles.title,children:"This page couldn’t load"}),(0,n.jsx)("p",{style:i.errorStyles.message,children:r?"A server error occurred. Reload to try again.":"Reload to try again, or go back."}),(0,n.jsxs)("div",{style:i.errorStyles.buttonGroup,children:[(0,n.jsx)("form",{style:i.errorStyles.form,children:(0,n.jsx)("button",{type:"submit",style:i.errorStyles.button,children:"Reload"})}),!r&&(0,n.jsx)("button",{type:"button",style:i.errorStyles.buttonSecondary,onClick:()=>{window.history.length>1?window.history.back():window.location.href="/"},children:"Back"})]})]})}),t&&(0,n.jsxs)("p",{style:i.errorStyles.digestFooter,children:["ERROR ",t]})]})]})};("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},12354,(e,t,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"handleISRError",{enumerable:!0,get:function(){return o}});let n=e.r(1425);function o({error:e}){if(!n.workUnitAsyncStorage)return;let t=n.workUnitAsyncStorage.getStore();switch(t?.type){case"prerender":case"prerender-client":case"prerender-legacy":throw e&&console.error(e),e;case"request":case"prerender-runtime":case"validation-client":case"cache":case"private-cache":case"unstable-cache":case"build-time-generator":case void 0:return}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},1425,(e,t,r)=>{let n,o,i;Object.defineProperty(r,"__esModule",{value:!0});var u={actionAsyncStorage:function(){return n},workAsyncStorage:function(){return o},workUnitAsyncStorage:function(){return i}};for(var a in u)Object.defineProperty(r,a,{enumerable:!0,get:u[a]});("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},18800,(e,t,r)=>{var n=e.r(71645);function o(e){var t="https://react.dev/errors/"+e;if(1<arguments.length){t+="?args[]="+encodeURIComponent(arguments[1]);for(var r=2;r<arguments.length;r++)t+="&args[]="+encodeURIComponent(arguments[r])}return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function i(){}var u={d:{f:i,r:function(){throw Error(o(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},a=Symbol.for("react.portal"),s=Symbol.for("react.recoverable"),c=Symbol.for("react.optimistic_key"),l=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function f(e,t){return"font"===e?"":"string"==typeof t?"use-credentials"===t?t:"":void 0}r.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=u,r.browser=function(e){return{$$typeof:s,_reason:e}},r.createPortal=function(e,t){var r=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!t||1!==t.nodeType&&9!==t.nodeType&&11!==t.nodeType)throw Error(o(299));return function(e,t,r){var n=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:a,key:null==n?null:n===c?c:""+n,children:e,containerInfo:t,implementation:r}}(e,t,null,r)},r.flushSync=function(e){var t=l.T,r=u.p;try{if(l.T=null,u.p=2,e)return e()}finally{l.T=t,u.p=r,u.d.f()}},r.preconnect=function(e,t){"string"==typeof e&&(t=t?"string"==typeof(t=t.crossOrigin)?"use-credentials"===t?t:"":void 0:null,u.d.C(e,t))},r.prefetchDNS=function(e){"string"==typeof e&&u.d.D(e)},r.preinit=function(e,t){if("string"==typeof e&&t&&"string"==typeof t.as){var r=t.as,n=f(r,t.crossOrigin),o="string"==typeof t.integrity?t.integrity:void 0,i="string"==typeof t.fetchPriority?t.fetchPriority:void 0;"style"===r?u.d.S(e,"string"==typeof t.precedence?t.precedence:void 0,{crossOrigin:n,integrity:o,fetchPriority:i}):"script"===r&&u.d.X(e,{crossOrigin:n,integrity:o,fetchPriority:i,nonce:"string"==typeof t.nonce?t.nonce:void 0})}},r.preinitModule=function(e,t){if("string"==typeof e)if("object"==typeof t&&null!==t){if(null==t.as||"script"===t.as){var r=f(t.as,t.crossOrigin);u.d.M(e,{crossOrigin:r,integrity:"string"==typeof t.integrity?t.integrity:void 0,nonce:"string"==typeof t.nonce?t.nonce:void 0,fetchPriority:"string"==typeof t.fetchPriority?t.fetchPriority:void 0})}}else null==t&&u.d.M(e)},r.preload=function(e,t){if("string"==typeof e&&"object"==typeof t&&null!==t&&"string"==typeof t.as){var r=t.as,n=f(r,t.crossOrigin);u.d.L(e,r,{crossOrigin:n,integrity:"string"==typeof t.integrity?t.integrity:void 0,nonce:"string"==typeof t.nonce?t.nonce:void 0,type:"string"==typeof t.type?t.type:void 0,fetchPriority:"string"==typeof t.fetchPriority?t.fetchPriority:void 0,referrerPolicy:"string"==typeof t.referrerPolicy?t.referrerPolicy:void 0,imageSrcSet:"string"==typeof t.imageSrcSet?t.imageSrcSet:void 0,imageSizes:"string"==typeof t.imageSizes?t.imageSizes:void 0,media:"string"==typeof t.media?t.media:void 0})}},r.preloadModule=function(e,t){if("string"==typeof e)if(t){var r=f(t.as,t.crossOrigin);u.d.m(e,{as:"string"==typeof t.as&&"script"!==t.as?t.as:void 0,crossOrigin:r,integrity:"string"==typeof t.integrity?t.integrity:void 0,nonce:"string"==typeof t.nonce?t.nonce:void 0,fetchPriority:"string"==typeof t.fetchPriority?t.fetchPriority:void 0})}else u.d.m(e)},r.requestFormReset=function(e){u.d.r(e)},r.unstable_batchedUpdates=function(e,t){return e(t)},r.useFormState=function(e,t,r){return l.H.useFormState(e,t,r)},r.useFormStatus=function(){return l.H.useHostTransitionStatus()},r.version="19.3.0-canary-278794d7-20261002"},74080,(e,t,r)=>{e.i(47167),!function e(){if("u">typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),t.exports=e.r(18800)},45689,(e,t,r)=>{var n=Symbol.for("react.transitional.element");function o(e,t,r){var o=null;if(void 0!==r&&(o=""+r),void 0!==t.key&&(o=""+t.key),"key"in t)for(var i in r={},t)"key"!==i&&(r[i]=t[i]);else r=t;return{$$typeof:n,type:e,key:o,ref:void 0!==(t=r.ref)?t:null,props:r}}r.Fragment=Symbol.for("react.fragment"),r.jsx=o,r.jsxs=o},50740,(e,t,r)=>{var n=e.i(47167),o=Symbol.for("react.transitional.element"),i=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),c=Symbol.for("react.consumer"),l=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),g=Symbol.for("react.activity"),h=Symbol.for("react.view_transition"),v=Symbol.iterator,b={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},m=Object.assign,_={};function x(e,t,r){this.props=e,this.context=t,this.refs=_,this.updater=r||b}function S(){}function O(e,t,r){this.props=e,this.context=t,this.refs=_,this.updater=r||b}x.prototype.isReactComponent={},x.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},x.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},S.prototype=x.prototype;var j=O.prototype=new S;j.constructor=O,m(j,x.prototype),j.isPureReactComponent=!0;var T=Array.isArray;function E(){}var w={H:null,A:null,T:null,S:null},R=Object.prototype.hasOwnProperty;function C(e,t,r){var n=r.ref;return{$$typeof:o,type:e,key:t,ref:void 0!==n?n:null,props:r}}function P(e){return"object"==typeof e&&null!==e&&e.$$typeof===o}var k=/\/+/g;function H(e,t){var r,n;return"object"==typeof e&&null!==e&&null!=e.key?(r=""+e.key,n={"=":"=0",":":"=2"},"$"+r.replace(/[=:]/g,function(e){return n[e]})):t.toString(36)}function A(e,t,r){if(null==e)return e;var n=[],u=0;return!function e(t,r,n,u,a){var s,c,l,f=typeof t;("undefined"===f||"boolean"===f)&&(t=null);var d=!1;if(null===t)d=!0;else switch(f){case"bigint":case"string":case"number":d=!0;break;case"object":switch(t.$$typeof){case o:case i:d=!0;break;case y:return e((d=t._init)(t._payload),r,n,u,a)}}if(d)return a=a(t),d=""===u?"."+H(t,0):u,T(a)?(n="",null!=d&&(n=d.replace(k,"$&/")+"/"),e(a,r,n,"",function(e){return e})):null!=a&&(P(a)&&(s=a,c=n+(null==a.key||t&&t.key===a.key?"":(""+a.key).replace(k,"$&/")+"/")+d,a=C(s.type,c,s.props)),r.push(a)),1;d=0;var p=""===u?".":u+":";if(T(t))for(var g=0;g<t.length;g++)f=p+H(u=t[g],g),d+=e(u,r,n,f,a);else if("function"==typeof(g=null===(l=t)||"object"!=typeof l?null:"function"==typeof(l=v&&l[v]||l["@@iterator"])?l:null))for(t=g.call(t),g=0;!(u=t.next()).done;)f=p+H(u=u.value,g++),d+=e(u,r,n,f,a);else if("object"===f){if("function"==typeof t.then)return e(function(e){switch(e.status){case"fulfilled":return e.value;case"rejected":throw e.reason;default:switch("string"==typeof e.status?e.then(E,E):(e.status="pending",e.then(function(t){"pending"===e.status&&(e.status="fulfilled",e.value=t)},function(t){"pending"===e.status&&(e.status="rejected",e.reason=t)})),e.status){case"fulfilled":return e.value;case"rejected":throw e.reason}}throw e}(t),r,n,u,a);throw Error("Objects are not valid as a React child (found: "+("[object Object]"===(r=String(t))?"object with keys {"+Object.keys(t).join(", ")+"}":r)+"). If you meant to render a collection of children, use an array instead.")}return d}(e,n,"","",function(e){return t.call(r,e,u++)}),n}function M(e){if(-1===e._status){var t=(0,e._result)();t.then(function(r){(0===e._status||-1===e._status)&&(e._status=1,e._result=r,void 0===t.status&&(t.status="fulfilled",t.value=r))},function(r){(0===e._status||-1===e._status)&&(e._status=2,e._result=r,void 0===t.status&&(t.status="rejected",t.reason=r))}),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var I="function"==typeof reportError?reportError:function(e){if("object"==typeof window&&"function"==typeof window.ErrorEvent){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:"object"==typeof e&&null!==e&&"string"==typeof e.message?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if("object"==typeof n.default&&"function"==typeof n.default.emit)return void n.default.emit("uncaughtException",e);console.error(e)};function L(e){var t=w.T,r={};r.types=null!==t?t.types:null,w.T=r;try{var n=e(),o=w.S;null!==o&&o(r,n),"object"==typeof n&&null!==n&&"function"==typeof n.then&&n.then(E,I)}catch(e){I(e)}finally{null!==t&&null!==r.types&&(t.types=r.types),w.T=t}}function $(e){var t=w.T;if(null!==t){var r=t.types;null===r?t.types=[e]:-1===r.indexOf(e)&&r.push(e)}else L($.bind(null,e))}r.Activity=g,r.Children={map:A,forEach:function(e,t,r){A(e,function(){t.apply(this,arguments)},r)},count:function(e){var t=0;return A(e,function(){t++}),t},toArray:function(e){return A(e,function(e){return e})||[]},only:function(e){if(!P(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},r.Component=x,r.Fragment=u,r.Profiler=s,r.PureComponent=O,r.StrictMode=a,r.Suspense=d,r.ViewTransition=h,r.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=w,r.__COMPILER_RUNTIME={__proto__:null,c:function(e){return w.H.useMemoCache(e)}},r.addTransitionType=$,r.cache=function(e){return function(){return e.apply(null,arguments)}},r.cacheSignal=function(){return null},r.cloneElement=function(e,t,r){if(null==e)throw Error("The argument must be a React element, but you passed "+e+".");var n=m({},e.props),o=e.key;if(null!=t)for(i in void 0!==t.key&&(o=""+t.key),t)R.call(t,i)&&"key"!==i&&"__self"!==i&&"__source"!==i&&("ref"!==i||void 0!==t.ref)&&(n[i]=t[i]);var i=arguments.length-2;if(1===i)n.children=r;else if(1<i){for(var u=Array(i),a=0;a<i;a++)u[a]=arguments[a+2];n.children=u}return C(e.type,o,n)},r.createContext=function(e){return(e={$$typeof:l,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider=e,e.Consumer={$$typeof:c,_context:e},e},r.createElement=function(e,t,r){var n,o={},i=null;if(null!=t)for(n in void 0!==t.key&&(i=""+t.key),t)R.call(t,n)&&"key"!==n&&"__self"!==n&&"__source"!==n&&(o[n]=t[n]);var u=arguments.length-2;if(1===u)o.children=r;else if(1<u){for(var a=Array(u),s=0;s<u;s++)a[s]=arguments[s+2];o.children=a}if(e&&e.defaultProps)for(n in u=e.defaultProps)void 0===o[n]&&(o[n]=u[n]);return C(e,i,o)},r.createRef=function(){return{current:null}},r.forwardRef=function(e){return{$$typeof:f,render:e}},r.isValidElement=P,r.lazy=function(e){return{$$typeof:y,_payload:{_status:-1,_result:e},_init:M}},r.memo=function(e,t){return{$$typeof:p,type:e,compare:void 0===t?null:t}},r.startTransition=L,r.unstable_useCacheRefresh=function(){return w.H.useCacheRefresh()},r.use=function(e){return w.H.use(e)},r.useActionState=function(e,t,r){return w.H.useActionState(e,t,r)},r.useCallback=function(e,t){return w.H.useCallback(e,t)},r.useContext=function(e){return w.H.useContext(e)},r.useDebugValue=function(){},r.useDeferredValue=function(e,t){return w.H.useDeferredValue(e,t)},r.useEffect=function(e,t){return w.H.useEffect(e,t)},r.useEffectEvent=function(e){return w.H.useEffectEvent(e)},r.useId=function(){return w.H.useId()},r.useImperativeHandle=function(e,t,r){return w.H.useImperativeHandle(e,t,r)},r.useInsertionEffect=function(e,t){return w.H.useInsertionEffect(e,t)},r.useLayoutEffect=function(e,t){return w.H.useLayoutEffect(e,t)},r.useMemo=function(e,t){return w.H.useMemo(e,t)},r.useOptimistic=function(e,t){return w.H.useOptimistic(e,t)},r.useReducer=function(e,t,r){return w.H.useReducer(e,t,r)},r.useRef=function(e){return w.H.useRef(e)},r.useState=function(e){return w.H.useState(e)},r.useSyncExternalStore=function(e,t,r){return w.H.useSyncExternalStore(e,t,r)},r.useTransition=function(){return w.H.useTransition()},r.version="19.3.0-canary-278794d7-20261002"},71645,(e,t,r)=>{e.i(47167),t.exports=e.r(50740)},43476,(e,t,r)=>{e.i(47167),t.exports=e.r(45689)},43369,(e,t,r)=>{let n;e.i(47167),Object.defineProperty(r,"__esModule",{value:!0});var o={getAssetToken:function(){return s},getAssetTokenQuery:function(){return c},getDeploymentId:function(){return u},getDeploymentIdQuery:function(){return a}};for(var i in o)Object.defineProperty(r,i,{enumerable:!0,get:o[i]});function u(){return n}function a(e=!1){let t=n;return t?`${e?"&":"?"}dpl=${t}`:""}function s(){return!1}function c(e=!1){return""}"u">typeof window?(n=document.documentElement.dataset.dplId,document.documentElement.removeAttribute("data-dpl-id")):n=void 0},42732,(e,t,r)=>{e.i(47167),Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"HeadManagerContext",{enumerable:!0,get:function(){return n}});let n=(e.r(55682)._(e.r(71645))).default.createContext({})}],35451,(e,t,r)=>{var n={156:function(e){var t,r,n,o=e.exports={};function i(){throw Error("setTimeout has not been defined")}function u(){throw Error("clearTimeout has not been defined")}try{t="function"==typeof setTimeout?setTimeout:i}catch(e){t=i}try{r="function"==typeof clearTimeout?clearTimeout:u}catch(e){r=u}function a(e){if(t===setTimeout)return setTimeout(e,0);if((t===i||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(r){try{return t.call(null,e,0)}catch(r){return t.call(this,e,0)}}}var s=[],c=!1,l=-1;function f(){c&&n&&(c=!1,n.length?s=n.concat(s):l=-1,s.length&&d())}function d(){if(!c){var e=a(f);c=!0;for(var t=s.length;t;){for(n=s,s=[];++l<t;)n&&n[l].run();l=-1,t=s.length}n=null,c=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===u||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function p(e,t){this.fun=e,this.array=t}function y(){}o.nextTick=function(e){var t=Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];s.push(new p(e,t)),1!==s.length||c||a(d)},p.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=y,o.addListener=y,o.once=y,o.off=y,o.removeListener=y,o.removeAllListeners=y,o.emit=y,o.prependListener=y,o.prependOnceListener=y,o.listeners=function(e){return[]},o.binding=function(e){throw Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(e){throw Error("process.chdir is not supported")},o.umask=function(){return 0}}},o={};function i(e){var t=o[e];if(void 0!==t)return t.exports;var r=o[e]={exports:{}},u=!0;try{n[e](r,r.exports,i),u=!1}finally{u&&delete o[e]}return r.exports}i.ab="/ROOT/node_modules/next/dist/compiled/process/",t.exports=i(156)}]);
@@ -1,81 +0,0 @@
1
- "use client";
2
-
3
- import { useEffect, useState } from "react";
4
- import type { LiveEvent } from "@/lib/contracts";
5
- import { activityLabel, activityTitle, highlightedNote, newestTitle } from "./activity";
6
- import { ago } from "./format";
7
- import { DEMO } from "./mode";
8
-
9
- /** Where each older action leaves a narrowing bar: the second under 640 px, the third under 900 (the newest stays). */
10
- const OLDER_STEPS: readonly string[] = ["", "max-[640px]:hidden", "max-[900px]:hidden"];
11
- /**
12
- * Under 900 px the newest action takes the room it needs, and the older one only what's left (a container, so as that
13
- * runs out its time goes, then the rest of it, rather than squeezing to a sliver). At 900 and up they share the bar as
14
- * they always have.
15
- */
16
- const OLDER_ROOM = "max-[900px]:@container max-[900px]:basis-0 max-[900px]:grow";
17
- /** What an older action keeps in what's left: its time under 136 px, nothing under 64 (the dot and a few letters). */
18
- const OLDER_TIME = "@max-[136px]:hidden";
19
- const OLDER_REST = "@max-[64px]:hidden";
20
-
21
- /**
22
- * The activity bar (VISUAL_REFRESH.md §6): a slim strip along the bottom, always there, with Claude Code's last 3
23
- * actions, newest first, each with an orange dot. Live activity is the demo's differentiator, so it's never hidden;
24
- * it stays slim so the Map remains the focus. E1 adds the Guide's input beside it. While show_on_map has highlighted
25
- * something, its right end says how many and offers Clear (Esc does the same once nothing is selected).
26
- *
27
- * In a narrow window (VISUAL_REFRESH.md, "Narrow windows") the older actions go first: 2 under 900 px, the newest
28
- * keeping the room it needs and the older one what's left, the newest alone under 640, and under 520 its time and the
29
- * "Claude Code" word go too (the dot's title keeps the word). Each action truncates, whole in its title, and the
30
- * newest's title lists the older ones with their times. The highlights' count and Clear always stay.
31
- */
32
- export default function ActivityBar({ recent, connected, highlightCount, onClear }: {
33
- recent: readonly LiveEvent[];
34
- connected: boolean;
35
- /** How many places show_on_map has highlighted. */
36
- highlightCount: number;
37
- onClear: () => void;
38
- }){
39
- // the clock lives in state, ticking every second: reading Date.now() during render isn't allowed
40
- const [now, setNow] = useState(0);
41
- useEffect(() => {
42
- const timer = setInterval(() => setNow(Date.now()), 1_000);
43
- return () => clearInterval(timer);
44
- }, []);
45
-
46
- const highlightNote = highlightedNote(highlightCount);
47
-
48
- // the static demo never connects: say why the bar is empty, instead of "Not connected" (ADR-049)
49
- const empty = DEMO
50
- ? "In the app, Claude Code's tool calls show up here as it works. This static demo has no live channel."
51
- : connected ? "No tool calls yet" : "Not connected";
52
-
53
- return (
54
- <footer data-testid="activity-bar" className="relative z-20 flex h-8 shrink-0 items-center gap-4 border-t border-hairline bg-panel px-4 text-[13px]">
55
- <span className="flex shrink-0 items-center gap-2 text-text-2" title={connected ? "Claude Code: connected to the live channel" : "Claude Code: not connected to the live channel"}>
56
- <span aria-hidden className={`h-2 w-2 rounded-full ${connected ? "bg-text-2" : "border border-text-2"}`} />
57
- <span className={recent.length > 0 ? "max-[520px]:hidden" : undefined}>Claude Code</span>
58
- </span>
59
- {recent.length === 0
60
- ? <span className="min-w-0 truncate text-text-2" title={empty}>{empty}</span>
61
- : (
62
- <ol aria-label="Claude Code's last actions" className="flex min-w-0 flex-1 items-center gap-6">
63
- {recent.map((event, i) => (
64
- <li key={`${event.at}\0${i}`} className={`flex min-w-0 items-center gap-2 ${OLDER_STEPS[i] ?? ""} ${i > 0 ? OLDER_ROOM : ""}`}>
65
- <span aria-hidden className={`h-2 w-2 shrink-0 rounded-full bg-agent ${i > 0 ? OLDER_REST : ""}`} />
66
- {/* the newest's title also holds what a narrow bar drops: the older actions and the times */}
67
- <span className={`truncate ${i === 0 ? "text-text" : `text-text-2 ${OLDER_REST}`}`} title={i === 0 ? newestTitle(recent, now) : activityTitle(event)}>{activityLabel(event)}</span>
68
- {now > 0 && <span className={`shrink-0 text-[12px] text-text-2 max-[520px]:hidden ${i > 0 ? OLDER_TIME : ""}`}>{ago(Math.max(0, now - Date.parse(event.at)))}</span>}
69
- </li>
70
- ))}
71
- </ol>
72
- )}
73
- {highlightNote !== null && (
74
- <span className="ml-auto flex shrink-0 items-center gap-3 text-text-2">
75
- {highlightNote}
76
- <button type="button" onClick={onClear} className="text-control hover:underline" title="Clear Claude Code's highlights (Esc)">Clear</button>
77
- </span>
78
- )}
79
- </footer>
80
- );
81
- }
@@ -1,93 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useState, type CSSProperties } from "react";
4
- import { IconChevronDown } from "@tabler/icons-react";
5
- import type { IndexStatus, StageName } from "@/lib/contracts";
6
- import { api, ApiError } from "./api";
7
- import { formatCount, headline, stageLabel, type Tone } from "./format";
8
- import { DEMO } from "./mode";
9
- import { placePopover, usePlaceOnResize } from "./popover";
10
- import { useDismiss } from "./useDismiss";
11
-
12
- /** The status menu's width, at normal sizes (narrower only when the Map is). */
13
- const MENU_WIDTH = 340;
14
-
15
- /** Green means indexed and nothing else (VISUAL_REFRESH.md §2); a failure, or nothing indexed, is the error color. No motion. */
16
- const DOTS: Record<Tone, string> = {
17
- ok: "bg-ok",
18
- busy: "bg-text-2",
19
- warn: "bg-danger",
20
- off: "bg-text-2",
21
- };
22
-
23
- const STAGES: readonly StageName[] = ["structure", "summaries", "embeddings"];
24
-
25
- /**
26
- * The index status (VISUAL_REFRESH.md §6: a status dot on the right of the top bar): the stage that most needs
27
- * attention, in one line. Opening it lists every stage with its counts and note, and offers a re-index
28
- * (POST /api/index) with its progress. The static demo's index is frozen, so there it says so instead (ADR-049).
29
- */
30
- export default function StatusPill({ status }: { status: IndexStatus | null }){
31
- const [open, setOpen] = useState(false);
32
- const [reindex, setReindex] = useState<string | null>(null);
33
- // where the menu opens, worked out as it opens and as the window resizes: right under the pill, kept inside a narrow
34
- // Map (popover.ts)
35
- const [menuPlace, setMenuPlace] = useState<CSSProperties>({ right: 0, width: MENU_WIDTH });
36
- const ref = useDismiss<HTMLDivElement>(open, () => setOpen(false));
37
- const place = useCallback(() => {
38
- if (ref.current) setMenuPlace(placePopover(ref.current, MENU_WIDTH, "end"));
39
- }, [ref]);
40
- usePlaceOnResize(open, place);
41
- if (status === null) return null;
42
- const head = headline(status);
43
- const toggle = (): void => {
44
- if (!open) place();
45
- setOpen((o) => !o);
46
- };
47
-
48
- const runReindex = (): void => {
49
- setReindex("starting…");
50
- api.reindex((p) => setReindex(`${p.stage} ${formatCount(p.done)} / ${formatCount(p.total)}`)).then(
51
- (done) => setReindex(`re-indexed ${formatCount(done.files)} files in ${(done.totalMs / 1000).toFixed(1)} s`),
52
- (err: unknown) => setReindex(err instanceof ApiError ? err.message : "the re-index failed"),
53
- );
54
- };
55
-
56
- // a narrow window keeps the dot alone (TopBar's steps), and a squeezed pill truncates its words: the title has them
57
- return (
58
- <div ref={ref} className="relative min-w-0">
59
- <button
60
- type="button"
61
- data-testid="status-pill"
62
- onClick={toggle}
63
- aria-expanded={open}
64
- title={`${head.text} · ${DEMO ? "Index status: what's indexed" : "Index status: what's indexed, and re-index"}`}
65
- className="flex max-w-full items-center gap-2 rounded-md border border-border px-2.5 py-1 text-[12px] text-text-2 hover:border-text-2 hover:text-text"
66
- >
67
- <span aria-hidden className={`h-2 w-2 shrink-0 rounded-full ${DOTS[head.tone]}`} />
68
- <span className="truncate max-[520px]:hidden">{head.text}</span>
69
- <IconChevronDown aria-hidden size={14} stroke={1.75} className={`shrink-0 ${open ? "rotate-180" : ""}`} />
70
- </button>
71
- {open && (
72
- <div data-testid="status-menu" data-covers style={menuPlace} className="absolute top-9 z-30 space-y-3 overflow-y-auto rounded-lg border border-border bg-surface p-3 text-[12px] text-text-2">
73
- {STAGES.map((name) => (
74
- <div key={name}>
75
- <div className="text-[13px] text-text">{stageLabel(name, status.stages[name])}</div>
76
- {status.stages[name].note && <div>{status.stages[name].note}</div>}
77
- </div>
78
- ))}
79
- <div className="flex items-center justify-between gap-3 border-t border-hairline pt-3">
80
- {DEMO
81
- ? <span>A static demo: the index is frozen at export.</span>
82
- : (
83
- <>
84
- <span className="truncate" title={reindex ?? `index version ${status.indexVersion}`}>{reindex ?? `index version ${status.indexVersion}`}</span>
85
- <button type="button" onClick={runReindex} className="shrink-0 text-[13px] text-control underline underline-offset-2 hover:text-text">Re-index</button>
86
- </>
87
- )}
88
- </div>
89
- </div>
90
- )}
91
- </div>
92
- );
93
- }
@@ -1,84 +0,0 @@
1
- "use client";
2
-
3
- import { useSyncExternalStore, type ReactNode } from "react";
4
- import Image from "next/image";
5
- import { IconHelp, IconSearch } from "@tabler/icons-react";
6
-
7
- type TopBarProps = {
8
- /** The repo as "owner / repo", or the repo picker. */
9
- repo: ReactNode;
10
- /** Opens ⌘K search. The field appears once it's passed. */
11
- onSearch?: () => void;
12
- /** The index-status dot. */
13
- status?: ReactNode;
14
- /** Opens the help (owner review). */
15
- onHelp?: () => void;
16
- };
17
-
18
- const noSubscription = () => () => {};
19
-
20
- /**
21
- * The top bar (VISUAL_REFRESH.md §6), left to right: the Nebulosity mark and name, the repo as "owner / repo", the
22
- * view's title, a wide search field, and the index status on the right. Structure is v1's only lens, so the view title
23
- * stands where PIVOT_SPEC.md §7's lens switcher will go when History (E3) and Clusters (E5) arrive.
24
- *
25
- * A narrower window drops secondary text, one piece per step (VISUAL_REFRESH.md, "Narrow windows"), so nothing ever
26
- * sits on anything else: under 1100 px the view title, under 768 the search's shortcut (sooner if the field can't hold
27
- * it and its words whole), under 640 its words (it becomes an icon beside the help), under 520 the status pill's words
28
- * (StatusPill), under 440 the Nebulosity name beside the mark. Between steps the search's words truncate first, then
29
- * the status words and the repo's owner, then its name, each whole in a title. The steps go by the window's width,
30
- * which is the Map's own down to the floor (narrow.ts); under the floor every step has been taken.
31
- */
32
- export default function TopBar({ repo, onSearch, status, onHelp }: TopBarProps){
33
- // the server renders "Ctrl K"; a Mac shows "⌘K" once hydrated, without a mismatch
34
- const isMac = useSyncExternalStore(noSubscription, () => /Mac|iPhone|iPad/.test(navigator.platform), () => false);
35
-
36
- return (
37
- <header className="pointer-events-auto relative z-20 flex h-12 shrink-0 items-center gap-4 border-b border-hairline bg-canvas px-4 max-[440px]:gap-3">
38
- <div className="flex shrink-0 items-center gap-2">
39
- <Image src="/icon.svg" alt="" width={18} height={18} unoptimized />
40
- <span className="text-[14px] font-medium text-text max-[440px]:hidden">Nebulosity</span>
41
- </div>
42
- <span aria-hidden className="h-4 w-px shrink-0 bg-hairline" />
43
- <div className="flex min-w-0 items-center gap-3">
44
- {repo}
45
- <span className="shrink-0 text-[13px] text-text-2 max-[1100px]:hidden">Dependency map</span>
46
- </div>
47
- {/* the search field takes what the bar has left, so its words (w-0: they don't hold the field open) truncate
48
- before the repo's name or the status words do; a container, so its shortcut goes as soon as the field
49
- can't hold it and the words whole (256 px), the words before they're cut to a letter (90 px), and it's
50
- never narrower than its icon */}
51
- <div className="@container flex min-w-[42px] flex-1 justify-center max-[640px]:justify-end">
52
- {onSearch && (
53
- <button
54
- type="button"
55
- onClick={onSearch}
56
- data-testid="search-button"
57
- aria-label="Search files and concepts"
58
- title={`Search files and concepts (${isMac ? "⌘K" : "Ctrl K"})`}
59
- className="flex w-full max-w-xl cursor-text items-center gap-2 rounded-lg border border-border bg-surface px-3 py-1.5 text-[13px] text-text-2 hover:border-text-2 max-[640px]:w-auto max-[640px]:cursor-pointer max-[640px]:px-2"
60
- >
61
- <IconSearch aria-hidden size={16} stroke={1.75} className="shrink-0" />
62
- <span className="w-0 flex-1 truncate text-left max-[640px]:hidden @max-[90px]:hidden">Search files and concepts</span>
63
- <kbd className="shrink-0 rounded-md border border-border px-1.5 font-sans text-[12px] text-text-2 max-[768px]:hidden @max-[256px]:hidden">{isMac ? "⌘K" : "Ctrl K"}</kbd>
64
- </button>
65
- )}
66
- </div>
67
- <div className="flex min-w-0 items-center gap-2">
68
- {onHelp && (
69
- <button
70
- type="button"
71
- onClick={onHelp}
72
- data-testid="help-button"
73
- aria-label="How to use the Map"
74
- title="How to use the Map (?)"
75
- className="grid h-7 w-7 shrink-0 place-items-center rounded-md border border-border text-text-2 hover:border-text-2 hover:text-text"
76
- >
77
- <IconHelp aria-hidden size={16} stroke={1.75} />
78
- </button>
79
- )}
80
- {status}
81
- </div>
82
- </header>
83
- );
84
- }