@parca/profile 0.19.23 → 0.19.25

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 (46) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
  3. package/dist/ProfileView/components/ColorStackLegend.js +0 -1
  4. package/dist/ProfileView/components/DashboardItems/index.d.ts +3 -2
  5. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
  6. package/dist/ProfileView/components/DashboardItems/index.js +2 -2
  7. package/dist/ProfileView/components/ProfileFilters/filterPresets.d.ts +11 -0
  8. package/dist/ProfileView/components/ProfileFilters/filterPresets.d.ts.map +1 -0
  9. package/dist/ProfileView/components/ProfileFilters/filterPresets.js +64 -0
  10. package/dist/ProfileView/components/ProfileFilters/index.d.ts.map +1 -1
  11. package/dist/ProfileView/components/ProfileFilters/index.js +54 -9
  12. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.d.ts +2 -0
  13. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.d.ts.map +1 -1
  14. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +58 -4
  15. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts.map +1 -1
  16. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +22 -2
  17. package/dist/ProfileView/index.d.ts +1 -1
  18. package/dist/ProfileView/index.d.ts.map +1 -1
  19. package/dist/ProfileView/index.js +2 -1
  20. package/dist/ProfileView/types/visualization.d.ts +6 -10
  21. package/dist/ProfileView/types/visualization.d.ts.map +1 -1
  22. package/dist/ProfileViewWithData.d.ts.map +1 -1
  23. package/dist/ProfileViewWithData.js +52 -22
  24. package/dist/Sandwich/components/CalleesSection.d.ts +3 -12
  25. package/dist/Sandwich/components/CalleesSection.d.ts.map +1 -1
  26. package/dist/Sandwich/components/CalleesSection.js +2 -4
  27. package/dist/Sandwich/components/CallersSection.d.ts +3 -13
  28. package/dist/Sandwich/components/CallersSection.d.ts.map +1 -1
  29. package/dist/Sandwich/components/CallersSection.js +5 -8
  30. package/dist/Sandwich/index.d.ts +2 -10
  31. package/dist/Sandwich/index.d.ts.map +1 -1
  32. package/dist/Sandwich/index.js +5 -103
  33. package/dist/styles.css +1 -1
  34. package/package.json +6 -6
  35. package/src/ProfileView/components/ColorStackLegend.tsx +0 -2
  36. package/src/ProfileView/components/DashboardItems/index.tsx +4 -12
  37. package/src/ProfileView/components/ProfileFilters/filterPresets.ts +76 -0
  38. package/src/ProfileView/components/ProfileFilters/index.tsx +65 -12
  39. package/src/ProfileView/components/ProfileFilters/useProfileFilters.ts +67 -6
  40. package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts +27 -2
  41. package/src/ProfileView/index.tsx +2 -0
  42. package/src/ProfileView/types/visualization.ts +7 -18
  43. package/src/ProfileViewWithData.tsx +65 -30
  44. package/src/Sandwich/components/CalleesSection.tsx +10 -28
  45. package/src/Sandwich/components/CallersSection.tsx +13 -34
  46. package/src/Sandwich/index.tsx +8 -170
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.19.25](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.24...@parca/profile@0.19.25) (2025-07-21)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.19.24](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.23...@parca/profile@0.19.24) (2025-07-17)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.19.23](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.22...@parca/profile@0.19.23) (2025-07-16)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -1 +1 @@
1
- {"version":3,"file":"ColorStackLegend.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/components/ColorStackLegend.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgB,MAAM,OAAO,CAAC;AAarC,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,QAAA,MAAM,gBAAgB,GAAI,oCAA0C,KAAK,KAAG,KAAK,CAAC,GAAG,CAAC,OAyGrF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"ColorStackLegend.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/components/ColorStackLegend.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgB,MAAM,OAAO,CAAC;AAarC,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,QAAA,MAAM,gBAAgB,GAAI,oCAA0C,KAAK,KAAG,KAAK,CAAC,GAAG,CAAC,OAuGrF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -33,7 +33,6 @@ const ColorStackLegend = ({ mappings, compareMode = false, loading }) => {
33
33
  .filter(f => f.type === 'frame' && f.field === 'binary')
34
34
  .map(f => f.value);
35
35
  }, [appliedFilters]);
