@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.
Files changed (33) hide show
  1. package/README.md +211 -62
  2. package/dist/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.d.ts.map +1 -1
  3. package/dist/FlameGraph/FlameGraphComponent/Header.d.ts +0 -3
  4. package/dist/FlameGraph/FlameGraphComponent/Header.d.ts.map +1 -1
  5. package/dist/FlameGraph/FlameGraphComponent/index.d.ts +2 -0
  6. package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -1
  7. package/dist/FlameGraph/FlameGraphRenderer.d.ts +2 -0
  8. package/dist/FlameGraph/FlameGraphRenderer.d.ts.map +1 -1
  9. package/dist/FlamegraphRenderer.d.ts +23 -5
  10. package/dist/FlamegraphRenderer.d.ts.map +1 -1
  11. package/dist/Toolbar.d.ts +4 -1
  12. package/dist/Toolbar.d.ts.map +1 -1
  13. package/dist/i18n.d.ts +2 -0
  14. package/dist/i18n.d.ts.map +1 -1
  15. package/dist/index.cjs.js +4 -4
  16. package/dist/index.cjs.js.map +1 -1
  17. package/dist/index.esm.js +4 -4
  18. package/dist/index.esm.js.map +1 -1
  19. package/dist/index.node.cjs.js +6 -1
  20. package/dist/index.node.cjs.js.map +1 -1
  21. package/dist/index.node.esm.js +8 -3
  22. package/dist/index.node.esm.js.map +1 -1
  23. package/package.json +4 -2
  24. package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.module.css +69 -21
  25. package/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx +57 -86
  26. package/src/FlameGraph/FlameGraphComponent/Header.tsx +23 -36
  27. package/src/FlameGraph/FlameGraphComponent/index.tsx +13 -9
  28. package/src/FlameGraph/FlameGraphRenderer.tsx +14 -11
  29. package/src/FlamegraphRenderer.tsx +103 -20
  30. package/src/SharedQueryInput.module.scss +5 -2
  31. package/src/Toolbar.module.scss +13 -0
  32. package/src/Toolbar.tsx +29 -3
  33. 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
- type FlamegraphMessages,
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
- export const FlamegraphRenderer: React.FC<FlamegraphRendererProps> = (
41
- props
42
- ) => {
43
- const { colorMode = 'dark', i18n, ...restProps } = props;
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
- is="span"
50
- data-flamegraph-color-mode={colorMode}
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
 
@@ -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 = 175;
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
- <div>
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
- <div>
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);