<commit_before>// @flow

import React, { Fragment, useCallback, useContext, useMemo } from 'react';
import { ElementTypeClass, ElementTypeFunction } from 'src/devtools/types';
import { createRegExp } from './utils';
import { TreeContext } from './TreeContext';

import type { Element } from '../types';

import styles from './Element.css';

type Props = {
  index: number,
  style: Object,
};

export default function ElementView({ index, style }: Props) {
  const {
    baseDepth,
    getElementAtIndex,
    selectOwner,
    selectedElementID,
    selectElementByID,
  } = useContext(TreeContext);

  const element = getElementAtIndex(index);

  if (element == null) {
    console.warn(`<ElementView> Could not find element at index ${index}`);
    return null;
  }

  const { depth, displayName, id, key, type } = ((element: any): Element);

  const handleDoubleClick = useCallback(() => selectOwner(id), [id]);

  // TODO Add click and key handlers for toggling element open/close state.

  const handleClick = useCallback(
    ({ metaKey }) => selectElementByID(metaKey ? null : id),
    [id]
  );

  const isSelected = selectedElementID === id;
  const showDollarR =
    isSelected && (type === ElementTypeClass || type === ElementTypeFunction);

  // TODO styles.SelectedElement is 100% width but it doesn't take horizontal overflow into account.

  return (
    <div
      className={isSelected ? styles.SelectedElement : styles.Element}
      onClick={handleClick}
      onDoubleClick={handleDoubleClick}
      style={{
        ...style, // "style" comes from react-window
        paddingLeft: `${(depth - baseDepth) * 0.75 + 0.25}rem`,
      }}
    >
      <span className={styles.Component}>
        <DisplayName displayName={displayName} id={id} />
        {key && (
          <Fragment>
            &nbsp;<span className={styles.AttributeName}>key</span>=
            <span className={styles.AttributeValue}>"{key}"</span>
          </Fragment>
        )}
      </span>
      {showDollarR && <span className={styles.DollarR}>&nbsp;== $r</span>}
    </div>
  );
}

type DisplayNameProps = {|
  displayName: string | null,
  id: number,
|};<commit_msg>Scroll to newly selected component if it's out of view<commit_after>// @flow

import React, {
  Fragment,
  useCallback,
  useContext,
  useMemo,
  useRef,
  useEffect,
} from 'react';
import { ElementTypeClass, ElementTypeFunction } from 'src/devtools/types';
import { createRegExp } from './utils';
import { TreeContext } from './TreeContext';

import type { Element } from '../types';

import styles from './Element.css';

type Props = {
  index: number,
  style: Object,
};

export default function ElementView({ index, style }: Props) {
  const {
    baseDepth,
    getElementAtIndex,
    selectOwner,
    selectedElementID,
    selectElementByID,
  } = useContext(TreeContext);

  const element = getElementAtIndex(index);

  if (element == null) {
    console.warn(`<ElementView> Could not find element at index ${index}`);
    return null;
  }

  const { depth, displayName, id, key, type } = ((element: any): Element);

  const handleDoubleClick = useCallback(() => selectOwner(id), [id]);

  // TODO Add click and key handlers for toggling element open/close state.

  const handleClick = useCallback(
    ({ metaKey }) => selectElementByID(metaKey ? null : id),
    [id]
  );

  const isSelected = selectedElementID === id;
  const showDollarR =
    isSelected && (type === ElementTypeClass || type === ElementTypeFunction);

  const component = useRef(null);
  useEffect(() => {
    if (isSelected && component.current !== null) {
      component.current.scrollIntoView();
    }
  }, [isSelected]);

  // TODO styles.SelectedElement is 100% width but it doesn't take horizontal overflow into account.

  return (
    <div
      className={isSelected ? styles.SelectedElement : styles.Element}
      onClick={handleClick}
      onDoubleClick={handleDoubleClick}
      style={{
        ...style, // "style" comes from react-window
        paddingLeft: `${(depth - baseDepth) * 0.75 + 0.25}rem`,
      }}
    >
      <span ref={component} className={styles.Component}>
        <DisplayName displayName={displayName} id={id} />
        {key && (
          <Fragment>
            &nbsp;<span className={styles.AttributeName}>key</span>=
            <span className={styles.AttributeValue}>"{key}"</span>
          </Fragment>
        )}
      </span>
      {showDollarR && <span className={styles.DollarR}>&nbsp;== $r</span>}
    </div>
  );
}

type DisplayNameProps = {|
  displayName: string | null,
  id: number,
|};
{'fraction_non_alphanumeric': 0.14123801220575413, 'fraction_numerical': 0.003923278116826504, 'mean_word_length': 3.2062328139321723, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5603927', 'n_tokens_mistral': 1372, 'n_tokens_neox': 1331, 'n_words': 358}