@rsdoctor/components 1.3.12 → 1.3.13-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,53 +1,70 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import react, { memo, useEffect, useMemo, useState } from "react";
2
+ import react, { memo, useCallback, useEffect, useMemo, useState } from "react";
3
3
  import core from "echarts-for-react/esm/core";
4
4
  import { TreemapChart } from "echarts/charts";
5
5
  import { TooltipComponent } from "echarts/components";
6
6
  import { CanvasRenderer } from "echarts/renderers";
7
- import { BUNDLE_ANALYZER_COLORS, COLOR_GROUPS } from "./constants.mjs";
8
- import { Card, Checkbox, Space, Tag, Tooltip, Typography } from "antd";
9
- import { InfoCircleOutlined, VerticalAlignBottomOutlined, VerticalAlignTopOutlined } from "@ant-design/icons";
10
- import { formatSize, useI18n } from "../../utils/index.mjs";
11
- import { SearchModal } from "../../pages/BundleSize/components/search-modal.mjs";
7
+ import { Checkbox, Input, Radio } from "antd";
8
+ import { FullscreenExitOutlined, FullscreenOutlined, LeftOutlined, RightOutlined, SearchOutlined } from "@ant-design/icons";
9
+ import { formatSize } from "../../utils/index.mjs";
10
+ import { SDK } from "@rsdoctor/types";
11
+ import { ServerAPIProvider } from "../Manifest/index.mjs";
12
12
  import treemap_module from "./treemap.module.mjs";
13
+ import { TREE_COLORS } from "./constants.mjs";
13
14
  import * as __WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__ from "echarts/core";
15
+ __WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__.use([
16
+ TreemapChart,
17
+ TooltipComponent,
18
+ CanvasRenderer
19
+ ]);
14
20
  function hashString(str) {
15
21
  let hash = 5381;
16
22
  for(let i = 0; i < str.length; i++)hash = (hash << 5) + hash + str.charCodeAt(i);
17
23
  return hash >>> 0;
18
24
  }
25
+ function blendWithWhite(hex, ratio) {
26
+ const r = parseInt(hex.slice(1, 3), 16);
27
+ const g = parseInt(hex.slice(3, 5), 16);
28
+ const b = parseInt(hex.slice(5, 7), 16);
29
+ const blendedR = Math.round(r * ratio + 255 * (1 - ratio));
30
+ const blendedG = Math.round(g * ratio + 255 * (1 - ratio));
31
+ const blendedB = Math.round(b * ratio + 255 * (1 - ratio));
32
+ return `#${blendedR.toString(16).padStart(2, '0')}${blendedG.toString(16).padStart(2, '0')}${blendedB.toString(16).padStart(2, '0')}`;
33
+ }
19
34
  function getLevelOption() {
20
35
  return [
21
36
  {
22
37
  itemStyle: {
23
- color: 'white',
24
- borderColor: '#eee',
25
- borderWidth: 5,
26
- gapWidth: 5
27
- },
28
- emphasis: {
29
- itemStyle: {
30
- borderColor: '#a29f9f'
31
- }
38
+ borderWidth: 0,
39
+ gapWidth: 2
32
40
  }
33
41
  },
34
42
  {
35
- colorSaturation: [
36
- 0.25,
37
- 0.5
38
- ],
39
43
  itemStyle: {
44
+ borderColorAlpha: [
45
+ 1,
46
+ 0.3
47
+ ],
40
48
  borderWidth: 5,
41
- gapWidth: 5,
42
- borderColorSaturation: 0.5,
43
- borderColor: '#eee'
49
+ gapWidth: 1
50
+ },
51
+ upperLabel: {
52
+ show: true,
53
+ color: '#555555',
54
+ height: 30
55
+ },
56
+ emphasis: {
57
+ itemStyle: {
58
+ borderColor: '#ccc'
59
+ }
44
60
  }
45
61
  }
46
62
  ];
47
63
  }