36
- console.log('currentBinaryFilters', currentBinaryFilters);
37
36
  const mappingsList = useMappingList(mappings);
38
37
  const mappingColors = useMemo(() => {
39
38
  const colors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
@@ -2,7 +2,7 @@ import { ProfilerOnRenderCallback } from 'react';
2
2
  import { QueryServiceClient } from '@parca/client';
3
3
  import { CurrentPathFrame } from '../../../ProfileFlameGraph/FlameGraphArrow/utils';
4
4
  import { ProfileSource } from '../../../ProfileSource';
5
- import type { FlamegraphData, SourceData, TopTableData, VisualizationType } from '../../types/visualization';
5
+ import type { FlamegraphData, SandwichData, SourceData, TopTableData, VisualizationType } from '../../types/visualization';
6
6
  interface GetDashboardItemProps {
7
7
  type: VisualizationType;
8
8
  isHalfScreen: boolean;
@@ -10,6 +10,7 @@ interface GetDashboardItemProps {
10
10
  flamegraphData: FlamegraphData;
11
11
  flamechartData: FlamegraphData;
12
12
  topTableData?: TopTableData;
13
+ sandwichData: SandwichData;
13
14
  sourceData?: SourceData;
14
15
  profileSource: ProfileSource;
15
16
  total: bigint;
@@ -23,6 +24,6 @@ interface GetDashboardItemProps {
23
24
  };
24
25
  queryClient?: QueryServiceClient;
25
26
  }
26
- export declare const getDashboardItem: ({ type, isHalfScreen, dimensions, flamegraphData, flamechartData, topTableData, sourceData, profileSource, total, filtered, curPathArrow, setNewCurPathArrow, perf, queryClient, }: GetDashboardItemProps) => JSX.Element;
27
+ export declare const getDashboardItem: ({ type, isHalfScreen, dimensions, flamegraphData, flamechartData, topTableData, sourceData, sandwichData, profileSource, total, filtered, curPathArrow, setNewCurPathArrow, perf, }: GetDashboardItemProps) => JSX.Element;
27
28
  export {};
28
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,oLAe9B,qBAAqB,KAAG,GAAG,CAAC,OAyG9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
@@ -17,7 +17,7 @@ import ProfileFlameGraph from '../../../ProfileFlameGraph';
17
17
  import Sandwich from '../../../Sandwich';
18
18
  import { SourceView } from '../../../SourceView';
19
19
  import { Table } from '../../../Table';
20
- export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphData, flamechartData, topTableData, sourceData, profileSource, total, filtered, curPathArrow, setNewCurPathArrow, perf, queryClient, }) => {
20
+ export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphData, flamechartData, topTableData, sourceData, sandwichData, profileSource, total, filtered, curPathArrow, setNewCurPathArrow, perf, }) => {
21
21
  switch (type) {
22
22
  case 'flamegraph':
23
23
  return (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
@@ -37,7 +37,7 @@ export const getDashboardItem = ({ type, isHalfScreen, dimensions, flamegraphDat
37
37
  case 'table':
38
38
  return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), isHalfScreen: isHalfScreen, metadataMappingFiles: flamegraphData.metadataMappingFiles })) : (_jsx(_Fragment, {}));
39
39
  case 'sandwich':
40
- return topTableData != null ? (_jsx(Sandwich, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), metadataMappingFiles: flamegraphData.metadataMappingFiles, profileSource: profileSource, queryClient: queryClient })) : (_jsx(_Fragment, {}));
40
+ return topTableData != null ? (_jsx(Sandwich, { profileSource: profileSource, sandwichData: sandwichData })) : (_jsx(_Fragment, {}));
41
41
  case 'source':
42
42
  return sourceData != null ? (_jsx(SourceView, { loading: sourceData.loading, data: sourceData.data, total: total, filtered: filtered })) : (_jsx(_Fragment, {}));
