@kylincloud/flamegraph 0.35.8 → 0.35.10
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/README.md +292 -50
- package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts.map +1 -1
- package/dist/FlameGraph/FlameGraphComponent/Header.d.ts +0 -3
- package/dist/FlameGraph/FlameGraphComponent/Header.d.ts.map +1 -1
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -1
- package/dist/FlameGraph/FlameGraphRenderer.d.ts +2 -0
- package/dist/FlameGraph/FlameGraphRenderer.d.ts.map +1 -1
- package/dist/FlamegraphRenderer.d.ts +23 -5
- package/dist/FlamegraphRenderer.d.ts.map +1 -1
- package/dist/ProfilerTable.d.ts.map +1 -1
- package/dist/Toolbar.d.ts +4 -1
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/index.cjs.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +4 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.node.cjs.js +6 -1
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.esm.js +8 -3
- package/dist/index.node.esm.js.map +1 -1
- package/package.json +4 -1
- package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.module.css +69 -21
- package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx +57 -86
- package/src/FlameGraph/FlameGraphComponent/Header.tsx +23 -36
- package/src/FlameGraph/FlameGraphComponent/index.tsx +13 -9
- package/src/FlameGraph/FlameGraphRenderer.tsx +14 -11
- package/src/FlamegraphRenderer.tsx +103 -20
- package/src/ProfilerTable.tsx +24 -11
- package/src/SharedQueryInput.module.scss +5 -2
- package/src/Toolbar.module.scss +13 -0
- package/src/Toolbar.tsx +29 -3
- package/src/i18n.tsx +11 -2
- package/src/sass/_css-variables.scss +15 -2
- package/src/sass/flamegraph.scss +59 -0
- package/src/shims/Table.module.scss +7 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kylincloud/flamegraph",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.10",
|
|
4
4
|
"description": "KylinCloud flamegraph renderer (Pyroscope-based)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.node.cjs.js",
|
|
@@ -80,6 +80,9 @@
|
|
|
80
80
|
"build:js": "rollup -c",
|
|
81
81
|
"build:assets": "cp src/logo-v3-small.svg dist/logo-v3-small.svg || true",
|
|
82
82
|
"type-check": "tsc -p tsconfig.build.json --noEmit",
|
|
83
|
+
"dev:types": "tsc -p tsconfig.build.json --emitDeclarationOnly --watch",
|
|
84
|
+
"dev:js": "rollup -c -w",
|
|
85
|
+
"dev": "pnpm run dev:js",
|
|
83
86
|
"lint": "eslint ./ --cache --fix"
|
|
84
87
|
}
|
|
85
88
|
}
|
|
@@ -1,40 +1,88 @@
|
|
|
1
|
-
.
|
|
2
|
-
max-width: 510px;
|
|
3
|
-
min-width: 292px;
|
|
4
|
-
width: inherit;
|
|
5
|
-
padding-right: 20px !important;
|
|
6
|
-
}
|
|
1
|
+
/* src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.module.css */
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
/* 容器 */
|
|
4
|
+
.container {
|
|
9
5
|
display: flex;
|
|
10
6
|
align-items: center;
|
|
11
|
-
flex-direction: column;
|
|
12
7
|
}
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
/* 触发按钮:色带 + 下拉箭头 */
|
|
10
|
+
.triggerButton {
|
|
16
11
|
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: 6px;
|
|
14
|
+
padding: 4px 8px;
|
|
15
|
+
border: 1px solid var(--ps-ui-border);
|
|
16
|
+
border-radius: 4px;
|
|
17
|
+
background-color: var(--ps-immutable-off-white);
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
height: 37px;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
.
|
|
20
|
-
|
|
22
|
+
.triggerButton:hover {
|
|
23
|
+
background-color: var(--ps-ui-element-bg-highlight);
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
.
|
|
24
|
-
|
|
26
|
+
.dropdownArrow {
|
|
27
|
+
font-size: 8px;
|
|
28
|
+
color: var(--ps-text-secondary);
|
|
29
|
+
margin-left: 4px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* 菜单项样式 */
|
|
33
|
+
.menuItem {
|
|
25
34
|
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: space-between;
|
|
37
|
+
gap: 12px;
|
|
38
|
+
min-width: 200px;
|
|
39
|
+
padding: 4px 0;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
.
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
.menuItemText {
|
|
43
|
+
color: var(--ps-text-primary);
|
|
44
|
+
font-size: 13px;
|
|
31
45
|
}
|
|
32
46
|
|
|
47
|
+
/* ========== 以下为旧样式,保留兼容性 ========== */
|
|
48
|
+
|
|
33
49
|
.row {
|
|
34
50
|
display: flex;
|
|
51
|
+
flex-direction: row;
|
|
35
52
|
justify-content: space-between;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
padding-bottom: 2px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.row p {
|
|
57
|
+
font-size: 13px;
|
|
58
|
+
margin: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.dropdownWrapper {
|
|
62
|
+
display: flex;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.diffPaletteDropdown {
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
border: 1px solid var(--ps-ui-border);
|
|
68
|
+
border-radius: 4px;
|
|
69
|
+
padding: 4px 8px;
|
|
70
|
+
background-color: var(--ps-immutable-off-white);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.diffPaletteDropdown:hover {
|
|
74
|
+
background-color: var(--ps-ui-element-bg-highlight);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.dropdownItem {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
gap: 8px;
|
|
81
|
+
margin-top: 4px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.dropdownItem svg {
|
|
85
|
+
width: 16px;
|
|
86
|
+
height: 16px;
|
|
87
|
+
flex-shrink: 0;
|
|
40
88
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx
|
|
2
|
+
// 差分火焰图图例区域的「调色板选择下拉框」组件,用于切换色带样式
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import cx from 'classnames';
|
|
4
|
-
import useResizeObserver from '@react-hook/resize-observer';
|
|
5
5
|
import {
|
|
6
6
|
ColorBlindPalette,
|
|
7
7
|
DefaultPalette,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from './colorPalette';
|
|
10
10
|
import DiffLegend from './DiffLegend';
|
|
11
11
|
import CheckIcon from './CheckIcon';
|
|
12
|
-
//
|
|
12
|
+
// 在把通用 UI 抽成独立包之前,临时复用 shims 目录下的 Dropdown 封装
|
|
13
13
|
// eslint-disable-next-line
|
|
14
14
|
import Dropdown, { MenuItem, MenuButton } from '../../shims/Dropdown';
|
|
15
15
|
// eslint-disable-next-line
|
|
@@ -18,10 +18,13 @@ import dropdownStyles from '../../shims/Dropdown.module.scss';
|
|
|
18
18
|
import styles from './DiffLegendPaletteDropdown.module.css';
|
|
19
19
|
import { useFlamegraphI18n } from '../../i18n';
|
|
20
20
|
|
|
21
|
+
// 当前支持的调色板列表(默认 + 色盲友好)
|
|
21
22
|
const paletteList = [DefaultPalette, ColorBlindPalette];
|
|
22
23
|
|
|
23
24
|
interface DiffLegendPaletteDropdownProps {
|
|
25
|
+
// 当前选中的调色板
|
|
24
26
|
palette: FlamegraphPalette;
|
|
27
|
+
// 调色板变化回调
|
|
25
28
|
onChange: (p: FlamegraphPalette) => void;
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -29,101 +32,69 @@ export const DiffLegendPaletteDropdown = (
|
|
|
29
32
|
props: DiffLegendPaletteDropdownProps
|
|
30
33
|
) => {
|
|
31
34
|
const { palette = DefaultPalette, onChange } = props;
|
|
32
|
-
const legendRef = React.useRef<HTMLDivElement>(null);
|
|
33
|
-
const showMode = useSizeMode(legendRef);
|
|
34
|
-
|
|
35
35
|
const messages = useFlamegraphI18n();
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// 获取调色板的显示名称(优先走 i18n 文案)
|
|
38
|
+
const getPaletteName = (p: FlamegraphPalette) => {
|
|
39
|
+
if (p.name === 'Default') {
|
|
39
40
|
return messages.paletteDefaultName;
|
|
40
41
|
}
|
|
41
|
-
if (name === 'Color Blind') {
|
|
42
|
+
if (p.name === 'Color Blind') {
|
|
42
43
|
return messages.paletteColorBlindName;
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
return name;
|
|
45
|
+
return p.name;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{messages.diffLegendRemovedLabel}
|
|
53
|
-
</p>
|
|
54
|
-
<p style={{ color: palette.badColor.rgb().string() }}>
|
|
55
|
-
{messages.diffLegendAddedLabel}
|
|
56
|
-
</p>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<div ref={legendRef} className={styles.dropdownWrapper}>
|
|
60
|
-
<Dropdown
|
|
61
|
-
label={messages.diffLegendSelectPalette}
|
|
62
|
-
align="end"
|
|
63
|
-
menuButton={
|
|
64
|
-
<MenuButton
|
|
65
|
-
className={cx(
|
|
66
|
-
// eslint-disable-next-line
|
|
67
|
-
dropdownStyles.dropdownMenuButton,
|
|
68
|
-
styles.diffPaletteDropdown
|
|
69
|
-
)}
|
|
70
|
-
>
|
|
71
|
-
<DiffLegend palette={palette} showMode={showMode} />
|
|
72
|
-
</MenuButton>
|
|
73
|
-
}
|
|
74
|
-
onItemClick={(e) => onChange(e.value)}
|
|
75
|
-
>
|
|
76
|
-
{paletteList.map((p) => (
|
|
77
|
-
<MenuItem key={p.name} value={p}>
|
|
78
|
-
<div>
|
|
79
|
-
<label>{renderPaletteLabel(p.name)}</label>
|
|
80
|
-
<div className={styles.dropdownItem}>
|
|
81
|
-
<DiffLegend palette={p} showMode={showMode} />
|
|
82
|
-
|
|
83
|
-
{p === palette ? <CheckIcon /> : null}
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</MenuItem>
|
|
87
|
-
))}
|
|
88
|
-
</Dropdown>
|
|
89
|
-
</div>
|
|
90
|
-
</>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* TODO: unify this and toolbar's
|
|
96
|
-
* Custom hook that returns the size ('large' | 'small')
|
|
97
|
-
* that should be displayed
|
|
98
|
-
* based on the toolbar width
|
|
99
|
-
*/
|
|
100
|
-
// arbitrary value
|
|
101
|
-
// as a simple heuristic, try to run the comparison view
|
|
102
|
-
// and see when the buttons start to overlap
|
|
103
|
-
const WIDTH_THRESHOLD = 13 * 37;
|
|
104
|
-
const useSizeMode = (target: React.RefObject<HTMLDivElement>) => {
|
|
105
|
-
const [size, setSize] = React.useState<'large' | 'small'>('large');
|
|
106
|
-
|
|
107
|
-
const calcMode = (width: number) => {
|
|
108
|
-
if (width < WIDTH_THRESHOLD) {
|
|
109
|
-
return 'small';
|
|
48
|
+
// 获取调色板的颜色描述(用于下拉菜单中的辅助说明,同样走 i18n)
|
|
49
|
+
const getPaletteColorDesc = (p: FlamegraphPalette) => {
|
|
50
|
+
if (p.name === 'Default') {
|
|
51
|
+
return messages.paletteDefaultDesc;
|
|
110
52
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
React.useLayoutEffect(() => {
|
|
115
|
-
if (target.current) {
|
|
116
|
-
const { width } = target.current.getBoundingClientRect();
|
|
117
|
-
|
|
118
|
-
setSize(calcMode(width));
|
|
53
|
+
if (p.name === 'Color Blind') {
|
|
54
|
+
return messages.paletteColorBlindDesc;
|
|
119
55
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
useResizeObserver(target, (entry: ResizeObserverEntry) => {
|
|
123
|
-
setSize(calcMode(entry.contentRect.width));
|
|
124
|
-
});
|
|
56
|
+
return '';
|
|
57
|
+
};
|
|
125
58
|
|
|
126
|
-
return
|
|
59
|
+
return (
|
|
60
|
+
<div className={styles.container}>
|
|
61
|
+
<Dropdown
|
|
62
|
+
// 下拉菜单的无障碍 label 文案(i18n)
|
|
63
|
+
label={messages.diffLegendSelectPalette}
|
|
64
|
+
align="end"
|
|
65
|
+
menuButton={
|
|
66
|
+
<MenuButton
|
|
67
|
+
className={cx(
|
|
68
|
+
dropdownStyles.dropdownMenuButton,
|
|
69
|
+
styles.triggerButton
|
|
70
|
+
)}
|
|
71
|
+
>
|
|
72
|
+
{/* 触发按钮:当前色带预览 + 下拉箭头 */}
|
|
73
|
+
<DiffLegend palette={palette} showMode="small" />
|
|
74
|
+
<span className={styles.dropdownArrow}>▼</span>
|
|
75
|
+
</MenuButton>
|
|
76
|
+
}
|
|
77
|
+
onItemClick={(e) => {
|
|
78
|
+
// e.value 是可选值,点击菜单项时带出的 palette 对象
|
|
79
|
+
if (e.value) {
|
|
80
|
+
onChange(e.value as FlamegraphPalette);
|
|
81
|
+
}
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
{paletteList.map((p) => (
|
|
85
|
+
<MenuItem key={p.name} value={p}>
|
|
86
|
+
<div className={styles.menuItem}>
|
|
87
|
+
<span className={styles.menuItemText}>
|
|
88
|
+
{getPaletteName(p)} {getPaletteColorDesc(p)}
|
|
89
|
+
</span>
|
|
90
|
+
{/* 当前选中的调色板右侧展示对勾图标 */}
|
|
91
|
+
{p.name === palette.name && <CheckIcon />}
|
|
92
|
+
</div>
|
|
93
|
+
</MenuItem>
|
|
94
|
+
))}
|
|
95
|
+
</Dropdown>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
127
98
|
};
|
|
128
99
|
|
|
129
100
|
export default DiffLegendPaletteDropdown;
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
+
// src/FlameGraph/FlameGraphComponent/Header.tsx
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { Flamebearer } from '../../models';
|
|
3
4
|
import styles from './Header.module.css';
|
|
4
|
-
import { FlamegraphPalette } from './colorPalette';
|
|
5
|
-
import { DiffLegendPaletteDropdown } from './DiffLegendPaletteDropdown';
|
|
6
5
|
|
|
7
6
|
interface HeaderProps {
|
|
8
7
|
format: Flamebearer['format'];
|
|
9
8
|
units: Flamebearer['units'];
|
|
10
|
-
|
|
11
|
-
palette: FlamegraphPalette;
|
|
12
|
-
setPalette: (p: FlamegraphPalette) => void;
|
|
13
9
|
toolbarVisible?: boolean;
|
|
14
10
|
}
|
|
11
|
+
|
|
15
12
|
export default function Header(props: HeaderProps) {
|
|
16
|
-
const { format, units,
|
|
13
|
+
const { format, units, toolbarVisible } = props;
|
|
17
14
|
|
|
18
15
|
const unitsToFlamegraphTitle = {
|
|
19
16
|
objects: 'number of objects in RAM per function',
|
|
@@ -28,41 +25,31 @@ export default function Header(props: HeaderProps) {
|
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
const getTitle = () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
case 'double': {
|
|
49
|
-
return (
|
|
50
|
-
<>
|
|
51
|
-
<DiffLegendPaletteDropdown
|
|
52
|
-
palette={palette}
|
|
53
|
-
onChange={setPalette}
|
|
54
|
-
/>
|
|
55
|
-
</>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
default:
|
|
60
|
-
throw new Error(`unexpected format ${format}`);
|
|
28
|
+
// 只有 single 模式才显示标题
|
|
29
|
+
// double 模式的 DiffLegend 已移到 Toolbar
|
|
30
|
+
if (format === 'single') {
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
className={`${styles.row} ${styles.flamegraphTitle}`}
|
|
34
|
+
role="heading"
|
|
35
|
+
aria-level={2}
|
|
36
|
+
>
|
|
37
|
+
{unitsToFlamegraphTitle[units] && (
|
|
38
|
+
<>Frame width represents {unitsToFlamegraphTitle[units]}</>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
61
42
|
}
|
|
43
|
+
return null;
|
|
62
44
|
};
|
|
63
45
|
|
|
64
46
|
const title = toolbarVisible ? getTitle() : null;
|
|
65
47
|
|
|
48
|
+
// 如果没有内容要显示,返回 null 避免占用空间
|
|
49
|
+
if (!title) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
66
53
|
return (
|
|
67
54
|
<div className={styles.flamegraphHeader}>
|
|
68
55
|
<div>{title}</div>
|
|
@@ -53,6 +53,9 @@ interface FlamegraphProps {
|
|
|
53
53
|
headerVisible?: boolean;
|
|
54
54
|
disableClick?: boolean;
|
|
55
55
|
showSingleLevel?: boolean;
|
|
56
|
+
|
|
57
|
+
/** 是否显示右键菜单中的「打开 Sandwich 视图」项,默认 true */
|
|
58
|
+
enableSandwichView?: boolean;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
@@ -79,6 +82,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
79
82
|
setActiveItem,
|
|
80
83
|
selectedItem,
|
|
81
84
|
updateView,
|
|
85
|
+
enableSandwichView = true,
|
|
82
86
|
} = props;
|
|
83
87
|
|
|
84
88
|
const { onZoom, onReset, isDirty, onFocusOnNode } = props;
|
|
@@ -105,7 +109,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
105
109
|
);
|
|
106
110
|
|
|
107
111
|
opt.match({
|
|
108
|
-
Nothing: () => {},
|
|
112
|
+
Nothing: () => { },
|
|
109
113
|
Just: (bar) => {
|
|
110
114
|
zoom.match({
|
|
111
115
|
Nothing: () => {
|
|
@@ -160,7 +164,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
160
164
|
);
|
|
161
165
|
|
|
162
166
|
const onClick = bar.mapOrElse(
|
|
163
|
-
() => () => {},
|
|
167
|
+
() => () => { },
|
|
164
168
|
(f) => onFocusOnNode.bind(null, f.i, f.j)
|
|
165
169
|
);
|
|
166
170
|
|
|
@@ -210,15 +214,14 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
210
214
|
};
|
|
211
215
|
|
|
212
216
|
const OpenInSandwichViewItem = () => {
|
|
213
|
-
|
|
217
|
+
// 如果没有 updateView,或者不开启三明治视图菜单,直接不渲染
|
|
218
|
+
if (!updateView || !enableSandwichView) {
|
|
214
219
|
return null;
|
|
215
220
|
}
|
|
216
221
|
|
|
217
222
|
const handleClick = () => {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
setActiveItem({ name: barName });
|
|
221
|
-
}
|
|
223
|
+
updateView('sandwich');
|
|
224
|
+
setActiveItem({ name: barName });
|
|
222
225
|
};
|
|
223
226
|
|
|
224
227
|
return (
|
|
@@ -275,6 +278,7 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
275
278
|
setActiveItem,
|
|
276
279
|
updateView,
|
|
277
280
|
i18n,
|
|
281
|
+
enableSandwichView,
|
|
278
282
|
]
|
|
279
283
|
);
|
|
280
284
|
|
|
@@ -341,12 +345,12 @@ export default function FlameGraphComponent(props: FlamegraphProps) {
|
|
|
341
345
|
'vertical-orientation': flamebearer.format === 'double',
|
|
342
346
|
})}
|
|
343
347
|
>
|
|
348
|
+
{/* Header 已简化,仅在 single 模式下显示标题 */}
|
|
349
|
+
{/* DiffLegend 已移到 Toolbar */}
|
|
344
350
|
{headerVisible && (
|
|
345
351
|
<Header
|
|
346
352
|
format={flamebearer.format}
|
|
347
353
|
units={flamebearer.units}
|
|
348
|
-
palette={palette}
|
|
349
|
-
setPalette={setPalette}
|
|
350
354
|
toolbarVisible={toolbarVisible}
|
|
351
355
|
/>
|
|
352
356
|
)}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// src/FlameGraph/FlameGraphRenderer.tsx
|
|
1
2
|
/* eslint-disable react/no-unused-state */
|
|
2
3
|
/* eslint-disable no-bitwise */
|
|
3
4
|
/* eslint-disable react/no-access-state-in-setstate */
|
|
@@ -60,6 +61,7 @@ export interface FlamegraphRendererProps {
|
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
children?: ReactNode;
|
|
64
|
+
enableSandwichView?: boolean;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
interface FlamegraphRendererState {
|
|
@@ -101,7 +103,7 @@ class FlameGraphRenderer extends Component<
|
|
|
101
103
|
|
|
102
104
|
// eslint-disable-next-line react/static-property-placement
|
|
103
105
|
static defaultProps = {
|
|
104
|
-
showCredit:
|
|
106
|
+
showCredit: false,
|
|
105
107
|
};
|
|
106
108
|
|
|
107
109
|
constructor(props: FlamegraphRendererProps) {
|
|
@@ -344,6 +346,11 @@ class FlameGraphRenderer extends Component<
|
|
|
344
346
|
return this.props.showToolbar !== undefined ? this.props.showToolbar : true;
|
|
345
347
|
}
|
|
346
348
|
|
|
349
|
+
// 统一的 setPalette 方法
|
|
350
|
+
handleSetPalette = (p: typeof DefaultPalette) => {
|
|
351
|
+
this.setState({ palette: p });
|
|
352
|
+
};
|
|
353
|
+
|
|
347
354
|
render = () => {
|
|
348
355
|
// This is necessary because the order switches depending on single vs comparison view
|
|
349
356
|
const tablePane = (
|
|
@@ -390,11 +397,8 @@ class FlameGraphRenderer extends Component<
|
|
|
390
397
|
isDirty={this.isDirty}
|
|
391
398
|
palette={this.state.palette}
|
|
392
399
|
toolbarVisible={toolbarVisible}
|
|
393
|
-
setPalette={
|
|
394
|
-
|
|
395
|
-
palette: p,
|
|
396
|
-
})
|
|
397
|
-
}
|
|
400
|
+
setPalette={this.handleSetPalette}
|
|
401
|
+
enableSandwichView={this.props.enableSandwichView}
|
|
398
402
|
/>
|
|
399
403
|
);
|
|
400
404
|
|
|
@@ -446,11 +450,7 @@ class FlameGraphRenderer extends Component<
|
|
|
446
450
|
isDirty={this.isDirty}
|
|
447
451
|
palette={this.state.palette}
|
|
448
452
|
toolbarVisible={toolbarVisible}
|
|
449
|
-
setPalette={
|
|
450
|
-
this.setState({
|
|
451
|
-
palette: p,
|
|
452
|
-
})
|
|
453
|
-
}
|
|
453
|
+
setPalette={this.handleSetPalette}
|
|
454
454
|
{...myCustomParams}
|
|
455
455
|
/>
|
|
456
456
|
);
|
|
@@ -535,6 +535,9 @@ class FlameGraphRenderer extends Component<
|
|
|
535
535
|
highlightQuery={this.state.searchQuery}
|
|
536
536
|
onFocusOnSubtree={this.onFocusOnNode}
|
|
537
537
|
ExportData={this.props.ExportData}
|
|
538
|
+
// 添加 palette 和 setPalette props
|
|
539
|
+
palette={this.state.palette}
|
|
540
|
+
setPalette={this.handleSetPalette}
|
|
538
541
|
/>
|
|
539
542
|
)}
|
|
540
543
|
{this.props.children}
|