import { IAugmentedJQuery, IComponentOptions } from 'angular' import fromPairs = require('lodash.frompairs') import NgComponent from 'ngcomponent' import * as React from 'react' import { render, unmountComponentAtNode } from 'react-dom' /** * Wraps a React component in Angular. Returns a new Angular component. * * Usage: * * ```ts * type Props = { foo: number } * class ReactComponent extends React.Component {} * const AngularComponent = react2angular(ReactComponent, ['foo']) * ``` */ export function react2angular( Class: React.ComponentClass | React.SFC, bindingNames: (keyof Props)[] | null = null, injectNames: string[] = [] ): IComponentOptions { const names = bindingNames || (Class.propTypes && Object.keys(Class.propTypes) as (keyof Props)[]) || [] return { bindings: fromPairs(names.map(_ => [_, '<'])), controller: ['$element', ...injectNames, class extends NgComponent { static get $$ngIsClass() { return true } isDestroyed = false injectedProps: { [name: string]: any } constructor(private $element: IAugmentedJQuery, ...injectedProps: any[]) { super() this.injectedProps = {} injectNames.forEach((name, i) => { this.injectedProps[name] = injectedProps[i] }) } render() { if (!this.isDestroyed) { render(, this.$element[0]) } } componentWillUnmount() { this.isDestroyed = true unmountComponentAtNode(this.$element[0]) } }] } }