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