<NME> react_interop.dart
<BEF> // ignore_for_file: deprecated_member_use_from_same_package
/// JS interop classes for main React JS APIs and react-dart internals.
///
/// For use in `react_client.dart` and by advanced react-dart users.

// ignore_for_file: deprecated_member_use_from_same_package

@JS()
library react_client.react_interop;

import 'dart:html';

import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'package:meta/meta.dart';
import 'package:react/hooks.dart';
import 'package:react/react.dart';
import 'package:react/react_client.dart' show ComponentFactory;
import 'package:react/react_client/bridge.dart';
import 'package:react/react_client/js_backed_map.dart';
import 'package:react/react_client/component_factory.dart'
    show ReactDartWrappedComponentFactoryProxy, ReactDartFunctionComponentFactoryProxy, ReactJsComponentFactoryProxy;
import 'package:react/react_client/js_interop_helpers.dart';
import 'package:react/react_client/zone.dart';
import 'package:react/src/js_interop_util.dart';
import 'package:react/src/react_client/dart2_interop_workaround_bindings.dart';

typedef ReactElement ReactJsComponentFactory(props, children);
typedef dynamic JsPropValidator(
    JsMap props, String propName, String componentName, String location, String propFullName, String secret);

// ----------------------------------------------------------------------------
//   Top-level API
// ----------------------------------------------------------------------------

@JS()
abstract class React {
  external static String get version;
  external static ReactElement cloneElement(ReactElement element, [JsMap props, dynamic children]);
  external static ReactContext createContext([
    dynamic defaultValue,
    int Function(dynamic currentValue, dynamic nextValue) calculateChangedBits,
  ]);
  @Deprecated('7.0.0')
  external static ReactClass createClass(ReactClassConfig reactClassConfig);
  @Deprecated('7.0.0')
  external static ReactJsComponentFactory createFactory(type);
  external static ReactElement createElement(dynamic type, props, [dynamic children]);
  external static JsRef createRef();
  external static ReactClass forwardRef(Function(JsMap props, dynamic ref) wrapperFunction);
  external static ReactClass memo(
    dynamic wrapperFunction, [
    bool Function(JsMap prevProps, JsMap nextProps) areEqual,
  ]);

  external static bool isValidElement(dynamic object);
///     }
///
/// Learn more: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
Ref<CurrentType> createRef<CurrentType>() {
  return new Ref<CurrentType>();
}

/// When this is provided as the ref prop, a reference to the rendered component
/// will be available via [current].
///
/// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
class Ref<CurrentType> {
  /// A JavaScript ref object returned by [React.createRef].
  JsRef jsRef;

  Ref() {
    jsRef = React.createRef();
  }

  /// A reference to the latest instance of the rendered component.
  ///
  /// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
  CurrentType get current {
    final jsCurrent = jsRef.current;

    if (jsCurrent is! Element) {
      final dartCurrent = (jsCurrent as ReactComponent)?.dartComponent;

      if (dartCurrent != null) {
        return dartCurrent as CurrentType;
      }
    }
    return jsCurrent;
  }
}

@JS()
@anonymous
class JsRef {

  Ref() : jsRef = React.createRef();

  /// Constructor for [useRef], calls [React.useRef] to initialize [current] to [initialValue].
  ///
  /// See: <https://reactjs.org/docs/hooks-reference.html#useref>.
  Ref.useRefInit(T initialValue) : jsRef = React.useRef(initialValue);

  Ref.fromJs(this.jsRef);

  /// A reference to the latest instance of the rendered component.
  ///
  /// See [createRef] for usage examples and more info.
  T get current {
    final jsCurrent = jsRef.current;

    // Note: this ReactComponent check will pass for many types of JS objects,
    // so don't assume for sure that it's a ReactComponent
    if (jsCurrent is! Element && jsCurrent is ReactComponent) {
      final dartCurrent = jsCurrent.dartComponent;

      if (dartCurrent != null) {
        return dartCurrent as T;
      }
    }
    return jsCurrent;
  }

  /// Sets the value of [current].
  ///
  /// See: <https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables>.
  set current(T value) {
    if (value is Component) {
      jsRef.current = value.jsThis;
    } else {
      jsRef.current = value;
    }
  }
}

/// A JS ref object returned by [React.createRef].
///
/// Dart factories will automatically unwrap [Ref] objects to this JS representation,
/// so using this class directly shouldn't be necessary.
@JS()
@anonymous
class JsRef {
  external dynamic get current;
  external set current(dynamic value);
}

/// Automatically passes a [Ref] through a component to one of its children.
///
/// __Example 1:__ Forwarding refs to DOM components
///
/// _[Analogous JS Demo](https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components)_
///
/// ```dart
/// import 'dart:html';
/// import 'package:react/react.dart' as react;
///
/// // ---------- Component Definition ----------
/// final FancyButton = react.forwardRef2((props, ref) {
///   return react.button({'ref': ref, 'className': 'FancyButton'}, 'Click me!');
/// }, displayName: 'FancyButton');
///
/// // ---------- Component Consumption ----------
/// void main() {
///   final ref = createRef<Element>();
///
///   react_dom.render(FancyButton({'ref': ref}));
///
///   // You can now get a ref directly to the DOM button:
///   final buttonNode = ref.current;
/// }
/// ```
///
/// __Example 2:__ Forwarding refs in higher-order components
///
/// _[Analogous JS Demo](https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-in-higher-order-components)_
///
/// ```dart
/// import 'dart:html';
/// import 'package:react/react.dart' as react;
/// import 'package:react/react_client.dart' show setClientConfiguration, ReactJsComponentFactoryProxy;
/// import 'package:react/react_dom.dart' as react_dom;
///
/// // ---------- Component Definitions ----------
///
/// final FancyButton = react.forwardRef2((props, ref) {
///   return react.button({'ref': ref, 'className': 'FancyButton'}, 'Click me!');
/// }, displayName: 'FancyButton');
///
/// class _LogProps extends react.Component2 {
///   @override
///   void componentDidUpdate(Map prevProps, _, [__]) {
///     print('old props: $prevProps');
///     print('new props: ${this.props}');
///   }
///
///   @override
///   render() {
///     final propsToForward = {...props}..remove('forwardedRef');
///
///     // Assign the custom prop `forwardedRef` as a ref on the component passed in via `props.component`
///     return props['component']({...propsToForward, 'ref': props['forwardedRef']}, props['children']);
///   }
/// }
/// final _logPropsHoc = react.registerComponent2(() => _LogProps());
///
/// final LogProps = react.forwardRef2((props, ref) {
///   // Note the second param "ref" provided by react.forwardRef2.
///   // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"
///   // And it can then be attached to the Component.
///   return _logPropsHoc({...props, 'forwardedRef': ref});
///   // Optional: Make the displayName more useful for the React dev tools.
///   // See: https://reactjs.org/docs/forwarding-refs.html#displaying-a-custom-name-in-devtools
/// }, displayName: 'LogProps(${_logPropsHoc.type.displayName})');
///
/// // ---------- Component Consumption ----------
/// void main() {
///   setClientConfiguration();
///   final ref = react.createRef<Element>();
///
///   react_dom.render(LogProps({'component': FancyButton, 'ref': ref}),
///       querySelector('#idOfSomeNodeInTheDom'));
///
///   // You can still get a ref directly to the DOM button:
///   final buttonNode = ref.current;
/// }
/// ```
/// See: <https://reactjs.org/docs/forwarding-refs.html>.
ReactComponentFactoryProxy forwardRef2(
  DartForwardRefFunctionComponent wrapperFunction, {
  String displayName,
}) =>
    ReactDartWrappedComponentFactoryProxy.forwardRef(wrapperFunction, displayName: displayName);

@Deprecated('Use forwardRef2')
ReactJsComponentFactoryProxy forwardRef(
  Function(Map props, Ref ref) wrapperFunction, {
  String displayName = 'Anonymous',
}) {
  final wrappedComponent = allowInterop((JsMap props, JsRef ref) => componentZone.run(() {
        final dartProps = JsBackedMap.backedBy(props);
        for (var value in dartProps.values) {
          if (value is Function) {
            // Tag functions that came straight from the JS
            // so that we know to pass them through as-is during prop conversion.
            isRawJsFunctionFromProps[value] = true;
          }
        }

        final dartRef = Ref.fromJs(ref);
        return wrapperFunction(dartProps, dartRef);
      }));
  defineProperty(wrappedComponent, 'displayName', JsPropertyDescriptor(value: displayName));

  var hoc = React.forwardRef(wrappedComponent);
  // ignore: invalid_use_of_protected_member
  setProperty(hoc, 'dartComponentVersion', ReactDartComponentVersion.component2);

  return ReactJsComponentFactoryProxy(hoc, alwaysReturnChildrenAsList: true);
}

/// A [higher order component](https://reactjs.org/docs/higher-order-components.html) for function components
/// that behaves similar to the way [`React.PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent)
/// does for class-based components.
///
/// If your function component renders the same result given the same props, you can wrap it in a call to
/// `memo` for a performance boost in some cases by memoizing the result. This means that React will skip
/// rendering the component, and reuse the last rendered result.
///
/// ```dart
/// import 'package:react/react.dart' as react;
///
/// final MyComponent = react.memo2(react.registerFunctionComponent((props) {
///   /* render using props */
/// }));
/// ```
///
/// `memo2` only affects props changes. If your function component wrapped in `memo2` has a
/// [useState] or [useContext] Hook in its implementation, it will still rerender when `state` or `context` change.
///
/// By default it will only shallowly compare complex objects in the props map.
/// If you want control over the comparison, you can also provide a custom comparison
/// function to the [areEqual] argument as shown in the example below.
///
/// ```dart
/// import 'package:react/react.dart' as react;
///
/// final MyComponent = react.memo2(react.registerFunctionComponent((props) {
///   // render using props
/// }), areEqual: (prevProps, nextProps) {
///   // Do some custom comparison logic to return a bool based on prevProps / nextProps
/// });
/// ```
///
/// > __This method only exists as a performance optimization.__
/// >
/// > Do not rely on it to “prevent” a render, as this can lead to bugs.
///
/// See: <https://reactjs.org/docs/react-api.html#reactmemo>.
ReactComponentFactoryProxy memo2(ReactComponentFactoryProxy factory,
    {bool Function(Map prevProps, Map nextProps) areEqual}) {
  final _areEqual = areEqual == null
      ? null
      : allowInterop((JsMap prevProps, JsMap nextProps) {
          final dartPrevProps = JsBackedMap.backedBy(prevProps);
          final dartNextProps = JsBackedMap.backedBy(nextProps);
          return areEqual(dartPrevProps, dartNextProps);
        });
  final hoc = React.memo(factory.type, _areEqual);
  setProperty(hoc, 'dartComponentVersion', ReactDartComponentVersion.component2);

  return ReactDartWrappedComponentFactoryProxy(hoc);
}

@Deprecated('Use memo2')
ReactJsComponentFactoryProxy memo(ReactDartFunctionComponentFactoryProxy factory,
    {bool Function(Map prevProps, Map nextProps) areEqual}) {
  final _areEqual = areEqual == null
      ? null
      : allowInterop((JsMap prevProps, JsMap nextProps) {
          final dartPrevProps = JsBackedMap.backedBy(prevProps);
          final dartNextProps = JsBackedMap.backedBy(nextProps);
          return areEqual(dartPrevProps, dartNextProps);
        });
  final hoc = React.memo(factory.type, _areEqual);
  setProperty(hoc, 'dartComponentVersion', ReactDartComponentVersion.component2);

  return ReactJsComponentFactoryProxy(hoc, alwaysReturnChildrenAsList: true);
}

abstract class ReactDom {
  static Element findDOMNode(object) => ReactDOM.findDOMNode(object);
  static ReactComponent render(ReactElement component, Element element) => ReactDOM.render(component, element);
  static bool unmountComponentAtNode(Element element) => ReactDOM.unmountComponentAtNode(element);

