@principal-ai/file-city-react 0.5.6 → 0.5.7

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.
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /**
3
3
  * FileCity3D - 3D visualization of a codebase using React Three Fiber
4
4
  *
@@ -7,49 +7,13 @@
7
7
  *
8
8
  * Supports animated transition from 2D (flat) to 3D (grown buildings).
9
9
  */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.resetCamera = resetCamera;
45
- exports.FileCity3D = FileCity3D;
46
- const react_1 = __importStar(require("react"));
47
- const fiber_1 = require("@react-three/fiber");
48
- const industry_theme_1 = require("@principal-ade/industry-theme");
49
- const three_1 = require("@react-spring/three");
50
- const drei_1 = require("@react-three/drei");
51
- const file_city_builder_1 = require("@principal-ai/file-city-builder");
52
- const THREE = __importStar(require("three"));
10
+ import { useMemo, useRef, useState, useEffect, useCallback, } from 'react';
11
+ import { Canvas, useFrame, useThree } from '@react-three/fiber';
12
+ import { useTheme } from '@principal-ade/industry-theme';
13
+ import { animated } from '@react-spring/three';
14
+ import { OrbitControls, PerspectiveCamera, Text, RoundedBox, } from '@react-three/drei';
15
+ import { getFileConfig } from '@principal-ai/file-city-builder';
16
+ import * as THREE from 'three';
53
17
  const DEFAULT_ANIMATION = {
54
18
  startFlat: false,
55
19
  autoStartDelay: 500,
@@ -142,7 +106,7 @@ function getConfigForFile(building) {
142
106
  matchType: 'filename',
143
107
  };
144
108
  }
145
- return (0, file_city_builder_1.getFileConfig)(building.path);
109
+ return getFileConfig(building.path);
146
110
  }
