@kylincloud/flamegraph 0.35.7 → 0.35.9
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 +211 -62
- 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/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 -2
- 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/SharedQueryInput.module.scss +5 -2
- package/src/Toolbar.module.scss +13 -0
- package/src/Toolbar.tsx +29 -3
- package/src/i18n.tsx +11 -2
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
// src/FlamegraphRenderer.tsx
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import FlameGraphRenderer
|
|
3
|
+
import FlameGraphRenderer from './FlameGraph/FlameGraphRenderer';
|
|
4
|
+
import type {
|
|
4
5
|
FlamegraphRendererProps as InnerFlamegraphRendererProps,
|
|
5
6
|
} from './FlameGraph/FlameGraphRenderer';
|
|
7
|
+
|
|
6
8
|
import './sass/flamegraph.scss';
|
|
9
|
+
|
|
7
10
|
import {
|
|
8
11
|
FlamegraphI18nProvider,
|
|
9
|
-
|
|
12
|
+
defaultMessages,
|
|
13
|
+
zhCNMessages,
|
|
10
14
|
} from './i18n';
|
|
15
|
+
import type { FlamegraphMessages } from './i18n';
|
|
11
16
|
|
|
12
17
|
// 原项目里这个值由 webpack 注入,这里直接关掉 logo
|
|
13
18
|
const overrideProps = {
|
|
14
19
|
showPyroscopeLogo: false,
|
|
15
20
|
};
|
|
16
21
|
|
|
22
|
+
/** 对外暴露的 locale 类型 */
|
|
23
|
+
export type FlamegraphLocale = 'auto' | 'en' | 'zh-CN';
|
|
24
|
+
|
|
17
25
|
export type FlamegraphRendererProps = Omit<
|
|
18
26
|
InnerFlamegraphRendererProps,
|
|
19
27
|
'showPyroscopeLogo'
|
|
20
28
|
> & {
|
|
21
29
|
/** 颜色模式:原生 light/dark + 新增 kylin */
|
|
22
30
|
colorMode?: 'light' | 'dark' | 'kylin';
|
|
23
|
-
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 文案覆盖:
|
|
34
|
+
* - 如果显式传入 i18n,则优先使用这一套(不再根据 locale 推断)
|
|
35
|
+
* - 如果不传,则根据 locale(或浏览器语言)自动选择内置英文 / 中文
|
|
36
|
+
*/
|
|
24
37
|
i18n?: Partial<FlamegraphMessages>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 语言设置:
|
|
41
|
+
* - 不传时等价于 "auto"
|
|
42
|
+
* - "auto" 表示根据浏览器语言(navigator.language)自动选择
|
|
43
|
+
* - "en" / "zh-CN" 为强制指定
|
|
44
|
+
*/
|
|
45
|
+
locale?: FlamegraphLocale;
|
|
46
|
+
/** 是否开启三明治视图菜单 */
|
|
47
|
+
sandwich?: boolean;
|
|
25
48
|
};
|
|
26
49
|
|
|
27
50
|
// 让 TS 认识自定义标签 <pyro-flamegraph>
|
|
@@ -32,30 +55,90 @@ declare global {
|
|
|
32
55
|
'pyro-flamegraph': React.DetailedHTMLProps<
|
|
33
56
|
React.HTMLAttributes<HTMLElement>,
|
|
34
57
|
HTMLElement
|
|
35
|
-
|
|
58
|
+
> & {
|
|
59
|
+
profile?: any;
|
|
60
|
+
};
|
|
36
61
|
}
|
|
37
62
|
}
|
|
38
63
|
}
|
|
39
64
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
/**
|
|
66
|
+
* 浏览器语言 -> 内部 locale
|
|
67
|
+
* SSR / 非浏览器环境时默认 en
|
|
68
|
+
*/
|
|
69
|
+
const detectBrowserLocale = (): Exclude<FlamegraphLocale, 'auto'> => {
|
|
70
|
+
if (typeof navigator === 'undefined' || !navigator.language) {
|
|
71
|
+
return 'en';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const lang = navigator.language.toLowerCase();
|
|
75
|
+
|
|
76
|
+
if (lang.startsWith('zh')) {
|
|
77
|
+
return 'zh-CN';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return 'en';
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 决定实际使用的文案:
|
|
85
|
+
* 1. 如果调用方显式传了 i18n,则直接使用 i18n(优先级最高);
|
|
86
|
+
* 2. 否则根据 locale / 浏览器语言选择内置英文或中文语言包。
|
|
87
|
+
*/
|
|
88
|
+
const resolveMessages = (
|
|
89
|
+
locale: FlamegraphLocale | undefined,
|
|
90
|
+
i18n?: Partial<FlamegraphMessages>
|
|
91
|
+
): Partial<FlamegraphMessages> => {
|
|
92
|
+
// 业务显式传入 i18n,则不再干预
|
|
93
|
+
if (i18n) {
|
|
94
|
+
return i18n;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const effectiveLocale = locale ?? 'auto';
|
|
98
|
+
const finalLocale =
|
|
99
|
+
effectiveLocale === 'auto' ? detectBrowserLocale() : effectiveLocale;
|
|
100
|
+
|
|
101
|
+
if (finalLocale === 'zh-CN') {
|
|
102
|
+
return zhCNMessages;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 默认英文
|
|
106
|
+
return defaultMessages;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** 根据 colorMode 生成一个主题 class(可按你自己的 SCSS 改) */
|
|
110
|
+
const getThemeClass = (colorMode: FlamegraphRendererProps['colorMode']) => {
|
|
111
|
+
switch (colorMode) {
|
|
112
|
+
case 'dark':
|
|
113
|
+
return 'ps-theme-dark';
|
|
114
|
+
case 'kylin':
|
|
115
|
+
return 'ps-theme-kylin';
|
|
116
|
+
case 'light':
|
|
117
|
+
default:
|
|
118
|
+
return 'ps-theme-light';
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const FlamegraphRenderer: React.FC<FlamegraphRendererProps> = (props) => {
|
|
123
|
+
const { i18n, locale, colorMode = 'light', sandwich = true,...rest } = props;
|
|
124
|
+
|
|
125
|
+
const messages = React.useMemo(
|
|
126
|
+
() => resolveMessages(locale, i18n),
|
|
127
|
+
[locale, i18n]
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const themeClass = React.useMemo(
|
|
131
|
+
() => getThemeClass(colorMode),
|
|
132
|
+
[colorMode]
|
|
133
|
+
);
|
|
44
134
|
|
|
45
|
-
// 虽然 pyro-flamegraph 不是合法的 HTML 元素
|
|
46
|
-
// 但它只是作为样式 scope 容器存在(配合 sass/flamegraph.scss 里的一堆选择器)
|
|
47
135
|
return (
|
|
48
|
-
<pyro-flamegraph
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
>
|
|
52
|
-
<FlamegraphI18nProvider messages={i18n}>
|
|
53
|
-
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
|
54
|
-
<FlameGraphRenderer
|
|
55
|
-
{...(restProps as InnerFlamegraphRendererProps)}
|
|
56
|
-
{...overrideProps}
|
|
57
|
-
/>
|
|
136
|
+
<pyro-flamegraph className={themeClass}>
|
|
137
|
+
<FlamegraphI18nProvider messages={messages}>
|
|
138
|
+
<FlameGraphRenderer {...overrideProps}enableSandwichView={sandwich} {...rest} />
|
|
58
139
|
</FlamegraphI18nProvider>
|
|
59
140
|
</pyro-flamegraph>
|
|
60
141
|
);
|
|
61
142
|
};
|
|
143
|
+
|
|
144
|
+
export { FlamegraphRenderer };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/* src/SharedQueryInput.module.scss */
|
|
2
|
+
|
|
1
3
|
.wrapper {
|
|
2
4
|
display: flex;
|
|
3
5
|
flex-direction: row;
|
|
4
6
|
align-items: center;
|
|
5
|
-
flex-grow: 1
|
|
7
|
+
/* 移除 flex-grow: 1,让宽度由父组件控制 */
|
|
8
|
+
width: 100%;
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
.search {
|
|
@@ -12,7 +15,7 @@
|
|
|
12
15
|
margin-right: 1.5px;
|
|
13
16
|
border: 1px solid var(--ps-ui-border);
|
|
14
17
|
display: flex;
|
|
15
|
-
flex-grow: 1
|
|
18
|
+
/* 移除 flex-grow: 1 */
|
|
16
19
|
height: 37px;
|
|
17
20
|
width: 100%;
|
|
18
21
|
|
package/src/Toolbar.module.scss
CHANGED
|
@@ -13,6 +13,19 @@ $buttonHeight: 37px;
|
|
|
13
13
|
align-items: center;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
// 搜索框包裹器 - 固定宽度 360px
|
|
17
|
+
.searchWrapper {
|
|
18
|
+
width: 360px;
|
|
19
|
+
flex-shrink: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 右侧区域:色带下拉 + 工具按钮
|
|
23
|
+
.rightSection {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: 4px;
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
.viewType {
|
|
17
30
|
display: flex;
|
|
18
31
|
flex-direction: row;
|
package/src/Toolbar.tsx
CHANGED
|
@@ -25,6 +25,8 @@ import { FitModes } from './fitMode/fitMode';
|
|
|
25
25
|
import SharedQueryInput from './SharedQueryInput';
|
|
26
26
|
import type { ViewTypes } from './FlameGraph/FlameGraphComponent/viewTypes';
|
|
27
27
|
import type { FlamegraphRendererProps } from './FlameGraph/FlameGraphRenderer';
|
|
28
|
+
import { FlamegraphPalette } from './FlameGraph/FlameGraphComponent/colorPalette';
|
|
29
|
+
import { DiffLegendPaletteDropdown } from './FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown';
|
|
28
30
|
import {
|
|
29
31
|
TableIcon,
|
|
30
32
|
TablePlusFlamegraphIcon,
|
|
@@ -43,7 +45,7 @@ import {
|
|
|
43
45
|
const cx = classNames.bind(styles);
|
|
44
46
|
|
|
45
47
|
const DIVIDER_WIDTH = 5;
|
|
46
|
-
const QUERY_INPUT_WIDTH =
|
|
48
|
+
const QUERY_INPUT_WIDTH = 360;
|
|
47
49
|
const LEFT_MARGIN = 2;
|
|
48
50
|
const RIGHT_MARGIN = 2;
|
|
49
51
|
const TOOLBAR_SQUARE_WIDTH = 40 + LEFT_MARGIN + RIGHT_MARGIN;
|
|
@@ -135,6 +137,10 @@ export interface ProfileHeaderProps {
|
|
|
135
137
|
selectedNode: Maybe<{ i: number; j: number }>;
|
|
136
138
|
onFocusOnSubtree: (i: number, j: number) => void;
|
|
137
139
|
sharedQuery?: FlamegraphRendererProps['sharedQuery'];
|
|
140
|
+
|
|
141
|
+
// 用于 diff 模式的调色板
|
|
142
|
+
palette?: FlamegraphPalette;
|
|
143
|
+
setPalette?: (p: FlamegraphPalette) => void;
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
const Divider = () => <div className={styles.divider} />;
|
|
@@ -160,10 +166,15 @@ const Toolbar = memo(
|
|
|
160
166
|
enableChangingDisplay = true,
|
|
161
167
|
sharedQuery,
|
|
162
168
|
ExportData,
|
|
169
|
+
palette,
|
|
170
|
+
setPalette,
|
|
163
171
|
}: ProfileHeaderProps) => {
|
|
164
172
|
const toolbarRef = useRef<HTMLDivElement>(null);
|
|
165
173
|
const i18n = useFlamegraphI18n();
|
|
166
174
|
|
|
175
|
+
// 是否显示调色板选择器(仅在 diff 模式且有 palette 时显示)
|
|
176
|
+
const showPaletteDropdown = flamegraphType === 'double' && palette && setPalette;
|
|
177
|
+
|
|
167
178
|
const fitModeItem = {
|
|
168
179
|
el: (
|
|
169
180
|
<>
|
|
@@ -247,7 +258,8 @@ const Toolbar = memo(
|
|
|
247
258
|
return (
|
|
248
259
|
<div role="toolbar" ref={toolbarRef}>
|
|
249
260
|
<div className={styles.navbar}>
|
|
250
|
-
|
|
261
|
+
{/* 左侧:搜索框 */}
|
|
262
|
+
<div className={styles.searchWrapper}>
|
|
251
263
|
<SharedQueryInput
|
|
252
264
|
width={QUERY_INPUT_WIDTH}
|
|
253
265
|
onHighlightChange={handleSearchChange}
|
|
@@ -255,7 +267,20 @@ const Toolbar = memo(
|
|
|
255
267
|
sharedQuery={sharedQuery}
|
|
256
268
|
/>
|
|
257
269
|
</div>
|
|
258
|
-
|
|
270
|
+
|
|
271
|
+
{/* 右侧:色带下拉 + 工具按钮 */}
|
|
272
|
+
<div className={styles.rightSection}>
|
|
273
|
+
{/* diff 模式下显示调色板选择器 */}
|
|
274
|
+
{showPaletteDropdown && (
|
|
275
|
+
<>
|
|
276
|
+
<DiffLegendPaletteDropdown
|
|
277
|
+
palette={palette}
|
|
278
|
+
onChange={setPalette}
|
|
279
|
+
/>
|
|
280
|
+
<Divider />
|
|
281
|
+
</>
|
|
282
|
+
)}
|
|
283
|
+
|
|
259
284
|
<div className={styles.itemsContainer}>
|
|
260
285
|
{toolbarFilteredItems.visible.map((v, i) => (
|
|
261
286
|
// eslint-disable-next-line react/no-array-index-key
|
|
@@ -278,6 +303,7 @@ const Toolbar = memo(
|
|
|
278
303
|
)}
|
|
279
304
|
</div>
|
|
280
305
|
</div>
|
|
306
|
+
|
|
281
307
|
{!isCollapsed && (
|
|
282
308
|
<div className={styles.navbarCollapsedItems}>
|
|
283
309
|
{toolbarFilteredItems.hidden.map((v, i) => (
|
package/src/i18n.tsx
CHANGED
|
@@ -60,6 +60,9 @@ export type FlamegraphMessages = {
|
|
|
60
60
|
diffLegendSelectPalette: string;
|
|
61
61
|
paletteDefaultName: string;
|
|
62
62
|
paletteColorBlindName: string;
|
|
63
|
+
// 调色板补充描述(出现在下拉菜单里)
|
|
64
|
+
paletteDefaultDesc: string;
|
|
65
|
+
paletteColorBlindDesc: string;
|
|
63
66
|
|
|
64
67
|
// 搜索框 & 多视图搜索联动
|
|
65
68
|
searchPlaceholder: string;
|
|
@@ -206,11 +209,14 @@ export const defaultMessages: FlamegraphMessages = {
|
|
|
206
209
|
diffLegendSelectPalette: 'Select a palette',
|
|
207
210
|
paletteDefaultName: 'Default',
|
|
208
211
|
paletteColorBlindName: 'Color Blind',
|
|
212
|
+
// 调色板补充描述(英文)
|
|
213
|
+
paletteDefaultDesc: '(green to red)',
|
|
214
|
+
paletteColorBlindDesc: '(blue to red)',
|
|
209
215
|
|
|
210
216
|
// 搜索框 & 多视图搜索联动
|
|
211
217
|
searchPlaceholder: 'Search...',
|
|
212
218
|
syncSearchBars: 'Sync Search Bars',
|
|
213
|
-
unsyncSearchBars: 'Unsync Search Bars'
|
|
219
|
+
unsyncSearchBars: 'Unsync Search Bars',
|
|
214
220
|
};
|
|
215
221
|
|
|
216
222
|
export const zhCNMessages: FlamegraphMessages = {
|
|
@@ -257,11 +263,14 @@ export const zhCNMessages: FlamegraphMessages = {
|
|
|
257
263
|
diffLegendSelectPalette: '选择颜色方案',
|
|
258
264
|
paletteDefaultName: '默认',
|
|
259
265
|
paletteColorBlindName: '色盲模式',
|
|
266
|
+
// 调色板补充描述(中文)
|
|
267
|
+
paletteDefaultDesc: '(绿色 → 红色)',
|
|
268
|
+
paletteColorBlindDesc: '(蓝色 → 红色)',
|
|
260
269
|
|
|
261
270
|
// 搜索框 & 多视图搜索联动
|
|
262
271
|
searchPlaceholder: '搜索...',
|
|
263
272
|
syncSearchBars: '同步搜索栏',
|
|
264
|
-
unsyncSearchBars: '取消同步搜索栏'
|
|
273
|
+
unsyncSearchBars: '取消同步搜索栏',
|
|
265
274
|
};
|
|
266
275
|
|
|
267
276
|
const I18nContext = createContext<FlamegraphMessages>(defaultMessages);
|