43
43
  default:
@@ -0,0 +1,11 @@
1
+ import type { ProfileFilter } from '@parca/store';
2
+ export interface FilterPreset {
3
+ key: string;
4
+ name: string;
5
+ description: string;
6
+ filters: Array<Omit<ProfileFilter, 'id'>>;
7
+ }
8
+ export declare const filterPresets: FilterPreset[];
9
+ export declare const isPresetKey: (key: string) => boolean;
10
+ export declare const getPresetByKey: (key: string) => FilterPreset | undefined;
11
+ //# sourceMappingURL=filterPresets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterPresets.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/filterPresets.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;CAC3C;AAED,eAAO,MAAM,aAAa,EAAE,YAAY,EA6CvC,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,OAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,YAAY,GAAG,SAE3D,CAAC"}
@@ -0,0 +1,64 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ export const filterPresets = [
14
+ {
15
+ key: 'go_runtime_expected_off_cpu',
16
+ name: 'Go Runtime Expected Off-CPU',
17
+ description: 'Excludes expected Go runtime blocking functions',
18
+ filters: [
19
+ {
20
+ type: 'stack',
21
+ field: 'function_name',
22
+ matchType: 'not_equal',
23
+ value: 'runtime.usleep',
24
+ },
25
+ {
26
+ type: 'stack',
27
+ field: 'function_name',
28
+ matchType: 'not_equal',
29
+ value: 'runtime.futex',
30
+ },
31
+ ],
32
+ },
33
+ {
34
+ key: 'rust_runtime_expected_off_cpu',
35
+ name: 'Rust Expected Off-CPU',
36
+ description: 'Excludes expected Rust runtime blocking functions',
37
+ filters: [
38
+ {
39
+ type: 'stack',
40
+ field: 'function_name',
41
+ matchType: 'not_equal',
42
+ value: 'parking_lot_core::thread_parker::imp::ThreadParker::futex_wait',
43
+ },
44
+ {
45
+ type: 'stack',
46
+ field: 'function_name',
47
+ matchType: 'not_equal',
48
+ value: 'tokio::runtime::time::Driver::park_internal',
49
+ },
50
+ {
51
+ type: 'stack',
52
+ field: 'function_name',
53
+ matchType: 'not_equal',
54
+ value: 'futex_wait',
55
+ },
56
+ ],
57
+ },
58
+ ];
59
+ export const isPresetKey = (key) => {
60
+ return filterPresets.some(preset => preset.key === key);
61
+ };
62
+ export const getPresetByKey = (key) => {
63
+ return filterPresets.find(preset => preset.key === key);
64
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/index.tsx"],"names":[],"mappings":"AAoBA,OAAO,EAAoB,KAAK,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAE1E,eAAO,MAAM,gBAAgB,GAAI,QAAQ,aAAa,KAAG,OAIxD,CAAC;AA4HF,QAAA,MAAM,cAAc,QAAO,GAAG,CAAC,OA6I9B,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,EAAoB,KAAK,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAE1E,eAAO,MAAM,gBAAgB,GAAI,QAAQ,aAAa,KAAG,OASxD,CAAC;AAyIF,QAAA,MAAM,cAAc,QAAO,GAAG,CAAC,OA+K9B,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -15,8 +15,14 @@ import { useCallback } from 'react';
15
15
  import { Icon } from '@iconify/react';
16
16
  import cx from 'classnames';
17
17
  import { Button, Input, Select } from '@parca/components';
18
+ import { filterPresets, getPresetByKey, isPresetKey } from './filterPresets';
18
19
  import { useProfileFilters } from './useProfileFilters';
19
20
  export const isFilterComplete = (filter) => {
21
+ // For preset filters, only need type and value
22
+ if (filter.type != null && isPresetKey(filter.type)) {
23
+ return filter.value !== '' && filter.type != null;
24
+ }
25
+ // For regular filters, need all fields
20
26
  return (filter.value !== '' && filter.type != null && filter.field != null && filter.matchType != null);
21
27
  };
22
28
  const filterTypeItems = [
@@ -34,6 +40,13 @@ const filterTypeItems = [
34
40
  expanded: (_jsxs(_Fragment, { children: [_jsx("span", { children: "Frame Filter" }), _jsx("br", {}), _jsx("span", { className: "text-xs", children: "Filters individual frames" })] })),
35
41
  },
36
42
  },
43
+ ...filterPresets.map(preset => ({
44
+ key: preset.key,
45
+ element: {
46
+ active: _jsx(_Fragment, { children: preset.name }),
47
+ expanded: (_jsxs(_Fragment, { children: [_jsx("span", { children: preset.name }), _jsx("br", {}), _jsx("span", { className: "text-xs", children: preset.description })] })),
48
+ },
49
+ })),
37
50
  ];
