import React, { useRef, useLayoutEffect } from 'react'; import { StyleSheet, Platform, StyleProp, ViewStyle } from 'react-native'; import { WebView, WebViewMessageEvent } from 'react-native-webview'; import PlotlyBasic from './lib/PlotlyBasic'; import PlotlyFull from './lib/PlotlyFull'; /* Base 64 encode source code Postmessage source code into webview Webview decodes and evals Plotly is now in the webview! */ const messages = { CHART_LOADED: 'CHART_LOADED', }; const errorHandlerFn = ` window.onerror = function(message, source, lineno, colno, error) { document.getElementById('error').innerHTML += message + '\\n'; }; `; // eslint-disable-next-line @typescript-eslint/no-explicit-any type Data = any; // eslint-disable-next-line @typescript-eslint/no-explicit-any type Layout = any; // eslint-disable-next-line @typescript-eslint/no-explicit-any type Config = any; type UpdateProps = { data: Data[]; layout: Layout | undefined; config: Config | undefined; }; type UpdateFunctions = { react: (data: Data[], layout?: Layout, config?: Config) => void; relayout: (layout: Layout) => void; restyle: (data: Data, index: number) => void; }; export interface PlotlyProps { data: Data[]; layout?: Layout; config?: Config; update?: ( currentProps: UpdateProps, nextProps: UpdateProps, updateFns: UpdateFunctions ) => void; debug?: boolean; style?: StyleProp; onLoad?: () => void; enableFullPlotly?: boolean; } const Plotly: React.FC = (props) => { const lastPropsRef = useRef(props); const chart = useRef(null); const loadedRef = useRef(false); // As of 2/5/2019 it seems that using a # in the html causes the css // parsing to crash on Android const html = `

      

    
    
    
    `;

  const invoke = (str: string) => {
    if (chart && chart.current)
      chart.current.injectJavaScript(`(function(){${str}})()`);
  };

  const invokeEncoded = (str: string) => {
    invoke(`eval(atob("${str}"));`);
  };

  // Can uncomment and call for debugging purposes
  // const debug = (msg: string) => {
  //   invoke(`document.getElementById('debug').innerHTML += \`${msg}\` + '\\n';`);
  // };

  const initialPlot = (data: Data[], layout?: Layout, config?: Config) => {
    invoke(`
        window.Plotly.newPlot(
          'chart',
          ${JSON.stringify(data)},
          ${JSON.stringify(layout)},
          ${JSON.stringify(config)}
        ).then(function() {
          window.ReactNativeWebView.postMessage('${messages.CHART_LOADED}');
        });
      `);
  };

  const plotlyReact = (data: Data[], layout?: Layout, config?: Config) => {
    invoke(`
        window.Plotly.react(
          'chart',
          ${JSON.stringify(data)},
          ${JSON.stringify(layout)},
          ${JSON.stringify(config)}
        );
      `);
  };

  const plotlyRelayout = (layout: Layout) => {
    invoke(`
        window.Plotly.relayout(
          'chart',
          ${JSON.stringify(layout)}
        );
      `);
  };

  const plotlyRestyle = (data: Data, i: number) => {
    invoke(`
        window.Plotly.restyle(
          'chart',
          ${JSON.stringify(data)},
          ${i}
        );
      `);
  };

  const webviewLoaded = () => {
    if (Platform.OS === 'android') {
      // On iOS this is included in a