@parca/profile 0.16.415 → 0.16.417

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 (88) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/Callgraph/index.js +3 -2
  3. package/dist/GraphTooltipArrow/Content.d.ts +1 -3
  4. package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
  5. package/dist/GraphTooltipArrow/Content.js +4 -4
  6. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +2 -2
  7. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts +1 -3
  8. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
  9. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +6 -16
  10. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  11. package/dist/ProfileExplorer/ProfileExplorerCompare.js +3 -3
  12. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts.map +1 -1
  13. package/dist/ProfileExplorer/ProfileExplorerSingle.js +1 -1
  14. package/dist/ProfileExplorer/index.d.ts.map +1 -1
  15. package/dist/ProfileExplorer/index.js +1 -7
  16. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +1 -3
  17. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts.map +1 -1
  18. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.js +2 -2
  19. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -2
  20. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts.map +1 -1
  21. package/dist/ProfileIcicleGraph/IcicleGraph/index.js +4 -3
  22. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts +1 -3
  23. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.d.ts.map +1 -1
  24. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.js +8 -20
  25. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +1 -3
  26. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts.map +1 -1
  27. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +2 -2
  28. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +1 -2
  29. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
  30. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +6 -9
  31. package/dist/ProfileIcicleGraph/index.d.ts +1 -3
  32. package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
  33. package/dist/ProfileIcicleGraph/index.js +20 -48
  34. package/dist/ProfileMetricsGraph/index.js +1 -2
  35. package/dist/ProfileSelector/index.d.ts.map +1 -1
  36. package/dist/ProfileSelector/index.js +19 -2
  37. package/dist/ProfileView/FilterByFunctionButton.d.ts +1 -4
  38. package/dist/ProfileView/FilterByFunctionButton.d.ts.map +1 -1
  39. package/dist/ProfileView/FilterByFunctionButton.js +12 -3
  40. package/dist/ProfileView/ViewSelector.d.ts +1 -3
  41. package/dist/ProfileView/ViewSelector.d.ts.map +1 -1
  42. package/dist/ProfileView/ViewSelector.js +3 -4
  43. package/dist/ProfileView/VisualizationPanel.d.ts +0 -2
  44. package/dist/ProfileView/VisualizationPanel.d.ts.map +1 -1
  45. package/dist/ProfileView/VisualizationPanel.js +2 -2
  46. package/dist/ProfileView/index.d.ts +1 -5
  47. package/dist/ProfileView/index.d.ts.map +1 -1
  48. package/dist/ProfileView/index.js +11 -18
  49. package/dist/ProfileViewWithData.d.ts +1 -3
  50. package/dist/ProfileViewWithData.d.ts.map +1 -1
  51. package/dist/ProfileViewWithData.js +15 -12
  52. package/dist/SourceView/index.js +1 -1
  53. package/dist/SourceView/useSelectedLineRange.js +1 -1
  54. package/dist/Table/index.d.ts +1 -2
  55. package/dist/Table/index.d.ts.map +1 -1
  56. package/dist/Table/index.js +9 -25
  57. package/dist/TopTable/index.d.ts.map +1 -1
  58. package/dist/TopTable/index.js +3 -7
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +3 -0
  62. package/dist/styles.css +1 -1
  63. package/package.json +7 -7
  64. package/src/Callgraph/index.tsx +3 -3
  65. package/src/GraphTooltipArrow/Content.tsx +4 -14
  66. package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +2 -2
  67. package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +6 -22
  68. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +2 -3
  69. package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -5
  70. package/src/ProfileExplorer/index.tsx +0 -8
  71. package/src/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.tsx +2 -4
  72. package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +5 -8
  73. package/src/ProfileIcicleGraph/IcicleGraphArrow/ColorStackLegend.tsx +8 -27
  74. package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +2 -4
  75. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +4 -17
  76. package/src/ProfileIcicleGraph/index.tsx +19 -67
  77. package/src/ProfileMetricsGraph/index.tsx +2 -2
  78. package/src/ProfileSelector/index.tsx +23 -2
  79. package/src/ProfileView/FilterByFunctionButton.tsx +15 -9
  80. package/src/ProfileView/ViewSelector.tsx +6 -7
  81. package/src/ProfileView/VisualizationPanel.tsx +1 -9
  82. package/src/ProfileView/index.tsx +8 -23
  83. package/src/ProfileViewWithData.tsx +15 -18
  84. package/src/SourceView/index.tsx +1 -1
  85. package/src/SourceView/useSelectedLineRange.ts +2 -2
  86. package/src/Table/index.tsx +10 -41
  87. package/src/TopTable/index.tsx +3 -8
  88. package/src/index.tsx +4 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAS1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAa1B,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAgJD,QAAA,MAAM,kBAAkB,yJAerB,uBAAuB,KAAG,GAAG,CAAC,OAkQhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileIcicleGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,OAAO,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,eAAe,CAAC;AAS1D,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAc1C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,uBAAuB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAyHD,QAAA,MAAM,kBAAkB,6IAcrB,uBAAuB,KAAG,GAAG,CAAC,OAgPhC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -16,28 +16,22 @@ import { Icon } from '@iconify/react';
16
16
  import { AnimatePresence, motion } from 'framer-motion';
17
17
  import { Button, IcicleGraphSkeleton, IconButton, useParcaContext, useURLState, } from '@parca/components';
18
18
  import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
19
- import { capitalizeOnlyFirstLetter, divide, selectQueryParam, } from '@parca/utilities';
19
+ import { capitalizeOnlyFirstLetter, divide, selectQueryParam } from '@parca/utilities';
20
20
  import { useProfileViewContext } from '../ProfileView/ProfileViewContext';
21
21
  import DiffLegend from '../components/DiffLegend';
22
22
  import GroupByDropdown from './ActionButtons/GroupByDropdown';
23
23
  import SortBySelect from './ActionButtons/SortBySelect';
24
- import IcicleGraph from './IcicleGraph';
25
- import IcicleGraphArrow, { FIELD_FUNCTION_NAME } from './IcicleGraphArrow';
24
+ import { IcicleGraph } from './IcicleGraph';
25
+ import { FIELD_FUNCTION_NAME, IcicleGraphArrow } from './IcicleGraphArrow';
26
26
  import ColorStackLegend from './IcicleGraphArrow/ColorStackLegend';
27
27
  import useMappingList from './IcicleGraphArrow/useMappingList';
