main
js 135 lines 3.28 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import * as React from 'react';
11 import {useContext} from 'react';
12
13 import {ContextMenuContext} from '../context';
14 import {
15 copyInspectedElementPath as copyInspectedElementPathAPI,
16 storeAsGlobal as storeAsGlobalAPI,
17 } from '../../../backendAPI';
18 import Icon from '../Icon';
19 import ContextMenuContainer from '../../ContextMenu/ContextMenuContainer';
20
21 import type Store from 'react-devtools-shared/src/devtools/store';
22 import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
23 import type {ContextMenuContextType} from '../context';
24
25 import styles from './KeyValueContextMenuContainer.css';
26
27 type Props = {
28 children: React.Node,
29 anchorElementRef: {
30 current: React.ElementRef<any> | null,
31 },
32 store: Store,
33 attributeSourceCanBeInspected: boolean,
34 bridge: FrontendBridge,
35 id: number,
36 path: Array<any>,
37 canBeCopiedToClipboard: boolean,
38 };
39
40 export default function KeyValueContextMenuContainer({
41 children,
42 anchorElementRef,
43 store,
44 attributeSourceCanBeInspected,
45 bridge,
46 id,
47 path,
48 canBeCopiedToClipboard,
49 }: Props): React.Node {
50 const {
51 isEnabledForInspectedElement: isContextMenuEnabledForInspectedElement,
52 viewAttributeSourceFunction,
53 } = useContext<ContextMenuContextType>(ContextMenuContext);
54
55 const menuItems = React.useMemo(() => {
56 const items = [
57 {
58 onClick: () => {
59 const rendererID = store.getRendererIDForElement(id);
60 if (rendererID !== null) {
61 storeAsGlobalAPI({
62 bridge,
63 id,
64 path,
65 rendererID,
66 });
67 }
68 },
69 content: (
70 <span className={styles.ContextMenuItemContent}>
71 <Icon type="store-as-global-variable" />
72 <label>Store as global variable</label>
73 </span>
74 ),
75 },
76 ];
77
78 if (canBeCopiedToClipboard) {
79 items.unshift({
80 onClick: () => {
81 const rendererID = store.getRendererIDForElement(id);
82 if (rendererID !== null) {
83 copyInspectedElementPathAPI({
84 bridge,
85 id,
86 path,
87 rendererID,
88 });
89 }
90 },
91 content: (
92 <span className={styles.ContextMenuItemContent}>
93 <Icon type="copy" />
94 <label>Copy value to clipboard</label>
95 </span>
96 ),
97 });
98 }
99
100 if (viewAttributeSourceFunction != null && attributeSourceCanBeInspected) {
101 items.push({
102 onClick: () => viewAttributeSourceFunction(id, path),
103 content: (
104 <span className={styles.ContextMenuItemContent}>
105 <Icon type="code" />
106 <label>Go to definition</label>
107 </span>
108 ),
109 });
110 }
111 return items;
112 }, [
113 store,
114 viewAttributeSourceFunction,
115 attributeSourceCanBeInspected,
116 canBeCopiedToClipboard,
117 bridge,
118 id,
119 path,
120 ]);
121
122 if (!isContextMenuEnabledForInspectedElement) {
123 return children;
124 }
125
126 return (
127 <>
128 {children}
129 <ContextMenuContainer
130 anchorElementRef={anchorElementRef}
131 items={menuItems}
132 />
133 </>
134 );
135 }