@principal-ai/file-city-react 0.5.2 → 0.5.4
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 +7 -2
- package/dist/components/FileCity3D/FileCity3D.d.ts +104 -0
- package/dist/components/FileCity3D/FileCity3D.d.ts.map +1 -0
- package/dist/components/FileCity3D/FileCity3D.js +547 -0
- package/dist/components/FileCity3D/index.d.ts +6 -0
- package/dist/components/FileCity3D/index.d.ts.map +1 -0
- package/dist/components/FileCity3D/index.js +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/package.json +8 -3
- package/src/components/ArchitectureMapHighlightLayers.tsx +8 -2
- package/src/components/FileCity3D/FileCity3D.tsx +1011 -0
- package/src/components/FileCity3D/index.ts +16 -0
- package/src/index.ts +11 -0
- package/src/stories/FileCity3D.stories.tsx +480 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileCity3D - 3D visualization component
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { FileCity3D, resetCamera } from './FileCity3D';
|
|
6
|
+
export type {
|
|
7
|
+
FileCity3DProps,
|
|
8
|
+
AnimationConfig,
|
|
9
|
+
HighlightLayer,
|
|
10
|
+
HighlightItem,
|
|
11
|
+
IsolationMode,
|
|
12
|
+
HeightScaling,
|
|
13
|
+
CityData,
|
|
14
|
+
CityBuilding,
|
|
15
|
+
CityDistrict,
|
|
16
|
+
} from './FileCity3D';
|
package/src/index.ts
CHANGED
|
@@ -70,3 +70,14 @@ export {
|
|
|
70
70
|
|
|
71
71
|
// Re-export theme utilities for consumers
|
|
72
72
|
export { ThemeProvider, useTheme } from '@principal-ade/industry-theme';
|
|
73
|
+
|
|
74
|
+
// 3D visualization component
|
|
75
|
+
export { FileCity3D, resetCamera } from './components/FileCity3D';
|
|
76
|
+
export type {
|
|
77
|
+
FileCity3DProps,
|
|
78
|
+
AnimationConfig,
|
|
79
|
+
HighlightLayer as FileCity3DHighlightLayer,
|
|
80
|
+
HighlightItem as FileCity3DHighlightItem,
|
|
81
|
+
IsolationMode,
|
|
82
|
+
HeightScaling,
|
|
83
|
+
} from './components/FileCity3D';
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { ThemeProvider } from '@principal-ade/industry-theme';
|
|
4
|
+
import { FileCity3D, type CityData, type CityBuilding, type CityDistrict } from '../components/FileCity3D';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof FileCity3D> = {
|
|
7
|
+
title: 'Components/FileCity3D',
|
|
8
|
+
component: FileCity3D,
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<ThemeProvider>
|
|
12
|
+
<Story />
|
|
13
|
+
</ThemeProvider>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'fullscreen',
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
width: { control: 'text' },
|
|
21
|
+
height: { control: 'number' },
|
|
22
|
+
showControls: { control: 'boolean' },
|
|
23
|
+
heightScaling: { control: 'select', options: ['logarithmic', 'linear'] },
|
|
24
|
+
isolationMode: { control: 'select', options: ['none', 'transparent', 'collapse', 'hide'] },
|
|
25
|
+
dimOpacity: { control: { type: 'range', min: 0, max: 1, step: 0.05 } },
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof FileCity3D>;
|
|
31
|
+
|
|
32
|
+
// Code extensions use lineCount for height
|
|
33
|
+
const CODE_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'py', 'rs', 'go', 'java'];
|
|
34
|
+
const NON_CODE_EXTENSIONS = ['json', 'css', 'md', 'yaml', 'svg', 'png'];
|
|
35
|
+
|
|
36
|
+
// Helper to generate sample buildings
|
|
37
|
+
function generateBuildings(
|
|
38
|
+
basePath: string,
|
|
39
|
+
count: number,
|
|
40
|
+
startX: number,
|
|
41
|
+
startZ: number,
|
|
42
|
+
areaWidth: number,
|
|
43
|
+
areaDepth: number
|
|
44
|
+
): CityBuilding[] {
|
|
45
|
+
const buildings: CityBuilding[] = [];
|
|
46
|
+
const allExtensions = [...CODE_EXTENSIONS, ...NON_CODE_EXTENSIONS];
|
|
47
|
+
const cols = Math.ceil(Math.sqrt(count));
|
|
48
|
+
|
|
49
|
+
for (let i = 0; i < count; i++) {
|
|
50
|
+
const col = i % cols;
|
|
51
|
+
const row = Math.floor(i / cols);
|
|
52
|
+
const ext = allExtensions[i % allExtensions.length];
|
|
53
|
+
const isCode = CODE_EXTENSIONS.includes(ext);
|
|
54
|
+
|
|
55
|
+
// Code files: logarithmic distribution of line counts (20-3000 lines)
|
|
56
|
+
const lineCount = isCode
|
|
57
|
+
? Math.floor(Math.exp(Math.random() * Math.log(3000 - 20) + Math.log(20)))
|
|
58
|
+
: undefined;
|
|
59
|
+
const size = isCode
|
|
60
|
+
? lineCount! * 40
|
|
61
|
+
: Math.floor(Math.random() * 200000) + 1000;
|
|
62
|
+
|
|
63
|
+
buildings.push({
|
|
64
|
+
path: `${basePath}/file${i}.${ext}`,
|
|
65
|
+
position: {
|
|
66
|
+
x: startX + (col / cols) * areaWidth + areaWidth / cols / 2,
|
|
67
|
+
y: 0,
|
|
68
|
+
z: startZ + (row / cols) * areaDepth + areaDepth / cols / 2,
|
|
69
|
+
},
|
|
70
|
+
dimensions: [(areaWidth / cols) * 0.7, 10, (areaDepth / cols) * 0.7],
|
|
71
|
+
type: 'file',
|
|
72
|
+
fileExtension: ext,
|
|
73
|
+
size,
|
|
74
|
+
lineCount,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return buildings;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Sample city data
|
|
82
|
+
const sampleCityData: CityData = {
|
|
83
|
+
buildings: [
|
|
84
|
+
...generateBuildings('src', 12, 0, 0, 40, 40),
|
|
85
|
+
...generateBuildings('src/components', 8, 50, 0, 30, 30),
|
|
86
|
+
...generateBuildings('src/utils', 6, 50, 40, 25, 25),
|
|
87
|
+
...generateBuildings('tests', 5, 0, 50, 30, 20),
|
|
88
|
+
],
|
|
89
|
+
districts: [
|
|
90
|
+
{
|
|
91
|
+
path: 'src',
|
|
92
|
+
worldBounds: { minX: -2, maxX: 42, minZ: -2, maxZ: 42 },
|
|
93
|
+
fileCount: 12,
|
|
94
|
+
type: 'directory',
|
|
95
|
+
label: { text: 'src', bounds: { minX: -2, maxX: 42, minZ: 42, maxZ: 46 }, position: 'bottom' },
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
path: 'src/components',
|
|
99
|
+
worldBounds: { minX: 48, maxX: 82, minZ: -2, maxZ: 32 },
|
|
100
|
+
fileCount: 8,
|
|
101
|
+
type: 'directory',
|
|
102
|
+
label: { text: 'components', bounds: { minX: 48, maxX: 82, minZ: 32, maxZ: 36 }, position: 'bottom' },
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
path: 'src/utils',
|
|
106
|
+
worldBounds: { minX: 48, maxX: 77, minZ: 38, maxZ: 67 },
|
|
107
|
+
fileCount: 6,
|
|
108
|
+
type: 'directory',
|
|
109
|
+
label: { text: 'utils', bounds: { minX: 48, maxX: 77, minZ: 67, maxZ: 71 }, position: 'bottom' },
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
path: 'tests',
|
|
113
|
+
worldBounds: { minX: -2, maxX: 32, minZ: 48, maxZ: 72 },
|
|
114
|
+
fileCount: 5,
|
|
115
|
+
type: 'directory',
|
|
116
|
+
label: { text: 'tests', bounds: { minX: -2, maxX: 32, minZ: 72, maxZ: 76 }, position: 'bottom' },
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
bounds: { minX: -5, maxX: 85, minZ: -5, maxZ: 80 },
|
|
120
|
+
metadata: { totalFiles: 31, totalDirectories: 4, rootPath: '/project' },
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Large city for stress testing
|
|
124
|
+
function generateLargeCityData(): CityData {
|
|
125
|
+
const buildings: CityBuilding[] = [];
|
|
126
|
+
const districts: CityDistrict[] = [];
|
|
127
|
+
const gridSize = 5;
|
|
128
|
+
const dirSize = 40;
|
|
129
|
+
const filesPerDir = 15;
|
|
130
|
+
|
|
131
|
+
for (let row = 0; row < gridSize; row++) {
|
|
132
|
+
for (let col = 0; col < gridSize; col++) {
|
|
133
|
+
const dirPath = `dir_${row}_${col}`;
|
|
134
|
+
const startX = col * (dirSize + 10);
|
|
135
|
+
const startZ = row * (dirSize + 10);
|
|
136
|
+
|
|
137
|
+
buildings.push(...generateBuildings(dirPath, filesPerDir, startX, startZ, dirSize, dirSize));
|
|
138
|
+
districts.push({
|
|
139
|
+
path: dirPath,
|
|
140
|
+
worldBounds: {
|
|
141
|
+
minX: startX - 2,
|
|
142
|
+
maxX: startX + dirSize + 2,
|
|
143
|
+
minZ: startZ - 2,
|
|
144
|
+
maxZ: startZ + dirSize + 2,
|
|
145
|
+
},
|
|
146
|
+
fileCount: filesPerDir,
|
|
147
|
+
type: 'directory',
|
|
148
|
+
label: {
|
|
149
|
+
text: dirPath,
|
|
150
|
+
bounds: {
|
|
151
|
+
minX: startX - 2,
|
|
152
|
+
maxX: startX + dirSize + 2,
|
|
153
|
+
minZ: startZ + dirSize + 2,
|
|
154
|
+
maxZ: startZ + dirSize + 6,
|
|
155
|
+
},
|
|
156
|
+
position: 'bottom',
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const totalSize = gridSize * (dirSize + 10);
|
|
163
|
+
return {
|
|
164
|
+
buildings,
|
|
165
|
+
districts,
|
|
166
|
+
bounds: { minX: -10, maxX: totalSize + 10, minZ: -10, maxZ: totalSize + 10 },
|
|
167
|
+
metadata: { totalFiles: buildings.length, totalDirectories: districts.length, rootPath: '/large-project' },
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Monorepo layout
|
|
172
|
+
function generateMonorepoCityData(): CityData {
|
|
173
|
+
const buildings: CityBuilding[] = [];
|
|
174
|
+
const districts: CityDistrict[] = [];
|
|
175
|
+
|
|
176
|
+
const packages = [
|
|
177
|
+
{ name: 'packages/core', files: 20, x: 0, z: 0, w: 50, d: 50 },
|
|
178
|
+
{ name: 'packages/cli', files: 10, x: 60, z: 0, w: 35, d: 35 },
|
|
179
|
+
{ name: 'packages/react', files: 15, x: 60, z: 45, w: 40, d: 40 },
|
|
180
|
+
{ name: 'packages/server', files: 8, x: 0, z: 60, w: 30, d: 30 },
|
|
181
|
+
{ name: 'apps/web', files: 25, x: 110, z: 0, w: 55, d: 55 },
|
|
182
|
+
{ name: 'apps/docs', files: 12, x: 110, z: 65, w: 40, d: 35 },
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
for (const pkg of packages) {
|
|
186
|
+
buildings.push(...generateBuildings(pkg.name, pkg.files, pkg.x, pkg.z, pkg.w, pkg.d));
|
|
187
|
+
districts.push({
|
|
188
|
+
path: pkg.name,
|
|
189
|
+
worldBounds: {
|
|
190
|
+
minX: pkg.x - 2,
|
|
191
|
+
maxX: pkg.x + pkg.w + 2,
|
|
192
|
+
minZ: pkg.z - 2,
|
|
193
|
+
maxZ: pkg.z + pkg.d + 2,
|
|
194
|
+
},
|
|
195
|
+
fileCount: pkg.files,
|
|
196
|
+
type: 'directory',
|
|
197
|
+
label: {
|
|
198
|
+
text: pkg.name.split('/').pop() || pkg.name,
|
|
199
|
+
bounds: {
|
|
200
|
+
minX: pkg.x - 2,
|
|
201
|
+
maxX: pkg.x + pkg.w + 2,
|
|
202
|
+
minZ: pkg.z + pkg.d + 2,
|
|
203
|
+
maxZ: pkg.z + pkg.d + 6,
|
|
204
|
+
},
|
|
205
|
+
position: 'bottom',
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
buildings,
|
|
212
|
+
districts,
|
|
213
|
+
bounds: { minX: -10, maxX: 175, minZ: -10, maxZ: 110 },
|
|
214
|
+
metadata: { totalFiles: buildings.length, totalDirectories: districts.length, rootPath: '/monorepo' },
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Default view - starts fully grown in 3D mode
|
|
220
|
+
*/
|
|
221
|
+
export const Default: Story = {
|
|
222
|
+
args: {
|
|
223
|
+
cityData: sampleCityData,
|
|
224
|
+
height: '100vh',
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Animated intro - starts flat (2D), then grows into 3D with a ripple effect
|
|
230
|
+
*/
|
|
231
|
+
export const AnimatedIntro: Story = {
|
|
232
|
+
args: {
|
|
233
|
+
cityData: sampleCityData,
|
|
234
|
+
height: '100vh',
|
|
235
|
+
animation: {
|
|
236
|
+
startFlat: true,
|
|
237
|
+
autoStartDelay: 800,
|
|
238
|
+
staggerDelay: 20,
|
|
239
|
+
tension: 100,
|
|
240
|
+
friction: 12,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Manual control - starts flat, use button to trigger growth
|
|
247
|
+
*/
|
|
248
|
+
export const ManualControl: Story = {
|
|
249
|
+
args: {
|
|
250
|
+
cityData: sampleCityData,
|
|
251
|
+
height: '100vh',
|
|
252
|
+
animation: {
|
|
253
|
+
startFlat: true,
|
|
254
|
+
autoStartDelay: null,
|
|
255
|
+
staggerDelay: 15,
|
|
256
|
+
},
|
|
257
|
+
showControls: true,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Fast animation - snappy growth effect
|
|
263
|
+
*/
|
|
264
|
+
export const FastAnimation: Story = {
|
|
265
|
+
args: {
|
|
266
|
+
cityData: sampleCityData,
|
|
267
|
+
height: '100vh',
|
|
268
|
+
animation: {
|
|
269
|
+
startFlat: true,
|
|
270
|
+
autoStartDelay: 500,
|
|
271
|
+
staggerDelay: 8,
|
|
272
|
+
tension: 200,
|
|
273
|
+
friction: 18,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Slow dramatic reveal
|
|
280
|
+
*/
|
|
281
|
+
export const SlowDramatic: Story = {
|
|
282
|
+
args: {
|
|
283
|
+
cityData: sampleCityData,
|
|
284
|
+
height: '100vh',
|
|
285
|
+
animation: {
|
|
286
|
+
startFlat: true,
|
|
287
|
+
autoStartDelay: 1000,
|
|
288
|
+
staggerDelay: 40,
|
|
289
|
+
tension: 60,
|
|
290
|
+
friction: 8,
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Large city with animation - 375 buildings
|
|
297
|
+
*/
|
|
298
|
+
export const LargeCityAnimated: Story = {
|
|
299
|
+
args: {
|
|
300
|
+
cityData: generateLargeCityData(),
|
|
301
|
+
height: '100vh',
|
|
302
|
+
animation: {
|
|
303
|
+
startFlat: true,
|
|
304
|
+
autoStartDelay: 600,
|
|
305
|
+
staggerDelay: 5,
|
|
306
|
+
tension: 150,
|
|
307
|
+
friction: 16,
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Monorepo layout with animation
|
|
314
|
+
*/
|
|
315
|
+
export const MonorepoAnimated: Story = {
|
|
316
|
+
args: {
|
|
317
|
+
cityData: generateMonorepoCityData(),
|
|
318
|
+
height: '100vh',
|
|
319
|
+
animation: {
|
|
320
|
+
startFlat: true,
|
|
321
|
+
autoStartDelay: 700,
|
|
322
|
+
staggerDelay: 12,
|
|
323
|
+
tension: 120,
|
|
324
|
+
friction: 14,
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Static 3D view (no animation)
|
|
331
|
+
*/
|
|
332
|
+
export const Static3D: Story = {
|
|
333
|
+
args: {
|
|
334
|
+
cityData: sampleCityData,
|
|
335
|
+
height: '100vh',
|
|
336
|
+
animation: { startFlat: false },
|
|
337
|
+
showControls: false,
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* With click handler
|
|
343
|
+
*/
|
|
344
|
+
export const WithClickHandler: Story = {
|
|
345
|
+
args: {
|
|
346
|
+
cityData: sampleCityData,
|
|
347
|
+
height: '100vh',
|
|
348
|
+
onBuildingClick: (building) => {
|
|
349
|
+
console.log('Clicked building:', building.path);
|
|
350
|
+
alert(`Clicked: ${building.path}`);
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Isolation - transparent mode
|
|
357
|
+
*/
|
|
358
|
+
export const IsolationTransparent: Story = {
|
|
359
|
+
args: {
|
|
360
|
+
cityData: sampleCityData,
|
|
361
|
+
height: '100vh',
|
|
362
|
+
isolationMode: 'transparent',
|
|
363
|
+
dimOpacity: 0.1,
|
|
364
|
+
highlightLayers: [
|
|
365
|
+
{
|
|
366
|
+
id: 'focus',
|
|
367
|
+
name: 'Focus Layer',
|
|
368
|
+
enabled: true,
|
|
369
|
+
color: '#22c55e',
|
|
370
|
+
items: [{ path: 'src', type: 'directory' as const }],
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Isolation - collapse mode
|
|
378
|
+
*/
|
|
379
|
+
export const IsolationCollapse: Story = {
|
|
380
|
+
args: {
|
|
381
|
+
cityData: sampleCityData,
|
|
382
|
+
height: '100vh',
|
|
383
|
+
isolationMode: 'collapse',
|
|
384
|
+
highlightLayers: [
|
|
385
|
+
{
|
|
386
|
+
id: 'focus',
|
|
387
|
+
name: 'Focus Layer',
|
|
388
|
+
enabled: true,
|
|
389
|
+
color: '#3b82f6',
|
|
390
|
+
items: [{ path: 'src/components', type: 'directory' as const }],
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Isolation - hide mode
|
|
398
|
+
*/
|
|
399
|
+
export const IsolationHide: Story = {
|
|
400
|
+
args: {
|
|
401
|
+
cityData: sampleCityData,
|
|
402
|
+
height: '100vh',
|
|
403
|
+
isolationMode: 'hide',
|
|
404
|
+
highlightLayers: [
|
|
405
|
+
{
|
|
406
|
+
id: 'focus',
|
|
407
|
+
name: 'Focus Layer',
|
|
408
|
+
enabled: true,
|
|
409
|
+
color: '#f59e0b',
|
|
410
|
+
items: [{ path: 'tests', type: 'directory' as const }],
|
|
411
|
+
},
|
|
412
|
+
],
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Multiple highlight layers
|
|
418
|
+
*/
|
|
419
|
+
export const MultipleHighlights: Story = {
|
|
420
|
+
args: {
|
|
421
|
+
cityData: sampleCityData,
|
|
422
|
+
height: '100vh',
|
|
423
|
+
isolationMode: 'transparent',
|
|
424
|
+
dimOpacity: 0.08,
|
|
425
|
+
highlightLayers: [
|
|
426
|
+
{
|
|
427
|
+
id: 'src',
|
|
428
|
+
name: 'Source',
|
|
429
|
+
enabled: true,
|
|
430
|
+
color: '#22c55e',
|
|
431
|
+
items: [{ path: 'src', type: 'directory' as const }],
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
id: 'tests',
|
|
435
|
+
name: 'Tests',
|
|
436
|
+
enabled: true,
|
|
437
|
+
color: '#ef4444',
|
|
438
|
+
items: [{ path: 'tests', type: 'directory' as const }],
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Animated intro with highlight
|
|
446
|
+
*/
|
|
447
|
+
export const AnimatedWithHighlight: Story = {
|
|
448
|
+
args: {
|
|
449
|
+
cityData: sampleCityData,
|
|
450
|
+
height: '100vh',
|
|
451
|
+
animation: {
|
|
452
|
+
startFlat: true,
|
|
453
|
+
autoStartDelay: 800,
|
|
454
|
+
staggerDelay: 20,
|
|
455
|
+
},
|
|
456
|
+
isolationMode: 'transparent',
|
|
457
|
+
dimOpacity: 0.15,
|
|
458
|
+
highlightLayers: [
|
|
459
|
+
{
|
|
460
|
+
id: 'components',
|
|
461
|
+
name: 'Components',
|
|
462
|
+
enabled: true,
|
|
463
|
+
color: '#8b5cf6',
|
|
464
|
+
items: [{ path: 'src/components', type: 'directory' as const }],
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Linear height scaling
|
|
472
|
+
*/
|
|
473
|
+
export const LinearHeightScaling: Story = {
|
|
474
|
+
args: {
|
|
475
|
+
cityData: sampleCityData,
|
|
476
|
+
height: '100vh',
|
|
477
|
+
heightScaling: 'linear',
|
|
478
|
+
linearScale: 0.5,
|
|
479
|
+
},
|
|
480
|
+
};
|