28
28
  const numberFormatter = new Intl.NumberFormat('en-US');
29
29
  const ErrorContent = ({ errorMessage }) => {
30
30
  return _jsx("div", { className: "flex justify-center p-10", children: errorMessage });
31
31
  };
32
- const ShowHideLegendButton = ({ navigateTo, isHalfScreen, }) => {
33
- const [colorStackLegend, setStoreColorStackLegend] = useURLState({
34
- param: 'color_stack_legend',
35
- navigateTo,
36
- });
37
- const [binaryFrameFilter, setBinaryFrameFilter] = useURLState({
38
- param: 'binary_frame_filter',
39
- navigateTo,
40
- });
32
+ const ShowHideLegendButton = ({ isHalfScreen }) => {
33
+ const [colorStackLegend, setStoreColorStackLegend] = useURLState('color_stack_legend');
34
+ const [binaryFrameFilter, setBinaryFrameFilter] = useURLState('binary_frame_filter');
41
35
  const { compareMode } = useProfileViewContext();
42
36
  const isColorStackLegendEnabled = colorStackLegend === 'true';
43
37
  const [colorProfileName] = useUserPreference(USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key);
@@ -49,28 +43,18 @@ const ShowHideLegendButton = ({ navigateTo, isHalfScreen, }) => {
49
43
  };
50
44
  return (_jsx(_Fragment, { children: colorProfileName === 'default' || compareMode ? null : (_jsx(_Fragment, { children: isHalfScreen ? (_jsxs(_Fragment, { children: [_jsx(IconButton, { className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center !py-2 !px-3 cursor-pointer min-h-[38px]", icon: isColorStackLegendEnabled ? 'ph:eye-closed' : 'ph:eye', toolTipText: isColorStackLegendEnabled ? 'Hide legend' : 'Show legend', onClick: () => setColorStackLegend(isColorStackLegendEnabled ? 'false' : 'true'), id: "h-show-legend-button" }), binaryFrameFilter !== undefined && binaryFrameFilter.length > 0 && (_jsx(IconButton, { className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center !py-2 !px-3 cursor-pointer min-h-[38px]", icon: "system-uicons:reset", toolTipText: "Reset the legend selection", onClick: () => resetLegend(), id: "h-reset-legend-button" }))] })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { className: "gap-2 w-max", variant: "neutral", onClick: () => setColorStackLegend(isColorStackLegendEnabled ? 'false' : 'true'), id: "h-show-legend-button", children: [isColorStackLegendEnabled ? 'Hide legend' : 'Show legend', _jsx(Icon, { icon: isColorStackLegendEnabled ? 'ph:eye-closed' : 'ph:eye', width: 20 })] }), binaryFrameFilter !== undefined && binaryFrameFilter.length > 0 && (_jsxs(Button, { className: "gap-2 w-max", variant: "neutral", onClick: () => resetLegend(), id: "h-reset-legend-button", children: ["Reset Legend", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }))] })) })) }));
51
45
  };
