<commit_before>/* @flow */
/* eslint class-methods-use-this: 0 */
import React from "react";
import { cloneDeep } from "lodash";

type Props = {
  data: string | Object,
  mediaType: "application/vnd.plotly.v1+json"
};

declare class PlotlyHTMLElement extends HTMLElement {
  data: Object;
  layout: Object;
  newPlot: () => void;
  redraw: () => void;
}

const NULL_MIMETYPE = "text/vnd.plotly.v1+html";
const MIMETYPE = "application/vnd.plotly.v1+json";

/*
 * As part of the init notebook mode, Plotly sneaks a <script> tag in to load
 * the plotlyjs lib. We have already loaded this though, so we "handle" the
 * transform by doing nothing and returning null.
 */
const PlotlyNullTransform = () => null;
PlotlyNullTransform.MIMETYPE = NULL_MIMETYPE;
PlotlyNullTransform.defaultProps = {
  mediaType: NULL_MIMETYPE
};

export class PlotlyTransform extends React.Component<Props> {
  plotDiv: ?PlotlyHTMLElement;
  Plotly: Object;

  static MIMETYPE = MIMETYPE;

  static defaultProps = {
    mediaType: MIMETYPE
  };

  componentDidMount(): void {
    // Handle case of either string to be `JSON.parse`d or pure object
    const figure = this.getFigure();
    this.Plotly = require("@nteract/plotly");
    this.Plotly.newPlot(this.plotDiv, figure.data, figure.layout);
  }

  shouldComponentUpdate(nextProps: Props): boolean {
    return this.props.data !== nextProps.data;
  }

  componentDidUpdate() {
    const figure = this.getFigure();
    if (!this.plotDiv) return;
    this.plotDiv.data = figure.data;
    this.plotDiv.layout = figure.layout;
    this.Plotly.redraw(this.plotDiv);
  }

  plotDivRef = (plotDiv: PlotlyHTMLElement | null): void => {
    this.plotDiv = plotDiv;
  };

  getFigure = (): Object => {
    const figure = this.props.data;
    if (typeof figure === "string") {
      return JSON.parse(figure);
    }

    // The Plotly API *mutates* the figure to include a UID, which means
    // they won't take our frozen objects
    if (Object.isFrozen(figure)) {
      return cloneDeep(figure);
    }

    const { data = {}, layout = {} } = figure;

    return { data, layout };
  };

  render(): ?React$Element<any> {
    const { layout } = this.getFigure();
    const style = {};
    if (layout && layout.height && !layout.autosize) {
      style.height = layout.height;
    }
    // $FlowFixMe: a normal div doesn't have the properties that plotly puts on it
    return <div ref={this.plotDivRef} style={style} />;
  }
}

export { PlotlyNullTransform };
export default PlotlyTransform;
<commit_msg>Update types on React component<commit_after>/* eslint class-methods-use-this: 0 */
import React from "react";
import { cloneDeep } from "lodash";

type Props = {
  data: string | object,
  mediaType: "application/vnd.plotly.v1+json"
};


type ObjectType = object;

interface FigureLayout extends ObjectType {
  height?: string,
  autosize?: boolean,
}

interface Figure extends ObjectType {
  data: object,
  layout: FigureLayout,
}

declare class PlotlyHTMLElement extends HTMLDivElement {
  data: object;
  layout: object;
  newPlot: () => void;
  redraw: () => void;
}

const NULL_MIMETYPE = "text/vnd.plotly.v1+html";
const MIMETYPE = "application/vnd.plotly.v1+json";

/*
 * As part of the init notebook mode, Plotly sneaks a <script> tag in to load
 * the plotlyjs lib. We have already loaded this though, so we "handle" the
 * transform by doing nothing and returning null.
 */
const PlotlyNullTransform = () => null;
PlotlyNullTransform.MIMETYPE = NULL_MIMETYPE;
PlotlyNullTransform.defaultProps = {
  mediaType: NULL_MIMETYPE
};

export class PlotlyTransform extends React.Component<Props> {
  plotDiv?: PlotlyHTMLElement | null;
  Plotly!: { newPlot: Function, redraw: Function };

  static MIMETYPE = MIMETYPE;

  static defaultProps = {
    mediaType: MIMETYPE
  };

  componentDidMount(): void {
    // Handle case of either string to be `JSON.parse`d or pure object
    const figure = this.getFigure();
    this.Plotly = require("@nteract/plotly");
    this.Plotly.newPlot(this.plotDiv, figure.data, figure.layout);
  }

  shouldComponentUpdate(nextProps: Props): boolean {
    return this.props.data !== nextProps.data;
  }

  componentDidUpdate() {
    const figure = this.getFigure();
    if (!this.plotDiv) return;
    this.plotDiv.data = figure.data;
    this.plotDiv.layout = figure.layout;
    this.Plotly.redraw(this.plotDiv);
  }

  plotDivRef = (plotDiv: PlotlyHTMLElement | null): void => {
    this.plotDiv = plotDiv;
  };

  getFigure = (): Figure => {
    const figure = this.props.data;
    if (typeof figure === "string") {
      return JSON.parse(figure);
    }

    // The Plotly API *mutates* the figure to include a UID, which means
    // they won't take our frozen objects
    if (Object.isFrozen(figure)) {
      return cloneDeep(figure) as Figure;
    }

    const { data = {}, layout = {} } = figure as Figure;

    return { data, layout };
  };

  render() {
    const { layout } = this.getFigure();
    const style: React.CSSProperties = {};
    if (layout && layout.height && !layout.autosize) {
      style.height = layout.height;
    }
    // $FlowFixMe: a normal div doesn't have the properties that plotly puts on it
    return <div ref={this.plotDivRef} style={style} />;
  }
}

export { PlotlyNullTransform };
export default PlotlyTransform;

{'fraction_non_alphanumeric': 0.12474129821260584, 'fraction_numerical': 0.0015051740357478834, 'mean_word_length': 3.459731543624161, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 20, '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': '3505615', 'n_tokens_mistral': 1729, 'n_tokens_neox': 1697, 'n_words': 468}