UNPKG

zoid

Version:
128 lines (102 loc) 3.87 kB
/* @flow */ import { onCloseWindow, type CrossDomainWindowType } from 'cross-domain-utils/src'; import { ZalgoPromise } from 'zalgo-promise/src'; import { eventEmitter, type EventEmitterType } from 'belter/src'; import { ProxyWindow } from 'post-robot/src'; import { ParentComponent } from '../parent'; import { RENDER_DRIVERS, type ContextDriverType } from '../parent/drivers'; import type { Component } from '../component'; import type { CancelableType } from '../../types'; import { cleanup, type CleanupType } from '../../lib'; export type DelegatePropsType = { onClose : () => ?ZalgoPromise<void>, onDisplay : () => ?ZalgoPromise<void>, window : ?ProxyWindow }; export type DelegateOptionsType = { context : string, props : DelegatePropsType, overrides : { userClose : (string) => ZalgoPromise<void>, error : (mixed) => ZalgoPromise<void>, on : (string, () => void) => CancelableType } }; export type DelegateReturnType = { overrides : Object, destroy : () => ZalgoPromise<void> }; export class DelegateComponent<P> { component : Component<P> source : CrossDomainWindowType context : string props : DelegatePropsType event : EventEmitterType clean : CleanupType uid : string userClose : (string) => ZalgoPromise<void> getDomain : () => ZalgoPromise<string> error : (mixed) => ZalgoPromise<void> on : (string, () => void) => CancelableType constructor(component : Component<P>, source : CrossDomainWindowType, options : DelegateOptionsType) { this.component = component; this.context = options.context; this.clean = cleanup(this); this.event = eventEmitter(); // $FlowFixMe this.destroyComponent = ParentComponent.prototype.destroyComponent; // $FlowFixMe this.resize = ParentComponent.prototype.resize; // $FlowFixMe this.renderTemplate = ParentComponent.prototype.renderTemplate; // $FlowFixMe this.registerActiveComponent = ParentComponent.prototype.registerActiveComponent; this.props = { window: options.props.window, onClose: options.props.onClose, onDisplay: options.props.onDisplay }; for (let propName of component.getPropNames()) { // $FlowFixMe let prop = this.component.getProp(propName); if (prop.allowDelegate) { this.props[propName] = options.props[propName]; } } this.userClose = options.overrides.userClose; this.error = options.overrides.error; this.on = options.overrides.on; // $FlowFixMe this.registerActiveComponent(); this.watchForClose(source); } getDelegate() : DelegateReturnType { return { overrides: this.getOverrides(), destroy: () => this.destroy() }; } get driver() : ContextDriverType { return RENDER_DRIVERS[this.context]; } watchForClose(source : CrossDomainWindowType) { let closeWindowListener = onCloseWindow(source, () => this.destroy(), 3000); this.clean.register('destroyCloseWindowListener', closeWindowListener.cancel); } getOverrides() : { [string] : mixed } { let context = this.context; let delegateOverrides = RENDER_DRIVERS[context].delegateOverrides; let overrides = {}; let self = this; for (let key of Object.keys(delegateOverrides)) { overrides[key] = function delegateOverride() : mixed { // $FlowFixMe return ParentComponent.prototype[key].apply(self, arguments); }; } return overrides; } destroy() : ZalgoPromise<void> { return this.clean.all(); } }