52
- const GroupAndSortActionButtons = ({ navigateTo }) => {
53
- const [storeSortBy = FIELD_FUNCTION_NAME, setStoreSortBy] = useURLState({
54
- param: 'sort_by',
55
- navigateTo,
46
+ const GroupAndSortActionButtons = () => {
47
+ const [storeSortBy, setStoreSortBy] = useURLState('sort_by', {
48
+ defaultValue: FIELD_FUNCTION_NAME,
56
49
  });
57
50
  const { compareMode } = useProfileViewContext();
58
- const [storeGroupBy = [FIELD_FUNCTION_NAME], setStoreGroupBy] = useURLState({
59
- param: 'group_by',
60
- navigateTo,
51
+ const [groupBy, setStoreGroupBy] = useURLState('group_by', {
52
+ defaultValue: [FIELD_FUNCTION_NAME],
53
+ alwaysReturnArray: true,
61
54
  });
62
55
  const setGroupBy = useCallback((keys) => {
63
56
  setStoreGroupBy(keys);
64
57
  }, [setStoreGroupBy]);
65
- const groupBy = useMemo(() => {
66
- if (storeGroupBy !== undefined) {
67
- if (typeof storeGroupBy === 'string') {
68
- return [storeGroupBy];
69
- }
70
- return storeGroupBy;
71
- }
72
- return [FIELD_FUNCTION_NAME];
73
- }, [storeGroupBy]);
74
58
  const toggleGroupBy = useCallback((key) => {
75
59
  groupBy.includes(key)
76
60
  ? setGroupBy(groupBy.filter(v => v !== key)) // remove
@@ -78,29 +62,19 @@ const GroupAndSortActionButtons = ({ navigateTo }) => {
78
62
  }, [groupBy, setGroupBy]);
79
63
  return (_jsxs(_Fragment, { children: [_jsx(GroupByDropdown, { groupBy: groupBy, toggleGroupBy: toggleGroupBy }), _jsx(SortBySelect, { compareMode: compareMode, sortBy: storeSortBy, setSortBy: setStoreSortBy })] }));
80
64
  };
81
- const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, navigateTo, loading, setActionButtons, error, width, isHalfScreen, mappings, }) {
65
+ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, total, filtered, curPath, setNewCurPath, profileType, loading, setActionButtons, error, width, isHalfScreen, mappings, }) {
82
66
  const { onError, authenticationErrorMessage, isDarkMode } = useParcaContext();
83
67
  const { compareMode } = useProfileViewContext();
84
68
  const [isLoading, setIsLoading] = useState(true);
85
69
  const isColorStackLegendEnabled = selectQueryParam('color_stack_legend') === 'true';
86
70
  const mappingsList = useMappingList(mappings);
87
- const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState({
88
- param: 'sort_by',
89
- navigateTo,
90
- });
91
- const [invertStack = '', setInvertStack] = useURLState({
92
- param: 'invert_call_stack',
93
- navigateTo,
94
- });
71
+ const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState('sort_by');
72
+ const [invertStack = '', setInvertStack] = useURLState('invert_call_stack');
95
73
  const isInvert = invertStack === 'true';
96
74
  // By default, we want delta profiles (CPU) to be relatively compared.
97
75
  // For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
98
76
  const compareAbsoluteDefault = profileType?.delta === false ? 'true' : 'false';
99
- const [compareAbsolute = compareAbsoluteDefault, setCompareAbsolute] = useURLState({
100
- param: 'compare_absolute',
101
- navigateTo,
102
- withURLUpdate: true,
103
- });
77
+ const [compareAbsolute = compareAbsoluteDefault, setCompareAbsolute] = useURLState('compare_absolute');
104
78
  const isCompareAbsolute = compareAbsolute === 'true';
105
79
  const [totalFormatted, totalUnfilteredFormatted, isTrimmed, trimmedFormatted, trimmedPercentage, isFiltered, filteredPercentage,] = useMemo(() => {
106
80
  if (graph === undefined && arrow === undefined) {
@@ -121,9 +95,8 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
121
95
  ];
122
96
  }, [graph, arrow, filtered, total]);
123
97
  useEffect(() => {
124
- setActionButtons?.(_jsx("div", { className: "flex w-full justify-end gap-2 pb-2", children: _jsxs("div", { className: "ml-2 flex w-full flex-col items-start justify-between gap-2 md:flex-row md:items-end", children: [_jsx(GroupAndSortActionButtons, { navigateTo: navigateTo }), isHalfScreen ? (_jsx(IconButton, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', toolTipText: isInvert ? 'Original Call Stack' : 'Invert Call Stack', onClick: () => setInvertStack(isInvert ? '' : 'true'), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setInvertStack(isInvert ? '' : 'true'), children: [isInvert ? 'Original Call Stack' : 'Invert Call Stack', _jsx(Icon, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', width: 20 })] })), _jsx(ShowHideLegendButton, { isHalfScreen: isHalfScreen, navigateTo: navigateTo }), compareMode && (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setCompareAbsolute(isCompareAbsolute ? '' : 'true'), children: [isCompareAbsolute ? 'Compare Relative' : 'Compare Absolute', _jsx(Icon, { icon: isCompareAbsolute ? 'fluent-mdl2:compare' : 'fluent-mdl2:compare-uneven', width: 20 })] })), isHalfScreen ? (_jsx(IconButton, { icon: "system-uicons:reset", disabled: curPath.length === 0, toolTipText: "Reset View", onClick: () => setNewCurPath([]), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, children: ["Reset View", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }))] }) }));
98
+ setActionButtons?.(_jsx("div", { className: "flex w-full justify-end gap-2 pb-2", children: _jsxs("div", { className: "ml-2 flex w-full flex-col items-start justify-between gap-2 md:flex-row md:items-end", children: [_jsx(GroupAndSortActionButtons, {}), isHalfScreen ? (_jsx(IconButton, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', toolTipText: isInvert ? 'Original Call Stack' : 'Invert Call Stack', onClick: () => setInvertStack(isInvert ? '' : 'true'), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setInvertStack(isInvert ? '' : 'true'), children: [isInvert ? 'Original Call Stack' : 'Invert Call Stack', _jsx(Icon, { icon: isInvert ? 'ph:sort-ascending' : 'ph:sort-descending', width: 20 })] })), _jsx(ShowHideLegendButton, { isHalfScreen: isHalfScreen }), compareMode && (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setCompareAbsolute(isCompareAbsolute ? '' : 'true'), children: [isCompareAbsolute ? 'Compare Relative' : 'Compare Absolute', _jsx(Icon, { icon: isCompareAbsolute ? 'fluent-mdl2:compare' : 'fluent-mdl2:compare-uneven', width: 20 })] })), isHalfScreen ? (_jsx(IconButton, { icon: "system-uicons:reset", disabled: curPath.length === 0, toolTipText: "Reset View", onClick: () => setNewCurPath([]), className: "rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 items-center flex border border-gray-200 dark:border-gray-600 dark:text-white justify-center py-2 px-3 cursor-pointer min-h-[38px]" })) : (_jsxs(Button, { variant: "neutral", className: "gap-2 w-max", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, children: ["Reset View", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }))] }) }));
125
99
  }, [
126
- navigateTo,
127
100
  isInvert,
128
101
  setInvertStack,
129
102
  arrow,
@@ -155,9 +128,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
155
128
  if (total === 0n && !loading)
156
129
  return _jsx("div", { className: "mx-auto text-center", children: "Profile has no samples" });
157
130
  if (graph !== undefined)
158
- return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, navigateTo: navigateTo }));
131
+ return (_jsx(IcicleGraph, { width: width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType }));
159
132
  if (arrow !== undefined)
160
- return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, navigateTo: navigateTo, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList }));
133
+ return (_jsx(IcicleGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, profileType: profileType, sortBy: storeSortBy, flamegraphLoading: isLoading, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList }));
161
134
  }, [
162
135
  isLoading,
163
136
  graph,
@@ -169,7 +142,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
169
142
  curPath,
170
143
  setNewCurPath,
171
144
  profileType,
172
- navigateTo,
173
145
  storeSortBy,
174
146
  isHalfScreen,
175
147
  isDarkMode,
@@ -185,6 +157,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
185
157
  if (isTrimmed) {
186
158
  console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
187
159
  }
188
- return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, isColorStackLegendEnabled && (_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode, mappings: mappings, loading: isLoading })), _jsx("div", { className: "min-h-48", id: "h-icicle-graph", children: _jsx(_Fragment, { children: icicleGraph }) }), _jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] })] }, "icicle-graph-loaded") }));
160
+ return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, isColorStackLegendEnabled && (_jsx(ColorStackLegend, { compareMode: compareMode, mappings: mappings, loading: isLoading })), _jsx("div", { className: "min-h-48", id: "h-icicle-graph", children: _jsx(_Fragment, { children: icicleGraph }) }), _jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] })] }, "icicle-graph-loaded") }));
189
161
  };
190
162
  export default ProfileIcicleGraph;
@@ -36,8 +36,7 @@ const getStepCountFromScreenWidth = (pixelsPerPoint) => {
36
36
  };