48
- const TreeMapInner = /*#__PURE__*/ memo(({ treeData, valueKey = 'sourceSize', style, onChartClick, forwardedRef })=>{
64
+ const TreeMapInner = /*#__PURE__*/ memo(({ treeData, sizeType, style, onChartClick, forwardedRef, highlightNodeId, centerNodeId, rootPath })=>{
49
65
  const [option, setOption] = useState(null);
50
66
  const chartRef = react.useRef(null);
67
+ const chartDataRef = react.useRef([]);
51
68
  useEffect(()=>{
52
69
  if (forwardedRef && chartRef.current) if ('function' == typeof forwardedRef) forwardedRef(chartRef.current);
53
70
  else forwardedRef.current = chartRef.current;
@@ -55,115 +72,284 @@ const TreeMapInner = /*#__PURE__*/ memo(({ treeData, valueKey = 'sourceSize', st
55
72
  forwardedRef,
56
73
  chartRef.current
57
74
  ]);
58
- useEffect(()=>{
59
- __WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__.use([
60
- TreemapChart,
61
- TooltipComponent,
62
- CanvasRenderer
63
- ]);
64
- }, []);
65
75
  useEffect(()=>{
66
76
  if (!treeData) return;
67
- function convert(node, colorGroup, level = 0) {
68
- const groupColors = BUNDLE_ANALYZER_COLORS[colorGroup];
69
- const children = node.children?.map((c, _i)=>convert(c, colorGroup, level + 1));
70
- return {
71
- id: node.path ? hashString(node.path) : void 0,
77
+ function convert(node, index = 0, level = 0, parentColor, siblingIndex = 0, siblingCount = 1) {
78
+ const baseColor = parentColor || TREE_COLORS[index % TREE_COLORS.length];
79
+ const children = node.children?.map((c, childIndex)=>convert(c, index, level + 1, baseColor, childIndex, node.children?.length || 0));
80
+ let val = 0;
81
+ if ('stat' === sizeType) val = node.sourceSize || 0;
82
+ else if ('parsed' === sizeType) val = node.bundledSize || 0;
83
+ else if ('gzip' === sizeType) val = node.gzipSize || 0;
84
+ else if ('value' === sizeType) val = node.value || 0;
85
+ if (!val && node.value) val = node.value;
86
+ const nodeId = node.path ? hashString(node.path) : hashString(node.name || '');
87
+ const isHighlighted = highlightNodeId === nodeId;
88
+ const baseColorRatio = 0 === level ? 1 : Math.max(0.2, 1 - 0.2 * level);
89
+ const baseBorderRatio = 0 === level ? 1 : Math.max(0.3, 1 - 0.25 * level);
90
+ const siblingGradientRange = 0.15;
91
+ const siblingRatio = siblingCount > 1 ? 1 - siblingIndex / (siblingCount - 1) * siblingGradientRange : 1;
92
+ const colorRatio = baseColorRatio * siblingRatio;
93
+ const borderRatio = baseBorderRatio * siblingRatio;
94
+ const nodeColor = isHighlighted ? '#fff5f5' : 0 === level ? blendWithWhite(baseColor, 0.8) : blendWithWhite(baseColor, colorRatio);
95
+ const nodeBorderColor = isHighlighted ? '#ff4d4f' : 0 === level ? baseColor : blendWithWhite(baseColor, borderRatio);
96
+ const result = {
97
+ id: nodeId,
72
98
  name: node.name,
73
- value: node[valueKey] || node.value || node['sourceSize'] || 0,
74
- path: node.path,
75
- sourceSize: node.sourceSize ?? node.value,
76
- bundledSize: node.bundledSize,
77
- gzipSize: node.gzipSize,
78
- children: children && children.length > 0 ? children : void 0,
99
+ value: val,
100
+ path: node.path || node.name,
101
+ sourceSize: node.sourceSize ?? ('stat' === sizeType ? val : 0),
102
+ bundledSize: node.bundledSize ?? ('parsed' === sizeType ? val : 0),
103
+ gzipSize: node.gzipSize ?? ('gzip' === sizeType ? val : 0),
79
104
  itemStyle: {
80
- borderWidth: 2,
81
- gapWidth: 2,
82
- borderColorSaturation: 0.2,
83
- colorSaturation: 0.2,
84
- color: groupColors[level % groupColors.length],
85
- borderColor: groupColors[level % groupColors.length]
86
- },
87
- level
105
+ borderWidth: isHighlighted ? 4 : 1,
106
+ color: nodeColor,
107
+ borderColor: nodeBorderColor,
108
+ ...0 === level && {
109
+ gapWidth: 2
110
+ }
111
+ }
88
112
  };
113
+ if (children && children.length > 0) result.children = children;
114
+ if (isHighlighted) result.emphasis = {
115
+ itemStyle: {
116
+ borderColor: '#ff4d4f',
117
+ borderWidth: 4,
118
+ color: '#fff5f5'
119
+ }
120
+ };
121
+ return result;
89
122
  }
90
- const data = treeData.map((item, index)=>{
91
- const group = COLOR_GROUPS[index % COLOR_GROUPS.length];
92
- return convert(item, group, 0);
93
- });
123
+ const data = treeData.map((item, index)=>convert(item, index, 0, void 0, index, treeData.length)).filter((item)=>item.value > 0 || item.children && item.children.length > 0);
124
+ chartDataRef.current = data;
94
125
  setOption({
126
+ color: TREE_COLORS,
95
127
  title: {
96
- text: 'Bundle Tree Map',
97
- left: 'center'
128
+ text: 'Rsdoctor TreeMap',
129
+ left: 'center',
130
+ top: 10,
131
+ textStyle: {
132
+ fontSize: 16,
133
+ fontWeight: 'bold',
134
+ color: 'rgba(0, 0, 0, 0.8)'
135
+ }
98
136
  },
99
137
  tooltip: {
100
- position: 'top',
138
+ padding: 10,
139
+ backgroundColor: '#fff',
140
+ borderColor: '#eee',
141
+ borderWidth: 1,
142
+ textStyle: {
143
+ color: 'rgba(0, 0, 0, 0.8)'
144
+ },
145
+ confine: true,
146
+ extraCssText: 'max-width: 450px; word-wrap: break-word;',
147
+ position: function(pos, _params, _dom, _rect, size) {
148
+ var obj = {
149
+ top: pos[1] + 10
150
+ };
151
+ if (pos[0] < size.viewSize[0] / 2) obj.left = pos[0] + 10;
152
+ else obj.right = size.viewSize[0] - pos[0] + 10;
153
+ return obj;
154
+ },
101
155
  formatter: function(info) {
102
- var treePathInfo = info.treePathInfo;
103
- var treePath = [];
104
- for(var i = 1; i < treePathInfo.length; i++)treePath.push(treePathInfo[i].name);
105
- var node = info.data || {};
106
- var path = node.path || treePath.join('/');
107
- var sourceSize = node.sourceSize;
108
- var bundledSize = node.bundledSize;
109
- var gzipSize = node.gzipSize;
110
- var level = node.level;
111
- function makeRow(label, value, valueColor) {
112
- return `<div class="${treemap_module["tooltip-row"]}"><span class="${treemap_module["tooltip-label"]}">${label}</span><span${valueColor ? ` style="color: ${valueColor}"` : ''}>${value}</span></div>`;
156
+ const node = info.data || {};
157
+ const name = node.name;
158
+ let path = node.path || name;
159
+ if (rootPath && path) {
160
+ const normalizedRoot = rootPath.replace(/\\/g, '/').replace(/\/$/, '');
161
+ const normalizedPath = path.replace(/\\/g, '/');
162
+ if (normalizedPath.startsWith(normalizedRoot + '/')) path = normalizedPath.slice(normalizedRoot.length + 1);
163
+ else if (normalizedPath === normalizedRoot) path = '';
113
164
  }
114
- return [
115
- `<div class="${treemap_module["tooltip-path"]}">` + __WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__.format.encodeHTML(path) + '</div>',
116
- makeRow(0 === level ? 'Asset' : 'Source', void 0 !== sourceSize ? formatSize(sourceSize) : '-'),
117
- !bundledSize ? '' : makeRow('Bundled', formatSize(bundledSize), '#1890ff'),
118
- !gzipSize ? '' : makeRow('Gzipped', formatSize(gzipSize), '#52c41a')
119
- ].join('');
165
+ const sourceSize = node.sourceSize || node.value;
166
+ const bundledSize = node.bundledSize;
167
+ const gzipSize = node.gzipSize;
168
+ function makeRow(label, value, color) {
169
+ return `<div class="${treemap_module["tooltip-row"]}">
170
+ <span class="${treemap_module["tooltip-label"]}" style="color: ${color};">${label}</span>
171
+ <span style="color: ${color};">${value}</span>
172
+ </div>`;
173
+ }
174
+ const rows = [];
175
+ if (void 0 !== sourceSize) rows.push(makeRow('Stat size', formatSize(sourceSize), '#52c41a'));
176
+ if (void 0 !== bundledSize) rows.push(makeRow('Parsed size', formatSize(bundledSize), '#fadb14'));
177
+ if (void 0 !== gzipSize) rows.push(makeRow('Gzipped size', formatSize(gzipSize), '#1677ff'));
178
+ return `
179
+ <div style="font-family: sans-serif; font-size: 12px; line-height: 1.5;">
180
+ <div style="margin-bottom: 6px; max-width: 400px; word-wrap: break-word; overflow-wrap: break-word; word-break: break-all; white-space: normal; color: rgba(0, 0, 0, 0.8);">${__WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__.format.encodeHTML(path)}</div>
181
+ ${rows.join('')}
182
+ </div>
183
+ `;
120
184
  }
121
185
  },
122
186
  series: [
123
187
  {
124
- name: 'Bundle Tree Map',
125
- id: 'bundle-treemap',
126
188
  type: 'treemap',
127
- visibleMin: 300,
128
- left: 10,
129
- right: 10,
130
- top: 10,
131
- bottom: 10,
132
189
  label: {
133
190
  show: true,
134
191
  formatter: '{b}',
135
- color: '#000'
192
+ fontSize: 12,
193
+ color: '#000',
194
+ position: 'inside',
195
+ fontWeight: 'normal',
196
+ textBorderColor: '#fff',
197
+ textBorderWidth: 2,
198
+ padding: [
199
+ 4,
200
+ 8,
201
+ 4,
202
+ 8
203
+ ]
136
204
  },
137
205
  upperLabel: {
138
206
  show: true,
139
- height: 30
207
+ height: 30,
208
+ color: '#000',
209
+ fontSize: 12,
210
+ fontWeight: 'normal',
211
+ padding: [
212
+ 0,
213
+ 0,
214
+ 0,
215
+ 4
216
+ ]
140
217
  },
141
218
  levels: getLevelOption(),
142
- data: data
219
+ data: data,
220
+ breadcrumb: {
221
+ show: true,
222
+ left: 'center',
223
+ top: 'bottom',
224
+ height: 22,
225
+ emptyItemWidth: 25,
226
+ itemStyle: {
227
+ color: '#999',
228
+ borderColor: 'transparent',
229
+ borderWidth: 0,
230
+ borderRadius: 0
231
+ },
232
+ emphasis: {
233
+ itemStyle: {
234
+ color: '#333'
235
+ }
236
+ },
237
+ textStyle: {
238
+ fontFamily: 'sans-serif',
239
+ fontSize: 12,
240
+ color: '#666'
241
+ }
242
+ },
243
+ roam: true,
244
+ nodeClick: false,
245
+ zoomToNodeRatio: 0.5,
246
+ animationDurationUpdate: 500,
247
+ width: '100%',
248
+ height: '100%',
249
+ top: 40,
250
+ bottom: 30,
251
+ left: 0,
252
+ right: 0
143
253
  }
144
254
  ]
145
255
  });
146
256
  }, [
147
257
  treeData,
148
- valueKey
258
+ sizeType,
259
+ highlightNodeId,
260
+ rootPath
261
+ ]);
262
+ useEffect(()=>{
263
+ if (centerNodeId && chartRef.current && option) {
264
+ const chartInstance = chartRef.current.getEchartsInstance();
265
+ if (chartInstance) {
266
+ const findNodeInfo = (data, targetId, path = [])=>{
267
+ for (const item of data){
268
+ const currentPath = [
269
+ ...path,
270
+ item.name
271
+ ];
272
+ if (item.id === targetId) return {
273
+ name: item.name,
274
+ path: currentPath
275
+ };
276
+ if (item.children) {
277
+ const found = findNodeInfo(item.children, targetId, currentPath);
278
+ if (found) return found;
279
+ }
280
+ }
281
+ return null;
282
+ };
283
+ setTimeout(()=>{
284
+ const nodeInfo = findNodeInfo(chartDataRef.current, centerNodeId);
285
+ if (!nodeInfo) return;
286
+ try {
287
+ chartInstance.dispatchAction({
288
+ type: 'highlight',
289
+ seriesIndex: 0,
290
+ name: nodeInfo.name
291
+ });
292
+ } catch (e) {}
293
+ const zoomStrategies = [
294
+ ()=>chartInstance.dispatchAction({
295
+ type: 'treemapZoomToNode',
296
+ seriesIndex: 0,
297
+ targetNodeId: String(centerNodeId)
298
+ }),
299
+ ()=>chartInstance.dispatchAction({
300
+ type: 'treemapZoomToNode',
301
+ seriesIndex: 0,
302
+ name: nodeInfo.name
303
+ }),
304
+ ()=>chartInstance.dispatchAction({
305
+ type: 'treemapZoomToNode',
306
+ seriesIndex: 0,
307
+ name: nodeInfo.path.join('/')
308
+ }),
309
+ ()=>nodeInfo.path.length > 0 && chartInstance.dispatchAction({
310
+ type: 'treemapZoomToNode',
311
+ seriesIndex: 0,
312
+ name: nodeInfo.path[nodeInfo.path.length - 1]
313
+ })
314
+ ];
315
+ for (const strategy of zoomStrategies)try {
316
+ strategy();
317
+ return;
318
+ } catch (e) {
319
+ console.error('Failed to zoom to node with id:', centerNodeId, e);
320
+ }
321
+ console.warn('Failed to zoom to node with id:', centerNodeId);
322
+ }, 200);
323
+ }
324
+ }
325
+ }, [
326
+ centerNodeId,
327
+ option
149
328
  ]);
150
329
  return option ? /*#__PURE__*/ jsx("div", {
330
+ className: treemap_module["chart-container"],
331
+ style: style,
151
332
  children: /*#__PURE__*/ jsx(core, {
152
333
  ref: chartRef,
153
334
  option: option,
154
335
  echarts: __WEBPACK_EXTERNAL_MODULE_echarts_core_d2845954__,
155
- onEvents: onChartClick ? {
156
- click: onChartClick
157
- } : void 0,
336
+ onEvents: {
337
+ click: (params)=>{
338
+ if (chartRef.current) {
339
+ const instance = chartRef.current.getEchartsInstance();
340
+ if (instance && params?.data?.id) instance.dispatchAction({
341
+ type: 'treemapZoomToNode',
342
+ seriesIndex: 0,
343
+ targetNodeId: String(params.data.id)
344
+ });
345
+ }
346
+ onChartClick?.(params);
347
+ }
348
+ },
158
349
  style: {
159
350
  width: '100%',
160
- minHeight: '500px',
161
- maxHeight: '1000px',
162
- border: '5px solid white',
163
- borderRadius: '10px',
164
- ...style
165
- },
166
- className: treemap_module["chart-container"]
351
+ height: '100%'
352
+ }
167
353
  })
168
354
  }) : null;
169
355
  });
@@ -171,146 +357,286 @@ const TreeMap = /*#__PURE__*/ react.forwardRef((props, ref)=>/*#__PURE__*/ jsx(T
171
357
  ...props,
172
358
  forwardedRef: ref
173
359
  }));
174
- const AssetTreemapWithFilter = ({ treeData, onChartClick, bundledSize = false })=>{
360
+ const AssetTreemapWithFilter = ({ treeData, onChartClick, bundledSize = true })=>/*#__PURE__*/ jsx(ServerAPIProvider, {
361
+ api: SDK.ServerAPI.API.GetProjectInfo,
362
+ children: (projectInfo)=>/*#__PURE__*/ jsx(AssetTreemapWithFilterInner, {
363
+ treeData: treeData,
364
+ onChartClick: onChartClick,
365
+ bundledSize: bundledSize,
366
+ rootPath: projectInfo.root
367
+ })
368
+ });
369
+ const AssetTreemapWithFilterInner = ({ treeData, onChartClick, bundledSize = true, rootPath })=>{
175
370
  const assetNames = useMemo(()=>treeData.map((item)=>item.name), [
176
371
  treeData
177
372
  ]);
178
373
  const [checkedAssets, setCheckedAssets] = useState(assetNames);
179
374
  const [collapsed, setCollapsed] = useState(false);
180
- const [searchModalOpen, setSearchModalOpen] = useState(false);
375
+ const [sizeType, setSizeType] = useState(bundledSize ? 'parsed' : 'stat');
376
+ const [searchQuery, setSearchQuery] = useState('');
377
+ const [isFullscreen, setIsFullscreen] = useState(false);
378
+ const [highlightNodeId, setHighlightNodeId] = useState();
379
+ const [centerNodeId, setCenterNodeId] = useState();
181
380
  const chartRef = react.useRef(null);
182
- const { t } = useI18n();
183
- const filteredTreeData = useMemo(()=>treeData.filter((item)=>checkedAssets.includes(item.name)), [
381
+ const containerRef = react.useRef(null);
382
+ const enterFullscreen = useCallback(()=>{
383
+ if (containerRef.current) containerRef.current.requestFullscreen().then(()=>setIsFullscreen(true)).catch((err)=>console.error('Failed to enter fullscreen:', err));
384
+ }, []);
385
+ const exitFullscreen = useCallback(()=>{
386
+ document.exitFullscreen().then(()=>setIsFullscreen(false)).catch((err)=>console.error('Failed to exit fullscreen:', err));
387
+ }, []);
388
+ const toggleFullscreen = useCallback(()=>{
389
+ if (isFullscreen) exitFullscreen();
390
+ else enterFullscreen();
391
+ }, [
392
+ isFullscreen,
393
+ enterFullscreen,
394
+ exitFullscreen
395
+ ]);
396
+ useEffect(()=>{
397
+ const handleFullscreenChange = ()=>{
398
+ setIsFullscreen(!!document.fullscreenElement);
399
+ };
400
+ document.addEventListener('fullscreenchange', handleFullscreenChange);
401
+ return ()=>{
402
+ document.removeEventListener('fullscreenchange', handleFullscreenChange);
403
+ };
404
+ }, []);
405
+ const searchResults = useMemo(()=>{
406
+ if (!searchQuery.trim()) return [];
407
+ const regex = new RegExp(searchQuery, 'i');
408
+ const results = [];
409
+ const collectMatchingPaths = (node)=>{
410
+ if (node.path && regex.test(node.path)) {
411
+ const nodeId = hashString(node.path);
412
+ results.push({
413
+ path: node.path,
414
+ nodeId
415
+ });
416
+ }
417
+ if (node.children) node.children.forEach(collectMatchingPaths);
418
+ };
419
+ treeData.forEach(collectMatchingPaths);
420
+ return results;
421
+ }, [
422
+ treeData,
423
+ searchQuery
424
+ ]);
425
+ const filteredTreeData = useMemo(()=>{
426
+ let filtered = treeData.filter((item)=>checkedAssets.includes(item.name));
427
+ return filtered;
428
+ }, [
184
429
  treeData,
185
430
  checkedAssets
186
431
  ]);
187
- const handleModuleClick = (module)=>{
188
- if (!module?.path) return;
189
- const nodeId = hashString(module.path);
190
- if (chartRef.current) {
191
- const echartsInstance = chartRef.current.getEchartsInstance();
192
- echartsInstance.dispatchAction({
193
- type: 'treemapZoomToNode',
194
- seriesId: 'bundle-treemap',
195
- targetNodeId: nodeId.toString()
196
- });
432
+ const handleSearchResultClick = useCallback((nodeId)=>{
433
+ setHighlightNodeId(nodeId);
434
+ setCenterNodeId(nodeId);
435
+ }, []);
436
+ const removeRootPath = useCallback((filepath)=>{
437
+ if (!rootPath || !filepath) return filepath;
438
+ const normalizedRoot = rootPath.replace(/\\/g, '/').replace(/\/$/, '');
439
+ const normalizedPath = filepath.replace(/\\/g, '/');
440
+ if (normalizedPath.startsWith(normalizedRoot + '/')) return normalizedPath.slice(normalizedRoot.length + 1);
441
+ if (normalizedPath === normalizedRoot) return '';
442
+ return filepath;
443
+ }, [
444
+ rootPath
445
+ ]);
446
+ const getSize = useCallback((node, type)=>{
447
+ if ('stat' === type) return node.sourceSize || 0;
448
+ if ('parsed' === type) return node.bundledSize || 0;
449
+ if ('gzip' === type) return node.gzipSize || 0;
450
+ if ('value' === type) return node.value || 0;
451
+ if (node.value) return node.value;
452
+ return 0;
453
+ }, []);
454
+ const calculateNodeTotalSize = useCallback((node, type)=>{
455
+ let size = getSize(node, type);
456
+ if (node.children && node.children.length > 0) {
457
+ const childrenSize = node.children.reduce((sum, child)=>sum + calculateNodeTotalSize(child, type), 0);
458
+ if (0 === size || !node.path && childrenSize > 0) size = childrenSize;
197
459
  }
198
- setSearchModalOpen(false);
199
- };
200
- return /*#__PURE__*/ jsx("div", {
201
- style: {
202
- display: 'flex',
203
- flexDirection: 'column',
204
- gap: 16
205
- },
460
+ return size;
461
+ }, [
462
+ getSize
463
+ ]);
464
+ const getChunkSize = useCallback((name, type)=>{
465
+ const node = treeData.find((n)=>n.name === name);
466
+ if (!node) return 0;
467
+ const sizeTypeToUse = type || sizeType;
468
+ return calculateNodeTotalSize(node, sizeTypeToUse);
469
+ }, [
470
+ treeData,
471
+ sizeType,
472
+ calculateNodeTotalSize
473
+ ]);
474
+ return /*#__PURE__*/ jsxs("div", {
206
475
  className: treemap_module.treemap,
207
- children: /*#__PURE__*/ jsxs(Space, {
208
- direction: "vertical",
209
- style: {
210
- width: '100%'
211
- },
212
- children: [
213
- /*#__PURE__*/ jsx(Card, {
214
- title: /*#__PURE__*/ jsxs(Space, {
476
+ ref: containerRef,
477
+ children: [
478
+ /*#__PURE__*/ jsx("button", {
479
+ className: treemap_module["fullscreen-button"],
480
+ onClick: toggleFullscreen,
481
+ title: isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen',
482
+ "aria-label": isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen',
483
+ children: isFullscreen ? /*#__PURE__*/ jsx(FullscreenExitOutlined, {}) : /*#__PURE__*/ jsx(FullscreenOutlined, {})
484
+ }),
485
+ /*#__PURE__*/ jsxs("div", {
486
+ className: `${treemap_module.sidebar} ${collapsed ? treemap_module.collapsed : ''}`,
487
+ children: [
488
+ /*#__PURE__*/ jsx("div", {
489
+ className: `${treemap_module["sidebar-toggle"]} ${collapsed ? treemap_module.collapsed : ''}`,
490
+ onClick: ()=>setCollapsed(!collapsed),
491
+ children: collapsed ? /*#__PURE__*/ jsx(RightOutlined, {}) : /*#__PURE__*/ jsx(LeftOutlined, {})
492
+ }),
493
+ /*#__PURE__*/ jsxs("div", {
494
+ className: treemap_module["sidebar-content"],
215
495
  children: [
216
- /*#__PURE__*/ jsx(Typography.Text, {
217
- children: t('Output Assets List')
218
- }),
219
- /*#__PURE__*/ jsx(SearchModal, {
220
- onModuleClick: handleModuleClick,
221
- open: searchModalOpen,
222
- setOpen: setSearchModalOpen,
223
- isIcon: true
496
+ /*#__PURE__*/ jsxs("div", {
497
+ children: [
498
+ /*#__PURE__*/ jsx("h4", {
499
+ children: "Treemap sizes"
500
+ }),
501
+ /*#__PURE__*/ jsxs(Radio.Group, {
502
+ value: sizeType,
503
+ onChange: (e)=>setSizeType(e.target.value),
504
+ size: "small",
505
+ buttonStyle: "solid",
506
+ children: [
507
+ /*#__PURE__*/ jsx(Radio.Button, {
508
+ value: "stat",
509
+ children: "Stat"
510
+ }),
511
+ /*#__PURE__*/ jsx(Radio.Button, {
512
+ value: "parsed",
513
+ children: "Parsed"
514
+ }),
515
+ /*#__PURE__*/ jsx(Radio.Button, {
516
+ value: "gzip",
517
+ children: "Gzipped"
518
+ })
519
+ ]
520
+ })
521
+ ]
224
522
  }),
225
- /*#__PURE__*/ jsx(Tooltip, {
226
- color: 'white',
227
- title: /*#__PURE__*/ jsxs("span", {
228
- children: [
229
- "✨ In Rspack, TreeMap proportions are always based on Bundled Size by default.",
230
- /*#__PURE__*/ jsx("br", {}),
231
- " In Webpack, TreeMap proportions are based on Bundled Size only when SourceMap is enabled.",
232
- /*#__PURE__*/ jsx("br", {}),
233
- "✨ ",
234
- /*#__PURE__*/ jsx("b", {
235
- children: "Bundled Size"
236
- }),
237
- ": The size of a module after bundling and minification.",
238
- /*#__PURE__*/ jsx("br", {}),
239
- "✨ ",
240
- /*#__PURE__*/ jsx("b", {
241
- children: "Source Size"
242
- }),
243
- ": The size of a module after compilation (e.g., TypeScript/JSX to JS), but before bundling and minification.",
244
- /*#__PURE__*/ jsx("br", {}),
245
- "✨ ",
246
- /*#__PURE__*/ jsx("b", {
247
- children: "Gzipped Size"
523
+ /*#__PURE__*/ jsxs("div", {
524
+ children: [
525
+ /*#__PURE__*/ jsx("h4", {
526
+ children: "Search modules"
527
+ }),
528
+ /*#__PURE__*/ jsx(Input, {
529
+ placeholder: "Enter regexp",
530
+ value: searchQuery,
531
+ onChange: (e)=>{
532
+ setSearchQuery(e.target.value);
533
+ setHighlightNodeId(void 0);
534
+ setCenterNodeId(void 0);
535
+ },
536
+ suffix: /*#__PURE__*/ jsx(SearchOutlined, {
537
+ style: {
538
+ color: '#ccc'
539
+ }
248
540
  }),
249
- ": The compressed file size that users actually download, as most web servers use gzip compression.",
250
- /*#__PURE__*/ jsx("br", {})
251
- ]
252
- }),
253
- overlayInnerStyle: {
254
- width: 620,
255
- color: 'black'
256
- },
257
- children: /*#__PURE__*/ jsx(InfoCircleOutlined, {
258
- style: {
259
- color: '#1890ff',
260
- marginLeft: 8
261
- }
262
- })
541
+ allowClear: true,
542
+ size: "small"
543
+ }),
544
+ searchQuery.trim() && searchResults.length > 0 && /*#__PURE__*/ jsxs("div", {
545
+ className: treemap_module["search-results"],
546
+ children: [
547
+ /*#__PURE__*/ jsxs("div", {
548
+ className: treemap_module["search-results-header"],
549
+ children: [
550
+ "Found ",
551
+ searchResults.length,
552
+ " file",
553
+ searchResults.length > 1 ? 's' : ''
554
+ ]
555
+ }),
556
+ /*#__PURE__*/ jsx("div", {
557
+ className: treemap_module["search-results-list"],
558
+ children: searchResults.map((result, index)=>{
559
+ const displayPath = removeRootPath(result.path);
560
+ return /*#__PURE__*/ jsx("div", {
561
+ className: treemap_module["search-result-item"],
562
+ onClick: ()=>handleSearchResultClick(result.nodeId),
563
+ title: result.path,
564
+ children: displayPath || result.path
565
+ }, index);
566
+ })
567
+ })
568
+ ]
569
+ }),
570
+ searchQuery.trim() && 0 === searchResults.length && /*#__PURE__*/ jsxs("div", {
571
+ className: treemap_module["search-results-empty"],
572
+ children: [
573
+ 'No files found matching "',
574
+ searchQuery,
575
+ '"'
576
+ ]
577
+ })
578
+ ]
263
579
  }),
264
- /*#__PURE__*/ jsxs(Tag, {
265
- color: "blue",
580
+ /*#__PURE__*/ jsxs("div", {
266
581
  children: [
267
- "TreeMap area based on",
268
- ' ',
269
- bundledSize ? 'Bundled Size' : 'Source Size'
582
+ /*#__PURE__*/ jsx("h4", {
583
+ children: "Show chunks"
584
+ }),
585
+ /*#__PURE__*/ jsx(Checkbox, {
586
+ indeterminate: checkedAssets.length > 0 && checkedAssets.length < assetNames.length,
587
+ checked: checkedAssets.length === assetNames.length,
588
+ onChange: (e)=>setCheckedAssets(e.target.checked ? assetNames : []),
589
+ className: treemap_module["all-none-checkbox"],
590
+ children: "All"
591
+ }),
592
+ /*#__PURE__*/ jsx("div", {
593
+ className: treemap_module["chunk-list"],
594
+ children: assetNames.map((name)=>/*#__PURE__*/ jsxs("div", {
595
+ className: treemap_module["chunk-item"],
596
+ children: [
597
+ /*#__PURE__*/ jsx(Checkbox, {
598
+ checked: checkedAssets.includes(name),
599
+ onChange: (e)=>{
600
+ e.target.checked ? setCheckedAssets([
601
+ ...checkedAssets,
602
+ name
603
+ ]) : setCheckedAssets(checkedAssets.filter((a)=>a !== name));
604
+ },
605
+ children: /*#__PURE__*/ jsx("span", {
606
+ title: name,
607
+ children: name
608
+ })
609
+ }),
610
+ /*#__PURE__*/ jsx("span", {
611
+ className: treemap_module["size-tag"],
612
+ children: formatSize(getChunkSize(name, 'value'))
613
+ })
614
+ ]
615
+ }, name))
616
+ })
270
617
  ]
271
618
  })
272
619
  ]
273
- }),
274
- extra: /*#__PURE__*/ jsx("span", {
275
- className: treemap_module["collapse-icon"],
276
- onClick: ()=>setCollapsed((c)=>!c),
277
- "aria-label": collapsed ? t('Expand') : t('Collapse'),
278
- children: collapsed ? /*#__PURE__*/ jsx(VerticalAlignBottomOutlined, {}) : /*#__PURE__*/ jsx(VerticalAlignTopOutlined, {})
279
- }),
280
- size: "small",
281
- className: `card-body ${collapsed ? 'collapsed' : ''}`,
282
- children: /*#__PURE__*/ jsxs("div", {
283
- className: `checkbox-container ${collapsed ? 'collapsed' : ''}`,
284
- children: [
285
- /*#__PURE__*/ jsx(Checkbox, {
286
- indeterminate: checkedAssets.length > 0 && checkedAssets.length < assetNames.length,
287
- checked: checkedAssets.length === assetNames.length,
288
- onChange: (e)=>setCheckedAssets(e.target.checked ? assetNames : []),
289
- className: treemap_module["all-none-checkbox"],
290
- children: 'ALL / NONE'
291
- }, "all-none-checkbox"),
292
- /*#__PURE__*/ jsx(Checkbox.Group, {
293
- options: assetNames,
294
- value: checkedAssets,
295
- onChange: setCheckedAssets,
296
- className: `checkbox-container ${collapsed ? 'collapsed' : ''} ${treemap_module["asset-checkbox-group"]}`
297
- }, "asset-checkbox-group")
298
- ]
299
620
  })
300
- }),
301
- /*#__PURE__*/ jsx("div", {
621
+ ]
622
+ }),
623
+ /*#__PURE__*/ jsx("div", {
624
+ className: treemap_module["chart-wrapper"],
625
+ children: /*#__PURE__*/ jsx(TreeMap, {
626
+ ref: chartRef,
627
+ treeData: filteredTreeData,
628
+ sizeType: sizeType,
629
+ onChartClick: onChartClick,
630
+ highlightNodeId: highlightNodeId,
631
+ centerNodeId: centerNodeId,
632
+ rootPath: rootPath,
302
633
  style: {
303
- flex: 1
304
- },
305
- children: /*#__PURE__*/ jsx(TreeMap, {
306
- ref: chartRef,
307
- treeData: filteredTreeData,
308
- valueKey: bundledSize ? 'bundledSize' : 'sourceSize',
309
- onChartClick: onChartClick
310
- })
634
+ width: '100%',
635
+ height: '100%'
636
+ }
311
637
  })
312
- ]
313
- })
638
+ })
639
+ ]
314
640
  });
315
641
  };
316
642
  export { AssetTreemapWithFilter, TreeMap };