@principal-ai/file-city-react 0.4.6 → 0.4.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.
- package/dist/components/ArchitectureMapHighlightLayers.d.ts.map +1 -1
- package/dist/components/ArchitectureMapHighlightLayers.js +10 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/render/client/drawLayeredBuildings.d.ts +3 -1
- package/dist/render/client/drawLayeredBuildings.d.ts.map +1 -1
- package/dist/render/client/drawLayeredBuildings.js +9 -40
- package/dist/utils/fileColorHighlightLayers.d.ts +10 -1
- package/dist/utils/fileColorHighlightLayers.d.ts.map +1 -1
- package/dist/utils/fileColorHighlightLayers.js +8 -5
- package/dist/utils/fileColorOverrides.d.ts +19 -0
- package/dist/utils/fileColorOverrides.d.ts.map +1 -0
- package/dist/utils/fileColorOverrides.js +52 -0
- package/dist/utils/fileTypeIcons.d.ts +16 -0
- package/dist/utils/fileTypeIcons.d.ts.map +1 -0
- package/dist/utils/fileTypeIcons.js +91 -0
- package/dist/utils/lucideIconConverter.d.ts.map +1 -1
- package/dist/utils/lucideIconConverter.js +11 -0
- package/package.json +2 -2
- package/src/components/ArchitectureMapHighlightLayers.tsx +10 -0
- package/src/index.ts +7 -0
- package/src/render/client/drawLayeredBuildings.ts +9 -51
- package/src/stories/AllFileTypes.stories.tsx +29 -2
- package/src/utils/fileColorHighlightLayers.ts +20 -5
- package/src/utils/fileColorOverrides.ts +54 -0
- package/src/utils/fileTypeIcons.ts +116 -0
- package/src/utils/lucideIconConverter.tsx +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArchitectureMapHighlightLayers.d.ts","sourceRoot":"","sources":["../../src/components/ArchitectureMapHighlightLayers.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAQjF,OAAO,EAIL,cAAc,EAGf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"ArchitectureMapHighlightLayers.d.ts","sourceRoot":"","sources":["../../src/components/ArchitectureMapHighlightLayers.tsx"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,8 @@ const react_1 = __importStar(require("react"));
|
|
|
38
38
|
const industry_theme_1 = require("@principal-ade/industry-theme");
|
|
39
39
|
const cityDataUtils_1 = require("../builder/cityDataUtils");
|
|
40
40
|
const drawLayeredBuildings_1 = require("../render/client/drawLayeredBuildings");
|
|
41
|
+
const fileColorHighlightLayers_1 = require("../utils/fileColorHighlightLayers");
|
|
42
|
+
const fileTypeIcons_1 = require("../utils/fileTypeIcons");
|
|
41
43
|
const DEFAULT_DISPLAY_OPTIONS = {
|
|
42
44
|
showGrid: false,
|
|
43
45
|
showConnections: true,
|
|
@@ -187,6 +189,11 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
|
|
|
187
189
|
const resolvedDefaultBuildingColor = defaultBuildingColor ?? theme.colors.muted;
|
|
188
190
|
const canvasRef = (0, react_1.useRef)(null);
|
|
189
191
|
const containerRef = (0, react_1.useRef)(null);
|
|
192
|
+
// 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);
|
|
196
|
+
}, []);
|
|
190
197
|
const [interactionState, setInteractionState] = (0, react_1.useState)({
|
|
191
198
|
hoveredDistrict: null,
|
|
192
199
|
hoveredBuilding: null,
|
|
@@ -832,7 +839,8 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
|
|
|
832
839
|
(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
|
|
833
840
|
showDirectoryLabels, districtBorderRadius, layerIndex);
|
|
834
841
|
// Draw buildings with layer support
|
|
835
|
-
(0, drawLayeredBuildings_1.drawLayeredBuildings)(ctx, visibleBuildingsMemo, worldToCanvas, scale * zoomState.scale, allLayers, interactionState.hoveredBuilding, resolvedDefaultBuildingColor, showFileNames, resolvedHoverBorderColor, disableOpacityDimming, showFileTypeIcons, buildingBorderRadius, layerIndex)
|
|
842
|
+
(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
|
|
843
|
+
iconMap);
|
|
836
844
|
// Performance monitoring end available for debugging
|
|
837
845
|
// Performance stats available but not logged to reduce console noise
|
|
838
846
|
// Uncomment for debugging: render time, buildings/districts counts, layer counts
|
|
@@ -866,6 +874,7 @@ onHover, buildingBorderRadius = 0, districtBorderRadius = 0, }) {
|
|
|
866
874
|
visibleBuildingsMemo,
|
|
867
875
|
abstractedPathsSet,
|
|
868
876
|
layerIndex,
|
|
877
|
+
iconMap,
|
|
869
878
|
]);
|
|
870
879
|
// Optimized hit testing
|
|
871
880
|
const performHitTest = (0, react_1.useCallback)((canvasX, canvasY) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ export { type LayerRenderStrategy, type LayerItem, type HighlightLayer, LayerInd
|
|
|
3
3
|
export { type MapInteractionState, type MapDisplayOptions } from './types/react-types';
|
|
4
4
|
export { filterCityDataForSelectiveRender, filterCityDataForSubdirectory, filterCityDataForMultipleDirectories, } from './builder/cityDataUtils';
|
|
5
5
|
export { createFileColorHighlightLayers, getDefaultFileColorConfig, getFileColorMapping, } from './utils/fileColorHighlightLayers';
|
|
6
|
-
export type { ColorLayerConfig, FileSuffixConfig, FileSuffixColorConfig, } from './utils/fileColorHighlightLayers';
|
|
6
|
+
export type { ColorLayerConfig, FileSuffixConfig, FileSuffixColorConfig, FileTypeIconConfig, } from './utils/fileColorHighlightLayers';
|
|
7
|
+
export { devFileColorOverrides, mergeFileColorConfig } from './utils/fileColorOverrides';
|
|
8
|
+
export { extractIconConfig, getFileTypeIcon, drawFileTypeIcon } from './utils/fileTypeIcons';
|
|
7
9
|
export type { CityData, CityBuilding, CityDistrict, SelectiveRenderOptions, Bounds2D, Position3D, } from '@principal-ai/file-city-builder';
|
|
8
10
|
export { MultiVersionCityBuilder } from '@principal-ai/file-city-builder';
|
|
9
11
|
export { useCodeCityData } from './hooks/useCodeCityData';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,8BAA8B,EAC9B,KAAK,mCAAmC,GACzC,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,UAAU,GACX,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,oCAAoC,GACrC,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,8BAA8B,EAC9B,KAAK,mCAAmC,GACzC,MAAM,6CAA6C,CAAC;AAGrD,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,UAAU,GACX,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EACL,gCAAgC,EAChC,6BAA6B,EAC7B,oCAAoC,GACrC,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAGzF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG7F,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,QAAQ,EACR,UAAU,GACX,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAG1E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAG7F,YAAY,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAGhE,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,GAChC,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useTheme = exports.ThemeProvider = exports.CityViewWithReactFlow = exports.useCodeCityData = exports.MultiVersionCityBuilder = exports.getFileColorMapping = exports.getDefaultFileColorConfig = exports.createFileColorHighlightLayers = exports.filterCityDataForMultipleDirectories = exports.filterCityDataForSubdirectory = exports.filterCityDataForSelectiveRender = exports.LayerIndex = exports.ArchitectureMapHighlightLayers = void 0;
|
|
3
|
+
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
4
|
// Main component export
|
|
5
5
|
var ArchitectureMapHighlightLayers_1 = require("./components/ArchitectureMapHighlightLayers");
|
|
6
6
|
Object.defineProperty(exports, "ArchitectureMapHighlightLayers", { enumerable: true, get: function () { return ArchitectureMapHighlightLayers_1.ArchitectureMapHighlightLayers; } });
|
|
@@ -17,6 +17,15 @@ var fileColorHighlightLayers_1 = require("./utils/fileColorHighlightLayers");
|
|
|
17
17
|
Object.defineProperty(exports, "createFileColorHighlightLayers", { enumerable: true, get: function () { return fileColorHighlightLayers_1.createFileColorHighlightLayers; } });
|
|
18
18
|
Object.defineProperty(exports, "getDefaultFileColorConfig", { enumerable: true, get: function () { return fileColorHighlightLayers_1.getDefaultFileColorConfig; } });
|
|
19
19
|
Object.defineProperty(exports, "getFileColorMapping", { enumerable: true, get: function () { return fileColorHighlightLayers_1.getFileColorMapping; } });
|
|
20
|
+
// 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; } });
|
|
24
|
+
// 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; } });
|
|
20
29
|
// Re-export MultiVersionCityBuilder which was requested
|
|
21
30
|
var file_city_builder_1 = require("@principal-ai/file-city-builder");
|
|
22
31
|
Object.defineProperty(exports, "MultiVersionCityBuilder", { enumerable: true, get: function () { return file_city_builder_1.MultiVersionCityBuilder; } });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CityBuilding, CityDistrict } from '@principal-ai/file-city-builder';
|
|
2
|
+
import { FileTypeIconConfig } from '../../utils/fileColorHighlightLayers';
|
|
2
3
|
export type LayerRenderStrategy = 'border' | 'fill' | 'glow' | 'pattern' | 'cover' | 'icon' | 'custom';
|
|
3
4
|
export interface LayerItem {
|
|
4
5
|
path: string;
|
|
@@ -70,5 +71,6 @@ export declare function drawLayeredBuildings(ctx: CanvasRenderingContext2D, buil
|
|
|
70
71
|
x: number;
|
|
71
72
|
y: number;
|
|
72
73
|
}, scale: number, layers: HighlightLayer[], hoveredBuilding?: CityBuilding | null, defaultBuildingColor?: string, showFileNames?: boolean, hoverBorderColor?: string, disableOpacityDimming?: boolean, showFileTypeIcons?: boolean, borderRadius?: number, // Border radius for buildings (default: 0 - sharp corners)
|
|
73
|
-
layerIndex?: LayerIndex
|
|
74
|
+
layerIndex?: LayerIndex, // Optional pre-built index for performance
|
|
75
|
+
iconMap?: Map<string, FileTypeIconConfig>): void;
|
|
74
76
|
//# sourceMappingURL=drawLayeredBuildings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawLayeredBuildings.d.ts","sourceRoot":"","sources":["../../../src/render/client/drawLayeredBuildings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"drawLayeredBuildings.d.ts","sourceRoot":"","sources":["../../../src/render/client/drawLayeredBuildings.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ exports.drawGrid = drawGrid;
|
|
|
5
5
|
exports.drawLayeredDistricts = drawLayeredDistricts;
|
|
6
6
|
exports.drawLayeredBuildings = drawLayeredBuildings;
|
|
7
7
|
const lucideIconConverter_1 = require("../../utils/lucideIconConverter");
|
|
8
|
+
const fileTypeIcons_1 = require("../../utils/fileTypeIcons");
|
|
8
9
|
/**
|
|
9
10
|
* LayerIndex provides O(1) path lookups instead of O(n) iteration.
|
|
10
11
|
* This dramatically improves performance with large numbers of layer items.
|
|
@@ -582,38 +583,10 @@ layerIndex) {
|
|
|
582
583
|
} // End of !hasCover check
|
|
583
584
|
});
|
|
584
585
|
}
|
|
585
|
-
/**
|
|
586
|
-
* Draw a React symbol (⚛) at the given position
|
|
587
|
-
*/
|
|
588
|
-
function drawReactSymbol(ctx, x, y, size, color = '#00D8FF', glow = true) {
|
|
589
|
-
ctx.save();
|
|
590
|
-
// Position and setup
|
|
591
|
-
ctx.translate(x, y);
|
|
592
|
-
// Glow effect for React symbol
|
|
593
|
-
if (glow) {
|
|
594
|
-
ctx.shadowColor = color;
|
|
595
|
-
ctx.shadowBlur = 8;
|
|
596
|
-
}
|
|
597
|
-
// Draw the React symbol (⚛)
|
|
598
|
-
ctx.fillStyle = color;
|
|
599
|
-
ctx.font = `${size}px Arial`;
|
|
600
|
-
ctx.textAlign = 'center';
|
|
601
|
-
ctx.textBaseline = 'middle';
|
|
602
|
-
ctx.fillText('⚛', 0, 0);
|
|
603
|
-
ctx.restore();
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Check if a file is a React file (JSX/TSX)
|
|
607
|
-
*/
|
|
608
|
-
function isReactFile(fileExtension) {
|
|
609
|
-
if (!fileExtension)
|
|
610
|
-
return false;
|
|
611
|
-
const ext = fileExtension.toLowerCase();
|
|
612
|
-
return ext === '.jsx' || ext === '.tsx';
|
|
613
|
-
}
|
|
614
586
|
// Draw buildings with layer support
|
|
615
587
|
function drawLayeredBuildings(ctx, buildings, worldToCanvas, scale, layers, hoveredBuilding, defaultBuildingColor, showFileNames, hoverBorderColor, disableOpacityDimming, showFileTypeIcons, borderRadius = 0, // Border radius for buildings (default: 0 - sharp corners)
|
|
616
|
-
layerIndex
|
|
588
|
+
layerIndex, // Optional pre-built index for performance
|
|
589
|
+
iconMap) {
|
|
617
590
|
// Build index once for all buildings (O(n) instead of O(n²))
|
|
618
591
|
const index = layerIndex || new LayerIndex(layers);
|
|
619
592
|
buildings.forEach(building => {
|
|
@@ -679,16 +652,12 @@ layerIndex) {
|
|
|
679
652
|
ctx.strokeRect(bounds.x - 1, bounds.y - 1, bounds.width + 2, bounds.height + 2);
|
|
680
653
|
}
|
|
681
654
|
}
|
|
682
|
-
// Draw
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
const reactSize = Math.min(width, height) * 0.75;
|
|
689
|
-
const reactX = pos.x;
|
|
690
|
-
const reactY = pos.y;
|
|
691
|
-
drawReactSymbol(ctx, reactX, reactY, reactSize);
|
|
655
|
+
// Draw file type icon if enabled and icon map is provided
|
|
656
|
+
if (showFileTypeIcons && iconMap) {
|
|
657
|
+
const iconConfig = (0, fileTypeIcons_1.getFileTypeIcon)(building.path, iconMap);
|
|
658
|
+
if (iconConfig) {
|
|
659
|
+
(0, fileTypeIcons_1.drawFileTypeIcon)(ctx, iconConfig, pos.x, pos.y, width, height);
|
|
660
|
+
}
|
|
692
661
|
}
|
|
693
662
|
// Draw filename if enabled
|
|
694
663
|
if (showFileNames && width > 100 && height > 30) {
|
|
@@ -23,9 +23,18 @@ export interface ColorLayerConfig {
|
|
|
23
23
|
height: number;
|
|
24
24
|
}, scale: number) => void;
|
|
25
25
|
}
|
|
26
|
+
export interface FileTypeIconConfig {
|
|
27
|
+
type: 'emoji' | 'lucide';
|
|
28
|
+
name: string;
|
|
29
|
+
color?: string;
|
|
30
|
+
backgroundColor?: string;
|
|
31
|
+
glow?: boolean;
|
|
32
|
+
size?: number;
|
|
33
|
+
}
|
|
26
34
|
export interface FileSuffixConfig {
|
|
27
35
|
primary: ColorLayerConfig;
|
|
28
36
|
secondary?: ColorLayerConfig;
|
|
37
|
+
icon?: FileTypeIconConfig;
|
|
29
38
|
displayName?: string;
|
|
30
39
|
description?: string;
|
|
31
40
|
category?: string;
|
|
@@ -73,7 +82,7 @@ export declare function createFileColorHighlightLayers(files: Array<{
|
|
|
73
82
|
}> | null | undefined, config?: FileSuffixColorConfig): HighlightLayer[];
|
|
74
83
|
/**
|
|
75
84
|
* Get the default file color configuration.
|
|
76
|
-
* This returns the configuration loaded from files.json.
|
|
85
|
+
* This returns the configuration loaded from files.json merged with local dev overrides.
|
|
77
86
|
*/
|
|
78
87
|
export declare function getDefaultFileColorConfig(): FileSuffixColorConfig;
|
|
79
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileColorHighlightLayers.d.ts","sourceRoot":"","sources":["../../src/utils/fileColorHighlightLayers.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EAEd,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"fileColorHighlightLayers.d.ts","sourceRoot":"","sources":["../../src/utils/fileColorHighlightLayers.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EAEd,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;AAI/C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,mBAAmB,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,YAAY,CAAC,EAAE,CACb,GAAG,EAAE,wBAAwB,EAC7B,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAC/D,KAAK,EAAE,MAAM,KACV,IAAI,CAAC;CACX;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,gBAAgB,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EACjD,MAAM,CAAC,EAAE,qBAAqB,GAC7B,cAAc,EAAE,CAuSlB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,qBAAqB,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ1F"}
|
|
@@ -4,6 +4,7 @@ exports.createFileColorHighlightLayers = createFileColorHighlightLayers;
|
|
|
4
4
|
exports.getDefaultFileColorConfig = getDefaultFileColorConfig;
|
|
5
5
|
exports.getFileColorMapping = getFileColorMapping;
|
|
6
6
|
const file_city_builder_1 = require("@principal-ai/file-city-builder");
|
|
7
|
+
const fileColorOverrides_1 = require("./fileColorOverrides");
|
|
7
8
|
/**
|
|
8
9
|
* Creates highlight layers for files based on file extension configurations.
|
|
9
10
|
*
|
|
@@ -37,8 +38,9 @@ function createFileColorHighlightLayers(files, config) {
|
|
|
37
38
|
if (!files || files.length === 0) {
|
|
38
39
|
return [];
|
|
39
40
|
}
|
|
40
|
-
// Use provided config or fall back to default
|
|
41
|
-
const colorConfig = config ||
|
|
41
|
+
// Use provided config or fall back to default merged with dev overrides
|
|
42
|
+
const colorConfig = config ||
|
|
43
|
+
(0, fileColorOverrides_1.mergeFileColorConfig)(file_city_builder_1.defaultFileColorConfig, fileColorOverrides_1.devFileColorOverrides);
|
|
42
44
|
const { suffixConfigs, defaultConfig: defaultFileConfig, includeUnmatched = true } = colorConfig;
|
|
43
45
|
// Validation
|
|
44
46
|
if (!suffixConfigs || typeof suffixConfigs !== 'object') {
|
|
@@ -276,10 +278,10 @@ function createFileColorHighlightLayers(files, config) {
|
|
|
276
278
|
}
|
|
277
279
|
/**
|
|
278
280
|
* Get the default file color configuration.
|
|
279
|
-
* This returns the configuration loaded from files.json.
|
|
281
|
+
* This returns the configuration loaded from files.json merged with local dev overrides.
|
|
280
282
|
*/
|
|
281
283
|
function getDefaultFileColorConfig() {
|
|
282
|
-
return file_city_builder_1.defaultFileColorConfig;
|
|
284
|
+
return (0, fileColorOverrides_1.mergeFileColorConfig)(file_city_builder_1.defaultFileColorConfig, fileColorOverrides_1.devFileColorOverrides);
|
|
283
285
|
}
|
|
284
286
|
/**
|
|
285
287
|
* Get a simple color mapping from the configuration.
|
|
@@ -289,7 +291,8 @@ function getDefaultFileColorConfig() {
|
|
|
289
291
|
* @returns Record mapping file extensions to hex color strings
|
|
290
292
|
*/
|
|
291
293
|
function getFileColorMapping(config) {
|
|
292
|
-
const colorConfig = config ||
|
|
294
|
+
const colorConfig = config ||
|
|
295
|
+
(0, fileColorOverrides_1.mergeFileColorConfig)(file_city_builder_1.defaultFileColorConfig, fileColorOverrides_1.devFileColorOverrides);
|
|
293
296
|
return Object.entries(colorConfig.suffixConfigs).reduce((acc, [extension, suffixConfig]) => {
|
|
294
297
|
acc[extension] = suffixConfig.primary.color;
|
|
295
298
|
return acc;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FileSuffixColorConfig } from './fileColorHighlightLayers';
|
|
2
|
+
/**
|
|
3
|
+
* Development overrides for file color configuration.
|
|
4
|
+
* Add new file extensions here during development, then move them to
|
|
5
|
+
* @principal-ai/file-city-builder/src/config/files.json when ready to publish.
|
|
6
|
+
*
|
|
7
|
+
* These overrides will merge with (and take precedence over) the default config.
|
|
8
|
+
*/
|
|
9
|
+
export declare const devFileColorOverrides: Partial<FileSuffixColorConfig>;
|
|
10
|
+
/**
|
|
11
|
+
* Merges the default file color configuration with local development overrides.
|
|
12
|
+
* Overrides take precedence over defaults.
|
|
13
|
+
*
|
|
14
|
+
* @param defaultConfig - The default configuration from the builder package
|
|
15
|
+
* @param overrides - Local development overrides
|
|
16
|
+
* @returns Merged configuration with overrides applied
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeFileColorConfig(defaultConfig: FileSuffixColorConfig, overrides: Partial<FileSuffixColorConfig>): FileSuffixColorConfig;
|
|
19
|
+
//# sourceMappingURL=fileColorOverrides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileColorOverrides.d.ts","sourceRoot":"","sources":["../../src/utils/fileColorOverrides.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,CAoBhE,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,qBAAqB,EACpC,SAAS,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACxC,qBAAqB,CAWvB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.devFileColorOverrides = void 0;
|
|
4
|
+
exports.mergeFileColorConfig = mergeFileColorConfig;
|
|
5
|
+
/**
|
|
6
|
+
* Development overrides for file color configuration.
|
|
7
|
+
* Add new file extensions here during development, then move them to
|
|
8
|
+
* @principal-ai/file-city-builder/src/config/files.json when ready to publish.
|
|
9
|
+
*
|
|
10
|
+
* These overrides will merge with (and take precedence over) the default config.
|
|
11
|
+
*/
|
|
12
|
+
exports.devFileColorOverrides = {
|
|
13
|
+
suffixConfigs: {
|
|
14
|
+
// Add your new file extensions here during development
|
|
15
|
+
"package.json": {
|
|
16
|
+
primary: {
|
|
17
|
+
color: "#CB3837",
|
|
18
|
+
renderStrategy: "fill",
|
|
19
|
+
opacity: 1.0,
|
|
20
|
+
},
|
|
21
|
+
icon: {
|
|
22
|
+
type: "lucide",
|
|
23
|
+
name: "Package",
|
|
24
|
+
color: "#ffffff",
|
|
25
|
+
size: 0.6,
|
|
26
|
+
},
|
|
27
|
+
displayName: "Package",
|
|
28
|
+
description: "npm package.json files",
|
|
29
|
+
category: "Configuration",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Merges the default file color configuration with local development overrides.
|
|
35
|
+
* Overrides take precedence over defaults.
|
|
36
|
+
*
|
|
37
|
+
* @param defaultConfig - The default configuration from the builder package
|
|
38
|
+
* @param overrides - Local development overrides
|
|
39
|
+
* @returns Merged configuration with overrides applied
|
|
40
|
+
*/
|
|
41
|
+
function mergeFileColorConfig(defaultConfig, overrides) {
|
|
42
|
+
return {
|
|
43
|
+
...defaultConfig,
|
|
44
|
+
...overrides,
|
|
45
|
+
suffixConfigs: {
|
|
46
|
+
...defaultConfig.suffixConfigs,
|
|
47
|
+
...(overrides.suffixConfigs || {}),
|
|
48
|
+
},
|
|
49
|
+
// Keep default config's defaultConfig unless explicitly overridden
|
|
50
|
+
...(overrides.defaultConfig && { defaultConfig: overrides.defaultConfig }),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FileSuffixColorConfig, FileTypeIconConfig } from './fileColorHighlightLayers';
|
|
2
|
+
/**
|
|
3
|
+
* Extract icon configurations from file color config
|
|
4
|
+
* This creates a map of file extensions to their icon configs
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractIconConfig(colorConfig: FileSuffixColorConfig): Map<string, FileTypeIconConfig>;
|
|
7
|
+
/**
|
|
8
|
+
* Get icon configuration for a file path
|
|
9
|
+
* Uses same matching logic as file color system
|
|
10
|
+
*/
|
|
11
|
+
export declare function getFileTypeIcon(filePath: string, iconMap: Map<string, FileTypeIconConfig>): FileTypeIconConfig | null;
|
|
12
|
+
/**
|
|
13
|
+
* Draw a file type icon on the canvas
|
|
14
|
+
*/
|
|
15
|
+
export declare function drawFileTypeIcon(ctx: CanvasRenderingContext2D, icon: FileTypeIconConfig, x: number, y: number, buildingWidth: number, buildingHeight: number): void;
|
|
16
|
+
//# sourceMappingURL=fileTypeIcons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileTypeIcons.d.ts","sourceRoot":"","sources":["../../src/utils/fileTypeIcons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGvF;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,qBAAqB,GACjC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAUjC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GACvC,kBAAkB,GAAG,IAAI,CA0B3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,kBAAkB,EACxB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,QAkDvB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractIconConfig = extractIconConfig;
|
|
4
|
+
exports.getFileTypeIcon = getFileTypeIcon;
|
|
5
|
+
exports.drawFileTypeIcon = drawFileTypeIcon;
|
|
6
|
+
const lucideIconConverter_1 = require("./lucideIconConverter");
|
|
7
|
+
/**
|
|
8
|
+
* Extract icon configurations from file color config
|
|
9
|
+
* This creates a map of file extensions to their icon configs
|
|
10
|
+
*/
|
|
11
|
+
function extractIconConfig(colorConfig) {
|
|
12
|
+
const iconMap = new Map();
|
|
13
|
+
Object.entries(colorConfig.suffixConfigs).forEach(([suffix, config]) => {
|
|
14
|
+
if (config.icon) {
|
|
15
|
+
iconMap.set(suffix, config.icon);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return iconMap;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get icon configuration for a file path
|
|
22
|
+
* Uses same matching logic as file color system
|
|
23
|
+
*/
|
|
24
|
+
function getFileTypeIcon(filePath, iconMap) {
|
|
25
|
+
const lastSlash = filePath.lastIndexOf('/');
|
|
26
|
+
const fileName = lastSlash === -1 ? filePath : filePath.substring(lastSlash + 1);
|
|
27
|
+
// Check exact filename match first (e.g., "package.json")
|
|
28
|
+
if (iconMap.has(fileName)) {
|
|
29
|
+
return iconMap.get(fileName) || null;
|
|
30
|
+
}
|
|
31
|
+
const lastDot = fileName.lastIndexOf('.');
|
|
32
|
+
if (lastDot === -1 || lastDot === fileName.length - 1) {
|
|
33
|
+
// No extension or ends with dot
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
// Check compound extensions (longest first) - same as fileColorHighlightLayers
|
|
37
|
+
const sortedExtensions = Array.from(iconMap.keys()).sort((a, b) => b.length - a.length);
|
|
38
|
+
const lowerFileName = fileName.toLowerCase();
|
|
39
|
+
for (const ext of sortedExtensions) {
|
|
40
|
+
if (ext.startsWith('.') && lowerFileName.endsWith(ext)) {
|
|
41
|
+
return iconMap.get(ext) || null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Draw a file type icon on the canvas
|
|
48
|
+
*/
|
|
49
|
+
function drawFileTypeIcon(ctx, icon, x, y, buildingWidth, buildingHeight) {
|
|
50
|
+
ctx.save();
|
|
51
|
+
if (icon.type === 'emoji') {
|
|
52
|
+
// Calculate size as percentage of building
|
|
53
|
+
const sizeScale = icon.size || 0.75;
|
|
54
|
+
const emojiSize = Math.min(buildingWidth, buildingHeight) * sizeScale;
|
|
55
|
+
// Glow effect
|
|
56
|
+
if (icon.glow) {
|
|
57
|
+
ctx.shadowColor = icon.color || '#00D8FF';
|
|
58
|
+
ctx.shadowBlur = 8;
|
|
59
|
+
}
|
|
60
|
+
ctx.fillStyle = icon.color || '#ffffff';
|
|
61
|
+
ctx.font = `${emojiSize}px Arial`;
|
|
62
|
+
ctx.textAlign = 'center';
|
|
63
|
+
ctx.textBaseline = 'middle';
|
|
64
|
+
ctx.fillText(icon.name, x, y);
|
|
65
|
+
}
|
|
66
|
+
else if (icon.type === 'lucide') {
|
|
67
|
+
// Calculate size as percentage of building (same as emoji)
|
|
68
|
+
const sizeScale = icon.size || 0.5;
|
|
69
|
+
const actualIconSize = Math.min(buildingWidth, buildingHeight) * sizeScale;
|
|
70
|
+
// Round to nearest 4px to reduce cache misses and prevent flickering
|
|
71
|
+
const roundedIconSize = Math.round(actualIconSize / 4) * 4;
|
|
72
|
+
const svgSize = Math.max(16, Math.min(roundedIconSize, 64)); // Clamp between 16-64px for SVG generation
|
|
73
|
+
// Optional background circle
|
|
74
|
+
if (icon.backgroundColor) {
|
|
75
|
+
const bgRadius = actualIconSize * 0.7;
|
|
76
|
+
ctx.fillStyle = icon.backgroundColor;
|
|
77
|
+
ctx.beginPath();
|
|
78
|
+
ctx.arc(x, y, bgRadius, 0, Math.PI * 2);
|
|
79
|
+
ctx.fill();
|
|
80
|
+
}
|
|
81
|
+
// Draw Lucide icon - use rounded size for cache, scale to actual size
|
|
82
|
+
const img = (0, lucideIconConverter_1.getLucideIconImage)(icon.name, icon.color || '#ffffff', svgSize);
|
|
83
|
+
if (img) {
|
|
84
|
+
const iconX = x - actualIconSize / 2;
|
|
85
|
+
const iconY = y - actualIconSize / 2;
|
|
86
|
+
// Scale the cached icon to actual size
|
|
87
|
+
ctx.drawImage(img, iconX, iconY, actualIconSize, actualIconSize);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
ctx.restore();
|
|
91
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lucideIconConverter.d.ts","sourceRoot":"","sources":["../../src/utils/lucideIconConverter.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lucideIconConverter.d.ts","sourceRoot":"","sources":["../../src/utils/lucideIconConverter.tsx"],"names":[],"mappings":"AA4BA;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAgB,EACvB,IAAI,GAAE,MAAW,GAChB,MAAM,GAAG,IAAI,CAoCf;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,SAejC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAgB,EACvB,IAAI,GAAE,MAAW,GAChB,gBAAgB,GAAG,IAAI,CAuBzB;AAED;;GAEG;AACH,wBAAgB,cAAc,SAG7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}
|
|
@@ -18,6 +18,17 @@ const ICON_PATHS = {
|
|
|
18
18
|
FileText: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>',
|
|
19
19
|
File: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/>',
|
|
20
20
|
Folder: '<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/>',
|
|
21
|
+
Package: '<path d="m7.5 4.27 9 5.15"/><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>',
|
|
22
|
+
BookOpen: '<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>',
|
|
23
|
+
BookText: '<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/><path d="M8 7h6"/><path d="M8 11h8"/>',
|
|
24
|
+
ScrollText: '<path d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"/><path d="M19 17V5a2 2 0 0 0-2-2H4"/><path d="M15 8h-5"/><path d="M15 12h-5"/>',
|
|
25
|
+
Settings: '<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>',
|
|
26
|
+
Home: '<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>',
|
|
27
|
+
Lock: '<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
28
|
+
GitBranch: '<line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>',
|
|
29
|
+
EyeOff: '<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>',
|
|
30
|
+
Key: '<circle cx="7.5" cy="15.5" r="5.5"/><path d="m21 2-9.6 9.6"/><path d="m15.5 7.5 3 3L22 7l-3-3"/>',
|
|
31
|
+
Atom: '<circle cx="12" cy="12" r="1"/><path d="M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z"/><path d="M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z"/>',
|
|
21
32
|
};
|
|
22
33
|
/**
|
|
23
34
|
* Convert a Lucide icon name to an SVG data URL that can be used in Canvas
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@principal-ai/file-city-react",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "React components for File City visualization",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@principal-ade/industry-theme": "^0.1.3",
|
|
16
16
|
"@principal-ai/alexandria-core-library": "^0.1.36",
|
|
17
|
-
"@principal-ai/file-city-builder": "^0.3.
|
|
17
|
+
"@principal-ai/file-city-builder": "^0.3.3",
|
|
18
18
|
"lucide-react": "^0.563.0",
|
|
19
19
|
"reactflow": "^11.11.4"
|
|
20
20
|
},
|
|
@@ -21,6 +21,8 @@ import {
|
|
|
21
21
|
SelectiveRenderOptions,
|
|
22
22
|
} from '@principal-ai/file-city-builder';
|
|
23
23
|
import { MapInteractionState, MapDisplayOptions } from '../types/react-types';
|
|
24
|
+
import { getDefaultFileColorConfig } from '../utils/fileColorHighlightLayers';
|
|
25
|
+
import { extractIconConfig } from '../utils/fileTypeIcons';
|
|
24
26
|
|
|
25
27
|
const DEFAULT_DISPLAY_OPTIONS: MapDisplayOptions = {
|
|
26
28
|
showGrid: false,
|
|
@@ -326,6 +328,12 @@ function ArchitectureMapHighlightLayersInner({
|
|
|
326
328
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
327
329
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
328
330
|
|
|
331
|
+
// Extract icon configuration from file color config
|
|
332
|
+
const iconMap = useMemo(() => {
|
|
333
|
+
const colorConfig = getDefaultFileColorConfig();
|
|
334
|
+
return extractIconConfig(colorConfig);
|
|
335
|
+
}, []);
|
|
336
|
+
|
|
329
337
|
const [interactionState, setInteractionState] = useState<MapInteractionState>({
|
|
330
338
|
hoveredDistrict: null,
|
|
331
339
|
hoveredBuilding: null,
|
|
@@ -1211,6 +1219,7 @@ function ArchitectureMapHighlightLayersInner({
|
|
|
1211
1219
|
showFileTypeIcons,
|
|
1212
1220
|
buildingBorderRadius,
|
|
1213
1221
|
layerIndex, // Pre-built index for O(1) lookups
|
|
1222
|
+
iconMap, // Icon configuration map for file type icons
|
|
1214
1223
|
);
|
|
1215
1224
|
|
|
1216
1225
|
// Performance monitoring end available for debugging
|
|
@@ -1246,6 +1255,7 @@ function ArchitectureMapHighlightLayersInner({
|
|
|
1246
1255
|
visibleBuildingsMemo,
|
|
1247
1256
|
abstractedPathsSet,
|
|
1248
1257
|
layerIndex,
|
|
1258
|
+
iconMap,
|
|
1249
1259
|
]);
|
|
1250
1260
|
|
|
1251
1261
|
// Optimized hit testing
|
package/src/index.ts
CHANGED
|
@@ -33,8 +33,15 @@ export type {
|
|
|
33
33
|
ColorLayerConfig,
|
|
34
34
|
FileSuffixConfig,
|
|
35
35
|
FileSuffixColorConfig,
|
|
36
|
+
FileTypeIconConfig,
|
|
36
37
|
} from './utils/fileColorHighlightLayers';
|
|
37
38
|
|
|
39
|
+
// File color override utilities for development
|
|
40
|
+
export { devFileColorOverrides, mergeFileColorConfig } from './utils/fileColorOverrides';
|
|
41
|
+
|
|
42
|
+
// File type icon utilities
|
|
43
|
+
export { extractIconConfig, getFileTypeIcon, drawFileTypeIcon } from './utils/fileTypeIcons';
|
|
44
|
+
|
|
38
45
|
// Re-export commonly used types from builder
|
|
39
46
|
export type {
|
|
40
47
|
CityData,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { CityBuilding, CityDistrict } from '@principal-ai/file-city-builder';
|
|
2
2
|
import { getLucideIconImage } from '../../utils/lucideIconConverter';
|
|
3
|
+
import { FileTypeIconConfig } from '../../utils/fileColorHighlightLayers';
|
|
4
|
+
import { getFileTypeIcon, drawFileTypeIcon } from '../../utils/fileTypeIcons';
|
|
3
5
|
|
|
4
6
|
// Layer types and interfaces
|
|
5
7
|
export type LayerRenderStrategy =
|
|
@@ -814,47 +816,6 @@ export function drawLayeredDistricts(
|
|
|
814
816
|
});
|
|
815
817
|
}
|
|
816
818
|
|
|
817
|
-
/**
|
|
818
|
-
* Draw a React symbol (⚛) at the given position
|
|
819
|
-
*/
|
|
820
|
-
function drawReactSymbol(
|
|
821
|
-
ctx: CanvasRenderingContext2D,
|
|
822
|
-
x: number,
|
|
823
|
-
y: number,
|
|
824
|
-
size: number,
|
|
825
|
-
color: string = '#00D8FF',
|
|
826
|
-
glow: boolean = true,
|
|
827
|
-
) {
|
|
828
|
-
ctx.save();
|
|
829
|
-
|
|
830
|
-
// Position and setup
|
|
831
|
-
ctx.translate(x, y);
|
|
832
|
-
|
|
833
|
-
// Glow effect for React symbol
|
|
834
|
-
if (glow) {
|
|
835
|
-
ctx.shadowColor = color;
|
|
836
|
-
ctx.shadowBlur = 8;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
// Draw the React symbol (⚛)
|
|
840
|
-
ctx.fillStyle = color;
|
|
841
|
-
ctx.font = `${size}px Arial`;
|
|
842
|
-
ctx.textAlign = 'center';
|
|
843
|
-
ctx.textBaseline = 'middle';
|
|
844
|
-
ctx.fillText('⚛', 0, 0);
|
|
845
|
-
|
|
846
|
-
ctx.restore();
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
/**
|
|
850
|
-
* Check if a file is a React file (JSX/TSX)
|
|
851
|
-
*/
|
|
852
|
-
function isReactFile(fileExtension?: string): boolean {
|
|
853
|
-
if (!fileExtension) return false;
|
|
854
|
-
const ext = fileExtension.toLowerCase();
|
|
855
|
-
return ext === '.jsx' || ext === '.tsx';
|
|
856
|
-
}
|
|
857
|
-
|
|
858
819
|
// Draw buildings with layer support
|
|
859
820
|
export function drawLayeredBuildings(
|
|
860
821
|
ctx: CanvasRenderingContext2D,
|
|
@@ -870,6 +831,7 @@ export function drawLayeredBuildings(
|
|
|
870
831
|
showFileTypeIcons?: boolean,
|
|
871
832
|
borderRadius: number = 0, // Border radius for buildings (default: 0 - sharp corners)
|
|
872
833
|
layerIndex?: LayerIndex, // Optional pre-built index for performance
|
|
834
|
+
iconMap?: Map<string, FileTypeIconConfig>, // Optional icon configuration map
|
|
873
835
|
) {
|
|
874
836
|
// Build index once for all buildings (O(n) instead of O(n²))
|
|
875
837
|
const index = layerIndex || new LayerIndex(layers);
|
|
@@ -967,16 +929,12 @@ export function drawLayeredBuildings(
|
|
|
967
929
|
}
|
|
968
930
|
}
|
|
969
931
|
|
|
970
|
-
// Draw
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
const reactSize = Math.min(width, height) * 0.75;
|
|
977
|
-
const reactX = pos.x;
|
|
978
|
-
const reactY = pos.y;
|
|
979
|
-
drawReactSymbol(ctx, reactX, reactY, reactSize);
|
|
932
|
+
// Draw file type icon if enabled and icon map is provided
|
|
933
|
+
if (showFileTypeIcons && iconMap) {
|
|
934
|
+
const iconConfig = getFileTypeIcon(building.path, iconMap);
|
|
935
|
+
if (iconConfig) {
|
|
936
|
+
drawFileTypeIcon(ctx, iconConfig, pos.x, pos.y, width, height);
|
|
937
|
+
}
|
|
980
938
|
}
|
|
981
939
|
|
|
982
940
|
// Draw filename if enabled
|
|
@@ -26,7 +26,10 @@ type Story = StoryObj<typeof meta>;
|
|
|
26
26
|
const allFileTypes = [
|
|
27
27
|
// Frontend
|
|
28
28
|
{ path: 'frontend/typescript/index.ts', size: 1500 },
|
|
29
|
+
{ path: 'frontend/typescript/index.tsx', size: 1700 },
|
|
29
30
|
{ path: 'frontend/typescript/App.tsx', size: 3200 },
|
|
31
|
+
{ path: 'frontend/javascript/index.js', size: 1300 },
|
|
32
|
+
{ path: 'frontend/javascript/index.jsx', size: 1500 },
|
|
30
33
|
{ path: 'frontend/javascript/script.js', size: 1200 },
|
|
31
34
|
{ path: 'frontend/javascript/Component.jsx', size: 1800 },
|
|
32
35
|
{ path: 'frontend/html/index.html', size: 2000 },
|
|
@@ -71,7 +74,15 @@ const allFileTypes = [
|
|
|
71
74
|
{ path: 'tests/specs/Form.spec.jsx', size: 2000 },
|
|
72
75
|
{ path: 'tests/snapshots/component.snap', size: 3500 },
|
|
73
76
|
|
|
77
|
+
// Storybook - Component documentation
|
|
78
|
+
{ path: 'stories/Button.stories.ts', size: 2200 },
|
|
79
|
+
{ path: 'stories/Card.stories.tsx', size: 2600 },
|
|
80
|
+
{ path: 'stories/Input.stories.js', size: 1800 },
|
|
81
|
+
{ path: 'stories/Modal.stories.jsx', size: 2400 },
|
|
82
|
+
|
|
74
83
|
// Data & Config
|
|
84
|
+
{ path: 'config/package.json', size: 2400 },
|
|
85
|
+
{ path: 'config/tsconfig.json', size: 1800 },
|
|
75
86
|
{ path: 'config/data.json', size: 1200 },
|
|
76
87
|
{ path: 'config/settings.yaml', size: 1000 },
|
|
77
88
|
{ path: 'config/app.yml', size: 950 },
|
|
@@ -81,6 +92,7 @@ const allFileTypes = [
|
|
|
81
92
|
|
|
82
93
|
// Documentation
|
|
83
94
|
{ path: 'docs/README.md', size: 4200 },
|
|
95
|
+
{ path: 'docs/CHANGELOG.md', size: 3600 },
|
|
84
96
|
{ path: 'docs/API.mdx', size: 3800 },
|
|
85
97
|
{ path: 'docs/notes.txt', size: 600 },
|
|
86
98
|
|
|
@@ -128,11 +140,26 @@ const allFileTypes = [
|
|
|
128
140
|
|
|
129
141
|
// Lock files
|
|
130
142
|
{ path: 'package-lock.json', size: 256000 },
|
|
131
|
-
{ path: 'Cargo.lock', size: 45000 },
|
|
132
143
|
{ path: 'yarn.lock', size: 128000 },
|
|
144
|
+
{ path: 'pnpm-lock.yaml', size: 180000 },
|
|
145
|
+
{ path: 'bun.lockb', size: 95000 },
|
|
146
|
+
{ path: 'Cargo.lock', size: 45000 },
|
|
147
|
+
{ path: 'Gemfile.lock', size: 32000 },
|
|
148
|
+
{ path: 'poetry.lock', size: 78000 },
|
|
149
|
+
{ path: 'composer.lock', size: 156000 },
|
|
150
|
+
{ path: 'go.sum', size: 28000 },
|
|
133
151
|
|
|
134
152
|
// Config files (exact names)
|
|
153
|
+
{ path: '.env', size: 450 },
|
|
154
|
+
{ path: '.env.example', size: 380 },
|
|
155
|
+
{ path: '.env.local', size: 420 },
|
|
156
|
+
{ path: '.env.development', size: 400 },
|
|
157
|
+
{ path: '.env.production', size: 460 },
|
|
158
|
+
{ path: '.env.test', size: 340 },
|
|
135
159
|
{ path: '.gitignore', size: 600 },
|
|
160
|
+
{ path: '.husky/pre-commit', size: 450 },
|
|
161
|
+
{ path: '.husky/commit-msg', size: 380 },
|
|
162
|
+
{ path: '.husky/pre-push', size: 420 },
|
|
136
163
|
{ path: '.dockerignore', size: 400 },
|
|
137
164
|
{ path: '.npmignore', size: 300 },
|
|
138
165
|
{ path: '.eslintignore', size: 250 },
|
|
@@ -195,7 +222,7 @@ export const AllFileTypesWithColors: Story = {
|
|
|
195
222
|
<ArchitectureMapHighlightLayers
|
|
196
223
|
cityData={cityData}
|
|
197
224
|
highlightLayers={highlightLayers}
|
|
198
|
-
showLayerControls={
|
|
225
|
+
showLayerControls={false}
|
|
199
226
|
fullSize={true}
|
|
200
227
|
canvasBackgroundColor="#0a0a0a"
|
|
201
228
|
defaultBuildingColor="#36454F"
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
LayerItem,
|
|
5
5
|
LayerRenderStrategy,
|
|
6
6
|
} from '../render/client/drawLayeredBuildings';
|
|
7
|
+
import { devFileColorOverrides, mergeFileColorConfig } from './fileColorOverrides';
|
|
7
8
|
|
|
8
9
|
// Type definitions for the color configuration
|
|
9
10
|
export interface ColorLayerConfig {
|
|
@@ -30,9 +31,19 @@ export interface ColorLayerConfig {
|
|
|
30
31
|
) => void;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
export interface FileTypeIconConfig {
|
|
35
|
+
type: 'emoji' | 'lucide';
|
|
36
|
+
name: string; // emoji character or Lucide icon name
|
|
37
|
+
color?: string;
|
|
38
|
+
backgroundColor?: string;
|
|
39
|
+
glow?: boolean;
|
|
40
|
+
size?: number; // Scale factor (0-1) relative to building size - default: 0.75 for emoji, 0.5 for lucide
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
export interface FileSuffixConfig {
|
|
34
44
|
primary: ColorLayerConfig;
|
|
35
45
|
secondary?: ColorLayerConfig;
|
|
46
|
+
icon?: FileTypeIconConfig; // Optional icon configuration independent of render strategy
|
|
36
47
|
displayName?: string;
|
|
37
48
|
description?: string;
|
|
38
49
|
category?: string;
|
|
@@ -85,8 +96,10 @@ export function createFileColorHighlightLayers(
|
|
|
85
96
|
return [];
|
|
86
97
|
}
|
|
87
98
|
|
|
88
|
-
// Use provided config or fall back to default
|
|
89
|
-
const colorConfig =
|
|
99
|
+
// Use provided config or fall back to default merged with dev overrides
|
|
100
|
+
const colorConfig =
|
|
101
|
+
config ||
|
|
102
|
+
mergeFileColorConfig(defaultFileColorConfig as FileSuffixColorConfig, devFileColorOverrides);
|
|
90
103
|
|
|
91
104
|
const { suffixConfigs, defaultConfig: defaultFileConfig, includeUnmatched = true } = colorConfig;
|
|
92
105
|
|
|
@@ -377,10 +390,10 @@ export function createFileColorHighlightLayers(
|
|
|
377
390
|
|
|
378
391
|
/**
|
|
379
392
|
* Get the default file color configuration.
|
|
380
|
-
* This returns the configuration loaded from files.json.
|
|
393
|
+
* This returns the configuration loaded from files.json merged with local dev overrides.
|
|
381
394
|
*/
|
|
382
395
|
export function getDefaultFileColorConfig(): FileSuffixColorConfig {
|
|
383
|
-
return defaultFileColorConfig as FileSuffixColorConfig;
|
|
396
|
+
return mergeFileColorConfig(defaultFileColorConfig as FileSuffixColorConfig, devFileColorOverrides);
|
|
384
397
|
}
|
|
385
398
|
|
|
386
399
|
/**
|
|
@@ -391,7 +404,9 @@ export function getDefaultFileColorConfig(): FileSuffixColorConfig {
|
|
|
391
404
|
* @returns Record mapping file extensions to hex color strings
|
|
392
405
|
*/
|
|
393
406
|
export function getFileColorMapping(config?: FileSuffixColorConfig): Record<string, string> {
|
|
394
|
-
const colorConfig =
|
|
407
|
+
const colorConfig =
|
|
408
|
+
config ||
|
|
409
|
+
mergeFileColorConfig(defaultFileColorConfig as FileSuffixColorConfig, devFileColorOverrides);
|
|
395
410
|
return Object.entries(colorConfig.suffixConfigs).reduce((acc, [extension, suffixConfig]) => {
|
|
396
411
|
acc[extension] = suffixConfig.primary.color;
|
|
397
412
|
return acc;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { FileSuffixColorConfig } from './fileColorHighlightLayers';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Development overrides for file color configuration.
|
|
5
|
+
* Add new file extensions here during development, then move them to
|
|
6
|
+
* @principal-ai/file-city-builder/src/config/files.json when ready to publish.
|
|
7
|
+
*
|
|
8
|
+
* These overrides will merge with (and take precedence over) the default config.
|
|
9
|
+
*/
|
|
10
|
+
export const devFileColorOverrides: Partial<FileSuffixColorConfig> = {
|
|
11
|
+
suffixConfigs: {
|
|
12
|
+
// Add your new file extensions here during development
|
|
13
|
+
"package.json": {
|
|
14
|
+
primary: {
|
|
15
|
+
color: "#CB3837",
|
|
16
|
+
renderStrategy: "fill",
|
|
17
|
+
opacity: 1.0,
|
|
18
|
+
},
|
|
19
|
+
icon: {
|
|
20
|
+
type: "lucide",
|
|
21
|
+
name: "Package",
|
|
22
|
+
color: "#ffffff",
|
|
23
|
+
size: 0.6,
|
|
24
|
+
},
|
|
25
|
+
displayName: "Package",
|
|
26
|
+
description: "npm package.json files",
|
|
27
|
+
category: "Configuration",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Merges the default file color configuration with local development overrides.
|
|
34
|
+
* Overrides take precedence over defaults.
|
|
35
|
+
*
|
|
36
|
+
* @param defaultConfig - The default configuration from the builder package
|
|
37
|
+
* @param overrides - Local development overrides
|
|
38
|
+
* @returns Merged configuration with overrides applied
|
|
39
|
+
*/
|
|
40
|
+
export function mergeFileColorConfig(
|
|
41
|
+
defaultConfig: FileSuffixColorConfig,
|
|
42
|
+
overrides: Partial<FileSuffixColorConfig>,
|
|
43
|
+
): FileSuffixColorConfig {
|
|
44
|
+
return {
|
|
45
|
+
...defaultConfig,
|
|
46
|
+
...overrides,
|
|
47
|
+
suffixConfigs: {
|
|
48
|
+
...defaultConfig.suffixConfigs,
|
|
49
|
+
...(overrides.suffixConfigs || {}),
|
|
50
|
+
},
|
|
51
|
+
// Keep default config's defaultConfig unless explicitly overridden
|
|
52
|
+
...(overrides.defaultConfig && { defaultConfig: overrides.defaultConfig }),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { FileSuffixColorConfig, FileTypeIconConfig } from './fileColorHighlightLayers';
|
|
2
|
+
import { getLucideIconImage } from './lucideIconConverter';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extract icon configurations from file color config
|
|
6
|
+
* This creates a map of file extensions to their icon configs
|
|
7
|
+
*/
|
|
8
|
+
export function extractIconConfig(
|
|
9
|
+
colorConfig: FileSuffixColorConfig,
|
|
10
|
+
): Map<string, FileTypeIconConfig> {
|
|
11
|
+
const iconMap = new Map<string, FileTypeIconConfig>();
|
|
12
|
+
|
|
13
|
+
Object.entries(colorConfig.suffixConfigs).forEach(([suffix, config]) => {
|
|
14
|
+
if (config.icon) {
|
|
15
|
+
iconMap.set(suffix, config.icon);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return iconMap;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get icon configuration for a file path
|
|
24
|
+
* Uses same matching logic as file color system
|
|
25
|
+
*/
|
|
26
|
+
export function getFileTypeIcon(
|
|
27
|
+
filePath: string,
|
|
28
|
+
iconMap: Map<string, FileTypeIconConfig>,
|
|
29
|
+
): FileTypeIconConfig | null {
|
|
30
|
+
const lastSlash = filePath.lastIndexOf('/');
|
|
31
|
+
const fileName = lastSlash === -1 ? filePath : filePath.substring(lastSlash + 1);
|
|
32
|
+
|
|
33
|
+
// Check exact filename match first (e.g., "package.json")
|
|
34
|
+
if (iconMap.has(fileName)) {
|
|
35
|
+
return iconMap.get(fileName) || null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const lastDot = fileName.lastIndexOf('.');
|
|
39
|
+
if (lastDot === -1 || lastDot === fileName.length - 1) {
|
|
40
|
+
// No extension or ends with dot
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Check compound extensions (longest first) - same as fileColorHighlightLayers
|
|
45
|
+
const sortedExtensions = Array.from(iconMap.keys()).sort((a, b) => b.length - a.length);
|
|
46
|
+
|
|
47
|
+
const lowerFileName = fileName.toLowerCase();
|
|
48
|
+
for (const ext of sortedExtensions) {
|
|
49
|
+
if (ext.startsWith('.') && lowerFileName.endsWith(ext)) {
|
|
50
|
+
return iconMap.get(ext) || null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Draw a file type icon on the canvas
|
|
59
|
+
*/
|
|
60
|
+
export function drawFileTypeIcon(
|
|
61
|
+
ctx: CanvasRenderingContext2D,
|
|
62
|
+
icon: FileTypeIconConfig,
|
|
63
|
+
x: number,
|
|
64
|
+
y: number,
|
|
65
|
+
buildingWidth: number,
|
|
66
|
+
buildingHeight: number,
|
|
67
|
+
) {
|
|
68
|
+
ctx.save();
|
|
69
|
+
|
|
70
|
+
if (icon.type === 'emoji') {
|
|
71
|
+
// Calculate size as percentage of building
|
|
72
|
+
const sizeScale = icon.size || 0.75;
|
|
73
|
+
const emojiSize = Math.min(buildingWidth, buildingHeight) * sizeScale;
|
|
74
|
+
|
|
75
|
+
// Glow effect
|
|
76
|
+
if (icon.glow) {
|
|
77
|
+
ctx.shadowColor = icon.color || '#00D8FF';
|
|
78
|
+
ctx.shadowBlur = 8;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ctx.fillStyle = icon.color || '#ffffff';
|
|
82
|
+
ctx.font = `${emojiSize}px Arial`;
|
|
83
|
+
ctx.textAlign = 'center';
|
|
84
|
+
ctx.textBaseline = 'middle';
|
|
85
|
+
ctx.fillText(icon.name, x, y);
|
|
86
|
+
} else if (icon.type === 'lucide') {
|
|
87
|
+
// Calculate size as percentage of building (same as emoji)
|
|
88
|
+
const sizeScale = icon.size || 0.5;
|
|
89
|
+
const actualIconSize = Math.min(buildingWidth, buildingHeight) * sizeScale;
|
|
90
|
+
|
|
91
|
+
// Round to nearest 4px to reduce cache misses and prevent flickering
|
|
92
|
+
const roundedIconSize = Math.round(actualIconSize / 4) * 4;
|
|
93
|
+
const svgSize = Math.max(16, Math.min(roundedIconSize, 64)); // Clamp between 16-64px for SVG generation
|
|
94
|
+
|
|
95
|
+
// Optional background circle
|
|
96
|
+
if (icon.backgroundColor) {
|
|
97
|
+
const bgRadius = actualIconSize * 0.7;
|
|
98
|
+
ctx.fillStyle = icon.backgroundColor;
|
|
99
|
+
ctx.beginPath();
|
|
100
|
+
ctx.arc(x, y, bgRadius, 0, Math.PI * 2);
|
|
101
|
+
ctx.fill();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Draw Lucide icon - use rounded size for cache, scale to actual size
|
|
105
|
+
const img = getLucideIconImage(icon.name, icon.color || '#ffffff', svgSize);
|
|
106
|
+
|
|
107
|
+
if (img) {
|
|
108
|
+
const iconX = x - actualIconSize / 2;
|
|
109
|
+
const iconY = y - actualIconSize / 2;
|
|
110
|
+
// Scale the cached icon to actual size
|
|
111
|
+
ctx.drawImage(img, iconX, iconY, actualIconSize, actualIconSize);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
ctx.restore();
|
|
116
|
+
}
|
|
@@ -13,6 +13,17 @@ const ICON_PATHS: Record<string, string> = {
|
|
|
13
13
|
FileText: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>',
|
|
14
14
|
File: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/>',
|
|
15
15
|
Folder: '<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/>',
|
|
16
|
+
Package: '<path d="m7.5 4.27 9 5.15"/><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>',
|
|
17
|
+
BookOpen: '<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>',
|
|
18
|
+
BookText: '<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/><path d="M8 7h6"/><path d="M8 11h8"/>',
|
|
19
|
+
ScrollText: '<path d="M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4"/><path d="M19 17V5a2 2 0 0 0-2-2H4"/><path d="M15 8h-5"/><path d="M15 12h-5"/>',
|
|
20
|
+
Settings: '<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>',
|
|
21
|
+
Home: '<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>',
|
|
22
|
+
Lock: '<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
|
23
|
+
GitBranch: '<line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>',
|
|
24
|
+
EyeOff: '<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>',
|
|
25
|
+
Key: '<circle cx="7.5" cy="15.5" r="5.5"/><path d="m21 2-9.6 9.6"/><path d="m15.5 7.5 3 3L22 7l-3-3"/>',
|
|
26
|
+
Atom: '<circle cx="12" cy="12" r="1"/><path d="M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z"/><path d="M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z"/>',
|
|
16
27
|
};
|
|
17
28
|
|
|
18
29
|
/**
|