37
37
  export const useQueryRange = (client, queryExpression, start, end, sumBy, skip = false) => {
38
38
  const metadata = useGrpcMetadata();
39
- const { navigateTo } = useParcaContext();
40
- const [stepCountStr, setStepCount] = useURLState({ param: 'step_count', navigateTo });
39
+ const [stepCountStr, setStepCount] = useURLState('step_count');
41
40
  const defaultStepCount = useMemo(() => {
42
41
  return getStepCountFromScreenWidth(10);
43
42
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,6IAUlB,oBAAoB,KAAG,GAAG,CAAC,OAwT7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,6IAUlB,oBAAoB,KAAG,GAAG,CAAC,OA6U7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- import { useEffect, useMemo, useState } from 'react';
14
+ import { useEffect, useMemo, useRef, useState } from 'react';
15
15
  import Select from 'react-select';
16
16
  import { Button, ButtonGroup, DateTimeRange, DateTimeRangePicker, IconButton, useGrpcMetadata, useParcaContext, } from '@parca/components';
17
17
  import { CloseIcon } from '@parca/icons';
@@ -44,6 +44,7 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
44
44
  const { loading: profileTypesLoading, data: profileTypesData, error, } = useProfileTypes(queryClient);
45
45
  const { heightStyle } = useMetricsGraphDimensions(comparing);
46
46
  const { viewComponent } = useParcaContext();
47
+ const sumByRef = useRef(null);
47
48
  const [timeRangeSelection, setTimeRangeSelection] = useState(DateTimeRange.fromRangeKey(querySelection.timeSelection, querySelection.from, querySelection.to));
48
49
  const [queryExpressionString, setQueryExpressionString] = useState(querySelection.expression);
49
50
  const profileType = useMemo(() => {
@@ -171,7 +172,23 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
171
172
  setUserSumBySelection(selectedOptions.map(option => option.value));
172
173
  }, placeholder: "Labels...", styles: {
173
174
  indicatorSeparator: () => ({ display: 'none' }),
174
- }, isDisabled: !profileType.delta })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
175
+ }, isDisabled: !profileType.delta, ref: sumByRef, onKeyDown: e => {
176
+ const currentRef = sumByRef.current;
177
+ if (currentRef == null) {
178
+ return;
179
+ }
180
+ const inputRef = currentRef.inputRef;
181
+ if (inputRef == null) {
182
+ return;
183
+ }
184
+ if (e.key === 'Enter' &&
185
+ inputRef.value === '' &&
186
+ currentRef.state.focusedOptionId === null // menu is not open
187
+ ) {
188
+ setQueryExpression(true);
189
+ currentRef.blur();
190
+ }
191
+ } })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
175
192
  e.preventDefault();
176
193
  setQueryExpression(true);
177
194
  }, id: "h-matcher-search-button", children: "Search" }) })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
@@ -1,6 +1,3 @@
1
- import type { NavigateFunction } from '@parca/utilities';
2
- declare const FilterByFunctionButton: ({ navigateTo, }: {
3
- navigateTo: NavigateFunction | undefined;
4
- }) => JSX.Element;
1
+ declare const FilterByFunctionButton: () => JSX.Element;
5
2
  export default FilterByFunctionButton;
6
3
  //# sourceMappingURL=FilterByFunctionButton.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FilterByFunctionButton.d.ts","sourceRoot":"","sources":["../../src/ProfileView/FilterByFunctionButton.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,QAAA,MAAM,sBAAsB,oBAEzB;IACD,UAAU,EAAE,gBAAgB,GAAG,SAAS,CAAC;CAC1C,KAAG,GAAG,CAAC,OA6BP,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"FilterByFunctionButton.d.ts","sourceRoot":"","sources":["../../src/ProfileView/FilterByFunctionButton.tsx"],"names":[],"mappings":"AAoBA,QAAA,MAAM,sBAAsB,QAAO,GAAG,CAAC,OAuCtC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -14,8 +14,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { useCallback, useMemo, useState } from 'react';
15
15
  import { Icon } from '@iconify/react';
16
16
  import { Input, useURLState } from '@parca/components';
17
- const FilterByFunctionButton = ({ navigateTo, }) => {
18
- const [storeValue, setStoreValue] = useURLState({ param: 'filter_by_function', navigateTo });
17
+ import { USER_PREFERENCES, useUserPreference } from '@parca/hooks';
18
+ const FilterByFunctionButton = () => {
19
+ const [highlightAfterFilteringEnabled] = useUserPreference(USER_PREFERENCES.HIGHTLIGHT_AFTER_FILTERING.key);
20
+ const [storeValue, setStoreValue] = useURLState('filter_by_function');
21
+ const [_, setSearchString] = useURLState('search_string');
19
22
  const [localValue, setLocalValue] = useState(storeValue);
20
23
  const isClearAction = useMemo(() => {
21
24
  return localValue === storeValue && localValue != null && localValue !== '';
@@ -24,11 +27,17 @@ const FilterByFunctionButton = ({ navigateTo, }) => {
24
27
  if (isClearAction) {
25
28
  setLocalValue('');
26
29
  setStoreValue('');
30
+ if (highlightAfterFilteringEnabled) {
31
+ setSearchString('');
32
+ }
27
33
  }
28
34
  else {
29
35
  setStoreValue(localValue);
36
+ if (highlightAfterFilteringEnabled) {
37
+ setSearchString(localValue);
38
+ }
30
39
  }
31
- }, [localValue, isClearAction, setStoreValue]);
40
+ }, [localValue, isClearAction, setStoreValue, highlightAfterFilteringEnabled, setSearchString]);
32
41
  return (_jsx(Input, { placeholder: "Filter by function", className: "text-sm", onAction: onAction, onChange: e => setLocalValue(e.target.value), value: localValue ?? '', onBlur: () => setLocalValue(storeValue), actionIcon: isClearAction ? _jsx(Icon, { icon: "ep:circle-close" }) : _jsx(Icon, { icon: "ep:arrow-right" }), id: "h-filter-by-function" }));
33
42
  };
34
43
  export default FilterByFunctionButton;
