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 {useState} from 'react';
    
  12. import Store from '../../store';
    
  13. import EditableName from './EditableName';
    
  14. import EditableValue from './EditableValue';
    
  15. import {parseHookPathForEdit} from './utils';
    
  16. import styles from './NewKeyValue.css';
    
  17. 
    
  18. import type {InspectedElement} from 'react-devtools-shared/src/frontend/types';
    
  19. import type {FrontendBridge} from 'react-devtools-shared/src/bridge';
    
  20. 
    
  21. type Props = {
    
  22.   bridge: FrontendBridge,
    
  23.   depth: number,
    
  24.   hidden: boolean,
    
  25.   hookID?: ?number,
    
  26.   inspectedElement: InspectedElement,
    
  27.   path: Array<string | number>,
    
  28.   store: Store,
    
  29.   type: 'props' | 'state' | 'hooks' | 'context',
    
  30. };
    
  31. 
    
  32. export default function NewKeyValue({
    
  33.   bridge,
    
  34.   depth,
    
  35.   hidden,
    
  36.   hookID,
    
  37.   inspectedElement,
    
  38.   path,
    
  39.   store,
    
  40.   type,
    
  41. }: Props): React.Node {
    
  42.   const [newPropKey, setNewPropKey] = useState<number>(0);
    
  43.   const [newPropName, setNewPropName] = useState<string>('');
    
  44. 
    
  45.   // $FlowFixMe[missing-local-annot]
    
  46.   const overrideNewEntryName = (oldPath: any, newPath) => {
    
  47.     setNewPropName(newPath[newPath.length - 1]);
    
  48.   };
    
  49. 
    
  50.   const overrideNewEntryValue = (
    
  51.     newPath: Array<string | number>,
    
  52.     value: any,
    
  53.   ) => {
    
  54.     if (!newPropName) {
    
  55.       return;
    
  56.     }
    
  57. 
    
  58.     setNewPropName('');
    
  59.     setNewPropKey(newPropKey + 1);
    
  60. 
    
  61.     const {id} = inspectedElement;
    
  62.     const rendererID = store.getRendererIDForElement(id);
    
  63.     if (rendererID !== null) {
    
  64.       let basePath: Array<string | number> = newPath;
    
  65.       if (hookID != null) {
    
  66.         basePath = parseHookPathForEdit(basePath);
    
  67.       }
    
  68. 
    
  69.       bridge.send('overrideValueAtPath', {
    
  70.         type,
    
  71.         hookID,
    
  72.         id,
    
  73.         path: basePath,
    
  74.         rendererID,
    
  75.         value,
    
  76.       });
    
  77.     }
    
  78.   };
    
  79. 
    
  80.   return (
    
  81.     <div
    
  82.       key={newPropKey}
    
  83.       hidden={hidden}
    
  84.       style={{
    
  85.         paddingLeft: `${(depth - 1) * 0.75}rem`,
    
  86.       }}>
    
  87.       <div className={styles.NewKeyValue}>
    
  88.         <EditableName
    
  89.           autoFocus={newPropKey > 0}
    
  90.           className={styles.EditableName}
    
  91.           overrideName={overrideNewEntryName}
    
  92.           path={[]}
    
  93.         />
    
  94.         :&nbsp;
    
  95.         <EditableValue
    
  96.           className={styles.EditableValue}
    
  97.           overrideValue={overrideNewEntryValue}
    
  98.           path={[...path, newPropName]}
    
  99.           value={''}
    
  100.         />
    
  101.       </div>
    
  102.     </div>
    
  103.   );
    
  104. }