-
Notifications
You must be signed in to change notification settings - Fork 51.1k
Expand file tree
/
Copy pathInspectedElementSourcePanel.js
More file actions
121 lines (103 loc) · 3.27 KB
/
InspectedElementSourcePanel.js
File metadata and controls
121 lines (103 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import * as React from 'react';
import {copy} from 'clipboard-js';
import Button from '../Button';
import ButtonIcon from '../ButtonIcon';
import Skeleton from './Skeleton';
import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';
import useOpenResource from '../useOpenResource';
import type {ReactFunctionLocation} from 'shared/ReactTypes';
import styles from './InspectedElementSourcePanel.css';
import formatLocationForDisplay from './formatLocationForDisplay';
type Props = {
source: ReactFunctionLocation,
symbolicatedSourcePromise: Promise<ReactFunctionLocation | null>,
};
function InspectedElementSourcePanel({
source,
symbolicatedSourcePromise,
}: Props): React.Node {
return (
<div>
<div className={styles.SourceHeaderRow}>
<div className={styles.SourceHeader}>source</div>
<React.Suspense
fallback={
<Button disabled={true} title="Loading source maps...">
<ButtonIcon type="copy" />
</Button>
}>
<CopySourceButton
source={source}
symbolicatedSourcePromise={symbolicatedSourcePromise}
/>
</React.Suspense>
</div>
<React.Suspense
fallback={
<div className={styles.SourceOneLiner}>
<Skeleton height={16} width="40%" />
</div>
}>
<FormattedSourceString
source={source}
symbolicatedSourcePromise={symbolicatedSourcePromise}
/>
</React.Suspense>
</div>
);
}
function CopySourceButton({source, symbolicatedSourcePromise}: Props) {
const symbolicatedSource = React.use(symbolicatedSourcePromise);
if (symbolicatedSource == null) {
const [, sourceURL, line, column] = source;
const handleCopy = withPermissionsCheck(
{permissions: ['clipboardWrite']},
() => copy(`${sourceURL}:${line}:${column}`),
);
return (
<Button onClick={handleCopy} title="Copy to clipboard">
<ButtonIcon type="copy" />
</Button>
);
}
const [, sourceURL, line, column] = symbolicatedSource;
const handleCopy = withPermissionsCheck(
{permissions: ['clipboardWrite']},
() => copy(`${sourceURL}:${line}:${column}`),
);
return (
<Button onClick={handleCopy} title="Copy to clipboard">
<ButtonIcon type="copy" />
</Button>
);
}
function FormattedSourceString({source, symbolicatedSourcePromise}: Props) {
const symbolicatedSource = React.use(symbolicatedSourcePromise);
const [linkIsEnabled, viewSource] = useOpenResource(
source,
symbolicatedSource,
);
const [, sourceURL, line, column] =
symbolicatedSource == null ? source : symbolicatedSource;
return (
<div
className={styles.SourceOneLiner}
data-testname="InspectedElementView-FormattedSourceString">
<span
className={linkIsEnabled ? styles.Link : null}
title={sourceURL + ':' + line}
onClick={viewSource}>
{formatLocationForDisplay(sourceURL, line, column)}
</span>
</div>
);
}
export default InspectedElementSourcePanel;