@@ -1,8 +1,6 @@
1
- import type { NavigateFunction } from '@parca/utilities';
2
1
  interface Props {
3
2
  position: number;
4
3
  defaultValue: string;
5
- navigateTo?: NavigateFunction;
6
4
  placeholderText?: string;
7
5
  primary?: boolean;
8
6
  addView?: boolean;
@@ -10,6 +8,6 @@ interface Props {
10
8
  icon?: JSX.Element;
11
9
  id?: string;
12
10
  }
13
- declare const ViewSelector: ({ defaultValue, navigateTo, position, placeholderText, primary, addView, disabled, icon, id, }: Props) => JSX.Element;
11
+ declare const ViewSelector: ({ defaultValue, position, placeholderText, primary, addView, disabled, icon, id, }: Props) => JSX.Element;
14
12
  export default ViewSelector;
15
13
  //# sourceMappingURL=ViewSelector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ViewSelector.d.ts","sourceRoot":"","sources":["../../src/ProfileView/ViewSelector.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,YAAY,mGAUf,KAAK,KAAG,GAAG,CAAC,OAkFd,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ViewSelector.d.ts","sourceRoot":"","sources":["../../src/ProfileView/ViewSelector.tsx"],"names":[],"mappings":"AAgBA,UAAU,KAAK;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,YAAY,uFASf,KAAK,KAAG,GAAG,CAAC,OAoFd,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -13,11 +13,10 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
13
13
  // limitations under the License.
14
14
  import { Select, useParcaContext, useURLState } from '@parca/components';
15
15
  import { useUIFeatureFlag } from '@parca/hooks';
16
- const ViewSelector = ({ defaultValue, navigateTo, position, placeholderText, primary = false, addView = false, disabled = false, icon, id, }) => {
16
+ const ViewSelector = ({ defaultValue, position, placeholderText, primary = false, addView = false, disabled = false, icon, id, }) => {
17
17
  const [callgraphEnabled] = useUIFeatureFlag('callgraph');
18
- const [dashboardItems = ['icicle'], setDashboardItems] = useURLState({
19
- param: 'dashboard_items',
20
- navigateTo,
18
+ const [dashboardItems = ['icicle'], setDashboardItems] = useURLState('dashboard_items', {
19
+ alwaysReturnArray: true,
21
20
  });
22
21
  const { enableSourcesView } = useParcaContext();
23
22
  const allItems = [
@@ -1,12 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
3
- import type { NavigateFunction } from '@parca/utilities';
4
3
  interface Props {
5
4
  dashboardItem: string;
6
5
  index: number;
7
6
  isMultiPanelView: boolean;
8
7
  handleClosePanel: (dashboardItem: string) => void;
9
- navigateTo: NavigateFunction | undefined;
10
8
  dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
11
9
  getDashboardItemByType: (props: {
12
10
  type: string;
@@ -1 +1 @@
1
- {"version":3,"file":"VisualizationPanel.d.ts","sourceRoot":"","sources":["../../src/ProfileView/VisualizationPanel.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAItC,OAAO,KAAK,EAAC,gCAAgC,EAAC,MAAM,qBAAqB,CAAC;AAI1E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAIvD,UAAU,KAAK;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,UAAU,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACzC,eAAe,EAAE,gCAAgC,GAAG,IAAI,GAAG,SAAS,CAAC;IACrE,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAC9B,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,OAAO,CAAC;QACtB,gBAAgB,EAAE,CAAC,aAAa,EAAE,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;KACxD,KAAK,GAAG,CAAC,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,kBAAkB,mCA+D7B,CAAC"}
1
+ {"version":3,"file":"VisualizationPanel.d.ts","sourceRoot":"","sources":["../../src/ProfileView/VisualizationPanel.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAItC,OAAO,KAAK,EAAC,gCAAgC,EAAC,MAAM,qBAAqB,CAAC;AAO1E,UAAU,KAAK;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,gCAAgC,GAAG,IAAI,GAAG,SAAS,CAAC;IACrE,sBAAsB,EAAE,CAAC,KAAK,EAAE;QAC9B,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,OAAO,CAAC;QACtB,gBAAgB,EAAE,CAAC,aAAa,EAAE,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;KACxD,KAAK,GAAG,CAAC,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,kBAAkB,mCAyD7B,CAAC"}
@@ -17,10 +17,10 @@ import cx from 'classnames';
17
17
  import { IconButton, useParcaContext } from '@parca/components';
18
18
  import { CloseIcon } from '@parca/icons';
19
19
  import ViewSelector from './ViewSelector';
20
- export const VisualizationPanel = React.memo(function VisualizationPanel({ dashboardItem, index, isMultiPanelView, handleClosePanel, navigateTo, dragHandleProps, getDashboardItemByType, }) {
20
+ export const VisualizationPanel = React.memo(function VisualizationPanel({ dashboardItem, index, isMultiPanelView, handleClosePanel, dragHandleProps, getDashboardItemByType, }) {
21
21
  const [actionButtons, setActionButtons] = useState(_jsx(_Fragment, {}));
22
22
  const { flamegraphHint } = useParcaContext();
23
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex w-full items-center justify-end gap-2 pb-2 min-h-[78px]", children: [_jsxs("div", { className: cx('flex w-full justify-between flex-col-reverse md:flex-row', isMultiPanelView && dashboardItem === 'icicle' ? 'items-end gap-x-2' : 'items-end'), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: cx(isMultiPanelView ? '' : 'hidden', 'flex items-center'), ...dragHandleProps, children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) }), _jsx("div", { className: "flex gap-2", children: actionButtons })] }), _jsxs("div", { className: cx('flex flex-row items-center gap-4', isMultiPanelView && dashboardItem === 'icicle' && 'pb-[10px]'), children: [_jsx(ViewSelector, { id: "h-switch-viz", defaultValue: dashboardItem, navigateTo: navigateTo, position: index }), dashboardItem === 'icicle' && flamegraphHint != null ? (_jsx("div", { className: "px-2", children: flamegraphHint })) : null] })] }), isMultiPanelView && (_jsx(IconButton, { className: "py-0", onClick: () => handleClosePanel(dashboardItem), icon: _jsx(CloseIcon, {}) }))] }), getDashboardItemByType({
23
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex w-full items-center justify-end gap-2 pb-2 min-h-[78px]", children: [_jsxs("div", { className: cx('flex w-full justify-between flex-col-reverse md:flex-row', isMultiPanelView && dashboardItem === 'icicle' ? 'items-end gap-x-2' : 'items-end'), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: cx(isMultiPanelView ? '' : 'hidden', 'flex items-center'), ...dragHandleProps, children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) }), _jsx("div", { className: "flex gap-2", children: actionButtons })] }), _jsxs("div", { className: cx('flex flex-row items-center gap-4', isMultiPanelView && dashboardItem === 'icicle' && 'pb-[10px]'), children: [_jsx(ViewSelector, { id: "h-switch-viz", defaultValue: dashboardItem, position: index }), dashboardItem === 'icicle' && flamegraphHint != null ? (_jsx("div", { className: "px-2", children: flamegraphHint })) : null] })] }), isMultiPanelView && (_jsx(IconButton, { className: "py-0", onClick: () => handleClosePanel(dashboardItem), icon: _jsx(CloseIcon, {}) }))] }), getDashboardItemByType({
24
24
  type: dashboardItem,
25
25
  isHalfScreen: isMultiPanelView,
26
26
  setActionButtons,
@@ -1,8 +1,5 @@
1
1
  import { Callgraph as CallgraphType, Flamegraph, FlamegraphArrow, QueryServiceClient, Source, TableArrow, Top } from '@parca/client';
2
2
  import { ProfileSource } from '../ProfileSource';
3
- type NavigateFunction = (path: string, queryParams: any, options?: {
4
- replace?: boolean;
5
- }) => void;
6
3
  export interface FlamegraphData {
7
4
  loading: boolean;
8
5
  data?: Flamegraph;
@@ -43,11 +40,10 @@ export interface ProfileViewProps {
43
40
  sourceData?: SourceData;
44
41
  profileSource?: ProfileSource;
45
42
  queryClient?: QueryServiceClient;
46
- navigateTo?: NavigateFunction;
47
43
  compare?: boolean;
48
44
  onDownloadPProf: () => void;
49
45
  pprofDownloading?: boolean;
50
46
  }
51
- export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, navigateTo, onDownloadPProf, pprofDownloading, compare, }: ProfileViewProps) => JSX.Element;
47
+ export declare const ProfileView: ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, }: ProfileViewProps) => JSX.Element;
52
48
  export {};
53
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA2BA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACV,GAAG,EACJ,MAAM,eAAe,CAAC;AAgBvB,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAS/C,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAC,KAAK,IAAI,CAAC;AAEhG,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,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,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,UAAU,aAAa;IACrB,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,UAAU,UAAU;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,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,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAWD,eAAO,MAAM,WAAW,sKAarB,gBAAgB,KAAG,GAAG,CAAC,OA+UzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA2BA,OAAO,EACL,SAAS,IAAI,aAAa,EAC1B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,UAAU,EACV,GAAG,EACJ,MAAM,eAAe,CAAC;AAgBvB,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAS/C,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,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,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,UAAU,aAAa;IACrB,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,UAAU,UAAU;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,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,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAWD,eAAO,MAAM,WAAW,0JAYrB,gBAAgB,KAAG,GAAG,CAAC,OAoUzB,CAAC"}
@@ -12,7 +12,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
12
12
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
- import { Profiler, useEffect, useMemo, useState } from 'react';
15
+ import { Profiler, useEffect, useState } from 'react';
16
16
  import { Icon } from '@iconify/react';
17
17
  import cx from 'classnames';
18
18
  import { scaleLinear } from 'd3';
@@ -26,7 +26,7 @@ import { Callgraph } from '../';
26
26
  import { jsonToDot } from '../Callgraph/utils';
27
27
  import ProfileIcicleGraph from '../ProfileIcicleGraph';
28
28
  import { SourceView } from '../SourceView';
29
- import Table from '../Table';
29
+ import { Table } from '../Table';
30
30
  import ProfileShareButton from '../components/ProfileShareButton';
31
31
  import FilterByFunctionButton from './FilterByFunctionButton';
32
32
  import { ProfileViewContextProvider } from './ProfileViewContext';
@@ -38,23 +38,16 @@ function arrayEquals(a, b) {
38
38
  a.length === b.length &&
39
39
  a.every((val, index) => val === b[index]));
40
40
  }
41
- export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, navigateTo, onDownloadPProf, pprofDownloading, compare, }) => {
41
+ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, callgraphData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, }) => {
42
42
  const { timezone } = useParcaContext();
43
43
  const { ref, dimensions } = useContainerDimensions();
44
44
  const [curPath, setCurPath] = useState([]);
45
- const [rawDashboardItems = ['icicle'], setDashboardItems] = useURLState({
46
- param: 'dashboard_items',
47
- navigateTo,
45
+ const [dashboardItems, setDashboardItems] = useURLState('dashboard_items', {
46
+ alwaysReturnArray: true,
48
47
  });
49
48
  const [graphvizLoaded, setGraphvizLoaded] = useState(false);
50
49
  const [callgraphSVG, setCallgraphSVG] = useState(undefined);
51
- const [currentSearchString] = useURLState({ param: 'search_string' });
52
- const dashboardItems = useMemo(() => {
53
- if (rawDashboardItems !== undefined) {
54
- return rawDashboardItems;
55
- }
56
- return ['icicle'];
57
- }, [rawDashboardItems]);
50
+ const [currentSearchString, setSearchString] = useURLState('search_string');
58
51
  const isDarkMode = useAppSelector(selectDarkMode);
59
52
  const isMultiPanelView = dashboardItems.length > 1;
60
53
  const { perf, profileViewExternalMainActions, profileViewExternalSubActions } = useParcaContext();
@@ -107,7 +100,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
107
100
  return (_jsx(ConditionalWrapper, { condition: perf?.onRender != null, WrapperComponent: Profiler, wrapperProps: {
108
101
  id: 'icicleGraph',
109
102
  onRender: perf?.onRender,
110
- }, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, arrow: flamegraphData?.arrow, graph: flamegraphData?.data, total: total, filtered: filtered, profileType: profileSource?.ProfileType(), navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons, error: flamegraphData.error, isHalfScreen: isHalfScreen, width: dimensions?.width !== undefined
103
+ }, children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, arrow: flamegraphData?.arrow, graph: flamegraphData?.data, total: total, filtered: filtered, profileType: profileSource?.ProfileType(), loading: flamegraphData.loading, setActionButtons: setActionButtons, error: flamegraphData.error, isHalfScreen: isHalfScreen, width: dimensions?.width !== undefined
111
104
  ? isHalfScreen
112
105
  ? (dimensions.width - 40) / 2
113
106
  : dimensions.width - 16
@@ -119,7 +112,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
119
112
  dimensions?.width !== undefined ? (_jsx(Callgraph, { data: callgraphData.data, svgString: callgraphSVG, profileType: profileSource?.ProfileType(), width: isHalfScreen ? dimensions?.width / 2 : dimensions?.width })) : (_jsx(_Fragment, {}));
120
113
  }
121
114
  case 'table': {
122
- return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), navigateTo: navigateTo, setActionButtons: setActionButtons, currentSearchString: currentSearchString, isHalfScreen: isHalfScreen })) : (_jsx(_Fragment, {}));
115
+ return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), setActionButtons: setActionButtons, currentSearchString: currentSearchString, setSearchString: setSearchString, isHalfScreen: isHalfScreen })) : (_jsx(_Fragment, {}));
123
116
  }
124
117
  case 'source': {
125
118
  return sourceData != null ? (_jsx(SourceView, { loading: sourceData.loading, data: sourceData.data, total: total, filtered: filtered, setActionButtons: setActionButtons })) : (_jsx(_Fragment, {}));
@@ -157,13 +150,13 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
157
150
  'items-center': hasProfileSource,
158
151
  }), children: [_jsxs("div", { children: [hasProfileSource && (_jsxs("div", { className: "max-w-[300px]", children: [_jsx("div", { className: "text-sm font-medium capitalize", children: headerParts.length > 0 ? headerParts[0].replace(/"/g, '') : '' }), _jsx("div", { className: "text-xs", children: headerParts.length > 1
159
152
  ? headerParts[headerParts.length - 1].replace(/"/g, '')
160
- : '' })] })), profileViewExternalMainActions != null ? profileViewExternalMainActions : null] }), _jsxs("div", { className: "lg:flex flex-wrap items-center gap-2 md:justify-end hidden", children: [_jsx(FilterByFunctionButton, { navigateTo: navigateTo }), profileViewExternalSubActions != null ? profileViewExternalSubActions : null, _jsx(UserPreferences, { customButton: _jsxs(Button, { className: "gap-2", variant: "neutral", id: "h-viz-preferences", children: ["Preferences", _jsx(Icon, { icon: "pajamas:preferences", width: 20 })] }) }), profileSource !== undefined && queryClient !== undefined ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient })) : null, _jsxs(Button, { className: "gap-2", variant: "neutral", onClick: e => {
153
+ : '' })] })), profileViewExternalMainActions != null ? profileViewExternalMainActions : null] }), _jsxs("div", { className: "lg:flex flex-wrap items-center gap-2 md:justify-end hidden", children: [_jsx(FilterByFunctionButton, {}), profileViewExternalSubActions != null ? profileViewExternalSubActions : null, _jsx(UserPreferences, { customButton: _jsxs(Button, { className: "gap-2", variant: "neutral", id: "h-viz-preferences", children: ["Preferences", _jsx(Icon, { icon: "pajamas:preferences", width: 20 })] }) }), profileSource !== undefined && queryClient !== undefined ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient })) : null, _jsxs(Button, { className: "gap-2", variant: "neutral", onClick: e => {
161
154
  e.preventDefault();
162
155
  onDownloadPProf();
163
- }, disabled: pprofDownloading, id: "h-download-pprof", children: [pprofDownloading != null && pprofDownloading ? 'Downloading...' : 'Download pprof', _jsx(Icon, { icon: "material-symbols:download", width: 20 })] }), _jsx(ViewSelector, { defaultValue: "", navigateTo: navigateTo, position: -1, placeholderText: "Add panel", icon: _jsx(Icon, { icon: "material-symbols:add", width: 20 }), addView: true, disabled: isMultiPanelView || dashboardItems.length < 1, id: "h-add-panel" })] })] }), _jsx("div", { className: "w-full", ref: ref, children: _jsx(DragDropContext, { onDragEnd: onDragEnd, children: _jsx(Droppable, { droppableId: "droppable", direction: "horizontal", children: provided => (_jsx("div", { ref: provided.innerRef, className: cx('grid w-full gap-2', isMultiPanelView ? 'grid-cols-2' : 'grid-cols-1'), ...provided.droppableProps, children: dashboardItems.map((dashboardItem, index) => {
156
+ }, disabled: pprofDownloading, id: "h-download-pprof", children: [pprofDownloading != null && pprofDownloading ? 'Downloading...' : 'Download pprof', _jsx(Icon, { icon: "material-symbols:download", width: 20 })] }), _jsx(ViewSelector, { defaultValue: "", position: -1, placeholderText: "Add panel", icon: _jsx(Icon, { icon: "material-symbols:add", width: 20 }), addView: true, disabled: isMultiPanelView || dashboardItems.length < 1, id: "h-add-panel" })] })] }), _jsx("div", { className: "w-full", ref: ref, children: _jsx(DragDropContext, { onDragEnd: onDragEnd, children: _jsx(Droppable, { droppableId: "droppable", direction: "horizontal", children: provided => (_jsx("div", { ref: provided.innerRef, className: cx('grid w-full gap-2', isMultiPanelView ? 'grid-cols-2' : 'grid-cols-1'), ...provided.droppableProps, children: dashboardItems.map((dashboardItem, index) => {
164
157
  return (_jsx(Draggable, { draggableId: dashboardItem, index: index, isDragDisabled: !isMultiPanelView, children: (provided, snapshot) => (_createElement("div", { ref: provided.innerRef, ...provided.draggableProps, key: dashboardItem, className: cx('w-full rounded p-2 shadow dark:border dark:border-gray-700 dark:bg-gray-700 min-h-96', snapshot.isDragging
165
158
  ? 'bg-gray-200 dark:bg-gray-500'
166
159
  : 'bg-white dark:bg-gray-700') },
167
- _jsx(VisualizationPanel, { handleClosePanel: handleClosePanel, isMultiPanelView: isMultiPanelView, dashboardItem: dashboardItem, getDashboardItemByType: getDashboardItemByType, dragHandleProps: provided.dragHandleProps, navigateTo: navigateTo, index: index }))) }, dashboardItem));
160
+ _jsx(VisualizationPanel, { handleClosePanel: handleClosePanel, isMultiPanelView: isMultiPanelView, dashboardItem: dashboardItem, getDashboardItemByType: getDashboardItemByType, dragHandleProps: provided.dragHandleProps, index: index }))) }, dashboardItem));
168
161
  }) })) }) }) })] }) }));
