@leanspec/ui 0.2.5-dev.20251120072524 → 0.2.5-dev.20251120093243
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/packages/ui/.next/BUILD_ID +1 -1
- package/.next/standalone/packages/ui/.next/app-path-routes-manifest.json +9 -0
- package/.next/standalone/packages/ui/.next/build-manifest.json +7 -6
- package/.next/standalone/packages/ui/.next/prerender-manifest.json +28 -3
- package/.next/standalone/packages/ui/.next/routes-manifest.json +71 -0
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/packages/ui/.next/server/app/_not-found.rsc +20 -19
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_full.segment.rsc +20 -19
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_index.segment.rsc +26 -25
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +3 -3
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/packages/ui/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -5
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js +2 -3
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/[id]/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js +2 -3
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/discover/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js +6 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/list-directory/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js +2 -3
- package/.next/standalone/packages/ui/.next/server/app/api/local-projects/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js +9 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/[spec]/status/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js +4 -3
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/specs/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/build-manifest.json +11 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js +8 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/[id]/stats/route_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/revalidate/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/dependency-graph/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/specs/[id]/subspecs/[file]/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js +3 -4
- package/.next/standalone/packages/ui/.next/server/app/api/stats/route.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js +21 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js +21 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/[specId]/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js +20 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/[projectId]/specs/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/app-paths-manifest.json +3 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/build-manifest.json +18 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/next-font-manifest.json +6 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page/server-reference-manifest.json +4 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js +19 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js.map +5 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page.js.nft.json +1 -0
- package/.next/standalone/packages/ui/.next/server/app/projects/page_client-reference-manifest.js +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.html +2 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.meta +14 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.rsc +34 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_full.segment.rsc +34 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_index.segment.rsc +27 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/_tree.segment.rsc +9 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects/__PAGE__.segment.rsc +9 -0
- package/.next/standalone/packages/ui/.next/server/app/projects.segments/projects.segment.rsc +4 -0
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js +4 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/specs/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/specs/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/specs/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app/stats/page/build-manifest.json +5 -4
- package/.next/standalone/packages/ui/.next/server/app/stats/page.js +2 -2
- package/.next/standalone/packages/ui/.next/server/app/stats/page.js.nft.json +1 -1
- package/.next/standalone/packages/ui/.next/server/app/stats/page_client-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/app-paths-manifest.json +9 -0
- package/.next/standalone/packages/ui/.next/server/chunks/6681a__next-internal_server_app_api_projects_[id]_specs_[spec]_route_actions_d018d9e0.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/730ea_ui__next-internal_server_app_api_projects_[id]_stats_route_actions_a0bb04a8.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__0fbfea15._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__126dea7b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__1f037512._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__3559376c._.js +21 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__548e27d4._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/{[root-of-the-server]__d293d769._.js → [root-of-the-server]__65667b70._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__675a763e._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/{[root-of-the-server]__c83721f3._.js → [root-of-the-server]__803d07f0._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8075fe29._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__8233e09b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__84cdc14a._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__9ce722b4._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__a2d7cbed._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__aa677b0d._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__ac744182._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__bb9fca84._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/{[root-of-the-server]__fad83967._.js → [root-of-the-server]__bdc3963a._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/{[root-of-the-server]__57791a48._.js → [root-of-the-server]__f5c6d6b8._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__fb91986f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_local-projects_list-directory_route_actions_d620ec1a.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/f825c_server_app_api_projects_[id]_specs_[spec]_status_route_actions_e9f1bdc5.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui__next-internal_server_app_api_projects_[id]_route_actions_bff49675.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_db_index_ts_556307fa._.js +64 -5
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_0bd881ee._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/packages_ui_src_lib_specs_sources_database-source_ts_baa0160d._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/38a22_sonner_dist_index_mjs_207730fe._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/6e9bd_next_dist_7af75658._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{_a5b58449._.js → 6e9bd_next_dist_df5dcbe9._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/730ea_ui__next-internal_server_app_projects_[projectId]_specs_page_actions_82e32fe4.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__01bfc8ff._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__1d0c2012._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__4ec37765._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__1af33d49._.js → [root-of-the-server]__50122e7e._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__34ab4950._.js → [root-of-the-server]__5382b397._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__73f60f12._.js +7 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__88a691ee._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__a7ae8552._.js +7 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__bdbbba01._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__c592f5d1._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__cc589a54._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ec5b96a5._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/{[root-of-the-server]__cbbbfb5d._.js → [root-of-the-server]__fd80e4dd._.js} +2 -2
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_000dd317._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_196b5a83._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_39562b2a._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_3b617676._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_4129cc0f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6174313a._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6e4dd8b6._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_85effc18._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_ad8c1e99._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_bae6d2b8._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_c2f54661._.js +5 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_fdd7780b._.js +4 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/f825c_server_app_projects_[projectId]_specs_[specId]_page_actions_22d9c35e.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_af9d3830._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_[projectId]_page_actions_f2986585.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui__next-internal_server_app_projects_page_actions_715940ea.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_be242d6c._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_[projectId]_project-context-syncer_tsx_7954ea3b._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_projects_page_tsx_6e166c8e._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_app_specs_specs-client_tsx_0bb8f8f8._.js +1 -1
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_components_ui_select_tsx_7e21d40f._.js +3 -0
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/packages_ui_src_lib_specs_sources_database-source_ts_f7186c2a._.js +60 -1
- package/.next/standalone/packages/ui/.next/server/middleware-build-manifest.js +5 -4
- package/.next/standalone/packages/ui/.next/server/pages/404.html +2 -2
- package/.next/standalone/packages/ui/.next/server/pages/500.html +2 -2
- package/.next/standalone/packages/ui/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/packages/ui/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/07f48b316e895080.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/0a7be410b438418a.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/1089ca88f6bef846.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/17471c87082c392c.js +5 -0
- package/.next/standalone/packages/ui/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/35ccd3286e538bd2.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/571033caca823138.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/5c2072ad938de8ed.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/843e1dfdc28e1385.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/9dad7fd31627df80.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/afb7c5a4255f4081.js +3 -0
- package/.next/standalone/packages/ui/.next/static/chunks/{c557ac675be79771.js → b760a3a9c2c8be28.js} +1 -1
- package/.next/standalone/packages/ui/.next/static/chunks/dcdd95180149fa10.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/ebd89051637b9a47.js +4 -0
- package/.next/standalone/packages/ui/.next/static/chunks/f9db24028d8c058e.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/fb640f50455ba34f.js +1 -0
- package/.next/standalone/packages/ui/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
- package/.next/standalone/packages/ui/bin/ui.js +17 -7
- package/.next/standalone/packages/ui/package.json +2 -1
- package/.next/standalone/packages/ui/src/app/api/local-projects/list-directory/route.ts +38 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/route.ts +97 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/route.ts +38 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/[spec]/status/route.ts +97 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/specs/route.ts +7 -0
- package/.next/standalone/packages/ui/src/app/api/projects/[id]/stats/route.ts +19 -0
- package/.next/standalone/packages/ui/src/app/api/projects/route.ts +48 -1
- package/.next/standalone/packages/ui/src/app/dashboard-client.tsx +67 -6
- package/.next/standalone/packages/ui/src/app/layout.tsx +11 -8
- package/.next/standalone/packages/ui/src/app/not-found.tsx +1 -1
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/layout.tsx +18 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/page.tsx +10 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/project-context-syncer.tsx +16 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/[specId]/page.tsx +34 -0
- package/.next/standalone/packages/ui/src/app/projects/[projectId]/specs/page.tsx +20 -0
- package/.next/standalone/packages/ui/src/app/projects/page.tsx +156 -0
- package/.next/standalone/packages/ui/src/app/specs/specs-client.tsx +7 -2
- package/.next/standalone/packages/ui/src/components/create-project-dialog.tsx +139 -0
- package/.next/standalone/packages/ui/src/components/directory-picker.tsx +191 -0
- package/.next/standalone/packages/ui/src/components/main-sidebar.tsx +4 -0
- package/.next/standalone/packages/ui/src/components/project-switcher.tsx +105 -196
- package/.next/standalone/packages/ui/src/components/ui/dropdown-menu.tsx +200 -0
- package/.next/standalone/packages/ui/src/components/ui/popover.tsx +31 -0
- package/.next/standalone/packages/ui/src/contexts/project-context.tsx +10 -6
- package/.next/standalone/packages/ui/src/lib/db/index.ts +100 -0
- package/.next/standalone/packages/ui/src/lib/projects/registry.ts +77 -3
- package/.next/standalone/packages/ui/src/lib/specs/sources/multi-project-source.ts +4 -4
- package/.next/standalone/packages/ui/tsconfig.tsbuildinfo +1 -1
- package/.next/static/chunks/07f48b316e895080.js +1 -0
- package/.next/static/chunks/0a7be410b438418a.js +1 -0
- package/.next/static/chunks/1089ca88f6bef846.js +1 -0
- package/.next/static/chunks/17471c87082c392c.js +5 -0
- package/.next/static/chunks/220ba5cb8fe4dd69.js +1 -0
- package/.next/static/chunks/35ccd3286e538bd2.js +1 -0
- package/.next/static/chunks/571033caca823138.js +1 -0
- package/.next/static/chunks/5a6fc30cd64085b4.css +1 -0
- package/.next/static/chunks/5c2072ad938de8ed.js +1 -0
- package/.next/static/chunks/843e1dfdc28e1385.js +1 -0
- package/.next/static/chunks/9dad7fd31627df80.js +1 -0
- package/.next/static/chunks/{c3d4d07de959ecf1.js → a055d4b2866ff8d4.js} +1 -1
- package/.next/static/chunks/afb7c5a4255f4081.js +3 -0
- package/.next/static/chunks/{c557ac675be79771.js → b760a3a9c2c8be28.js} +1 -1
- package/.next/static/chunks/dcdd95180149fa10.js +1 -0
- package/.next/static/chunks/ebd89051637b9a47.js +4 -0
- package/.next/static/chunks/f9db24028d8c058e.js +1 -0
- package/.next/static/chunks/fb640f50455ba34f.js +1 -0
- package/.next/static/chunks/turbopack-b9690cacbf9fe48c.js +3 -0
- package/bin/ui.js +17 -7
- package/package.json +2 -1
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__175bef84._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__4b3c3001._.js +0 -21
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__4b77d48f._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__60b6d106._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__a627840f._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__beb134c0._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c6689757._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__c8a20942._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__cd1fb0a2._.js +0 -4
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__dfa71dcd._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/[root-of-the-server]__e9ba3fa9._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ecee3_js-yaml_dist_js-yaml_mjs_0775f118._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__a9d7fd42._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__b2fe773d._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__b3633d6e._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__e79a982a._.js +0 -7
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/[root-of-the-server]__ff03fc1e._.js +0 -7
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_66209e84._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_6cd9a5e0._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b483c9fe._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/_b5040d31._.js +0 -5
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_9710705b._.js +0 -3
- package/.next/standalone/packages/ui/.next/server/chunks/ssr/node_modules__pnpm_b8ff10b9._.js +0 -3
- package/.next/standalone/packages/ui/.next/static/chunks/093ea4b175adb770.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
- package/.next/standalone/packages/ui/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/aa47b212786d8695.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/ae04dcd433be6dab.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/c0576ccd1437ac5e.css +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
- package/.next/standalone/packages/ui/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/d79bf953f0dfb650.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
- package/.next/standalone/packages/ui/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
- package/.next/standalone/packages/ui/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
- package/.next/static/chunks/093ea4b175adb770.js +0 -1
- package/.next/static/chunks/5f97d665a4d9dc62.js +0 -3
- package/.next/static/chunks/9b7b7024c39c5f99.js +0 -1
- package/.next/static/chunks/aa47b212786d8695.js +0 -1
- package/.next/static/chunks/ae04dcd433be6dab.js +0 -1
- package/.next/static/chunks/c0576ccd1437ac5e.css +0 -1
- package/.next/static/chunks/c0fe4c94c7282ac0.js +0 -4
- package/.next/static/chunks/c61cbb6a0ba3b6ab.js +0 -1
- package/.next/static/chunks/d79bf953f0dfb650.js +0 -1
- package/.next/static/chunks/e50fb8d0b728cd35.js +0 -5
- package/.next/static/chunks/e6e238dbf1d3e740.js +0 -1
- package/.next/static/chunks/turbopack-9cc79aa1b34ffcbe.js +0 -3
- /package/.next/standalone/packages/ui/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
- /package/.next/standalone/packages/ui/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/packages/ui/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
- /package/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_buildManifest.js +0 -0
- /package/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{fMRsihZys1Dhy9qQRwNrc → T1wNN9JmkdwBabQsqL-tC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,17612,22453,e=>{"use strict";var t=e.i(90022),s=e.i(31231),i=e.i(87985);let l="u">typeof window?s.useLayoutEffect:s.useEffect;function n(e){if(void 0!==e)switch(typeof e){case"number":return e;case"string":if(e.endsWith("px"))return parseFloat(e)}}let r=null;function a({containerElement:e,direction:t,isRtl:s,scrollOffset:i}){if("horizontal"===t&&s)switch(function(e=!1){if(null===r||e){let e=document.createElement("div"),t=e.style;t.width="50px",t.height="50px",t.overflow="scroll",t.direction="rtl";let s=document.createElement("div"),i=s.style;return i.width="100px",i.height="100px",e.appendChild(s),document.body.appendChild(e),e.scrollLeft>0?r="positive-descending":(e.scrollLeft=1,r=0===e.scrollLeft?"negative":"positive-ascending"),document.body.removeChild(e),r}return r}()){case"negative":return-i;case"positive-descending":if(e){let{clientWidth:t,scrollLeft:s,scrollWidth:i}=e;return i-t-s}}return i}function o(e,t="Assertion error"){if(!e)throw console.error(t),Error(t)}function c(e,t){if(e===t)return!0;if(!!e!=!!t||(o(void 0!==e),o(void 0!==t),Object.keys(e).length!==Object.keys(t).length))return!1;for(let s in e)if(!Object.is(t[s],e[s]))return!1;return!0}function d({cachedBounds:e,itemCount:t,itemSize:s}){if(0===t)return 0;if("number"==typeof s)return t*s;{let s=e.get(0===e.size?0:e.size-1);return o(void 0!==s,"Unexpected bounds cache miss"),t*((s.scrollOffset+s.size)/e.size)}}function u({cachedBounds:e,containerScrollOffset:t,containerSize:s,itemCount:i,overscanCount:l}){let n=i-1,r=0,a=-1,o=0,c=-1,d=0;for(;d<n;){let s=e.get(d);if(s.scrollOffset+s.size>t)break;d++}for(o=Math.max(0,(r=d)-l);d<n;){let i=e.get(d);if(i.scrollOffset+i.size>=t+s)break;d++}return c=Math.min(i-1,(a=Math.min(n,d))+l),r<0&&(r=0,a=-1,o=0,c=-1),{startIndexVisible:r,stopIndexVisible:a,startIndexOverscan:o,stopIndexOverscan:c}}function h(e,t){let{ariaAttributes:s,style:i,...l}=e,{ariaAttributes:n,style:r,...a}=t;return c(s,n)&&c(i,r)&&c(l,a)}function f({children:e,className:i,defaultHeight:r=0,listRef:f,onResize:m,onRowsRendered:x,overscanCount:p=3,rowComponent:g,rowCount:v,rowHeight:S,rowProps:b,tagName:w="div",style:j,...y}){let N=(0,s.useMemo)(()=>b,Object.values(b)),C=(0,s.useMemo)(()=>(0,s.memo)(g,h),[g]),[I,z]=(0,s.useState)(null),T=null!=S&&"object"==typeof S&&"getAverageRowHeight"in S&&"function"==typeof S.getAverageRowHeight,{getCellBounds:O,getEstimatedSize:R,scrollToIndex:E,startIndexOverscan:A,startIndexVisible:M,stopIndexOverscan:k,stopIndexVisible:L}=function({containerElement:e,containerStyle:t,defaultContainerSize:i=0,direction:r,isRtl:h=!1,itemCount:f,itemProps:m,itemSize:x,onResize:p,overscanCount:g}){var v;let S,[b,w]=(0,s.useState)({startIndexVisible:0,startIndexOverscan:0,stopIndexVisible:-1,stopIndexOverscan:-1}),{startIndexVisible:j,startIndexOverscan:y,stopIndexVisible:N,stopIndexOverscan:C}={startIndexVisible:Math.min(f-1,b.startIndexVisible),startIndexOverscan:Math.min(f-1,b.startIndexOverscan),stopIndexVisible:Math.min(f-1,b.stopIndexVisible),stopIndexOverscan:Math.min(f-1,b.stopIndexOverscan)},{height:I=i,width:z=i}=function({box:e,defaultHeight:t,defaultWidth:i,disabled:r,element:a,mode:o,style:c}){let{styleHeight:d,styleWidth:u}=(0,s.useMemo)(()=>({styleHeight:n(c?.height),styleWidth:n(c?.width)}),[c?.height,c?.width]),[h,f]=(0,s.useState)({height:t,width:i}),m=r||"only-height"===o&&void 0!==d||"only-width"===o&&void 0!==u||void 0!==d&&void 0!==u;return l(()=>{if(null===a||m)return;let t=new ResizeObserver(e=>{for(let t of e){let{contentRect:e,target:s}=t;a===s&&f(t=>t.height===e.height&&t.width===e.width?t:{height:e.height,width:e.width})}});return t.observe(a,{box:e}),()=>{t?.unobserve(a)}},[e,m,a,d,u]),(0,s.useMemo)(()=>({height:d??h.height,width:u??h.width}),[h,d,u])}({defaultHeight:"vertical"===r?i:void 0,defaultWidth:"horizontal"===r?i:void 0,element:e,mode:"vertical"===r?"only-height":"only-width",style:t}),T=(0,s.useRef)({height:0,width:0}),O="vertical"===r?I:z,R=function({containerSize:e,itemSize:t}){let s;return"string"==typeof t?(o(t.endsWith("%"),`Invalid item size: "${t}"; string values must be percentages (e.g. "100%")`),o(void 0!==e,"Container size must be defined if a percentage item size is specified"),s=e*parseInt(t)/100):s=t,s}({containerSize:O,itemSize:x});(0,s.useLayoutEffect)(()=>{if("function"==typeof p){let e=T.current;(e.height!==I||e.width!==z)&&(p({height:I,width:z},{...e}),e.height=I,e.width=z)}},[I,p,z]);let E=function({itemCount:e,itemProps:t,itemSize:i}){return(0,s.useMemo)(()=>(function({itemCount:e,itemProps:t,itemSize:s}){let i=new Map;return{get(l){for(o(l<e,`Invalid index ${l}`);i.size-1<l;){let e,n=i.size;switch(typeof s){case"function":e=s(n,t);break;case"number":e=s}if(0===n)i.set(n,{size:e,scrollOffset:0});else{let t=i.get(n-1);o(void 0!==t,`Unexpected bounds cache miss for index ${l}`),i.set(n,{scrollOffset:t.scrollOffset+t.size,size:e})}}let n=i.get(l);return o(void 0!==n,`Unexpected bounds cache miss for index ${l}`),n},set(e,t){i.set(e,t)},get size(){return i.size}}})({itemCount:e,itemProps:t,itemSize:i}),[e,t,i])}({itemCount:f,itemProps:m,itemSize:R}),A=(0,s.useCallback)(e=>E.get(e),[E]),M=(0,s.useCallback)(()=>d({cachedBounds:E,itemCount:f,itemSize:R}),[E,f,R]),k=(0,s.useCallback)(t=>u({cachedBounds:E,containerScrollOffset:a({containerElement:e,direction:r,isRtl:h,scrollOffset:t}),containerSize:O,itemCount:f,overscanCount:g}),[E,e,O,r,h,f,g]);return l(()=>{w(k(("vertical"===r?e?.scrollTop:e?.scrollLeft)??0))},[e,r,k]),l(()=>{if(!e)return;let t=()=>{w(t=>{let{scrollLeft:s,scrollTop:i}=e,l=u({cachedBounds:E,containerScrollOffset:a({containerElement:e,direction:r,isRtl:h,scrollOffset:"vertical"===r?i:s}),containerSize:O,itemCount:f,overscanCount:g});return c(l,t)?t:l})};return e.addEventListener("scroll",t),()=>{e.removeEventListener("scroll",t)}},[E,e,O,r,f,g]),{getCellBounds:A,getEstimatedSize:M,scrollToIndex:(v=({align:t="auto",containerScrollOffset:s,index:i})=>{let l=function({align:e,cachedBounds:t,index:s,itemCount:i,itemSize:l,containerScrollOffset:n,containerSize:r}){if(s<0||s>=i)throw RangeError(`Invalid index specified: ${s}`,{cause:`Index ${s} is not within the range of 0 - ${i-1}`});let a=d({cachedBounds:t,itemCount:i,itemSize:l}),o=t.get(s),c=Math.max(0,Math.min(a-r,o.scrollOffset)),u=Math.max(0,o.scrollOffset-r+o.size);switch("smart"===e&&(e=n>=u&&n<=c?"auto":"center"),e){case"start":return c;case"end":return u;case"center":return o.scrollOffset<=r/2?0:o.scrollOffset+o.size/2>=a-r/2?a-r:o.scrollOffset+o.size/2-r/2;default:return n>=u&&n<=c?n:n<u?u:c}}({align:t,cachedBounds:E,containerScrollOffset:s,containerSize:O,index:i,itemCount:f,itemSize:R});if(e){if(l=a({containerElement:e,direction:r,isRtl:h,scrollOffset:l}),"function"!=typeof e.scrollTo){let e=k(l);c(b,e)||w(e)}return l}},S=(0,s.useRef)(()=>{throw Error("Cannot call during render.")}),l(()=>{S.current=v},[v]),(0,s.useCallback)(e=>S.current?.(e),[S])),startIndexOverscan:y,startIndexVisible:j,stopIndexOverscan:C,stopIndexVisible:N}}({containerElement:I,containerStyle:j,defaultContainerSize:r,direction:"vertical",itemCount:v,itemProps:N,itemSize:(0,s.useMemo)(()=>T?e=>S.getRowHeight(e)??S.getAverageRowHeight():S,[T,S]),onResize:m,overscanCount:p});(0,s.useImperativeHandle)(f,()=>({get element(){return I},scrollToRow({align:e="auto",behavior:t="auto",index:s}){let i=E({align:e,containerScrollOffset:I?.scrollTop??0,index:s});"function"==typeof I?.scrollTo&&I.scrollTo({behavior:t,top:i})}}),[I,E]),l(()=>{if(!I)return;let e=Array.from(I.children).filter((e,t)=>{if(e.hasAttribute("aria-hidden"))return!1;let s=`${A+t}`;return e.setAttribute("data-react-window-index",s),!0});if(T)return S.observeRowElements(e)},[I,T,S,A,k]),(0,s.useEffect)(()=>{A>=0&&k>=0&&x&&x({startIndex:M,stopIndex:L},{startIndex:A,stopIndex:k})},[x,A,M,k,L]);let B=(0,s.useMemo)(()=>{let e=[];if(v>0)for(let t=A;t<=k;t++){let i=O(t);e.push((0,s.createElement)(C,{...N,ariaAttributes:{"aria-posinset":t+1,"aria-setsize":v,role:"listitem"},key:t,index:t,style:{position:"absolute",left:0,transform:`translateY(${i.scrollOffset}px)`,height:T?void 0:i.size,width:"100%"}}))}return e},[C,O,T,v,N,A,k]),V=(0,t.jsx)("div",{"aria-hidden":!0,style:{height:R(),width:"100%",zIndex:-1}});return(0,s.createElement)(w,{role:"list",...y,className:i,ref:z,style:{position:"relative",maxHeight:"100%",flexGrow:1,overflowY:"auto",...j}},B,e,V)}s.useState,s.useRef,s.useState,s.useRef;var m=e.i(329),x=e.i(58362),p=e.i(25761),g=e.i(44021),v=e.i(22764);let S=(0,e.i(22436).default)("funnel",[["path",{d:"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z",key:"sc7q7i"}]]);var b=e.i(21079),w=e.i(35893),j=e.i(68497),y=e.i(8402),N=e.i(8737),C=e.i(32137),I=e.i(97705),z=e.i(45878);let T={specs:[],signature:null,scrollTop:0,activeSpecId:null},O=[],R=new Set,E=new Set,A=new Set;function M(){for(let e of R)e()}function k(e){return R.add(e),()=>{R.delete(e)}}function L(){return T}function B(){return(0,s.useSyncExternalStore)(k,L,()=>T)}function V(){let e=s.useCallback(e=>(E.add(e),()=>{E.delete(e)}),[]);return(0,s.useSyncExternalStore)(e,()=>L().specs,()=>O)}function H(){let e=s.useCallback(e=>(A.add(e),()=>{A.delete(e)}),[]);return(0,s.useSyncExternalStore)(e,()=>L().activeSpecId,()=>null)}function P(e){if(0===e.length)return;let t=e.map(e=>[e.id,e.specNumber??"",e.title??"",e.status??"",e.priority??"",e.updatedAt?new Date(e.updatedAt).getTime():0].join(":")).join("|");if(t!==T.signature)for(let s of(T={...T,specs:e,signature:t},M(),E))s()}function $(e){if(T.activeSpecId!==e)for(let t of(T={...T,activeSpecId:e},M(),A))t()}function F(e){1>Math.abs(e-T.scrollTop)||(T={...T,scrollTop:e})}function W(){return T.scrollTop}e.s(["getSidebarScrollTop",()=>W,"primeSpecsSidebar",()=>P,"setActiveSidebarSpec",()=>$,"updateSidebarScrollTop",()=>F,"useSpecsSidebarActiveSpec",()=>H,"useSpecsSidebarSpecs",()=>V,"useSpecsSidebarState",()=>B],22453);let U=s.useLayoutEffect;function q({initialSpecs:e=[],currentSpecId:l,currentSubSpec:n,onSpecHover:r}){let[a,o]=s.useState(""),[c,d]=s.useState("all"),[u,h]=s.useState("all"),[T,O]=s.useState("all"),[R,E]=s.useState(!1),[A,M]=s.useState(()=>"true"===localStorage.getItem("specs-nav-sidebar-collapsed")),[k,L]=s.useState(!1),[B,P]=s.useState(!1),$=s.useRef(null),q=s.useRef(null),D=s.useRef(!1),K=s.useRef(null),Y=s.useRef(0),G=s.useRef(!1),X=s.useRef(!0),J=V(),Q=H(),Z=s.useMemo(()=>J.length>0?J:e,[J,e]),_=l||Q||"";s.useEffect(()=>{P(!0)},[]),s.useEffect(()=>{document.documentElement.style.setProperty("--specs-nav-sidebar-width",A?"0px":"280px"),localStorage.setItem("specs-nav-sidebar-collapsed",String(A))},[A]),s.useEffect(()=>{L(!1)},[_,n]);let ee=s.useMemo(()=>{let e=Z;if(a){let t=a.toLowerCase();e=e.filter(e=>e.title?.toLowerCase().includes(t)||e.specName.toLowerCase().includes(t)||e.specNumber?.toString().includes(t))}return"all"!==c&&(e=e.filter(e=>e.status===c)),"all"!==u&&(e=e.filter(e=>e.priority===u)),"all"!==T&&(e=e.filter(e=>e.tags?.includes(T))),console.debug(e),e},[Z,a,c,u,T]),et=s.useMemo(()=>{let e=new Set;return Z.forEach(t=>{t.tags?.forEach(t=>e.add(t))}),Array.from(e).sort()},[Z]),es="all"!==c||"all"!==u||"all"!==T,ei=s.useMemo(()=>[...ee].sort((e,t)=>(t.specNumber||0)-(e.specNumber||0)),[ee]);U(()=>{let e=null,t=null;Y.current=W(),G.current=Y.current>0;let s=()=>{let i=K.current?.element;if(!i){e=window.requestAnimationFrame(s);return}D.current||(Y.current>0&&(i.scrollTop=Y.current),D.current=!0);let l=()=>{null===q.current&&(q.current=window.requestAnimationFrame(()=>{q.current=null,Y.current=i.scrollTop,F(i.scrollTop)}))};i.addEventListener("scroll",l,{passive:!0}),t=()=>{i.removeEventListener("scroll",l)}};return s(),()=>{t&&t(),null!==e&&window.cancelAnimationFrame(e),null!==q.current&&(window.cancelAnimationFrame(q.current),q.current=null)}},[]),U(()=>{if(!X.current||(X.current=!1,G.current||!_))return;let e=null,t=()=>{if(G.current)return;if(!D.current||!K.current){e=window.requestAnimationFrame(t);return}let s=ei.findIndex(e=>e.id===_);-1!==s&&(G.current=!0,K.current.scrollToRow({index:s,align:"center"}))};return t(),()=>{null!==e&&window.cancelAnimationFrame(e)}},[ei,_]),s.useEffect(()=>(window.toggleSpecsSidebar=()=>L(e=>!e),()=>{window.toggleSpecsSidebar=void 0}),[]);let el=s.useCallback(e=>{let{index:s,style:l}=e,a=ei[s],o=a.id===_,c=(a.contentMd?(0,C.extractH1Title)(a.contentMd):null)||a.title||a.specName;return(0,t.jsx)("div",{style:l,className:"px-1",children:(0,t.jsx)("div",{className:"mb-0.5",children:(0,t.jsx)("div",{className:"flex items-center gap-0.5",children:(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsxs)(i.default,{ref:o&&!n?$:null,href:`/specs/${a.specNumber||a.id}`,onMouseEnter:()=>r?.(a.specNumber?.toString()||a.id),className:(0,C.cn)("w-full flex flex-col gap-1 p-1.5 rounded-md text-sm transition-colors",o?"bg-accent text-accent-foreground font-medium":"hover:bg-accent/50"),children:[(0,t.jsxs)("div",{className:"flex items-center gap-1.5",children:[a.specNumber&&(0,t.jsxs)("span",{className:"text-xs font-mono text-muted-foreground shrink-0",children:["#",a.specNumber.toString().padStart(3,"0")]}),(0,t.jsx)("span",{className:"truncate text-xs leading-relaxed",children:c})]}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 flex-wrap",children:[a.status&&(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)("div",{children:(0,t.jsx)(j.StatusBadge,{status:a.status,iconOnly:!0,className:"text-[10px] scale-90"})})}),(0,t.jsx)(y.TooltipContent,{side:"right",children:(0,j.getStatusLabel)(a.status)})]}),a.priority&&(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)("div",{children:(0,t.jsx)(I.PriorityBadge,{priority:a.priority,iconOnly:!0,className:"text-[10px] scale-90"})})}),(0,t.jsx)(y.TooltipContent,{side:"right",children:(0,I.getPriorityLabel)(a.priority)})]}),"number"==typeof a.subSpecsCount&&a.subSpecsCount>0&&(0,t.jsxs)("span",{className:"text-[10px] text-muted-foreground",children:["+",a.subSpecsCount," files"]}),a.updatedAt&&(0,t.jsx)("span",{className:"text-[10px] text-muted-foreground",children:(0,z.formatRelativeTime)(a.updatedAt)})]})]})}),(0,t.jsx)(y.TooltipContent,{side:"right",className:"max-w-[300px]",children:(0,t.jsxs)("div",{className:"space-y-1",children:[(0,t.jsx)("div",{className:"font-semibold",children:c}),(0,t.jsx)("div",{className:"text-xs text-muted-foreground",children:a.specName})]})})]})})})})},[ei,_,n,r]),en=s.useMemo(()=>window.innerHeight-56-180,[]),er=s.useMemo(()=>s.memo(f),[]);return(0,t.jsxs)(y.TooltipProvider,{delayDuration:700,children:[k&&(0,t.jsx)("div",{className:"fixed inset-0 bg-black/50 z-40 lg:hidden",onClick:()=>L(!1)}),(0,t.jsxs)("div",{className:"relative flex-shrink-0",children:[(0,t.jsxs)("aside",{className:(0,C.cn)("sticky top-14 h-[calc(100vh-3.5rem)] border-r border-border bg-background flex flex-col overflow-hidden transition-all duration-300","hidden lg:flex",B&&A?"lg:w-0 lg:border-r-0":"lg:w-[280px]",k&&"fixed left-0 top-14 z-50 flex w-[280px]"),children:[(0,t.jsxs)("div",{className:"p-4 border-b border-border",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between mb-3",children:[(0,t.jsx)("h2",{className:"font-semibold text-sm",children:"Specifications"}),(0,t.jsxs)("div",{className:"flex items-center gap-1",children:[(0,t.jsxs)(y.Tooltip,{children:[(0,t.jsx)(y.TooltipTrigger,{asChild:!0,children:(0,t.jsx)(w.Button,{variant:R||es?"default":"ghost",size:"sm",onClick:()=>E(!R),className:"h-6 w-6 p-0",children:(0,t.jsx)(S,{className:"h-4 w-4"})})}),(0,t.jsx)(y.TooltipContent,{side:"bottom",children:R?"Hide filters":"Show filters"})]}),(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>L(!1),className:"h-6 w-6 p-0 lg:hidden",children:(0,t.jsx)(g.X,{className:"h-4 w-4"})}),(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>M(!0),className:"h-6 w-6 p-0 hidden lg:flex lg:items-center lg:justify-center",children:(0,t.jsx)(x.ChevronLeft,{className:"h-4 w-4"})})]})]}),R&&(0,t.jsxs)("div",{className:"space-y-2 mb-3 pb-3 border-b border-border",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between",children:[(0,t.jsx)("span",{className:"text-xs font-medium text-muted-foreground",children:"Filters"}),es&&(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>{d("all"),h("all"),O("all")},className:"h-5 text-xs px-2 py-0",children:"Clear"})]}),(0,t.jsxs)(N.Select,{value:c,onValueChange:d,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Status"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Status"}),(0,t.jsx)(N.SelectItem,{value:"planned",children:"Planned"}),(0,t.jsx)(N.SelectItem,{value:"in-progress",children:"In Progress"}),(0,t.jsx)(N.SelectItem,{value:"complete",children:"Complete"}),(0,t.jsx)(N.SelectItem,{value:"archived",children:"Archived"})]})]}),(0,t.jsxs)(N.Select,{value:u,onValueChange:h,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Priority"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Priority"}),(0,t.jsx)(N.SelectItem,{value:"low",children:"Low"}),(0,t.jsx)(N.SelectItem,{value:"medium",children:"Medium"}),(0,t.jsx)(N.SelectItem,{value:"high",children:"High"}),(0,t.jsx)(N.SelectItem,{value:"critical",children:"Critical"})]})]}),et.length>0&&(0,t.jsxs)(N.Select,{value:T,onValueChange:O,children:[(0,t.jsx)(N.SelectTrigger,{className:"h-8 text-xs",children:(0,t.jsx)(N.SelectValue,{placeholder:"Tag"})}),(0,t.jsxs)(N.SelectContent,{children:[(0,t.jsx)(N.SelectItem,{value:"all",children:"All Tags"}),et.map(e=>(0,t.jsx)(N.SelectItem,{value:e,children:e},e))]})]})]}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsx)(m.Search,{className:"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground"}),(0,t.jsx)(b.Input,{placeholder:"Search specs...",value:a,onChange:e=>o(e.target.value),className:"pl-8 h-9 border-border"})]})]}),(0,t.jsx)("div",{className:"flex-1 overflow-hidden",children:0===ei.length?(0,t.jsx)("div",{className:"text-center py-8 text-sm text-muted-foreground",children:"No specs found"}):(0,t.jsx)(er,{listRef:K,defaultHeight:en,rowCount:ei.length,rowHeight:72,overscanCount:5,rowComponent:el,rowProps:{}})})]}),B&&A&&(0,t.jsx)(w.Button,{variant:"ghost",size:"sm",onClick:()=>M(!1),className:"hidden lg:items-center lg:justify-center lg:flex h-6 w-6 p-0 fixed z-50 top-20 -translate-y-1 -translate-x-1/2 left-[calc(var(--main-sidebar-width,240px))] bg-background border",children:(0,t.jsx)(p.ChevronRight,{className:"h-4 w-4"})}),(0,t.jsx)(w.Button,{onClick:()=>L(!0),size:"icon",className:"lg:hidden fixed bottom-6 left-6 h-12 w-12 rounded-full shadow-lg z-40 hover:scale-110 transition-transform","aria-label":"Show specifications list",children:(0,t.jsx)(v.List,{className:"h-5 w-5"})})]})]})}e.s(["SpecsNavSidebar",()=>q],17612)},53213,e=>{"use strict";var t=e.i(90022),s=e.i(17612),i=e.i(32137);function l({className:e,...s}){return(0,t.jsx)("div",{className:(0,i.cn)("animate-pulse rounded-md bg-muted",e),...s})}var n=e.i(22453);function r(){let e=(0,n.useSpecsSidebarState)(),i=e.specs,r=e.activeSpecId||"";return(0,t.jsxs)("div",{className:"flex min-h-[calc(100vh-3.5rem)] w-full min-w-0",children:[(0,t.jsx)(s.SpecsNavSidebar,{initialSpecs:i,currentSpecId:r}),(0,t.jsx)("div",{className:"flex-1 min-w-0 px-4 py-6 sm:px-8 sm:py-10",children:(0,t.jsxs)("div",{className:"space-y-6",children:[(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)(l,{className:"h-7 w-56"}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-3",children:[(0,t.jsx)(l,{className:"h-6 w-24"}),(0,t.jsx)(l,{className:"h-6 w-24"}),(0,t.jsx)(l,{className:"h-6 w-20"})]}),(0,t.jsx)(l,{className:"h-4 w-64"})]}),(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsx)(l,{className:"h-5 w-40"}),(0,t.jsx)(l,{className:"h-32 w-full"})]}),(0,t.jsx)("div",{className:"space-y-4",children:[...Array(6)].map((e,s)=>(0,t.jsx)(l,{className:"h-4 w-full"},s))})]})})]})}e.s(["SpecDetailLoadingShell",()=>r],53213)}]);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/b760a3a9c2c8be28.js","static/chunks/ebd89051637b9a47.js","static/chunks/7f732ea69e643219.js","static/chunks/f3ec9fd77a8618b1.js","static/chunks/5c2072ad938de8ed.js"],runtimeModuleIds:[79757]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=new WeakMap;function n(e,t){this.m=e,this.e=t}let o=n.prototype,l=Object.prototype.hasOwnProperty,i="undefined"!=typeof Symbol&&Symbol.toStringTag;function s(e,t,r){l.call(e,t)||Object.defineProperty(e,t,r)}function u(e,t){let r=e[t];return r||(r=a(t),e[t]=r),r}function a(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function c(e,t){s(e,"__esModule",{value:!0}),i&&s(e,i,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)s(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?s(e,n,{get:o,set:t[r++],enumerable:!0}):s(e,n,{get:o,enumerable:!0})}Object.seal(e)}o.s=function(e,t){let r,n;null!=t?n=(r=u(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,c(n,e)},o.j=function(e,t){var n,o;let i,s,a;null!=t?s=(i=u(this.c,t)).exports:(i=this.m,s=this.e);let c=(n=i,o=s,(a=r.get(n))||(r.set(n,a=[]),n.exports=n.namespaceObject=new Proxy(o,{get(e,t){if(l.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of a){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of a)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),a);"object"==typeof e&&null!==e&&c.push(e)},o.v=function(e,t){(null!=t?u(this.c,t):this.m).exports=e},o.n=function(e,t){let r;(r=null!=t?u(this.c,t):this.m).exports=r.namespaceObject=e};let f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,p=[null,f({}),f([]),f(f)];function h(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!p.includes(t);t=f(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),c(t,n),t}function d(e){let t=N(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=h(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function m(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}o.i=d,o.A=function(e){return this.r(e)(d.bind(this))},o.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},o.r=function(e){return N(e,this.m).exports},o.f=function(e){function t(t){if(l.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(l.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let b=Symbol("turbopack queues"),y=Symbol("turbopack exports"),O=Symbol("turbopack error");function g(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}o.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:l,reject:i,promise:s}=m(),u=Object.assign(s,{[y]:r.exports,[b]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[y]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(b in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[y]:{},[b]:e=>e(t)};return e.then(e=>{r[y]=e,g(t)},e=>{r[O]=e,g(t)}),r}}return{[y]:e,[b]:()=>{}}}),r=()=>t.map(e=>{if(e[O])throw e[O];return e[y]}),{promise:l,resolve:i}=m(),s=Object.assign(()=>i(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[b](u)),s.queueCount?l:r()},function(e){e?i(u[O]=e):l(u[y]),g(n)}),n&&-1===n.status&&(n.status=0)};let w=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function j(e,t){throw Error(`Invariant: ${t(e)}`)}w.prototype=URL.prototype,o.U=w,o.z=function(e){throw Error("dynamic usage of require is not supported")},o.g=globalThis;let R=n.prototype;var C,U=((C=U||{})[C.Runtime=0]="Runtime",C[C.Parent=1]="Parent",C[C.Update=2]="Update",C);let k=new Map;o.M=k;let v=new Map,_=new Map;async function P(e,t,r){let n;if("string"==typeof r)return A(e,t,S(r));let o=r.included||[],l=o.map(e=>!!k.has(e)||v.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);let i=r.moduleChunks||[],s=i.map(e=>_.get(e)).filter(e=>e);if(s.length>0){if(s.length===i.length)return void await Promise.all(s);let r=new Set;for(let e of i)_.has(e)||r.add(e);for(let n of r){let r=A(e,t,S(n));_.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=A(e,t,S(r.path)),i))_.has(o)||_.set(o,n)}for(let e of o)v.has(e)||v.set(e,n);await n}R.l=function(e){return P(1,this.m.id,e)};let $=Promise.resolve(void 0),T=new WeakMap;function A(t,r,n){let o=e.loadChunkCached(t,n),l=T.get(o);if(void 0===l){let e=T.set.bind(T,o,$);l=o.then(e).catch(e=>{let o;switch(t){case 0:o=`as a runtime dependency of chunk ${r}`;break;case 1:o=`from module ${r}`;break;case 2:o="from an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}throw Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0)}),T.set(o,l)}return l}function S(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}`}R.L=function(e){return A(1,this.m.id,e)},R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.b=function(e){let t=new Blob([`self.TURBOPACK_WORKER_LOCATION = ${JSON.stringify(location.origin)};
|
|
2
|
+
self.TURBOPACK_NEXT_CHUNK_URLS = ${JSON.stringify(e.reverse().map(S),null,2)};
|
|
3
|
+
importScripts(...self.TURBOPACK_NEXT_CHUNK_URLS.map(c => self.TURBOPACK_WORKER_LOCATION + c).reverse());`],{type:"text/javascript"});return URL.createObjectURL(t)};let E=/\.js(?:\?[^#]*)?(?:#.*)?$/,K=/\.css(?:\?[^#]*)?(?:#.*)?$/;function x(e){return K.test(e)}o.w=function(t,r,n){return e.loadWebAssembly(1,this.m.id,t,r,n)},o.u=function(t,r){return e.loadWebAssemblyModule(1,this.m.id,t,r)};let M={};o.c=M;let N=(e,t)=>{let r=M[e];if(r){if(r.error)throw r.error;return r}return L(e,U.Parent,t.id)};function L(e,t,r){let o=k.get(e);if("function"!=typeof o)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let l=a(e),i=l.exports;M[e]=l;let s=new n(l,i);try{o(s,l,i)}catch(e){throw l.error=e,e}return l.namespaceObject&&l.exports!==l.namespaceObject&&h(l.exports,l.namespaceObject),l}function q(r){let n,o=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(("undefined"!=typeof TURBOPACK_NEXT_CHUNK_URLS?TURBOPACK_NEXT_CHUNK_URLS.pop():e.getAttribute("src")).replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(r[0]);return 2===r.length?n=r[1]:(n=void 0,!function(e,t,r,n){let o=1;for(;o<e.length;){let t=e[o],n=o+1;for(;n<e.length&&"function"!=typeof e[n];)n++;if(n===e.length)throw Error("malformed chunk format, expected a factory function");if(!r.has(t)){let l=e[n];for(Object.defineProperty(l,"name",{value:"module evaluation"});o<n;o++)t=e[o],r.set(t,l)}o=n+1}}(r,0,k)),e.registerChunk(o,n)}let B=new Map;function W(e){let t=B.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},B.set(e,t)}return t}e={async registerChunk(e,t){if(W(S(e)).resolve(),null!=t){for(let e of t.otherChunks)W(S("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(t=>P(0,e,t))),t.runtimeModuleIds.length>0)for(let r of t.runtimeModuleIds)!function(e,t){let r=M[t];if(r){if(r.error)throw r.error;return}L(t,U.Runtime,e)}(e,r)}},loadChunkCached:(e,t)=>(function(e,t){let r=W(t);if(r.loadingStarted)return r.promise;if(e===U.Runtime)return r.loadingStarted=!0,x(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(x(t));else if(E.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(TURBOPACK_WORKER_LOCATION+t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(x(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(E.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let l=fetch(S(r)),{instance:i}=await WebAssembly.instantiateStreaming(l,o);return i.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(S(r));return await WebAssembly.compileStreaming(o)}};let I=globalThis.TURBOPACK;globalThis.TURBOPACK={push:q},I.forEach(q)})();
|
|
@@ -17,6 +17,7 @@ program
|
|
|
17
17
|
.option('-s, --specs <dir>', 'Specs directory (auto-detected if omitted)')
|
|
18
18
|
.option('-p, --port <port>', 'Port to run on', '3000')
|
|
19
19
|
.option('--no-open', "Don't open the browser automatically")
|
|
20
|
+
.option('--multi-project', 'Enable multi-project mode')
|
|
20
21
|
.option('--dry-run', 'Show what would run without executing')
|
|
21
22
|
.action(async (options) => {
|
|
22
23
|
try {
|
|
@@ -33,15 +34,24 @@ program.parseAsync(process.argv);
|
|
|
33
34
|
async function startUi(options) {
|
|
34
35
|
const cwd = process.cwd();
|
|
35
36
|
const port = validatePort(options.port);
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
let specsDir = '';
|
|
39
|
+
let specsMode = 'filesystem';
|
|
40
|
+
|
|
41
|
+
if (options.multiProject) {
|
|
42
|
+
specsMode = 'multi-project';
|
|
43
|
+
} else {
|
|
44
|
+
specsDir = resolveSpecsDirectory(cwd, options.specs);
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
const serverPath = getServerPath();
|
|
38
48
|
|
|
39
49
|
if (options.dryRun) {
|
|
40
|
-
printDryRun({ port, specsDir, serverPath, openBrowser: options.open });
|
|
50
|
+
printDryRun({ port, specsDir, specsMode, serverPath, openBrowser: options.open });
|
|
41
51
|
return;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
await launchServer({ port, specsDir, serverPath, openBrowser: options.open });
|
|
54
|
+
await launchServer({ port, specsDir, specsMode, serverPath, openBrowser: options.open });
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
function validatePort(value) {
|
|
@@ -134,22 +144,22 @@ function getServerPath() {
|
|
|
134
144
|
throw new Error('LeanSpec UI build not found. Reinstall @leanspec/ui or run pnpm --filter @leanspec/ui build.');
|
|
135
145
|
}
|
|
136
146
|
|
|
137
|
-
function printDryRun({ port, specsDir, serverPath, openBrowser }) {
|
|
147
|
+
function printDryRun({ port, specsDir, specsMode, serverPath, openBrowser }) {
|
|
138
148
|
console.log(chalk.cyan('Would run:'));
|
|
139
|
-
console.log(chalk.dim(` SPECS_MODE
|
|
149
|
+
console.log(chalk.dim(` SPECS_MODE=${specsMode} SPECS_DIR=${specsDir} PORT=${port} node ${serverPath}`));
|
|
140
150
|
if (openBrowser) {
|
|
141
151
|
console.log(chalk.dim(` open http://localhost:${port}`));
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
154
|
|
|
145
|
-
async function launchServer({ port, specsDir, serverPath, openBrowser }) {
|
|
155
|
+
async function launchServer({ port, specsDir, specsMode, serverPath, openBrowser }) {
|
|
146
156
|
const spinner = ora('Starting LeanSpec UI...').start();
|
|
147
157
|
const serverDir = dirname(serverPath);
|
|
148
158
|
const env = {
|
|
149
159
|
...process.env,
|
|
150
160
|
NODE_ENV: 'production',
|
|
151
161
|
NEXT_TELEMETRY_DISABLED: '1',
|
|
152
|
-
SPECS_MODE:
|
|
162
|
+
SPECS_MODE: specsMode,
|
|
153
163
|
SPECS_DIR: specsDir,
|
|
154
164
|
PORT: port,
|
|
155
165
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanspec/ui",
|
|
3
|
-
"version": "0.2.5-dev.
|
|
3
|
+
"version": "0.2.5-dev.20251120093243",
|
|
4
4
|
"description": "LeanSpec web UI launcher for visual spec management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
58
58
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
59
59
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
60
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
60
61
|
"@radix-ui/react-progress": "^1.1.8",
|
|
61
62
|
"@radix-ui/react-select": "^2.1.14",
|
|
62
63
|
"@radix-ui/react-separator": "^1.1.8",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Route for listing directory contents
|
|
3
|
+
*
|
|
4
|
+
* POST /api/local-projects/list-directory - List directories in a path
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
8
|
+
import { projectRegistry } from '@/lib/projects';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* POST /api/local-projects/list-directory
|
|
13
|
+
* List directories in a given path
|
|
14
|
+
*
|
|
15
|
+
* Body: { path?: string }
|
|
16
|
+
*/
|
|
17
|
+
export async function POST(request: NextRequest) {
|
|
18
|
+
try {
|
|
19
|
+
const body = await request.json();
|
|
20
|
+
const { path } = body;
|
|
21
|
+
|
|
22
|
+
// Use CWD if path is not provided, falling back to homedir
|
|
23
|
+
const targetPath = path || process.cwd() || homedir();
|
|
24
|
+
|
|
25
|
+
const items = await projectRegistry.listDirectory(targetPath);
|
|
26
|
+
|
|
27
|
+
return NextResponse.json({
|
|
28
|
+
path: targetPath,
|
|
29
|
+
items,
|
|
30
|
+
});
|
|
31
|
+
} catch (error: any) {
|
|
32
|
+
console.error('Error listing directory:', error);
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ error: 'Failed to list directory', details: error.message },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getProjectById } from '@/lib/db/queries';
|
|
3
|
+
import { projectRegistry } from '@/lib/projects/registry';
|
|
4
|
+
|
|
5
|
+
export async function GET(
|
|
6
|
+
request: Request,
|
|
7
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
const { id } = await params;
|
|
11
|
+
|
|
12
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
13
|
+
const project = await projectRegistry.getProject(id);
|
|
14
|
+
if (!project) {
|
|
15
|
+
return NextResponse.json(
|
|
16
|
+
{ error: 'Project not found' },
|
|
17
|
+
{ status: 404 }
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
// Touch project to update lastAccessed
|
|
21
|
+
await projectRegistry.touchProject(id);
|
|
22
|
+
return NextResponse.json({ project });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const project = await getProjectById(id);
|
|
26
|
+
if (!project) {
|
|
27
|
+
return NextResponse.json(
|
|
28
|
+
{ error: 'Project not found' },
|
|
29
|
+
{ status: 404 }
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return NextResponse.json({ project });
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Error fetching project:', error);
|
|
35
|
+
return NextResponse.json(
|
|
36
|
+
{ error: 'Failed to fetch project' },
|
|
37
|
+
{ status: 500 }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function DELETE(
|
|
43
|
+
request: Request,
|
|
44
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
48
|
+
return NextResponse.json(
|
|
49
|
+
{ error: 'Multi-project mode is not enabled' },
|
|
50
|
+
{ status: 400 }
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { id } = await params;
|
|
55
|
+
await projectRegistry.removeProject(id);
|
|
56
|
+
return NextResponse.json({ success: true });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('Error deleting project:', error);
|
|
59
|
+
return NextResponse.json(
|
|
60
|
+
{ error: 'Failed to delete project' },
|
|
61
|
+
{ status: 500 }
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function PATCH(
|
|
67
|
+
request: Request,
|
|
68
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
69
|
+
) {
|
|
70
|
+
try {
|
|
71
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
72
|
+
return NextResponse.json(
|
|
73
|
+
{ error: 'Multi-project mode is not enabled' },
|
|
74
|
+
{ status: 400 }
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { id } = await params;
|
|
79
|
+
const body = await request.json();
|
|
80
|
+
|
|
81
|
+
// Handle favorite toggle separately
|
|
82
|
+
if ('favorite' in body) {
|
|
83
|
+
const favorite = await projectRegistry.toggleFavorite(id);
|
|
84
|
+
const project = await projectRegistry.getProject(id);
|
|
85
|
+
return NextResponse.json({ project, favorite });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const project = await projectRegistry.updateProject(id, body);
|
|
89
|
+
return NextResponse.json({ project });
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Error updating project:', error);
|
|
92
|
+
return NextResponse.json(
|
|
93
|
+
{ error: 'Failed to update project' },
|
|
94
|
+
{ status: 500 }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getSpecById } from '@/lib/db/queries';
|
|
3
|
+
import { specsService } from '@/lib/specs/service';
|
|
4
|
+
|
|
5
|
+
export async function GET(
|
|
6
|
+
request: Request,
|
|
7
|
+
{ params }: { params: Promise<{ id: string; spec: string }> }
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
const { id, spec: specId } = await params;
|
|
11
|
+
|
|
12
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
13
|
+
const spec = await specsService.getSpec(specId, id);
|
|
14
|
+
if (!spec) {
|
|
15
|
+
return NextResponse.json(
|
|
16
|
+
{ error: 'Spec not found' },
|
|
17
|
+
{ status: 404 }
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return NextResponse.json({ spec });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const spec = await getSpecById(specId);
|
|
24
|
+
if (!spec) {
|
|
25
|
+
return NextResponse.json(
|
|
26
|
+
{ error: 'Spec not found' },
|
|
27
|
+
{ status: 404 }
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return NextResponse.json({ spec });
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error fetching spec:', error);
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ error: 'Failed to fetch spec' },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { createUpdatedFrontmatter } from '@leanspec/core';
|
|
6
|
+
import { projectRegistry } from '@/lib/projects/registry';
|
|
7
|
+
|
|
8
|
+
const ALLOWED_STATUSES = ['planned', 'in-progress', 'complete', 'archived'] as const;
|
|
9
|
+
type AllowedStatus = (typeof ALLOWED_STATUSES)[number];
|
|
10
|
+
|
|
11
|
+
async function findSpecDirectory(specsDir: string, specIdentifier: string): Promise<string | null> {
|
|
12
|
+
if (!existsSync(specsDir)) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { readdir } = await import('node:fs/promises');
|
|
17
|
+
const entries = await readdir(specsDir, { withFileTypes: true });
|
|
18
|
+
|
|
19
|
+
// Match by spec number or full directory name
|
|
20
|
+
const specPattern = /^(\d{2,})-/;
|
|
21
|
+
const specNum = parseInt(specIdentifier.split('-')[0], 10);
|
|
22
|
+
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (!entry.isDirectory()) continue;
|
|
25
|
+
|
|
26
|
+
// Match by full name or by spec number
|
|
27
|
+
if (entry.name === specIdentifier) {
|
|
28
|
+
return path.join(specsDir, entry.name);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!isNaN(specNum) && specPattern.test(entry.name)) {
|
|
32
|
+
const dirNum = parseInt(entry.name.split('-')[0], 10);
|
|
33
|
+
if (dirNum === specNum) {
|
|
34
|
+
return path.join(specsDir, entry.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function PATCH(
|
|
43
|
+
request: Request,
|
|
44
|
+
{ params }: { params: Promise<{ id: string; spec: string }> }
|
|
45
|
+
) {
|
|
46
|
+
try {
|
|
47
|
+
const { id: projectId, spec: specId } = await params;
|
|
48
|
+
|
|
49
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
50
|
+
return NextResponse.json({ error: 'Multi-project mode not enabled' }, { status: 400 });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const project = await projectRegistry.getProject(projectId);
|
|
54
|
+
if (!project) {
|
|
55
|
+
return NextResponse.json({ error: 'Project not found' }, { status: 404 });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let payload: { status?: AllowedStatus } = {};
|
|
59
|
+
try {
|
|
60
|
+
payload = await request.json();
|
|
61
|
+
} catch {
|
|
62
|
+
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { status } = payload;
|
|
66
|
+
if (!status || !ALLOWED_STATUSES.includes(status)) {
|
|
67
|
+
return NextResponse.json({ error: 'Invalid status value' }, { status: 400 });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const specIdentifier = decodeURIComponent(specId);
|
|
71
|
+
const specDir = await findSpecDirectory(project.specsDir, specIdentifier);
|
|
72
|
+
|
|
73
|
+
if (!specDir) {
|
|
74
|
+
return NextResponse.json({ error: 'Spec not found' }, { status: 404 });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const readmePath = path.join(specDir, 'README.md');
|
|
78
|
+
|
|
79
|
+
if (!existsSync(readmePath)) {
|
|
80
|
+
return NextResponse.json({ error: 'Spec README.md not found' }, { status: 404 });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Read current content
|
|
84
|
+
const currentContent = await readFile(readmePath, 'utf-8');
|
|
85
|
+
|
|
86
|
+
// Update frontmatter using @leanspec/core
|
|
87
|
+
const { content: updatedContent } = createUpdatedFrontmatter(currentContent, { status });
|
|
88
|
+
|
|
89
|
+
// Write back to file
|
|
90
|
+
await writeFile(readmePath, updatedContent, 'utf-8');
|
|
91
|
+
|
|
92
|
+
return NextResponse.json({ success: true });
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Failed to update spec status:', error);
|
|
95
|
+
return NextResponse.json({ error: 'Failed to update spec status' }, { status: 500 });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { NextResponse } from 'next/server';
|
|
6
6
|
import { getSpecsByProjectId } from '@/lib/db/queries';
|
|
7
|
+
import { specsService } from '@/lib/specs/service';
|
|
7
8
|
|
|
8
9
|
export async function GET(
|
|
9
10
|
request: Request,
|
|
@@ -11,6 +12,12 @@ export async function GET(
|
|
|
11
12
|
) {
|
|
12
13
|
try {
|
|
13
14
|
const { id } = await params;
|
|
15
|
+
|
|
16
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
17
|
+
const specs = await specsService.getAllSpecs(id);
|
|
18
|
+
return NextResponse.json({ specs });
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
const specs = await getSpecsByProjectId(id);
|
|
15
22
|
return NextResponse.json({ specs });
|
|
16
23
|
} catch (error) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getStats } from '@/lib/db/service-queries';
|
|
3
|
+
|
|
4
|
+
export async function GET(
|
|
5
|
+
request: Request,
|
|
6
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
7
|
+
) {
|
|
8
|
+
try {
|
|
9
|
+
const { id } = await params;
|
|
10
|
+
const stats = await getStats(id);
|
|
11
|
+
return NextResponse.json({ stats });
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.error('Error fetching stats:', error);
|
|
14
|
+
return NextResponse.json(
|
|
15
|
+
{ error: 'Failed to fetch stats' },
|
|
16
|
+
{ status: 500 }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -4,11 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
import { NextResponse } from 'next/server';
|
|
6
6
|
import { getProjects } from '@/lib/db/queries';
|
|
7
|
+
import { projectRegistry } from '@/lib/projects/registry';
|
|
7
8
|
|
|
8
9
|
export async function GET() {
|
|
9
10
|
try {
|
|
11
|
+
// Check if running in multi-project mode
|
|
12
|
+
if (process.env.SPECS_MODE === 'multi-project') {
|
|
13
|
+
const projects = await projectRegistry.getProjects();
|
|
14
|
+
const recentProjects = await projectRegistry.getRecentProjects();
|
|
15
|
+
const favoriteProjects = await projectRegistry.getFavoriteProjects();
|
|
16
|
+
return NextResponse.json({
|
|
17
|
+
mode: 'multi-project',
|
|
18
|
+
projects,
|
|
19
|
+
recentProjects,
|
|
20
|
+
favoriteProjects
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
const projects = await getProjects();
|
|
11
|
-
return NextResponse.json({
|
|
25
|
+
return NextResponse.json({
|
|
26
|
+
mode: 'single-project',
|
|
27
|
+
projects
|
|
28
|
+
});
|
|
12
29
|
} catch (error) {
|
|
13
30
|
console.error('Error fetching projects:', error);
|
|
14
31
|
return NextResponse.json(
|
|
@@ -17,3 +34,33 @@ export async function GET() {
|
|
|
17
34
|
);
|
|
18
35
|
}
|
|
19
36
|
}
|
|
37
|
+
|
|
38
|
+
export async function POST(request: Request) {
|
|
39
|
+
try {
|
|
40
|
+
if (process.env.SPECS_MODE !== 'multi-project') {
|
|
41
|
+
return NextResponse.json(
|
|
42
|
+
{ error: 'Multi-project mode is not enabled' },
|
|
43
|
+
{ status: 400 }
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const body = await request.json();
|
|
48
|
+
const { path, favorite, color } = body;
|
|
49
|
+
|
|
50
|
+
if (!path) {
|
|
51
|
+
return NextResponse.json(
|
|
52
|
+
{ error: 'Project path is required' },
|
|
53
|
+
{ status: 400 }
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const project = await projectRegistry.addProject(path, { favorite, color });
|
|
58
|
+
return NextResponse.json({ project });
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Error adding project:', error);
|
|
61
|
+
return NextResponse.json(
|
|
62
|
+
{ error: error instanceof Error ? error.message : 'Failed to add project' },
|
|
63
|
+
{ status: 500 }
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
3
4
|
import Link from 'next/link';
|
|
5
|
+
import { useProject } from '@/contexts/project-context';
|
|
4
6
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
5
7
|
import { Button } from '@/components/ui/button';
|
|
6
8
|
import {
|
|
@@ -11,7 +13,8 @@ import {
|
|
|
11
13
|
LayoutGrid,
|
|
12
14
|
List,
|
|
13
15
|
TrendingUp,
|
|
14
|
-
Calendar
|
|
16
|
+
Calendar,
|
|
17
|
+
Loader2
|
|
15
18
|
} from 'lucide-react';
|
|
16
19
|
import { StatusBadge } from '@/components/status-badge';
|
|
17
20
|
import { PriorityBadge } from '@/components/priority-badge';
|
|
@@ -133,20 +136,78 @@ function ActivityItem({ spec, action, time }: { spec: Spec; action: string; time
|
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
export function DashboardClient({ initialSpecs, initialStats }: DashboardClientProps) {
|
|
136
|
-
const
|
|
139
|
+
const { mode, currentProject, isLoading: isProjectLoading } = useProject();
|
|
140
|
+
const [specs, setSpecs] = useState<Spec[]>(initialSpecs);
|
|
141
|
+
const [stats, setStats] = useState<Stats>(initialStats);
|
|
142
|
+
const [isLoadingData, setIsLoadingData] = useState(false);
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (mode === 'multi-project') {
|
|
146
|
+
if (currentProject) {
|
|
147
|
+
fetchProjectData(currentProject.id);
|
|
148
|
+
} else {
|
|
149
|
+
setSpecs([]);
|
|
150
|
+
setStats({ totalSpecs: 0, completionRate: 0, specsByStatus: [] });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, [mode, currentProject]);
|
|
154
|
+
|
|
155
|
+
const fetchProjectData = async (projectId: string) => {
|
|
156
|
+
setIsLoadingData(true);
|
|
157
|
+
try {
|
|
158
|
+
const [specsRes, statsRes] = await Promise.all([
|
|
159
|
+
fetch(`/api/projects/${projectId}/specs`),
|
|
160
|
+
fetch(`/api/projects/${projectId}/stats`)
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
if (specsRes.ok && statsRes.ok) {
|
|
164
|
+
const specsData = await specsRes.json();
|
|
165
|
+
const statsData = await statsRes.json();
|
|
166
|
+
|
|
167
|
+
const parsedSpecs = specsData.specs.map((s: any) => ({
|
|
168
|
+
...s,
|
|
169
|
+
createdAt: s.createdAt ? new Date(s.createdAt) : null,
|
|
170
|
+
updatedAt: s.updatedAt ? new Date(s.updatedAt) : null,
|
|
171
|
+
}));
|
|
172
|
+
|
|
173
|
+
setSpecs(parsedSpecs);
|
|
174
|
+
setStats(statsData.stats);
|
|
175
|
+
}
|
|
176
|
+
} catch (e) {
|
|
177
|
+
console.error(e);
|
|
178
|
+
} finally {
|
|
179
|
+
setIsLoadingData(false);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
if (mode === 'multi-project' && !currentProject) {
|
|
184
|
+
if (isProjectLoading) {
|
|
185
|
+
return <div className="flex items-center justify-center h-screen"><Loader2 className="animate-spin" /></div>;
|
|
186
|
+
}
|
|
187
|
+
return (
|
|
188
|
+
<div className="flex flex-col items-center justify-center h-[calc(100vh-4rem)] text-center p-8">
|
|
189
|
+
<h2 className="text-2xl font-bold mb-2">Welcome to LeanSpec</h2>
|
|
190
|
+
<p className="text-muted-foreground mb-4">Select a project from the sidebar or create a new one to get started.</p>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (isLoadingData) {
|
|
196
|
+
return <div className="flex items-center justify-center h-screen"><Loader2 className="animate-spin" /></div>;
|
|
197
|
+
}
|
|
137
198
|
|
|
138
199
|
// Get specs by status
|
|
139
|
-
const inProgressSpecs =
|
|
200
|
+
const inProgressSpecs = specs
|
|
140
201
|
.filter(spec => spec.status === 'in-progress')
|
|
141
202
|
.sort((a, b) => (b.specNumber || 0) - (a.specNumber || 0))
|
|
142
203
|
.slice(0, 5);
|
|
143
204
|
|
|
144
|
-
const plannedSpecs =
|
|
205
|
+
const plannedSpecs = specs
|
|
145
206
|
.filter(spec => spec.status === 'planned')
|
|
146
207
|
.sort((a, b) => (b.specNumber || 0) - (a.specNumber || 0))
|
|
147
208
|
.slice(0, 5);
|
|
148
209
|
|
|
149
|
-
const recentlyAdded =
|
|
210
|
+
const recentlyAdded = specs
|
|
150
211
|
.sort((a, b) => {
|
|
151
212
|
if (!a.createdAt) return 1;
|
|
152
213
|
if (!b.createdAt) return -1;
|
|
@@ -154,7 +215,7 @@ export function DashboardClient({ initialSpecs, initialStats }: DashboardClientP
|
|
|
154
215
|
})
|
|
155
216
|
.slice(0, 5);
|
|
156
217
|
|
|
157
|
-
const recentActivity =
|
|
218
|
+
const recentActivity = specs
|
|
158
219
|
.filter(spec => spec.updatedAt)
|
|
159
220
|
.sort((a, b) => {
|
|
160
221
|
if (!a.updatedAt) return 1;
|