@parca/profile 0.19.142 → 0.19.144

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 (137) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
  3. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +22 -28
  4. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  5. package/dist/ProfileExplorer/ProfileExplorerCompare.js +72 -73
  6. package/dist/ProfileFlameChart/SamplesStrips/index.d.ts +2 -2
  7. package/dist/ProfileFlameChart/SamplesStrips/index.d.ts.map +1 -1
  8. package/dist/ProfileFlameChart/index.d.ts.map +1 -1
  9. package/dist/ProfileFlameChart/index.js +20 -24
  10. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.d.ts.map +1 -1
  11. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +13 -14
  12. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
  13. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +6 -5
  14. package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
  15. package/dist/ProfileFlameGraph/index.js +8 -7
  16. package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
  17. package/dist/ProfileMetricsGraph/index.js +6 -8
  18. package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
  19. package/dist/ProfileSelector/MetricsGraphSection.js +48 -55
  20. package/dist/ProfileSelector/index.d.ts +1 -1
  21. package/dist/ProfileSelector/index.d.ts.map +1 -1
  22. package/dist/ProfileSelector/index.js +216 -210
  23. package/dist/ProfileSelector/useAutoQuerySelector.d.ts +1 -3
  24. package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
  25. package/dist/ProfileSelector/useAutoQuerySelector.js +133 -104
  26. package/dist/ProfileView/components/ActionButtons/SortByDropdown.d.ts.map +1 -1
  27. package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +24 -25
  28. package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
  29. package/dist/ProfileView/components/ColorStackLegend.js +3 -5
  30. package/dist/ProfileView/components/InvertCallStack/index.d.ts.map +1 -1
  31. package/dist/ProfileView/components/InvertCallStack/index.js +47 -47
  32. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts +1 -2
  33. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts.map +1 -1
  34. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +37 -34
  35. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
  36. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +282 -294
  37. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
  38. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +7 -8
  39. package/dist/ProfileView/components/Toolbars/index.d.ts +2 -2
  40. package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
  41. package/dist/ProfileView/components/Toolbars/index.js +1 -1
  42. package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -1
  43. package/dist/ProfileView/components/ViewSelector/index.js +53 -75
  44. package/dist/ProfileView/context/DashboardContext.d.ts.map +1 -1
  45. package/dist/ProfileView/context/DashboardContext.js +36 -44
  46. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -1
  47. package/dist/ProfileView/hooks/useResetFlameGraphState.js +8 -7
  48. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
  49. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +59 -59
  50. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.d.ts.map +1 -1
  51. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +37 -22
  52. package/dist/ProfileView/hooks/useVisualizationState.d.ts +3 -3
  53. package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
  54. package/dist/ProfileView/hooks/useVisualizationState.js +116 -147
  55. package/dist/ProfileViewWithData.d.ts.map +1 -1
  56. package/dist/ProfileViewWithData.js +35 -45
  57. package/dist/Sandwich/index.d.ts.map +1 -1
  58. package/dist/Sandwich/index.js +6 -5
  59. package/dist/SourceView/index.d.ts.map +1 -1
  60. package/dist/SourceView/index.js +6 -4
  61. package/dist/SourceView/useSelectedLineRange.d.ts.map +1 -1
  62. package/dist/SourceView/useSelectedLineRange.js +52 -76
  63. package/dist/Table/MoreDropdown.d.ts.map +1 -1
  64. package/dist/Table/MoreDropdown.js +42 -53
  65. package/dist/Table/TableContextMenu.d.ts.map +1 -1
  66. package/dist/Table/TableContextMenu.js +15 -19
  67. package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
  68. package/dist/Table/hooks/useTableConfiguration.js +107 -115
  69. package/dist/Table/index.d.ts.map +1 -1
  70. package/dist/Table/index.js +16 -16
  71. package/dist/TopTable/index.d.ts.map +1 -1
  72. package/dist/TopTable/index.js +112 -127
  73. package/dist/hooks/urlParsers.d.ts +18 -0
  74. package/dist/hooks/urlParsers.d.ts.map +1 -0
  75. package/dist/hooks/urlParsers.js +44 -0
  76. package/dist/hooks/useColorBy.d.ts +5 -0
  77. package/dist/hooks/useColorBy.d.ts.map +1 -0
  78. package/dist/hooks/useColorBy.js +63 -0
  79. package/dist/hooks/useCompareModeMeta.d.ts.map +1 -1
  80. package/dist/hooks/useCompareModeMeta.js +94 -138
  81. package/dist/hooks/useDashboardItems.d.ts +5 -0
  82. package/dist/hooks/useDashboardItems.d.ts.map +1 -0
  83. package/dist/hooks/useDashboardItems.js +68 -0
  84. package/dist/hooks/useQueryState.d.ts +4 -4
  85. package/dist/hooks/useQueryState.d.ts.map +1 -1
  86. package/dist/hooks/useQueryState.js +127 -122
  87. package/dist/index.d.ts +3 -2
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +3 -12
  90. package/dist/useQuery.js +2 -1
  91. package/dist/useSumBy.d.ts +1 -1
  92. package/dist/useSumBy.d.ts.map +1 -1
  93. package/dist/useSumBy.js +2 -2
  94. package/package.json +4 -3
  95. package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +11 -13
  96. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +11 -9
  97. package/src/ProfileFlameChart/SamplesStrips/index.tsx +2 -2
  98. package/src/ProfileFlameChart/index.tsx +21 -28
  99. package/src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx +10 -9
  100. package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +5 -3
  101. package/src/ProfileFlameGraph/index.tsx +6 -9
  102. package/src/ProfileMetricsGraph/index.tsx +6 -8
  103. package/src/ProfileSelector/MetricsGraphSection.tsx +5 -10
  104. package/src/ProfileSelector/index.tsx +33 -33
  105. package/src/ProfileSelector/useAutoQuerySelector.ts +64 -42
  106. package/src/ProfileView/components/ActionButtons/SortByDropdown.tsx +10 -6
  107. package/src/ProfileView/components/ColorStackLegend.tsx +2 -4
  108. package/src/ProfileView/components/InvertCallStack/index.tsx +5 -4
  109. package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.tsx +94 -192
  110. package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts +21 -21
  111. package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +24 -25
  112. package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +4 -5
  113. package/src/ProfileView/components/Toolbars/index.tsx +3 -3
  114. package/src/ProfileView/components/ViewSelector/index.tsx +9 -16
  115. package/src/ProfileView/context/DashboardContext.tsx +6 -6
  116. package/src/ProfileView/hooks/useResetFlameGraphState.ts +6 -4
  117. package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +24 -26
  118. package/src/ProfileView/hooks/useResetStateOnSeriesChange.ts +16 -8
  119. package/src/ProfileView/hooks/useVisualizationState.ts +61 -69
  120. package/src/ProfileViewWithData.tsx +29 -35
  121. package/src/Sandwich/index.tsx +4 -3
  122. package/src/SourceView/index.tsx +4 -2
  123. package/src/SourceView/useSelectedLineRange.ts +34 -19
  124. package/src/Table/MoreDropdown.tsx +9 -11
  125. package/src/Table/TableContextMenu.tsx +10 -13
  126. package/src/Table/hooks/useTableConfiguration.tsx +3 -4
  127. package/src/Table/index.tsx +12 -21
  128. package/src/TopTable/index.tsx +3 -4
  129. package/src/hooks/urlParsers.ts +38 -0
  130. package/src/hooks/useColorBy.ts +42 -0
  131. package/src/hooks/useCompareModeMeta.ts +61 -91
  132. package/src/hooks/useDashboardItems.ts +46 -0
  133. package/src/hooks/useQueryState.test.tsx +275 -345
  134. package/src/hooks/useQueryState.ts +153 -120
  135. package/src/index.tsx +16 -15
  136. package/src/useQuery.tsx +1 -1
  137. package/src/useSumBy.ts +3 -3