169
162
  };
@@ -1,12 +1,10 @@
1
1
  import { QueryServiceClient } from '@parca/client';
2
- import { type NavigateFunction } from '@parca/utilities';
3
2
  import { ProfileSource } from './ProfileSource';
4
3
  interface ProfileViewWithDataProps {
5
4
  queryClient: QueryServiceClient;
6
5
  profileSource: ProfileSource;
7
- navigateTo?: NavigateFunction;
8
6
  compare?: boolean;
9
7
  }
10
- export declare const ProfileViewWithData: ({ queryClient, profileSource, navigateTo, }: ProfileViewWithDataProps) => JSX.Element;
8
+ export declare const ProfileViewWithData: ({ queryClient, profileSource, }: ProfileViewWithDataProps) => JSX.Element;
11
9
  export default ProfileViewWithData;
12
10
  //# sourceMappingURL=ProfileViewWithData.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileViewWithData.d.ts","sourceRoot":"","sources":["../src/ProfileViewWithData.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA0B,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAE1E,OAAO,EAAa,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGnE,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAK9C,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB,gDAI7B,wBAAwB,KAAG,GAAG,CAAC,OAgNjC,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;AAK1E,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAK9C,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,mBAAmB,oCAG7B,wBAAwB,KAAG,GAAG,CAAC,OA+MjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -19,15 +19,20 @@ import { FIELD_FUNCTION_NAME } from './ProfileIcicleGraph/IcicleGraphArrow';