  /// Returns a a portal that renders [children] into a [container].
  ///
  /// Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
  ///
  /// [children] can be any renderable React child, such as a [ReactElement], [String], or fragment.
  ///
  /// See: <https://reactjs.org/docs/portals.html>
  static ReactPortal createPortal(dynamic children, Element container) => ReactDOM.createPortal(children, container);
}

@JS('ReactDOMServer')
abstract class ReactDomServer {
  external static String renderToString(ReactElement component);
  external static String renderToStaticMarkup(ReactElement component);
}

/// Runtime type checking for React props and similar objects.
///
/// See: <https://reactjs.org/docs/typechecking-with-proptypes.html>
/// See: <https://www.npmjs.com/package/prop-types>
@JS('React.PropTypes')
abstract class PropTypes {
  /// PropTypes.checkPropTypes(...) only console.error(...)s a given message once.
  /// To reset the cache while testing call PropTypes.resetWarningCache()
  ///
  /// See: <https://www.npmjs.com/package/prop-types#proptypesresetwarningcache>
  external static resetWarningCache();
}

// ----------------------------------------------------------------------------
//   Types and data structures
// ----------------------------------------------------------------------------

/// A React class specification returned by `React.createClass`.
///
/// To be used as the value of [ReactElement.type], which is set upon initialization
/// by a component factory or by [React.createElement].
///
/// See: <http://facebook.github.io/react/docs/top-level-api.html#react.createclass>
@JS()
@anonymous
class ReactClass {
  /// The cached, unmodifiable copy of [Component2.defaultProps] computed in
  /// [registerComponent2].
  ///
  /// For use in `ReactDartComponentFactoryProxy2` when creating new [ReactElement]s,
  /// or for external use involving inspection of Dart prop defaults.
  external JsMap get defaultProps;
  external set defaultProps(JsMap value);

  /// The `displayName` string is used in debugging messages.
  ///
  /// See: <http://facebook.github.io/react/docs/component-specs.html#displayname>
  external String get displayName;
  external set displayName(String value);

  /// The cached, unmodifiable copy of [Component.getDefaultProps] computed in
  /// [registerComponent].
  ///
  /// For use in [ReactDartComponentFactoryProxy] when creating new [ReactElement]s,
  /// or for external use involving inspection of Dart prop defaults.
  @Deprecated('7.0.0`')
  external Map get dartDefaultProps;
  @Deprecated('7.0.0`')
  external set dartDefaultProps(Map value);

  /// A string to distinguish between different Dart component implementations / base classes.
  ///
  /// See [ReactDartComponentVersion] for values.
  ///
  /// __For internal use only.__
  @protected
  external String get dartComponentVersion;
  @protected
  external set dartComponentVersion(String value);
}

/// Constants for use with [ReactClass.dartComponentVersion] to distinguish
/// different versions of Dart component implementations / base classes.
///
/// __For internal use only.__
@protected
@sealed
abstract class ReactDartComponentVersion {
  /// A [Component]-based component.
  @protected
  static const String component = '1';

  /// A [Component2]-based component.
  @protected
  static const String component2 = '2';

  /// Returns [ReactClass.dartComponentVersion] if [type] is the [ReactClass] for a Dart component
  /// (a react-dart [ReactElement] or [ReactComponent]), and null otherwise.
  @protected
  static String fromType(dynamic type) {
    // This check doesn't do much since ReactClass is an anonymous JS object,
    // but it lets us safely cast to ReactClass.
    if (type is ReactClass) {
      return type.dartComponentVersion;
    }
    if (type is Function) {
      return getProperty(type, 'dartComponentVersion');
    }

    return null;
  }
}

/// A JS interop class used as an argument to [React.createClass].
///
/// See: <http://facebook.github.io/react/docs/top-level-api.html#react.createclass>.
///
/// > __DEPRECATED.__
/// >
/// > Will be removed alongside [React.createClass] in the `7.0.0` release.
@Deprecated('7.0.0')
@JS()
@anonymous
class ReactClassConfig {
  external factory ReactClassConfig({
    String displayName,
    List mixins,
    Function componentWillMount,
    Function componentDidMount,
    Function componentWillReceiveProps,
    Function shouldComponentUpdate,
    Function componentWillUpdate,
    Function componentDidUpdate,
    Function componentWillUnmount,
    Function getChildContext,
    Map<String, dynamic> childContextTypes,
    Function getDefaultProps,
    Function getInitialState,
    Function render,
  });

  /// The `displayName` string is used in debugging messages.
  ///
  /// See: <http://facebook.github.io/react/docs/component-specs.html#displayname>
  external String get displayName;
  external set displayName(String value);
}

/// Interop class for the data structure at `ReactElement._store`.
///
/// Used to validate variadic children before they get to [React.createElement].
@JS()
@anonymous
class ReactElementStore {
  external bool get validated;
  external set validated(bool value);
}

/// A virtual DOM element representing an instance of a DOM element,
/// React component, or fragment.
///
/// React elements are the building blocks of React applications.
/// One might confuse elements with a more widely known concept of "components".
/// An element describes what you want to see on the screen. React elements are immutable.
///
/// Typically, elements are not used directly, but get returned from components.
///
/// These can be created directly by [React.createElement], or by invoking
/// React element DOM/component factories.
///
///     react.h1({}, 'Content here');
///     MaterialButton({}, 'Click me');
///
/// See <https://reactjs.org/docs/glossary.html#elements>
/// and <https://reactjs.org/docs/glossary.html#components>.
@JS()
@anonymous
class ReactElement {
  external ReactElementStore get _store; // ignore: unused_element

