@parca/profile 0.19.140 → 0.19.143

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 (182) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/dist/GraphTooltipArrow/Content.js +224 -30
  3. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +192 -33
  4. package/dist/GraphTooltipArrow/ExpandOnHoverValue.js +53 -3
  5. package/dist/GraphTooltipArrow/index.d.ts.map +1 -1
  6. package/dist/GraphTooltipArrow/index.js +86 -56
  7. package/dist/GraphTooltipArrow/useGraphTooltip/index.js +37 -37
  8. package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +94 -68
  9. package/dist/MatchersInput/SuggestionItem.js +91 -12
  10. package/dist/MatchersInput/SuggestionsList.d.ts +2 -1
  11. package/dist/MatchersInput/SuggestionsList.d.ts.map +1 -1
  12. package/dist/MatchersInput/SuggestionsList.js +371 -157
  13. package/dist/MatchersInput/SuggestionsList.test.d.ts +2 -0
  14. package/dist/MatchersInput/SuggestionsList.test.d.ts.map +1 -0
  15. package/dist/MatchersInput/index.js +308 -115
  16. package/dist/MetricsCircle/index.js +39 -3
  17. package/dist/MetricsGraph/MetricsContextMenu/index.js +119 -19
  18. package/dist/MetricsGraph/MetricsInfoPanel/index.js +81 -20
  19. package/dist/MetricsGraph/MetricsTooltip/index.d.ts.map +1 -1
  20. package/dist/MetricsGraph/MetricsTooltip/index.js +107 -74
  21. package/dist/MetricsGraph/index.js +552 -203
  22. package/dist/MetricsGraph/useMetricsGraphDimensions.js +46 -25
  23. package/dist/MetricsGraph/utils/colorMapping.js +24 -17
  24. package/dist/MetricsSeries/index.js +70 -7
  25. package/dist/PreSelectedMatchers/index.d.ts.map +1 -1
  26. package/dist/PreSelectedMatchers/index.js +249 -102
  27. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  28. package/dist/ProfileExplorer/ProfileExplorerCompare.js +240 -45
  29. package/dist/ProfileExplorer/ProfileExplorerSingle.js +98 -11
  30. package/dist/ProfileExplorer/index.js +183 -32
  31. package/dist/ProfileFlameChart/SamplesStrips/SamplesGraph/index.js +333 -148
  32. package/dist/ProfileFlameChart/SamplesStrips/SamplesStrips.stories.js +69 -35
  33. package/dist/ProfileFlameChart/SamplesStrips/index.js +645 -134
  34. package/dist/ProfileFlameChart/SamplesStrips/labelSetUtils.js +114 -55
  35. package/dist/ProfileFlameChart/index.js +260 -126
  36. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +283 -85
  37. package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenuWrapper.js +56 -20
  38. package/dist/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.js +211 -140
  39. package/dist/ProfileFlameGraph/FlameGraphArrow/MemoizedTooltip.js +133 -38
  40. package/dist/ProfileFlameGraph/FlameGraphArrow/MiniMap.js +261 -216
  41. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
  42. package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +71 -45
  43. package/dist/ProfileFlameGraph/FlameGraphArrow/TooltipContext.d.ts.map +1 -1
  44. package/dist/ProfileFlameGraph/FlameGraphArrow/TooltipContext.js +58 -28
  45. package/dist/ProfileFlameGraph/FlameGraphArrow/ZoomControls.d.ts.map +1 -1
  46. package/dist/ProfileFlameGraph/FlameGraphArrow/ZoomControls.js +59 -8
  47. package/dist/ProfileFlameGraph/FlameGraphArrow/index.js +396 -179
  48. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.d.ts.map +1 -1
  49. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.js +68 -50
  50. package/dist/ProfileFlameGraph/FlameGraphArrow/useMappingList.js +62 -38
  51. package/dist/ProfileFlameGraph/FlameGraphArrow/useNodeColor.js +14 -6
  52. package/dist/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.js +124 -82
  53. package/dist/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.js +160 -98
  54. package/dist/ProfileFlameGraph/FlameGraphArrow/useZoom.js +232 -112
  55. package/dist/ProfileFlameGraph/FlameGraphArrow/utils.js +137 -114
  56. package/dist/ProfileFlameGraph/benchmarks/benchdata/populateData.js +85 -0
  57. package/dist/ProfileFlameGraph/index.js +322 -147
  58. package/dist/ProfileMetricsGraph/hooks/useQueryRange.js +140 -32
  59. package/dist/ProfileMetricsGraph/index.js +515 -256
  60. package/dist/ProfileSelector/CompareButton.js +132 -12
  61. package/dist/ProfileSelector/MetricsGraphSection.js +228 -63
  62. package/dist/ProfileSelector/index.d.ts +1 -1
  63. package/dist/ProfileSelector/index.d.ts.map +1 -1
  64. package/dist/ProfileSelector/index.js +734 -142
  65. package/dist/ProfileSelector/useAutoQuerySelector.d.ts +1 -3
  66. package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
  67. package/dist/ProfileSelector/useAutoQuerySelector.js +280 -132
  68. package/dist/ProfileSource.js +230 -163
  69. package/dist/ProfileTypeSelector/index.js +214 -125
  70. package/dist/ProfileView/components/ActionButtons/GroupByDropdown.js +50 -4
  71. package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +137 -32
  72. package/dist/ProfileView/components/ColorStackLegend.js +182 -54
  73. package/dist/ProfileView/components/DashboardItems/index.js +87 -28
  74. package/dist/ProfileView/components/DashboardLayout/index.js +108 -16
  75. package/dist/ProfileView/components/DiffLegend.js +172 -29
  76. package/dist/ProfileView/components/GroupByLabelsDropdown/index.js +199 -55
  77. package/dist/ProfileView/components/InvertCallStack/index.js +97 -9
  78. package/dist/ProfileView/components/ProfileFilters/filterPresets.js +260 -315
  79. package/dist/ProfileView/components/ProfileFilters/index.js +518 -215
  80. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +370 -306
  81. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +191 -118
  82. package/dist/ProfileView/components/ProfileHeader/index.js +105 -11
  83. package/dist/ProfileView/components/ShareButton/ResultBox.js +119 -16
  84. package/dist/ProfileView/components/ShareButton/index.js +352 -62
  85. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
  86. package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +664 -192
  87. package/dist/ProfileView/components/Toolbars/SwitchMenuItem.js +94 -7
  88. package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +196 -155
  89. package/dist/ProfileView/components/Toolbars/index.js +441 -21
  90. package/dist/ProfileView/components/ViewSelector/Dropdown.js +233 -22
  91. package/dist/ProfileView/components/ViewSelector/index.js +186 -82
  92. package/dist/ProfileView/components/VisualizationContainer/index.d.ts.map +1 -1
  93. package/dist/ProfileView/components/VisualizationContainer/index.js +52 -7
  94. package/dist/ProfileView/components/VisualizationPanel.js +185 -8
  95. package/dist/ProfileView/context/DashboardContext.js +74 -26
  96. package/dist/ProfileView/context/ProfileViewContext.js +56 -15
  97. package/dist/ProfileView/hooks/useAutoSelectDimension.js +71 -41
  98. package/dist/ProfileView/hooks/useProfileMetadata.js +50 -18
  99. package/dist/ProfileView/hooks/useResetFlameGraphState.js +31 -10
  100. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +71 -27
  101. package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +53 -17
  102. package/dist/ProfileView/hooks/useVisualizationState.js +229 -69
  103. package/dist/ProfileView/index.js +383 -45
  104. package/dist/ProfileView/types/visualization.js +1 -13
  105. package/dist/ProfileView/utils/colorUtils.js +8 -7
  106. package/dist/ProfileViewWithData.js +319 -225
  107. package/dist/QueryControls/index.js +418 -47
  108. package/dist/Sandwich/components/CalleesSection.js +54 -4
  109. package/dist/Sandwich/components/CallersSection.js +97 -27
  110. package/dist/Sandwich/components/TableSection.js +77 -4
  111. package/dist/Sandwich/index.js +125 -12
  112. package/dist/Sandwich/utils/processRowData.js +48 -39
  113. package/dist/SelectWithRefresh/index.js +102 -28
  114. package/dist/SimpleMatchers/Select.js +520 -187
  115. package/dist/SimpleMatchers/index.js +590 -288
  116. package/dist/SourceView/Highlighter.js +230 -70
  117. package/dist/SourceView/LineNo.js +72 -17
  118. package/dist/SourceView/index.js +177 -101
  119. package/dist/SourceView/lang-detector/ext-to-lang.json +798 -798
  120. package/dist/SourceView/lang-detector/index.js +28 -14
  121. package/dist/SourceView/useSelectedLineRange.js +72 -20
  122. package/dist/Table/ColorCell.js +42 -1
  123. package/dist/Table/ColumnsVisibility.js +114 -6
  124. package/dist/Table/MoreDropdown.js +107 -21
  125. package/dist/Table/TableContextMenu.js +144 -134
  126. package/dist/Table/TableContextMenuWrapper.js +59 -14
  127. package/dist/Table/hooks/useColorManagement.js +58 -16
  128. package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
  129. package/dist/Table/hooks/useTableConfiguration.js +323 -167
  130. package/dist/Table/index.js +217 -123
  131. package/dist/Table/utils/functions.js +169 -144
  132. package/dist/Table/utils/topAndBottomExpandedRowModel.js +69 -52
  133. package/dist/TimelineGuide/index.js +209 -16
  134. package/dist/TopTable/benchmarks/benchdata/populateData.js +91 -0
  135. package/dist/TopTable/index.js +325 -121
  136. package/dist/contexts/LabelsQueryProvider.js +94 -32
  137. package/dist/contexts/UnifiedLabelsContext.js +114 -49
  138. package/dist/contexts/utils.js +37 -15
  139. package/dist/hooks/urlParsers.js +27 -15
  140. package/dist/hooks/useColorBy.js +47 -10
  141. package/dist/hooks/useCompareModeMeta.js +112 -62
  142. package/dist/hooks/useDashboardItems.js +52 -11
  143. package/dist/hooks/useLabels.js +295 -52
  144. package/dist/hooks/useQueryState.d.ts +1 -1
  145. package/dist/hooks/useQueryState.d.ts.map +1 -1
  146. package/dist/hooks/useQueryState.js +375 -329
  147. package/dist/index.js +11 -6
  148. package/dist/testdata/fg-diff.json +3750 -0
  149. package/dist/testdata/fg-simple.json +1879 -0
  150. package/dist/testdata/link_data.json +56 -0
  151. package/dist/testdata/tabular.json +30 -0
  152. package/dist/testdata/test_flamegraph.json +26846 -0
  153. package/dist/testdata/test_graph.json +53 -0
  154. package/dist/useDelayedLoader.js +32 -18
  155. package/dist/useGrpcQuery/index.js +71 -11
  156. package/dist/useHasProfileData.js +90 -12
  157. package/dist/useQuery.js +205 -64
  158. package/dist/useSumBy.d.ts.map +1 -1
  159. package/dist/useSumBy.js +294 -138
  160. package/dist/utils.js +62 -30
  161. package/package.json +9 -9
  162. package/src/GraphTooltipArrow/index.tsx +3 -0
  163. package/src/MatchersInput/SuggestionsList.test.tsx +70 -0
  164. package/src/MatchersInput/SuggestionsList.tsx +11 -10
  165. package/src/MatchersInput/index.tsx +1 -1
  166. package/src/MetricsGraph/MetricsTooltip/index.tsx +22 -34
  167. package/src/PreSelectedMatchers/index.tsx +3 -0
  168. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +9 -2
  169. package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +3 -0
  170. package/src/ProfileFlameGraph/FlameGraphArrow/TooltipContext.tsx +3 -0
  171. package/src/ProfileFlameGraph/FlameGraphArrow/ZoomControls.tsx +3 -0
  172. package/src/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.ts +3 -0
  173. package/src/ProfileSelector/index.tsx +31 -9
  174. package/src/ProfileSelector/useAutoQuerySelector.ts +64 -42
  175. package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +3 -0
  176. package/src/ProfileView/components/VisualizationContainer/index.tsx +3 -0
  177. package/src/Table/hooks/useTableConfiguration.tsx +7 -13
  178. package/src/hooks/useQueryState.ts +18 -3
  179. package/src/useDelayedLoader.ts +10 -10
  180. package/src/useSumBy.ts +12 -18
  181. package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.js +0 -455
  182. package/dist/hooks/useQueryState.test.js +0 -868