19
19
  import { ProfileView } from './ProfileView';
20
20
  import { useQuery } from './useQuery';
21
21
  import { downloadPprof } from './utils';
22
- export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, }) => {
22
+ export const ProfileViewWithData = ({ queryClient, profileSource, }) => {
23
23
  const metadata = useGrpcMetadata();
24
- const [dashboardItems = ['icicle']] = useURLState({ param: 'dashboard_items', navigateTo });
25
- const [sourceBuildID] = useURLState({ param: 'source_buildid', navigateTo });
26
- const [sourceFilename] = useURLState({ param: 'source_filename', navigateTo });
27
- const [groupBy = [FIELD_FUNCTION_NAME]] = useURLState({ param: 'group_by', navigateTo });
28
- const [invertStack] = useURLState({ param: 'invert_call_stack', navigateTo });
24
+ const [dashboardItems] = useURLState('dashboard_items', {
25
+ alwaysReturnArray: true,
26
+ });
27
+ const [sourceBuildID] = useURLState('source_buildid');
28
+ const [sourceFilename] = useURLState('source_filename');
29
+ const [groupBy] = useURLState('group_by', {
30
+ defaultValue: [FIELD_FUNCTION_NAME],
31
+ alwaysReturnArray: true,
32
+ });
33
+ const [invertStack] = useURLState('invert_call_stack');
29
34
  const invertCallStack = invertStack === 'true';
30
- const [binaryFrameFilterStr] = useURLState({ param: 'binary_frame_filter', navigateTo });
35
+ const [binaryFrameFilterStr] = useURLState('binary_frame_filter');
31
36
  const binaryFrameFilter = typeof binaryFrameFilterStr === 'string'
32
37
  ? binaryFrameFilterStr.split(',')
33
38
  : binaryFrameFilterStr;
@@ -40,19 +45,17 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
40
45
  width = width - 12 - 16 - 12;
41
46
  return (1 / width) * 100;
42
47
  }, []);