  /// The type of this element.
  ///
  /// For DOM components, this will be a [String] tagName (e.g., `'div'`, `'a'`).
  ///
  /// For composite components (react-dart or pure JS), this will be a [ReactClass].
  external dynamic get type;

  /// The props this element was created with.
  external InteropProps get props;

  /// This element's `key`, which is used to uniquely identify it among its siblings.
  ///
  /// Not needed when children are passed variadically
  /// (as arguments to a factory, as opposed to items within a list/iterable).
  ///
  /// See: <https://reactjs.org/docs/reconciliation.html#keys>.
  external String get key;

  /// This element's `ref`, which can be used to access the associated
  /// [Component]/[ReactComponent]/[Element] after it has been rendered.
  ///
  /// See: <https://reactjs.org/docs/refs-and-the-dom.html>.
  external dynamic get ref;
}

/// A virtual DOM node representing a React Portal, returned by [ReactDom.createPortal].
///
/// Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
///
/// Children can be any renderable React child, such as an element, string, or fragment.
///
/// While closely related, portals are not [ReactElement]s.
///
/// See: <https://reactjs.org/docs/portals.html>
@JS()
@anonymous
class ReactPortal {
  external dynamic /* ReactNodeList */ get children;
  external dynamic get containerInfo;
}

/// The JavaScript component instance, which backs each react-dart [Component].
///
/// See: <http://facebook.github.io/react/docs/glossary.html#react-components>
@JS()
@anonymous
class ReactComponent {
  // TODO: Cast as Component2 in 7.0.0
  external Component get dartComponent;
  // TODO how to make this JsMap without breaking stuff?
  external InteropProps get props;
  external dynamic get context;
  external JsMap get state;
  external set state(JsMap value);
  external get refs;
  external void setState(state, [callback]);
  external void forceUpdate([callback]);
}

// ----------------------------------------------------------------------------
//   Interop internals
// ----------------------------------------------------------------------------

/// A JavaScript interop class representing a value in a React JS `context` object.
///
/// Used for storing/accessing Dart [ReactDartContextInternal] objects in `context`
/// in a way that's opaque to the JS, and avoids the need to use dart2js interceptors.
///
/// __For internal/advanced use only.__
///
/// > __DEPRECATED - DO NOT USE__
/// >
/// > This API was never stable in any version of ReactJS, and was replaced with a new, incompatible context API
/// > in ReactJS 16 that is exposed via the [Component2] class.
/// >
/// > This will be completely removed when the JS side of it is slated for removal (ReactJS 18 / react.dart 7.0.0)
@Deprecated('7.0.0')
@JS()
@anonymous
class InteropContextValue {
  external factory InteropContextValue();
}

/// A JavaScript interop class representing the return value of `createContext`.
///
/// Used for accessing Dart [Context.Provider] & [Context.Consumer] components.
///
/// __For internal/advanced use only.__
@JS()
@anonymous
class ReactContext {
  external ReactClass get Provider;
  external ReactClass get Consumer;
}

/// A JavaScript interop class representing a React JS `props` object.
///
/// Used for storing/accessing [ReactDartComponentInternal] objects in
/// react-dart [ReactElement]s and [ReactComponent]s, as well as for preparing
/// reserved props (`key` and `ref`) for consumption by ReactJS.
///
/// __For internal/advanced use only.__
@JS()
@anonymous
class InteropProps implements JsMap {
  /// __Deprecated.__
  ///
  /// This has been deprecated along with `Component` since its
  /// replacement - `Component2` utilizes JS Maps for props,
  /// making `internal` obsolete.
  ///
  /// Will be removed alongside `Component` in the `7.0.0` release.
  @Deprecated('7.0.0')
  external ReactDartComponentInternal get internal;
  external dynamic get key;
  external dynamic get ref;

  external set key(dynamic value);
  external set ref(dynamic value);

  /// __Deprecated.__
  ///
  /// This has been deprecated along with `Component` since its
  /// replacement - `Component2` utilizes JS Maps for props,
  /// making `InteropProps` obsolete.
  ///
  /// Will be removed alongside `Component` in the `7.0.0` release.
  @Deprecated('7.0.0')
  external factory InteropProps({
    ReactDartComponentInternal internal,
    String key,
    dynamic ref,
  });
}

/// __Deprecated.__
///
/// This has been deprecated along with `Component` since its
/// replacement - `Component2` utilizes JS Maps for props,
/// making `InteropProps` obsolete.
///
/// Will be removed alongside `Component` in the `7.0.0` release.
///
/// > Internal react-dart information used to proxy React JS lifecycle to Dart
/// > [Component] instances.
/// >
/// > __For internal/advanced use only.__
@Deprecated('7.0.0')
class ReactDartComponentInternal {
  /// For a `ReactElement`, this is the initial props with defaults merged.
  ///
  /// For a `ReactComponent`, this is the props the component was last rendered with,
  /// and is used within props-related lifecycle internals.
  Map props;
}

/// Internal react-dart information used to proxy React JS lifecycle to Dart
/// [Component] instances.
///
/// __For internal/advanced use only.__
///
/// > __DEPRECATED - DO NOT USE__
/// >
/// > This API was never stable in any version of ReactJS, and was replaced with a new, incompatible context API
/// > in ReactJS 16 that is exposed via the [Component2] class.
/// >
/// > This will be completely removed when the JS side of it is slated for removal (ReactJS 18 / react.dart 7.0.0)
@Deprecated('7.0.0')
class ReactDartContextInternal {
  final dynamic value;

  ReactDartContextInternal(this.value);
}

/// Creates a new JS Error object with the provided message.
@JS('Error')
class JsError {
  external JsError(message);
}

/// A JS variable that can be used with Dart interop in order to force returning a JavaScript `null`.
/// Use this if dart2js is possibly converting Dart `null` into `undefined`.
@JS('_jsNull')
external get jsNull;

/// A JS variable that can be used with Dart interop in order to force returning a JavaScript `undefined`.
/// Use this if dart2js is possibly converting Dart `undefined` into `null`.
@JS('_jsUndefined')
external get jsUndefined;

/// Throws the error passed to it from Javascript.
/// This allows us to catch the error in dart which re-dartifies the js errors/exceptions.
@alwaysThrows
@JS('_throwErrorFromJS')
external void throwErrorFromJS(error);

/// Marks [child] as validated, as if it were passed into [React.createElement]
/// as a variadic child.
///
/// Offloaded to the JS to avoid dart2js interceptor lookup.
@JS('_markChildValidated')
external void markChildValidated(child);

/// Mark each child in [children] as validated so that React doesn't emit key warnings.
///
/// ___Only for use with variadic children.___
void markChildrenValidated(List<dynamic> children) {
  children.forEach((dynamic child) {
    // Use `isValidElement` since `is ReactElement` doesn't behave as expected.
    if (React.isValidElement(child)) {
      markChildValidated(child);
    }
  });
}

/// Returns a new JS [ReactClass] for a component that uses
/// [dartInteropStatics] and [componentStatics] internally to proxy between
/// the JS and Dart component instances.
///
/// > __DEPRECATED.__
/// >
/// > Will be removed in `7.0.0` alongside [Component].
@JS('_createReactDartComponentClass')
@Deprecated('7.0.0')
external ReactClass createReactDartComponentClass(
    ReactDartInteropStatics dartInteropStatics, ComponentStatics componentStatics,
    [JsComponentConfig jsConfig]);

/// Returns a new JS [ReactClass] for a component that uses
/// [dartInteropStatics] and [componentStatics] internally to proxy between
/// the JS and Dart component instances.
///
/// See `_ReactDartInteropStatics2.staticsForJs`]` for an example implementation.
@JS('_createReactDartComponentClass2')
external ReactClass createReactDartComponentClass2(JsMap dartInteropStatics, ComponentStatics2 componentStatics,
    [JsComponentConfig2 jsConfig]);

@JS('React.__isDevelopment')
external bool get _inReactDevMode;

/// Whether the "dev" build of react.js is being used.
///
/// Useful for creating conditional logic based on whether your application is being served in a production environment.
///
///     if (inReactDevMode) {
///       print('Debug info that only developers should see.');
///     }
///
/// > This value will be `true` if your HTML page includes `react.js` or `react_with_addons.js`,
///   and `false` if your HTML page includes `react_prod.js` or `react_with_react_dom_prod.js`.
bool get inReactDevMode => _inReactDevMode;

/// An object that stores static methods used by all Dart components.
///
/// __Deprecated.__
///
/// Will be removed when [Component] is removed in the `7.0.0` release.
@JS()
@anonymous
@Deprecated('7.0.0')
class ReactDartInteropStatics {
  external factory ReactDartInteropStatics({
    Component Function(
      ReactComponent jsThis,
      ReactDartComponentInternal internal,
      InteropContextValue context,
      ComponentStatics componentStatics,
    )
        initComponent,
    InteropContextValue Function(Component component) handleGetChildContext,
    void Function(Component component) handleComponentWillMount,
    void Function(Component component) handleComponentDidMount,
    void Function(
      Component component,
      ReactDartComponentInternal nextInternal,
      InteropContextValue nextContext,
    )
        handleComponentWillReceiveProps,
    bool Function(Component component, InteropContextValue nextContext) handleShouldComponentUpdate,
    void Function(Component component, InteropContextValue nextContext) handleComponentWillUpdate,
    void Function(Component component, ReactDartComponentInternal prevInternal) handleComponentDidUpdate,
    void Function(Component component) handleComponentWillUnmount,
    dynamic Function(Component component) handleRender,
  });
}

/// An object that stores static methods and information for a specific component class.
///
/// This object is made accessible to a component's JS ReactClass config, which
/// passes it to certain methods in [ReactDartInteropStatics].
///
/// See [ReactDartInteropStatics], [createReactDartComponentClass].
class ComponentStatics {
  final ComponentFactory<Component> componentFactory;
  ComponentStatics(this.componentFactory);
}

/// An object that stores static methods and information for a specific component class.
///
/// This object is made accessible to a component's JS ReactClass config, which
/// passes it to certain methods in [ReactDartInteropStatics2].
///
/// See [ReactDartInteropStatics2], [createReactDartComponentClass2].
class ComponentStatics2 {
  final ComponentFactory<Component2> componentFactory;
  final Component2 instanceForStaticMethods;
  final Component2BridgeFactory bridgeFactory;

