@parca/profile 0.19.151 → 0.19.152
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.
- package/CHANGELOG.md +4 -0
- package/dist/GraphTooltipArrow/Content.d.ts +2 -1
- package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/Content.js +203 -9
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.d.ts +28 -0
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.d.ts.map +1 -0
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.js +845 -0
- package/dist/GraphTooltipArrow/index.d.ts +2 -1
- package/dist/GraphTooltipArrow/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/index.js +11 -2
- package/dist/GraphTooltipArrow/openInNewTab.d.ts +2 -0
- package/dist/GraphTooltipArrow/openInNewTab.d.ts.map +1 -0
- package/dist/GraphTooltipArrow/openInNewTab.js +40 -0
- package/dist/ProfileFlameGraph/FlameGraphArrow/MemoizedTooltip.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/MemoizedTooltip.js +119 -56
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/src/GraphTooltipArrow/Content.tsx +86 -5
- package/src/GraphTooltipArrow/gpuFrameDescriptions.test.ts +53 -0
- package/src/GraphTooltipArrow/gpuFrameDescriptions.ts +556 -0
- package/src/GraphTooltipArrow/index.tsx +13 -1
- package/src/GraphTooltipArrow/openInNewTab.ts +43 -0
- package/src/ProfileFlameGraph/FlameGraphArrow/MemoizedTooltip.tsx +35 -2
|
@@ -21,6 +21,7 @@ import {pointer} from 'd3-selection';
|
|
|
21
21
|
interface GraphTooltipProps {
|
|
22
22
|
children: React.ReactNode;
|
|
23
23
|
contextElement: Element | null;
|
|
24
|
+
frozen?: boolean;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
function createPositionedVirtualElement(contextElement: Element, x = 0, y = 0): VirtualElement {
|
|
@@ -40,7 +41,11 @@ function createPositionedVirtualElement(contextElement: Element, x = 0, y = 0):
|
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
const GraphTooltip = ({
|
|
44
|
+
const GraphTooltip = ({
|
|
45
|
+
children,
|
|
46
|
+
contextElement,
|
|
47
|
+
frozen = false,
|
|
48
|
+
}: GraphTooltipProps): React.JSX.Element => {
|
|
44
49
|
'use no memo';
|
|
45
50
|
const [isPositioned, setIsPositioned] = useState(false);
|
|
46
51
|
|
|
@@ -60,10 +65,16 @@ const GraphTooltip = ({children, contextElement}: GraphTooltipProps): React.JSX.
|
|
|
60
65
|
whileElementsMounted: undefined,
|
|
61
66
|
});
|
|
62
67
|
|
|
68
|
+
// Read the latest `frozen` value from inside the mousemove handler without
|
|
69
|
+
// re-binding the listener every time it toggles.
|
|
70
|
+
const frozenRef = React.useRef(frozen);
|
|
71
|
+
frozenRef.current = frozen;
|
|
72
|
+
|
|
63
73
|
useEffect(() => {
|
|
64
74
|
if (contextElement === null) return;
|
|
65
75
|
|
|
66
76
|
const onMouseMove: EventListenerOrEventListenerObject = (e: Event) => {
|
|
77
|
+
if (frozenRef.current) return; // Hold position while ⇧ Shift is held.
|
|
67
78
|
const rel = pointer(e);
|
|
68
79
|
const tooltipX = rel[0];
|
|
69
80
|
const tooltipY = rel[1];
|
|
@@ -85,6 +96,7 @@ const GraphTooltip = ({children, contextElement}: GraphTooltipProps): React.JSX.
|
|
|
85
96
|
style={{
|
|
86
97
|
...floatingStyles,
|
|
87
98
|
visibility: !isPositioned ? 'hidden' : 'visible',
|
|
99
|
+
pointerEvents: frozen ? 'auto' : 'none',
|
|
88
100
|
}}
|
|
89
101
|
className="z-50 w-max"
|
|
90
102
|
>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright 2022 The Parca Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
13
|
+
|
|
14
|
+
// Open a URL in a new browser tab — robust to held modifier keys.
|
|
15
|
+
//
|
|
16
|
+
// Why this exists: the tooltip's "freeze" gesture requires the user to be
|
|
17
|
+
// holding ⇧ Shift. Browsers route Shift+click on a target="_blank" link to
|
|
18
|
+
// "new window" via real-keyboard state at navigation time, so both plain
|
|
19
|
+
// <a target="_blank"> clicks and `window.open` fall through to a window
|
|
20
|
+
// instead of a tab.
|
|
21
|
+
//
|
|
22
|
+
// Trick: dispatch a synthetic MouseEvent on a detached anchor with the
|
|
23
|
+
// platform's "new-tab" modifier set explicitly (Cmd & Ctrl)
|
|
24
|
+
// and Shift cleared. The browser reads modifier flags off the event for its
|
|
25
|
+
// routing decision, so this consistently opens in a new tab.
|
|
26
|
+
export function openInNewTab(url: string): void {
|
|
27
|
+
const a = document.createElement('a');
|
|
28
|
+
a.href = url;
|
|
29
|
+
a.target = '_blank';
|
|
30
|
+
a.rel = 'noopener noreferrer';
|
|
31
|
+
|
|
32
|
+
a.dispatchEvent(
|
|
33
|
+
new MouseEvent('click', {
|
|
34
|
+
bubbles: false,
|
|
35
|
+
cancelable: true,
|
|
36
|
+
view: window,
|
|
37
|
+
button: 0,
|
|
38
|
+
shiftKey: false,
|
|
39
|
+
metaKey: true,
|
|
40
|
+
ctrlKey: true,
|
|
41
|
+
})
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -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, {memo, useEffect, useState} from 'react';
|
|
14
|
+
import React, {memo, useEffect, useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import GraphTooltipArrow from '../../GraphTooltipArrow';
|
|
17
17
|
import GraphTooltipArrowContent from '../../GraphTooltipArrow/Content';
|
|
@@ -28,13 +28,45 @@ export const MemoizedTooltip = memo(function MemoizedTooltip({
|
|
|
28
28
|
dockedMetainfo,
|
|
29
29
|
}: MemoizedTooltipProps): React.JSX.Element | null {
|
|
30
30
|
const [tooltipRow, setTooltipRow] = useState<number | null>(null);
|
|
31
|
+
const [shiftHeld, setShiftHeld] = useState(false);
|
|
32
|
+
const shiftHeldRef = useRef(false);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
shiftHeldRef.current = shiftHeld;
|
|
36
|
+
}, [shiftHeld]);
|
|
37
|
+
|
|
31
38
|
const {table, total, totalUnfiltered, profileType, unit, compareAbsolute, tooltipId} =
|
|
32
39
|
useTooltipContext();
|
|
33
40
|
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const onKeyDown = (e: KeyboardEvent): void => {
|
|
43
|
+
if (e.key === 'Shift') setShiftHeld(true);
|
|
44
|
+
};
|
|
45
|
+
const onKeyUp = (e: KeyboardEvent): void => {
|
|
46
|
+
if (e.key === 'Shift') setShiftHeld(false);
|
|
47
|
+
};
|
|
48
|
+
// If the user opens the attribution link, releases Shift in the new tab,
|
|
49
|
+
// and comes back — our window never saw the keyup, so the frozen state
|
|
50
|
+
// would stick. Clear it whenever focus leaves the tab.
|
|
51
|
+
const onBlurOrHide = (): void => setShiftHeld(false);
|
|
52
|
+
window.addEventListener('keydown', onKeyDown);
|
|
53
|
+
window.addEventListener('keyup', onKeyUp);
|
|
54
|
+
window.addEventListener('blur', onBlurOrHide);
|
|
55
|
+
document.addEventListener('visibilitychange', onBlurOrHide);
|
|
56
|
+
return () => {
|
|
57
|
+
window.removeEventListener('keydown', onKeyDown);
|
|
58
|
+
window.removeEventListener('keyup', onKeyUp);
|
|
59
|
+
window.removeEventListener('blur', onBlurOrHide);
|
|
60
|
+
document.removeEventListener('visibilitychange', onBlurOrHide);
|
|
61
|
+
};
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
34
64
|
// This component subscribes to tooltip updates through a callback
|
|
35
65
|
// passed to the TooltipProvider, avoiding the need to lift state
|
|
36
66
|
useEffect(() => {
|
|
37
67
|
const handleTooltipUpdate = (event: CustomEvent<{row: number | null}>): void => {
|
|
68
|
+
// While Shift is held, lock the tooltip to its original frame.
|
|
69
|
+
if (shiftHeldRef.current) return;
|
|
38
70
|
setTooltipRow(event.detail.row);
|
|
39
71
|
};
|
|
40
72
|
|
|
@@ -82,7 +114,7 @@ export const MemoizedTooltip = memo(function MemoizedTooltip({
|
|
|
82
114
|
return null;
|
|
83
115
|
}
|
|
84
116
|
return (
|
|
85
|
-
<GraphTooltipArrow contextElement={contextElement}>
|
|
117
|
+
<GraphTooltipArrow contextElement={contextElement} frozen={shiftHeld}>
|
|
86
118
|
<GraphTooltipArrowContent
|
|
87
119
|
table={table}
|
|
88
120
|
row={tooltipRow}
|
|
@@ -92,6 +124,7 @@ export const MemoizedTooltip = memo(function MemoizedTooltip({
|
|
|
92
124
|
profileType={profileType}
|
|
93
125
|
unit={unit}
|
|
94
126
|
compareAbsolute={compareAbsolute}
|
|
127
|
+
frozen={shiftHeld}
|
|
95
128
|
/>
|
|
96
129
|
</GraphTooltipArrow>
|
|
97
130
|
);
|