@principal-ai/file-city-react 0.3.0 → 0.4.1

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.
@@ -2,267 +2,110 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSampleCityData = createSampleCityData;
4
4
  exports.createSmallSampleCityData = createSmallSampleCityData;
5
- // Helper function to create sample city data for stories
5
+ const file_city_builder_1 = require("@principal-ai/file-city-builder");
6
+ // Sample file structure representing a typical project
7
+ const sampleFileStructure = [
8
+ // Source files
9
+ { path: 'src/index.ts', size: 1500 },
10
+ { path: 'src/App.tsx', size: 3200 },
11
+ { path: 'src/components/Header.tsx', size: 1800 },
12
+ { path: 'src/components/Footer.tsx', size: 1200 },
13
+ { path: 'src/components/Sidebar.tsx', size: 2100 },
14
+ { path: 'src/components/Card.tsx', size: 900 },
15
+ { path: 'src/components/Button.tsx', size: 600 },
16
+ { path: 'src/utils/helpers.ts', size: 2500 },
17
+ { path: 'src/utils/api.ts', size: 3100 },
18
+ { path: 'src/utils/validators.ts', size: 1400 },
19
+ { path: 'src/hooks/useAuth.ts', size: 800 },
20
+ { path: 'src/hooks/useData.ts', size: 1100 },
21
+ { path: 'src/styles/main.css', size: 4500 },
22
+ { path: 'src/styles/components.css', size: 2800 },
23
+ // Test files
24
+ { path: 'tests/unit/app.test.ts', size: 2200 },
25
+ { path: 'tests/unit/header.test.ts', size: 1600 },
26
+ { path: 'tests/unit/footer.test.tsx', size: 1400 },
27
+ { path: 'tests/integration/api.test.ts', size: 3400 },
28
+ { path: '__tests__/components.test.tsx', size: 2900 },
29
+ { path: '__tests__/utils.test.ts', size: 1900 },
30
+ // Config files
31
+ { path: 'package.json', size: 1200 },
32
+ { path: 'tsconfig.json', size: 800 },
33
+ { path: 'webpack.config.js', size: 2100 },
34
+ { path: '.eslintrc.js', size: 600 },
35
+ { path: '.prettierrc', size: 200 },
36
+ { path: 'README.md', size: 3500 },
37
+ // Documentation
38
+ { path: 'docs/README.md', size: 4200 },
39
+ { path: 'docs/API.md', size: 5100 },
40
+ { path: 'docs/CONTRIBUTING.md', size: 2300 },
41
+ // Build files
42
+ { path: 'dist/bundle.js', size: 45000 },
43
+ { path: 'dist/index.html', size: 800 },
44
+ { path: 'dist/styles.css', size: 12000 },
45
+ // Node modules (sample)
46
+ { path: 'node_modules/react/index.js', size: 8000 },
47
+ { path: 'node_modules/react/package.json', size: 1500 },
48
+ { path: 'node_modules/typescript/lib/typescript.js', size: 65000 },
49
+ { path: 'node_modules/@types/react/index.d.ts', size: 3200 },
50
+ // Deprecated files
51
+ { path: 'src/deprecated/OldComponent.tsx', size: 2400 },
52
+ { path: 'src/deprecated/LegacyAPI.ts', size: 3100 },
53
+ ];
54
+ // Convert file structure to FileInfo objects
55
+ function createFileInfoList(files) {
56
+ return files.map(file => ({
57
+ name: file.path.split('/').pop() || file.path,
58
+ path: file.path,
59
+ relativePath: file.path,
60
+ size: file.size,
61
+ extension: file.path.includes('.') ? '.' + (file.path.split('.').pop() || '') : '',
62
+ lastModified: new Date(),
63
+ isDirectory: false,
64
+ }));
65
+ }
66
+ // Cache the city data to avoid rebuilding on every render
67
+ let cachedCityData = null;
68
+ // Helper function to create sample city data for stories using the real treemap builder
6
69
  function createSampleCityData() {
7
- const buildings = [];
8
- const districts = [];
9
- // Define file structure
10
- const fileStructure = [
11
- // Source files
12
- { path: 'src/index.ts', size: 1500 },
13
- { path: 'src/App.tsx', size: 3200 },
14
- { path: 'src/components/Header.tsx', size: 1800 },
15
- { path: 'src/components/Footer.tsx', size: 1200 },
16
- { path: 'src/components/Sidebar.tsx', size: 2100 },
17
- { path: 'src/components/Card.tsx', size: 900 },
18
- { path: 'src/components/Button.tsx', size: 600 },
19
- { path: 'src/utils/helpers.ts', size: 2500 },
20
- { path: 'src/utils/api.ts', size: 3100 },
21
- { path: 'src/utils/validators.ts', size: 1400 },
22
- { path: 'src/hooks/useAuth.ts', size: 800 },
23
- { path: 'src/hooks/useData.ts', size: 1100 },
24
- { path: 'src/styles/main.css', size: 4500 },
25
- { path: 'src/styles/components.css', size: 2800 },
26
- // Test files
27
- { path: 'tests/unit/app.test.ts', size: 2200 },
28
- { path: 'tests/unit/header.test.ts', size: 1600 },
29
- { path: 'tests/unit/footer.test.tsx', size: 1400 },
30
- { path: 'tests/integration/api.test.ts', size: 3400 },
31
- { path: '__tests__/components.test.tsx', size: 2900 },
32
- { path: '__tests__/utils.test.ts', size: 1900 },
33
- // Config files
34
- { path: 'package.json', size: 1200 },
35
- { path: 'tsconfig.json', size: 800 },
36
- { path: 'webpack.config.js', size: 2100 },
37
- { path: '.eslintrc.js', size: 600 },
38
- { path: '.prettierrc', size: 200 },
39
- { path: 'README.md', size: 3500 },
40
- // Documentation
41
- { path: 'docs/README.md', size: 4200 },
42
- { path: 'docs/API.md', size: 5100 },
43
- { path: 'docs/CONTRIBUTING.md', size: 2300 },
44
- // Build files
45
- { path: 'dist/bundle.js', size: 45000 },
46
- { path: 'dist/index.html', size: 800 },
47
- { path: 'dist/styles.css', size: 12000 },
48
- // Node modules (sample)
49
- { path: 'node_modules/react/index.js', size: 8000 },
50
- { path: 'node_modules/react/package.json', size: 1500 },
51
- { path: 'node_modules/typescript/lib/typescript.js', size: 65000 },
52
- { path: 'node_modules/@types/react/index.d.ts', size: 3200 },
53
- // Deprecated files
54
- { path: 'src/deprecated/OldComponent.tsx', size: 2400 },
55
- { path: 'src/deprecated/LegacyAPI.ts', size: 3100 },
56
- ];
57
- // Create a simple grid layout
58
- let currentX = 0;
59
- let currentZ = 0;
60
- const spacing = 2;
61
- const maxPerRow = 10;
62
- let itemsInRow = 0;
63
- // Group files by directory
64
- const filesByDir = new Map();
65
- fileStructure.forEach(file => {
66
- const dir = file.path.includes('/') ? file.path.substring(0, file.path.lastIndexOf('/')) : '';
67
- if (!filesByDir.has(dir)) {
68
- filesByDir.set(dir, []);
69
- }
70
- const dirFiles = filesByDir.get(dir);
71
- if (dirFiles) {
72
- dirFiles.push(file);
73
- }
74
- });
75
- // Track district bounds
76
- const districtBounds = new Map();
77
- // Process each directory group
78
- const sortedDirs = Array.from(filesByDir.keys()).sort();
79
- let districtStartX = 0;
80
- sortedDirs.forEach(dir => {
81
- const files = filesByDir.get(dir);
82
- if (!files)
83
- return;
84
- const districtMinX = currentX;
85
- const districtMinZ = currentZ;
86
- files.forEach(file => {
87
- const extension = file.path.includes('.') ? '.' + (file.path.split('.').pop() || '') : '';
88
- // Calculate building dimensions based on file size
89
- const height = Math.log(file.size + 1) * 2;
90
- const width = Math.sqrt(file.size) / 10;
91
- const depth = width;
92
- buildings.push({
93
- path: file.path,
94
- position: {
95
- x: currentX + width / 2,
96
- y: height / 2,
97
- z: currentZ + depth / 2,
98
- },
99
- dimensions: [width, height, depth],
100
- type: 'file',
101
- fileExtension: extension,
102
- size: file.size,
103
- lastModified: new Date(),
104
- });
105
- // Update position for next building
106
- currentX += width + spacing;
107
- itemsInRow++;
108
- if (itemsInRow >= maxPerRow) {
109
- currentX = districtStartX;
110
- currentZ += depth + spacing;
111
- itemsInRow = 0;
112
- }
113
- });
114
- // Create district bounds
115
- if (dir) {
116
- const districtMaxX = currentX > districtMinX ? currentX : districtMinX + 10;
117
- const districtMaxZ = currentZ > districtMinZ ? currentZ + 5 : districtMinZ + 10;
118
- districtBounds.set(dir, {
119
- minX: districtMinX - 1,
120
- maxX: districtMaxX + 1,
121
- minZ: districtMinZ - 1,
122
- maxZ: districtMaxZ + 1,
123
- });
124
- // Move to next district area
125
- currentX = districtMaxX + spacing * 3;
126
- if (currentX > 100) {
127
- currentX = 0;
128
- currentZ = districtMaxZ + spacing * 3;
129
- }
130
- districtStartX = currentX;
131
- itemsInRow = 0;
132
- }
133
- });
134
- // Create districts from bounds
135
- const allPaths = new Set(districtBounds.keys());
136
- const processedPaths = new Set();
137
- // Helper to create all parent paths
138
- const getParentPaths = (path) => {
139
- const parts = path.split('/');
140
- const parents = [];
141
- for (let i = 1; i < parts.length; i++) {
142
- parents.push(parts.slice(0, i).join('/'));
143
- }
144
- return parents;
145
- };
146
- // Add all parent paths to the set
147
- allPaths.forEach(path => {
148
- getParentPaths(path).forEach(parent => allPaths.add(parent));
70
+ if (cachedCityData) {
71
+ return cachedCityData;
72
+ }
73
+ const fileInfos = createFileInfoList(sampleFileStructure);
74
+ const fileTree = (0, file_city_builder_1.buildFileSystemTreeFromFileInfoList)(fileInfos, 'sample-project');
75
+ const builder = new file_city_builder_1.CodeCityBuilderWithGrid();
76
+ cachedCityData = builder.buildCityFromFileSystem(fileTree, '', {
77
+ paddingTop: 2,
78
+ paddingBottom: 2,
79
+ paddingLeft: 2,
80
+ paddingRight: 2,
81
+ paddingInner: 1,
82
+ paddingOuter: 3,
149
83
  });
150
- // Create districts for all paths
151
- allPaths.forEach(path => {
152
- if (processedPaths.has(path))
153
- return;
154
- // Find all children of this path
155
- const children = Array.from(districtBounds.keys()).filter(p => p.startsWith(path + '/') && !p.slice(path.length + 1).includes('/'));
156
- let bounds;
157
- if (districtBounds.has(path)) {
158
- const pathBounds = districtBounds.get(path);
159
- if (!pathBounds)
160
- return;
161
- bounds = pathBounds;
162
- }
163
- else if (children.length > 0) {
164
- // Calculate bounds from children
165
- const childBounds = children
166
- .map(c => districtBounds.get(c))
167
- .filter((b) => b !== undefined);
168
- if (childBounds.length === 0)
169
- return;
170
- bounds = {
171
- minX: Math.min(...childBounds.map(c => c.minX)),
172
- maxX: Math.max(...childBounds.map(c => c.maxX)),
173
- minZ: Math.min(...childBounds.map(c => c.minZ)),
174
- maxZ: Math.max(...childBounds.map(c => c.maxZ)),
175
- };
176
- }
177
- else {
178
- return; // Skip if no bounds
179
- }
180
- const fileCount = buildings.filter(b => b.path === path || b.path.startsWith(path + '/')).length;
181
- districts.push({
182
- path,
183
- worldBounds: bounds,
184
- fileCount,
185
- type: 'directory',
186
- });
187
- processedPaths.add(path);
188
- });
189
- // Calculate overall bounds
190
- const allX = buildings.map(b => b.position.x);
191
- const allZ = buildings.map(b => b.position.z);
192
- const bounds = {
193
- minX: Math.min(...allX) - 5,
194
- maxX: Math.max(...allX) + 5,
195
- minZ: Math.min(...allZ) - 5,
196
- maxZ: Math.max(...allZ) + 5,
197
- };
198
- return {
199
- buildings,
200
- districts,
201
- bounds,
202
- metadata: {
203
- totalFiles: buildings.length,
204
- totalDirectories: districts.length,
205
- analyzedAt: new Date(),
206
- rootPath: '/',
207
- layoutConfig: {
208
- paddingTop: 2,
209
- paddingBottom: 2,
210
- paddingLeft: 2,
211
- paddingRight: 2,
212
- paddingInner: 1,
213
- paddingOuter: 3,
214
- },
215
- },
216
- };
84
+ return cachedCityData;
217
85
  }
86
+ // Smaller sample file structure
87
+ const smallFileStructure = [
88
+ { path: 'src/index.ts', size: 1500 },
89
+ { path: 'src/App.tsx', size: 3200 },
90
+ { path: 'src/utils/helpers.ts', size: 800 },
91
+ { path: 'package.json', size: 1200 },
92
+ ];
93
+ let cachedSmallCityData = null;
218
94
  // Create a smaller sample for performance testing
219
95
  function createSmallSampleCityData() {
220
- const buildings = [
221
- {
222
- path: 'index.ts',
223
- position: { x: 5, y: 3, z: 5 },
224
- dimensions: [4, 6, 4],
225
- type: 'file',
226
- fileExtension: '.ts',
227
- size: 1500,
228
- lastModified: new Date(),
229
- },
230
- {
231
- path: 'App.tsx',
232
- position: { x: 12, y: 4, z: 5 },
233
- dimensions: [5, 8, 5],
234
- type: 'file',
235
- fileExtension: '.tsx',
236
- size: 3200,
237
- lastModified: new Date(),
238
- },
239
- {
240
- path: 'utils/helpers.ts',
241
- position: { x: 5, y: 2.5, z: 15 },
242
- dimensions: [3, 5, 3],
243
- type: 'file',
244
- fileExtension: '.ts',
245
- size: 800,
246
- lastModified: new Date(),
247
- },
248
- ];
249
- const districts = [
250
- {
251
- path: 'utils',
252
- worldBounds: { minX: 2, maxX: 10, minZ: 12, maxZ: 20 },
253
- fileCount: 1,
254
- type: 'directory',
255
- },
256
- ];
257
- return {
258
- buildings,
259
- districts,
260
- bounds: { minX: 0, maxX: 20, minZ: 0, maxZ: 25 },
261
- metadata: {
262
- totalFiles: buildings.length,
263
- totalDirectories: districts.length,
264
- analyzedAt: new Date(),
265
- rootPath: '/',
266
- },
267
- };
96
+ if (cachedSmallCityData) {
97
+ return cachedSmallCityData;
98
+ }
99
+ const fileInfos = createFileInfoList(smallFileStructure);
100
+ const fileTree = (0, file_city_builder_1.buildFileSystemTreeFromFileInfoList)(fileInfos, 'small-sample');
101
+ const builder = new file_city_builder_1.CodeCityBuilderWithGrid();
102
+ cachedSmallCityData = builder.buildCityFromFileSystem(fileTree, '', {
103
+ paddingTop: 2,
104
+ paddingBottom: 2,
105
+ paddingLeft: 2,
106
+ paddingRight: 2,
107
+ paddingInner: 1,
108
+ paddingOuter: 3,
109
+ });
110
+ return cachedSmallCityData;
268
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principal-ai/file-city-react",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "React components for File City visualization",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -21,17 +21,13 @@
21
21
  "react": "^19.0.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@storybook/addon-essentials": "^7.6.0",
25
- "@storybook/addon-interactions": "^7.6.0",
26
- "@storybook/addon-links": "^7.6.0",
27
- "@storybook/blocks": "^7.6.0",
28
- "@storybook/react": "^7.6.0",
29
- "@storybook/react-vite": "^7.6.0",
30
- "@storybook/test": "^7.6.0",
31
- "@types/react": "^18.0.0",
24
+ "@storybook/addon-docs": "^10.1.2",
25
+ "@storybook/addon-links": "^10.1.2",
26
+ "@storybook/react-vite": "^10.1.2",
27
+ "@types/react": "^19.0.0",
32
28
  "react": "^19.1.1",
33
29
  "react-dom": "^19.1.1",
34
- "storybook": "^7.6.0",
30
+ "storybook": "^10.1.2",
35
31
  "typescript": "^5.0.0",
36
32
  "vite": "^5.0.0"
37
33
  },