  ComponentStatics2({
    @required this.componentFactory,
    @required this.instanceForStaticMethods,
    @required this.bridgeFactory,
  });
}

/// Additional configuration passed to [createReactDartComponentClass]
/// that needs to be directly accessible by that JS code.
///
/// > __DEPRECATED - DO NOT USE__
/// >
/// > The `context` API that this supports was never stable in any version of ReactJS,
/// > and was replaced with a new, incompatible context API in ReactJS 16 that is exposed
/// > via the [Component2] class and is supported by [JsComponentConfig2].
/// >
/// > This will be completely removed when the JS side of `context` it is slated for
/// > removal (ReactJS 18 / react.dart 7.0.0)
@Deprecated('7.0.0')
@JS()
@anonymous
class JsComponentConfig {
  external factory JsComponentConfig({
    Iterable<String> childContextKeys,
    Iterable<String> contextKeys,
  });
}

/// Additional configuration passed to [createReactDartComponentClass2]
/// that needs to be directly accessible by that JS code.
@JS()
@anonymous
class JsComponentConfig2 {
  external factory JsComponentConfig2({
    dynamic contextType,
    JsMap defaultProps,
    JsMap propTypes,
    @required List<String> skipMethods,
  });
}

/// Information on an error caught by `componentDidCatch`.
@JS()
@anonymous
class ReactErrorInfo {
  /// The component stack trace associated with this error.
  ///
  /// See: https://reactjs.org/docs/error-boundaries.html#component-stack-traces
  external String get componentStack;
  external set componentStack(String value);

