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 | function Option(options) {
|
41 | return function (target, propertyKey) {
|
42 | if (!(target instanceof AbstractComponent)) {
|
43 | throw new Error('The `Option` decorator can only be used on properties within an `AbstractComponent` subclass.');
|
44 | }
|
45 | options.component = target['_componentName'];
|
46 | target['_componentOptions'] = target['_componentOptions'] || [];
|
47 | target['_componentOptions'].push(options);
|
48 | Object.defineProperty(target, propertyKey, {
|
49 | get: function () {
|
50 | return this.application.options.getValue(options.name);
|
51 | },
|
52 | enumerable: true,
|
53 | configurable: true
|
54 | });
|
55 | };
|
56 | }
|
57 | exports.Option = Option;
|
58 | class ComponentEvent extends events_1.Event {
|
59 | constructor(name, owner, component) {
|
60 | super(name);
|
61 | this.owner = owner;
|
62 | this.component = component;
|
63 | }
|
64 | }
|
65 | ComponentEvent.ADDED = 'componentAdded';
|
66 | ComponentEvent.REMOVED = 'componentRemoved';
|
67 | exports.ComponentEvent = ComponentEvent;
|
68 | exports.DUMMY_APPLICATION_OWNER = Symbol();
|
69 | class AbstractComponent extends events_1.EventDispatcher {
|
70 | constructor(owner) {
|
71 | super();
|
72 | this._componentOwner = owner;
|
73 | this.initialize();
|
74 | }
|
75 | initialize() { }
|
76 | bubble(name, ...args) {
|
77 | super.trigger(name, ...args);
|
78 | if (this.owner instanceof AbstractComponent && this._componentOwner !== exports.DUMMY_APPLICATION_OWNER) {
|
79 | this.owner.bubble(name, ...args);
|
80 | }
|
81 | return this;
|
82 | }
|
83 | getOptionDeclarations() {
|
84 | return (this._componentOptions || []).slice();
|
85 | }
|
86 | get application() {
|
87 | return this._componentOwner === exports.DUMMY_APPLICATION_OWNER
|
88 | ? this
|
89 | : this._componentOwner.application;
|
90 | }
|
91 | get owner() {
|
92 | return this._componentOwner === exports.DUMMY_APPLICATION_OWNER
|
93 | ? this
|
94 | : this._componentOwner;
|
95 | }
|
96 | }
|
97 | exports.AbstractComponent = AbstractComponent;
|
98 | class ChildableComponent extends AbstractComponent {
|
99 | constructor(owner) {
|
100 | super(owner);
|
101 | _.entries(this._defaultComponents || {}).forEach(([name, component]) => {
|
102 | this.addComponent(name, component);
|
103 | });
|
104 | }
|
105 | getComponent(name) {
|
106 | return (this._componentChildren || {})[name];
|
107 | }
|
108 | getComponents() {
|
109 | return _.values(this._componentChildren);
|
110 | }
|
111 | hasComponent(name) {
|
112 | return !!(this._componentChildren || {})[name];
|
113 | }
|
114 | addComponent(name, componentClass) {
|
115 | if (!this._componentChildren) {
|
116 | this._componentChildren = {};
|
117 | }
|
118 | if (this._componentChildren[name]) {
|
119 | return this._componentChildren[name];
|
120 | }
|
121 | else {
|
122 | const component = typeof componentClass === 'function'
|
123 | ? new componentClass(this)
|
124 | : componentClass;
|
125 | const event = new ComponentEvent(ComponentEvent.ADDED, this, component);
|
126 | this.bubble(event);
|
127 | this._componentChildren[name] = component;
|
128 | return component;
|
129 | }
|
130 | }
|
131 | removeComponent(name) {
|
132 | const component = (this._componentChildren || {})[name];
|
133 | if (component) {
|
134 | delete this._componentChildren[name];
|
135 | component.stopListening();
|
136 | this.bubble(new ComponentEvent(ComponentEvent.REMOVED, this, component));
|
137 | return component;
|
138 | }
|
139 | }
|
140 | removeAllComponents() {
|
141 | for (const component of _.values(this._componentChildren)) {
|
142 | component.stopListening();
|
143 | }
|
144 | this._componentChildren = {};
|
145 | }
|
146 | }
|
147 | exports.ChildableComponent = ChildableComponent;
|
148 |
|
\ | No newline at end of file |