@parca/profile 0.16.100 → 0.16.102

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 (49) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/Callgraph/index.d.ts +0 -1
  3. package/dist/GraphTooltip/index.d.ts +2 -3
  4. package/dist/IcicleGraph.d.ts +4 -5
  5. package/dist/IcicleGraph.js +11 -5
  6. package/dist/MatchersInput/SuggestionItem.d.ts +0 -1
  7. package/dist/MatchersInput/SuggestionsList.d.ts +0 -1
  8. package/dist/MatchersInput/index.d.ts +0 -1
  9. package/dist/MetricsCircle/index.d.ts +0 -1
  10. package/dist/MetricsGraph/index.d.ts +0 -1
  11. package/dist/MetricsSeries/index.d.ts +0 -1
  12. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +0 -1
  13. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +0 -1
  14. package/dist/ProfileExplorer/index.d.ts +0 -1
  15. package/dist/ProfileIcicleGraph/index.d.ts +0 -1
  16. package/dist/ProfileMetricsGraph/index.d.ts +0 -1
  17. package/dist/ProfileSelector/CompareButton.d.ts +0 -1
  18. package/dist/ProfileSelector/MergeButton.d.ts +0 -1
  19. package/dist/ProfileSelector/index.d.ts +0 -1
  20. package/dist/ProfileSource.d.ts +0 -1
  21. package/dist/ProfileSource.js +12 -0
  22. package/dist/ProfileTypeSelector/index.d.ts +0 -1
  23. package/dist/ProfileView/FilterByFunctionButton.d.ts +0 -1
  24. package/dist/ProfileView/ViewSelector.d.ts +0 -1
  25. package/dist/ProfileView/index.d.ts +0 -1
  26. package/dist/ProfileView/index.js +3 -3
  27. package/dist/ProfileViewWithData.d.ts +0 -1
  28. package/dist/TopTable/index.d.ts +0 -1
  29. package/dist/TopTable/index.js +2 -2
  30. package/dist/components/DiffLegend.d.ts +0 -1
  31. package/dist/components/ProfileShareButton/ResultBox.d.ts +0 -1
  32. package/dist/components/ProfileShareButton/index.d.ts +0 -1
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.js +2 -2
  35. package/dist/styles.css +1 -1
  36. package/dist/utils.d.ts +1 -1
  37. package/package.json +5 -5
  38. package/src/Callgraph/index.tsx +1 -1
  39. package/src/GraphTooltip/index.tsx +8 -4
  40. package/src/IcicleGraph.tsx +29 -13
  41. package/src/MetricsGraph/index.tsx +1 -1
  42. package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -1
  43. package/src/ProfileSource.tsx +1 -2
  44. package/src/ProfileTypeSelector/index.tsx +3 -2
  45. package/src/ProfileView/ViewSelector.tsx +2 -1
  46. package/src/ProfileView/index.tsx +7 -9
  47. package/src/TopTable/index.tsx +4 -3
  48. package/src/index.tsx +2 -2
  49. package/src/utils.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.16.102](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.101...@parca/profile@0.16.102) (2023-01-26)