38
51
  const fieldItems = [
39
52
  {
@@ -140,14 +153,40 @@ const ProfileFilters = () => {
140
153
  return (_jsxs("div", { className: "flex gap-2 w-full", children: [_jsxs("div", { className: "flex-1 flex flex-wrap gap-2", children: [filtersToRender.map(filter => {
141
154
  const isNumberField = filter.field === 'address' || filter.field === 'line_number';
142
155
  const matchTypeItems = isNumberField ? numberMatchTypeItems : stringMatchTypeItems;
156
+ const isPresetFilter = filter.type != null && isPresetKey(filter.type);
143
157
  return (_jsxs("div", { className: "flex items-center gap-0", children: [_jsx(Select, { items: filterTypeItems, selectedKey: filter.type, placeholder: "Select Filter", onSelection: key => {
144
- const newType = key;
145
- updateFilter(filter.id, {
146
- type: newType,
147
- field: filter.field ?? 'function_name',
148
- matchType: filter.matchType ?? 'contains',
149
- });
150
- }, className: cx('rounded-l-md pr-1 gap-0 focus:z-50 focus:relative focus:outline-1 rounded-r-none ', filter.type != null ? 'border-r-0 w-28' : 'w-32') }), filter.type != null && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', onSelection: key => {
158
+ // Check if this is a preset selection
159
+ if (isPresetKey(key)) {
160
+ const preset = getPresetByKey(key);
161
+ if (preset != null) {
162
+ updateFilter(filter.id, {
163
+ type: preset.key,
164
+ field: undefined,
165
+ matchType: undefined,
166
+ value: preset.name,
167
+ });
168
+ }
169
+ }
170
+ else {
171
+ const newType = key;
172
+ // Check if we're converting a preset filter to a regular filter
173
+ if (filter.type != null && isPresetKey(filter.type)) {
174
+ updateFilter(filter.id, {
175
+ type: newType,
176
+ field: 'function_name',
177
+ matchType: 'contains',
178
+ value: '',
179
+ });
180
+ }
181
+ else {
182
+ updateFilter(filter.id, {
183
+ type: newType,
184
+ field: filter.field ?? 'function_name',
185
+ matchType: filter.matchType ?? 'contains',
186
+ });
187
+ }
188
+ }
189
+ }, className: cx('rounded-l-md pr-1 gap-0 focus:z-50 focus:relative focus:outline-1', isPresetFilter ? 'rounded-r-none border-r-0' : 'rounded-r-none', filter.type != null ? 'border-r-0 w-auto' : 'w-32') }), filter.type != null && !isPresetFilter && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', onSelection: key => {
151
190
  const newField = key;
152
191
  const isNewFieldNumber = newField === 'address' || newField === 'line_number';
153
192
  const isCurrentFieldNumber = filter.field === 'address' || filter.field === 'line_number';
@@ -161,13 +200,19 @@ const ProfileFilters = () => {
161
200
  updateFilter(filter.id, { field: newField });
162
201
  }
163
202
  }, className: "rounded-none border-r-0 w-32 pr-1 gap-0 focus:z-50 focus:relative focus:outline-1" }), _jsx(Select, { items: matchTypeItems, selectedKey: filter.matchType ?? '', onSelection: key => updateFilter(filter.id, { matchType: key }), className: "rounded-none border-r-0 pr-1 gap-0 focus:z-50 focus:relative focus:outline-1" }), _jsx(Input, { placeholder: "Value", value: filter.value, onChange: e => updateFilter(filter.id, { value: e.target.value }), onKeyDown: handleKeyDown, className: "rounded-none w-36 text-sm focus:outline-1" })] })), _jsx(Button, { variant: "neutral", onClick: () => {
164
- if (localFilters.length === 1) {
203
+ // If we're displaying local filters and this is the last one, reset everything
204
+ if (localFilters.length > 0 && localFilters.length === 1) {
205
+ resetFilters();
206
+ }
207
+ // If we're displaying applied filters and this is the last one, reset everything
208
+ else if (localFilters.length === 0 && filtersToRender.length === 1) {
165
209
  resetFilters();
166
210
  }
211
+ // Otherwise, just remove this specific filter
167
212
  else {
168
213
  removeFilter(filter.id);
169
214
  }
170
215
  }, className: cx('h-[38px] p-3', filter.type != null ? 'rounded-none rounded-r-md' : 'rounded-l-none rounded-r-md'), children: _jsx(Icon, { icon: "mdi:close", className: "h-4 w-4" }) })] }, filter.id));
171
- }), localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", children: _jsx(Icon, { icon: "mdi:filter-plus-outline", className: "h-4 w-4" }) })), localFilters.length === 0 && (appliedFilters?.length ?? 0) === 0 && (_jsxs(Button, { variant: "neutral", onClick: addFilter, className: "flex items-center gap-2", children: [_jsx(Icon, { icon: "mdi:filter-outline", className: "h-4 w-4" }), _jsx("span", { children: "Filter" })] }))] }), localFilters.length > 0 && hasUnsavedChanges && localFilters.some(isFilterComplete) && (_jsx(Button, { variant: "primary", onClick: onApplyFilters, className: cx('flex items-center gap-2 self-end'), children: _jsx("span", { children: "Apply" }) }))] }));
216
+ }), localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", children: _jsx(Icon, { icon: "mdi:filter-plus-outline", className: "h-4 w-4" }) })), localFilters.length === 0 && (appliedFilters?.length ?? 0) === 0 && (_jsxs(Button, { variant: "neutral", onClick: addFilter, className: "flex items-center gap-2", children: [_jsx(Icon, { icon: "mdi:filter-outline", className: "h-4 w-4" }), _jsx("span", { children: "Filter" })] }))] }), localFilters.length > 0 && (_jsx(Button, { variant: "primary", onClick: onApplyFilters, disabled: !hasUnsavedChanges || !localFilters.some(isFilterComplete), className: cx('flex items-center gap-2 self-end'), children: _jsx("span", { children: "Apply" }) }))] }));
172
217
  };
