import { EventChannel, SylApi, Types } from '@syllepsis/adapter'; import { IRenderer } from './types'; const noop = () => {}; type ViewCtorMap = { template: ComponentCtor; mask?: ComponentCtor; } & Types.StringMap; type ViewMap = { template: IRenderer; mask?: IRenderer; } & { [x: string]: IRenderer; }; class LayerRenderer { public container: HTMLElement; public ViewMap: ViewCtorMap; public viewMap: ViewMap = {} as ViewMap; public adapter: SylApi; public Renderer: Types.Ctor>; public layerType = 'template'; public curProps: Partial = {}; private viewContainer: { mask: HTMLElement; template: HTMLElement }; constructor( adapter: SylApi, container: HTMLElement, viewMapProps: ViewCtorMap, viewContainer: { mask: HTMLElement; template: HTMLElement }, Renderer: Types.Ctor> ) { this.container = container; this.ViewMap = viewMapProps; this.adapter = adapter; this.Renderer = Renderer; this.viewContainer = viewContainer; this.viewMap.template = new Renderer(this.adapter, this.ViewMap.template, viewContainer.template); if (!this.ViewMap.mask) this.ViewMap.mask = this.ViewMap.template; this.viewMap.mask = new Renderer(this.adapter, this.ViewMap.mask, viewContainer.mask); adapter.on(EventChannel.LocalEvent.SWITCH_LAYER, this.updateTemplate); } private iteratorViewMap = (cb: (renderer: IRenderer) => any) => Object.keys(this.viewMap).forEach(name => cb(this.viewMap[name])); public renderLayer() { this.iteratorViewMap(renderer => this.container.appendChild(renderer.container)); } public updateTemplate = (layerType = 'template') => { if (!this.ViewMap[layerType] || layerType === this.layerType) return; this.viewMap.template.unmount(); this.layerType = layerType; this.viewMap.template = new this.Renderer(this.adapter, this.ViewMap[layerType], this.viewContainer.template); this.viewMap.template.setProps(this.curProps, noop); }; /** * mount card in dom container * @param props */ public mount(props: Props) { const childNodes = Array.from(this.container.childNodes); for (const child of childNodes) { child.remove(); } this.update(props); this.renderLayer(); } /** * update view if props changed, will update all of cached viewMap * at the same time */ public update = (props: Partial) => { this.curProps = props; this.iteratorViewMap(renderer => { renderer.setProps(props, noop); }); }; /** * uninstall all of the Render View */ public uninstall() { this.iteratorViewMap(renderer => { renderer.unmount(); }); this.adapter.off(EventChannel.LocalEvent.SELECTION_CHANGED, this.updateTemplate); this.adapter.off(EventChannel.LocalEvent.SWITCH_LAYER, this.updateTemplate); } } export { LayerRenderer, ViewCtorMap };