@@ -1,3 +1,7 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
+ import { c as _c } from "react-compiler-runtime";
1
5
  // Copyright 2022 The Parca Authors
2
6
  // Licensed under the Apache License, Version 2.0 (the "License");
3
7
  // you may not use this file except in compliance with the License.
@@ -10,33 +14,62 @@
10
14
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
15
  // See the License for the specific language governing permissions and
12
16
  // limitations under the License.
17
+
13
18
  import { useMemo, useRef } from 'react';
14
19
  import { RowHeight } from './FlameGraphNodes';
15
20
  import { FIELD_CUMULATIVE, FIELD_DEPTH, FIELD_VALUE_OFFSET } from './index';
16
21
  import { getMaxDepth } from './utils';
22
+
17
23
  /**
18
24
  * This function groups rows by their depth level.
19
25
  * Instead of scanning all rows to find depth matches, we pre-compute
20
26
  * buckets so viewport rendering only examines depth ranges that are relevant.
21
27
  */
22
- const useDepthBuckets = (table) => {
23
- return useMemo(() => {
24
- if (table === undefined)
25
- return [];
26
- const depthColumn = table.getChild(FIELD_DEPTH);
27
- if (depthColumn === null)
28
- return [];
29
- // Find max depth
30
- const maxDepth = getMaxDepth(depthColumn);
31
- // Create buckets for each depth level
32
- const buckets = Array.from({ length: maxDepth + 1 }, () => []);
33
- // Populate buckets with row indices
34
- for (let row = 0; row < table.numRows; row++) {
35
- const depth = depthColumn.get(row) ?? 0;
36
- buckets[depth].push(row);
28
+ var useDepthBuckets = function useDepthBuckets(table) {
29
+ var $ = _c(4);
30
+ var t0;
31
+ if ($[0] !== table) {
32
+ bb0: {
33
+ if (table === undefined) {
34
+ var t1;
35
+ if ($[2] === Symbol["for"]("react.memo_cache_sentinel")) {
36
+ t1 = [];
37
+ $[2] = t1;
38
+ } else {
39
+ t1 = $[2];
37
40
  }
38
- return buckets;
39
- }, [table]);
41
+ t0 = t1;
42
+ break bb0;
43
+ }
44
+ var depthColumn = table.getChild(FIELD_DEPTH);
45
+ if (depthColumn === null) {
46
+ var _t;
47
+ if ($[3] === Symbol["for"]("react.memo_cache_sentinel")) {
48
+ _t = [];
49
+ $[3] = _t;
50
+ } else {
51
+ _t = $[3];
52
+ }
53
+ t0 = _t;
54
+ break bb0;
55
+ }
56
+ var maxDepth = getMaxDepth(depthColumn);
57
+ var buckets = Array.from({
58
+ length: maxDepth + 1
59
+ }, _temp);
60
+ for (var row = 0; row < table.numRows; row++) {
61
+ var _depthColumn$get;
62
+ var depth = (_depthColumn$get = depthColumn.get(row)) !== null && _depthColumn$get !== void 0 ? _depthColumn$get : 0;
63
+ buckets[depth].push(row);
64
+ }
65
+ t0 = buckets;
66
+ }
67
+ $[0] = table;
68
+ $[1] = t0;
69
+ } else {
70
+ t0 = $[1];
71
+ }
72
+ return t0;
40
73
  };
41
74
  /**
42
75
  * useVisibleNodes returns row indices visible in the current viewport through multi-stage culling.
@@ -50,88 +83,117 @@ const useDepthBuckets = (table) => {
50
83
  * Critical for maintaining 60fps performance on large flamegraphs where
51
84
  * rendering all nodes would freeze the browser.
52
85
  */
53
- export const useVisibleNodes = ({ table, viewport, total, width, selectedRow, effectiveDepth, }) => {
54
- const depthBuckets = useDepthBuckets(table);
55
- const lastResultRef = useRef({ key: '', result: [] });
56
- const renderedRangeRef = useRef({
86
+ export var useVisibleNodes = function useVisibleNodes(_ref) {
87
+ var table = _ref.table,
88
+ viewport = _ref.viewport,
89
+ total = _ref.total,
90
+ width = _ref.width,
91
+ selectedRow = _ref.selectedRow,
92
+ effectiveDepth = _ref.effectiveDepth;
93
+ var depthBuckets = useDepthBuckets(table);
94
+ var lastResultRef = useRef({
95
+ key: '',
96
+ result: []
97
+ });
98
+ var renderedRangeRef = useRef({
99
+ minDepth: Infinity,
100
+ maxDepth: -Infinity,
101
+ table: null
102
+ });
103
+ return useMemo(function () {
104
+ // This happens when the continer is scrolled off screen, in this case we return all previously rendered nodes
105
+ // to avoid trimming the rendered nodes to zero which would cause jank when scrolling back into view
106
+ if (viewport.containerHeight === 0 && lastResultRef.current.result.length > 0) {
107
+ return lastResultRef.current.result;
108
+ }
109
+
110
+ // Create a stable key for memoization to prevent unnecessary recalculations
111
+ var memoKey = "".concat(viewport.scrollTop, "-").concat(viewport.containerHeight, "-").concat(selectedRow, "-").concat(effectiveDepth, "-").concat(width, "-").concat(Number(total), "-").concat(table.numRows);
112
+
113
+ // Return cached result if viewport hasn't meaningfully changed
114
+ if (lastResultRef.current.key === memoKey) {
115
+ return lastResultRef.current.result;
116
+ }
117
+ if (table === null) return [];
118
+ var visibleRows = [];
119
+ var scrollTop = viewport.scrollTop,
120
+ containerHeight = viewport.containerHeight;
121
+
122
+ // Viewport Culling Algorithm:
123
+ // 1. Calculate visible depth range based on scroll position and container height
124
+ // 2. Add 5-row buffer above/below for smooth scrolling experience
125
+ // Note: We never shrink the rendered range to avoid back and forth node removals (and in turn additions when scrolled down again) to the dom.
126
+
127
+ var BUFFER = 15; // Buffer for smoother scrolling
128
+
129
+ var visibleStartDepth = Math.max(0, Math.floor(scrollTop / RowHeight) - BUFFER);
130
+ var visibleDepths = Math.ceil(containerHeight / RowHeight);
131
+ var visibleEndDepth = Math.min(effectiveDepth, visibleStartDepth + visibleDepths + BUFFER);
132
+
133
+ // Reset range if table changed (new data loaded) as this is new data
134
+ if (renderedRangeRef.current.table !== table) {
135
+ renderedRangeRef.current = {
57
136
  minDepth: Infinity,
58
137
  maxDepth: -Infinity,
59
- table: null,
60
- });
61
- return useMemo(() => {
62
- // This happens when the continer is scrolled off screen, in this case we return all previously rendered nodes
63
- // to avoid trimming the rendered nodes to zero which would cause jank when scrolling back into view
64
- if (viewport.containerHeight === 0 && lastResultRef.current.result.length > 0) {
65
- return lastResultRef.current.result;
66
- }
67
- // Create a stable key for memoization to prevent unnecessary recalculations
68
- const memoKey = `${viewport.scrollTop}-${viewport.containerHeight}-${selectedRow}-${effectiveDepth}-${width}-${Number(total)}-${table.numRows}`;
69
- // Return cached result if viewport hasn't meaningfully changed
70
- if (lastResultRef.current.key === memoKey) {
71
- return lastResultRef.current.result;
72
- }
73
- if (table === null)
74
- return [];
75
- const visibleRows = [];
76
- const { scrollTop, containerHeight } = viewport;
77
- // Viewport Culling Algorithm:
78
- // 1. Calculate visible depth range based on scroll position and container height
79
- // 2. Add 5-row buffer above/below for smooth scrolling experience
80
- // Note: We never shrink the rendered range to avoid back and forth node removals (and in turn additions when scrolled down again) to the dom.
81
- const BUFFER = 15; // Buffer for smoother scrolling
82
- const visibleStartDepth = Math.max(0, Math.floor(scrollTop / RowHeight) - BUFFER);
83
- const visibleDepths = Math.ceil(containerHeight / RowHeight);
84
- const visibleEndDepth = Math.min(effectiveDepth, visibleStartDepth + visibleDepths + BUFFER);
85
- // Reset range if table changed (new data loaded) as this is new data
86
- if (renderedRangeRef.current.table !== table) {
87
- renderedRangeRef.current = {
88
- minDepth: Infinity,
89
- maxDepth: -Infinity,
90
- table,
91
- };
92
- }
93
- // Expand the rendered range (never shrink when scrolling up/down)
94
- renderedRangeRef.current.minDepth = Math.min(renderedRangeRef.current.minDepth, visibleStartDepth);
95
- renderedRangeRef.current.maxDepth = Math.max(renderedRangeRef.current.maxDepth, visibleEndDepth);
96
- const startDepth = renderedRangeRef.current.minDepth;
97
- const endDepth = renderedRangeRef.current.maxDepth;
98
- const cumulativeColumn = table.getChild(FIELD_CUMULATIVE);
99
- const valueOffsetColumn = table.getChild(FIELD_VALUE_OFFSET);
100
- const selectionOffset = valueOffsetColumn?.get(selectedRow) !== null &&
101
- valueOffsetColumn?.get(selectedRow) !== undefined
102
- ? BigInt(valueOffsetColumn?.get(selectedRow))
103
- : 0n;
104
- const selectionCumulative = cumulativeColumn?.get(selectedRow) != null ? BigInt(cumulativeColumn?.get(selectedRow)) : 0n;
105
- const totalNumber = Number(total);
106
- const selectionOffsetNumber = Number(selectionOffset);
107
- const selectionCumulativeNumber = Number(selectionCumulative);
108
- // Iterate only through visible depth range instead of all rows
109
- for (let depth = startDepth; depth <= endDepth && depth < depthBuckets.length; depth++) {
110
- // Skip if depth is beyond effective depth limit
111
- if (effectiveDepth !== undefined && depth > effectiveDepth) {
112
- continue;
113
- }
114
- const rowsAtDepth = depthBuckets[depth];
115
- for (const row of rowsAtDepth) {
116
- const cumulative = cumulativeColumn?.get(row) != null ? Number(cumulativeColumn?.get(row)) : 0;
117
- const valueOffset = valueOffsetColumn?.get(row) !== null && valueOffsetColumn?.get(row) !== undefined
118
- ? Number(valueOffsetColumn?.get(row))
119
- : 0;
120
- // Horizontal culling: Skip nodes outside selection bounds
121
- if (valueOffset + cumulative <= selectionOffsetNumber ||
122
- valueOffset >= selectionOffsetNumber + selectionCumulativeNumber) {
123
- continue;
124
- }
125
- // Size culling: Skip nodes too small to be visible (< 1px width)
126
- const computedWidth = (cumulative / totalNumber) * width;
127
- if (computedWidth <= 1) {
128
- continue;
129
- }
130
- visibleRows.push(row);
131
- }
138
+ table: table
139
+ };
140
+ }
141
+
142
+ // Expand the rendered range (never shrink when scrolling up/down)
143
+ renderedRangeRef.current.minDepth = Math.min(renderedRangeRef.current.minDepth, visibleStartDepth);
144
+ renderedRangeRef.current.maxDepth = Math.max(renderedRangeRef.current.maxDepth, visibleEndDepth);
145
+ var startDepth = renderedRangeRef.current.minDepth;
146
+ var endDepth = renderedRangeRef.current.maxDepth;
147
+ var cumulativeColumn = table.getChild(FIELD_CUMULATIVE);
148
+ var valueOffsetColumn = table.getChild(FIELD_VALUE_OFFSET);
149
+ var selectionOffset = (valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(selectedRow)) !== null && (valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(selectedRow)) !== undefined ? BigInt(valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(selectedRow)) : 0n;
150
+ var selectionCumulative = (cumulativeColumn === null || cumulativeColumn === void 0 ? void 0 : cumulativeColumn.get(selectedRow)) != null ? BigInt(cumulativeColumn === null || cumulativeColumn === void 0 ? void 0 : cumulativeColumn.get(selectedRow)) : 0n;
151
+ var totalNumber = Number(total);
152
+ var selectionOffsetNumber = Number(selectionOffset);
153
+ var selectionCumulativeNumber = Number(selectionCumulative);
154
+
155
+ // Iterate only through visible depth range instead of all rows
156
+ for (var depth = startDepth; depth <= endDepth && depth < depthBuckets.length; depth++) {
157
+ // Skip if depth is beyond effective depth limit
158
+ if (effectiveDepth !== undefined && depth > effectiveDepth) {
159
+ continue;
160
+ }
161
+ var rowsAtDepth = depthBuckets[depth];
162
+ var _iterator = _createForOfIteratorHelper(rowsAtDepth),
163
+ _step;
164
+ try {
165
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
166
+ var row = _step.value;
167
+ var cumulative = (cumulativeColumn === null || cumulativeColumn === void 0 ? void 0 : cumulativeColumn.get(row)) != null ? Number(cumulativeColumn === null || cumulativeColumn === void 0 ? void 0 : cumulativeColumn.get(row)) : 0;
168
+ var valueOffset = (valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(row)) !== null && (valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(row)) !== undefined ? Number(valueOffsetColumn === null || valueOffsetColumn === void 0 ? void 0 : valueOffsetColumn.get(row)) : 0;
169
+
170
+ // Horizontal culling: Skip nodes outside selection bounds
171
+ if (valueOffset + cumulative <= selectionOffsetNumber || valueOffset >= selectionOffsetNumber + selectionCumulativeNumber) {
172
+ continue;
173
+ }
174
+
175
+ // Size culling: Skip nodes too small to be visible (< 1px width)
176
+ var computedWidth = cumulative / totalNumber * width;
177
+ if (computedWidth <= 1) {
178
+ continue;
179
+ }
180
+ visibleRows.push(row);
132
181
  }
133
- // Cache the result with the current key
134
- lastResultRef.current = { key: memoKey, result: visibleRows };
135
- return visibleRows;
136
- }, [depthBuckets, viewport, total, width, selectedRow, effectiveDepth, table]);
182
+ } catch (err) {
183
+ _iterator.e(err);
184
+ } finally {
185
+ _iterator.f();
186
+ }
187
+ }
188
+
189
+ // Cache the result with the current key
190
+ lastResultRef.current = {
191
+ key: memoKey,
192
+ result: visibleRows
193
+ };
194
+ return visibleRows;
195
+ }, [depthBuckets, viewport, total, width, selectedRow, effectiveDepth, table]);
137
196
  };
197
+ function _temp() {
198
+ return [];
199
+ }
@@ -1,3 +1,10 @@
1
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
7
+ import { c as _c } from "react-compiler-runtime";
1
8
  // Copyright 2022 The Parca Authors
2
9
  // Licensed under the Apache License, Version 2.0 (the "License");
3
10
  // you may not use this file except in compliance with the License.
@@ -10,120 +17,233 @@
10
17
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
18
  // See the License for the specific language governing permissions and
12
19
  // limitations under the License.
20
+
13
21
  import { useCallback, useEffect, useRef, useState } from 'react';
14
22
  import { flushSync } from 'react-dom';
15
- const MIN_ZOOM = 1.0;
16
- export const MAX_ZOOM = 100.0;
17
- const BUTTON_ZOOM_STEP = 1.5;
23
+ var MIN_ZOOM = 1.0;
24
+ export var MAX_ZOOM = 100.0;
25
+ var BUTTON_ZOOM_STEP = 1.5;
18
26
  // Sensitivity for trackpad/wheel zoom - smaller = smoother
19
- const WHEEL_ZOOM_SENSITIVITY = 0.01;
20
- const clampZoom = (zoom) => {
21
- return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));
27
+ var WHEEL_ZOOM_SENSITIVITY = 0.01;
28
+ var clampZoom = function clampZoom(zoom) {
29
+ return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));
22
30
  };