@@ -23,15 +23,17 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
23
23
  // See the License for the specific language governing permissions and
24
24
  // limitations under the License.
25
25
 
26
- import { useCallback, useEffect, useMemo, useState } from 'react';
27
- import { DateTimeRange, useParcaContext, useURLState, useURLStateBatch } from '@parca/components';
26
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
27
+ import { useQueryState as useNuqsQueryState, useQueryStates } from 'nuqs';
28
+ import { DateTimeRange, useParcaContext } from '@parca/components';
28
29
  import { Query } from '@parca/parser';
29
30
  import { ProfileSelectionFromParams } from '../ProfileSource';
30
31
  import { useResetFlameGraphState } from '../ProfileView/hooks/useResetFlameGraphState';
31
32
  import { useResetStateOnProfileTypeChange } from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
32
33
  import { DEFAULT_EMPTY_SUM_BY, sumByToParam, useSumBy, useSumByFromParams } from '../useSumBy';
34
+ import { commaArrayParam, stringParam } from './urlParsers';
33
35
  export var useQueryState = function useQueryState() {
34
- var _ref, _ref2;
36
+ var _queryParams$expressi, _queryParams$from, _queryParams$to, _queryParams$time_sel, _ref, _ref2;
35
37
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
36
38
  var _useParcaContext = useParcaContext(),
37
39
  queryClient = _useParcaContext.queryServiceClient;
@@ -46,61 +48,64 @@ export var useQueryState = function useQueryState() {
46
48
  _options$comparing = options.comparing,
47
49
  comparing = _options$comparing === void 0 ? false : _options$comparing,
48
50
  onProfileTypeChange = options.onProfileTypeChange;
49
- var batchUpdates = useURLStateBatch();
50
51
  var resetFlameGraphState = useResetFlameGraphState();
51
52
  var resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
52
53
 
53
- // URL state hooks with appropriate suffixes
54
- var _useURLState = useURLState("expression".concat(suffix), {
55
- defaultValue: defaultExpression
56
- }),
57
- _useURLState2 = _slicedToArray(_useURLState, 2),
58
- expression = _useURLState2[0],
59
- setExpressionState = _useURLState2[1];
60
- var _useURLState3 = useURLState("from".concat(suffix), {
61
- defaultValue: defaultFrom === null || defaultFrom === void 0 ? void 0 : defaultFrom.toString()
62
- }),
63
- _useURLState4 = _slicedToArray(_useURLState3, 2),
64
- from = _useURLState4[0],
65
- setFromState = _useURLState4[1];
66
- var _useURLState5 = useURLState("to".concat(suffix), {
67
- defaultValue: defaultTo === null || defaultTo === void 0 ? void 0 : defaultTo.toString()
68
- }),
69
- _useURLState6 = _slicedToArray(_useURLState5, 2),
70
- to = _useURLState6[0],
71
- setToState = _useURLState6[1];
72
- var _useURLState7 = useURLState("time_selection".concat(suffix), {
73
- defaultValue: defaultTimeSelection
74
- }),
75
- _useURLState8 = _slicedToArray(_useURLState7, 2),
76
- timeSelection = _useURLState8[0],
77
- setTimeSelectionState = _useURLState8[1];
78
- var _useURLState9 = useURLState("sum_by".concat(suffix)),
79
- _useURLState0 = _slicedToArray(_useURLState9, 2),
80
- sumByParam = _useURLState0[0],
81
- setSumByParam = _useURLState0[1];
82
- var _useURLState1 = useURLState('group_by', {
83
- alwaysReturnArray: true
54
+ // URL state hooks with appropriate suffixes via useQueryStates
55
+ var _useQueryStates = useQueryStates({
56
+ expression: stringParam,
57
+ from: stringParam,
58
+ to: stringParam,
59
+ time_selection: stringParam,
60
+ sum_by: stringParam,
61
+ merge_from: stringParam,
62
+ merge_to: stringParam,
63
+ selection: stringParam
64
+ }, {
65
+ history: 'replace',
66
+ urlKeys: {
67
+ expression: "expression".concat(suffix),
68
+ from: "from".concat(suffix),
69
+ to: "to".concat(suffix),
70
+ time_selection: "time_selection".concat(suffix),
71
+ sum_by: "sum_by".concat(suffix),
72
+ merge_from: "merge_from".concat(suffix),
73
+ merge_to: "merge_to".concat(suffix),
74
+ selection: "selection".concat(suffix)
75
+ }
84
76
  }),
85
- _useURLState10 = _slicedToArray(_useURLState1, 2),
86
- setGroupByParam = _useURLState10[1];
87
- var _useURLState11 = useURLState("merge_from".concat(suffix)),
88
- _useURLState12 = _slicedToArray(_useURLState11, 2),
89
- mergeFrom = _useURLState12[0],
90
- setMergeFromState = _useURLState12[1];
91
- var _useURLState13 = useURLState("merge_to".concat(suffix)),
92
- _useURLState14 = _slicedToArray(_useURLState13, 2),
93
- mergeTo = _useURLState14[0],
94
- setMergeToState = _useURLState14[1];
77
+ _useQueryStates2 = _slicedToArray(_useQueryStates, 2),
78
+ queryParams = _useQueryStates2[0],
79
+ setQueryParams = _useQueryStates2[1];
80
+ var expression = (_queryParams$expressi = queryParams.expression) !== null && _queryParams$expressi !== void 0 ? _queryParams$expressi : defaultExpression;
81
+ var from = (_queryParams$from = queryParams.from) !== null && _queryParams$from !== void 0 ? _queryParams$from : defaultFrom === null || defaultFrom === void 0 ? void 0 : defaultFrom.toString();
82
+ var to = (_queryParams$to = queryParams.to) !== null && _queryParams$to !== void 0 ? _queryParams$to : defaultTo === null || defaultTo === void 0 ? void 0 : defaultTo.toString();
83
+ var timeSelection = (_queryParams$time_sel = queryParams.time_selection) !== null && _queryParams$time_sel !== void 0 ? _queryParams$time_sel : defaultTimeSelection;
84
+ var sumByParam = queryParams.sum_by;
85
+ var mergeFrom = queryParams.merge_from;
86
+ var mergeTo = queryParams.merge_to;
87
+ var selectionParam = queryParams.selection;
95
88
 
96
- // ProfileSelection URL state hooks - reuses merge_from/merge_to but adds selection
97
- var _useURLState15 = useURLState("selection".concat(suffix)),
98
- _useURLState16 = _slicedToArray(_useURLState15, 2),
99
- selectionParam = _useURLState16[0],
100
- setSelectionParam = _useURLState16[1];
89
+ // Individual setters for direct access
90
+ var setExpressionState = useCallback(function (val) {
91
+ return void setQueryParams({
92
+ expression: val
93
+ });
94
+ }, [setQueryParams]);
95
+ var setSumByParam = useCallback(function (val_0) {
96
+ return void setQueryParams({
97
+ sum_by: val_0
98
+ });
99
+ }, [setQueryParams]);
100
+ var _useNuqsQueryState = useNuqsQueryState('group_by', commaArrayParam),
101
+ _useNuqsQueryState2 = _slicedToArray(_useNuqsQueryState, 2),
102
+ setRawGroupByParam = _useNuqsQueryState2[1];
103
+ var setGroupByParam = useCallback(function (val_1) {
104
+ void setRawGroupByParam(val_1);
105
+ }, [setRawGroupByParam]);
101
106
 
102
107
  // Parse sumBy from URL parameter format
103
- var sumBy = useSumByFromParams(sumByParam);
108
+ var sumBy = useSumByFromParams(sumByParam !== null && sumByParam !== void 0 ? sumByParam : undefined);
104
109
 
105
110
  // Draft state management
106
111
  var _useState = useState(expression !== null && expression !== void 0 ? expression : defaultExpression),
@@ -185,22 +190,29 @@ export var useQueryState = function useQueryState() {
185
190
 
186
191
  // Sync computed sumBy to URL if URL doesn't already have a value
187
192
  // to ensure the shared URL can always pick it up.
193
+ // Only run once (when sumByParam first becomes available), not on every change,
194
+ // to avoid oscillation with external writers (useViewQueryState).
195
+ var hasSyncedSumByRef = useRef(false);
188
196
  useEffect(function () {
189
- if (sumByParam === undefined && computedSumByFromURL !== undefined && !sumBySelectionLoading) {
190
- setSumByParam(sumByToParam(computedSumByFromURL));
197
+ if (sumByParam !== null) {
198
+ hasSyncedSumByRef.current = true;
199
+ }
200
+ if (!hasSyncedSumByRef.current && sumByParam === null && computedSumByFromURL !== undefined && !sumBySelectionLoading) {
201
+ hasSyncedSumByRef.current = true;
202
+ void setSumByParam(sumByToParam(computedSumByFromURL));
191
203
  }
192
204
  }, [sumByParam, computedSumByFromURL, sumBySelectionLoading, setSumByParam]);
193
205
 
194
206
  // Construct the QuerySelection object (committed state from URL)
195
207
  var querySelection = useMemo(function () {
196
- var range = DateTimeRange.fromRangeKey(timeSelection !== null && timeSelection !== void 0 ? timeSelection : defaultTimeSelection, from !== undefined && from !== '' ? parseInt(from) : defaultFrom, to !== undefined && to !== '' ? parseInt(to) : defaultTo);
208
+ var range = DateTimeRange.fromRangeKey(timeSelection !== null && timeSelection !== void 0 ? timeSelection : defaultTimeSelection, from != null && from !== '' ? parseInt(from) : defaultFrom, to != null && to !== '' ? parseInt(to) : defaultTo);
197
209
  return _objectSpread({
198
210
  expression: expression !== null && expression !== void 0 ? expression : defaultExpression,
199
211
  from: range.getFromMs(),
200
212
  to: range.getToMs(),
201
213
  timeSelection: range.getRangeKey(),
202
214
  sumBy: computedSumByFromURL
203
- }, mergeFrom !== undefined && mergeFrom !== '' && mergeTo !== undefined && mergeTo !== '' ? {
215
+ }, mergeFrom != null && mergeFrom !== '' && mergeTo != null && mergeTo !== '' ? {
204
216
  mergeFrom: mergeFrom,
205
217
  mergeTo: mergeTo
206
218
  } : {});
@@ -226,7 +238,7 @@ export var useQueryState = function useQueryState() {
226
238
 
227
239
  // Compute ProfileSelection from URL params
228
240
  var profileSelection = useMemo(function () {
229
- return ProfileSelectionFromParams(mergeFrom, mergeTo, selectionParam);
241
+ return ProfileSelectionFromParams(mergeFrom !== null && mergeFrom !== void 0 ? mergeFrom : undefined, mergeTo !== null && mergeTo !== void 0 ? mergeTo : undefined, selectionParam !== null && selectionParam !== void 0 ? selectionParam : undefined);
230
242
  }, [mergeFrom, mergeTo, selectionParam]);
231
243
 
232
244
  // Compute ProfileSource from ProfileSelection
@@ -240,74 +252,67 @@ export var useQueryState = function useQueryState() {
240
252
  // to the current moment when the Search button is clicked
241
253
  // Optional expression parameter allows updating the expression before committing
242
254
  var commitDraft = useCallback(function (refreshedTimeRange, expression_0) {
243
- batchUpdates(function () {
244
- var _refreshedTimeRange$f, _refreshedTimeRange$f2, _refreshedTimeRange$t, _refreshedTimeRange$t2, _refreshedTimeRange$t3;
245
- // Use provided expression or current draft expression
246
- var finalExpression = expression_0 !== null && expression_0 !== void 0 ? expression_0 : draftExpression;
255
+ var _refreshedTimeRange$f, _refreshedTimeRange$f2, _refreshedTimeRange$t, _refreshedTimeRange$t2, _refreshedTimeRange$t3;
256
+ // Use provided expression or current draft expression
257
+ var finalExpression = expression_0 !== null && expression_0 !== void 0 ? expression_0 : draftExpression;
247
258
 
248
- // Update draft state with new expression if provided
249
- if (expression_0 !== undefined) {
250
- setDraftExpression(expression_0);
251
- }
259
+ // Update draft state with new expression if provided
260
+ if (expression_0 !== undefined) {
261
+ setDraftExpression(expression_0);
262
+ }
252
263
 
253
- // Calculate the actual from/to values from draftSelection if not provided
254
- var calculatedFrom = draftSelection.from.toString();
255
- var calculatedTo = draftSelection.to.toString();
256
- var finalFrom = (_refreshedTimeRange$f = refreshedTimeRange === null || refreshedTimeRange === void 0 || (_refreshedTimeRange$f2 = refreshedTimeRange.from) === null || _refreshedTimeRange$f2 === void 0 ? void 0 : _refreshedTimeRange$f2.toString()) !== null && _refreshedTimeRange$f !== void 0 ? _refreshedTimeRange$f : draftFrom !== '' ? draftFrom : calculatedFrom;
257
- var finalTo = (_refreshedTimeRange$t = refreshedTimeRange === null || refreshedTimeRange === void 0 || (_refreshedTimeRange$t2 = refreshedTimeRange.to) === null || _refreshedTimeRange$t2 === void 0 ? void 0 : _refreshedTimeRange$t2.toString()) !== null && _refreshedTimeRange$t !== void 0 ? _refreshedTimeRange$t : draftTo !== '' ? draftTo : calculatedTo;
258
- var finalTimeSelection = (_refreshedTimeRange$t3 = refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.timeSelection) !== null && _refreshedTimeRange$t3 !== void 0 ? _refreshedTimeRange$t3 : draftTimeSelection;
264
+ // Calculate the actual from/to values from draftSelection if not provided
265
+ var calculatedFrom = draftSelection.from.toString();
266
+ var calculatedTo = draftSelection.to.toString();
267
+ var finalFrom = (_refreshedTimeRange$f = refreshedTimeRange === null || refreshedTimeRange === void 0 || (_refreshedTimeRange$f2 = refreshedTimeRange.from) === null || _refreshedTimeRange$f2 === void 0 ? void 0 : _refreshedTimeRange$f2.toString()) !== null && _refreshedTimeRange$f !== void 0 ? _refreshedTimeRange$f : draftFrom !== '' ? draftFrom : calculatedFrom;
268
+ var finalTo = (_refreshedTimeRange$t = refreshedTimeRange === null || refreshedTimeRange === void 0 || (_refreshedTimeRange$t2 = refreshedTimeRange.to) === null || _refreshedTimeRange$t2 === void 0 ? void 0 : _refreshedTimeRange$t2.toString()) !== null && _refreshedTimeRange$t !== void 0 ? _refreshedTimeRange$t : draftTo !== '' ? draftTo : calculatedTo;
269
+ var finalTimeSelection = (_refreshedTimeRange$t3 = refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.timeSelection) !== null && _refreshedTimeRange$t3 !== void 0 ? _refreshedTimeRange$t3 : draftTimeSelection;
259
270
 
260
- // Update draft state with refreshed time range if provided
261
- if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.from) !== undefined) {
262
- setDraftFrom(finalFrom);
263
- }
264
- if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.to) !== undefined) {
265
- setDraftTo(finalTo);
266
- }
267
- if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.timeSelection) !== undefined) {
268
- setDraftTimeSelection(finalTimeSelection);
269
- }
270
- setExpressionState(finalExpression);
271
- setFromState(finalFrom);
272
- setToState(finalTo);
273
- setTimeSelectionState(finalTimeSelection);
271
+ // Update draft state with refreshed time range if provided
272
+ if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.from) !== undefined) {
273
+ setDraftFrom(finalFrom);
274
+ }
275
+ if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.to) !== undefined) {
276
+ setDraftTo(finalTo);
277
+ }
278
+ if ((refreshedTimeRange === null || refreshedTimeRange === void 0 ? void 0 : refreshedTimeRange.timeSelection) !== undefined) {
279
+ setDraftTimeSelection(finalTimeSelection);
280
+ }
274
281
 
275
- // Auto-calculate merge parameters for delta profiles
276
- // Parse the final expression to check if it's a delta profile
277
- var finalQuery = Query.parse(finalExpression);
278
- var isDelta_0 = finalQuery.profileType().delta;
279
- if (isDelta_0) {
280
- setSumByParam(sumByToParam(draftSumBy));
281
- } else {
282
- setSumByParam(DEFAULT_EMPTY_SUM_BY);
282
+ // Auto-calculate merge parameters for delta profiles
283
+ var finalQuery = Query.parse(finalExpression);
284
+ var isDelta_0 = finalQuery.profileType().delta;
285
+ var sumByValue = isDelta_0 ? sumByToParam(draftSumBy) : sumByToParam(DEFAULT_EMPTY_SUM_BY);
286
+ var mergeFromValue = null;
287
+ var mergeToValue = null;
288
+ var selectionValue = null;
289
+ if (isDelta_0 && finalFrom !== '' && finalTo !== '') {
290
+ var fromMs = parseInt(finalFrom);
291
+ var toMs = parseInt(finalTo);
292
+ mergeFromValue = (BigInt(fromMs) * 1000000n).toString();
293
+ mergeToValue = (BigInt(toMs) * 1000000n).toString();
294
+ if (!comparing) {
295
+ selectionValue = finalExpression;
283
296
  }
284
- if (isDelta_0 && finalFrom !== '' && finalTo !== '') {
285
- var fromMs = parseInt(finalFrom);
286
- var toMs = parseInt(finalTo);
287
- setMergeFromState((BigInt(fromMs) * 1000000n).toString());
288
- setMergeToState((BigInt(toMs) * 1000000n).toString());
297
+ }
289
298
 
290
- // Auto-select the time range for delta profiles (but not in compare mode)
291
- // This applies both on initial load AND when Search is clicked
292
- // The selection will use the final expression and the updated time range
293
- if (!comparing) {
294
- setSelectionParam(finalExpression);
295
- } else {
296
- setSelectionParam(undefined);
297
- }
298
- } else {
299
- setMergeFromState(undefined);
300
- setMergeToState(undefined);
301
- // Clear ProfileSelection for non-delta profiles
302
- setSelectionParam(undefined);
303
- }
304
- resetFlameGraphState();
305
- if (draftProfileType.toString() !== Query.parse(querySelection.expression).profileType().toString()) {
306
- resetStateOnProfileTypeChange();
307
- onProfileTypeChange === null || onProfileTypeChange === void 0 || onProfileTypeChange();
308
- }
299
+ // Atomic URL update with all params at once
300
+ void setQueryParams({
301
+ expression: finalExpression,
302
+ from: finalFrom,
303
+ to: finalTo,
304
+ time_selection: finalTimeSelection,
305
+ sum_by: sumByValue,
306
+ merge_from: mergeFromValue,
307
+ merge_to: mergeToValue,
308
+ selection: selectionValue
309
309
  });
310
- }, [batchUpdates, draftExpression, draftFrom, draftTo, draftTimeSelection, draftSumBy, draftSelection.from, draftSelection.to, comparing, setExpressionState, setFromState, setToState, setTimeSelectionState, setSumByParam, setMergeFromState, setMergeToState, setSelectionParam, resetFlameGraphState, resetStateOnProfileTypeChange, onProfileTypeChange, draftProfileType, querySelection.expression]);
310
+ resetFlameGraphState();
311
+ if (draftProfileType.toString() !== Query.parse(querySelection.expression).profileType().toString()) {
312
+ resetStateOnProfileTypeChange();
313
+ onProfileTypeChange === null || onProfileTypeChange === void 0 || onProfileTypeChange();
314
+ }
315
+ }, [draftExpression, draftFrom, draftTo, draftTimeSelection, draftSumBy, draftSelection.from, draftSelection.to, comparing, setQueryParams, resetFlameGraphState, resetStateOnProfileTypeChange, onProfileTypeChange, draftProfileType, querySelection.expression]);
311
316
  var setDraftTimeRange = useCallback(function (newFrom, newTo, newTimeSelection) {
312
317
  setDraftFrom(newFrom.toString());
313
318
  setDraftTo(newTo.toString());
@@ -334,12 +339,12 @@ export var useQueryState = function useQueryState() {
334
339
 
335
340
  // Set ProfileSelection (auto-commits to URL immediately)
336
341
  var setProfileSelection = useCallback(function (mergeFrom_0, mergeTo_0, query_0) {
337
- batchUpdates(function () {
338
- setSelectionParam(query_0.toString());
339
- setMergeFromState(mergeFrom_0.toString());
340
- setMergeToState(mergeTo_0.toString());
342
+ void setQueryParams({
343
+ selection: query_0.toString(),
344
+ merge_from: mergeFrom_0.toString(),
345
+ merge_to: mergeTo_0.toString()
341
346
  });
342
- }, [batchUpdates, setSelectionParam, setMergeFromState, setMergeToState]);
347
+ }, [setQueryParams]);
343
348
  var draftParsedQuery = useMemo(function () {
344
349
  try {
345
350
  var _draftSelection$expre;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { ParamPreferences } from '@parca/components';
2
1
  import MatchersInput from './MatchersInput';
3
2
  import MetricsGraph, { type ContextMenuItemOrSubmenu, type Series } from './MetricsGraph';
4
3
  import ProfileExplorer from './ProfileExplorer';
@@ -25,7 +24,9 @@ export * from './useSumBy';
25
24
  export { QueryControls } from './QueryControls';
26
25
  export { default as ProfileFilters } from './ProfileView/components/ProfileFilters';
27
26
  export { useProfileFiltersUrlState } from './ProfileView/components/ProfileFilters/useProfileFiltersUrlState';
28
- export declare const DEFAULT_PROFILE_EXPLORER_PARAM_VALUES: ParamPreferences;
29
27
  export { useProfileTypes } from './ProfileSelector';
28
+ export { stringParam, boolParam, intParam, commaArrayParam, invertCallStackParser, groupByParser, flamechartDimensionParser, tableColumnsParser, hiddenBinariesParser, jsonParser, } from './hooks/urlParsers';
29
+ export { useDashboardItems } from './hooks/useDashboardItems';
30
+ export { useColorBy } from './hooks/useColorBy';
30
31
  export { ProfileExplorer, ProfileTypeSelector, CustomSelect, SelectWithRefresh, useLabelNames, MetricsGraph, SimpleMatchers, MatchersInput, type ContextMenuItemOrSubmenu, type Series, LabelsQueryProvider, useLabelsQueryProvider, UnifiedLabelsProvider, useUnifiedLabels, useQueryState, type LabelsQueryProviderContextType, };
31
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AAExD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,YAAY,EAAE,EAAC,KAAK,wBAAwB,EAAE,KAAK,MAAM,EAAC,MAAM,gBAAgB,CAAC;AACxF,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,8BAA8B,EACpC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAC,qBAAqB,EAAE,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACxF,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAOpD,OAAO,EAAC,yBAAyB,EAAC,MAAM,0CAA0C,CAAC;AAEnF,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,2DAA2D,CAAC;AACnE,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAC,yBAAyB,EAAC,MAAM,mEAAmE,CAAC;AAE5G,eAAO,MAAM,qCAAqC,EAAE,gBAWnD,CAAC;AAEF,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAElD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,KAAK,wBAAwB,EAC7B,KAAK,MAAM,EACX,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,KAAK,8BAA8B,GACpC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAgBA,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,YAAY,EAAE,EAAC,KAAK,wBAAwB,EAAE,KAAK,MAAM,EAAC,MAAM,gBAAgB,CAAC;AACxF,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAChD,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,cAAc,MAAM,kBAAkB,CAAC;AAC9C,OAAO,YAAY,MAAM,yBAAyB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,8BAA8B,EACpC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAC,qBAAqB,EAAE,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACxF,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAOpD,OAAO,EAAC,yBAAyB,EAAC,MAAM,0CAA0C,CAAC;AAEnF,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,2DAA2D,CAAC;AACnE,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,OAAO,IAAI,cAAc,EAAC,MAAM,yCAAyC,CAAC;AAClF,OAAO,EAAC,yBAAyB,EAAC,MAAM,mEAAmE,CAAC;AAE5G,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAElD,OAAO,EACL,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,GACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,KAAK,wBAAwB,EAC7B,KAAK,MAAM,EACX,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,KAAK,8BAA8B,GACpC,CAAC"}
package/dist/index.js CHANGED
@@ -47,17 +47,8 @@ export * from './useSumBy';
47
47
  export { QueryControls } from './QueryControls';
48
48
  export { default as ProfileFilters } from './ProfileView/components/ProfileFilters';
49
49
  export { useProfileFiltersUrlState } from './ProfileView/components/ProfileFilters/useProfileFiltersUrlState';
50
- export var DEFAULT_PROFILE_EXPLORER_PARAM_VALUES = {
51
- dashboard_items: {
52
- defaultValue: 'flamegraph',
53
- splitOnCommas: true // This param should split on commas for array values
54
- },
55
- group_by: {
56
- splitOnCommas: true
57
- },
58
- flamechart_dimension: {
59
- splitOnCommas: true
60
- }
61
- };
62
50
  export { useProfileTypes } from './ProfileSelector';
51
+ export { stringParam, boolParam, intParam, commaArrayParam, invertCallStackParser, groupByParser, flamechartDimensionParser, tableColumnsParser, hiddenBinariesParser, jsonParser } from './hooks/urlParsers';
52
+ export { useDashboardItems } from './hooks/useDashboardItems';
53
+ export { useColorBy } from './hooks/useColorBy';
63
54
  export { ProfileExplorer, ProfileTypeSelector, CustomSelect, SelectWithRefresh, useLabelNames, MetricsGraph, SimpleMatchers, MatchersInput, LabelsQueryProvider, useLabelsQueryProvider, UnifiedLabelsProvider, useUnifiedLabels, useQueryState };
package/dist/useQuery.js CHANGED
@@ -47,7 +47,8 @@ export var useQuery = function useQuery(client, profileSource, reportType, optio
47
47
  var protoFiltersKey = t2;
48
48
  var t3;
49
49
  if ($[4] !== profileSource) {
50
- t3 = profileSource.toKey();
50
+ var _profileSource$toKey;
51
+ t3 = (_profileSource$toKey = profileSource === null || profileSource === void 0 ? void 0 : profileSource.toKey()) !== null && _profileSource$toKey !== void 0 ? _profileSource$toKey : "";
51
52
  $[4] = profileSource;
52
53
  $[5] = t3;
53
54
  } else {
@@ -12,7 +12,7 @@ export declare const useDefaultSumBy: (profileType: ProfileType | undefined, lab
12
12
  isLoading: boolean;
13
13
  };
14
14
  export declare const useSumByFromParams: (param: string | string[] | undefined) => string[] | undefined;
15
- export declare const sumByToParam: (sumBy: string[] | undefined) => string | string[] | undefined;
15
+ export declare const sumByToParam: (sumBy: string[] | undefined) => string | null;
16
16
  export declare const useSumBy: (queryClient: QueryServiceClient, profileType: ProfileType | undefined, timeRange: DateTimeRange, draftProfileType: ProfileType | undefined, draftTimeRange: DateTimeRange, defaultValue?: string[]) => {
17
17
  sumBy: string[] | undefined;
18
18
  setSumBy: (sumBy: string[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../src/useSumBy.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAAO,CAAC;AA6BjD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,EAC5B,YAAY,MAAM,EAAE,GAAG,SAAS,EAChC,oBAEG;IACD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,KACL,CACD,MAAM,EAAE,GAAG,SAAS,EACpB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EAC1B;IACE,SAAS,EAAE,OAAO,CAAC;CACpB,CAqEF,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,KAC3B;IAAC,YAAY,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAMzD,CAAC;AAyBF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EAAE,GAAG,SAMpF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAU9E,CAAC;AAGF,eAAO,MAAM,QAAQ,GACnB,aAAa,kBAAkB,EAC/B,aAAa,WAAW,GAAG,SAAS,EACpC,WAAW,aAAa,EACxB,kBAAkB,WAAW,GAAG,SAAS,EACzC,gBAAgB,aAAa,EAC7B,eAAe,MAAM,EAAE,KACtB;IACD,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,OAAO,CAAC;CAoC9B,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,aAAa,kBAAkB,EAC/B,aAAa,WAAW,GAAG,SAAS,EACpC,WAAW,aAAa,EACxB,eAAe,MAAM,EAAE,KACtB;IACD,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,OAAO,CAAC;CAyB9B,CAAC"}
1
+ {"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../src/useSumBy.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAAO,CAAC;AA6BjD,eAAO,MAAM,iBAAiB,GAC5B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,EAC5B,YAAY,MAAM,EAAE,GAAG,SAAS,EAChC,oBAEG;IACD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,KACL,CACD,MAAM,EAAE,GAAG,SAAS,EACpB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EAC1B;IACE,SAAS,EAAE,OAAO,CAAC;CACpB,CAqEF,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,aAAa,WAAW,GAAG,SAAS,EACpC,mBAAmB,OAAO,EAC1B,QAAQ,MAAM,EAAE,GAAG,SAAS,KAC3B;IAAC,YAAY,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAMzD,CAAC;AAyBF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,EAAE,GAAG,SAMpF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM,GAAG,IAUnE,CAAC;AAGF,eAAO,MAAM,QAAQ,GACnB,aAAa,kBAAkB,EAC/B,aAAa,WAAW,GAAG,SAAS,EACpC,WAAW,aAAa,EACxB,kBAAkB,WAAW,GAAG,SAAS,EACzC,gBAAgB,aAAa,EAC7B,eAAe,MAAM,EAAE,KACtB;IACD,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,OAAO,CAAC;CAoC9B,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,aAAa,kBAAkB,EAC/B,aAAa,WAAW,GAAG,SAAS,EACpC,WAAW,aAAa,EACxB,eAAe,MAAM,EAAE,KACtB;IACD,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,KAAK,IAAI,CAAC;IACrD,mBAAmB,EAAE,OAAO,CAAC;CAyB9B,CAAC"}
package/dist/useSumBy.js CHANGED
@@ -163,12 +163,12 @@ export var useSumByFromParams = function useSumByFromParams(param) {
163
163
  };
164
164
  export var sumByToParam = function sumByToParam(sumBy) {
165
165
  if (sumBy === undefined) {
166
- return undefined;
166
+ return null;
167
167
  }
168
168
  if (sumBy.length === 0) {
169
169
  return '__none__';
170
170
  }
171
- return sumBy;
171
+ return sumBy.join(',');
172
172
  };
173
173
 
174
174
  // Combined hook that handles all sumBy logic: fetching labels, computing defaults, and managing selection
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.19.142",
3
+ "version": "0.19.144",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@floating-ui/react": "^0.27.12",
7
7
  "@headlessui/react": "^1.7.19",
8
8
  "@iconify/react": "^4.0.0",
9
9
  "@parca/client": "0.17.23",
10
- "@parca/components": "0.16.414",
10
+ "@parca/components": "0.16.415",
11
11
  "@parca/dynamicsize": "0.16.74",
12
12
  "@parca/hooks": "0.0.125",
13
13
  "@parca/icons": "0.16.82",
@@ -42,6 +42,7 @@
42
42
  "graphviz-wasm": "3.0.2",
43
43
  "lodash.throttle": "^4.1.1",
44
44
  "lz4js": "^0.2.0",
45
+ "nuqs": "^2.4.1",
45
46
  "react": "18.3.1",
46
47
  "react-beautiful-dnd": "^13.1.1",
47
48
  "react-contexify": "^6.0.0",
@@ -88,5 +89,5 @@
88
89
  "access": "public",
89
90
  "registry": "https://registry.npmjs.org/"
90
91
  },
91
- "gitHead": "da48a5951aeae6ef6a314839a223522d651e8910"
92
+ "gitHead": "aa4600b30ab13936a71c00552b3685fa7955f4d2"
92
93
  }
@@ -12,9 +12,10 @@
12
12
  // limitations under the License.
13
13
 
14
14
  import {Table} from '@uwdata/flechette';
15
+ import {useQueryState} from 'nuqs';
15
16
 
16
17
  import {QueryRequest_ReportType} from '@parca/client';
17
- import {useParcaContext, useURLState} from '@parca/components';
18
+ import {useParcaContext} from '@parca/components';
18
19
 
19
20
  import {
20
21
  FIELD_FUNCTION_FILE_NAME,
@@ -30,6 +31,8 @@ import {
30
31
  import {arrowToString} from '../../ProfileFlameGraph/FlameGraphArrow/utils';
31
32
  import {ProfileSource} from '../../ProfileSource';
32
33
  import {useProfileViewContext} from '../../ProfileView/context/ProfileViewContext';
34
+ import {stringParam} from '../../hooks/urlParsers';
35
+ import {useDashboardItems} from '../../hooks/useDashboardItems';
33
36
  import {useQuery} from '../../useQuery';
34
37
 
35
38
  interface Props {
@@ -107,28 +110,23 @@ export const useGraphTooltipMetaInfo = ({table, row}: Props): GraphTooltipMetaIn
107
110
  ])
108
111
  .filter(value => value[1] !== '') as Array<[string, string]>;
109
112
 
110
- const [dashboardItems, setDashboardItems] = useURLState<string[]>('dashboard_items', {
111
- alwaysReturnArray: true,
112
- });
113
+ const {dashboardItems, setDashboardItems} = useDashboardItems();
113
114
 
114
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
115
- const [unusedBuildId, setSourceBuildId] = useURLState('source_buildid');
115
+ const [_unusedBuildId, setSourceBuildId] = useQueryState('source_buildid', stringParam);
116
116
 
117
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
118
- const [unusedFilename, setSourceFilename] = useURLState('source_filename');
117
+ const [_unusedFilename, setSourceFilename] = useQueryState('source_filename', stringParam);
119
118
 
120
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
121
- const [unusedLine, setSourceLine] = useURLState('source_line');
119
+ const [_unusedLine, setSourceLine] = useQueryState('source_line', stringParam);
122
120
 
123
121
  const openFile = (): void => {
124
122
  setDashboardItems([dashboardItems[0], 'source']);
125
123
  if (mappingBuildID != null) {
126
- setSourceBuildId(mappingBuildID);
124
+ void setSourceBuildId(mappingBuildID);
127
125
  }
128
126
 
129
- setSourceFilename(functionFilename);
127
+ void setSourceFilename(functionFilename);
130
128
  if (lineNumber !== undefined) {
131
- setSourceLine(lineNumber.toString());
129
+ void setSourceLine(lineNumber.toString());
132
130
  }
133
131
  };
134
132
 
@@ -14,7 +14,6 @@
14
14
  import {useCallback, useEffect, useMemo, useState} from 'react';
15
15
 
16
16
  import {QueryServiceClient} from '@parca/client';
17
- import {useURLStateBatch} from '@parca/components';
18
17
  import {Query} from '@parca/parser';
19
18
  import {TEST_IDS, testId} from '@parca/test-utils';
20
19
  import type {NavigateFunction} from '@parca/utilities';
@@ -34,7 +33,6 @@ const ProfileExplorerCompare = ({
34
33
  navigateTo,
35
34
  }: ProfileExplorerCompareProps): JSX.Element => {
36
35
  const [showMetricsGraph, setShowMetricsGraph] = useState(true);
37
- const batchUpdates = useURLStateBatch();
38
36
  const {closeCompareMode, isCompareMode, isCompareAbsolute} = useCompareModeMeta();
39
37
 
40
38
  // Read ProfileSource states from URL for both sides
@@ -65,12 +63,17 @@ const ProfileExplorerCompare = ({
65
63
  }
66
64
 
67
65
  if (querySelectionB.expression === '' && querySelectionA.expression !== '') {
68
- batchUpdates(() => {
69
- setDraftExpressionB(querySelectionA.expression);
70
- setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection);
71
- // Commit to update the URL and trigger metrics graph load
72
- commitDraftB();
73
- });
66
+ setDraftExpressionB(querySelectionA.expression);
67
+ setDraftTimeRangeB(querySelectionA.from, querySelectionA.to, querySelectionA.timeSelection);
68
+ // Commit with explicit values since draft useState hasn't applied yet
69
+ commitDraftB(
70
+ {
71
+ from: querySelectionA.from,
72
+ to: querySelectionA.to,
73
+ timeSelection: querySelectionA.timeSelection,
74
+ },
75
+ querySelectionA.expression
76
+ );
74
77
  }
75
78
  }, [
76
79
  isCompareMode,
@@ -82,7 +85,6 @@ const ProfileExplorerCompare = ({
82
85
  setDraftExpressionB,
83
86
  setDraftTimeRangeB,
84
87
  commitDraftB,
85
- batchUpdates,
86
88
  ]);
87
89
 
88
90
  const closeProfileA = useCallback((): void => {
@@ -39,10 +39,10 @@ interface Props {
39
39
  loading?: boolean;
40
40
  cpus: LabelSet[];
41
41
  data: DataPoint[][];
42
- selectedTimeframe?: {
42
+ selectedTimeframe: {
43
43
  labels: LabelSet;
44
44
  bounds: NumberDuo;
45
- };
45
+ } | null;
46
46
  onSelectedTimeframe: (labels: LabelSet, bounds: NumberDuo | undefined) => void;
47
47
  width?: number;
48
48
  bounds: NumberDuo;