purecontext-mcp 1.1.8 → 1.2.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/AGENT_INSTRUCTIONS.md +393 -0
- package/AGENT_INSTRUCTIONS_SHORT.md +53 -0
- package/AST-SEARCH.md +274 -0
- package/CHANGELOG.md +62 -0
- package/CODE-INTELLIGENCE.md +369 -0
- package/HEALTH-DASHBOARDS.md +241 -0
- package/README.md +7 -0
- package/REFACTORING-SAFELY.md +279 -0
- package/UNDERSTANDING-RELATIONSHIPS.md +240 -0
- package/USER-GUIDE.md +14 -0
- package/VISUALIZING-CODE.md +199 -0
- package/WORKFLOW-TECH-DEBT.md +286 -0
- package/dist/core/db/dep-store.d.ts +75 -0
- package/dist/core/db/dep-store.d.ts.map +1 -1
- package/dist/core/db/dep-store.js +277 -0
- package/dist/core/db/dep-store.js.map +1 -1
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.js +12 -0
- package/dist/core/db/schema.js.map +1 -1
- package/dist/core/index-manager.js +1 -1
- package/dist/core/index-manager.js.map +1 -1
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/graph/diagram-renderer.d.ts +83 -0
- package/dist/graph/diagram-renderer.d.ts.map +1 -0
- package/dist/graph/diagram-renderer.js +294 -0
- package/dist/graph/diagram-renderer.js.map +1 -0
- package/dist/graph/graph-traversal.d.ts +92 -0
- package/dist/graph/graph-traversal.d.ts.map +1 -1
- package/dist/graph/graph-traversal.js +440 -2
- package/dist/graph/graph-traversal.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +145 -0
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/tools/check-delete-safe.d.ts +50 -0
- package/dist/server/tools/check-delete-safe.d.ts.map +1 -0
- package/dist/server/tools/check-delete-safe.js +308 -0
- package/dist/server/tools/check-delete-safe.js.map +1 -0
- package/dist/server/tools/check-move-safe.d.ts +44 -0
- package/dist/server/tools/check-move-safe.d.ts.map +1 -0
- package/dist/server/tools/check-move-safe.js +266 -0
- package/dist/server/tools/check-move-safe.js.map +1 -0
- package/dist/server/tools/check-rename-safe.d.ts +48 -0
- package/dist/server/tools/check-rename-safe.d.ts.map +1 -0
- package/dist/server/tools/check-rename-safe.js +218 -0
- package/dist/server/tools/check-rename-safe.js.map +1 -0
- package/dist/server/tools/diff-health-radar.d.ts +44 -0
- package/dist/server/tools/diff-health-radar.d.ts.map +1 -0
- package/dist/server/tools/diff-health-radar.js +192 -0
- package/dist/server/tools/diff-health-radar.js.map +1 -0
- package/dist/server/tools/find-cycles.d.ts +31 -0
- package/dist/server/tools/find-cycles.d.ts.map +1 -0
- package/dist/server/tools/find-cycles.js +85 -0
- package/dist/server/tools/find-cycles.js.map +1 -0
- package/dist/server/tools/find-implementations.d.ts +47 -0
- package/dist/server/tools/find-implementations.d.ts.map +1 -0
- package/dist/server/tools/find-implementations.js +167 -0
- package/dist/server/tools/find-implementations.js.map +1 -0
- package/dist/server/tools/find-untested-symbols.d.ts +52 -0
- package/dist/server/tools/find-untested-symbols.d.ts.map +1 -0
- package/dist/server/tools/find-untested-symbols.js +308 -0
- package/dist/server/tools/find-untested-symbols.js.map +1 -0
- package/dist/server/tools/get-architecture-snapshot.d.ts +43 -0
- package/dist/server/tools/get-architecture-snapshot.d.ts.map +1 -0
- package/dist/server/tools/get-architecture-snapshot.js +292 -0
- package/dist/server/tools/get-architecture-snapshot.js.map +1 -0
- package/dist/server/tools/get-call-hierarchy.d.ts +43 -0
- package/dist/server/tools/get-call-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/get-call-hierarchy.js +119 -0
- package/dist/server/tools/get-call-hierarchy.js.map +1 -0
- package/dist/server/tools/get-class-hierarchy.d.ts +36 -0
- package/dist/server/tools/get-class-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/get-class-hierarchy.js +125 -0
- package/dist/server/tools/get-class-hierarchy.js.map +1 -0
- package/dist/server/tools/get-complexity-hotspots.d.ts +50 -0
- package/dist/server/tools/get-complexity-hotspots.d.ts.map +1 -0
- package/dist/server/tools/get-complexity-hotspots.js +282 -0
- package/dist/server/tools/get-complexity-hotspots.js.map +1 -0
- package/dist/server/tools/get-coupling-map.d.ts +39 -0
- package/dist/server/tools/get-coupling-map.d.ts.map +1 -0
- package/dist/server/tools/get-coupling-map.js +107 -0
- package/dist/server/tools/get-coupling-map.js.map +1 -0
- package/dist/server/tools/get-debt-report.d.ts +44 -0
- package/dist/server/tools/get-debt-report.d.ts.map +1 -0
- package/dist/server/tools/get-debt-report.js +606 -0
- package/dist/server/tools/get-debt-report.js.map +1 -0
- package/dist/server/tools/get-entry-points.d.ts +79 -0
- package/dist/server/tools/get-entry-points.d.ts.map +1 -0
- package/dist/server/tools/get-entry-points.js +362 -0
- package/dist/server/tools/get-entry-points.js.map +1 -0
- package/dist/server/tools/get-public-api.d.ts +53 -0
- package/dist/server/tools/get-public-api.d.ts.map +1 -0
- package/dist/server/tools/get-public-api.js +218 -0
- package/dist/server/tools/get-public-api.js.map +1 -0
- package/dist/server/tools/get-test-coverage-map.d.ts +66 -0
- package/dist/server/tools/get-test-coverage-map.d.ts.map +1 -0
- package/dist/server/tools/get-test-coverage-map.js +588 -0
- package/dist/server/tools/get-test-coverage-map.js.map +1 -0
- package/dist/server/tools/get-todos.d.ts +51 -0
- package/dist/server/tools/get-todos.d.ts.map +1 -0
- package/dist/server/tools/get-todos.js +180 -0
- package/dist/server/tools/get-todos.js.map +1 -0
- package/dist/server/tools/get-type-graph.d.ts +73 -0
- package/dist/server/tools/get-type-graph.d.ts.map +1 -0
- package/dist/server/tools/get-type-graph.js +437 -0
- package/dist/server/tools/get-type-graph.js.map +1 -0
- package/dist/server/tools/health-radar.d.ts +50 -0
- package/dist/server/tools/health-radar.d.ts.map +1 -0
- package/dist/server/tools/health-radar.js +426 -0
- package/dist/server/tools/health-radar.js.map +1 -0
- package/dist/server/tools/plan-refactoring.d.ts +74 -0
- package/dist/server/tools/plan-refactoring.d.ts.map +1 -0
- package/dist/server/tools/plan-refactoring.js +644 -0
- package/dist/server/tools/plan-refactoring.js.map +1 -0
- package/dist/server/tools/render-call-graph.d.ts +40 -0
- package/dist/server/tools/render-call-graph.d.ts.map +1 -0
- package/dist/server/tools/render-call-graph.js +215 -0
- package/dist/server/tools/render-call-graph.js.map +1 -0
- package/dist/server/tools/render-class-hierarchy.d.ts +42 -0
- package/dist/server/tools/render-class-hierarchy.d.ts.map +1 -0
- package/dist/server/tools/render-class-hierarchy.js +265 -0
- package/dist/server/tools/render-class-hierarchy.js.map +1 -0
- package/dist/server/tools/render-dep-matrix.d.ts +38 -0
- package/dist/server/tools/render-dep-matrix.d.ts.map +1 -0
- package/dist/server/tools/render-dep-matrix.js +186 -0
- package/dist/server/tools/render-dep-matrix.js.map +1 -0
- package/dist/server/tools/render-diagram.d.ts +47 -0
- package/dist/server/tools/render-diagram.d.ts.map +1 -0
- package/dist/server/tools/render-diagram.js +266 -0
- package/dist/server/tools/render-diagram.js.map +1 -0
- package/dist/server/tools/render-import-graph.d.ts +41 -0
- package/dist/server/tools/render-import-graph.d.ts.map +1 -0
- package/dist/server/tools/render-import-graph.js +158 -0
- package/dist/server/tools/render-import-graph.js.map +1 -0
- package/dist/server/tools/search-ast.d.ts +55 -0
- package/dist/server/tools/search-ast.d.ts.map +1 -0
- package/dist/server/tools/search-ast.js +279 -0
- package/dist/server/tools/search-ast.js.map +1 -0
- package/dist/server/tools/search-by-complexity.d.ts +92 -0
- package/dist/server/tools/search-by-complexity.d.ts.map +1 -0
- package/dist/server/tools/search-by-complexity.js +268 -0
- package/dist/server/tools/search-by-complexity.js.map +1 -0
- package/dist/server/tools/search-by-decorator.d.ts +48 -0
- package/dist/server/tools/search-by-decorator.d.ts.map +1 -0
- package/dist/server/tools/search-by-decorator.js +518 -0
- package/dist/server/tools/search-by-decorator.js.map +1 -0
- package/dist/server/tools/search-by-signature.d.ts +56 -0
- package/dist/server/tools/search-by-signature.d.ts.map +1 -0
- package/dist/server/tools/search-by-signature.js +200 -0
- package/dist/server/tools/search-by-signature.js.map +1 -0
- package/dist/ui/assets/BlastRadius-QdgESOL8.js +1 -0
- package/dist/ui/assets/{DependencyGraph-B60SMPbX.js → DependencyGraph-BSMhzwWV.js} +1 -1
- package/dist/ui/assets/{NotFound-Bsg8Wppk.js → NotFound-CipFP_s1.js} +1 -1
- package/dist/ui/assets/{RepoDetail-Cie0D4_s.js → RepoDetail-Dfp5z5Kq.js} +1 -1
- package/dist/ui/assets/{RepoList-CldNt89M.js → RepoList-BKtST3hB.js} +1 -1
- package/dist/ui/assets/{Search-CgvpHMOi.js → Search-DzhGDViy.js} +1 -1
- package/dist/ui/assets/{SymbolView-B9h0LZTz.js → SymbolView-ryVEwAHG.js} +1 -1
- package/dist/ui/assets/{index-DADf5y_L.css → index-Ny8gn9F0.css} +1 -1
- package/dist/ui/assets/{index-eK0wMkUR.js → index-nX2chMqi.js} +2 -2
- package/dist/ui/assets/{useSearch-KAl3Qyi2.js → useSearch-BnBCRKui.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/dev/jcodemunch-gap-analysis.md +198 -0
- package/package.json +9 -1
- package/user-manual.md +2466 -0
- package/dist/ui/assets/BlastRadius-RP7vJEyQ.js +0 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search-by-signature.ts
|
|
3
|
+
*
|
|
4
|
+
* MCP tool: search_by_signature
|
|
5
|
+
*
|
|
6
|
+
* Find all symbols whose type signature matches a pattern — e.g. all functions
|
|
7
|
+
* returning `Promise<void>`, all functions accepting a `Request` parameter,
|
|
8
|
+
* all async functions.
|
|
9
|
+
*
|
|
10
|
+
* Implementation: pure SQL against the `symbols.signature` column.
|
|
11
|
+
* Three modes:
|
|
12
|
+
* - contains → WHERE signature LIKE '%pattern%' (default)
|
|
13
|
+
* - startsWith → WHERE signature LIKE 'pattern%'
|
|
14
|
+
* - regex → user-defined REGEXP function via better-sqlite3
|
|
15
|
+
*
|
|
16
|
+
* No AST re-parsing needed — signatures are stored as one-line strings.
|
|
17
|
+
*/
|
|
18
|
+
import { z } from 'zod';
|
|
19
|
+
import { openDatabase } from '../../core/db/schema.js';
|
|
20
|
+
import { buildMeta } from './_meta.js';
|
|
21
|
+
export const name = 'search_by_signature';
|
|
22
|
+
export const description = 'Find all symbols whose type signature matches a pattern. ' +
|
|
23
|
+
'Use this to locate all async functions, all functions returning a specific type, ' +
|
|
24
|
+
'all functions accepting a particular parameter type, or all exported symbols — ' +
|
|
25
|
+
'without reading files. Operates on the stored one-line signature string for every ' +
|
|
26
|
+
'indexed symbol. Three match modes: "contains" (default), "startsWith", "regex". ' +
|
|
27
|
+
'\n\nPattern examples:' +
|
|
28
|
+
'\n "Promise<void>" — all functions returning Promise<void>' +
|
|
29
|
+
'\n "async" — all async functions (signature starts with "async")' +
|
|
30
|
+
'\n "(req: Request" — all functions taking a Request parameter' +
|
|
31
|
+
'\n ": string[]" — all functions returning string[]' +
|
|
32
|
+
'\n "@Injectable" — all symbols with Injectable decorator in signature' +
|
|
33
|
+
'\n "export async" — all exported async symbols (startsWith mode)';
|
|
34
|
+
export const inputSchema = {
|
|
35
|
+
repoId: z.string().describe('Repository ID returned by index_folder or list_repos'),
|
|
36
|
+
pattern: z
|
|
37
|
+
.string()
|
|
38
|
+
.describe('Pattern to match against the symbol signature string'),
|
|
39
|
+
mode: z
|
|
40
|
+
.enum(['contains', 'startsWith', 'regex'])
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Match mode: "contains" (default) — signature contains pattern; ' +
|
|
43
|
+
'"startsWith" — signature starts with pattern; ' +
|
|
44
|
+
'"regex" — pattern is a JavaScript-compatible regular expression'),
|
|
45
|
+
kind: z
|
|
46
|
+
.enum([
|
|
47
|
+
'function', 'class', 'method', 'const', 'type', 'interface', 'enum',
|
|
48
|
+
'component', 'composable', 'hook', 'route', 'decorator', 'middleware',
|
|
49
|
+
])
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Filter results to a specific symbol kind'),
|
|
52
|
+
filePath: z
|
|
53
|
+
.string()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Restrict search to a specific file path or directory prefix'),
|
|
56
|
+
limit: z
|
|
57
|
+
.number()
|
|
58
|
+
.int()
|
|
59
|
+
.positive()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe('Maximum number of results to return (default 50)'),
|
|
62
|
+
};
|
|
63
|
+
// ─── Helper: register REGEXP on a db connection ───────────────────────────────
|
|
64
|
+
function registerRegexp(db) {
|
|
65
|
+
// SQLite does not ship with REGEXP — register a JS implementation.
|
|
66
|
+
// The function is invoked by SQLite as: regexp(pattern, value)
|
|
67
|
+
// which corresponds to: value REGEXP pattern
|
|
68
|
+
db.function('regexp', { deterministic: true }, (pattern, value) => {
|
|
69
|
+
try {
|
|
70
|
+
const re = new RegExp(String(pattern));
|
|
71
|
+
return re.test(String(value ?? '')) ? 1 : 0;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// ─── Handler ──────────────────────────────────────────────────────────────────
|
|
79
|
+
export async function handler(args) {
|
|
80
|
+
const t0 = Date.now();
|
|
81
|
+
const mode = args.mode ?? 'contains';
|
|
82
|
+
const limit = args.limit ?? 50;
|
|
83
|
+
// ── Validate regex before touching the DB ─────────────────────────────────
|
|
84
|
+
if (mode === 'regex') {
|
|
85
|
+
try {
|
|
86
|
+
new RegExp(args.pattern);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
return {
|
|
90
|
+
content: [{
|
|
91
|
+
type: 'text',
|
|
92
|
+
text: JSON.stringify({
|
|
93
|
+
error: `Invalid regular expression: ${err.message}`,
|
|
94
|
+
pattern: args.pattern,
|
|
95
|
+
}),
|
|
96
|
+
}],
|
|
97
|
+
isError: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const db = openDatabase(args.repoId);
|
|
102
|
+
try {
|
|
103
|
+
if (mode === 'regex') {
|
|
104
|
+
registerRegexp(db);
|
|
105
|
+
}
|
|
106
|
+
// ── Build query ──────────────────────────────────────────────────────────
|
|
107
|
+
const conditions = ['repo_id = @repoId'];
|
|
108
|
+
const params = { repoId: args.repoId };
|
|
109
|
+
if (mode === 'contains') {
|
|
110
|
+
conditions.push('signature LIKE @sigPattern');
|
|
111
|
+
params['sigPattern'] = `%${args.pattern}%`;
|
|
112
|
+
}
|
|
113
|
+
else if (mode === 'startsWith') {
|
|
114
|
+
conditions.push('signature LIKE @sigPattern');
|
|
115
|
+
params['sigPattern'] = `${args.pattern}%`;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// regex — uses the REGEXP function registered above
|
|
119
|
+
conditions.push('signature REGEXP @sigPattern');
|
|
120
|
+
params['sigPattern'] = args.pattern;
|
|
121
|
+
}
|
|
122
|
+
if (args.kind) {
|
|
123
|
+
conditions.push('kind = @kind');
|
|
124
|
+
params['kind'] = args.kind;
|
|
125
|
+
}
|
|
126
|
+
if (args.filePath) {
|
|
127
|
+
conditions.push('(file_path = @filePath OR file_path LIKE @filePathPrefix)');
|
|
128
|
+
params['filePath'] = args.filePath;
|
|
129
|
+
params['filePathPrefix'] = `${args.filePath}%`;
|
|
130
|
+
}
|
|
131
|
+
const sql = `
|
|
132
|
+
SELECT id, name, kind, file_path, start_byte, signature, summary
|
|
133
|
+
FROM symbols
|
|
134
|
+
WHERE ${conditions.join(' AND ')}
|
|
135
|
+
ORDER BY file_path, start_byte
|
|
136
|
+
LIMIT @limit
|
|
137
|
+
`;
|
|
138
|
+
params['limit'] = limit;
|
|
139
|
+
const rows = db.prepare(sql).all(params);
|
|
140
|
+
// ── Compute startLine approximation from file content ─────────────────────
|
|
141
|
+
// Group symbols by file to batch file reads
|
|
142
|
+
const fileSymbols = new Map();
|
|
143
|
+
for (const row of rows) {
|
|
144
|
+
const list = fileSymbols.get(row.file_path) ?? [];
|
|
145
|
+
list.push(row);
|
|
146
|
+
fileSymbols.set(row.file_path, list);
|
|
147
|
+
}
|
|
148
|
+
const lineMap = new Map(); // id → startLine
|
|
149
|
+
for (const [filePath, syms] of fileSymbols) {
|
|
150
|
+
// Try to get file content for accurate line numbers
|
|
151
|
+
const fileRow = db.prepare('SELECT raw_content FROM files WHERE repo_id = ? AND path = ?').get(args.repoId, filePath);
|
|
152
|
+
if (fileRow?.raw_content) {
|
|
153
|
+
const content = fileRow.raw_content;
|
|
154
|
+
for (const sym of syms) {
|
|
155
|
+
const slice = content.slice(0, Math.min(sym.start_byte, content.length));
|
|
156
|
+
let line = 1;
|
|
157
|
+
for (let i = 0; i < slice.length; i++) {
|
|
158
|
+
if (slice[i] === 0x0a)
|
|
159
|
+
line++;
|
|
160
|
+
}
|
|
161
|
+
lineMap.set(sym.id, line);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Fallback: rough approximation
|
|
166
|
+
for (const sym of syms) {
|
|
167
|
+
lineMap.set(sym.id, Math.max(1, Math.floor(sym.start_byte / 80) + 1));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const symbols = rows.map((row) => ({
|
|
172
|
+
symbolId: row.id,
|
|
173
|
+
name: row.name,
|
|
174
|
+
kind: row.kind,
|
|
175
|
+
filePath: row.file_path,
|
|
176
|
+
startLine: lineMap.get(row.id) ?? 1,
|
|
177
|
+
signature: row.signature,
|
|
178
|
+
summary: row.summary,
|
|
179
|
+
}));
|
|
180
|
+
// ── Token estimate ─────────────────────────────────────────────────────────
|
|
181
|
+
const responseBytes = symbols.reduce((sum, s) => sum + s.signature.length + s.summary.length + s.filePath.length + 50, 0);
|
|
182
|
+
const tokenEstimate = Math.ceil(responseBytes / 4);
|
|
183
|
+
return {
|
|
184
|
+
content: [{
|
|
185
|
+
type: 'text',
|
|
186
|
+
text: JSON.stringify({
|
|
187
|
+
symbols,
|
|
188
|
+
totalFound: symbols.length,
|
|
189
|
+
patternUsed: args.pattern,
|
|
190
|
+
_tokenEstimate: tokenEstimate,
|
|
191
|
+
_meta: buildMeta({ timingMs: Date.now() - t0 }),
|
|
192
|
+
}, null, 2),
|
|
193
|
+
}],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
db.close();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=search-by-signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-by-signature.js","sourceRoot":"","sources":["../../../src/server/tools/search-by-signature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e,r as h,L as O,f as G,b as M,a as $,A as H}from"./index-nX2chMqi.js";import{u as T}from"./useSearch-BnBCRKui.js";function V(t){const r=new Map;for(const n of t.entries)r.set(n.depth,(r.get(n.depth)??0)+1);return r}function q(t){return t===0?"—":t<=3?"Low (~30 min)":t<=10?"Medium (~2 hrs)":t<=30?"High (~1 day)":"Very high (>1 day)"}function I({label:t,value:r,sub:n,color:l="text-gray-100"}){return e.jsxs("div",{className:"bg-gray-800 rounded-lg px-4 py-3 flex flex-col gap-0.5",children:[e.jsx("span",{className:"text-[10px] font-semibold text-gray-500 uppercase tracking-wider",children:t}),e.jsx("span",{className:`text-xl font-bold tabular-nums ${l}`,children:r}),n&&e.jsx("span",{className:"text-xs text-gray-500",children:n})]})}const U={0:"bg-blue-500",1:"bg-red-500",2:"bg-orange-500"};function X(t){return U[t]??"bg-yellow-500"}function Y(t){return t===0?"Source":t===1?"Direct":t===2?"2-hop":`${t}-hop`}function K({data:t}){const r=V(t),n=r.get(1)??0,l=t.totalFiles-1-n,i=Math.max(...t.entries.map(a=>a.depth));return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsx(I,{label:"Files affected",value:t.totalFiles-1,sub:"excluding source",color:"text-red-400"}),e.jsx(I,{label:"Symbols affected",value:t.totalSymbols,color:"text-orange-400"}),e.jsx(I,{label:"Direct impact",value:n,sub:"1-hop files",color:"text-red-300"}),e.jsx(I,{label:"Indirect impact",value:l,sub:"2+ hop files",color:"text-yellow-300"})]}),e.jsxs("div",{className:"bg-gray-800 rounded-lg px-4 py-3 flex items-center justify-between",children:[e.jsx("span",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wider",children:"Estimated review effort"}),e.jsx("span",{className:"text-sm font-medium text-gray-200",children:q(t.totalFiles-1)})]}),i>0&&e.jsxs("div",{className:"bg-gray-800 rounded-lg px-4 py-3 space-y-2",children:[e.jsx("span",{className:"text-[10px] font-semibold text-gray-500 uppercase tracking-wider block",children:"Impact by depth"}),Array.from({length:i+1},(a,p)=>p).filter(a=>a>0).map(a=>{const p=r.get(a)??0,o=Math.max(...Array.from(r.values())),c=o>0?p/o*100:0;return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-gray-500 w-12 shrink-0",children:Y(a)}),e.jsx("div",{className:"flex-1 h-2 bg-gray-700 rounded-full overflow-hidden",children:e.jsx("div",{className:`h-full rounded-full ${X(a)}`,style:{width:`${c}%`}})}),e.jsx("span",{className:"text-xs text-gray-400 tabular-nums w-8 text-right",children:p})]},a)})]})]})}const k=680,j=k/2,v=k/2,Q=18,Z=24,J=[0,130,220,295];function D(t){return J[t]??295+(t-3)*60}function w(t){return t===0?"#3b82f6":t===1?"#ef4444":t===2?"#f97316":"#eab308"}function ee(t){return t===1?"rgba(239,68,68,0.18)":t===2?"rgba(249,115,22,0.18)":"rgba(234,179,8,0.18)"}function B(t){return t===1?"Direct dependents":t===2?"2-hop":`${t}-hop`}const P=28;function te(t){const r=new Map;for(const l of t.entries){const i=r.get(l.depth)??[];i.push(l),r.set(l.depth,i)}const n=[];for(const[l,i]of r){if(l===0){n.push({entry:i[0],x:j,y:v});continue}const a=D(l),p=i.slice(0,P);for(let o=0;o<p.length;o++){const c=2*Math.PI/p.length*o-Math.PI/2;n.push({entry:p[o],x:j+a*Math.cos(c),y:v+a*Math.sin(c)})}}return n}function se({node:t}){const r=t.entry,n=w(r.depth),l=r.depth===0?"Source":B(r.depth);return e.jsx("div",{className:"absolute z-20 pointer-events-none",style:{left:t.x/k*100+"%",top:t.y/k*100+"%",transform:"translate(-50%, -120%)"},children:e.jsxs("div",{className:"bg-gray-900 border border-gray-700 rounded-lg px-3 py-2 shadow-lg min-w-[160px] max-w-[260px]",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full shrink-0",style:{background:n}}),e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-gray-500",children:l})]}),e.jsx("p",{className:"text-xs font-mono text-gray-200 break-all leading-relaxed",children:r.filePath}),e.jsxs("p",{className:"text-[10px] text-gray-500 mt-1",children:[r.symbolCount," symbol",r.symbolCount!==1?"s":""]})]})})}function re({data:t,onNodeClick:r}){const n=te(t),[l,i]=h.useState(null),a=h.useRef(null);h.useEffect(()=>{const s=()=>i(null);return window.addEventListener("click",s),()=>window.removeEventListener("click",s)},[]);const p=h.useCallback((s,u)=>{s.stopPropagation(),r==null||r(u.entry.filePath)},[r]),o=Math.max(...t.entries.map(s=>s.depth)),c=new Map;for(const s of t.entries)c.set(s.depth,(c.get(s.depth)??0)+1);return e.jsxs("div",{className:"relative w-full h-full flex items-center justify-center overflow-hidden",children:[e.jsx("div",{className:"absolute top-3 left-3 z-10 flex flex-col gap-1",children:[{depth:0,label:"Source"},{depth:1,label:"Direct (1-hop)"},{depth:2,label:"2-hop"},{depth:3,label:"3+ hop"}].filter(({depth:s})=>s===0||(c.get(s)??0)>0).map(({depth:s,label:u})=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full shrink-0",style:{background:w(s)}}),e.jsx("span",{className:"text-[10px] text-gray-400",children:u})]},s))}),e.jsxs("svg",{ref:a,viewBox:`0 0 ${k} ${k}`,className:"w-full h-full max-w-[680px] max-h-[680px]","aria-label":"Blast radius radial graph",children:[Array.from({length:o},(s,u)=>u+1).map(s=>e.jsx("circle",{cx:j,cy:v,r:D(s),fill:ee(s),stroke:w(s),strokeWidth:1,strokeDasharray:"4 4",opacity:.5},s)),Array.from({length:o},(s,u)=>u+1).map(s=>{const u=c.get(s)??0;if(u===0)return null;const f=u>P?u-P:0,g=D(s);return e.jsx("g",{children:e.jsxs("text",{x:j,y:v-g+14,textAnchor:"middle",fill:w(s),fontSize:10,opacity:.7,children:[B(s)," (",u,f>0?`, +${f} more`:"",")"]})},s)}),n.filter(s=>s.entry.depth>0).map(s=>{const u=s.entry.depth-1,f=D(u),g=s.x-j,d=s.y-v,m=Math.sqrt(g*g+d*d),y=m===0?j:j+g/m*f,R=m===0?v:v+d/m*f;return e.jsx("line",{x1:y,y1:R,x2:s.x,y2:s.y,stroke:w(s.entry.depth),strokeWidth:1,strokeOpacity:.35},s.entry.filePath)}),n.map(s=>{const u=s.entry.depth===0?Z:Q,f=w(s.entry.depth),g=s.entry.filePath.split("/").pop()??s.entry.filePath,d=g.length>14?g.slice(0,12)+"…":g,m=(l==null?void 0:l.entry.filePath)===s.entry.filePath;return e.jsxs("g",{role:"button",tabIndex:0,"aria-label":`${s.entry.filePath} — ${s.entry.symbolCount} symbols`,style:{cursor:"pointer"},onMouseEnter:()=>i(s),onMouseLeave:()=>i(null),onClick:y=>p(y,s),onKeyDown:y=>{(y.key==="Enter"||y.key===" ")&&(y.preventDefault(),r==null||r(s.entry.filePath))},children:[e.jsx("circle",{cx:s.x,cy:s.y,r:u+(m?3:0),fill:f,fillOpacity:m?.9:.75,stroke:f,strokeWidth:m?2.5:1.5,style:{transition:"r 0.12s, fill-opacity 0.12s"}}),s.entry.depth===0&&e.jsx("text",{x:s.x,y:s.y+4,textAnchor:"middle",fill:"white",fontSize:10,fontWeight:"bold",pointerEvents:"none",children:s.entry.symbolCount}),e.jsx("text",{x:s.x,y:s.y+u+14,textAnchor:"middle",fill:m?"white":"#9ca3af",fontSize:9,pointerEvents:"none",children:d})]},s.entry.filePath)})]}),l&&e.jsx(se,{node:l})]})}function ae(t){return t===0?"text-blue-400":t===1?"text-red-400":t===2?"text-orange-400":"text-yellow-400"}function ne(t){return t===0?"bg-blue-500/20 text-blue-300 border-blue-500/30":t===1?"bg-red-500/20 text-red-300 border-red-500/30":t===2?"bg-orange-500/20 text-orange-300 border-orange-500/30":"bg-yellow-500/20 text-yellow-300 border-yellow-500/30"}function le(t){return t===0?"Source file":t===1?"Direct dependents (1 hop)":t===2?"2-hop dependents":`${t}-hop dependents`}function ie({entry:t,repoId:r}){const[n,l]=h.useState(!1),i=t.symbols.length>0;return e.jsxs("div",{className:"border border-gray-800 rounded-lg overflow-hidden",children:[e.jsxs("button",{type:"button",onClick:()=>l(a=>!a),className:"w-full flex items-center gap-3 px-3 py-2.5 bg-gray-800/50 hover:bg-gray-800 transition-colors text-left","aria-expanded":n,children:[e.jsx("svg",{width:"10",height:"10",viewBox:"0 0 10 10",fill:"none","aria-hidden":"true",className:`shrink-0 transition-transform ${n?"rotate-90":""}`,children:e.jsx("path",{d:"M3 1.5L7 5L3 8.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),e.jsx("code",{className:"flex-1 text-xs font-mono text-gray-200 truncate",children:t.filePath}),e.jsxs("span",{className:"text-[10px] text-gray-500 shrink-0",children:[t.symbolCount," symbol",t.symbolCount!==1?"s":""]})]}),n&&i&&e.jsx("div",{className:"divide-y divide-gray-800",children:t.symbols.map(a=>e.jsxs("div",{className:"px-3 py-2 flex items-start gap-2 hover:bg-gray-800/30 transition-colors",children:[e.jsx("span",{className:"text-[9px] font-semibold uppercase tracking-wider bg-gray-700 text-gray-400 rounded px-1.5 py-0.5 shrink-0 mt-px",children:a.kind}),e.jsxs("div",{className:"flex-1 min-w-0",children:[r?e.jsx(O,{to:`/symbols/${encodeURIComponent(a.id)}?repoId=${encodeURIComponent(r)}`,className:"text-xs font-medium text-blue-400 hover:text-blue-300 transition-colors font-mono",children:a.name}):e.jsx("span",{className:"text-xs font-medium text-gray-300 font-mono",children:a.name}),a.signature&&a.signature!==a.name&&e.jsx("p",{className:"text-[10px] text-gray-500 font-mono truncate mt-0.5",children:a.signature})]})]},a.id))}),n&&!i&&e.jsx("p",{className:"px-4 py-2 text-xs text-gray-600 italic",children:"No symbols indexed in this file."})]})}function oe({depth:t,entries:r,repoId:n}){const[l,i]=h.useState(t<=2);return e.jsxs("div",{children:[e.jsxs("button",{type:"button",onClick:()=>i(a=>!a),className:"flex items-center gap-2 w-full py-2 text-left group","aria-expanded":l,children:[e.jsx("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:`shrink-0 transition-transform text-gray-500 ${l?"rotate-90":""}`,children:e.jsx("path",{d:"M4 2L8 6L4 10",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})}),e.jsx("span",{className:`text-xs font-semibold ${ae(t)}`,children:le(t)}),e.jsx("span",{className:`text-[10px] font-semibold px-1.5 py-0.5 rounded border ${ne(t)}`,children:r.length})]}),l&&e.jsx("div",{className:"pl-4 mt-1 space-y-1.5",children:r.map(a=>e.jsx(ie,{entry:a,repoId:n},a.filePath))})]})}function ce({data:t,repoId:r}){const n=new Map;for(const i of t.entries){const a=n.get(i.depth)??[];a.push(i),n.set(i.depth,a)}const l=Array.from(n.keys()).sort((i,a)=>i-a);return t.entries.length===0?e.jsx("div",{className:"flex items-center justify-center h-32 text-gray-500 text-sm",children:"No dependent files found."}):e.jsx("div",{className:"space-y-2",children:l.map(i=>e.jsx(oe,{depth:i,entries:n.get(i),repoId:r},i))})}function de({repos:t,selectedId:r,onSelect:n}){return e.jsxs("select",{value:r??"",onChange:l=>n(l.target.value),className:"px-3 py-1.5 bg-gray-800 border border-gray-700 rounded text-sm text-gray-100 focus:outline-none focus:border-blue-500","aria-label":"Select repository",children:[!r&&e.jsx("option",{value:"",children:"Select repository…"}),t.map(l=>e.jsx("option",{value:l.repoId,children:l.rootPath.split(/[/\\]/).pop()??l.repoId},l.repoId))]})}function xe({value:t,onChange:r}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-gray-500",children:"Max depth"}),e.jsx("input",{type:"range",min:1,max:6,value:t,onChange:n=>r(Number(n.target.value)),className:"w-24 accent-blue-500","aria-label":"Max depth"}),e.jsx("span",{className:"text-xs font-mono text-gray-300 w-4",children:t})]})}function ue({repoId:t,selectedSymbol:r,onSelect:n}){const l=h.useRef(null),i=T({repoId:t,debounceMs:300}),a=c=>{i.setQuery(c)},p=c=>{n(c),i.clearSearch()},o=i.query.length>0&&i.results.length>0;return e.jsxs("div",{className:"relative",children:[r&&e.jsxs("div",{className:"mb-2 flex items-center gap-2 px-3 py-2 bg-blue-600/10 border border-blue-600/30 rounded-lg",children:[e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-wider bg-blue-600/30 text-blue-300 rounded px-1.5 py-0.5 shrink-0",children:r.kind}),e.jsx("span",{className:"text-sm text-blue-300 font-mono font-medium flex-1 truncate",children:r.name}),e.jsx("button",{type:"button",onClick:()=>n({...r,id:""}),className:"text-gray-500 hover:text-gray-300 transition-colors text-xs","aria-label":"Clear symbol selection",children:"✕"})]}),e.jsxs("div",{className:"relative",children:[e.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-gray-500 pointer-events-none",children:e.jsxs("svg",{width:"13",height:"13",viewBox:"0 0 14 14",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"6",cy:"6",r:"4.5",stroke:"currentColor",strokeWidth:"1.5"}),e.jsx("line",{x1:"9.5",y1:"9.5",x2:"12.5",y2:"12.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]})}),e.jsx("input",{ref:l,type:"search",value:i.query,onChange:c=>a(c.target.value),placeholder:t?"Search for a symbol…":"Select a repo first…",disabled:!t,className:"w-full pl-8 pr-4 py-2 bg-gray-800 border border-gray-700 rounded text-sm text-gray-100 placeholder-gray-500 focus:outline-none focus:border-blue-500 disabled:opacity-40","aria-label":"Search for a symbol to analyze"}),i.loading&&e.jsx("span",{className:"absolute right-3 top-1/2 -translate-y-1/2",children:e.jsx("span",{className:"block w-3 h-3 rounded-full border-2 border-blue-500 border-t-transparent animate-spin"})})]}),o&&e.jsx("div",{className:"absolute z-30 top-full left-0 right-0 mt-1 bg-gray-900 border border-gray-700 rounded-lg shadow-xl max-h-64 overflow-y-auto",children:i.results.slice(0,20).map(c=>e.jsxs("button",{type:"button",onClick:()=>p(c),className:"w-full text-left px-3 py-2.5 flex items-center gap-2 hover:bg-gray-800 transition-colors",children:[e.jsx("span",{className:"text-[9px] font-semibold uppercase tracking-wider bg-gray-700 text-gray-400 rounded px-1.5 py-0.5 shrink-0",children:c.kind}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-xs font-mono text-gray-200 truncate",children:c.name}),e.jsx("p",{className:"text-[10px] text-gray-500 truncate",children:c.filePath})]})]},c.id))})]})}function he({mode:t,onChange:r}){return e.jsx("div",{className:"flex rounded-lg border border-gray-700 overflow-hidden",children:["graph","list"].map(n=>e.jsx("button",{type:"button",onClick:()=>r(n),className:`px-3 py-1.5 text-xs font-medium transition-colors capitalize ${t===n?"bg-blue-600 text-white":"bg-gray-800 text-gray-400 hover:text-gray-200"}`,"aria-pressed":t===n,children:n==="graph"?e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"6",cy:"2",r:"1.5",fill:"currentColor"}),e.jsx("circle",{cx:"2",cy:"9",r:"1.5",fill:"currentColor"}),e.jsx("circle",{cx:"10",cy:"9",r:"1.5",fill:"currentColor"}),e.jsx("line",{x1:"6",y1:"3.5",x2:"2.8",y2:"7.7",stroke:"currentColor",strokeWidth:"1"}),e.jsx("line",{x1:"6",y1:"3.5",x2:"9.2",y2:"7.7",stroke:"currentColor",strokeWidth:"1"})]}),"Graph"]}):e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",children:[e.jsx("rect",{x:"1",y:"2",width:"10",height:"1.5",rx:"0.5",fill:"currentColor"}),e.jsx("rect",{x:"1",y:"5.25",width:"10",height:"1.5",rx:"0.5",fill:"currentColor"}),e.jsx("rect",{x:"1",y:"8.5",width:"7",height:"1.5",rx:"0.5",fill:"currentColor"})]}),"List"]})},n))})}function pe({hasSymbol:t}){return e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-center gap-4 py-16 px-8",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-gray-800 flex items-center justify-center mb-2",children:e.jsxs("svg",{width:"28",height:"28",viewBox:"0 0 28 28",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"14",cy:"14",r:"4",fill:"#3b82f6",opacity:"0.8"}),e.jsx("circle",{cx:"14",cy:"14",r:"8",stroke:"#ef4444",strokeWidth:"1.5",strokeDasharray:"3 3",opacity:"0.5"}),e.jsx("circle",{cx:"14",cy:"14",r:"12",stroke:"#f97316",strokeWidth:"1",strokeDasharray:"3 3",opacity:"0.3"})]})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-gray-300 font-medium mb-1",children:t?"Loading blast radius…":"Select a symbol to analyze"}),e.jsx("p",{className:"text-sm text-gray-500 max-w-xs",children:t?"Traversing the dependency graph…":"Search for a function, class, or type to see which files would be affected if it changed."})]})]})}function ye(){const[t,r]=G(),n=M(x=>x.repos),l=M(x=>x.reposLoaded),i=M(x=>x.setRepos),[a,p]=h.useState(t.get("repoId")??null);h.useEffect(()=>{l||$.listRepos().then(x=>i(x.repos)).catch(()=>{})},[l,i]),h.useEffect(()=>{!a&&n.length>0&&p(n[0].repoId)},[n,a]);const[o,c]=h.useState(null),s=t.get("symbolId"),u=t.get("symbolName"),[f,g]=h.useState(3),[d,m]=h.useState(null),[y,R]=h.useState(!1),[N,C]=h.useState(null),[L,A]=h.useState("graph"),E=h.useCallback(async(x,b,_)=>{R(!0),C(null),m(null);try{const S=await $.getBlastRadius(x,b,_);m(S)}catch(S){C(S instanceof H?S.message:String(S))}finally{R(!1)}},[]);h.useEffect(()=>{if(!a)return;const x=(o==null?void 0:o.id)||s;x&&E(a,x,f)},[a,o,s,f,E]);const F=h.useCallback(x=>{if(!x.id){c(null),m(null),C(null),r(b=>(b.delete("symbolId"),b.delete("symbolName"),b));return}c(x),r(b=>(a&&b.set("repoId",a),b.set("symbolId",x.id),b.set("symbolName",x.name),b))},[a,r]),W=h.useCallback(x=>{p(x),c(null),m(null),C(null)},[]),z=!!(o!=null&&o.id||s);return e.jsxs("div",{className:"h-full flex overflow-hidden",children:[e.jsxs("aside",{className:"w-72 shrink-0 border-r border-gray-800 flex flex-col overflow-hidden bg-gray-950",children:[e.jsx("div",{className:"px-4 py-3 border-b border-gray-800 shrink-0",children:e.jsx("h2",{className:"text-xs font-semibold text-gray-400 uppercase tracking-wider",children:"Blast Radius Analysis"})}),e.jsxs("div",{className:"flex-1 overflow-y-auto p-4 space-y-5",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"block text-[10px] font-semibold text-gray-500 uppercase tracking-wider",children:"Repository"}),e.jsx(de,{repos:n,selectedId:a,onSelect:W})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"block text-[10px] font-semibold text-gray-500 uppercase tracking-wider",children:"Symbol"}),e.jsx(ue,{repoId:a,selectedSymbol:o,onSelect:F})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"block text-[10px] font-semibold text-gray-500 uppercase tracking-wider",children:"Analysis depth"}),e.jsx(xe,{value:f,onChange:g})]}),!o&&s&&u&&e.jsxs("div",{className:"px-3 py-2 bg-blue-600/10 border border-blue-600/30 rounded-lg",children:[e.jsx("p",{className:"text-[10px] text-gray-500 mb-0.5",children:"Analyzing"}),e.jsx("p",{className:"text-xs font-mono text-blue-300 truncate",children:u})]}),d&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{className:"block text-[10px] font-semibold text-gray-500 uppercase tracking-wider",children:"Summary"}),e.jsx(K,{data:d})]})]})]}),e.jsxs("div",{className:"flex-1 flex flex-col overflow-hidden",children:[e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 border-b border-gray-800 shrink-0 bg-gray-900",children:[e.jsx("span",{className:"text-sm font-semibold text-gray-300",children:d?`${d.symbolName} — ${d.totalFiles-1} file${d.totalFiles-1!==1?"s":""} affected`:"Blast Radius"}),e.jsxs("div",{className:"ml-auto flex items-center gap-3",children:[d&&e.jsx(he,{mode:L,onChange:A}),d&&e.jsx("button",{type:"button",onClick:()=>{const x=(o==null?void 0:o.id)||s;a&&x&&E(a,x,f)},className:"px-2 py-1 text-xs bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded text-gray-300 transition-colors",children:"Refresh"})]})]}),e.jsxs("div",{className:"flex-1 overflow-hidden relative",children:[y&&e.jsxs("div",{className:"flex items-center justify-center h-full gap-2 text-gray-500",children:[e.jsx("span",{className:"block w-4 h-4 rounded-full border-2 border-blue-500 border-t-transparent animate-spin"}),e.jsx("span",{className:"text-sm",children:"Analyzing blast radius…"})]}),!y&&N&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsxs("div",{className:"text-center max-w-sm",children:[e.jsx("div",{className:"text-red-400 font-medium mb-1",children:"Analysis failed"}),e.jsx("div",{className:"text-sm text-gray-500",children:N})]})}),!y&&!N&&!d&&e.jsx(pe,{hasSymbol:z}),!y&&!N&&d&&d.totalFiles<=1&&e.jsxs("div",{className:"flex flex-col items-center justify-center h-full text-center gap-3 text-gray-500",children:[e.jsxs("svg",{width:"40",height:"40",viewBox:"0 0 40 40",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"20",cy:"20",r:"8",fill:"#3b82f6",fillOpacity:"0.2",stroke:"#3b82f6",strokeWidth:"1.5"}),e.jsx("text",{x:"20",y:"24",textAnchor:"middle",fill:"#3b82f6",fontSize:"10",fontWeight:"bold",children:"0"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-gray-300 font-medium",children:"No dependents found"}),e.jsxs("p",{className:"text-sm mt-0.5",children:["Nothing imports ",e.jsx("code",{className:"text-blue-400 font-mono",children:d.sourceFile})," within ",f," hop",f!==1?"s":"","."]})]})]}),!y&&!N&&d&&d.totalFiles>1&&L==="graph"&&e.jsx(re,{data:d}),!y&&!N&&d&&d.totalFiles>1&&L==="list"&&e.jsx("div",{className:"h-full overflow-y-auto p-4 scrollbar-thin",children:e.jsx(ce,{data:d,repoId:a})})]})]})]})}export{ye as default};
|