1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const _ = require("lodash");
|
4 | const events_1 = require("./events");
|
5 | const childMappings = [];
|
6 | function Component(options) {
|
7 | return (target) => {
|
8 | const proto = target.prototype;
|
9 | if (!(proto instanceof AbstractComponent)) {
|
10 | throw new Error('The `Component` decorator can only be used with a subclass of `AbstractComponent`.');
|
11 | }
|
12 | if (options.childClass) {
|
13 | if (!(proto instanceof ChildableComponent)) {
|
14 | throw new Error('The `Component` decorator accepts the parameter `childClass` only when used with a subclass of `ChildableComponent`.');
|
15 | }
|
16 | childMappings.push({
|
17 | host: proto,
|
18 | child: options.childClass
|
19 | });
|
20 | }
|
21 | const name = options.name;
|
22 | if (name) {
|
23 | proto.componentName = name;
|
24 | }
|
25 | const internal = !!options.internal;
|
26 | if (name && !internal) {
|
27 | for (const childMapping of childMappings) {
|
28 | if (!(proto instanceof childMapping.child)) {
|
29 | continue;
|
30 | }
|
31 | const host = childMapping.host;
|
32 | host['_defaultComponents'] = host['_defaultComponents'] || {};
|
33 | host['_defaultComponents'][name] = target;
|
34 | break;
|
35 | }
|
36 | }
|
37 | };
|
38 | }
|
39 | exports.Component = Component;
|
40 | class ComponentEvent extends events_1.Event {
|
41 | constructor(name, owner, component) {
|
42 | super(name);
|
43 | this.owner = owner;
|
44 | this.component = component;
|
45 | }
|
46 | }
|
47 | exports.ComponentEvent = ComponentEvent;
|
48 | ComponentEvent.ADDED = 'componentAdded';
|
49 | ComponentEvent.REMOVED = 'componentRemoved';
|
50 | exports.DUMMY_APPLICATION_OWNER = Symbol();
|
51 | class AbstractComponent extends events_1.EventDispatcher {
|
52 | constructor(owner) {
|
53 | super();
|
54 | this._componentOwner = owner;
|
55 | this.initialize();
|
56 | }
|
57 | initialize() { }
|
58 | bubble(name, ...args) {
|
59 | super.trigger(name, ...args);
|
60 | if (this.owner instanceof AbstractComponent && this._componentOwner !== exports.DUMMY_APPLICATION_OWNER) {
|
61 | this.owner.bubble(name, ...args);
|
62 | }
|
63 | return this;
|
64 | }
|
65 | getOptionDeclarations() {
|
66 | return (this._componentOptions || []).slice();
|
67 | }
|
68 | get application() {
|
69 | return this._componentOwner === exports.DUMMY_APPLICATION_OWNER
|
70 | ? this
|
71 | : this._componentOwner.application;
|
72 | }
|
73 | get owner() {
|
74 | return this._componentOwner === exports.DUMMY_APPLICATION_OWNER
|
75 | ? this
|
76 | : this._componentOwner;
|
77 | }
|
78 | }
|
79 | exports.AbstractComponent = AbstractComponent;
|
80 | class ChildableComponent extends AbstractComponent {
|
81 | constructor(owner) {
|
82 | super(owner);
|
83 | _.entries(this._defaultComponents || {}).forEach(([name, component]) => {
|
84 | this.addComponent(name, component);
|
85 | });
|
86 | }
|
87 | getComponent(name) {
|
88 | return (this._componentChildren || {})[name];
|
89 | }
|
90 | getComponents() {
|
91 | return _.values(this._componentChildren);
|
92 | }
|
93 | hasComponent(name) {
|
94 | return !!(this._componentChildren || {})[name];
|
95 | }
|
96 | addComponent(name, componentClass) {
|
97 | if (!this._componentChildren) {
|
98 | this._componentChildren = {};
|
99 | }
|
100 | if (this._componentChildren[name]) {
|
101 | return this._componentChildren[name];
|
102 | }
|
103 | else {
|
104 | const component = typeof componentClass === 'function'
|
105 | ? new componentClass(this)
|
106 | : componentClass;
|
107 | const event = new ComponentEvent(ComponentEvent.ADDED, this, component);
|
108 | this.bubble(event);
|
109 | this._componentChildren[name] = component;
|
110 | return component;
|
111 | }
|
112 | }
|
113 | removeComponent(name) {
|
114 | const component = (this._componentChildren || {})[name];
|
115 | if (component) {
|
116 | delete this._componentChildren[name];
|
117 | component.stopListening();
|
118 | this.bubble(new ComponentEvent(ComponentEvent.REMOVED, this, component));
|
119 | return component;
|
120 | }
|
121 | }
|
122 | removeAllComponents() {
|
123 | for (const component of _.values(this._componentChildren)) {
|
124 | component.stopListening();
|
125 | }
|
126 | this._componentChildren = {};
|
127 | }
|
128 | }
|
129 | exports.ChildableComponent = ChildableComponent;
|
130 |
|
\ | No newline at end of file |