@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,45 +1,10 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ArchitectureMapHighlightLayers = void 0;
37
- const react_1 = __importStar(require("react"));
38
- const industry_theme_1 = require("@principal-ade/industry-theme");
39
- const cityDataUtils_1 = require("../builder/cityDataUtils");
40
- const drawLayeredBuildings_1 = require("../render/client/drawLayeredBuildings");
41
- const fileColorHighlightLayers_1 = require("../utils/fileColorHighlightLayers");
42
- const fileTypeIcons_1 = require("../utils/fileTypeIcons");
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState, useMemo, useCallback } from 'react';
3
+ import { useTheme } from '@principal-ade/industry-theme';
4
+ import { filterCityDataForSelectiveRender, filterCityDataForSubdirectory, filterCityDataForMultipleDirectories, } from '../builder/cityDataUtils';
5
+ import { drawLayeredBuildings, drawLayeredDistricts, drawGrid, LayerIndex, } from '../render/client/drawLayeredBuildings';
6
+ import { getDefaultFileColorConfig } from '../utils/fileColorHighlightLayers';
7
+ import { extractIconConfig } from '../utils/fileTypeIcons';
43
8
  const DEFAULT_DISPLAY_OPTIONS = {
44
9
  showGrid: false,
45
10
  showConnections: true,
@@ -181,25 +146,25 @@ class PathHierarchyLookup {
181
146
  }
182
147
  function ArchitectureMapHighlightLayersInner({ cityData, highlightLayers = [], onLayerToggle, focusDirectory = null, rootDirectoryName, onDirectorySelect, onFileClick, enableZoom = false, zoomToPath = null, onZoomComplete, zoomAnimationSpeed = 0.12, allowZoomToPath = true, fullSize = false, showGrid = false, showFileNames = false, className = '', selectiveRender, canvasBackgroundColor, maxCanvasSize, hoverBorderColor, disableOpacityDimming = true, defaultDirectoryColor, defaultBuildingColor, subdirectoryMode, showLayerControls = false, showFileTypeIcons = true, showDirectoryLabels = true, transform = { rotation: 0 }, // Default to no rotation
183
148
  onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
184
- const { theme } = (0, industry_theme_1.useTheme)();
149
+ const { theme } = useTheme();
185
150
  // Use theme colors as defaults, with prop overrides
186
151
  const resolvedCanvasBackgroundColor = canvasBackgroundColor ?? theme.colors.background;
187
152
  const resolvedHoverBorderColor = hoverBorderColor ?? theme.colors.text;
188
153
  const resolvedDefaultDirectoryColor = defaultDirectoryColor ?? theme.colors.backgroundSecondary;
189
154
  const resolvedDefaultBuildingColor = defaultBuildingColor ?? theme.colors.muted;
190
- const canvasRef = (0, react_1.useRef)(null);
191
- const containerRef = (0, react_1.useRef)(null);
155
+ const canvasRef = useRef(null);
156
+ const containerRef = useRef(null);
192
157
  // Extract icon configuration from file color config
193
- const iconMap = (0, react_1.useMemo)(() => {
194
- const colorConfig = (0, fileColorHighlightLayers_1.getDefaultFileColorConfig)();
195
- return (0, fileTypeIcons_1.extractIconConfig)(colorConfig);
158
+ const iconMap = useMemo(() => {
159
+ const colorConfig = getDefaultFileColorConfig();
160
+ return extractIconConfig(colorConfig);
196
161
  }, []);
197
- const [interactionState, setInteractionState] = (0, react_1.useState)({
162
+ const [interactionState, setInteractionState] = useState({
198
163
  hoveredDistrict: null,
199
164
  hoveredBuilding: null,
200
165
  mousePos: { x: 0, y: 0 },
201
166
  });
202
- const [zoomState, setZoomState] = (0, react_1.useState)({
167
+ const [zoomState, setZoomState] = useState({
203
168
  scale: 1,
204
169
  offsetX: 0,
205
170
  offsetY: 0,
@@ -208,19 +173,19 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
208
173
  hasMouseMoved: false,
209
174
  });
210
175
  // Target zoom state for animated transitions
211
- const [targetZoom, setTargetZoom] = (0, react_1.useState)(null);
176
+ const [targetZoom, setTargetZoom] = useState(null);
212
177
  // Stable zoom scale - only updates when animation completes or user stops zooming
213
178
  // Used for expensive calculations that shouldn't run every frame
214
- const [stableZoomScale, setStableZoomScale] = (0, react_1.useState)(1);
215
- const stableZoomTimeoutRef = (0, react_1.useRef)(null);
179
+ const [stableZoomScale, setStableZoomScale] = useState(1);
180
+ const stableZoomTimeoutRef = useRef(null);
216
181
  // Track if we're currently animating
217
182
  const isAnimating = targetZoom !== null;
218
183
  // Track the last zoomToPath to detect changes
219
- const lastZoomToPathRef = (0, react_1.useRef)(null);
184
+ const lastZoomToPathRef = useRef(null);
220
185
  // Throttle ref for hover updates (improves performance with large datasets)
221
- const lastHoverUpdateRef = (0, react_1.useRef)(0);
186
+ const lastHoverUpdateRef = useRef(0);
222
187
  const HOVER_THROTTLE_MS = 16; // ~60fps max for hover updates
223
- (0, react_1.useEffect)(() => {
188
+ useEffect(() => {
224
189
  // Reset user interaction state when enableZoom is disabled
225
190
  if (!enableZoom) {
226
191
  setZoomState(prev => ({
@@ -241,7 +206,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
241
206
  }
242
207
  }, [enableZoom, allowZoomToPath]);
243
208
  // Animation loop for smooth zoom transitions
244
- (0, react_1.useEffect)(() => {
209
+ useEffect(() => {
245
210
  if (!targetZoom)
246
211
  return;
247
212
  const animate = () => {
@@ -279,7 +244,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
279
244
  }, [targetZoom, zoomState, zoomAnimationSpeed, onZoomComplete]);
280
245
  // Update stable zoom scale with debouncing
281
246
  // This ensures expensive calculations only run when zoom stabilizes
282
- (0, react_1.useEffect)(() => {
247
+ useEffect(() => {
283
248
  // Clear any pending timeout
284
249
  if (stableZoomTimeoutRef.current) {
285
250
  clearTimeout(stableZoomTimeoutRef.current);
@@ -299,13 +264,13 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
299
264
  };
300
265
  }, [zoomState.scale, isAnimating]);
301
266
  // Immediately update stable zoom when animation completes
302
- (0, react_1.useEffect)(() => {
267
+ useEffect(() => {
303
268
  if (!isAnimating && targetZoom === null) {
304
269
  // Animation just completed, update stable zoom immediately
305
270
  setStableZoomScale(zoomState.scale);
306
271
  }
307
272
  }, [isAnimating, targetZoom, zoomState.scale]);
308
- const [hitTestCache, setHitTestCache] = (0, react_1.useState)(null);
273
+ const [hitTestCache, setHitTestCache] = useState(null);
309
274
  const calculateCanvasResolution = (fileCount, _cityBounds) => {
310
275
  const minSize = 400;
311
276
  const scaleFactor = Math.sqrt(fileCount / 5);
@@ -315,12 +280,12 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
315
280
  }
316
281
  return { width: resolution, height: resolution };
317
282
  };
318
- const [canvasSize, setCanvasSize] = (0, react_1.useState)(() => calculateCanvasResolution(cityData?.buildings?.length || 10, cityData?.bounds));
319
- const [displayOptions] = (0, react_1.useState)({
283
+ const [canvasSize, setCanvasSize] = useState(() => calculateCanvasResolution(cityData?.buildings?.length || 10, cityData?.bounds));
284
+ const [displayOptions] = useState({
320
285
  ...DEFAULT_DISPLAY_OPTIONS,
321
286
  showGrid,
322
287
  });
323
- const filteredCityData = (0, react_1.useMemo)(() => {
288
+ const filteredCityData = useMemo(() => {
324
289
  if (!cityData) {
325
290
  return undefined;
326
291
  }
@@ -329,23 +294,23 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
329
294
  const autoCenter = subdirectoryMode.autoCenter === true;
330
295
  // Use new multi-filter function if filters are provided
331
296
  if (subdirectoryMode.filters && subdirectoryMode.filters.length > 0) {
332
- processedData = (0, cityDataUtils_1.filterCityDataForMultipleDirectories)(cityData, subdirectoryMode.filters, autoCenter, subdirectoryMode.combineMode || 'union');
297
+ processedData = filterCityDataForMultipleDirectories(cityData, subdirectoryMode.filters, autoCenter, subdirectoryMode.combineMode || 'union');
333
298
  }
334
299
  else if (subdirectoryMode.rootPath) {
335
300
  // Fallback to single path for backward compatibility
336
- processedData = (0, cityDataUtils_1.filterCityDataForSubdirectory)(cityData, subdirectoryMode.rootPath, autoCenter);
301
+ processedData = filterCityDataForSubdirectory(cityData, subdirectoryMode.rootPath, autoCenter);
337
302
  }
338
303
  }
339
- return (0, cityDataUtils_1.filterCityDataForSelectiveRender)(processedData, selectiveRender);
304
+ return filterCityDataForSelectiveRender(processedData, selectiveRender);
340
305
  }, [cityData, selectiveRender, subdirectoryMode]);
341
- const canvasSizingData = (0, react_1.useMemo)(() => {
306
+ const canvasSizingData = useMemo(() => {
342
307
  if (subdirectoryMode?.enabled && subdirectoryMode.autoCenter !== true && cityData) {
343
308
  return cityData;
344
309
  }
345
310
  return filteredCityData;
346
311
  }, [subdirectoryMode?.enabled, subdirectoryMode?.autoCenter, cityData, filteredCityData]);
347
312
  // Handle zoomToPath changes - calculate target zoom to frame the specified path
348
- (0, react_1.useEffect)(() => {
313
+ useEffect(() => {
349
314
  // Skip if programmatic zoom is not allowed or path hasn't changed
350
315
  if (!allowZoomToPath || zoomToPath === lastZoomToPathRef.current) {
351
316
  return;
@@ -435,7 +400,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
435
400
  displayOptions.padding,
436
401
  ]);
437
402
  // Build hit test cache with spatial indexing
438
- const buildHitTestCache = (0, react_1.useCallback)((cityData, scale, offsetX, offsetZ, zoomState, abstractedPaths) => {
403
+ const buildHitTestCache = useCallback((cityData, scale, offsetX, offsetZ, zoomState, abstractedPaths) => {
439
404
  const spatialGrid = new SpatialGrid(cityData.bounds);
440
405
  const pathLookup = new PathHierarchyLookup(abstractedPaths);
441
406
  // Only add visible buildings to spatial grid
@@ -474,19 +439,19 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
474
439
  };
475
440
  }, []);
476
441
  // Update canvas size when city data changes
477
- (0, react_1.useEffect)(() => {
442
+ useEffect(() => {
478
443
  if (canvasSizingData) {
479
444
  const newSize = calculateCanvasResolution(canvasSizingData.buildings.length, canvasSizingData.bounds);
480
445
  setCanvasSize(newSize);
481
446
  }
482
447
  }, [canvasSizingData, subdirectoryMode]);
483
448
  // Separate stable and dynamic layers for performance optimization
484
- const stableLayers = (0, react_1.useMemo)(() => highlightLayers.filter(layer => layer.dynamic !== true), [highlightLayers]);
485
- const dynamicLayers = (0, react_1.useMemo)(() => highlightLayers.filter(layer => layer.dynamic === true), [highlightLayers]);
449
+ const stableLayers = useMemo(() => highlightLayers.filter(layer => layer.dynamic !== true), [highlightLayers]);
450
+ const dynamicLayers = useMemo(() => highlightLayers.filter(layer => layer.dynamic === true), [highlightLayers]);
486
451
  // Combine all layers for rendering (moved up so abstractionLayer can use it)
487
- const allLayersWithoutAbstraction = (0, react_1.useMemo)(() => [...stableLayers, ...dynamicLayers], [stableLayers, dynamicLayers]);
452
+ const allLayersWithoutAbstraction = useMemo(() => [...stableLayers, ...dynamicLayers], [stableLayers, dynamicLayers]);
488
453
  // Calculate abstracted directories based on current zoom using tree structure
489
- const abstractionLayer = (0, react_1.useMemo)(() => {
454
+ const abstractionLayer = useMemo(() => {
490
455
  // Find the abstraction layer in our highlight layers
491
456
  const abstractionLayerDef = highlightLayers.find(layer => layer.id === 'directory-abstraction' && layer.abstractionLayer);
492
457
  if (!abstractionLayerDef || !abstractionLayerDef.enabled || !filteredCityData) {
@@ -695,7 +660,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
695
660
  allLayersWithoutAbstraction,
696
661
  ]);
697
662
  // Combine all layers for rendering, including calculated abstraction layer
698
- const allLayers = (0, react_1.useMemo)(() => {
663
+ const allLayers = useMemo(() => {
699
664
  const layers = [...stableLayers, ...dynamicLayers];
700
665
  // Replace abstraction layer with calculated one if it exists
701
666
  if (abstractionLayer) {
@@ -707,9 +672,9 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
707
672
  return layers;
708
673
  }, [stableLayers, dynamicLayers, abstractionLayer]);
709
674
  // Memoize layer index for O(1) path lookups - only rebuilds when layers change
710
- const layerIndex = (0, react_1.useMemo)(() => new drawLayeredBuildings_1.LayerIndex(allLayers), [allLayers]);
675
+ const layerIndex = useMemo(() => new LayerIndex(allLayers), [allLayers]);
711
676
  // Memoize abstracted paths lookup - only recalculates when abstraction layer changes
712
- const { abstractedPathsSet, abstractedPathLookup } = (0, react_1.useMemo)(() => {
677
+ const { abstractedPathsSet, abstractedPathLookup } = useMemo(() => {
713
678
  const pathsSet = new Set();
714
679
  const abstractionLayerDef = allLayers.find(l => l.id === 'directory-abstraction');
715
680
  if (abstractionLayerDef && abstractionLayerDef.enabled) {
@@ -725,7 +690,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
725
690
  };
726
691
  }, [allLayers]);
727
692
  // Memoize visible districts - only recalculates when data or abstraction changes, NOT on hover
728
- const visibleDistrictsMemo = (0, react_1.useMemo)(() => {
693
+ const visibleDistrictsMemo = useMemo(() => {
729
694
  if (!filteredCityData)
730
695
  return [];
731
696
  let districts = abstractedPathLookup.size > 0
@@ -759,7 +724,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
759
724
  return districts;
760
725
  }, [filteredCityData, abstractedPathLookup, abstractedPathsSet]);
761
726
  // Memoize visible buildings - only recalculates when data or abstraction changes, NOT on hover
762
- const visibleBuildingsMemo = (0, react_1.useMemo)(() => {
727
+ const visibleBuildingsMemo = useMemo(() => {
763
728
  if (!filteredCityData)
764
729
  return [];
765
730
  return abstractedPathLookup.size > 0
@@ -773,7 +738,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
773
738
  // 1. The spatial grid only depends on buildings/districts and abstraction
774
739
  // 2. performHitTest calculates coordinates using the current zoomState directly
775
740
  // 3. This avoids expensive cache rebuilds during zoom animation
776
- (0, react_1.useEffect)(() => {
741
+ useEffect(() => {
777
742
  if (!filteredCityData)
778
743
  return;
779
744
  const width = canvasRef.current?.clientWidth || canvasSize.width;
@@ -808,7 +773,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
808
773
  abstractionLayer,
809
774
  ]);
810
775
  // Main canvas drawing with layer-based highlighting
811
- (0, react_1.useEffect)(() => {
776
+ useEffect(() => {
812
777
  if (!canvasRef.current || !filteredCityData) {
813
778
  return;
814
779
  }
@@ -830,7 +795,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
830
795
  ctx.fillStyle = resolvedCanvasBackgroundColor;
831
796
  ctx.fillRect(0, 0, displayWidth, displayHeight);
832
797
  if (displayOptions.showGrid) {
833
- (0, drawLayeredBuildings_1.drawGrid)(ctx, displayWidth, displayHeight, displayOptions.gridSize);
798
+ drawGrid(ctx, displayWidth, displayHeight, displayOptions.gridSize);
834
799
  }
835
800
  const coordinateSystemData = subdirectoryMode?.enabled && subdirectoryMode.autoCenter !== true && cityData
836
801
  ? cityData
@@ -844,10 +809,10 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
844
809
  });
845
810
  // Use memoized visible districts and buildings (pre-filtered, doesn't recalculate on hover)
846
811
  // Draw districts with layer support
847
- (0, drawLayeredBuildings_1.drawLayeredDistricts)(ctx, visibleDistrictsMemo, worldToCanvas, scale * zoomState.scale, allLayers, interactionState.hoveredDistrict, fullSize, resolvedDefaultDirectoryColor, filteredCityData.metadata.layoutConfig, abstractedPathsSet, // Pass abstracted paths to skip labels
812
+ drawLayeredDistricts(ctx, visibleDistrictsMemo, worldToCanvas, scale * zoomState.scale, allLayers, interactionState.hoveredDistrict, fullSize, resolvedDefaultDirectoryColor, filteredCityData.metadata.layoutConfig, abstractedPathsSet, // Pass abstracted paths to skip labels
848
813
  showDirectoryLabels, districtBorderRadius, layerIndex);
849
814
  // Draw buildings with layer support
850
- (0, drawLayeredBuildings_1.drawLayeredBuildings)(ctx, visibleBuildingsMemo, worldToCanvas, scale * zoomState.scale, allLayers, interactionState.hoveredBuilding, resolvedDefaultBuildingColor, showFileNames, resolvedHoverBorderColor, disableOpacityDimming, showFileTypeIcons, buildingBorderRadius, layerIndex, // Pre-built index for O(1) lookups
815
+ drawLayeredBuildings(ctx, visibleBuildingsMemo, worldToCanvas, scale * zoomState.scale, allLayers, interactionState.hoveredBuilding, resolvedDefaultBuildingColor, showFileNames, resolvedHoverBorderColor, disableOpacityDimming, showFileTypeIcons, buildingBorderRadius, layerIndex, // Pre-built index for O(1) lookups
851
816
  iconMap);
852
817
  // Performance monitoring end available for debugging
853
818
  // Performance stats available but not logged to reduce console noise
@@ -885,7 +850,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
885
850
  iconMap,
886
851
  ]);
887
852
  // Optimized hit testing
888
- const performHitTest = (0, react_1.useCallback)((canvasX, canvasY) => {
853
+ const performHitTest = useCallback((canvasX, canvasY) => {
889
854
  if (!hitTestCache || !filteredCityData) {
890
855
  return { hoveredBuilding: null, hoveredDistrict: null };
891
856
  }
@@ -953,7 +918,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
953
918
  ]);
954
919
  // Mouse event handlers
955
920
  // Call onHover callback when interaction state changes
956
- (0, react_1.useEffect)(() => {
921
+ useEffect(() => {
957
922
  if (onHover && interactionState) {
958
923
  const fileTooltip = interactionState.hoveredBuilding
959
924
  ? {
@@ -977,7 +942,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
977
942
  }
978
943
  }, [interactionState, onHover]);
979
944
  // Helper function to transform mouse coordinates based on rotation/flip
980
- const transformMouseCoordinates = (0, react_1.useCallback)((x, y, canvasWidth, canvasHeight) => {
945
+ const transformMouseCoordinates = useCallback((x, y, canvasWidth, canvasHeight) => {
981
946
  const centerX = canvasWidth / 2;
982
947
  const centerY = canvasHeight / 2;
983
948
  // Translate to center
@@ -1006,7 +971,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1006
971
  transformedY += centerY;
1007
972
  return { x: transformedX, y: transformedY };
1008
973
  }, [transform]);
1009
- const handleMouseMoveInternal = (0, react_1.useCallback)((e) => {
974
+ const handleMouseMoveInternal = useCallback((e) => {
1010
975
  if (!canvasRef.current || !containerRef.current || !filteredCityData || zoomState.isDragging)
1011
976
  return;
1012
977
  // Throttle hover updates to improve performance with large datasets
@@ -1040,7 +1005,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1040
1005
  };
1041
1006
  });
1042
1007
  }, [filteredCityData, zoomState.isDragging, performHitTest, transformMouseCoordinates]);
1043
- const handleMouseMove = (0, react_1.useCallback)((e) => {
1008
+ const handleMouseMove = useCallback((e) => {
1044
1009
  if (enableZoom && zoomState.isDragging) {
1045
1010
  const rawDeltaX = e.clientX - zoomState.lastMousePos.x;
1046
1011
  const rawDeltaY = e.clientY - zoomState.lastMousePos.y;
@@ -1099,7 +1064,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1099
1064
  }
1100
1065
  }
1101
1066
  };
1102
- const handleMouseLeave = (0, react_1.useCallback)(() => {
1067
+ const handleMouseLeave = useCallback(() => {
1103
1068
  setInteractionState(prev => ({
1104
1069
  ...prev,
1105
1070
  hoveredDistrict: null,
@@ -1133,10 +1098,10 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1133
1098
  hasMouseMoved: false,
1134
1099
  }));
1135
1100
  };
1136
- const handleMouseUp = (0, react_1.useCallback)(() => {
1101
+ const handleMouseUp = useCallback(() => {
1137
1102
  setZoomState(prev => ({ ...prev, isDragging: false }));
1138
1103
  }, []);
1139
- const interactionCursor = (0, react_1.useMemo)(() => {
1104
+ const interactionCursor = useMemo(() => {
1140
1105
  if (enableZoom) {
1141
1106
  if (zoomState.isDragging) {
1142
1107
  return 'grabbing';
@@ -1157,7 +1122,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1157
1122
  interactionState.hoveredDistrict,
1158
1123
  ]);
1159
1124
  if (!filteredCityData) {
1160
- return (react_1.default.createElement("div", { className: className, style: {
1125
+ return (_jsxs("div", { className: className, style: {
1161
1126
  width: '100%',
1162
1127
  height: '100%',
1163
1128
  minHeight: '250px',
@@ -1168,41 +1133,39 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1168
1133
  justifyContent: 'center',
1169
1134
  position: 'relative',
1170
1135
  overflow: 'hidden',
1171
- } },
1172
- react_1.default.createElement("div", { style: {
1173
- position: 'absolute',
1174
- inset: 0,
1175
- display: 'grid',
1176
- gridTemplateColumns: 'repeat(auto-fit, minmax(80px, 1fr))',
1177
- gridAutoRows: 'minmax(80px, 1fr)',
1178
- gap: '20px',
1179
- padding: '20px',
1180
- } }, Array.from({ length: 200 }).map((_, i) => (react_1.default.createElement("div", { key: i, style: {
1181
- backgroundColor: resolvedDefaultBuildingColor,
1182
- borderRadius: buildingBorderRadius,
1183
- opacity: 0.6 + (i % 3) * 0.2,
1184
- } })))),
1185
- react_1.default.createElement("div", { style: {
1186
- position: 'absolute',
1187
- top: '35%',
1188
- left: '50%',
1189
- transform: 'translate(-50%, -50%)',
1190
- zIndex: 1,
1191
- display: 'flex',
1192
- alignItems: 'center',
1193
- justifyContent: 'center',
1194
- color: theme.colors.textMuted,
1195
- fontFamily: theme.fonts.body,
1196
- fontSize: `${theme.fontSizes[3]}px`,
1197
- fontWeight: theme.fontWeights.medium,
1198
- backgroundColor: resolvedCanvasBackgroundColor,
1199
- borderRadius: `${theme.radii[2]}px`,
1200
- padding: `${theme.space[4]}px ${theme.space[5]}px`,
1201
- textAlign: 'center',
1202
- minWidth: '300px',
1203
- } }, "No city data available")));
1136
+ }, children: [_jsx("div", { style: {
1137
+ position: 'absolute',
1138
+ inset: 0,
1139
+ display: 'grid',
1140
+ gridTemplateColumns: 'repeat(auto-fit, minmax(80px, 1fr))',
1141
+ gridAutoRows: 'minmax(80px, 1fr)',
1142
+ gap: '20px',
1143
+ padding: '20px',
1144
+ }, children: Array.from({ length: 200 }).map((_, i) => (_jsx("div", { style: {
1145
+ backgroundColor: resolvedDefaultBuildingColor,
1146
+ borderRadius: buildingBorderRadius,
1147
+ opacity: 0.6 + (i % 3) * 0.2,
1148
+ } }, i))) }), _jsx("div", { style: {
1149
+ position: 'absolute',
1150
+ top: '35%',
1151
+ left: '50%',
1152
+ transform: 'translate(-50%, -50%)',
1153
+ zIndex: 1,
1154
+ display: 'flex',
1155
+ alignItems: 'center',
1156
+ justifyContent: 'center',
1157
+ color: theme.colors.textMuted,
1158
+ fontFamily: theme.fonts.body,
1159
+ fontSize: `${theme.fontSizes[3]}px`,
1160
+ fontWeight: theme.fontWeights.medium,
1161
+ backgroundColor: resolvedCanvasBackgroundColor,
1162
+ borderRadius: `${theme.radii[2]}px`,
1163
+ padding: `${theme.space[4]}px ${theme.space[5]}px`,
1164
+ textAlign: 'center',
1165
+ minWidth: '300px',
1166
+ }, children: "No city data available" })] }));
1204
1167
  }
1205
- return (react_1.default.createElement("div", { ref: containerRef, className: className, style: {
1168
+ return (_jsxs("div", { ref: containerRef, className: className, style: {
1206
1169
  position: 'relative',
1207
1170
  width: '100%',
1208
1171
  height: '100%',
@@ -1224,65 +1187,59 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
1224
1187
  }
1225
1188
  return transforms.length > 0 ? transforms.join(' ') : undefined;
1226
1189
  })(),
1227
- } },
1228
- showLayerControls && highlightLayers.length > 0 && (react_1.default.createElement("div", { style: {
1229
- position: 'absolute',
1230
- bottom: `${theme.space[4]}px`,
1231
- left: `${theme.space[4]}px`,
1232
- zIndex: 10,
1233
- display: 'flex',
1234
- flexDirection: 'column',
1235
- gap: `${theme.space[2]}px`,
1236
- } }, highlightLayers.map(layer => (react_1.default.createElement("button", { key: layer.id, onClick: () => onLayerToggle?.(layer.id, !layer.enabled), style: {
1237
- padding: `${theme.space[2]}px ${theme.space[3]}px`,
1238
- borderRadius: `${theme.radii[2]}px`,
1239
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
1240
- transition: 'all 0.2s ease',
1241
- display: 'flex',
1242
- alignItems: 'center',
1243
- gap: `${theme.space[2]}px`,
1244
- fontSize: `${theme.fontSizes[0]}px`,
1245
- fontWeight: theme.fontWeights.medium,
1246
- fontFamily: theme.fonts.body,
1247
- backgroundColor: layer.enabled
1248
- ? theme.colors.backgroundSecondary
1249
- : theme.colors.background,
1250
- color: layer.enabled ? theme.colors.text : theme.colors.textSecondary,
1251
- border: `2px solid ${layer.enabled ? layer.color : theme.colors.border}`,
1252
- minWidth: '120px',
1253
- cursor: 'pointer',
1254
- }, title: `Toggle ${layer.name}` },
1255
- react_1.default.createElement("div", { style: {
1256
- width: '12px',
1257
- height: '12px',
1258
- borderRadius: '50%',
1259
- backgroundColor: layer.color,
1260
- opacity: layer.enabled ? 1 : 0.4,
1261
- transition: 'opacity 0.2s ease',
1262
- } }),
1263
- react_1.default.createElement("span", { style: { textAlign: 'left', flex: 1 } }, layer.name),
1264
- layer.items && layer.items.length > 0 && (react_1.default.createElement("span", { style: {
1265
- fontSize: `${theme.fontSizes[0]}px`,
1266
- color: layer.enabled ? theme.colors.textSecondary : theme.colors.textMuted,
1267
- } }, layer.items.length))))))),
1268
- react_1.default.createElement("canvas", { ref: canvasRef, style: {
1269
- position: 'absolute',
1270
- top: 0,
1271
- left: 0,
1272
- width: '100%',
1273
- height: '100%',
1274
- objectFit: 'contain',
1275
- zIndex: 1,
1276
- } }),
1277
- react_1.default.createElement("div", { style: {
1278
- position: 'absolute',
1279
- top: 0,
1280
- left: 0,
1281
- width: '100%',
1282
- height: '100%',
1283
- zIndex: 2,
1284
- cursor: interactionCursor,
1285
- }, onMouseMove: handleMouseMove, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onClick: handleClick, onMouseLeave: handleMouseLeave, onWheel: handleWheel })));
1190
+ }, children: [showLayerControls && highlightLayers.length > 0 && (_jsx("div", { style: {
1191
+ position: 'absolute',
1192
+ bottom: `${theme.space[4]}px`,
1193
+ left: `${theme.space[4]}px`,
1194
+ zIndex: 10,
1195
+ display: 'flex',
1196
+ flexDirection: 'column',
1197
+ gap: `${theme.space[2]}px`,
1198
+ }, children: highlightLayers.map(layer => (_jsxs("button", { onClick: () => onLayerToggle?.(layer.id, !layer.enabled), style: {
1199
+ padding: `${theme.space[2]}px ${theme.space[3]}px`,
1200
+ borderRadius: `${theme.radii[2]}px`,
1201
+ boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
1202
+ transition: 'all 0.2s ease',
1203
+ display: 'flex',
1204
+ alignItems: 'center',
1205
+ gap: `${theme.space[2]}px`,
1206
+ fontSize: `${theme.fontSizes[0]}px`,
1207
+ fontWeight: theme.fontWeights.medium,
1208
+ fontFamily: theme.fonts.body,
1209
+ backgroundColor: layer.enabled
1210
+ ? theme.colors.backgroundSecondary
1211
+ : theme.colors.background,
1212
+ color: layer.enabled ? theme.colors.text : theme.colors.textSecondary,
1213
+ border: `2px solid ${layer.enabled ? layer.color : theme.colors.border}`,
1214
+ minWidth: '120px',
1215
+ cursor: 'pointer',
1216
+ }, title: `Toggle ${layer.name}`, children: [_jsx("div", { style: {
1217
+ width: '12px',
1218
+ height: '12px',
1219
+ borderRadius: '50%',
1220
+ backgroundColor: layer.color,
1221
+ opacity: layer.enabled ? 1 : 0.4,
1222
+ transition: 'opacity 0.2s ease',
1223
+ } }), _jsx("span", { style: { textAlign: 'left', flex: 1 }, children: layer.name }), layer.items && layer.items.length > 0 && (_jsx("span", { style: {
1224
+ fontSize: `${theme.fontSizes[0]}px`,
1225
+ color: layer.enabled ? theme.colors.textSecondary : theme.colors.textMuted,
1226
+ }, children: layer.items.length }))] }, layer.id))) })), _jsx("canvas", { ref: canvasRef, style: {
1227
+ position: 'absolute',
1228
+ top: 0,
1229
+ left: 0,
1230
+ width: '100%',
1231
+ height: '100%',
1232
+ objectFit: 'contain',
1233
+ zIndex: 1,
1234
+ } }), _jsx("div", { style: {
1235
+ position: 'absolute',
1236
+ top: 0,
1237
+ left: 0,
1238
+ width: '100%',
1239
+ height: '100%',
1240
+ zIndex: 2,
1241
+ cursor: interactionCursor,
1242
+ }, onMouseMove: handleMouseMove, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onClick: handleClick, onMouseLeave: handleMouseLeave, onWheel: handleWheel })] }));
1286
1243
  }
1287
1244
  function calculateScaleAndOffset(cityData, width, height, padding) {
1288
1245
  const cityWidth = cityData.bounds.maxX - cityData.bounds.minX;
@@ -1298,4 +1255,4 @@ function calculateScaleAndOffset(cityData, width, height, padding) {
1298
1255
  const offsetZ = (height - scaledCityHeight) / 2;
1299
1256
  return { scale, offsetX, offsetZ };
1300
1257
  }
1301
- exports.ArchitectureMapHighlightLayers = ArchitectureMapHighlightLayersInner;
1258
+ export const ArchitectureMapHighlightLayers = ArchitectureMapHighlightLayersInner;