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 {smartParse} from '../../utils';
    
  15. import {parseHookPathForEdit} from './utils';
    
  16. import styles from './NewArrayValue.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.   index: number,
    
  27.   inspectedElement: InspectedElement,
    
  28.   path: Array<string | number>,
    
  29.   store: Store,
    
  30.   type: 'props' | 'context' | 'hooks' | 'state',
    
  31. };
    
  32. 
    
  33. export default function NewArrayValue({
    
  34.   bridge,
    
  35.   depth,
    
  36.   hidden,
    
  37.   hookID,
    
  38.   index,
    
  39.   inspectedElement,
    
  40.   path,
    
  41.   store,
    
  42.   type,
    
  43. }: Props): React.Node {
    
  44.   const [key, setKey] = useState<number>(0);
    
  45.   const [isInvalid, setIsInvalid] = useState(false);
    
  46. 
    
  47.   // This is a bit of an unusual usage of the EditableName component,
    
  48.   // but otherwise it acts the way we want for a new Array entry.
    
  49.   // $FlowFixMe[missing-local-annot]
    
  50.   const overrideName = (oldPath: any, newPath) => {
    
  51.     const value = newPath[newPath.length - 1];
    
  52. 
    
  53.     let parsedValue;
    
  54.     let newIsInvalid = true;
    
  55.     try {
    
  56.       parsedValue = smartParse(value);
    
  57.       newIsInvalid = false;
    
  58.     } catch (error) {}
    
  59. 
    
  60.     if (isInvalid !== newIsInvalid) {
    
  61.       setIsInvalid(newIsInvalid);
    
  62.     }
    
  63. 
    
  64.     if (!newIsInvalid) {
    
  65.       setKey(key + 1);
    
  66. 
    
  67.       const {id} = inspectedElement;
    
  68.       const rendererID = store.getRendererIDForElement(id);
    
  69.       if (rendererID !== null) {
    
  70.         let basePath = path;
    
  71.         if (hookID != null) {
    
  72.           basePath = parseHookPathForEdit(basePath);
    
  73.         }
    
  74. 
    
  75.         bridge.send('overrideValueAtPath', {
    
  76.           type,
    
  77.           hookID,
    
  78.           id,
    
  79.           path: [...basePath, index],
    
  80.           rendererID,
    
  81.           value: parsedValue,
    
  82.         });
    
  83.       }
    
  84.     }
    
  85.   };
    
  86. 
    
  87.   return (
    
  88.     <div
    
  89.       key={key}
    
  90.       hidden={hidden}
    
  91.       style={{
    
  92.         paddingLeft: `${(depth - 1) * 0.75}rem`,
    
  93.       }}>
    
  94.       <div className={styles.NewArrayValue}>
    
  95.         <EditableName
    
  96.           allowWhiteSpace={true}
    
  97.           autoFocus={key > 0}
    
  98.           className={[styles.EditableName, isInvalid && styles.Invalid].join(
    
  99.             ' ',
    
  100.           )}
    
  101.           initialValue=""
    
  102.           overrideName={overrideName}
    
  103.           path={path}
    
  104.         />
    
  105.       </div>
    
  106.     </div>
    
  107.   );
    
  108. }