23
- export const useZoom = (containerRef) => {
24
- const [zoomLevel, setZoomLevel] = useState(MIN_ZOOM);
25
- const zoomLevelRef = useRef(MIN_ZOOM);
26
- const scrollLeftRef = useRef(0);
27
- // Keep scrollLeftRef in sync with actual scroll position during regular scrolling
28
- useEffect(() => {
29
- const container = containerRef.current;
30
- if (container === null)
31
- return;
32
- const onScroll = () => {
33
- scrollLeftRef.current = container.scrollLeft;
34
- };
35
- container.addEventListener('scroll', onScroll, { passive: true });
36
- return () => container.removeEventListener('scroll', onScroll);
37
- }, [containerRef]);
38
- // Apply a new zoom level around a focal point
39
- const applyZoom = useCallback((newZoom, focalX) => {
40
- const container = containerRef.current;
41
- if (container === null)
42
- return;
43
- const oldZoom = zoomLevelRef.current;
44
- if (newZoom === oldZoom)
45
- return;
46
- // Pre-compute intended scrollLeft BEFORE flushSync so MiniMap reads correct value during render
47
- const contentX = container.scrollLeft + focalX;
48
- const ratio = contentX / oldZoom;
49
- const newScrollLeft = ratio * newZoom - focalX;
50
- scrollLeftRef.current = newScrollLeft;
51
- zoomLevelRef.current = newZoom;
52
- flushSync(() => setZoomLevel(newZoom));
53
- // Apply scroll to DOM after render (content is now wide enough)
54
- container.scrollLeft = newScrollLeft;
55
- }, [containerRef]);
56
- const zoomIn = useCallback(() => {
57
- const newZoom = clampZoom(zoomLevelRef.current * BUTTON_ZOOM_STEP);
58
- const container = containerRef.current;
59
- applyZoom(newZoom, container !== null ? container.clientWidth / 2 : 0);
60
- }, [containerRef, applyZoom]);
61
- const zoomOut = useCallback(() => {
62
- const newZoom = clampZoom(zoomLevelRef.current / BUTTON_ZOOM_STEP);
63
- const container = containerRef.current;
64
- applyZoom(newZoom, container !== null ? container.clientWidth / 2 : 0);
65
- }, [containerRef, applyZoom]);
66
- const resetZoom = useCallback(() => {
67
- zoomLevelRef.current = MIN_ZOOM;
68
- scrollLeftRef.current = 0;
69
- setZoomLevel(MIN_ZOOM);
70
- const container = containerRef.current;
71
- if (container !== null) {
72
- container.scrollLeft = 0;
31
+ export var useZoom = function useZoom(containerRef) {
32
+ var $ = _c(28);
33
+ var _useState = useState(MIN_ZOOM),
34
+ _useState2 = _slicedToArray(_useState, 2),
35
+ zoomLevel = _useState2[0],
36
+ setZoomLevel = _useState2[1];
37
+ var zoomLevelRef = useRef(MIN_ZOOM);
38
+ var scrollLeftRef = useRef(0);
39
+ var t0;
40
+ var t1;
41
+ if ($[0] !== containerRef) {
42
+ t0 = function t0() {
43
+ var container = containerRef.current;
44
+ if (container === null) {
45
+ return;
46
+ }
47
+ var onScroll = function onScroll() {
48
+ scrollLeftRef.current = container.scrollLeft;
49
+ };
50
+ container.addEventListener("scroll", onScroll, {
51
+ passive: true
52
+ });
53
+ return function () {
54
+ return container.removeEventListener("scroll", onScroll);
55
+ };
56
+ };
57
+ t1 = [containerRef];
58
+ $[0] = containerRef;
59
+ $[1] = t0;
60
+ $[2] = t1;
61
+ } else {
62
+ t0 = $[1];
63
+ t1 = $[2];
64
+ }
65
+ useEffect(t0, t1);
66
+ var t2;
67
+ if ($[3] !== containerRef) {
68
+ t2 = function t2(newZoom, focalX) {
69
+ var container_0 = containerRef.current;
70
+ if (container_0 === null) {
71
+ return;
72
+ }
73
+ var oldZoom = zoomLevelRef.current;
74
+ if (newZoom === oldZoom) {
75
+ return;
76
+ }
77
+ var contentX = container_0.scrollLeft + focalX;
78
+ var ratio = contentX / oldZoom;
79
+ var newScrollLeft = ratio * newZoom - focalX;
80
+ scrollLeftRef.current = newScrollLeft;
81
+ zoomLevelRef.current = newZoom;
82
+ flushSync(function () {
83
+ return setZoomLevel(newZoom);
84
+ });
85
+ container_0.scrollLeft = newScrollLeft;
86
+ };
87
+ $[3] = containerRef;
88
+ $[4] = t2;
89
+ } else {
90
+ t2 = $[4];
91
+ }
92
+ var applyZoom = t2;
93
+ var t3;
94
+ if ($[5] !== applyZoom || $[6] !== containerRef) {
95
+ t3 = function t3() {
96
+ var newZoom_0 = clampZoom(zoomLevelRef.current * BUTTON_ZOOM_STEP);
97
+ var container_1 = containerRef.current;
98
+ applyZoom(newZoom_0, container_1 !== null ? container_1.clientWidth / 2 : 0);
99
+ };
100
+ $[5] = applyZoom;
101
+ $[6] = containerRef;
102
+ $[7] = t3;
103
+ } else {
104
+ t3 = $[7];
105
+ }
106
+ var zoomIn = t3;
107
+ var t4;
108
+ if ($[8] !== applyZoom || $[9] !== containerRef) {
109
+ t4 = function t4() {
110
+ var newZoom_1 = clampZoom(zoomLevelRef.current / BUTTON_ZOOM_STEP);
111
+ var container_2 = containerRef.current;
112
+ applyZoom(newZoom_1, container_2 !== null ? container_2.clientWidth / 2 : 0);
113
+ };
114
+ $[8] = applyZoom;
115
+ $[9] = containerRef;
116
+ $[10] = t4;
117
+ } else {
118
+ t4 = $[10];
119
+ }
120
+ var zoomOut = t4;
121
+ var t5;
122
+ if ($[11] !== containerRef) {
123
+ t5 = function t5() {
124
+ zoomLevelRef.current = MIN_ZOOM;
125
+ scrollLeftRef.current = 0;
126
+ setZoomLevel(MIN_ZOOM);
127
+ var container_3 = containerRef.current;
128
+ if (container_3 !== null) {
129
+ container_3.scrollLeft = 0;
130
+ }
131
+ };
132
+ $[11] = containerRef;
133
+ $[12] = t5;
134
+ } else {
135
+ t5 = $[12];
136
+ }
137
+ var resetZoom = t5;
138
+ var t6;
139
+ var t7;
140
+ if ($[13] !== applyZoom || $[14] !== containerRef) {
141
+ t6 = function t6() {
142
+ var container_4 = containerRef.current;
143
+ if (container_4 === null) {
144
+ return;
145
+ }
146
+ var handleWheel = function handleWheel(e) {
147
+ if (!e.ctrlKey && !e.metaKey) {
148
+ return;
73
149
  }
74
- }, [containerRef]);
75
- useEffect(() => {
76
- const container = containerRef.current;
77
- if (container === null)
78
- return;
79
- const handleWheel = (e) => {
80
- if (!e.ctrlKey && !e.metaKey)
81
- return;
82
- e.preventDefault();
83
- let delta = e.deltaY;
84
- if (e.deltaMode === 1) {
85
- delta *= 20;
86
- }
87
- // Limiting the max zoom step per event to 15%, so to fix the huge jumps in Linux OS.
88
- const MAX_FACTOR = 0.15;
89
- const rawFactor = -delta * WHEEL_ZOOM_SENSITIVITY;
90
- const zoomFactor = 1 + Math.max(-MAX_FACTOR, Math.min(MAX_FACTOR, rawFactor));
91
- const newZoom = clampZoom(zoomLevelRef.current * zoomFactor);
92
- applyZoom(newZoom, e.clientX - container.getBoundingClientRect().left);
93
- };
94
- container.addEventListener('wheel', handleWheel, { passive: false });
95
- return () => {
96
- container.removeEventListener('wheel', handleWheel);
97
- };
98
- }, [containerRef, applyZoom]);
99
- const zoomToPosition = useCallback((normalizedX, targetZoom) => {
100
- const container = containerRef.current;
101
- if (container === null)
102
- return;
103
- const newZoom = clampZoom(targetZoom);
104
- if (newZoom === zoomLevelRef.current)
105
- return;
106
- const containerWidth = container.clientWidth;
107
- const contentWidth = containerWidth * newZoom;
108
- const targetScrollLeft = Math.max(0, Math.min(normalizedX * contentWidth - containerWidth / 2, contentWidth - containerWidth));
109
- // Pre-set scrollLeftRef before flushSync so MiniMap reads correct value during render
110
- scrollLeftRef.current = targetScrollLeft;
111
- zoomLevelRef.current = newZoom;
112
- flushSync(() => setZoomLevel(newZoom));
113
- container.scrollLeft = targetScrollLeft;
114
- }, [containerRef]);
115
- const setZoomWithScroll = useCallback((zoom, newScrollLeft) => {
116
- const container = containerRef.current;
117
- if (container === null)
118
- return;
119
- const clamped = clampZoom(zoom);
120
- const contentWidth = container.clientWidth * clamped;
121
- const clampedScroll = Math.max(0, Math.min(newScrollLeft, contentWidth - container.clientWidth));
122
- // Pre-set scrollLeftRef before flushSync so MiniMap reads correct value during render
123
- scrollLeftRef.current = clampedScroll;
124
- zoomLevelRef.current = clamped;
125
- flushSync(() => setZoomLevel(clamped));
126
- container.scrollLeft = clampedScroll;
127
- }, [containerRef]);
128
- return { zoomLevel, zoomIn, zoomOut, resetZoom, zoomToPosition, setZoomWithScroll, scrollLeftRef };
129
- };
150
+ e.preventDefault();
151
+ var delta = e.deltaY;
152
+ if (e.deltaMode === 1) {
153
+ delta = delta * 20;
154
+ }
155
+ var rawFactor = -delta * WHEEL_ZOOM_SENSITIVITY;
156
+ var zoomFactor = 1 + Math.max(-0.15, Math.min(0.15, rawFactor));
157
+ var newZoom_2 = clampZoom(zoomLevelRef.current * zoomFactor);
158
+ applyZoom(newZoom_2, e.clientX - container_4.getBoundingClientRect().left);
159
+ };
160
+ container_4.addEventListener("wheel", handleWheel, {
161
+ passive: false
162
+ });
163
+ return function () {
164
+ container_4.removeEventListener("wheel", handleWheel);
165
+ };
166
+ };
167
+ t7 = [containerRef, applyZoom];
168
+ $[13] = applyZoom;
169
+ $[14] = containerRef;
170
+ $[15] = t6;
171
+ $[16] = t7;
172
+ } else {
173
+ t6 = $[15];
174
+ t7 = $[16];
175
+ }
176
+ useEffect(t6, t7);
177
+ var t8;
178
+ if ($[17] !== containerRef) {
179
+ t8 = function t8(normalizedX, targetZoom) {
180
+ var container_5 = containerRef.current;
181
+ if (container_5 === null) {
182
+ return;
183
+ }
184
+ var newZoom_3 = clampZoom(targetZoom);
185
+ if (newZoom_3 === zoomLevelRef.current) {
186
+ return;
187
+ }
188
+ var containerWidth = container_5.clientWidth;
189
+ var contentWidth = containerWidth * newZoom_3;
190
+ var targetScrollLeft = Math.max(0, Math.min(normalizedX * contentWidth - containerWidth / 2, contentWidth - containerWidth));
191
+ scrollLeftRef.current = targetScrollLeft;
192
+ zoomLevelRef.current = newZoom_3;
193
+ flushSync(function () {
194
+ return setZoomLevel(newZoom_3);
195
+ });
196
+ container_5.scrollLeft = targetScrollLeft;
197
+ };
198
+ $[17] = containerRef;
199
+ $[18] = t8;
200
+ } else {
201
+ t8 = $[18];
202
+ }
203
+ var zoomToPosition = t8;
204
+ var t9;
205
+ if ($[19] !== containerRef) {
206
+ t9 = function t9(zoom, newScrollLeft_0) {
207
+ var container_6 = containerRef.current;
208
+ if (container_6 === null) {
209
+ return;
210
+ }
211
+ var clamped = clampZoom(zoom);
212
+ var contentWidth_0 = container_6.clientWidth * clamped;
213
+ var clampedScroll = Math.max(0, Math.min(newScrollLeft_0, contentWidth_0 - container_6.clientWidth));
214
+ scrollLeftRef.current = clampedScroll;
215
+ zoomLevelRef.current = clamped;
216
+ flushSync(function () {
217
+ return setZoomLevel(clamped);
218
+ });
219
+ container_6.scrollLeft = clampedScroll;
220
+ };
221
+ $[19] = containerRef;
222
+ $[20] = t9;
223
+ } else {
224
+ t9 = $[20];
225
+ }
226
+ var setZoomWithScroll = t9;
227
+ var t10;
228
+ if ($[21] !== resetZoom || $[22] !== setZoomWithScroll || $[23] !== zoomIn || $[24] !== zoomLevel || $[25] !== zoomOut || $[26] !== zoomToPosition) {
229
+ t10 = {
230
+ zoomLevel: zoomLevel,
231
+ zoomIn: zoomIn,
232
+ zoomOut: zoomOut,
233
+ resetZoom: resetZoom,
234
+ zoomToPosition: zoomToPosition,
235
+ setZoomWithScroll: setZoomWithScroll,
236
+ scrollLeftRef: scrollLeftRef
237
+ };
238
+ $[21] = resetZoom;
239
+ $[22] = setZoomWithScroll;
240
+ $[23] = zoomIn;
241
+ $[24] = zoomLevel;
242
+ $[25] = zoomOut;
243
+ $[26] = zoomToPosition;
244
+ $[27] = t10;
245
+ } else {
246
+ t10 = $[27];
247
+ }
248
+ return t10;
249
+ };