pkgviz 0.7.7 → 0.8.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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -1
- package/.next/build-manifest.json +15 -24
- package/.next/fallback-build-manifest.json +15 -0
- package/.next/images-manifest.json +14 -3
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +52 -16
- package/.next/required-server-files.js +349 -0
- package/.next/required-server-files.json +106 -75
- package/.next/routes-manifest.json +16 -6
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +20 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +9 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +22 -0
- package/.next/server/app/_global-error.rsc +15 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +20 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +20 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +13 -2
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.meta +19 -0
- package/.next/server/app/_not-found.rsc +18 -19
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +12 -0
- package/.next/server/app/favicon.ico/route.js +6 -1
- package/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +20 -0
- package/.next/server/app/page/next-font-manifest.json +11 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +93 -0
- package/.next/server/app/page.js +16 -13
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +3 -1
- package/.next/server/app-paths-manifest.json +2 -1
- package/.next/server/chunks/[externals]__0l8ei7u._.js +3 -0
- package/.next/server/chunks/[externals]__0l8ei7u._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__1to-yfd._.js +160 -0
- package/.next/server/chunks/[root-of-the-server]__1to-yfd._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +807 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_0g2jjls.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_0g2jjls.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0agsrep._.js +28 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0agsrep._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0f_e7c8._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0f_e7c8._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0yqn68e._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0yqn68e._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__112mz-6._.js +14 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__112mz-6._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11_76b7._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11_76b7._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12ovu0c._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12ovu0c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16pmw__._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16pmw__._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1f2jx51._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1f2jx51._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1rn09vt._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1rn09vt._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__20e4gkp._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__20e4gkp._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +807 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/ssr/_1acy_2s._.js +158 -0
- package/.next/server/chunks/ssr/_1acy_2s._.js.map +1 -0
- package/.next/server/chunks/ssr/_1rh2tf9._.js +367 -0
- package/.next/server/chunks/ssr/_1rh2tf9._.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0zi5s8-.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0zi5s8-.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0pt47yr.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0pt47yr.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_01xbj_9._.js +33 -0
- package/.next/server/chunks/ssr/node_modules_01xbj_9._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1c5ky4f._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1c5ky4f._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +6 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0wpq8j3._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0wpq8j3._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0q-w892.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0q-w892.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_loading_tsx_01g_-m0._.js +3 -0
- package/.next/server/chunks/ssr/src_app_loading_tsx_01g_-m0._.js.map +1 -0
- package/.next/server/middleware-build-manifest.js +24 -1
- package/.next/server/middleware-manifest.json +2 -2
- package/.next/server/next-font-manifest.js +1 -1
- package/.next/server/next-font-manifest.json +15 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages-manifest.json +2 -4
- package/.next/server/prefetch-hints.json +25 -0
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +94 -1
- package/.next/static/chunks/19mx3mg6lkumu.js +1 -0
- package/.next/static/chunks/1las_6j17xa9p.js +1 -0
- package/.next/static/chunks/1xk6snnh6e5_j.css +3 -0
- package/.next/static/chunks/2-rtuqsgzmno4.js +22 -0
- package/.next/static/chunks/27t_qfc-3_lzs.js +1 -0
- package/.next/static/chunks/2sswp23h6zh08.js +345 -0
- package/.next/static/chunks/310vm2bl3xxpt.js +31 -0
- package/.next/static/chunks/3fntmmi971322.js +1 -0
- package/.next/static/chunks/turbopack-1b6uko1cu_h42.js +1 -0
- package/.next/static/media/4fa387ec64143e14-s.2tuy5pz7dlieh.woff2 +0 -0
- package/.next/static/media/53b9e256198e5412-s.390ncx5urfkfu.woff2 +0 -0
- package/.next/static/media/5ce348bf30bf5439-s.31988l_ccedte.woff2 +0 -0
- package/.next/static/media/6306c77e7c8268e4-s.2dbetqa9o8jxf.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.21jp631_3pja2.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.0r6juujl39pe6.woff2 +0 -0
- package/.next/static/media/7d817b4c03b0c5f1-s.1uyisp29ctx0d.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.1qq4vpdcun5oj.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.1rgnod-3esatf.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.0wgildi0cnwt9.woff2 +0 -0
- package/.next/static/media/favicon.2246eezznj2ab.ico +0 -0
- package/.next/static/media/fef07dbb0973bf53-s.3p2_lha1f2xer.woff2 +0 -0
- package/.next/static/rjdzHqzPw2GCNhDbjcu0-/_buildManifest.js +11 -0
- package/.next/static/rjdzHqzPw2GCNhDbjcu0-/_clientMiddlewareManifest.js +1 -0
- package/README.md +176 -4
- package/bin/pkgviz.ts +57 -29
- package/package.json +57 -36
- package/src/app/actions/audit.actions.ts +7 -49
- package/src/app/globals.css +0 -2
- package/src/app/layout.tsx +3 -2
- package/src/app/loading.tsx +8 -0
- package/src/app/page.tsx +16 -2
- package/src/app/utils/buildGraph.ts +99 -100
- package/src/app/utils/getParsedFileStructure.ts +128 -54
- package/src/app/utils/inspectParserLanguageAsync.ts +39 -0
- package/src/app/utils/markCyclicPackages.ts +45 -185
- package/src/app/utils/parser/cpp/parseCppFile.ts +68 -86
- package/src/app/utils/parser/delphi/parseFile.ts +36 -120
- package/src/app/utils/parser/java/findEntryPoint.ts +2 -1
- package/src/app/utils/parser/java/parseJavaFile.ts +33 -45
- package/src/app/utils/parser/kotlin/parseFile.ts +34 -87
- package/src/app/utils/parser/python/parseFile.ts +30 -100
- package/src/app/utils/parser/typescript/parseFile.ts +17 -52
- package/src/app/utils/selectParserLanguage.ts +39 -0
- package/src/cli/formatAuditRuleFailures.ts +21 -0
- package/src/cli/runAuditAsync.ts +41 -0
- package/src/components/Breadcrumb.tsx +5 -4
- package/src/components/ExportPanel.tsx +53 -0
- package/src/components/Header.tsx +1 -0
- package/src/components/Loader.tsx +8 -2
- package/src/components/ProjectLoadError.tsx +15 -0
- package/src/components/SettingsPanel.tsx +184 -0
- package/src/components/Switch.tsx +9 -17
- package/src/components/ThemeToggle.tsx +2 -1
- package/src/components/ToggleSwitch.tsx +36 -0
- package/src/components/sidebar/Sidebar.tsx +14 -0
- package/src/components/sidebar/SidebarBadge.tsx +25 -0
- package/src/components/sidebar/SidebarRow.tsx +14 -0
- package/src/components/sidebar/SidebarSection.tsx +16 -0
- package/src/components/sidebar/SidebarTabs.tsx +58 -0
- package/src/contexts/SettingsContext.tsx +19 -20
- package/src/features/audit/adapters/inbound/react/AuditRuleList.tsx +76 -0
- package/src/features/audit/adapters/inbound/react/AuditRulePanel.tsx +30 -0
- package/src/features/audit/adapters/inbound/react/CycleInspector.tsx +116 -0
- package/src/features/audit/adapters/inbound/react/CyclicDependenciesRuleDetails.tsx +124 -0
- package/src/features/audit/adapters/inbound/react/useCycleSelection.ts +47 -0
- package/src/features/audit/application/use-cases/createAuditFromSnapshot.ts +28 -0
- package/src/features/audit/application/use-cases/resolveSelectedCycleIds.ts +18 -0
- package/src/features/audit/composition/createAuditAsync.ts +11 -0
- package/src/features/audit/domain/evaluateAuditRules.ts +42 -0
- package/src/features/audit/domain/hasBlockingAuditRuleFailure.ts +6 -0
- package/src/features/audit/domain/resolveAuditConfiguration.ts +27 -0
- package/src/features/audit/utils/cycleVisualization.ts +86 -0
- package/src/features/dependency-analysis/adapters/outbound/dependency-graph/analyzeDependencyImportsAsync.ts +172 -0
- package/src/features/dependency-analysis/adapters/outbound/dependency-graph/analyzeTypeScriptImportsAsync.ts +6 -0
- package/src/features/graph-view/adapters/inbound/react/DependencyGraphView.tsx +184 -0
- package/src/features/graph-view/adapters/inbound/react/GraphZoomControls.tsx +48 -0
- package/src/features/graph-view/adapters/inbound/react/applyGraphInteractionPresentation.ts +35 -0
- package/src/features/graph-view/adapters/inbound/react/createGraphViewModel.ts +240 -0
- package/src/features/graph-view/adapters/inbound/react/createGraphViewStyles.ts +37 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphFocus.ts +104 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphInteractions.ts +50 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphProjection.ts +71 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphViewport.ts +48 -0
- package/src/features/graph-view/domain/getDependencyHighlightClasses.ts +39 -0
- package/src/features/graph-view/domain/reduceGraphInteraction.ts +23 -0
- package/src/features/graph-view/utils/createCompoundOpacityIndex.ts +38 -0
- package/src/features/graph-view/utils/projectVisibleGraph.ts +94 -0
- package/src/features/graph-view/utils/readNodeDefinitionId.ts +7 -0
- package/src/features/graph-view/utils/removeEmptyStructuralNodes.ts +27 -0
- package/src/features/project-analysis/adapters/outbound/filesystem/readProjectSnapshotAsync.ts +12 -0
- package/src/features/project-analysis/application/use-cases/createProjectSnapshotReader.ts +29 -0
- package/src/features/project-analysis/composition/loadProjectOverviewAsync.ts +14 -0
- package/src/features/project-analysis/composition/loadProjectSnapshotAsync.ts +12 -0
- package/src/features/project-tree/adapters/inbound/react/ProjectTreePanel.tsx +52 -0
- package/src/features/project-tree/adapters/inbound/react/useProjectTreeExpansion.ts +46 -0
- package/src/features/project-tree/application/use-cases/buildProjectTree.ts +61 -0
- package/src/features/project-tree/application/use-cases/resolveProjectTreeNavigation.ts +13 -0
- package/src/features/project-tree/utils/findProjectTreeNode.ts +14 -0
- package/src/features/project-tree/utils/findProjectTreeNodeByGraphPackage.ts +21 -0
- package/src/features/project-tree/utils/getProjectTreeAncestorIds.ts +26 -0
- package/src/features/settings/utils/readSettingsEnvironment.ts +53 -0
- package/src/i18n/en.ts +21 -2
- package/src/i18n/i18n.ts +2 -3
- package/src/layouts/breadthfirst/style.ts +1 -0
- package/src/layouts/circle/style.ts +1 -0
- package/src/layouts/concentric/style.ts +1 -0
- package/src/layouts/elk/layout.ts +1 -3
- package/src/layouts/elk/style.ts +1 -0
- package/src/layouts/getWeightBuckets.ts +3 -1
- package/src/layouts/grid/style.ts +1 -0
- package/src/layouts/index.ts +0 -4
- package/src/layouts/style.ts +172 -25
- package/src/screens/home/Home.tsx +73 -25
- package/src/screens/home/HomeGraph.tsx +43 -0
- package/src/screens/home/HomeSidebar.tsx +129 -0
- package/src/shared/types/index.ts +0 -9
- package/src/shared/utils/getProjectName.ts +4 -1
- package/src/shared/utils/parseProjectPath.ts +1 -0
- package/src/shared/utils/toPosix.ts +1 -1
- package/src/types/audit.ts +76 -0
- package/src/types/auditVisualization.ts +22 -0
- package/src/types/graphInteraction.ts +9 -0
- package/src/types/parserSelection.ts +11 -0
- package/src/types/projectAnalysis.ts +20 -0
- package/src/types/projectAnalysisActionResult.ts +2 -0
- package/src/types/projectTree.ts +7 -0
- package/src/utils/filter/filterByPackagePrefix.ts +25 -7
- package/src/utils/filter/filterEmptyPackages.ts +28 -29
- package/src/utils/filter/filterSubPackagesFromDepth.ts +20 -17
- package/src/utils/filter/filterVendorPackages.ts +1 -1
- package/src/utils/filter/isIntrinsicGraphNode.ts +8 -0
- package/src/utils/filter/toggleCompoundNodes.ts +41 -31
- package/src/utils/runProjectAnalysisActionAsync.ts +14 -0
- package/tsconfig.json +11 -3
- package/.next/app-build-manifest.json +0 -29
- package/.next/cache/.previewinfo +0 -1
- package/.next/cache/.rscinfo +0 -1
- package/.next/cache/.tsbuildinfo +0 -1
- package/.next/cache/chrome-devtools-workspace-uuid +0 -1
- package/.next/cache/eslint/.cache_6t30dc +0 -1
- package/.next/cache/webpack/client-production/0.pack +0 -4
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/10.pack +0 -0
- package/.next/cache/webpack/client-production/11.pack +0 -0
- package/.next/cache/webpack/client-production/12.pack +0 -0
- package/.next/cache/webpack/client-production/13.pack +0 -0
- package/.next/cache/webpack/client-production/14.pack +0 -0
- package/.next/cache/webpack/client-production/15.pack +0 -0
- package/.next/cache/webpack/client-production/16.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/3.pack +0 -0
- package/.next/cache/webpack/client-production/4.pack +0 -0
- package/.next/cache/webpack/client-production/5.pack +0 -0
- package/.next/cache/webpack/client-production/6.pack +0 -0
- package/.next/cache/webpack/client-production/7.pack +0 -0
- package/.next/cache/webpack/client-production/8.pack +0 -0
- package/.next/cache/webpack/client-production/9.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/1.pack +0 -0
- package/.next/cache/webpack/server-production/10.pack +0 -4
- package/.next/cache/webpack/server-production/11.pack +0 -0
- package/.next/cache/webpack/server-production/12.pack +0 -0
- package/.next/cache/webpack/server-production/13.pack +0 -0
- package/.next/cache/webpack/server-production/14.pack +0 -0
- package/.next/cache/webpack/server-production/15.pack +0 -0
- package/.next/cache/webpack/server-production/16.pack +0 -0
- package/.next/cache/webpack/server-production/17.pack +0 -0
- package/.next/cache/webpack/server-production/18.pack +0 -4
- package/.next/cache/webpack/server-production/2.pack +0 -0
- package/.next/cache/webpack/server-production/3.pack +0 -0
- package/.next/cache/webpack/server-production/4.pack +0 -0
- package/.next/cache/webpack/server-production/5.pack +0 -0
- package/.next/cache/webpack/server-production/6.pack +0 -0
- package/.next/cache/webpack/server-production/7.pack +0 -0
- package/.next/cache/webpack/server-production/8.pack +0 -0
- package/.next/cache/webpack/server-production/9.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/.next/diagnostics/build-diagnostics.json +0 -6
- package/.next/diagnostics/framework.json +0 -1
- package/.next/server/app/index.html +0 -1
- package/.next/server/app/index.meta +0 -7
- package/.next/server/app/index.rsc +0 -20
- package/.next/server/chunks/548.js +0 -6
- package/.next/server/chunks/610.js +0 -7
- package/.next/server/chunks/985.js +0 -22
- package/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/.next/server/pages/_app.js +0 -1
- package/.next/server/pages/_app.js.nft.json +0 -1
- package/.next/server/pages/_document.js +0 -1
- package/.next/server/pages/_document.js.nft.json +0 -1
- package/.next/server/pages/_error.js +0 -19
- package/.next/server/pages/_error.js.nft.json +0 -1
- package/.next/server/webpack-runtime.js +0 -1
- package/.next/static/_YC2p40ZiYT2Gcw-h_tjC/_buildManifest.js +0 -1
- package/.next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js +0 -1
- package/.next/static/chunks/680-55ad17895c8fb70b.js +0 -1
- package/.next/static/chunks/90542734-29e255269788f1bd.js +0 -1
- package/.next/static/chunks/91dbc596-b9cdccd3f5cba95d.js +0 -1
- package/.next/static/chunks/964-b440f7af22c41ca5.js +0 -1
- package/.next/static/chunks/app/_not-found/page-11e4fea8e290f304.js +0 -1
- package/.next/static/chunks/app/layout-8aae7fba5ed8afb3.js +0 -1
- package/.next/static/chunks/app/page-91450b1230da8bca.js +0 -1
- package/.next/static/chunks/framework-bc35dade6ff9684e.js +0 -1
- package/.next/static/chunks/main-9e86d333c1e02dd1.js +0 -1
- package/.next/static/chunks/main-app-69a9ff75ff3465ca.js +0 -1
- package/.next/static/chunks/pages/_app-0a0020ddd67f79cf.js +0 -1
- package/.next/static/chunks/pages/_error-03529f2c21436739.js +0 -1
- package/.next/static/chunks/webpack-7adfafc806738767.js +0 -1
- package/.next/static/css/ec31779168107a11.css +0 -3
- package/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- package/.next/trace +0 -2
- package/.next/types/app/layout.ts +0 -84
- package/.next/types/app/page.ts +0 -84
- package/.next/types/cache-life.d.ts +0 -141
- package/.next/types/package.json +0 -1
- package/src/app/actions/graph.actions.ts +0 -25
- package/src/app/utils/parser/cpp/extractCppPackageFromImport.ts +0 -18
- package/src/app/utils/parser/delphi/extractPackageFromImport.ts +0 -21
- package/src/app/utils/parser/java/extractJavaPackageFromImport.ts +0 -39
- package/src/app/utils/parser/java/getIntrinsicPackagesRecursive.ts +0 -33
- package/src/app/utils/parser/kotlin/extractPackageFromImport.ts +0 -19
- package/src/app/utils/parser/python/extractPythonPackageFromImport.ts +0 -18
- package/src/app/utils/parser/typescript/extractTypeScriptPackageFromImport.ts +0 -18
- package/src/components/Cytoscape.tsx +0 -23
- package/src/components/Setting.tsx +0 -17
- package/src/components/Settings.tsx +0 -189
- package/src/components/ZoomInput.tsx +0 -94
- package/src/components/useCytoscape.ts +0 -343
- package/src/layouts/getLayoutStyle.ts +0 -19
- package/src/shared/utils/detectLanguage.ts +0 -255
- package/src/shared/utils/getJsonAsync.ts +0 -13
- package/src/shared/utils/parseEnv.ts +0 -91
- package/src/store/useLocalStorage.ts +0 -29
- package/src/utils/hasChildren.ts +0 -7
- /package/.next/{react-loadable-manifest.json → server/app/_global-error/page/react-loadable-manifest.json} +0 -0
- /package/.next/static/chunks/{polyfills-42372ed130431b0a.js → 0cz1d0mv5g_q7.js} +0 -0
- /package/.next/static/{_YC2p40ZiYT2Gcw-h_tjC → rjdzHqzPw2GCNhDbjcu0-}/_ssgManifest.js +0 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { LucideLoader } from 'lucide-react';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
|
+
/*** Renders the loading indicator. */
|
|
4
5
|
export default function Loader() {
|
|
5
6
|
return (
|
|
6
|
-
<div
|
|
7
|
+
<div
|
|
8
|
+
data-testid="loader"
|
|
9
|
+
role="status"
|
|
10
|
+
aria-label="Loading"
|
|
11
|
+
className="flex min-h-0 min-w-0 flex-1 items-center justify-center"
|
|
12
|
+
>
|
|
7
13
|
<LucideLoader />
|
|
8
14
|
</div>
|
|
9
15
|
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface ProjectLoadErrorProps {
|
|
2
|
+
readonly message: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/*** Renders a persistent project-loading error without taking down the surrounding PKGViz UI. */
|
|
6
|
+
export default function ProjectLoadError({ message }: ProjectLoadErrorProps) {
|
|
7
|
+
return (
|
|
8
|
+
<div role="alert" className="flex flex-1 items-center justify-center p-6">
|
|
9
|
+
<div className="max-w-xl rounded-md border border-red-300 bg-red-50 p-4 dark:border-red-900 dark:bg-red-950">
|
|
10
|
+
<p className="text-sm font-medium text-red-800 dark:text-red-200">Unable to load project</p>
|
|
11
|
+
<p className="mt-1 break-all text-xs text-red-700 dark:text-red-300">{message}</p>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { ChevronDownIcon } from 'lucide-react';
|
|
3
|
+
import { Select, Slider } from 'radix-ui';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
import { SidebarRow } from '@/components/sidebar/SidebarRow';
|
|
7
|
+
import { SidebarSection } from '@/components/sidebar/SidebarSection';
|
|
8
|
+
import Switch from '@/components/Switch';
|
|
9
|
+
import { useSettings } from '@/contexts/SettingsContext';
|
|
10
|
+
import { t } from '@/i18n/i18n';
|
|
11
|
+
|
|
12
|
+
/*** Renders the persistent first-rank graph controls below secondary sidebar tools. */
|
|
13
|
+
export function SettingsPanel() {
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<FilterSettings />
|
|
17
|
+
<SubPackageDepthSettings />
|
|
18
|
+
<LayoutSettings />
|
|
19
|
+
<LayoutSpacingSettings />
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/*** Renders package-visibility settings. */
|
|
25
|
+
function FilterSettings() {
|
|
26
|
+
const {
|
|
27
|
+
showCompoundNodes,
|
|
28
|
+
showVendorPackages,
|
|
29
|
+
toggleShowCompoundNodes,
|
|
30
|
+
toggleShowVendorPackages,
|
|
31
|
+
} = useSettings();
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SidebarSection title={t('settings.filter')}>
|
|
35
|
+
<SidebarRow>
|
|
36
|
+
<Switch
|
|
37
|
+
id="switch-show-vendor-packages"
|
|
38
|
+
label={t('settings.showVendorPackages')}
|
|
39
|
+
onToggle={toggleShowVendorPackages}
|
|
40
|
+
value={showVendorPackages}
|
|
41
|
+
/>
|
|
42
|
+
</SidebarRow>
|
|
43
|
+
<SidebarRow>
|
|
44
|
+
<Switch
|
|
45
|
+
id="switch-show-compound-nodes"
|
|
46
|
+
label={t('settings.showCompoundNodes')}
|
|
47
|
+
onToggle={toggleShowCompoundNodes}
|
|
48
|
+
value={showCompoundNodes}
|
|
49
|
+
/>
|
|
50
|
+
</SidebarRow>
|
|
51
|
+
</SidebarSection>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*** Renders the visible subpackage-depth control. */
|
|
56
|
+
function SubPackageDepthSettings() {
|
|
57
|
+
const { maxSubPackageDepth, setSubPackageDepth, subPackageDepth } = useSettings();
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<SidebarSection title={t('settings.subPackageDepth') + ': ' + subPackageDepth}>
|
|
61
|
+
<SidebarRow>
|
|
62
|
+
<SettingsSlider
|
|
63
|
+
ariaLabel={t('settings.subPackageDepth')}
|
|
64
|
+
max={maxSubPackageDepth}
|
|
65
|
+
min={1}
|
|
66
|
+
step={1}
|
|
67
|
+
value={subPackageDepth}
|
|
68
|
+
onValueChange={setSubPackageDepth}
|
|
69
|
+
/>
|
|
70
|
+
</SidebarRow>
|
|
71
|
+
</SidebarSection>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/*** Renders the active Cytoscape layout selector. */
|
|
76
|
+
function LayoutSettings() {
|
|
77
|
+
const { cytoscapeLayout, setCytoscapeLayout } = useSettings();
|
|
78
|
+
|
|
79
|
+
/*** Lets the Select close immediately before starting a potentially expensive graph layout. */
|
|
80
|
+
const selectLayout = (layout: string) => {
|
|
81
|
+
if (
|
|
82
|
+
layout !== 'breadthfirst' &&
|
|
83
|
+
layout !== 'circle' &&
|
|
84
|
+
layout !== 'concentric' &&
|
|
85
|
+
layout !== 'elk' &&
|
|
86
|
+
layout !== 'grid'
|
|
87
|
+
) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
React.startTransition(() => setCytoscapeLayout(layout));
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<SidebarSection title={t('settings.layout')}>
|
|
96
|
+
<SidebarRow>
|
|
97
|
+
<Select.Root value={cytoscapeLayout} onValueChange={selectLayout}>
|
|
98
|
+
<Select.Trigger
|
|
99
|
+
aria-label={t('cytoscapeLayout')}
|
|
100
|
+
className="inline-flex h-9 w-full items-center justify-between rounded-md border px-3"
|
|
101
|
+
>
|
|
102
|
+
<Select.Value className="text-foreground" />
|
|
103
|
+
<Select.Icon>
|
|
104
|
+
<ChevronDownIcon size={16} />
|
|
105
|
+
</Select.Icon>
|
|
106
|
+
</Select.Trigger>
|
|
107
|
+
<Select.Portal>
|
|
108
|
+
<Select.Content
|
|
109
|
+
position="popper"
|
|
110
|
+
side="bottom"
|
|
111
|
+
align="start"
|
|
112
|
+
sideOffset={6}
|
|
113
|
+
className="z-50 min-w-(--radix-select-trigger-width) rounded-md border bg-white shadow-md dark:bg-neutral-900"
|
|
114
|
+
>
|
|
115
|
+
<Select.Viewport className="p-1">
|
|
116
|
+
<Select.Group>
|
|
117
|
+
{['breadthfirst', 'circle', 'concentric', 'elk', 'grid'].map(layout => (
|
|
118
|
+
<Select.Item
|
|
119
|
+
key={layout}
|
|
120
|
+
value={layout}
|
|
121
|
+
textValue={t(layout)}
|
|
122
|
+
className="rounded px-2 py-1.5 hover:bg-neutral-100 dark:hover:bg-neutral-800"
|
|
123
|
+
>
|
|
124
|
+
<Select.ItemText>{t(layout)}</Select.ItemText>
|
|
125
|
+
</Select.Item>
|
|
126
|
+
))}
|
|
127
|
+
</Select.Group>
|
|
128
|
+
</Select.Viewport>
|
|
129
|
+
</Select.Content>
|
|
130
|
+
</Select.Portal>
|
|
131
|
+
</Select.Root>
|
|
132
|
+
</SidebarRow>
|
|
133
|
+
</SidebarSection>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/*** Renders the active layout-spacing control. */
|
|
138
|
+
function LayoutSpacingSettings() {
|
|
139
|
+
const { cytoscapeLayoutSpacing, setCytoscapeLayoutSpacing } = useSettings();
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<SidebarSection title={t('settings.layoutSpacing') + ': ' + cytoscapeLayoutSpacing.toFixed(2)}>
|
|
143
|
+
<SidebarRow>
|
|
144
|
+
<SettingsSlider
|
|
145
|
+
ariaLabel={t('settings.layoutSpacing')}
|
|
146
|
+
max={1}
|
|
147
|
+
min={0.1}
|
|
148
|
+
step={0.01}
|
|
149
|
+
value={cytoscapeLayoutSpacing}
|
|
150
|
+
onValueChange={setCytoscapeLayoutSpacing}
|
|
151
|
+
/>
|
|
152
|
+
</SidebarRow>
|
|
153
|
+
</SidebarSection>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*** Renders the shared slider shape used by numeric sidebar settings. */
|
|
158
|
+
function SettingsSlider({ ariaLabel, max, min, onValueChange, step, value }: SettingsSliderProps) {
|
|
159
|
+
return (
|
|
160
|
+
<Slider.Root
|
|
161
|
+
min={min}
|
|
162
|
+
max={max}
|
|
163
|
+
step={step}
|
|
164
|
+
value={[value]}
|
|
165
|
+
onValueChange={([nextValue]) => onValueChange(nextValue)}
|
|
166
|
+
aria-label={ariaLabel}
|
|
167
|
+
className="relative flex h-5 w-full touch-none select-none items-center"
|
|
168
|
+
>
|
|
169
|
+
<Slider.Track className="relative h-1.5 grow rounded-full bg-neutral-200 dark:bg-neutral-800">
|
|
170
|
+
<Slider.Range className="absolute h-1.5 rounded-full bg-blue-600 dark:bg-blue-400" />
|
|
171
|
+
</Slider.Track>
|
|
172
|
+
<Slider.Thumb className="block h-4 w-4 rounded-full border border-neutral-300 bg-white shadow focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-neutral-600 dark:bg-neutral-100" />
|
|
173
|
+
</Slider.Root>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
interface SettingsSliderProps {
|
|
178
|
+
readonly ariaLabel: string;
|
|
179
|
+
readonly max: number;
|
|
180
|
+
readonly min: number;
|
|
181
|
+
readonly onValueChange: (value: number) => void;
|
|
182
|
+
readonly step: number;
|
|
183
|
+
readonly value: number;
|
|
184
|
+
}
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { Switch } from 'radix-ui';
|
|
4
3
|
|
|
4
|
+
import { ToggleSwitch } from '@/components/ToggleSwitch';
|
|
5
|
+
|
|
6
|
+
/*** Renders a labeled settings switch. */
|
|
5
7
|
export default function RadixSwitch({ id, label, value, onToggle }: ISwitch) {
|
|
6
8
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
className="relative h-[18px] w-[42px] cursor-default rounded-full bg-neutral-200 dark:bg-neutral-800 outline-none data-[state=checked]:bg-neutral-200 dark:data-[state=checked]:bg-gray-700"
|
|
14
|
-
defaultChecked={value}
|
|
15
|
-
id={id}
|
|
16
|
-
checked={value}
|
|
17
|
-
onCheckedChange={onToggle}
|
|
18
|
-
>
|
|
19
|
-
<Switch.Thumb className="block size-[16px] translate-x-0.5 rounded-full bg-neutral-500 dark:bg-neutral-500 transition-transform duration-100 will-change-transform data-[state=checked]:bg-blue-500 dark:data-[state=checked]:bg-white data-[state=checked]:translate-x-[24px]" />
|
|
20
|
-
</Switch.Root>
|
|
21
|
-
</div>
|
|
22
|
-
</form>
|
|
9
|
+
<div className="flex h-[20px] items-center justify-between">
|
|
10
|
+
<label className="pr-[15px] leading-none whitespace-nowrap text-foreground" htmlFor={id}>
|
|
11
|
+
{label}
|
|
12
|
+
</label>
|
|
13
|
+
<ToggleSwitch ariaLabel={label} id={id} onToggle={onToggle} value={value} />
|
|
14
|
+
</div>
|
|
23
15
|
);
|
|
24
16
|
}
|
|
25
17
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
2
|
import { useTheme } from 'next-themes';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
4
|
|
|
5
|
+
/*** Renders the light and dark theme toggle. */
|
|
5
6
|
export default function ThemeToggle() {
|
|
6
7
|
const { theme, setTheme, resolvedTheme } = useTheme();
|
|
7
8
|
const [mounted, setMounted] = useState(false);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Switch } from 'radix-ui';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
/*** Renders a switch control without imposing row or label layout. */
|
|
6
|
+
export function ToggleSwitch({ ariaLabel, checkedColor, id, onToggle, value }: ToggleSwitchProps) {
|
|
7
|
+
return (
|
|
8
|
+
<Switch.Root
|
|
9
|
+
aria-label={ariaLabel}
|
|
10
|
+
className="relative h-[18px] w-[42px] shrink-0 cursor-pointer rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-neutral-200 dark:bg-neutral-800 dark:data-[state=checked]:bg-gray-700"
|
|
11
|
+
id={id}
|
|
12
|
+
checked={value}
|
|
13
|
+
onCheckedChange={onToggle}
|
|
14
|
+
>
|
|
15
|
+
{value && checkedColor ? (
|
|
16
|
+
<span
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
className="pointer-events-none absolute inset-0 rounded-full opacity-25"
|
|
19
|
+
style={{ backgroundColor: checkedColor }}
|
|
20
|
+
/>
|
|
21
|
+
) : null}
|
|
22
|
+
<Switch.Thumb
|
|
23
|
+
className="relative block size-[16px] translate-x-0.5 rounded-full bg-neutral-500 transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[24px] data-[state=checked]:bg-blue-500 dark:bg-neutral-500 dark:data-[state=checked]:bg-white"
|
|
24
|
+
style={value && checkedColor ? { backgroundColor: checkedColor } : undefined}
|
|
25
|
+
/>
|
|
26
|
+
</Switch.Root>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ToggleSwitchProps {
|
|
31
|
+
readonly ariaLabel: string;
|
|
32
|
+
readonly checkedColor?: string;
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly value: boolean;
|
|
35
|
+
readonly onToggle: () => void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/*** Renders the fixed-width application sidebar shell. */
|
|
4
|
+
export function Sidebar({ children }: SidebarProps) {
|
|
5
|
+
return (
|
|
6
|
+
<aside className="flex min-h-0 w-[18rem] min-w-[18rem] max-w-[18rem] shrink-0 self-stretch flex-col overflow-hidden border-r border-r-neutral-200 bg-neutral-100 md:pt-14 dark:border-r-neutral-800 dark:bg-neutral-950">
|
|
7
|
+
{children}
|
|
8
|
+
</aside>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface SidebarProps {
|
|
13
|
+
readonly children: React.ReactNode;
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/*** Renders a compact circular count badge for sidebar findings and secondary tabs. */
|
|
4
|
+
export function SidebarBadge({ count, tone = 'neutral' }: SidebarBadgeProps) {
|
|
5
|
+
const toneClass =
|
|
6
|
+
tone === 'danger'
|
|
7
|
+
? 'border-red-300 bg-red-50 text-red-700 dark:border-red-900 dark:bg-red-950 dark:text-red-300'
|
|
8
|
+
: 'border-neutral-300 text-neutral-700 dark:border-neutral-700 dark:text-neutral-200';
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<span
|
|
12
|
+
className={
|
|
13
|
+
'inline-flex h-5 min-w-5 shrink-0 items-center justify-center rounded-full border px-1 text-[10px] font-semibold leading-none ' +
|
|
14
|
+
toneClass
|
|
15
|
+
}
|
|
16
|
+
>
|
|
17
|
+
{count}
|
|
18
|
+
</span>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SidebarBadgeProps {
|
|
23
|
+
readonly count: number;
|
|
24
|
+
readonly tone?: 'danger' | 'neutral';
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/*** Renders one consistently styled row inside an application-sidebar section. */
|
|
4
|
+
export function SidebarRow({ children }: SidebarRowProps) {
|
|
5
|
+
return (
|
|
6
|
+
<div className="ml-3 border-b border-b-neutral-200 bg-white px-3 py-2 dark:border-b-neutral-800 dark:bg-neutral-900">
|
|
7
|
+
{children}
|
|
8
|
+
</div>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface SidebarRowProps {
|
|
13
|
+
readonly children: React.ReactNode;
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/*** Renders a non-collapsible application-sidebar category. */
|
|
4
|
+
export function SidebarSection({ children, title }: SidebarSectionProps) {
|
|
5
|
+
return (
|
|
6
|
+
<section>
|
|
7
|
+
<h3 className="mx-6 mt-6 mb-2 text-sm font-bold">{title}</h3>
|
|
8
|
+
{children}
|
|
9
|
+
</section>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface SidebarSectionProps {
|
|
14
|
+
readonly children: React.ReactNode;
|
|
15
|
+
readonly title: React.ReactNode;
|
|
16
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Tabs } from 'radix-ui';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { SidebarBadge } from '@/components/sidebar/SidebarBadge';
|
|
6
|
+
|
|
7
|
+
/*** Renders reusable secondary sidebar views above the persistent graph settings. */
|
|
8
|
+
export function SidebarTabs({ ariaLabel, onValueChange, tabs, value }: SidebarTabsProps) {
|
|
9
|
+
return (
|
|
10
|
+
<Tabs.Root
|
|
11
|
+
value={value ?? ''}
|
|
12
|
+
onValueChange={onValueChange}
|
|
13
|
+
className="flex min-h-0 flex-1 flex-col overflow-hidden"
|
|
14
|
+
>
|
|
15
|
+
<Tabs.List
|
|
16
|
+
aria-label={ariaLabel}
|
|
17
|
+
className="ml-3 flex shrink-0 border-b border-neutral-200 dark:border-neutral-800"
|
|
18
|
+
>
|
|
19
|
+
{tabs.map(tab => (
|
|
20
|
+
<Tabs.Trigger
|
|
21
|
+
key={tab.id}
|
|
22
|
+
value={tab.id}
|
|
23
|
+
disabled={tab.disabled}
|
|
24
|
+
className="flex flex-1 items-center justify-center gap-1.5 border-b-2 border-transparent px-3 py-2 text-xs text-neutral-500 disabled:cursor-default disabled:opacity-40 data-[state=active]:border-blue-600 data-[state=active]:text-neutral-900 dark:text-neutral-400 dark:data-[state=active]:border-blue-400 dark:data-[state=active]:text-neutral-100"
|
|
25
|
+
>
|
|
26
|
+
<span>{tab.label}</span>
|
|
27
|
+
{tab.badge ? <SidebarBadge count={tab.badge} tone={tab.badgeTone} /> : null}
|
|
28
|
+
</Tabs.Trigger>
|
|
29
|
+
))}
|
|
30
|
+
</Tabs.List>
|
|
31
|
+
{tabs.map(tab => (
|
|
32
|
+
<Tabs.Content
|
|
33
|
+
key={tab.id}
|
|
34
|
+
value={tab.id}
|
|
35
|
+
className="min-h-0 flex-1 overflow-y-auto border-b border-neutral-200 pb-3 outline-none dark:border-neutral-800"
|
|
36
|
+
>
|
|
37
|
+
{tab.content}
|
|
38
|
+
</Tabs.Content>
|
|
39
|
+
))}
|
|
40
|
+
</Tabs.Root>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface SidebarTab {
|
|
45
|
+
readonly badge?: number;
|
|
46
|
+
readonly badgeTone?: 'danger' | 'neutral';
|
|
47
|
+
readonly content: React.ReactNode;
|
|
48
|
+
readonly disabled?: boolean;
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly label: React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface SidebarTabsProps {
|
|
54
|
+
readonly ariaLabel: string;
|
|
55
|
+
readonly onValueChange: (value: string) => void;
|
|
56
|
+
readonly tabs: readonly SidebarTab[];
|
|
57
|
+
readonly value: string | null;
|
|
58
|
+
}
|
|
@@ -1,46 +1,40 @@
|
|
|
1
|
+
import { useLocalStorage } from 'ankh-hooks/store';
|
|
1
2
|
import type { LayoutOptions } from 'cytoscape';
|
|
3
|
+
import React, { createContext, type PropsWithChildren, use } from 'react';
|
|
2
4
|
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
getCytoscapeLayout,
|
|
6
|
-
getCytoscapeLayoutSpacing,
|
|
7
|
-
getShowCompoundNodes,
|
|
8
|
-
getShowVendorPackages,
|
|
9
|
-
getSubPackageDepth,
|
|
10
|
-
} from '@/shared/utils/parseEnv';
|
|
11
|
-
import { useLocalStorage } from '@/store/useLocalStorage';
|
|
5
|
+
import { readSettingsEnvironment } from '@/features/settings/utils/readSettingsEnvironment';
|
|
12
6
|
|
|
13
7
|
// Settings context
|
|
14
8
|
const SettingsContext = createContext<ISettingsContext | null>(null);
|
|
15
9
|
|
|
16
|
-
|
|
10
|
+
/*** Provides persisted graph settings to the application. */
|
|
17
11
|
export const SettingsProvider = ({ children }: PropsWithChildren) => {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
1
|
|
21
|
-
);
|
|
12
|
+
const environment = readSettingsEnvironment();
|
|
13
|
+
const [maxSubPackageDepth, setMaxSubPackageDepth] = useMaxSubPackageDepthSetting();
|
|
22
14
|
const [showCompoundNodes, setShowCompoundNodes] = useLocalStorage<boolean>(
|
|
23
15
|
'showCompoundNodes',
|
|
24
|
-
|
|
16
|
+
environment.showCompoundNodes
|
|
25
17
|
);
|
|
26
18
|
const [showVendorPackages, setShowVendorPackages] = useLocalStorage<boolean>(
|
|
27
19
|
'showVendorPackages',
|
|
28
|
-
|
|
20
|
+
environment.showVendorPackages
|
|
29
21
|
);
|
|
30
22
|
const [subPackageDepth, setSubPackageDepth] = useLocalStorage<number>(
|
|
31
23
|
'subPackageDepth',
|
|
32
|
-
|
|
24
|
+
environment.subPackageDepth
|
|
33
25
|
);
|
|
34
26
|
const [cytoscapeLayout, setCytoscapeLayout] = useLocalStorage<LayoutOptions['name']>(
|
|
35
27
|
'cytoscapeLayout',
|
|
36
|
-
|
|
28
|
+
environment.cytoscapeLayout
|
|
37
29
|
);
|
|
38
30
|
const [cytoscapeLayoutSpacing, setCytoscapeLayoutSpacing] = useLocalStorage<number>(
|
|
39
31
|
'cytoscapeLayoutSpacing',
|
|
40
|
-
|
|
32
|
+
environment.cytoscapeLayoutSpacing
|
|
41
33
|
);
|
|
42
34
|
|
|
35
|
+
/*** Toggles vendor package visibility. */
|
|
43
36
|
const toggleShowVendorPackages = () => setShowVendorPackages(prev => !prev);
|
|
37
|
+
/*** Toggles compound node visibility. */
|
|
44
38
|
const toggleShowCompoundNodes = () => setShowCompoundNodes(prev => !prev);
|
|
45
39
|
|
|
46
40
|
return (
|
|
@@ -65,7 +59,12 @@ export const SettingsProvider = ({ children }: PropsWithChildren) => {
|
|
|
65
59
|
);
|
|
66
60
|
};
|
|
67
61
|
|
|
68
|
-
|
|
62
|
+
/*** Owns the persisted maximum package-depth state. */
|
|
63
|
+
function useMaxSubPackageDepthSetting() {
|
|
64
|
+
return useLocalStorage<number>('maxSubPackageDepth', 1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*** Returns the current graph settings context. */
|
|
69
68
|
export function useSettings() {
|
|
70
69
|
const context = use(SettingsContext);
|
|
71
70
|
if (!context) throw new Error('useSettings() must be used within a SettingsProvider');
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { SidebarRow } from '@/components/sidebar/SidebarRow';
|
|
5
|
+
import { SidebarSection } from '@/components/sidebar/SidebarSection';
|
|
6
|
+
import { CyclicDependenciesRuleDetails } from '@/features/audit/adapters/inbound/react/CyclicDependenciesRuleDetails';
|
|
7
|
+
import type { Audit, AuditRuleResult } from '@/types/audit';
|
|
8
|
+
import type { CycleInspection, CycleSelection } from '@/types/auditVisualization';
|
|
9
|
+
|
|
10
|
+
/*** Renders only violated audit rules in the active Rules sidebar tab. */
|
|
11
|
+
export function AuditRuleList({
|
|
12
|
+
evaluation,
|
|
13
|
+
cycleSelection,
|
|
14
|
+
inspectedCycleId,
|
|
15
|
+
onCycleInspectionChange,
|
|
16
|
+
}: AuditRuleListProps) {
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
{evaluation.rules
|
|
20
|
+
.filter(rule => rule.status === 'failed')
|
|
21
|
+
.map(rule => (
|
|
22
|
+
<RuleDetails
|
|
23
|
+
key={rule.id}
|
|
24
|
+
evaluation={evaluation}
|
|
25
|
+
rule={rule}
|
|
26
|
+
cycleSelection={cycleSelection}
|
|
27
|
+
inspectedCycleId={inspectedCycleId}
|
|
28
|
+
onCycleInspectionChange={onCycleInspectionChange}
|
|
29
|
+
/>
|
|
30
|
+
))}
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*** Dispatches one violated rule to its dedicated sidebar renderer. */
|
|
36
|
+
function RuleDetails({
|
|
37
|
+
evaluation,
|
|
38
|
+
cycleSelection,
|
|
39
|
+
inspectedCycleId,
|
|
40
|
+
onCycleInspectionChange,
|
|
41
|
+
rule,
|
|
42
|
+
}: RuleDetailsProps) {
|
|
43
|
+
if (rule.id === 'cyclic-dependencies') {
|
|
44
|
+
return (
|
|
45
|
+
<CyclicDependenciesRuleDetails
|
|
46
|
+
cycles={evaluation.cyclicPackages}
|
|
47
|
+
cycleSelection={cycleSelection}
|
|
48
|
+
inspectedCycleId={inspectedCycleId}
|
|
49
|
+
onCycleInspectionChange={onCycleInspectionChange}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<SidebarSection title={rule.id}>
|
|
56
|
+
{rule.details.map((detail, index) => (
|
|
57
|
+
<SidebarRow key={detail + ':' + index}>
|
|
58
|
+
<code className="block truncate text-[11px]" title={detail}>
|
|
59
|
+
{detail}
|
|
60
|
+
</code>
|
|
61
|
+
</SidebarRow>
|
|
62
|
+
))}
|
|
63
|
+
</SidebarSection>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface AuditRuleListProps {
|
|
68
|
+
readonly inspectedCycleId?: string | null;
|
|
69
|
+
readonly evaluation: Audit['evaluation'];
|
|
70
|
+
readonly cycleSelection: CycleSelection;
|
|
71
|
+
readonly onCycleInspectionChange: (inspection: CycleInspection | null) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface RuleDetailsProps extends AuditRuleListProps {
|
|
75
|
+
readonly rule: AuditRuleResult;
|
|
76
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { AuditRuleList } from '@/features/audit/adapters/inbound/react/AuditRuleList';
|
|
5
|
+
import type { Audit } from '@/types/audit';
|
|
6
|
+
import type { CycleInspection, CycleSelection } from '@/types/auditVisualization';
|
|
7
|
+
|
|
8
|
+
/*** Renders violated audit rules while the Rules sidebar tab is active. */
|
|
9
|
+
export function AuditRulePanel({
|
|
10
|
+
evaluation,
|
|
11
|
+
cycleSelection,
|
|
12
|
+
inspectedCycleId,
|
|
13
|
+
onCycleInspectionChange,
|
|
14
|
+
}: AuditRulePanelProps) {
|
|
15
|
+
return (
|
|
16
|
+
<AuditRuleList
|
|
17
|
+
evaluation={evaluation}
|
|
18
|
+
cycleSelection={cycleSelection}
|
|
19
|
+
inspectedCycleId={inspectedCycleId}
|
|
20
|
+
onCycleInspectionChange={onCycleInspectionChange}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface AuditRulePanelProps {
|
|
26
|
+
readonly inspectedCycleId?: string | null;
|
|
27
|
+
readonly evaluation: Audit['evaluation'];
|
|
28
|
+
readonly cycleSelection: CycleSelection;
|
|
29
|
+
readonly onCycleInspectionChange: (inspection: CycleInspection | null) => void;
|
|
30
|
+
}
|