7
+
8
+ ### Bug Fixes
9
+
10
+ - change Reset zoom button text to be Reset view ([0061637](https://github.com/parca-dev/parca/commit/0061637873ca5dc7633a8ee9df7883779cd469d1))
11
+
12
+ ## [0.16.101](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.96...@parca/profile@0.16.101) (2023-01-25)
13
+
14
+ **Note:** Version bump only for package @parca/profile
15
+
6
16
  ## 0.16.100 (2023-01-22)
7
17
 
8
18
  **Note:** Version bump only for package @parca/profile
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Callgraph as CallgraphType } from '@parca/client';
3
2
  export interface Props {
4
3
  graph: CallgraphType;
@@ -1,6 +1,5 @@
1
- /// <reference types="react" />
2
1
  import { CallgraphNode, FlamegraphNode, FlamegraphNodeMeta, FlamegraphRootNode } from '@parca/client';
3
- import { Function, Location, Mapping } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
2
+ import { Function as ParcaFunction, Location, Mapping } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
4
3
  interface GraphTooltipProps {
5
4
  x: number;
6
5
  y: number;
@@ -13,7 +12,7 @@ interface GraphTooltipProps {
13
12
  strings?: string[];
14
13
  mappings?: Mapping[];
15
14
  locations?: Location[];
16
- functions?: Function[];
15
+ functions?: ParcaFunction[];
17
16
  }
18
17
  export interface HoveringNode extends CallgraphNode, FlamegraphRootNode, FlamegraphNode {
19
18
  diff: string;
@@ -1,6 +1,5 @@
1
- /// <reference types="react" />
2
1
  import { Flamegraph, FlamegraphNode, FlamegraphRootNode } from '@parca/client';
3
- import { Mapping, Function, Location } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
2
+ import { Mapping, Function as ParcaFunction, Location } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
4
3
  interface IcicleGraphProps {
5
4
  graph: Flamegraph;
6
5
  sampleUnit: string;
@@ -13,7 +12,7 @@ interface IcicleGraphNodesProps {
13
12
  strings: string[];
14
13
  mappings: Mapping[];
15
14
  locations: Location[];
16
- functions: Function[];
15
+ functions: ParcaFunction[];
17
16
  x: number;
18
17
  y: number;
19
18
  total: number;
@@ -30,7 +29,7 @@ interface IcicleGraphRootNodeProps {
30
29
  strings: string[];
31
30
  mappings: Mapping[];
32
31
  locations: Location[];
33
- functions: Function[];
32
+ functions: ParcaFunction[];
34
33
  xScale: (value: number) => number;
35
34
  total: number;
36
35
  totalWidth: number;
@@ -38,7 +37,7 @@ interface IcicleGraphRootNodeProps {
38
37
  setCurPath: (path: string[]) => void;
39
38
  setHoveringNode: (node: FlamegraphNode | FlamegraphRootNode | undefined) => void;
40
39
  }
41
- export declare function nodeLabel(node: FlamegraphNode, strings: string[], mappings: Mapping[], locations: Location[], functions: Function[]): string;
40
+ export declare function nodeLabel(node: FlamegraphNode, strings: string[], mappings: Mapping[], locations: Location[], functions: ParcaFunction[]): string;
42
41
  export declare function IcicleGraphNodes({ data, strings, mappings, locations, functions, x, y, xScale, total, totalWidth, level, setHoveringNode, path, setCurPath, curPath, }: IcicleGraphNodesProps): JSX.Element;
43
42
  export declare function IcicleGraphRootNode({ node, strings, mappings, locations, functions, xScale, total, totalWidth, setHoveringNode, setCurPath, curPath, }: IcicleGraphRootNodeProps): JSX.Element;
44
43
  export default function IcicleGraph({ graph, width, setCurPath, curPath, sampleUnit, }: IcicleGraphProps): JSX.Element;
@@ -22,7 +22,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
22
22
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
23
  // See the License for the specific language governing permissions and
24
24
  // limitations under the License.
25
- import React, { useEffect, useMemo, useRef, useState } from 'react';
25
+ import { useEffect, useMemo, useRef, useState, memo, Fragment } from 'react';
26
+ import cx from 'classnames';
26
27
  import { throttle } from 'lodash';
27
28
  import { pointer } from 'd3-selection';
28
29
  import { scaleLinear } from 'd3-scale';
@@ -32,6 +33,7 @@ import { selectDarkMode, useAppSelector } from '@parca/store';
32
33
  import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
33
34
  import { Button } from '@parca/components';
34
35
  import { hexifyAddress } from './utils';
36
+ import { useURLState } from '@parca/functions';
35
37
  var RowHeight = 26;
36
38
  var icicleRectStyles = {
37
39
  cursor: 'pointer',
@@ -117,10 +119,10 @@ export function IcicleGraphNodes(_a) {
117
119
  return;
118
120
  setHoveringNode(undefined);
119
121
  };
120
- return (_jsxs(React.Fragment, { children: [_jsx(IcicleRect, { x: xStart, y: 0, width: width, height: RowHeight, name: name, color: color, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, curPath: curPath }, "rect-".concat(key)), data !== undefined && data.length > 0 && (_jsx(IcicleGraphNodes, { data: d.children, strings: strings, mappings: mappings, locations: locations, functions: functions, x: xStart, y: RowHeight, xScale: newXScale, total: total, totalWidth: totalWidth, level: nextLevel, setHoveringNode: setHoveringNode, path: nextPath, curPath: nextCurPath, setCurPath: setCurPath }, "node-".concat(key)))] }, "node-".concat(key)));
122
+ return (_jsxs(Fragment, { children: [_jsx(IcicleRect, { x: xStart, y: 0, width: width, height: RowHeight, name: name, color: color, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, curPath: curPath }, "rect-".concat(key)), data !== undefined && data.length > 0 && (_jsx(IcicleGraphNodes, { data: d.children, strings: strings, mappings: mappings, locations: locations, functions: functions, x: xStart, y: RowHeight, xScale: newXScale, total: total, totalWidth: totalWidth, level: nextLevel, setHoveringNode: setHoveringNode, path: nextPath, curPath: nextCurPath, setCurPath: setCurPath }, "node-".concat(key)))] }, "node-".concat(key)));
121
123
  }) })));
122
124
  }
123
- var MemoizedIcicleGraphNodes = React.memo(IcicleGraphNodes);
125
+ var MemoizedIcicleGraphNodes = memo(IcicleGraphNodes);
124
126
  export function IcicleGraphRootNode(_a) {
125
127
  var node = _a.node, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, xScale = _a.xScale, total = _a.total, totalWidth = _a.totalWidth, setHoveringNode = _a.setHoveringNode, setCurPath = _a.setCurPath, curPath = _a.curPath;
126
128
  var isDarkMode = useAppSelector(selectDarkMode);
@@ -142,7 +144,7 @@ export function IcicleGraphRootNode(_a) {
142
144
  var path = [];
143
145
  return (_jsxs("g", __assign({ transform: 'translate(0, 0)' }, { children: [_jsx(IcicleRect, { x: 0, y: 0, width: totalWidth, height: RowHeight, name: 'root', color: color, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, curPath: curPath }), _jsx(MemoizedIcicleGraphNodes, { data: node.children, strings: strings, mappings: mappings, locations: locations, functions: functions, x: 0, y: RowHeight, xScale: xScale, total: total, totalWidth: totalWidth, level: 0, setHoveringNode: setHoveringNode, path: path, curPath: curPath, setCurPath: setCurPath })] })));
144
146
  }
145
- var MemoizedIcicleGraphRootNode = React.memo(IcicleGraphRootNode);
147
+ var MemoizedIcicleGraphRootNode = memo(IcicleGraphRootNode);
146
148
  export default function IcicleGraph(_a) {
147
149
  var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit;
148
150
  var _b = useState(), hoveringNode = _b[0], setHoveringNode = _b[1];
@@ -150,6 +152,10 @@ export default function IcicleGraph(_a) {
150
152
  var _d = useState(0), height = _d[0], setHeight = _d[1];
151
153
  var svg = useRef(null);
152
154
  var ref = useRef(null);
155
+ var rawDashboardItems = useURLState({
156
+ param: 'dashboard_items',
157
+ })[0];
158
+ var dashboardItems = rawDashboardItems;
153
159
  useEffect(function () {
154
160
  if (ref.current != null) {
155
161
  setHeight(ref === null || ref === void 0 ? void 0 : ref.current.getBoundingClientRect().height);
@@ -171,5 +177,5 @@ export default function IcicleGraph(_a) {
171
177
  var rel = pointer(e);
172
178
  throttledSetPos([rel[0], rel[1]]);
173
179
  };
174
- return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(GraphTooltip, { unit: sampleUnit, total: total, x: pos[0], y: pos[1], hoveringNode: hoveringNode, contextElement: svg.current, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function }), _jsx("div", __assign({ className: "w-full flex justify-start" }, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset zoom" })) })), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, onMouseMove: onMouseMove, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx(MemoizedIcicleGraphRootNode, { node: graph.root, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function, setHoveringNode: setHoveringNode, curPath: curPath, setCurPath: setCurPath, xScale: xScale, total: total, totalWidth: width }) })) }))] })));
180
+ return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); }, className: "relative" }, { children: [_jsx(GraphTooltip, { unit: sampleUnit, total: total, x: pos[0], y: pos[1], hoveringNode: hoveringNode, contextElement: svg.current, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function }), _jsx("div", __assign({ className: cx(dashboardItems.length > 1 ? 'top-[-46px] left-[25px]' : 'top-[-45px]', 'flex justify-start absolute ') }, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset View" })) })), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, onMouseMove: onMouseMove, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx(MemoizedIcicleGraphRootNode, { node: graph.root, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function, setHoveringNode: setHoveringNode, curPath: curPath, setCurPath: setCurPath, xScale: xScale, total: total, totalWidth: width }) })) }))] })));
175
181
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface Props {
3
2
  isHighlighted: boolean;
4
3
  onHighlight: () => void;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  export declare class Suggestion {
3
2
  type: string;
4
3
  typeahead: string;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Query } from '@parca/parser';
3
2
  import { LabelsResponse, QueryServiceClient } from '@parca/client';
4
3
  interface MatchersInputProps {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface MetricsCircleProps {
3
2
  cx: number;
4
3
  cy: number;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { SingleProfileSelection } from '..';
3
2
  import { MetricsSeries as MetricsSeriesPb, Label } from '@parca/client';
4
3
  import { DateTimeRange } from '@parca/components';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import * as d3 from 'd3';
3
2
  interface MetricsSeriesProps {
4
3
  data: any;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { NavigateFunction } from '@parca/functions';
3
2
  import { QueryServiceClient } from '@parca/client';
4
3
  import { ProfileSelection } from '..';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { NavigateFunction } from '@parca/functions';
3
2
  import { QueryServiceClient } from '@parca/client';
4
3
  import { ProfileSelection } from '..';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryServiceClient } from '@parca/client';
3
2
  import { NavigateFunction } from '@parca/functions';
4
3
  interface ProfileExplorerProps {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Flamegraph } from '@parca/client';
3
2
  export type ResizeHandler = (width: number, height: number) => void;
4
3
  interface ProfileIcicleGraphProps {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ProfileSelection } from '..';
3
2
  import { QueryServiceClient, QueryRangeResponse } from '@parca/client';
4
3
  import { RpcError } from '@protobuf-ts/runtime-rpc';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  declare const CompareButton: ({ disabled, onClick, }: {
3
2
  disabled: boolean;
4
3
  onClick: () => void;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  declare const MergeButton: ({ disabled, onClick, }: {
3
2
  disabled: boolean;
4
3
  onClick: () => void;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryServiceClient, ProfileTypesResponse } from '@parca/client';
3
2
  import { RpcError } from '@protobuf-ts/runtime-rpc';
4
3
  import { ProfileSelection } from '..';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ProfileType } from '@parca/parser';
3
2
  import { Label, QueryRequest, ProfileDiffSelection } from '@parca/client';
4
3
  export interface ProfileSource {
@@ -10,6 +10,18 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
13
+ // Copyright 2022 The Parca Authors
14
+ // Licensed under the Apache License, Version 2.0 (the "License");
15
+ // you may not use this file except in compliance with the License.
16
+ // You may obtain a copy of the License at
17
+ //
18
+ // http://www.apache.org/licenses/LICENSE-2.0
19
+ //
20
+ // Unless required by applicable law or agreed to in writing, software
21
+ // distributed under the License is distributed on an "AS IS" BASIS,
22
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ // See the License for the specific language governing permissions and
24
+ // limitations under the License.
13
25
  import { formatDate } from '@parca/functions';
14
26
  import { Query, ProfileType } from '@parca/parser';
15
27
  import { QueryRequest_Mode, QueryRequest_ReportType, ProfileDiffSelection_Mode, Timestamp, } from '@parca/client';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ProfileType, ProfileTypesResponse } from '@parca/client';
3
2
  import { RpcError } from '@protobuf-ts/runtime-rpc';
4
3
  interface WellKnownProfile {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { NavigateFunction } from '@parca/functions';
3
2
  declare const FilterByFunctionButton: ({ navigateTo, }: {
4
3
  navigateTo: NavigateFunction | undefined;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { NavigateFunction } from '@parca/functions';
3
2
  interface Props {
4
3
  position: number;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryServiceClient, Flamegraph, Top, Callgraph as CallgraphType } from '@parca/client';
3
2
  import { ResizeHandler } from '../ProfileIcicleGraph';
4
3
  import { ProfileSource } from '../ProfileSource';
@@ -41,13 +41,13 @@ import { Icon } from '@iconify/react';
41
41
  import { Button, Card, useParcaContext } from '@parca/components';
42
42
  import { useContainerDimensions } from '@parca/dynamicsize';
43
43
  import { useAppSelector, selectDarkMode } from '@parca/store';
44
- import { DragDropContext, Droppable, Draggable, } from 'react-beautiful-dnd';
44
+ import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
45
45
  import { Callgraph } from '../';
46
46
  import ProfileShareButton from '../components/ProfileShareButton';
47
47
  import FilterByFunctionButton from './FilterByFunctionButton';
48
48
  import ViewSelector from './ViewSelector';
49
49
  import ProfileIcicleGraph from '../ProfileIcicleGraph';
50
- import TopTable from '../TopTable';
50
+ import { TopTable } from '../TopTable';
51
51
  import useDelayedLoader from '../useDelayedLoader';
52
52
  import '../ProfileView.styles.css';
53
53
  function arrayEquals(a, b) {
@@ -133,7 +133,7 @@ export var ProfileView = function (_a) {
133
133
  onDownloadPProf();
134
134
  }, disabled: isLoading }, { children: "Download pprof" }))] })), _jsx(FilterByFunctionButton, { navigateTo: navigateTo })] })), _jsx("div", __assign({ className: "flex ml-auto gap-2" }, { children: _jsx(ViewSelector, { defaultValue: "", navigateTo: navigateTo, position: -1, placeholderText: "Add panel...", primary: true, addView: true, disabled: isMultiPanelView || dashboardItems.length < 1 }) }))] })), isLoaderVisible ? (_jsx(_Fragment, { children: loader })) : (_jsx(DragDropContext, __assign({ onDragEnd: onDragEnd }, { children: _jsx("div", __assign({ className: "w-full", ref: ref }, { children: _jsx(Droppable, __assign({ droppableId: "droppable", direction: "horizontal" }, { children: function (provided) { return (_jsx("div", __assign({ ref: provided.innerRef, className: "flex space-x-4 justify-between w-full" }, provided.droppableProps, { children: dashboardItems.map(function (dashboardItem, index) {
135
135
  return (_jsx(Draggable, __assign({ draggableId: dashboardItem, index: index, isDragDisabled: !isMultiPanelView }, { children: function (provided, snapshot) { return (_createElement("div", __assign({ ref: provided.innerRef }, provided.draggableProps, { key: dashboardItem, className: cx('border dark:bg-gray-700 rounded border-gray-300 dark:border-gray-500 p-3', isMultiPanelView ? 'w-1/2' : 'w-full', snapshot.isDragging ? 'bg-gray-200' : 'bg-white') }),
136
- _jsxs("div", __assign({ className: "w-full flex justify-end pb-2" }, { children: [_jsxs("div", __assign({ className: "w-full flex justify-between" }, { children: [_jsx("div", __assign({ className: cx(isMultiPanelView ? 'visible' : 'invisible') }, provided.dragHandleProps, { children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) })), _jsx(ViewSelector, { defaultValue: dashboardItem, navigateTo: navigateTo, position: index })] })), isMultiPanelView && (_jsx("button", __assign({ type: "button", onClick: function () { return handleClosePanel(dashboardItem); }, className: "pl-2" }, { children: _jsx(CloseIcon, {}) })))] })),
136
+ _jsxs("div", __assign({ className: "w-full flex justify-end pb-2" }, { children: [_jsxs("div", __assign({ className: "w-full flex justify-between" }, { children: [_jsx("div", __assign({ className: cx(isMultiPanelView ? 'visible' : 'invisible', 'flex items-center') }, provided.dragHandleProps, { children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) })), _jsx(ViewSelector, { defaultValue: dashboardItem, navigateTo: navigateTo, position: index })] })), isMultiPanelView && (_jsx("button", __assign({ type: "button", onClick: function () { return handleClosePanel(dashboardItem); }, className: "pl-2" }, { children: _jsx(CloseIcon, {}) })))] })),
137
137
  getDashboardItemByType({
138
138
  type: dashboardItem,
139
139
  isHalfScreen: isMultiPanelView,
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryServiceClient } from '@parca/client';
3
2
  import { ProfileSource } from './ProfileSource';
4
3
  import { NavigateFunction } from '@parca/functions';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { NavigateFunction } from '@parca/functions';
3
2
  import { TopNodeMeta, Top } from '@parca/client';
4
3
  import '../TopTable.styles.css';
@@ -22,7 +22,7 @@ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
22
22
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
23
  // See the License for the specific language governing permissions and
24
24
  // limitations under the License.
25
- import React, { useCallback, useMemo } from 'react';
25
+ import { useCallback, useMemo } from 'react';
26
26
  import { getLastItem, valueFormatter, isSearchMatch, parseParams, selectQueryParam, } from '@parca/functions';
27
27
  import { Table } from '@parca/components';
28
28
  import { createColumnHelper } from '@tanstack/react-table';
@@ -54,7 +54,7 @@ export var TopTable = function (_a) {
54
54
  var router = parseParams(window.location.search);
55
55
  var currentSearchString = selectQueryParam('search_string');
56
56
  var compareMode = Boolean(selectQueryParam('compare_a')) && Boolean(selectQueryParam('compare_b'));
57
- var columns = React.useMemo(function () {
57
+ var columns = useMemo(function () {
58
58
  var cols = [
59
59
  columnHelper.accessor('meta', {
60
60
  header: function () { return _jsx("span", __assign({ className: "text-left" }, { children: "Name" })); },
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  declare const DiffLegend: () => JSX.Element;
3
2
  export default DiffLegend;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  interface Props {
3
2
  value: string;
4
3
  className?: string;
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryRequest, QueryServiceClient } from '@parca/client';
3
2
  interface Props {
4
3
  queryRequest: QueryRequest;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ /// <reference types="react" />
2
2
  import type { Props as CallgraphProps } from '@parca/profile/src/Callgraph';
3
3
  import ProfileExplorer from './ProfileExplorer';
4
4
  import ProfileTypeSelector from './ProfileTypeSelector';
@@ -12,7 +12,7 @@ export * from './ProfileViewWithData';
12
12
  export * from './utils';
13
13
  export * from './ProfileTypeSelector';
14
14
  export type { CallgraphProps };
15
- declare const Callgraph: React.LazyExoticComponent<({ graph, sampleUnit, width, colorRange }: CallgraphProps) => JSX.Element>;
15
+ declare const Callgraph: import("react").LazyExoticComponent<({ graph, sampleUnit, width, colorRange }: CallgraphProps) => JSX.Element>;
16
16
  export { Callgraph, ProfileExplorer, ProfileTypeSelector };
17
17
  interface GrafanaParcaDataPayload {
18
18
  flamegraphData: FlamegraphData;
package/dist/index.js CHANGED
@@ -46,7 +46,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
46
46
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
47
  }
48
48
  };
49
- import React from 'react';
49
+ import { lazy } from 'react';
50
50
  import ProfileExplorer from './ProfileExplorer';
51
51
  import ProfileTypeSelector from './ProfileTypeSelector';
52
52
  export * from './IcicleGraph';
@@ -56,7 +56,7 @@ export * from './ProfileView';
56
56
  export * from './ProfileViewWithData';
57
57
  export * from './utils';
58
58
  export * from './ProfileTypeSelector';
59
- var Callgraph = React.lazy(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
59
+ var Callgraph = lazy(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
60
60
  switch (_a.label) {
61
61
  case 0: return [4 /*yield*/, import('@parca/profile/src/Callgraph')];
62
62
  case 1: return [2 /*return*/, _a.sent()];
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.\!absolute{position:absolute!important}.absolute{position:absolute}.relative{position:relative}.top-0{top:0}.left-0{left:0}.right-0{right:0}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mr-3{margin-right:.75rem}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-36{height:9rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-full{width:100%}.w-auto{width:auto}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
1
+ /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.invisible{visibility:hidden}.absolute{position:absolute}.\!absolute{position:absolute!important}.relative{position:relative}.top-\[-46px\]{top:-46px}.left-\[25px\]{left:25px}.top-\[-45px\]{top:-45px}.top-0{top:0}.left-0{left:0}.right-0{right:0}.z-50{z-index:50}.z-10{z-index:10}.m-auto{margin:auto}.m-0{margin:0}.m-2{margin:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mr-3{margin-right:.75rem}.ml-2{margin-left:.5rem}.mr-6{margin-right:1.5rem}.mt-2{margin-top:.5rem}.mt-1{margin-top:.25rem}.ml-auto{margin-left:auto}.mb-2{margin-bottom:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-36{height:9rem}.h-1{height:.25rem}.h-\[80vh\]{height:80vh}.h-4{height:1rem}.max-h-\[400px\]{max-height:400px}.w-auto{width:auto}.w-1\/5{width:20%}.w-4\/5{width:80%}.w-full{width:100%}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-40{width:10rem}.w-2\/5{width:40%}.w-1\/2{width:50%}.w-8{width:2rem}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-20{padding-bottom:5rem;padding-top:5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pt-2{padding-top:.5rem}.pb-4{padding-bottom:1rem}.pr-2{padding-right:.5rem}.pl-2{padding-left:.5rem}.pb-2{padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-90{opacity:.9}.opacity-100{opacity:1}.opacity-0{opacity:0}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-indigo-800:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(55 48 163/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { QueryRequest, QueryServiceClient } from '@parca/client';
2
- import { RpcMetadata } from '@protobuf-ts/runtime-rpc';
2
+ import type { RpcMetadata } from '@protobuf-ts/runtime-rpc';
3
3
  export declare const hexifyAddress: (address?: string) => string;
4
4
  export declare const downloadPprof: (request: QueryRequest, queryClient: QueryServiceClient, metadata: RpcMetadata) => Promise<Blob>;
5
5
  export declare const truncateString: (str: string, num: number) => string;
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.100",
3
+ "version": "0.16.102",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.62",
7
- "@parca/components": "^0.16.87",
7
+ "@parca/components": "^0.16.88",
8
8
  "@parca/dynamicsize": "^0.16.52",
9
- "@parca/functions": "^0.16.58",
9
+ "@parca/functions": "^0.16.59",
10
10
  "@parca/parser": "^0.16.53",
11
- "@parca/store": "^0.16.52",
11
+ "@parca/store": "^0.16.53",
12
12
  "@types/react-beautiful-dnd": "^13.1.3",
13
13
  "d3": "7.8.2",
14
14
  "d3-scale": "^4.0.2",
@@ -44,5 +44,5 @@
44
44
  "access": "public",
45
45
  "registry": "https://registry.npmjs.org/"
46
46
  },
47
- "gitHead": "85c32b3e602f5f8f35749de42b24bb93b32ccd3c"
47
+ "gitHead": "405ca5fbcd87a649009658ad699b3ba90ecc38b9"
48
48
  }
@@ -15,7 +15,7 @@ import {useState, useEffect, useRef} from 'react';
15
15
  import graphviz from 'graphviz-wasm';
16
16
  import * as d3 from 'd3';
17
17
  import {Stage, Layer, Rect, Arrow, Text, Label} from 'react-konva';
18
- import {KonvaEventObject} from 'konva/lib/Node';
18
+ import type {KonvaEventObject} from 'konva/lib/Node';
19
19
  import {Button} from '@parca/components';
20
20
  import {CallgraphNode, CallgraphEdge, Callgraph as CallgraphType} from '@parca/client';
21
21
  import {jsonToDot, getCurvePoints} from './utils';
@@ -19,7 +19,11 @@ import {CallgraphNode, FlamegraphNode, FlamegraphNodeMeta, FlamegraphRootNode} f
19
19
  import {getLastItem, valueFormatter} from '@parca/functions';
20
20
  import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
21
21
  import {hexifyAddress, truncateString} from '../';
22
- import {Function, Location, Mapping} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
22
+ import {
23
+ Function as ParcaFunction,
24
+ Location,
25
+ Mapping,
26
+ } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
23
27
 
24
28
  interface GraphTooltipProps {
25
29
  x: number;
@@ -33,7 +37,7 @@ interface GraphTooltipProps {
33
37
  strings?: string[];
34
38
  mappings?: Mapping[];
35
39
  locations?: Location[];
36
- functions?: Function[];
40
+ functions?: ParcaFunction[];
37
41
  }
38
42
 
39
43
  const virtualElement = {
@@ -76,7 +80,7 @@ const TooltipMetaInfo = ({
76
80
  strings?: string[];
77
81
  mappings?: Mapping[];
78
82
  locations?: Location[];
79
- functions?: Function[];
83
+ functions?: ParcaFunction[];
80
84
  }): JSX.Element => {
81
85
  if (hoveringNode.meta === undefined) return <></>;
82
86
 
@@ -219,7 +223,7 @@ const GraphTooltipContent = ({
219
223
  strings?: string[];
220
224
  mappings?: Mapping[];
221
225
  locations?: Location[];
222
- functions?: Function[];
226
+ functions?: ParcaFunction[];
223
227
  }): JSX.Element => {
224
228
  const [isCopied, setIsCopied] = useState<boolean>(false);
225
229
 
@@ -11,14 +11,19 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {MouseEvent, useEffect, useMemo, useRef, useState} from 'react';
14
+ import {MouseEvent, useEffect, useMemo, useRef, useState, memo, Fragment} from 'react';
15
15
 
16
+ import cx from 'classnames';
16
17
  import {throttle} from 'lodash';
17
18
  import {pointer} from 'd3-selection';
18
19
  import {scaleLinear} from 'd3-scale';
19
20
 
20
21
  import {Flamegraph, FlamegraphNode, FlamegraphRootNode} from '@parca/client';
21
- import {Mapping, Function, Location} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
22
+ import {
23
+ Mapping,
24
+ Function as ParcaFunction,
25
+ Location,
26
+ } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
22
27
  import type {HoveringNode} from './GraphTooltip';
23
28
  import GraphTooltip from './GraphTooltip';
24
29
  import {diffColor, getLastItem, isSearchMatch, selectQueryParam} from '@parca/functions';
@@ -26,6 +31,7 @@ import {selectDarkMode, useAppSelector} from '@parca/store';
26
31
  import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
27
32
  import {Button} from '@parca/components';
28
33
  import {hexifyAddress} from './utils';
34
+ import {useURLState} from '@parca/functions';
29
35
 
30
36
  interface IcicleGraphProps {
31
37
  graph: Flamegraph;
@@ -40,7 +46,7 @@ interface IcicleGraphNodesProps {
40
46
  strings: string[];
41
47
  mappings: Mapping[];
42
48
  locations: Location[];
43
- functions: Function[];
49
+ functions: ParcaFunction[];
44
50
  x: number;
45
51
  y: number;
46
52
  total: number;
@@ -58,7 +64,7 @@ interface IcicleGraphRootNodeProps {
58
64
  strings: string[];
59
65
  mappings: Mapping[];
60
66
  locations: Location[];
61
- functions: Function[];
67
+ functions: ParcaFunction[];
62
68
  xScale: (value: number) => number;
63
69
  total: number;
64
70
  totalWidth: number;
@@ -147,7 +153,7 @@ export function nodeLabel(
147
153
  strings: string[],
148
154
  mappings: Mapping[],
149
155
  locations: Location[],
150
- functions: Function[]
156
+ functions: ParcaFunction[]
151
157
  ): string {
152
158
  if (node.meta?.locationIndex === undefined) return '<unknown>';
153
159
  if (node.meta?.locationIndex === 0) return '<unknown>';
@@ -161,7 +167,7 @@ export function nodeLabel(
161
167
  const mappingFile =
162
168
  mapping?.fileStringIndex !== undefined ? strings[mapping.fileStringIndex] : '';
163
169
 
164
- const mappingString: string = `${
170
+ const mappingString = `${
165
171
  mappingFile !== '' ? '[' + (getLastItem(mappingFile) ?? '') + '] ' : ''
166
172
  }`;
167
173
 
@@ -251,7 +257,7 @@ export function IcicleGraphNodes({
251
257
  };
252
258
 
253
259
  return (
254
- <React.Fragment key={`node-${key}`}>
260
+ <Fragment key={`node-${key}`}>
255
261
  <IcicleRect
256
262
  key={`rect-${key}`}
257
263
  x={xStart}
@@ -285,14 +291,14 @@ export function IcicleGraphNodes({
285
291
  setCurPath={setCurPath}
286
292
  />
287
293
  )}
288
- </React.Fragment>
294
+ </Fragment>
289
295
  );
290
296
  })}
291
297
  </g>
292
298
  );
293
299
  }
294
300
 
295
- const MemoizedIcicleGraphNodes = React.memo(IcicleGraphNodes);
301
+ const MemoizedIcicleGraphNodes = memo(IcicleGraphNodes);
296
302
 
297
303
  export function IcicleGraphRootNode({
298
304
  node,
@@ -363,7 +369,7 @@ export function IcicleGraphRootNode({
363
369
  );
364
370
  }
365
371
 
366
- const MemoizedIcicleGraphRootNode = React.memo(IcicleGraphRootNode);
372
+ const MemoizedIcicleGraphRootNode = memo(IcicleGraphRootNode);
367
373
 
368
374
  export default function IcicleGraph({
369
375
  graph,
@@ -379,6 +385,11 @@ export default function IcicleGraph({
379
385
  const [height, setHeight] = useState(0);
380
386
  const svg = useRef(null);
381
387
  const ref = useRef<SVGGElement>(null);
388
+ const [rawDashboardItems] = useURLState({
389
+ param: 'dashboard_items',
390
+ });
391
+
392
+ const dashboardItems = rawDashboardItems as string[];
382
393
 
383
394
  useEffect(() => {
384
395
  if (ref.current != null) {
@@ -407,7 +418,7 @@ export default function IcicleGraph({
407
418
  };
408
419
 
409
420
  return (
410
- <div onMouseLeave={() => setHoveringNode(undefined)}>
421
+ <div onMouseLeave={() => setHoveringNode(undefined)} className="relative">
411
422
  <GraphTooltip
412
423
  unit={sampleUnit}
413
424
  total={total}
@@ -420,7 +431,12 @@ export default function IcicleGraph({
420
431
  locations={graph.locations}
421
432
  functions={graph.function}
422
433
  />
423
- <div className="w-full flex justify-start">
434
+ <div
435
+ className={cx(
436
+ dashboardItems.length > 1 ? 'top-[-46px] left-[25px]' : 'top-[-45px]',
437
+ 'flex justify-start absolute '
438
+ )}
439
+ >
424
440
  <Button
425
441
  color="neutral"
426
442
  onClick={() => setCurPath([])}
@@ -428,7 +444,7 @@ export default function IcicleGraph({
428
444
  className="w-auto"
429
445
  variant="neutral"
430
446
  >
431
- Reset zoom
447
+ Reset View
432
448
  </Button>
433
449
  </div>
434
450
  <svg
@@ -422,7 +422,7 @@ export const RawMetricsGraph = ({
422
422
  }
423
423
 
424
424
  let s: Series | null = null;
425
- let seriesIndex: number = -1;
425
+ let seriesIndex = -1;
426
426
 
427
427
  outer: for (let i = 0; i < series.length; i++) {
428
428
  const keys = profile.labels.map(e => e.name);
@@ -45,7 +45,7 @@ const ProfileExplorerSingle = ({
45
45
  querySelection={query}
46
46
  selectQuery={selectQuery}
47
47
  selectProfile={selectProfile}
48
- closeProfile={() => {}}
48
+ closeProfile={() => {}} // eslint-disable-line @typescript-eslint/no-empty-function
49
49
  profileSelection={profile}
50
50
  comparing={false}
51
51
  onCompareProfile={compareProfile}
@@ -11,7 +11,6 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React from 'react';
15
14
  import {formatDate} from '@parca/functions';
16
15
  import {Query, ProfileType} from '@parca/parser';
17
16
  import {
@@ -354,7 +353,7 @@ export class MergedProfileSource implements ProfileSource {
354
353
  Describe(): JSX.Element {
355
354
  return (
356
355
  <a>
357
- Merge of "{this.query}" from {formatDate(this.from, timeFormat)} to{' '}
356
+ Merge of &quot;{this.query}&quot; from {formatDate(this.from, timeFormat)} to{' '}
358
357
  {formatDate(this.to, timeFormat)}
359
358
  </a>
360
359
  );
@@ -11,10 +11,11 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {useMemo} from 'react';
14
+ import {useMemo} from 'react';
15
15
  import {ProfileType, ProfileTypesResponse} from '@parca/client';
16
16
  import {RpcError} from '@protobuf-ts/runtime-rpc';
17
- import {SelectElement, Select} from '@parca/components';
17
+ import {Select} from '@parca/components';
18
+ import type {SelectElement} from '@parca/components';
18
19
 
19
20
  interface WellKnownProfile {
20
21
  name: string;
@@ -11,7 +11,8 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import {Select, SelectElement} from '@parca/components';
14
+ import {Select} from '@parca/components';
15
+ import type {SelectElement} from '@parca/components';
15
16
  import {useURLState, NavigateFunction} from '@parca/functions';
16
17
  import useUIFeatureFlag from '@parca/functions/useUIFeatureFlag';
17
18
 
@@ -22,13 +22,8 @@ import {QueryServiceClient, Flamegraph, Top, Callgraph as CallgraphType} from '@
22
22
  import {Button, Card, useParcaContext} from '@parca/components';
23
23
  import {useContainerDimensions} from '@parca/dynamicsize';
24
24
  import {useAppSelector, selectDarkMode} from '@parca/store';
25
- import {
26
- DragDropContext,
27
- Droppable,
28
- Draggable,
29
- DropResult,
30
- DraggableLocation,
31
- } from 'react-beautiful-dnd';
25
+ import {DragDropContext, Droppable, Draggable} from 'react-beautiful-dnd';
26
+ import type {DropResult, DraggableLocation} from 'react-beautiful-dnd';
32
27
 
33
28
  import {Callgraph} from '../';
34
29
  import ProfileShareButton from '../components/ProfileShareButton';
@@ -36,7 +31,7 @@ import FilterByFunctionButton from './FilterByFunctionButton';
36
31
  import ViewSelector from './ViewSelector';
37
32
  import ProfileIcicleGraph, {ResizeHandler} from '../ProfileIcicleGraph';
38
33
  import {ProfileSource} from '../ProfileSource';
39
- import TopTable from '../TopTable';
34
+ import {TopTable} from '../TopTable';
40
35
  import useDelayedLoader from '../useDelayedLoader';
41
36
 
42
37
  import '../ProfileView.styles.css';
@@ -290,7 +285,10 @@ export const ProfileView = ({
290
285
  <div className="w-full flex justify-end pb-2">
291
286
  <div className="w-full flex justify-between">
292
287
  <div
293
- className={cx(isMultiPanelView ? 'visible' : 'invisible')}
288
+ className={cx(
289
+ isMultiPanelView ? 'visible' : 'invisible',
290
+ 'flex items-center'
291
+ )}
294
292
  {...provided.dragHandleProps}
295
293
  >
296
294
  <Icon
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {useCallback, useMemo} from 'react';
14
+ import {useCallback, useMemo} from 'react';
15
15
 
16
16
  import {
17
17
  getLastItem,
@@ -23,7 +23,8 @@ import {
23
23
  } from '@parca/functions';
24
24
  import {TopNode, TopNodeMeta, Top} from '@parca/client';
25
25
  import {Table} from '@parca/components';
26
- import {createColumnHelper, ColumnDef} from '@tanstack/react-table';
26
+ import {createColumnHelper} from '@tanstack/react-table';
27
+ import type {ColumnDef} from '@tanstack/react-table';
27
28
 
28
29
  import {hexifyAddress} from '../utils';
29
30
 
@@ -67,7 +68,7 @@ export const TopTable = ({data: top, sampleUnit: unit, navigateTo}: TopTableProp
67
68
  const compareMode =
68
69
  Boolean(selectQueryParam('compare_a')) && Boolean(selectQueryParam('compare_b'));
69
70
 
70
- const columns = React.useMemo(() => {
71
+ const columns = useMemo(() => {
71
72
  const cols: Array<ColumnDef<TopNode, any>> = [
72
73
  columnHelper.accessor('meta', {
73
74
  header: () => <span className="text-left">Name</span>,
package/src/index.tsx CHANGED
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React from 'react';
14
+ import {lazy} from 'react';
15
15
  import type {Props as CallgraphProps} from '@parca/profile/src/Callgraph';
16
16
  import ProfileExplorer from './ProfileExplorer';
17
17
  import ProfileTypeSelector from './ProfileTypeSelector';
@@ -28,7 +28,7 @@ export * from './ProfileTypeSelector';
28
28
 
29
29
  export type {CallgraphProps};
30
30
 
31
- const Callgraph = React.lazy(async () => await import('@parca/profile/src/Callgraph'));
31
+ const Callgraph = lazy(async () => await import('@parca/profile/src/Callgraph'));
32
32
 
33
33
  export {Callgraph, ProfileExplorer, ProfileTypeSelector};
34
34
 
package/src/utils.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  // limitations under the License.
13
13
 
14
14
  import {QueryRequest, QueryRequest_ReportType, QueryServiceClient} from '@parca/client';
15
- import {RpcMetadata} from '@protobuf-ts/runtime-rpc';
15
+ import type {RpcMetadata} from '@protobuf-ts/runtime-rpc';
16
16
 
17
17
  export const hexifyAddress = (address?: string): string => {
18
18
  if (address == null) {