173
218
  export default ProfileFilters;
@@ -1,5 +1,6 @@
1
1
  import { type Filter } from '@parca/client';
2
2
  import { type ProfileFilter } from '@parca/store';
3
+ import { type FilterPreset } from './filterPresets';
3
4
  export type { ProfileFilter };
4
5
  export declare const convertToProtoFilters: (profileFilters: ProfileFilter[]) => Filter[];
5
6
  export declare const useProfileFilters: () => {
@@ -14,5 +15,6 @@ export declare const useProfileFilters: () => {
14
15
  removeFilter: (id: string) => void;
15
16
  updateFilter: (id: string, updates: Partial<ProfileFilter>) => void;
16
17
  resetFilters: () => void;
18
+ applyPreset: (preset: FilterPreset) => void;
17
19
  };
18
20
  //# sourceMappingURL=useProfileFilters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAItB,YAAY,EAAC,aAAa,EAAC,CAAC;AAG5B,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EA+E7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CAkK1B,CAAC"}
1
+ {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAA8B,KAAK,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAG/E,YAAY,EAAC,aAAa,EAAC,CAAC;AAG5B,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAoG7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CAwM7C,CAAC"}
@@ -12,10 +12,31 @@
12
12
  // limitations under the License.
13
13
  import { useCallback, useEffect, useMemo } from 'react';
14
14
  import { selectLocalFilters, setLocalFilters, useAppDispatch, useAppSelector, } from '@parca/store';
15
+ import { getPresetByKey, isPresetKey } from './filterPresets';
15
16
  import { useProfileFiltersUrlState } from './useProfileFiltersUrlState';
16
17
  // Convert ProfileFilter[] to protobuf Filter[] matching the expected structure
17
18
  export const convertToProtoFilters = (profileFilters) => {
18
- return profileFilters
19
+ // First, expand any preset filters to their constituent filters
20
+ const expandedFilters = [];
21
+ for (const filter of profileFilters) {
22
+ if (filter.type != null && isPresetKey(filter.type)) {
23
+ // This is a preset filter, expand it
24
+ const preset = getPresetByKey(filter.type);
25
+ if (preset != null) {
26
+ preset.filters.forEach((presetFilter, index) => {
27
+ expandedFilters.push({
28
+ ...presetFilter,
29
+ id: `${filter.id}-expanded-${index}`,
30
+ });
31
+ });
32
+ }
33
+ }
34
+ else {
35
+ // Regular filter, add as is
36
+ expandedFilters.push(filter);
37
+ }
38
+ }
39
+ return expandedFilters
19
40
  .filter(f => f.value !== '' && f.type != null && f.field != null && f.matchType != null) // Only include complete filters with values
20
41
  .map(f => {
21
42
  // Build the condition based on field type
@@ -117,8 +138,22 @@ export const useProfileFilters = () => {
117
138
  // eslint-disable-next-line react-hooks/exhaustive-deps
118
139
  }, []);
119
140
  const hasUnsavedChanges = useMemo(() => {
120
- const localWithValues = localFilters.filter(f => f.value !== '');
121
- const appliedWithValues = (appliedFilters ?? []).filter(f => f.value !== '');
141
+ const localWithValues = localFilters.filter(f => {
142
+ // For preset filters, only need type and value
143
+ if (f.type != null && isPresetKey(f.type)) {
144
+ return f.value !== '' && f.type != null;
145
+ }
146
+ // For regular filters, need all fields
147
+ return f.value !== '' && f.type != null && f.field != null && f.matchType != null;
148
+ });
149
+ const appliedWithValues = (appliedFilters ?? []).filter(f => {
150
+ // For preset filters, only need type and value
151
+ if (f.type != null && isPresetKey(f.type)) {
152
+ return f.value !== '' && f.type != null;
153
+ }
154
+ // For regular filters, need all fields
155
+ return f.value !== '' && f.type != null && f.field != null && f.matchType != null;
156
+ });
122
157
  if (localWithValues.length !== appliedWithValues.length)
123
158
  return true;
124
159
  return !localWithValues.every((local, index) => {
@@ -183,7 +218,14 @@ export const useProfileFilters = () => {
183
218
  setAppliedFilters([]);
184
219
  }, [dispatch, setAppliedFilters]);
185
220
  const onApplyFilters = useCallback(() => {
186
- const validFilters = localFilters.filter(f => f.value !== '' && f.type != null && f.field != null && f.matchType != null);
221
+ const validFilters = localFilters.filter(f => {
222
+ // For preset filters, only need type and value
223
+ if (f.type != null && isPresetKey(f.type)) {
224
+ return f.value !== '' && f.type != null;
225
+ }
226
+ // For regular filters, need all fields
227
+ return f.value !== '' && f.type != null && f.field != null && f.matchType != null;
228
+ });
187
229
  const filtersToApply = validFilters.map((f, index) => ({
188
230
  ...f,
189
231
  id: `filter-${Date.now()}-${index}`,
@@ -193,6 +235,17 @@ export const useProfileFilters = () => {
193
235
  const protoFilters = useMemo(() => {
194
236
  return convertToProtoFilters(appliedFilters ?? []);
195
237
  }, [appliedFilters]);
238
+ const applyPreset = useCallback((preset) => {
239
+ const presetFilter = {
240
+ id: `filter-preset-${Date.now()}`,
241
+ type: preset.key,
242
+ value: preset.name,
243
+ };
244
+ // Add preset filter to existing filters
245
+ const updatedFilters = [...localFilters, presetFilter];
246
+ dispatch(setLocalFilters(updatedFilters));
247
+ setAppliedFilters(updatedFilters);
248
+ }, [dispatch, setAppliedFilters, localFilters]);
196
249
  return {
197
250
  localFilters,
198
251
  appliedFilters,
@@ -205,5 +258,6 @@ export const useProfileFilters = () => {
205
258
  removeFilter,
206
259
  updateFilter,
207
260
  resetFilters,
261
+ applyPreset,
208
262
  };
209
263
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useProfileFiltersUrlState.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts"],"names":[],"mappings":"AAaA,OAAO,EAAoB,KAAK,sBAAsB,EAAC,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAC,KAAK,aAAa,EAAC,MAAM,cAAc,CAAC;AA8ChD,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,aAAa,EAmBnE,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO;IAC3C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,iBAAiB,EAAE,sBAAsB,CAAC,aAAa,EAAE,CAAC,CAAC;CAmB5D,CAAC"}
1
+ {"version":3,"file":"useProfileFiltersUrlState.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts"],"names":[],"mappings":"AAaA,OAAO,EAAoB,KAAK,sBAAsB,EAAC,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAC,KAAK,aAAa,EAAC,MAAM,cAAc,CAAC;AAwDhD,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,aAAa,EAkCnE,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO;IAC3C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,iBAAiB,EAAE,sBAAsB,CAAC,aAAa,EAAE,CAAC,CAAC;CAmB5D,CAAC"}
@@ -11,6 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useURLStateCustom } from '@parca/components';
14
+ import { isPresetKey } from './filterPresets';
14
15
  // Compact encoding mappings
15
16
  const TYPE_MAP = {
16
17
  stack: 's',
@@ -39,8 +40,15 @@ const encodeProfileFilters = (filters) => {
39
40
  if (filters.length === 0)
40
41
  return '';
41
42
  return filters
42
- .filter(f => f.value !== '' && f.type != null && f.field != null && f.matchType != null)
43
+ .filter(f => f.value !== '' && f.type != null)
43
44
  .map(f => {
45
+ // Handle preset filters differently
46
+ if (isPresetKey(f.type)) {
47
+ const presetKey = encodeURIComponent(f.type);
48
+ const value = encodeURIComponent(f.value);
49
+ return `p:${presetKey}:${value}`;
50
+ }
51
+ // Handle regular filters
44
52
  const type = TYPE_MAP[f.type];
45
53
  const field = FIELD_MAP[f.field];
46
54
  const match = MATCH_MAP[f.matchType];
@@ -55,7 +63,19 @@ export const decodeProfileFilters = (encoded) => {
55
63
  return [];
56
64
  try {
57
65
  return encoded.split(',').map((filter, index) => {
58
- const [type, field, match, ...valueParts] = filter.split(':');
66
+ const parts = filter.split(':');
67
+ // Handle preset filters (format: p:presetKey:value)
68
+ if (parts[0] === 'p' && parts.length >= 3) {
69
+ const presetKey = decodeURIComponent(parts[1]);
70
+ const value = decodeURIComponent(parts.slice(2).join(':')); // Handle values with colons
71
+ return {
72
+ id: `filter-${Date.now()}-${index}`,
73
+ type: presetKey,
74
+ value,
75
+ };
76
+ }
77
+ // Handle regular filters (format: type:field:match:value)
78
+ const [type, field, match, ...valueParts] = parts;
59
79
  const value = decodeURIComponent(valueParts.join(':')); // Handle values with colons
60
80
  return {
61
81
  id: `filter-${Date.now()}-${index}`,
@@ -1,3 +1,3 @@
1
1
  import type { ProfileViewProps } from './types/visualization';
2
- export declare const ProfileView: ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, }: ProfileViewProps) => JSX.Element;
2
+ export declare const ProfileView: ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, sandwichData, }: ProfileViewProps) => JSX.Element;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,mLAazB,gBAAgB,KAAG,GAAG,CAAC,OA8HzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA+HzB,CAAC"}
@@ -23,7 +23,7 @@ import { DashboardProvider } from './context/DashboardContext';
23
23
  import { ProfileViewContextProvider } from './context/ProfileViewContext';
24
24
  import { useProfileMetadata } from './hooks/useProfileMetadata';
25
25
  import { useVisualizationState } from './hooks/useVisualizationState';
26
- export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, }) => {
26
+ export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, sandwichData, }) => {
27
27
  const { timezone, perf, profileViewExternalMainActions, preferencesModal, profileViewExternalSubActions, } = useParcaContext();
28
28
  const { ref, dimensions } = useContainerDimensions();
29
29
  const { curPath, setCurPath, curPathArrow, setCurPathArrow, colorStackLegend, colorBy, groupBy, toggleGroupBy, setGroupByLabels, sandwichFunctionName, resetSandwichFunctionName, } = useVisualizationState();
@@ -38,6 +38,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, t
38
38
  (selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true');
39
39
  const getDashboardItemByType = ({ type, isHalfScreen, }) => {
40
40
  return getDashboardItem({
41
+ sandwichData,
41
42
  type,
42
43
  isHalfScreen,
43
44
  dimensions,
@@ -1,8 +1,7 @@
1
- import { Callgraph as CallgraphType, Flamegraph, FlamegraphArrow, QueryServiceClient, Source, TableArrow } from '@parca/client';
1
+ import { FlamegraphArrow, QueryServiceClient, Source, TableArrow } from '@parca/client';
2
2
  import { ProfileSource } from '../../ProfileSource';
3
3
  export interface FlamegraphData {
4
4
  loading: boolean;
5
- data?: Flamegraph;
6
5
  arrow?: FlamegraphArrow;
7
6
  total?: bigint;
8
7
  filtered?: bigint;
@@ -19,26 +18,23 @@ export interface TopTableData {
19
18
  error?: any;
20
19
  unit?: string;
21
20
  }
22
- export interface CallgraphData {
23
- loading: boolean;
24
- data?: CallgraphType;
25
- total?: bigint;
26
- filtered?: bigint;
27
- error?: any;
28
- }
29
21
  export interface SourceData {
30
22
  loading: boolean;
31
23
  data?: Source;
32
24
  error?: any;
33
25
  }
26
+ export interface SandwichData {
27
+ callees: FlamegraphData;
28
+ callers: FlamegraphData;
29
+ }
34
30
  export type VisualizationType = 'flamegraph' | 'callgraph' | 'table' | 'source' | 'flamechart' | 'sandwich';
35
31
  export interface ProfileViewProps {
36
32
  total: bigint;
37
33
  filtered: bigint;
38
34
  flamegraphData: FlamegraphData;
39
35
  flamechartData: FlamegraphData;
36
+ sandwichData: SandwichData;
40
37
  topTableData?: TopTableData;
41
- callgraphData?: CallgraphData;
42
38
  sourceData?: SourceData;
43
39
  profileSource: ProfileSource;
44
40
  queryClient?: QueryServiceClient;
@@ -1 +1 @@
1
- {"version":3,"file":"visualization.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/types/visualization.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,WAAW,GACX,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC"}
1
+ {"version":3,"file":"visualization.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/types/visualization.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,eAAe,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,eAAe,CAAC;AAEtF,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,WAAW,GACX,OAAO,GACP,QAAQ,GACR,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAM1E,OAAO,EAAsB,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAMnE,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,mBAAmB,GAAI,4DAIjC,wBAAwB,KAAG,GAAG,CAAC,OA0QjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAM1E,OAAO,EAAsB,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAMnE,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,eAAO,MAAM,mBAAmB,GAAI,4DAIjC,wBAAwB,KAAG,GAAG,CAAC,OA6SjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}