43
- // make sure we get a string[]
44
- const groupByParam = typeof groupBy === 'string' ? [groupBy] : groupBy;
45
48
  const { isLoading: flamegraphLoading, response: flamegraphResponse, error: flamegraphError, } = useQuery(queryClient, profileSource, QueryRequest_ReportType.FLAMEGRAPH_ARROW, {
46
49
  skip: !dashboardItems.includes('icicle'),
47
50
  nodeTrimThreshold,
48
- groupBy: groupByParam,
51
+ groupBy,
49
52
  invertCallStack,
50
53
  binaryFrameFilter,
51
54
  });
52
55
  const { isLoading: profilemetadataLoading, response: profilemetadataResponse } = useQuery(queryClient, profileSource, QueryRequest_ReportType.PROFILE_METADATA, {
53
56
  skip: !dashboardItems.includes('icicle'),
54
57
  nodeTrimThreshold,
55
- groupBy: groupByParam,
58
+ groupBy,
56
59
  invertCallStack,
57
60
  binaryFrameFilter: undefined,
58
61
  });
@@ -164,6 +167,6 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
164
167
  ? sourceResponse?.report?.source
165
168
  : undefined,
166
169
  error: sourceError,
167
- }, profileSource: profileSource, queryClient: queryClient, navigateTo: navigateTo, onDownloadPProf: () => void downloadPProfClick(), pprofDownloading: pprofDownloading }));
170
+ }, profileSource: profileSource, queryClient: queryClient, onDownloadPProf: () => void downloadPProfClick(), pprofDownloading: pprofDownloading }));
168
171
  };
169
172
  export default ProfileViewWithData;
@@ -22,7 +22,7 @@ import { Highlighter, profileAwareRenderer } from './Highlighter';
22
22
  import useLineRange from './useSelectedLineRange';
23
23
  const MENU_ID = 'source-view-context-menu';
24
24
  export const SourceView = React.memo(function SourceView({ data, loading, total, filtered, setActionButtons, }) {
25
- const [sourceFileName] = useURLState({ param: 'source_filename', navigateTo: () => { } });
25
+ const [sourceFileName] = useURLState('source_filename');
26
26
  const { isDarkMode, sourceViewContextMenuItems = [] } = useParcaContext();
27
27
  const sourceCode = useMemo(() => {
28
28
  if (data === undefined) {
@@ -13,7 +13,7 @@
13
13
  import { useMemo } from 'react';
14
14
  import { useURLState } from '@parca/components';
15
15
  const useLineRange = () => {
16
- const [sourceLine, setSourceLine] = useURLState({ param: 'source_line', navigateTo: () => { } });
16
+ const [sourceLine, setSourceLine] = useURLState('source_line');
17
17
  const [startLine, endLine] = useMemo(() => {
18
18
  if (sourceLine == null) {
19
19
  return [-1, -1];
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Vector } from 'apache-arrow';
3
3
  import { ProfileType } from '@parca/parser';
4
- import { type NavigateFunction } from '@parca/utilities';
5
4
  export interface DataRow {
6
5
  id: number;
7
6
  name: string;
@@ -30,9 +29,9 @@ interface TableProps {
30
29
  total: bigint;
31
30
  filtered: bigint;
32
31
  profileType?: ProfileType;
33
- navigateTo?: NavigateFunction;
34
32
  loading: boolean;
35
33
  currentSearchString?: string;
34
+ setSearchString?: (searchString: string) => void;
36
35
  setActionButtons?: (buttons: React.JSX.Element) => void;
37
36
  isHalfScreen: boolean;
38
37
  unit?: string;