  /// The dart stack trace associated with this error.
  external StackTrace get dartStackTrace;
  external set dartStackTrace(StackTrace);
}

<MSG> Update Ref constructor, clean up generics / doc comments

<DFF> @@ -57,39 +57,43 @@ abstract class React {
 ///     }
 ///
 /// Learn more: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
-Ref<CurrentType> createRef<CurrentType>() {
-  return new Ref<CurrentType>();
+Ref<T> createRef<T>() {
+  return new Ref<T>();
 }
 
 /// When this is provided as the ref prop, a reference to the rendered component
 /// will be available via [current].
 ///
-/// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
-class Ref<CurrentType> {
+/// See [createRef] for usage examples and more info.
+class Ref<T> {
   /// A JavaScript ref object returned by [React.createRef].
-  JsRef jsRef;
+  final JsRef jsRef;
 
-  Ref() {
-    jsRef = React.createRef();
-  }
+  Ref() : jsRef = React.createRef();
+
+  Ref.fromJs(this.jsRef);
 
   /// A reference to the latest instance of the rendered component.
   ///
-  /// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.
-  CurrentType get current {
+  /// See [createRef] for usage examples and more info.
+  T get current {
     final jsCurrent = jsRef.current;
 
     if (jsCurrent is! Element) {
       final dartCurrent = (jsCurrent as ReactComponent)?.dartComponent;
 
       if (dartCurrent != null) {
-        return dartCurrent as CurrentType;
+        return dartCurrent as T;
       }
     }
     return jsCurrent;
   }
 }
 
+/// A JS ref object returned by [React.createRef].
+///
+/// Dart factories will automatically unwrap [Ref] objects to this JS representation,
+/// so using this class directly shouldn't be necessary.
 @JS()
 @anonymous
 class JsRef {

{'commit': "diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart\nindex 5f698a7..f065a53 100644\n--- a/lib/react_client/react_interop.dart\n+++ b/lib/react_client/react_interop.dart\n@@ -57,39 +57,43 @@ abstract class React {\n ///     }\n ///\n /// Learn more: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-Ref<CurrentType> createRef<CurrentType>() {\n-  return new Ref<CurrentType>();\n+Ref<T> createRef<T>() {\n+  return new Ref<T>();\n }\n \n /// When this is provided as the ref prop, a reference to the rendered component\n /// will be available via [current].\n ///\n-/// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-class Ref<CurrentType> {\n+/// See [createRef] for usage examples and more info.\n+class Ref<T> {\n   /// A JavaScript ref object returned by [React.createRef].\n-  JsRef jsRef;\n+  final JsRef jsRef;\n \n-  Ref() {\n-    jsRef = React.createRef();\n-  }\n+  Ref() : jsRef = React.createRef();\n+\n+  Ref.fromJs(this.jsRef);\n \n   /// A reference to the latest instance of the rendered component.\n   ///\n-  /// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-  CurrentType get current {\n+  /// See [createRef] for usage examples and more info.\n+  T get current {\n     final jsCurrent = jsRef.current;\n \n     if (jsCurrent is! Element) {\n       final dartCurrent = (jsCurrent as ReactComponent)?.dartComponent;\n \n       if (dartCurrent != null) {\n-        return dartCurrent as CurrentType;\n+        return dartCurrent as T;\n       }\n     }\n     return jsCurrent;\n   }\n }\n \n+/// A JS ref object returned by [React.createRef].\n+///\n+/// Dart factories will automatically unwrap [Ref] objects to this JS representation,\n+/// so using this class directly shouldn't be necessary.\n @JS()\n @anonymous\n class JsRef {\n", 'commit_subject': 'Update Ref constructor, clean up generics / doc comments', 'repo_name': 'cleandart/react-dart', 'committer': {'name': 'Greg Littlefield', 'email': '23165e8c71b29c67aedf5c473221b1d823fa7538@workiva.com', 'time_sec': '1568846746', 'tz_offset': '-420', 'date': {'seconds': '1568846746'}}, 'commit_tree': 'bd5c594c5be9d7c77295f754dacea9e076479852', 'commit_message': 'Update Ref constructor, clean up generics / doc comments\n', 'language_name': 'Python', 'license': 'bsd-2-clause', 'hunks': "@@ -57,39 +57,43 @@ abstract class React {\n ///     }\n ///\n /// Learn more: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-Ref<CurrentType> createRef<CurrentType>() {\n-  return new Ref<CurrentType>();\n+Ref<T> createRef<T>() {\n+  return new Ref<T>();\n }\n \n /// When this is provided as the ref prop, a reference to the rendered component\n /// will be available via [current].\n ///\n-/// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-class Ref<CurrentType> {\n+/// See [createRef] for usage examples and more info.\n+class Ref<T> {\n   /// A JavaScript ref object returned by [React.createRef].\n-  JsRef jsRef;\n+  final JsRef jsRef;\n \n-  Ref() {\n-    jsRef = React.createRef();\n-  }\n+  Ref() : jsRef = React.createRef();\n+\n+  Ref.fromJs(this.jsRef);\n \n   /// A reference to the latest instance of the rendered component.\n   ///\n-  /// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n-  CurrentType get current {\n+  /// See [createRef] for usage examples and more info.\n+  T get current {\n     final jsCurrent = jsRef.current;\n \n     if (jsCurrent is! Element) {\n       final dartCurrent = (jsCurrent as ReactComponent)?.dartComponent;\n \n       if (dartCurrent != null) {\n-        return dartCurrent as CurrentType;\n+        return dartCurrent as T;\n       }\n     }\n     return jsCurrent;\n   }\n }\n \n+/// A JS ref object returned by [React.createRef].\n+///\n+/// Dart factories will automatically unwrap [Ref] objects to this JS representation,\n+/// so using this class directly shouldn't be necessary.\n @JS()\n @anonymous\n class JsRef {\n", 'addition_count': 15, 'deletion_count': 11, 'src_file': 'a/lib/react_client/react_interop.dart', 'tgt_file': 'b/lib/react_client/react_interop.dart', 'file_extension': '.dart', 'before_file': '// ignore_for_file: deprecated_member_use_from_same_package\n/// JS interop classes for main React JS APIs and react-dart internals.\n///\n/// For use in `react_client.dart` and by advanced react-dart users.\n\n// ignore_for_file: deprecated_member_use_from_same_package\n\n@JS()\nlibrary react_client.react_interop;\n\nimport \'dart:html\';\n\nimport \'package:js/js.dart\';\nimport \'package:js/js_util.dart\';\nimport \'package:meta/meta.dart\';\nimport \'package:react/hooks.dart\';\nimport \'package:react/react.dart\';\nimport \'package:react/react_client.dart\' show ComponentFactory;\nimport \'package:react/react_client/bridge.dart\';\nimport \'package:react/react_client/js_backed_map.dart\';\nimport \'package:react/react_client/component_factory.dart\'\n    show ReactDartWrappedComponentFactoryProxy, ReactDartFunctionComponentFactoryProxy, ReactJsComponentFactoryProxy;\nimport \'package:react/react_client/js_interop_helpers.dart\';\nimport \'package:react/react_client/zone.dart\';\nimport \'package:react/src/js_interop_util.dart\';\nimport \'package:react/src/react_client/dart2_interop_workaround_bindings.dart\';\n\ntypedef ReactElement ReactJsComponentFactory(props, children);\ntypedef dynamic JsPropValidator(\n    JsMap props, String propName, String componentName, String location, String propFullName, String secret);\n\n// ----------------------------------------------------------------------------\n//   Top-level API\n// ----------------------------------------------------------------------------\n\n@JS()\nabstract class React {\n  external static String get version;\n  external static ReactElement cloneElement(ReactElement element, [JsMap props, dynamic children]);\n  external static ReactContext createContext([\n    dynamic defaultValue,\n    int Function(dynamic currentValue, dynamic nextValue) calculateChangedBits,\n  ]);\n  @Deprecated(\'7.0.0\')\n  external static ReactClass createClass(ReactClassConfig reactClassConfig);\n  @Deprecated(\'7.0.0\')\n  external static ReactJsComponentFactory createFactory(type);\n  external static ReactElement createElement(dynamic type, props, [dynamic children]);\n  external static JsRef createRef();\n  external static ReactClass forwardRef(Function(JsMap props, dynamic ref) wrapperFunction);\n  external static ReactClass memo(\n    dynamic wrapperFunction, [\n    bool Function(JsMap prevProps, JsMap nextProps) areEqual,\n  ]);\n\n  external static bool isValidElement(dynamic object);\n///     }\n///\n/// Learn more: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\nRef<CurrentType> createRef<CurrentType>() {\n  return new Ref<CurrentType>();\n}\n\n/// When this is provided as the ref prop, a reference to the rendered component\n/// will be available via [current].\n///\n/// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\nclass Ref<CurrentType> {\n  /// A JavaScript ref object returned by [React.createRef].\n  JsRef jsRef;\n\n  Ref() {\n    jsRef = React.createRef();\n  }\n\n  /// A reference to the latest instance of the rendered component.\n  ///\n  /// See: <https://reactjs.org/docs/refs-and-the-dom.html#creating-refs>.\n  CurrentType get current {\n    final jsCurrent = jsRef.current;\n\n    if (jsCurrent is! Element) {\n      final dartCurrent = (jsCurrent as ReactComponent)?.dartComponent;\n\n      if (dartCurrent != null) {\n        return dartCurrent as CurrentType;\n      }\n    }\n    return jsCurrent;\n  }\n}\n\n@JS()\n@anonymous\nclass JsRef {\n\n  Ref() : jsRef = React.createRef();\n\n  /// Constructor for [useRef], calls [React.useRef] to initialize [current] to [initialValue].\n  ///\n  /// See: <https://reactjs.org/docs/hooks-reference.html#useref>.\n  Ref.useRefInit(T initialValue) : jsRef = React.useRef(initialValue);\n\n  Ref.fromJs(this.jsRef);\n\n  /// A reference to the latest instance of the rendered component.\n  ///\n  /// See [createRef] for usage examples and more info.\n  T get current {\n    final jsCurrent = jsRef.current;\n\n    // Note: this ReactComponent check will pass for many types of JS objects,\n    // so don\'t assume for sure that it\'s a ReactComponent\n    if (jsCurrent is! Element && jsCurrent is ReactComponent) {\n      final dartCurrent = jsCurrent.dartComponent;\n\n      if (dartCurrent != null) {\n        return dartCurrent as T;\n      }\n    }\n    return jsCurrent;\n  }\n\n  /// Sets the value of [current].\n  ///\n  /// See: <https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables>.\n  set current(T value) {\n    if (value is Component) {\n      jsRef.current = value.jsThis;\n    } else {\n      jsRef.current = value;\n    }\n  }\n}\n\n/// A JS ref object returned by [React.createRef].\n///\n/// Dart factories will automatically unwrap [Ref] objects to this JS representation,\n/// so using this class directly shouldn\'t be necessary.\n@JS()\n@anonymous\nclass JsRef {\n  external dynamic get current;\n  external set current(dynamic value);\n}\n\n/// Automatically passes a [Ref] through a component to one of its children.\n///\n/// __Example 1:__ Forwarding refs to DOM components\n///\n/// _[Analogous JS Demo](https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-to-dom-components)_\n///\n/// ```dart\n/// import \'dart:html\';\n/// import \'package:react/react.dart\' as react;\n///\n/// // ---------- Component Definition ----------\n/// final FancyButton = react.forwardRef2((props, ref) {\n///   return react.button({\'ref\': ref, \'className\': \'FancyButton\'}, \'Click me!\');\n/// }, displayName: \'FancyButton\');\n///\n/// // ---------- Component Consumption ----------\n/// void main() {\n///   final ref = createRef<Element>();\n///\n///   react_dom.render(FancyButton({\'ref\': ref}));\n///\n///   // You can now get a ref directly to the DOM button:\n///   final buttonNode = ref.current;\n/// }\n/// ```\n///\n/// __Example 2:__ Forwarding refs in higher-order components\n///\n/// _[Analogous JS Demo](https://reactjs.org/docs/forwarding-refs.html#forwarding-refs-in-higher-order-components)_\n///\n/// ```dart\n/// import \'dart:html\';\n/// import \'package:react/react.dart\' as react;\n/// import \'package:react/react_client.dart\' show setClientConfiguration, ReactJsComponentFactoryProxy;\n/// import \'package:react/react_dom.dart\' as react_dom;\n///\n/// // ---------- Component Definitions ----------\n///\n/// final FancyButton = react.forwardRef2((props, ref) {\n///   return react.button({\'ref\': ref, \'className\': \'FancyButton\'}, \'Click me!\');\n/// }, displayName: \'FancyButton\');\n///\n/// class _LogProps extends react.Component2 {\n///   @override\n///   void componentDidUpdate(Map prevProps, _, [__]) {\n///     print(\'old props: $prevProps\');\n///     print(\'new props: ${this.props}\');\n///   }\n///\n///   @override\n///   render() {\n///     final propsToForward = {...props}..remove(\'forwardedRef\');\n///\n///     // Assign the custom prop `forwardedRef` as a ref on the component passed in via `props.component`\n///     return props[\'component\']({...propsToForward, \'ref\': props[\'forwardedRef\']}, props[\'children\']);\n///   }\n/// }\n/// final _logPropsHoc = react.registerComponent2(() => _LogProps());\n///\n/// final LogProps = react.forwardRef2((props, ref) {\n///   // Note the second param "ref" provided by react.forwardRef2.\n///   // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef"\n///   // And it can then be attached to the Component.\n///   return _logPropsHoc({...props, \'forwardedRef\': ref});\n///   // Optional: Make the displayName more useful for the React dev tools.\n///   // See: https://reactjs.org/docs/forwarding-refs.html#displaying-a-custom-name-in-devtools\n/// }, displayName: \'LogProps(${_logPropsHoc.type.displayName})\');\n///\n/// // ---------- Component Consumption ----------\n/// void main() {\n///   setClientConfiguration();\n///   final ref = react.createRef<Element>();\n///\n///   react_dom.render(LogProps({\'component\': FancyButton, \'ref\': ref}),\n///       querySelector(\'#idOfSomeNodeInTheDom\'));\n///\n///   // You can still get a ref directly to the DOM button:\n///   final buttonNode = ref.current;\n/// }\n/// ```\n/// See: <https://reactjs.org/docs/forwarding-refs.html>.\nReactComponentFactoryProxy forwardRef2(\n  DartForwardRefFunctionComponent wrapperFunction, {\n  String displayName,\n}) =>\n    ReactDartWrappedComponentFactoryProxy.forwardRef(wrapperFunction, displayName: displayName);\n\n@Deprecated(\'Use forwardRef2\')\nReactJsComponentFactoryProxy forwardRef(\n  Function(Map props, Ref ref) wrapperFunction, {\n  String displayName = \'Anonymous\',\n}) {\n  final wrappedComponent = allowInterop((JsMap props, JsRef ref) => componentZone.run(() {\n        final dartProps = JsBackedMap.backedBy(props);\n        for (var value in dartProps.values) {\n          if (value is Function) {\n            // Tag functions that came straight from the JS\n            // so that we know to pass them through as-is during prop conversion.\n            isRawJsFunctionFromProps[value] = true;\n          }\n        }\n\n        final dartRef = Ref.fromJs(ref);\n        return wrapperFunction(dartProps, dartRef);\n      }));\n  defineProperty(wrappedComponent, \'displayName\', JsPropertyDescriptor(value: displayName));\n\n  var hoc = React.forwardRef(wrappedComponent);\n  // ignore: invalid_use_of_protected_member\n  setProperty(hoc, \'dartComponentVersion\', ReactDartComponentVersion.component2);\n\n  return ReactJsComponentFactoryProxy(hoc, alwaysReturnChildrenAsList: true);\n}\n\n/// A [higher order component](https://reactjs.org/docs/higher-order-components.html) for function components\n/// that behaves similar to the way [`React.PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent)\n/// does for class-based components.\n///\n/// If your function component renders the same result given the same props, you can wrap it in a call to\n/// `memo` for a performance boost in some cases by memoizing the result. This means that React will skip\n/// rendering the component, and reuse the last rendered result.\n///\n/// ```dart\n/// import \'package:react/react.dart\' as react;\n///\n/// final MyComponent = react.memo2(react.registerFunctionComponent((props) {\n///   /* render using props */\n/// }));\n/// ```\n///\n/// `memo2` only affects props changes. If your function component wrapped in `memo2` has a\n/// [useState] or [useContext] Hook in its implementation, it will still rerender when `state` or `context` change.\n///\n/// By default it will only shallowly compare complex objects in the props map.\n/// If you want control over the comparison, you can also provide a custom comparison\n/// function to the [areEqual] argument as shown in the example below.\n///\n/// ```dart\n/// import \'package:react/react.dart\' as react;\n///\n/// final MyComponent = react.memo2(react.registerFunctionComponent((props) {\n///   // render using props\n/// }), areEqual: (prevProps, nextProps) {\n///   // Do some custom comparison logic to return a bool based on prevProps / nextProps\n/// });\n/// ```\n///\n/// > __This method only exists as a performance optimization.__\n/// >\n/// > Do not rely on it to “prevent” a render, as this can lead to bugs.\n///\n/// See: <https://reactjs.org/docs/react-api.html#reactmemo>.\nReactComponentFactoryProxy memo2(ReactComponentFactoryProxy factory,\n    {bool Function(Map prevProps, Map nextProps) areEqual}) {\n  final _areEqual = areEqual == null\n      ? null\n      : allowInterop((JsMap prevProps, JsMap nextProps) {\n          final dartPrevProps = JsBackedMap.backedBy(prevProps);\n          final dartNextProps = JsBackedMap.backedBy(nextProps);\n          return areEqual(dartPrevProps, dartNextProps);\n        });\n  final hoc = React.memo(factory.type, _areEqual);\n  setProperty(hoc, \'dartComponentVersion\', ReactDartComponentVersion.component2);\n\n  return ReactDartWrappedComponentFactoryProxy(hoc);\n}\n\n@Deprecated(\'Use memo2\')\nReactJsComponentFactoryProxy memo(ReactDartFunctionComponentFactoryProxy factory,\n    {bool Function(Map prevProps, Map nextProps) areEqual}) {\n  final _areEqual = areEqual == null\n      ? null\n      : allowInterop((JsMap prevProps, JsMap nextProps) {\n          final dartPrevProps = JsBackedMap.backedBy(prevProps);\n          final dartNextProps = JsBackedMap.backedBy(nextProps);\n          return areEqual(dartPrevProps, dartNextProps);\n        });\n  final hoc = React.memo(factory.type, _areEqual);\n  setProperty(hoc, \'dartComponentVersion\', ReactDartComponentVersion.component2);\n\n  return ReactJsComponentFactoryProxy(hoc, alwaysReturnChildrenAsList: true);\n}\n\nabstract class ReactDom {\n  static Element findDOMNode(object) => ReactDOM.findDOMNode(object);\n  static ReactComponent render(ReactElement component, Element element) => ReactDOM.render(component, element);\n  static bool unmountComponentAtNode(Element element) => ReactDOM.unmountComponentAtNode(element);\n\n  /// Returns a a portal that renders [children] into a [container].\n  ///\n  /// Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.\n  ///\n  /// [children] can be any renderable React child, such as a [ReactElement], [String], or fragment.\n  ///\n  /// See: <https://reactjs.org/docs/portals.html>\n  static ReactPortal createPortal(dynamic children, Element container) => ReactDOM.createPortal(children, container);\n}\n\n@JS(\'ReactDOMServer\')\nabstract class ReactDomServer {\n  external static String renderToString(ReactElement component);\n  external static String renderToStaticMarkup(ReactElement component);\n}\n\n/// Runtime type checking for React props and similar objects.\n///\n/// See: <https://reactjs.org/docs/typechecking-with-proptypes.html>\n/// See: <https://www.npmjs.com/package/prop-types>\n@JS(\'React.PropTypes\')\nabstract class PropTypes {\n  /// PropTypes.checkPropTypes(...) only console.error(...)s a given message once.\n  /// To reset the cache while testing call PropTypes.resetWarningCache()\n  ///\n  /// See: <https://www.npmjs.com/package/prop-types#proptypesresetwarningcache>\n  external static resetWarningCache();\n}\n\n// ----------------------------------------------------------------------------\n//   Types and data structures\n// ----------------------------------------------------------------------------\n\n/// A React class specification returned by `React.createClass`.\n///\n/// To be used as the value of [ReactElement.type], which is set upon initialization\n/// by a component factory or by [React.createElement].\n///\n/// See: <http://facebook.github.io/react/docs/top-level-api.html#react.createclass>\n@JS()\n@anonymous\nclass ReactClass {\n  /// The cached, unmodifiable copy of [Component2.defaultProps] computed in\n  /// [registerComponent2].\n  ///\n  /// For use in `ReactDartComponentFactoryProxy2` when creating new [ReactElement]s,\n  /// or for external use involving inspection of Dart prop defaults.\n  external JsMap get defaultProps;\n  external set defaultProps(JsMap value);\n\n  /// The `displayName` string is used in debugging messages.\n  ///\n  /// See: <http://facebook.github.io/react/docs/component-specs.html#displayname>\n  external String get displayName;\n  external set displayName(String value);\n\n  /// The cached, unmodifiable copy of [Component.getDefaultProps] computed in\n  /// [registerComponent].\n  ///\n  /// For use in [ReactDartComponentFactoryProxy] when creating new [ReactElement]s,\n  /// or for external use involving inspection of Dart prop defaults.\n  @Deprecated(\'7.0.0`\')\n  external Map get dartDefaultProps;\n  @Deprecated(\'7.0.0`\')\n  external set dartDefaultProps(Map value);\n\n  /// A string to distinguish between different Dart component implementations / base classes.\n  ///\n  /// See [ReactDartComponentVersion] for values.\n  ///\n  /// __For internal use only.__\n  @protected\n  external String get dartComponentVersion;\n  @protected\n  external set dartComponentVersion(String value);\n}\n\n/// Constants for use with [ReactClass.dartComponentVersion] to distinguish\n/// different versions of Dart component implementations / base classes.\n///\n/// __For internal use only.__\n@protected\n@sealed\nabstract class ReactDartComponentVersion {\n  /// A [Component]-based component.\n  @protected\n  static const String component = \'1\';\n\n  /// A [Component2]-based component.\n  @protected\n  static const String component2 = \'2\';\n\n  /// Returns [ReactClass.dartComponentVersion] if [type] is the [ReactClass] for a Dart component\n  /// (a react-dart [ReactElement] or [ReactComponent]), and null otherwise.\n  @protected\n  static String fromType(dynamic type) {\n    // This check doesn\'t do much since ReactClass is an anonymous JS object,\n    // but it lets us safely cast to ReactClass.\n    if (type is ReactClass) {\n      return type.dartComponentVersion;\n    }\n    if (type is Function) {\n      return getProperty(type, \'dartComponentVersion\');\n    }\n\n    return null;\n  }\n}\n\n/// A JS interop class used as an argument to [React.createClass].\n///\n/// See: <http://facebook.github.io/react/docs/top-level-api.html#react.createclass>.\n///\n/// > __DEPRECATED.__\n/// >\n/// > Will be removed alongside [React.createClass] in the `7.0.0` release.\n@Deprecated(\'7.0.0\')\n@JS()\n@anonymous\nclass ReactClassConfig {\n  external factory ReactClassConfig({\n    String displayName,\n    List mixins,\n    Function componentWillMount,\n    Function componentDidMount,\n    Function componentWillReceiveProps,\n    Function shouldComponentUpdate,\n    Function componentWillUpdate,\n    Function componentDidUpdate,\n    Function componentWillUnmount,\n    Function getChildContext,\n    Map<String, dynamic> childContextTypes,\n    Function getDefaultProps,\n    Function getInitialState,\n    Function render,\n  });\n\n  /// The `displayName` string is used in debugging messages.\n  ///\n  /// See: <http://facebook.github.io/react/docs/component-specs.html#displayname>\n  external String get displayName;\n  external set displayName(String value);\n}\n\n/// Interop class for the data structure at `ReactElement._store`.\n///\n/// Used to validate variadic children before they get to [React.createElement].\n@JS()\n@anonymous\nclass ReactElementStore {\n  external bool get validated;\n  external set validated(bool value);\n}\n\n/// A virtual DOM element representing an instance of a DOM element,\n/// React component, or fragment.\n///\n/// React elements are the building blocks of React applications.\n/// One might confuse elements with a more widely known concept of "components".\n/// An element describes what you want to see on the screen. React elements are immutable.\n///\n/// Typically, elements are not used directly, but get returned from components.\n///\n/// These can be created directly by [React.createElement], or by invoking\n/// React element DOM/component factories.\n///\n///     react.h1({}, \'Content here\');\n///     MaterialButton({}, \'Click me\');\n///\n/// See <https://reactjs.org/docs/glossary.html#elements>\n/// and <https://reactjs.org/docs/glossary.html#components>.\n@JS()\n@anonymous\nclass ReactElement {\n  external ReactElementStore get _store; // ignore: unused_element\n\n  /// The type of this element.\n  ///\n  /// For DOM components, this will be a [String] tagName (e.g., `\'div\'`, `\'a\'`).\n  ///\n  /// For composite components (react-dart or pure JS), this will be a [ReactClass].\n  external dynamic get type;\n\n  /// The props this element was created with.\n  external InteropProps get props;\n\n  /// This element\'s `key`, which is used to uniquely identify it among its siblings.\n  ///\n  /// Not needed when children are passed variadically\n  /// (as arguments to a factory, as opposed to items within a list/iterable).\n  ///\n  /// See: <https://reactjs.org/docs/reconciliation.html#keys>.\n  external String get key;\n\n  /// This element\'s `ref`, which can be used to access the associated\n  /// [Component]/[ReactComponent]/[Element] after it has been rendered.\n  ///\n  /// See: <https://reactjs.org/docs/refs-and-the-dom.html>.\n  external dynamic get ref;\n}\n\n/// A virtual DOM node representing a React Portal, returned by [ReactDom.createPortal].\n///\n/// Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.\n///\n/// Children can be any renderable React child, such as an element, string, or fragment.\n///\n/// While closely related, portals are not [ReactElement]s.\n///\n/// See: <https://reactjs.org/docs/portals.html>\n@JS()\n@anonymous\nclass ReactPortal {\n  external dynamic /* ReactNodeList */ get children;\n  external dynamic get containerInfo;\n}\n\n/// The JavaScript component instance, which backs each react-dart [Component].\n///\n/// See: <http://facebook.github.io/react/docs/glossary.html#react-components>\n@JS()\n@anonymous\nclass ReactComponent {\n  // TODO: Cast as Component2 in 7.0.0\n  external Component get dartComponent;\n  // TODO how to make this JsMap without breaking stuff?\n  external InteropProps get props;\n  external dynamic get context;\n  external JsMap get state;\n  external set state(JsMap value);\n  external get refs;\n  external void setState(state, [callback]);\n  external void forceUpdate([callback]);\n}\n\n// ----------------------------------------------------------------------------\n//   Interop internals\n// ----------------------------------------------------------------------------\n\n/// A JavaScript interop class representing a value in a React JS `context` object.\n///\n/// Used for storing/accessing Dart [ReactDartContextInternal] objects in `context`\n/// in a way that\'s opaque to the JS, and avoids the need to use dart2js interceptors.\n///\n/// __For internal/advanced use only.__\n///\n/// > __DEPRECATED - DO NOT USE__\n/// >\n/// > This API was never stable in any version of ReactJS, and was replaced with a new, incompatible context API\n/// > in ReactJS 16 that is exposed via the [Component2] class.\n/// >\n/// > This will be completely removed when the JS side of it is slated for removal (ReactJS 18 / react.dart 7.0.0)\n@Deprecated(\'7.0.0\')\n@JS()\n@anonymous\nclass InteropContextValue {\n  external factory InteropContextValue();\n}\n\n/// A JavaScript interop class representing the return value of `createContext`.\n///\n/// Used for accessing Dart [Context.Provider] & [Context.Consumer] components.\n///\n/// __For internal/advanced use only.__\n@JS()\n@anonymous\nclass ReactContext {\n  external ReactClass get Provider;\n  external ReactClass get Consumer;\n}\n\n/// A JavaScript interop class representing a React JS `props` object.\n///\n/// Used for storing/accessing [ReactDartComponentInternal] objects in\n/// react-dart [ReactElement]s and [ReactComponent]s, as well as for preparing\n/// reserved props (`key` and `ref`) for consumption by ReactJS.\n///\n/// __For internal/advanced use only.__\n@JS()\n@anonymous\nclass InteropProps implements JsMap {\n  /// __Deprecated.__\n  ///\n  /// This has been deprecated along with `Component` since its\n  /// replacement - `Component2` utilizes JS Maps for props,\n  /// making `internal` obsolete.\n  ///\n  /// Will be removed alongside `Component` in the `7.0.0` release.\n  @Deprecated(\'7.0.0\')\n  external ReactDartComponentInternal get internal;\n  external dynamic get key;\n  external dynamic get ref;\n\n  external set key(dynamic value);\n  external set ref(dynamic value);\n\n  /// __Deprecated.__\n  ///\n  /// This has been deprecated along with `Component` since its\n  /// replacement - `Component2` utilizes JS Maps for props,\n  /// making `InteropProps` obsolete.\n  ///\n  /// Will be removed alongside `Component` in the `7.0.0` release.\n  @Deprecated(\'7.0.0\')\n  external factory InteropProps({\n    ReactDartComponentInternal internal,\n    String key,\n    dynamic ref,\n  });\n}\n\n/// __Deprecated.__\n///\n/// This has been deprecated along with `Component` since its\n/// replacement - `Component2` utilizes JS Maps for props,\n/// making `InteropProps` obsolete.\n///\n/// Will be removed alongside `Component` in the `7.0.0` release.\n///\n/// > Internal react-dart information used to proxy React JS lifecycle to Dart\n/// > [Component] instances.\n/// >\n/// > __For internal/advanced use only.__\n@Deprecated(\'7.0.0\')\nclass ReactDartComponentInternal {\n  /// For a `ReactElement`, this is the initial props with defaults merged.\n  ///\n  /// For a `ReactComponent`, this is the props the component was last rendered with,\n  /// and is used within props-related lifecycle internals.\n  Map props;\n}\n\n/// Internal react-dart information used to proxy React JS lifecycle to Dart\n/// [Component] instances.\n///\n/// __For internal/advanced use only.__\n///\n/// > __DEPRECATED - DO NOT USE__\n/// >\n/// > This API was never stable in any version of ReactJS, and was replaced with a new, incompatible context API\n/// > in ReactJS 16 that is exposed via the [Component2] class.\n/// >\n/// > This will be completely removed when the JS side of it is slated for removal (ReactJS 18 / react.dart 7.0.0)\n@Deprecated(\'7.0.0\')\nclass ReactDartContextInternal {\n  final dynamic value;\n\n  ReactDartContextInternal(this.value);\n}\n\n/// Creates a new JS Error object with the provided message.\n@JS(\'Error\')\nclass JsError {\n  external JsError(message);\n}\n\n/// A JS variable that can be used with Dart interop in order to force returning a JavaScript `null`.\n/// Use this if dart2js is possibly converting Dart `null` into `undefined`.\n@JS(\'_jsNull\')\nexternal get jsNull;\n\n/// A JS variable that can be used with Dart interop in order to force returning a JavaScript `undefined`.\n/// Use this if dart2js is possibly converting Dart `undefined` into `null`.\n@JS(\'_jsUndefined\')\nexternal get jsUndefined;\n\n/// Throws the error passed to it from Javascript.\n/// This allows us to catch the error in dart which re-dartifies the js errors/exceptions.\n@alwaysThrows\n@JS(\'_throwErrorFromJS\')\nexternal void throwErrorFromJS(error);\n\n/// Marks [child] as validated, as if it were passed into [React.createElement]\n/// as a variadic child.\n///\n/// Offloaded to the JS to avoid dart2js interceptor lookup.\n@JS(\'_markChildValidated\')\nexternal void markChildValidated(child);\n\n/// Mark each child in [children] as validated so that React doesn\'t emit key warnings.\n///\n/// ___Only for use with variadic children.___\nvoid markChildrenValidated(List<dynamic> children) {\n  children.forEach((dynamic child) {\n    // Use `isValidElement` since `is ReactElement` doesn\'t behave as expected.\n    if (React.isValidElement(child)) {\n      markChildValidated(child);\n    }\n  });\n}\n\n/// Returns a new JS [ReactClass] for a component that uses\n/// [dartInteropStatics] and [componentStatics] internally to proxy between\n/// the JS and Dart component instances.\n///\n/// > __DEPRECATED.__\n/// >\n/// > Will be removed in `7.0.0` alongside [Component].\n@JS(\'_createReactDartComponentClass\')\n@Deprecated(\'7.0.0\')\nexternal ReactClass createReactDartComponentClass(\n    ReactDartInteropStatics dartInteropStatics, ComponentStatics componentStatics,\n    [JsComponentConfig jsConfig]);\n\n/// Returns a new JS [ReactClass] for a component that uses\n/// [dartInteropStatics] and [componentStatics] internally to proxy between\n/// the JS and Dart component instances.\n///\n/// See `_ReactDartInteropStatics2.staticsForJs`]` for an example implementation.\n@JS(\'_createReactDartComponentClass2\')\nexternal ReactClass createReactDartComponentClass2(JsMap dartInteropStatics, ComponentStatics2 componentStatics,\n    [JsComponentConfig2 jsConfig]);\n\n@JS(\'React.__isDevelopment\')\nexternal bool get _inReactDevMode;\n\n/// Whether the "dev" build of react.js is being used.\n///\n/// Useful for creating conditional logic based on whether your application is being served in a production environment.\n///\n///     if (inReactDevMode) {\n///       print(\'Debug info that only developers should see.\');\n///     }\n///\n/// > This value will be `true` if your HTML page includes `react.js` or `react_with_addons.js`,\n///   and `false` if your HTML page includes `react_prod.js` or `react_with_react_dom_prod.js`.\nbool get inReactDevMode => _inReactDevMode;\n\n/// An object that stores static methods used by all Dart components.\n///\n/// __Deprecated.__\n///\n/// Will be removed when [Component] is removed in the `7.0.0` release.\n@JS()\n@anonymous\n@Deprecated(\'7.0.0\')\nclass ReactDartInteropStatics {\n  external factory ReactDartInteropStatics({\n    Component Function(\n      ReactComponent jsThis,\n      ReactDartComponentInternal internal,\n      InteropContextValue context,\n      ComponentStatics componentStatics,\n    )\n        initComponent,\n    InteropContextValue Function(Component component) handleGetChildContext,\n    void Function(Component component) handleComponentWillMount,\n    void Function(Component component) handleComponentDidMount,\n    void Function(\n      Component component,\n      ReactDartComponentInternal nextInternal,\n      InteropContextValue nextContext,\n    )\n        handleComponentWillReceiveProps,\n    bool Function(Component component, InteropContextValue nextContext) handleShouldComponentUpdate,\n    void Function(Component component, InteropContextValue nextContext) handleComponentWillUpdate,\n    void Function(Component component, ReactDartComponentInternal prevInternal) handleComponentDidUpdate,\n    void Function(Component component) handleComponentWillUnmount,\n    dynamic Function(Component component) handleRender,\n  });\n}\n\n/// An object that stores static methods and information for a specific component class.\n///\n/// This object is made accessible to a component\'s JS ReactClass config, which\n/// passes it to certain methods in [ReactDartInteropStatics].\n///\n/// See [ReactDartInteropStatics], [createReactDartComponentClass].\nclass ComponentStatics {\n  final ComponentFactory<Component> componentFactory;\n  ComponentStatics(this.componentFactory);\n}\n\n/// An object that stores static methods and information for a specific component class.\n///\n/// This object is made accessible to a component\'s JS ReactClass config, which\n/// passes it to certain methods in [ReactDartInteropStatics2].\n///\n/// See [ReactDartInteropStatics2], [createReactDartComponentClass2].\nclass ComponentStatics2 {\n  final ComponentFactory<Component2> componentFactory;\n  final Component2 instanceForStaticMethods;\n  final Component2BridgeFactory bridgeFactory;\n\n  ComponentStatics2({\n    @required this.componentFactory,\n    @required this.instanceForStaticMethods,\n    @required this.bridgeFactory,\n  });\n}\n\n/// Additional configuration passed to [createReactDartComponentClass]\n/// that needs to be directly accessible by that JS code.\n///\n/// > __DEPRECATED - DO NOT USE__\n/// >\n/// > The `context` API that this supports was never stable in any version of ReactJS,\n/// > and was replaced with a new, incompatible context API in ReactJS 16 that is exposed\n/// > via the [Component2] class and is supported by [JsComponentConfig2].\n/// >\n/// > This will be completely removed when the JS side of `context` it is slated for\n/// > removal (ReactJS 18 / react.dart 7.0.0)\n@Deprecated(\'7.0.0\')\n@JS()\n@anonymous\nclass JsComponentConfig {\n  external factory JsComponentConfig({\n    Iterable<String> childContextKeys,\n    Iterable<String> contextKeys,\n  });\n}\n\n/// Additional configuration passed to [createReactDartComponentClass2]\n/// that needs to be directly accessible by that JS code.\n@JS()\n@anonymous\nclass JsComponentConfig2 {\n  external factory JsComponentConfig2({\n    dynamic contextType,\n    JsMap defaultProps,\n    JsMap propTypes,\n    @required List<String> skipMethods,\n  });\n}\n\n/// Information on an error caught by `componentDidCatch`.\n@JS()\n@anonymous\nclass ReactErrorInfo {\n  /// The component stack trace associated with this error.\n  ///\n  /// See: https://reactjs.org/docs/error-boundaries.html#component-stack-traces\n  external String get componentStack;\n  external set componentStack(String value);\n\n  /// The dart stack trace associated with this error.\n  external StackTrace get dartStackTrace;\n  external set dartStackTrace(StackTrace);\n}\n', 'message': 'Update Ref constructor, clean up generics / doc comments\n', 'author_name': 'Greg Littlefield', 'lang': 'dart'}