147
111
  function getColorForFile(building) {
148
112
  return getConfigForFile(building).color;
@@ -170,14 +134,14 @@ function hasActiveHighlights(layers) {
170
134
  return layers.some((layer) => layer.enabled && layer.items.length > 0);
171
135
  }
172
136
  // Animated RoundedBox wrapper
173
- const AnimatedRoundedBox = (0, three_1.animated)(drei_1.RoundedBox);
137
+ const AnimatedRoundedBox = animated(RoundedBox);
174
138
  function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hoveredIndex, growProgress, animationConfig, highlightLayers, isolationMode, hasActiveHighlights, dimOpacity, heightScaling, linearScale, staggerIndices, }) {
175
- const meshRef = (0, react_1.useRef)(null);
176
- const startTimeRef = (0, react_1.useRef)(null);
177
- const tempObject = (0, react_1.useMemo)(() => new THREE.Object3D(), []);
178
- const tempColor = (0, react_1.useMemo)(() => new THREE.Color(), []);
139
+ const meshRef = useRef(null);
140
+ const startTimeRef = useRef(null);
141
+ const tempObject = useMemo(() => new THREE.Object3D(), []);
142
+ const tempColor = useMemo(() => new THREE.Color(), []);
179
143
  // Pre-compute building data
180
- const buildingData = (0, react_1.useMemo)(() => {
144
+ const buildingData = useMemo(() => {
181
145
  return buildings.map((building, index) => {
182
146
  const [width, , depth] = building.dimensions;
183
147
  const highlight = getHighlightForPath(building.path, highlightLayers);
@@ -219,13 +183,13 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
219
183
  staggerIndices,
220
184
  animationConfig.staggerDelay,
221
185
  ]);
222
- const visibleBuildings = (0, react_1.useMemo)(() => buildingData.filter((b) => !b.shouldHide), [buildingData]);
186
+ const visibleBuildings = useMemo(() => buildingData.filter((b) => !b.shouldHide), [buildingData]);
223
187
  const minHeight = 0.3;
224
188
  const baseOffset = 0.2;
225
189
  const tension = animationConfig.tension || 120;
226
190
  const friction = animationConfig.friction || 14;
227
191
  const springDuration = Math.sqrt(1 / (tension * 0.001)) * friction * 20;
228
- (0, react_1.useEffect)(() => {
192
+ useEffect(() => {
229
193
  if (!meshRef.current)
230
194
  return;
231
195
  visibleBuildings.forEach((data, instanceIndex) => {
@@ -251,7 +215,7 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
251
215
  minHeight,
252
216
  baseOffset,
253
217
  ]);
254
- (0, fiber_1.useFrame)(({ clock }) => {
218
+ useFrame(({ clock }) => {
255
219
  if (!meshRef.current)
256
220
  return;
257
221
  if (startTimeRef.current === null && growProgress > 0) {
@@ -294,7 +258,7 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
294
258
  meshRef.current.instanceColor.needsUpdate = true;
295
259
  }
296
260
  });
297
- const handlePointerMove = (0, react_1.useCallback)((e) => {
261
+ const handlePointerMove = useCallback((e) => {
298
262
  e.stopPropagation();
299
263
  if (e.instanceId !== undefined &&
300
264
  e.instanceId < visibleBuildings.length) {
@@ -302,10 +266,10 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
302
266
  onHover?.(data.building);
303
267
  }
304
268
  }, [visibleBuildings, onHover]);
305
- const handlePointerOut = (0, react_1.useCallback)(() => {
269
+ const handlePointerOut = useCallback(() => {
306
270
  onHover?.(null);
307
271
  }, [onHover]);
308
- const handleClick = (0, react_1.useCallback)((e) => {
272
+ const handleClick = useCallback((e) => {
309
273
  e.stopPropagation();
310
274
  if (e.instanceId !== undefined &&
311
275
  e.instanceId < visibleBuildings.length) {
@@ -315,9 +279,7 @@ function InstancedBuildings({ buildings, centerOffset, onHover, onClick, hovered
315
279
  }, [visibleBuildings, onClick]);
316
280
  if (visibleBuildings.length === 0)
317
281
  return null;
318
- return (react_1.default.createElement("instancedMesh", { ref: meshRef, args: [undefined, undefined, visibleBuildings.length], onPointerMove: handlePointerMove, onPointerOut: handlePointerOut, onClick: handleClick, frustumCulled: false },
319
- react_1.default.createElement("boxGeometry", { args: [1, 1, 1] }),
320
- react_1.default.createElement("meshStandardMaterial", { metalness: 0.1, roughness: 0.35 })));
282
+ return (_jsxs("instancedMesh", { ref: meshRef, args: [undefined, undefined, visibleBuildings.length], onPointerMove: handlePointerMove, onPointerOut: handlePointerOut, onClick: handleClick, frustumCulled: false, children: [_jsx("boxGeometry", { args: [1, 1, 1] }), _jsx("meshStandardMaterial", { metalness: 0.1, roughness: 0.35 })] }));
321
283
  }
322
284
  function DistrictFloor({ district, centerOffset, opacity, }) {
323
285
  const { worldBounds } = district;
@@ -328,21 +290,17 @@ function DistrictFloor({ district, centerOffset, opacity, }) {
328
290
  const dirName = district.path.split('/').pop() || district.path;
329
291
  const pathDepth = district.path.split('/').length;
330
292
  const floorY = -5 - pathDepth * 0.1;
331
- return (react_1.default.createElement("group", { position: [centerX, 0, centerZ] },
332
- react_1.default.createElement("lineSegments", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY, 0], renderOrder: -1 },
333
- react_1.default.createElement("edgesGeometry", { args: [new THREE.PlaneGeometry(width, depth)], attach: "geometry" }),
334
- react_1.default.createElement("lineBasicMaterial", { color: "#475569", depthWrite: false })),
335
- district.label && (react_1.default.createElement(drei_1.Text, { position: [0, 1.5, depth / 2 + 2], rotation: [-Math.PI / 6, 0, 0], fontSize: Math.min(3, width / 6), color: "#cbd5e1", anchorX: "center", anchorY: "middle", outlineWidth: 0.1, outlineColor: "#0f172a" }, dirName))));
293
+ return (_jsxs("group", { position: [centerX, 0, centerZ], children: [_jsxs("lineSegments", { rotation: [-Math.PI / 2, 0, 0], position: [0, floorY, 0], renderOrder: -1, children: [_jsx("edgesGeometry", { args: [new THREE.PlaneGeometry(width, depth)], attach: "geometry" }), _jsx("lineBasicMaterial", { color: "#475569", depthWrite: false })] }), district.label && (_jsx(Text, { position: [0, 1.5, depth / 2 + 2], rotation: [-Math.PI / 6, 0, 0], fontSize: Math.min(3, width / 6), color: "#cbd5e1", anchorX: "center", anchorY: "middle", outlineWidth: 0.1, outlineColor: "#0f172a", children: dirName }))] }));
336
294
  }
337
295
  let cameraResetFn = null;
338
- function resetCamera() {
296
+ export function resetCamera() {
339
297
  cameraResetFn?.();
340
298
  }
341
299
  function AnimatedCamera({ citySize, isFlat }) {
342
- const { camera } = (0, fiber_1.useThree)();
300
+ const { camera } = useThree();
343
301
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
344
- const controlsRef = (0, react_1.useRef)(null);
345
- const resetToInitial = (0, react_1.useCallback)(() => {
302
+ const controlsRef = useRef(null);
303
+ const resetToInitial = useCallback(() => {
346
304
  const targetHeight = isFlat ? citySize * 1.5 : citySize * 1.1;
347
305
  const targetZ = isFlat ? 0 : citySize * 1.3;
348
306
  camera.position.set(0, targetHeight, targetZ);
@@ -352,18 +310,16 @@ function AnimatedCamera({ citySize, isFlat }) {
352
310
  controlsRef.current.update();
353
311
  }
354
312
  }, [isFlat, citySize, camera]);
355
- (0, react_1.useEffect)(() => {
313
+ useEffect(() => {
356
314
  resetToInitial();
357
315
  }, [resetToInitial]);
358
- (0, react_1.useEffect)(() => {
316
+ useEffect(() => {
359
317
  cameraResetFn = resetToInitial;
360
318
  return () => {
361
319
  cameraResetFn = null;
362
320
  };
363
321
  }, [resetToInitial]);
364
- return (react_1.default.createElement(react_1.default.Fragment, null,
365
- react_1.default.createElement(drei_1.PerspectiveCamera, { makeDefault: true, fov: 50, near: 1, far: citySize * 10 }),
366
- react_1.default.createElement(drei_1.OrbitControls, { ref: controlsRef, enableDamping: true, dampingFactor: 0.05, minDistance: 10, maxDistance: citySize * 3, maxPolarAngle: Math.PI / 2.1 })));
322
+ return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { makeDefault: true, fov: 50, near: 1, far: citySize * 10 }), _jsx(OrbitControls, { ref: controlsRef, enableDamping: true, dampingFactor: 0.05, minDistance: 10, maxDistance: citySize * 3, maxPolarAngle: Math.PI / 2.1 })] }));
367
323
  }
368
324
  function InfoPanel({ building }) {
369
325
  if (!building)
@@ -373,7 +329,7 @@ function InfoPanel({ building }) {
373
329
  const rawExt = building.fileExtension || building.path.split('.').pop() || '';
374
330
  const ext = rawExt.replace(/^\./, '');
375
331
  const isCode = isCodeFile(ext);
376
- return (react_1.default.createElement("div", { style: {
332
+ return (_jsxs("div", { style: {
377
333
  position: 'absolute',
378
334
  bottom: 16,
379
335
  left: 16,
@@ -386,22 +342,13 @@ function InfoPanel({ building }) {
386
342
  fontFamily: 'monospace',
387
343
  maxWidth: 400,
388
344
  pointerEvents: 'none',
389
- } },
390
- react_1.default.createElement("div", { style: { fontWeight: 600, marginBottom: 4 } }, fileName),
391
- react_1.default.createElement("div", { style: { color: '#94a3b8', fontSize: 12 } }, dirPath),
392
- react_1.default.createElement("div", { style: {
393
- color: '#64748b',
394
- fontSize: 11,
395
- marginTop: 4,
396
- display: 'flex',
397
- gap: 12,
398
- } },
399
- building.lineCount !== undefined && (react_1.default.createElement("span", null,
400
- building.lineCount.toLocaleString(),
401
- " lines")),
402
- building.size !== undefined && (react_1.default.createElement("span", null,
403
- (building.size / 1024).toFixed(1),
404
- " KB")))));
345
+ }, children: [_jsx("div", { style: { fontWeight: 600, marginBottom: 4 }, children: fileName }), _jsx("div", { style: { color: '#94a3b8', fontSize: 12 }, children: dirPath }), _jsxs("div", { style: {
346
+ color: '#64748b',
347
+ fontSize: 11,
348
+ marginTop: 4,
349
+ display: 'flex',
350
+ gap: 12,
351
+ }, children: [building.lineCount !== undefined && (_jsxs("span", { children: [building.lineCount.toLocaleString(), " lines"] })), building.size !== undefined && (_jsxs("span", { children: [(building.size / 1024).toFixed(1), " KB"] }))] })] }));
405
352
  }
406
353
  function ControlsOverlay({ isFlat, onToggle, onResetCamera, }) {
407
354
  const buttonStyle = {
@@ -416,24 +363,22 @@ function ControlsOverlay({ isFlat, onToggle, onResetCamera, }) {
416
363
  alignItems: 'center',
417
364
  gap: 6,
418
365
  };
419
- return (react_1.default.createElement("div", { style: {
366
+ return (_jsxs("div", { style: {
420
367
  position: 'absolute',
421
368
  top: 16,
422
369
  right: 16,
423
370
  display: 'flex',
424
371
  gap: 8,
425
- } },
426
- react_1.default.createElement("button", { onClick: onResetCamera, style: buttonStyle }, "Reset View"),
427
- react_1.default.createElement("button", { onClick: onToggle, style: buttonStyle }, isFlat ? 'Grow to 3D' : 'Flatten to 2D')));
372
+ }, children: [_jsx("button", { onClick: onResetCamera, style: buttonStyle, children: "Reset View" }), _jsx("button", { onClick: onToggle, style: buttonStyle, children: isFlat ? 'Grow to 3D' : 'Flatten to 2D' })] }));
428
373
  }
429
374
  function CityScene({ cityData, onBuildingHover, onBuildingClick, hoveredBuilding, growProgress, animationConfig, highlightLayers, isolationMode, dimOpacity, heightScaling, linearScale, }) {
430
- const centerOffset = (0, react_1.useMemo)(() => ({
375
+ const centerOffset = useMemo(() => ({
431
376
  x: (cityData.bounds.minX + cityData.bounds.maxX) / 2,
432
377
  z: (cityData.bounds.minZ + cityData.bounds.maxZ) / 2,
433
378
  }), [cityData.bounds]);
434
379
  const citySize = Math.max(cityData.bounds.maxX - cityData.bounds.minX, cityData.bounds.maxZ - cityData.bounds.minZ);
435
- const activeHighlights = (0, react_1.useMemo)(() => hasActiveHighlights(highlightLayers), [highlightLayers]);
436
- const staggerIndices = (0, react_1.useMemo)(() => {
380
+ const activeHighlights = useMemo(() => hasActiveHighlights(highlightLayers), [highlightLayers]);
381
+ const staggerIndices = useMemo(() => {
437
382
  const centerX = (cityData.bounds.minX + cityData.bounds.maxX) / 2;
438
383
  const centerZ = (cityData.bounds.minZ + cityData.bounds.maxZ) / 2;
439
384
  const withDistance = cityData.buildings.map((b, originalIndex) => ({
@@ -448,18 +393,12 @@ function CityScene({ cityData, onBuildingHover, onBuildingClick, hoveredBuilding
448
393
  });
449
394
  return indices;
450
395
  }, [cityData.buildings, cityData.bounds]);
451
- const hoveredIndex = (0, react_1.useMemo)(() => {
396
+ const hoveredIndex = useMemo(() => {
452
397
  if (!hoveredBuilding)
453
398
  return null;
454
399
  return cityData.buildings.findIndex((b) => b.path === hoveredBuilding.path);
455
400
  }, [hoveredBuilding, cityData.buildings]);
456
- return (react_1.default.createElement(react_1.default.Fragment, null,
457
- react_1.default.createElement(AnimatedCamera, { citySize: citySize, isFlat: growProgress === 0 }),
458
- react_1.default.createElement("ambientLight", { intensity: 0.4 }),
459
- react_1.default.createElement("directionalLight", { position: [citySize, citySize, citySize * 0.5], intensity: 1, castShadow: true, "shadow-mapSize": [2048, 2048] }),
460
- react_1.default.createElement("directionalLight", { position: [-citySize * 0.5, citySize * 0.5, -citySize * 0.5], intensity: 0.3 }),
461
- cityData.districts.map((district) => (react_1.default.createElement(DistrictFloor, { key: district.path, district: district, centerOffset: centerOffset, opacity: 1 }))),
462
- react_1.default.createElement(InstancedBuildings, { buildings: cityData.buildings, centerOffset: centerOffset, onHover: onBuildingHover, onClick: onBuildingClick, hoveredIndex: hoveredIndex, growProgress: growProgress, animationConfig: animationConfig, highlightLayers: highlightLayers, isolationMode: isolationMode, hasActiveHighlights: activeHighlights, dimOpacity: dimOpacity, heightScaling: heightScaling, linearScale: linearScale, staggerIndices: staggerIndices })));
401
+ return (_jsxs(_Fragment, { children: [_jsx(AnimatedCamera, { citySize: citySize, isFlat: growProgress === 0 }), _jsx("ambientLight", { intensity: 0.4 }), _jsx("directionalLight", { position: [citySize, citySize, citySize * 0.5], intensity: 1, castShadow: true, "shadow-mapSize": [2048, 2048] }), _jsx("directionalLight", { position: [-citySize * 0.5, citySize * 0.5, -citySize * 0.5], intensity: 0.3 }), cityData.districts.map((district) => (_jsx(DistrictFloor, { district: district, centerOffset: centerOffset, opacity: 1 }, district.path))), _jsx(InstancedBuildings, { buildings: cityData.buildings, centerOffset: centerOffset, onHover: onBuildingHover, onClick: onBuildingClick, hoveredIndex: hoveredIndex, growProgress: growProgress, animationConfig: animationConfig, highlightLayers: highlightLayers, isolationMode: isolationMode, hasActiveHighlights: activeHighlights, dimOpacity: dimOpacity, heightScaling: heightScaling, linearScale: linearScale, staggerIndices: staggerIndices })] }));
463
402
  }
464
403
  /**
465
404
  * FileCity3D - 3D visualization of codebase structure
@@ -467,17 +406,17 @@ function CityScene({ cityData, onBuildingHover, onBuildingClick, hoveredBuilding
467
406
  * Renders CityData as an interactive 3D city where buildings represent files
468
407
  * and their height corresponds to line count or file size.
469
408
  */
470
- function FileCity3D({ cityData, width = '100%', height = 600, onBuildingClick, className, style, animation, isGrown: externalIsGrown, onGrowChange, showControls = true, highlightLayers = [], isolationMode = 'transparent', dimOpacity = 0.15, isLoading = false, loadingMessage = 'Loading file city...', emptyMessage = 'No file tree data available', heightScaling = 'logarithmic', linearScale = 0.05, }) {
471
- const { theme } = (0, industry_theme_1.useTheme)();
472
- const [hoveredBuilding, setHoveredBuilding] = (0, react_1.useState)(null);
473
- const [internalIsGrown, setInternalIsGrown] = (0, react_1.useState)(false);
474
- const animationConfig = (0, react_1.useMemo)(() => ({ ...DEFAULT_ANIMATION, ...animation }), [animation]);
409
+ export function FileCity3D({ cityData, width = '100%', height = 600, onBuildingClick, className, style, animation, isGrown: externalIsGrown, onGrowChange, showControls = true, highlightLayers = [], isolationMode = 'transparent', dimOpacity = 0.15, isLoading = false, loadingMessage = 'Loading file city...', emptyMessage = 'No file tree data available', heightScaling = 'logarithmic', linearScale = 0.05, }) {
410
+ const { theme } = useTheme();
411
+ const [hoveredBuilding, setHoveredBuilding] = useState(null);
412
+ const [internalIsGrown, setInternalIsGrown] = useState(false);
413
+ const animationConfig = useMemo(() => ({ ...DEFAULT_ANIMATION, ...animation }), [animation]);
475
414
  const isGrown = externalIsGrown !== undefined ? externalIsGrown : internalIsGrown;
476
415
  const setIsGrown = (value) => {
477
416
  setInternalIsGrown(value);
478
417
  onGrowChange?.(value);
479
418
  };
480
- (0, react_1.useEffect)(() => {
419
+ useEffect(() => {
481
420
  if (animationConfig.startFlat && animationConfig.autoStartDelay !== null) {
482
421
  const timer = setTimeout(() => {
483
422
  setIsGrown(true);
@@ -494,7 +433,7 @@ function FileCity3D({ cityData, width = '100%', height = 600, onBuildingClick, c
494
433
  setIsGrown(!isGrown);
495
434
  };
496
435
  if (isLoading) {
497
- return (react_1.default.createElement("div", { className: className, style: {
436
+ return (_jsx("div", { className: className, style: {
498
437
  width,
499
438
  height,
500
439
  position: 'relative',
@@ -507,10 +446,10 @@ function FileCity3D({ cityData, width = '100%', height = 600, onBuildingClick, c
507
446
  fontFamily: 'system-ui, sans-serif',
508
447
  fontSize: 14,
509
448
  ...style,
510
- } }, loadingMessage));
449
+ }, children: loadingMessage }));
511
450
  }
512
451
  if (!cityData || cityData.buildings.length === 0) {
513
- return (react_1.default.createElement("div", { className: className, style: {
452
+ return (_jsx("div", { className: className, style: {
514
453
  width,
515
454
  height,
516
455
  position: 'relative',
@@ -523,25 +462,21 @@ function FileCity3D({ cityData, width = '100%', height = 600, onBuildingClick, c
523
462
  fontFamily: 'system-ui, sans-serif',
524
463
  fontSize: 14,
525
464
  ...style,
526
- } }, emptyMessage));
465
+ }, children: emptyMessage }));
527
466
  }
528
- return (react_1.default.createElement("div", { className: className, style: {
467
+ return (_jsxs("div", { className: className, style: {
529
468
  width,
530
469
  height,
531
470
  position: 'relative',
532
471
  background: theme.colors.background,
533
472
  overflow: 'hidden',
534
473
  ...style,
535
- } },
536
- react_1.default.createElement(fiber_1.Canvas, { shadows: true, style: {
537
- position: 'absolute',
538
- top: 0,
539
- left: 0,
540
- width: '100%',
541
- height: '100%',
542
- } },
543
- react_1.default.createElement(CityScene, { cityData: cityData, onBuildingHover: setHoveredBuilding, onBuildingClick: onBuildingClick, hoveredBuilding: hoveredBuilding, growProgress: growProgress, animationConfig: animationConfig, highlightLayers: highlightLayers, isolationMode: isolationMode, dimOpacity: dimOpacity, heightScaling: heightScaling, linearScale: linearScale })),
544
- react_1.default.createElement(InfoPanel, { building: hoveredBuilding }),
545
- showControls && (react_1.default.createElement(ControlsOverlay, { isFlat: !isGrown, onToggle: handleToggle, onResetCamera: resetCamera }))));
474
+ }, children: [_jsx(Canvas, { shadows: true, style: {
475
+ position: 'absolute',
476
+ top: 0,
477
+ left: 0,
478
+ width: '100%',
479
+ height: '100%',
480
+ }, children: _jsx(CityScene, { cityData: cityData, onBuildingHover: setHoveredBuilding, onBuildingClick: onBuildingClick, hoveredBuilding: hoveredBuilding, growProgress: growProgress, animationConfig: animationConfig, highlightLayers: highlightLayers, isolationMode: isolationMode, dimOpacity: dimOpacity, heightScaling: heightScaling, linearScale: linearScale }) }), _jsx(InfoPanel, { building: hoveredBuilding }), showControls && (_jsx(ControlsOverlay, { isFlat: !isGrown, onToggle: handleToggle, onResetCamera: resetCamera }))] }));
546
481
  }
547
- exports.default = FileCity3D;
482
+ export default FileCity3D;
@@ -1,9 +1,4 @@
1
- "use strict";
2
1
  /**
3
2
  * FileCity3D - 3D visualization component
4
3
  */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.resetCamera = exports.FileCity3D = void 0;
7
- var FileCity3D_1 = require("./FileCity3D");
8
- Object.defineProperty(exports, "FileCity3D", { enumerable: true, get: function () { return FileCity3D_1.FileCity3D; } });
9
- Object.defineProperty(exports, "resetCamera", { enumerable: true, get: function () { return FileCity3D_1.resetCamera; } });
4
+ export { FileCity3D, resetCamera } from './FileCity3D';
@@ -1,18 +1,15 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useCodeCityData = useCodeCityData;
4
- const react_1 = require("react");
5
- const file_city_builder_1 = require("@principal-ai/file-city-builder");
6
- function useCodeCityData({ fileSystemTree, autoUpdate = true, }) {
7
- const [cityData, setCityData] = (0, react_1.useState)(null);
8
- const [isLoading, setIsLoading] = (0, react_1.useState)(false);
9
- const [error, setError] = (0, react_1.useState)(null);
1
+ import { useState, useEffect, useMemo } from 'react';
2
+ import { MultiVersionCityBuilder } from '@principal-ai/file-city-builder';
3
+ export function useCodeCityData({ fileSystemTree, autoUpdate = true, }) {
4
+ const [cityData, setCityData] = useState(null);
5
+ const [isLoading, setIsLoading] = useState(false);
6
+ const [error, setError] = useState(null);
10
7
  // UI state
11
- const [highlightedPaths, setHighlightedPaths] = (0, react_1.useState)(new Set());
12
- const [selectedPaths, setSelectedPaths] = (0, react_1.useState)(new Set());
13
- const [focusDirectory, setFocusDirectory] = (0, react_1.useState)(null);
8
+ const [highlightedPaths, setHighlightedPaths] = useState(new Set());
9
+ const [selectedPaths, setSelectedPaths] = useState(new Set());
10
+ const [focusDirectory, setFocusDirectory] = useState(null);
14
11
  // Rebuild city data
15
- const rebuild = (0, react_1.useMemo)(() => {
12
+ const rebuild = useMemo(() => {
16
13
  return () => {
17
14
  if (!fileSystemTree) {
18
15
  setCityData(null);
@@ -24,7 +21,7 @@ function useCodeCityData({ fileSystemTree, autoUpdate = true, }) {
24
21
  try {
25
22
  // Create a single-version map for the builder
26
23
  const versionMap = new Map([['main', fileSystemTree]]);
27
- const { unionCity } = file_city_builder_1.MultiVersionCityBuilder.build(versionMap);
24
+ const { unionCity } = MultiVersionCityBuilder.build(versionMap);
28
25
  setCityData(unionCity);
29
26
  }
30
27
  catch (err) {
@@ -37,7 +34,7 @@ function useCodeCityData({ fileSystemTree, autoUpdate = true, }) {
37
34
  };
38
35
  }, [fileSystemTree]);
39
36
  // Auto rebuild when dependencies change
40
- (0, react_1.useEffect)(() => {
37
+ useEffect(() => {
41
38
  if (autoUpdate) {
42
39
  rebuild();
43
40
  }
package/dist/index.js CHANGED
@@ -1,45 +1,22 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resetCamera = exports.FileCity3D = exports.useTheme = exports.ThemeProvider = exports.CityViewWithReactFlow = exports.useCodeCityData = exports.MultiVersionCityBuilder = exports.drawFileTypeIcon = exports.getFileTypeIcon = exports.extractIconConfig = exports.mergeFileColorConfig = exports.devFileColorOverrides = exports.getFileColorMapping = exports.getDefaultFileColorConfig = exports.createFileColorHighlightLayers = exports.filterCityDataForMultipleDirectories = exports.filterCityDataForSubdirectory = exports.filterCityDataForSelectiveRender = exports.LayerIndex = exports.ArchitectureMapHighlightLayers = void 0;
4
1
  // Main component export
5
- var ArchitectureMapHighlightLayers_1 = require("./components/ArchitectureMapHighlightLayers");
6
- Object.defineProperty(exports, "ArchitectureMapHighlightLayers", { enumerable: true, get: function () { return ArchitectureMapHighlightLayers_1.ArchitectureMapHighlightLayers; } });
2
+ export { ArchitectureMapHighlightLayers, } from './components/ArchitectureMapHighlightLayers';
7
3
  // Layer and rendering types
8
- var drawLayeredBuildings_1 = require("./render/client/drawLayeredBuildings");
9
- Object.defineProperty(exports, "LayerIndex", { enumerable: true, get: function () { return drawLayeredBuildings_1.LayerIndex; } });
4
+ export { LayerIndex, } from './render/client/drawLayeredBuildings';
10
5
  // Utility functions
11
- var cityDataUtils_1 = require("./builder/cityDataUtils");
12
- Object.defineProperty(exports, "filterCityDataForSelectiveRender", { enumerable: true, get: function () { return cityDataUtils_1.filterCityDataForSelectiveRender; } });
13
- Object.defineProperty(exports, "filterCityDataForSubdirectory", { enumerable: true, get: function () { return cityDataUtils_1.filterCityDataForSubdirectory; } });
14
- Object.defineProperty(exports, "filterCityDataForMultipleDirectories", { enumerable: true, get: function () { return cityDataUtils_1.filterCityDataForMultipleDirectories; } });
6
+ export { filterCityDataForSelectiveRender, filterCityDataForSubdirectory, filterCityDataForMultipleDirectories, } from './builder/cityDataUtils';
15
7
  // File color highlight layer utilities
16
- var fileColorHighlightLayers_1 = require("./utils/fileColorHighlightLayers");
17
- Object.defineProperty(exports, "createFileColorHighlightLayers", { enumerable: true, get: function () { return fileColorHighlightLayers_1.createFileColorHighlightLayers; } });
18
- Object.defineProperty(exports, "getDefaultFileColorConfig", { enumerable: true, get: function () { return fileColorHighlightLayers_1.getDefaultFileColorConfig; } });
19
- Object.defineProperty(exports, "getFileColorMapping", { enumerable: true, get: function () { return fileColorHighlightLayers_1.getFileColorMapping; } });
8
+ export { createFileColorHighlightLayers, getDefaultFileColorConfig, getFileColorMapping, } from './utils/fileColorHighlightLayers';
20
9
  // File color override utilities for development
21
- var fileColorOverrides_1 = require("./utils/fileColorOverrides");
22
- Object.defineProperty(exports, "devFileColorOverrides", { enumerable: true, get: function () { return fileColorOverrides_1.devFileColorOverrides; } });
23
- Object.defineProperty(exports, "mergeFileColorConfig", { enumerable: true, get: function () { return fileColorOverrides_1.mergeFileColorConfig; } });
10
+ export { devFileColorOverrides, mergeFileColorConfig } from './utils/fileColorOverrides';
24
11
  // File type icon utilities
25
- var fileTypeIcons_1 = require("./utils/fileTypeIcons");
26
- Object.defineProperty(exports, "extractIconConfig", { enumerable: true, get: function () { return fileTypeIcons_1.extractIconConfig; } });
27
- Object.defineProperty(exports, "getFileTypeIcon", { enumerable: true, get: function () { return fileTypeIcons_1.getFileTypeIcon; } });
28
- Object.defineProperty(exports, "drawFileTypeIcon", { enumerable: true, get: function () { return fileTypeIcons_1.drawFileTypeIcon; } });
12
+ export { extractIconConfig, getFileTypeIcon, drawFileTypeIcon } from './utils/fileTypeIcons';
29
13
  // Re-export MultiVersionCityBuilder which was requested
30
- var file_city_builder_1 = require("@principal-ai/file-city-builder");
31
- Object.defineProperty(exports, "MultiVersionCityBuilder", { enumerable: true, get: function () { return file_city_builder_1.MultiVersionCityBuilder; } });
14
+ export { MultiVersionCityBuilder } from '@principal-ai/file-city-builder';
32
15
  // Export the useCodeCityData hook
33
- var useCodeCityData_1 = require("./hooks/useCodeCityData");
34
- Object.defineProperty(exports, "useCodeCityData", { enumerable: true, get: function () { return useCodeCityData_1.useCodeCityData; } });
16
+ export { useCodeCityData } from './hooks/useCodeCityData';
35
17
  // Export React Flow based city view component
36
- var CityViewWithReactFlow_1 = require("./components/CityViewWithReactFlow");
37
- Object.defineProperty(exports, "CityViewWithReactFlow", { enumerable: true, get: function () { return CityViewWithReactFlow_1.CityViewWithReactFlow; } });
18
+ export { CityViewWithReactFlow, } from './components/CityViewWithReactFlow';
38
19
  // Re-export theme utilities for consumers
39
- var industry_theme_1 = require("@principal-ade/industry-theme");
40
- Object.defineProperty(exports, "ThemeProvider", { enumerable: true, get: function () { return industry_theme_1.ThemeProvider; } });
41
- Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return industry_theme_1.useTheme; } });
20
+ export { ThemeProvider, useTheme } from '@principal-ade/industry-theme';
42
21
  // 3D visualization component
43
- var FileCity3D_1 = require("./components/FileCity3D");
44
- Object.defineProperty(exports, "FileCity3D", { enumerable: true, get: function () { return FileCity3D_1.FileCity3D; } });
45
- Object.defineProperty(exports, "resetCamera", { enumerable: true, get: function () { return FileCity3D_1.resetCamera; } });
22
+ export { FileCity3D, resetCamera } from './components/FileCity3D';
@@ -1,16 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LayerIndex = void 0;
4
- exports.drawGrid = drawGrid;
5
- exports.drawLayeredDistricts = drawLayeredDistricts;
6
- exports.drawLayeredBuildings = drawLayeredBuildings;
7
- const lucideIconConverter_1 = require("../../utils/lucideIconConverter");
8
- const fileTypeIcons_1 = require("../../utils/fileTypeIcons");
1
+ import { getLucideIconImage } from '../../utils/lucideIconConverter';
2
+ import { getFileTypeIcon, drawFileTypeIcon } from '../../utils/fileTypeIcons';
9
3
  /**
10
4
  * LayerIndex provides O(1) path lookups instead of O(n) iteration.
11
5
  * This dramatically improves performance with large numbers of layer items.
12
6
  */
13
- class LayerIndex {
7
+ export class LayerIndex {
14
8
  constructor(layers) {
15
9
  // Map from exact path to layer items (for file items)
16
10
  this.exactIndex = new Map();
@@ -86,7 +80,6 @@ class LayerIndex {
86
80
  return sorted;
87
81
  }
88
82
  }
89
- exports.LayerIndex = LayerIndex;
90
83
  // Helper function to draw rounded rectangles
91
84
  function drawRoundedRect(ctx, x, y, width, height, radius, fill, stroke) {
92
85
  ctx.beginPath();
@@ -106,7 +99,7 @@ function drawRoundedRect(ctx, x, y, width, height, radius, fill, stroke) {
106
99
  ctx.stroke();
107
100
  }
108
101
  // Draw grid helper (copied from original)
109
- function drawGrid(ctx, width, height, gridSize) {
102
+ export function drawGrid(ctx, width, height, gridSize) {
110
103
  ctx.save();
111
104
  ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
112
105
  ctx.lineWidth = 1;
@@ -284,7 +277,7 @@ function renderCoverStrategy(ctx, bounds, layer, item, _scale) {
284
277
  let img = null;
285
278
  // Check for lucideIcon first (new way)
286
279
  if (coverOptions.lucideIcon) {
287
- img = (0, lucideIconConverter_1.getLucideIconImage)(coverOptions.lucideIcon, '#ffffff', coverOptions.iconSize || 24);
280
+ img = getLucideIconImage(coverOptions.lucideIcon, '#ffffff', coverOptions.iconSize || 24);
288
281
  }
289
282
  // Fallback to direct image URL (old way)
290
283
  else if (coverOptions.image) {
@@ -396,7 +389,7 @@ function applyLayerRendering(ctx, bounds, layer, item, scale, borderRadius = 0)
396
389
  }
397
390
  }
398
391
  // Draw districts with layer support
399
- function drawLayeredDistricts(ctx, districts, worldToCanvas, scale, // This includes the zoom scale for text proportionality
392
+ export function drawLayeredDistricts(ctx, districts, worldToCanvas, scale, // This includes the zoom scale for text proportionality
400
393
  layers, hoveredDistrict, fullSize, defaultDirectoryColor, layoutConfig, abstractedPaths, // Paths of directories that are abstracted (have covers)
401
394
  showDirectoryLabels = true, borderRadius = 0, // Border radius for districts (default: sharp corners)
402
395
  layerIndex) {
@@ -584,7 +577,7 @@ layerIndex) {
584
577
  });
585
578
  }
586
579
  // Draw buildings with layer support
587
- function drawLayeredBuildings(ctx, buildings, worldToCanvas, scale, layers, hoveredBuilding, defaultBuildingColor, showFileNames, hoverBorderColor, disableOpacityDimming, showFileTypeIcons, borderRadius = 0, // Border radius for buildings (default: 0 - sharp corners)
580
+ export function drawLayeredBuildings(ctx, buildings, worldToCanvas, scale, layers, hoveredBuilding, defaultBuildingColor, showFileNames, hoverBorderColor, disableOpacityDimming, showFileTypeIcons, borderRadius = 0, // Border radius for buildings (default: 0 - sharp corners)
588
581
  layerIndex, // Optional pre-built index for performance
589
582
  iconMap) {
590
583
  // Build index once for all buildings (O(n) instead of O(n²))
@@ -657,7 +650,7 @@ iconMap) {
657
650
  let iconBottomY = pos.y;
658
651
  let hasIcon = false;
659
652
  if (showFileTypeIcons && iconMap) {
660
- const iconConfig = (0, fileTypeIcons_1.getFileTypeIcon)(building.path, iconMap);
653
+ const iconConfig = getFileTypeIcon(building.path, iconMap);
661
654
  if (iconConfig) {
662
655
  hasIcon = true;
663
656
  // For wide buildings (wider than tall), shift icon up to make room for text below
@@ -666,7 +659,7 @@ iconMap) {
666
659
  const isWide = width > height;
667
660
  const iconYOffset = (willShowText && isWide) ? -height * 0.15 : 0;
668
661
  const iconY = pos.y + iconYOffset;
669
- (0, fileTypeIcons_1.drawFileTypeIcon)(ctx, iconConfig, pos.x, iconY, width, height);
662
+ drawFileTypeIcon(ctx, iconConfig, pos.x, iconY, width, height);
670
663
  // Calculate where the icon ends vertically
671
664
  const minDimension = Math.min(width, height);
672
665
  if (iconConfig.type === 'emoji') {
@@ -1,8 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSampleCityData = createSampleCityData;
4
- exports.createSmallSampleCityData = createSmallSampleCityData;
5
- const file_city_builder_1 = require("@principal-ai/file-city-builder");
1
+ import { CodeCityBuilderWithGrid, buildFileSystemTreeFromFileInfoList, } from '@principal-ai/file-city-builder';
6
2
  // Sample file structure representing a typical project
7
3
  const sampleFileStructure = [
8
4
  // Source files
@@ -66,13 +62,13 @@ function createFileInfoList(files) {
66
62
  // Cache the city data to avoid rebuilding on every render
67
63
  let cachedCityData = null;
68
64
  // Helper function to create sample city data for stories using the real treemap builder
69
- function createSampleCityData() {
65
+ export function createSampleCityData() {
70
66
  if (cachedCityData) {
71
67
  return cachedCityData;
72
68
  }
73
69
  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();
70
+ const fileTree = buildFileSystemTreeFromFileInfoList(fileInfos, 'sample-project');
71
+ const builder = new CodeCityBuilderWithGrid();
76
72
  cachedCityData = builder.buildCityFromFileSystem(fileTree, '', {
77
73
  paddingTop: 2,
78
74
  paddingBottom: 2,
@@ -92,13 +88,13 @@ const smallFileStructure = [
92
88
  ];
93
89
  let cachedSmallCityData = null;
94
90
  // Create a smaller sample for performance testing
95
- function createSmallSampleCityData() {
91
+ export function createSmallSampleCityData() {
96
92
  if (cachedSmallCityData) {
97
93
  return cachedSmallCityData;
98
94
  }
99
95
  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();
96
+ const fileTree = buildFileSystemTreeFromFileInfoList(fileInfos, 'small-sample');
97
+ const builder = new CodeCityBuilderWithGrid();
102
98
  cachedSmallCityData = builder.buildCityFromFileSystem(fileTree, '', {
103
99
  paddingTop: 2,
104
100
  paddingBottom: 2,