Skip to content

Commit 031a5aa

Browse files
author
Brian Vaughn
authored
Show component location for selected element in bottom/right of props panel (#17567)
* Show component location info for selected element in bottom/right of props panel * Moved RegExp declaration into function basedon PR feedback
1 parent e039e69 commit 031a5aa

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@
3131
font-family: var(--font-family-sans);
3232
}
3333

34+
.Source {
35+
padding: 0.25rem;
36+
border-top: 1px solid var(--color-border);
37+
}
38+
39+
.SourceHeaderRow {
40+
display: flex;
41+
align-items: center;
42+
}
43+
44+
.SourceHeader {
45+
flex: 1 1;
46+
font-family: var(--font-family-sans);
47+
}
48+
49+
.SourceOneLiner {
50+
font-family: var(--font-family-monospace);
51+
font-size: var(--font-size-monospace-normal);
52+
white-space: nowrap;
53+
overflow: hidden;
54+
text-overflow: ellipsis;
55+
max-width: 100%;
56+
margin-left: 1rem;
57+
}
58+
3459
.Component,
3560
.Owner {
3661
color: var(--color-component-name);

packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* @flow
88
*/
99

10+
import {copy} from 'clipboard-js';
1011
import React, {useCallback, useContext} from 'react';
1112
import {TreeDispatcherContext, TreeStateContext} from './TreeContext';
1213
import {BridgeContext, StoreContext} from '../context';
@@ -272,6 +273,7 @@ function InspectedElementView({
272273
hooks,
273274
owners,
274275
props,
276+
source,
275277
state,
276278
} = inspectedElement;
277279

@@ -403,6 +405,54 @@ function InspectedElementView({
403405
))}
404406
</div>
405407
)}
408+
409+
{source !== null && (
410+
<Source fileName={source.fileName} lineNumber={source.lineNumber} />
411+
)}
412+
</div>
413+
);
414+
}
415+
416+
// This function is based on packages/shared/describeComponentFrame.js
417+
function formatSourceForDisplay(fileName: string, lineNumber: string) {
418+
const BEFORE_SLASH_RE = /^(.*)[\\\/]/;
419+
420+
let nameOnly = fileName.replace(BEFORE_SLASH_RE, '');
421+
422+
// In DEV, include code for a common special case:
423+
// prefer "folder/index.js" instead of just "index.js".
424+
if (/^index\./.test(nameOnly)) {
425+
const match = fileName.match(BEFORE_SLASH_RE);
426+
if (match) {
427+
const pathBeforeSlash = match[1];
428+
if (pathBeforeSlash) {
429+
const folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
430+
nameOnly = folderName + '/' + nameOnly;
431+
}
432+
}
433+
}
434+
435+
return `${nameOnly}:${lineNumber}`;
436+
}
437+
438+
type SourceProps = {|
439+
fileName: string,
440+
lineNumber: string,
441+
|};
442+
443+
function Source({fileName, lineNumber}: SourceProps) {
444+
const handleCopy = () => copy(`${fileName}:${lineNumber}`);
445+
return (
446+
<div className={styles.Source}>
447+
<div className={styles.SourceHeaderRow}>
448+
<div className={styles.SourceHeader}>source</div>
449+
<Button onClick={handleCopy} title="Copy to clipboard">
450+
<ButtonIcon type="copy" />
451+
</Button>
452+
</div>
453+
<div className={styles.SourceOneLiner}>
454+
{formatSourceForDisplay(fileName, lineNumber)}
455+
</div>
406456
</div>
407457
);
408458
}

0 commit comments

Comments
 (0)