structured-fw 1.1.0 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/system/EventEmitter.d.ts +1 -1
- package/build/system/EventEmitter.js +11 -12
- package/build/system/client/Client.d.ts +1 -6
- package/build/system/client/Client.js +2 -9
- package/build/system/client/ClientApplication.d.ts +13 -0
- package/build/system/client/ClientApplication.js +43 -0
- package/build/system/client/ClientComponent.d.ts +10 -6
- package/build/system/client/ClientComponent.js +92 -79
- package/build/system/client/DataStoreView.d.ts +1 -0
- package/build/system/client/DataStoreView.js +4 -1
- package/build/system/types/component.types.d.ts +11 -10
- package/build/system/types/eventEmitter.types.d.ts +1 -1
- package/build/system/types/general.types.d.ts +1 -0
- package/package.json +2 -2
- package/build/system/client/App.d.ts +0 -7
- package/build/system/client/App.js +0 -8
|
@@ -3,7 +3,7 @@ export declare class EventEmitter<T extends Record<string, any> = Record<string,
|
|
|
3
3
|
protected listeners: Partial<Record<Extract<keyof T, string>, Array<EventEmitterCallback<any>>>>;
|
|
4
4
|
protected destroyed: boolean;
|
|
5
5
|
on<K extends Extract<keyof T, string>>(eventName: K, callback: EventEmitterCallback<T[K]>): void;
|
|
6
|
-
emit(eventName: Extract<keyof T, string>, payload?: any): void
|
|
6
|
+
emit(eventName: Extract<keyof T, string>, payload?: any): Promise<void>;
|
|
7
7
|
off(eventName: keyof T, callback: EventEmitterCallback<any>): void;
|
|
8
8
|
unbindAllListeners(): void;
|
|
9
9
|
emitterDestroy(): void;
|
|
@@ -10,28 +10,27 @@ export class EventEmitter {
|
|
|
10
10
|
if (!Array.isArray(this.listeners[eventName])) {
|
|
11
11
|
this.listeners[eventName] = [];
|
|
12
12
|
}
|
|
13
|
+
if (this.listeners[eventName].indexOf(callback) > -1) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
13
16
|
this.listeners[eventName].push(callback);
|
|
14
17
|
}
|
|
15
|
-
emit(eventName, payload) {
|
|
18
|
+
async emit(eventName, payload) {
|
|
16
19
|
if (this.destroyed) {
|
|
17
20
|
return;
|
|
18
21
|
}
|
|
19
22
|
if (Array.isArray(this.listeners[eventName]) || Array.isArray(this.listeners['*'])) {
|
|
20
|
-
(this.listeners[eventName] || []).concat(this.listeners['*'] || [])
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
const listeners = (this.listeners[eventName] || []).concat(this.listeners['*'] || []);
|
|
24
|
+
for (let i = 0; i < listeners.length; i++) {
|
|
25
|
+
await listeners[i](payload, eventName);
|
|
26
|
+
}
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
off(eventName, callback) {
|
|
26
30
|
if (Array.isArray(this.listeners[eventName])) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.listeners[eventName].splice(index, 1);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
31
|
+
const index = this.listeners[eventName].indexOf(callback);
|
|
32
|
+
if (index > -1) {
|
|
33
|
+
this.listeners[eventName].splice(index, 1);
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
}
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export class Client {
|
|
4
|
-
constructor() {
|
|
5
|
-
this.Components = new App();
|
|
6
|
-
this.Net = new Net();
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
new App();
|
|
1
|
+
import { ClientApplication } from './ClientApplication.js';
|
|
2
|
+
new ClientApplication();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DataStore } from './DataStore.js';
|
|
2
|
+
import { ClientComponent } from './ClientComponent.js';
|
|
3
|
+
import { InitializerFunction } from '../types/component.types.js';
|
|
4
|
+
export declare class ClientApplication {
|
|
5
|
+
root: ClientComponent;
|
|
6
|
+
store: DataStore;
|
|
7
|
+
initializers: Record<string, InitializerFunction>;
|
|
8
|
+
constructor();
|
|
9
|
+
getInitializer(componentName: string): InitializerFunction | null;
|
|
10
|
+
private loadInitializers;
|
|
11
|
+
hasInitializer(componentName: string): boolean;
|
|
12
|
+
registerInitializer(componentName: string, initializerFunctionString: string): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DataStore } from './DataStore.js';
|
|
2
|
+
import { ClientComponent } from './ClientComponent.js';
|
|
3
|
+
export class ClientApplication {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.store = new DataStore();
|
|
6
|
+
this.initializers = {};
|
|
7
|
+
this.loadInitializers();
|
|
8
|
+
this.root = new ClientComponent(null, 'root', document.body, this);
|
|
9
|
+
}
|
|
10
|
+
getInitializer(componentName) {
|
|
11
|
+
if (!this.hasInitializer(componentName)) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return this.initializers[componentName];
|
|
15
|
+
}
|
|
16
|
+
loadInitializers() {
|
|
17
|
+
if (!!window.initializers) {
|
|
18
|
+
for (const componentName in window.initializers) {
|
|
19
|
+
this.registerInitializer(componentName, window.initializers[componentName]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
hasInitializer(componentName) {
|
|
24
|
+
return componentName in this.initializers;
|
|
25
|
+
}
|
|
26
|
+
registerInitializer(componentName, initializerFunctionString) {
|
|
27
|
+
if (this.hasInitializer(componentName)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const AsyncFunction = async function () { }.constructor;
|
|
31
|
+
const initializerFunction = new AsyncFunction(`
|
|
32
|
+
if (!this.destroyed) {
|
|
33
|
+
const init = ${initializerFunctionString};
|
|
34
|
+
try {
|
|
35
|
+
await init.apply(this, [...arguments]);
|
|
36
|
+
} catch(e) {
|
|
37
|
+
console.error('Error in component ${componentName}: ' + e.message, this);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`);
|
|
41
|
+
this.initializers[componentName] = initializerFunction;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { LooseObject } from '../types/general.types.js';
|
|
2
2
|
import { ClientComponentEventCallback } from '../types/component.types.js';
|
|
3
3
|
import { DataStoreView } from './DataStoreView.js';
|
|
4
|
-
import { DataStore } from './DataStore.js';
|
|
5
4
|
import { Net } from './Net.js';
|
|
6
5
|
import { EventEmitter } from '../EventEmitter.js';
|
|
6
|
+
import { ClientApplication } from './ClientApplication.js';
|
|
7
|
+
import { EventEmitterCallback } from '../types/eventEmitter.types.js';
|
|
7
8
|
export declare class ClientComponent extends EventEmitter {
|
|
8
9
|
readonly name: string;
|
|
9
10
|
children: Array<ClientComponent>;
|
|
@@ -12,9 +13,10 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
12
13
|
readonly isRoot: boolean;
|
|
13
14
|
readonly root: ClientComponent;
|
|
14
15
|
store: DataStoreView;
|
|
15
|
-
private
|
|
16
|
+
private app;
|
|
16
17
|
readonly net: Net;
|
|
17
18
|
private initializerExecuted;
|
|
19
|
+
readonly fn: Record<string, (...args: Array<any>) => any | undefined>;
|
|
18
20
|
destroyed: boolean;
|
|
19
21
|
private redrawRequest;
|
|
20
22
|
private bound;
|
|
@@ -25,7 +27,7 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
25
27
|
private refsArray;
|
|
26
28
|
isReady: boolean;
|
|
27
29
|
private data;
|
|
28
|
-
constructor(parent: ClientComponent | null, name: string, domNode: HTMLElement,
|
|
30
|
+
constructor(parent: ClientComponent | null, name: string, domNode: HTMLElement, app: ClientApplication);
|
|
29
31
|
private init;
|
|
30
32
|
private reset;
|
|
31
33
|
private runInitializer;
|
|
@@ -46,7 +48,6 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
46
48
|
private execCondition;
|
|
47
49
|
conditionalCallback(name: string, callback: (args?: any) => boolean, updateConditionals?: boolean): void;
|
|
48
50
|
private updateConditionals;
|
|
49
|
-
remove(): Promise<void>;
|
|
50
51
|
parentFind(parentName: string): ClientComponent | null;
|
|
51
52
|
find(componentName: string, recursive?: boolean): null | ClientComponent;
|
|
52
53
|
query(componentName: string, recursive?: boolean, results?: Array<ClientComponent>): Array<ClientComponent>;
|
|
@@ -57,8 +58,11 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
57
58
|
private transitionAttributes;
|
|
58
59
|
private transitionAxis;
|
|
59
60
|
private destroy;
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
remove(): Promise<void>;
|
|
62
|
+
bind<T extends any>(element: ClientComponent, event: string, callback: EventEmitterCallback<T>): void;
|
|
63
|
+
bind<T extends LooseObject | undefined>(element: HTMLElement | Window | Array<HTMLElement | Window>, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: ClientComponentEventCallback<T>): void;
|
|
64
|
+
unbind<T extends LooseObject | undefined = undefined>(element: HTMLElement | Window | ClientComponent, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: ClientComponentEventCallback<T> | EventEmitterCallback<T>): void;
|
|
65
|
+
private unbindOwn;
|
|
62
66
|
private unbindAll;
|
|
63
67
|
log(msg: any): void;
|
|
64
68
|
warn(msg: any): void;
|
|
@@ -4,7 +4,7 @@ import { Net } from './Net.js';
|
|
|
4
4
|
import { NetRequest } from './NetRequest.js';
|
|
5
5
|
import { EventEmitter } from '../EventEmitter.js';
|
|
6
6
|
export class ClientComponent extends EventEmitter {
|
|
7
|
-
constructor(parent, name, domNode,
|
|
7
|
+
constructor(parent, name, domNode, app) {
|
|
8
8
|
super();
|
|
9
9
|
this.children = [];
|
|
10
10
|
this.net = new Net();
|
|
@@ -31,15 +31,35 @@ export class ClientComponent extends EventEmitter {
|
|
|
31
31
|
this.root = parent.root;
|
|
32
32
|
this.parent = parent;
|
|
33
33
|
}
|
|
34
|
-
this.
|
|
35
|
-
this.store = new DataStoreView(this.
|
|
34
|
+
this.app = app;
|
|
35
|
+
this.store = new DataStoreView(this.app.store, this);
|
|
36
|
+
const self = this;
|
|
37
|
+
this.fn = new Proxy(this.store, {
|
|
38
|
+
set(target, key, val) {
|
|
39
|
+
const fnKey = `fn_${key}`;
|
|
40
|
+
if (target.has(fnKey)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
target.set(fnKey, val);
|
|
44
|
+
return true;
|
|
45
|
+
},
|
|
46
|
+
get(target, key) {
|
|
47
|
+
return target.get(`fn_${key}`) || (() => {
|
|
48
|
+
self.warn(`Function ${key} not defined`);
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
});
|
|
36
52
|
if (this.isRoot) {
|
|
37
53
|
this.init(false);
|
|
38
54
|
}
|
|
39
55
|
}
|
|
40
|
-
async init(isRedraw) {
|
|
41
|
-
const initializerExists =
|
|
56
|
+
async init(isRedraw, data = {}) {
|
|
57
|
+
const initializerExists = this.app.hasInitializer(this.name);
|
|
42
58
|
this.reset();
|
|
59
|
+
this.initData();
|
|
60
|
+
objectEach(data, (key, val) => {
|
|
61
|
+
this.setData(key, val, false);
|
|
62
|
+
});
|
|
43
63
|
this.initChildren();
|
|
44
64
|
await Promise.all(this.children.map(async (child) => {
|
|
45
65
|
await child.init(isRedraw);
|
|
@@ -48,9 +68,7 @@ export class ClientComponent extends EventEmitter {
|
|
|
48
68
|
this.store.import(undefined, false, false);
|
|
49
69
|
}
|
|
50
70
|
this.initRefs();
|
|
51
|
-
this.initData();
|
|
52
71
|
this.initModels();
|
|
53
|
-
this.promoteRefs();
|
|
54
72
|
this.initConditionals();
|
|
55
73
|
await this.runInitializer(isRedraw);
|
|
56
74
|
this.updateConditionals(false);
|
|
@@ -78,34 +96,15 @@ export class ClientComponent extends EventEmitter {
|
|
|
78
96
|
this.children = [];
|
|
79
97
|
}
|
|
80
98
|
async runInitializer(isRedraw = false) {
|
|
81
|
-
const initializer = window.initializers[this.name];
|
|
82
|
-
if (!initializer) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
99
|
if (!this.initializerExecuted && !this.destroyed) {
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
initializerFunction = new AsyncFunction(`
|
|
90
|
-
const init = ${initializer};
|
|
91
|
-
if (!this.destroyed) {
|
|
92
|
-
try {
|
|
93
|
-
await init.apply(this, [...arguments]);
|
|
94
|
-
} catch(e) {
|
|
95
|
-
console.error('Error in component ${this.name}: ' + e.message, this);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
`);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
initializerFunction = initializer;
|
|
102
|
-
}
|
|
103
|
-
if (initializerFunction) {
|
|
104
|
-
await initializerFunction.apply(this, [{
|
|
105
|
-
net: this.net,
|
|
106
|
-
isRedraw
|
|
107
|
-
}]);
|
|
100
|
+
const initializer = this.app.getInitializer(this.name);
|
|
101
|
+
if (initializer === null) {
|
|
102
|
+
return;
|
|
108
103
|
}
|
|
104
|
+
await initializer.apply(this, [{
|
|
105
|
+
net: this.net,
|
|
106
|
+
isRedraw
|
|
107
|
+
}]);
|
|
109
108
|
}
|
|
110
109
|
this.initializerExecuted = true;
|
|
111
110
|
}
|
|
@@ -159,7 +158,7 @@ export class ClientComponent extends EventEmitter {
|
|
|
159
158
|
const childNode = scope.childNodes[i];
|
|
160
159
|
if (childNode.nodeType == 1) {
|
|
161
160
|
if (childNode.hasAttribute(`data-${window.structuredClientConfig.componentNameAttribute}`)) {
|
|
162
|
-
const component = new ClientComponent(this, childNode.getAttribute(`data-${window.structuredClientConfig.componentNameAttribute}`) || '', childNode, this.
|
|
161
|
+
const component = new ClientComponent(this, childNode.getAttribute(`data-${window.structuredClientConfig.componentNameAttribute}`) || '', childNode, this.app);
|
|
163
162
|
this.children.push(component);
|
|
164
163
|
if (typeof callback === 'function') {
|
|
165
164
|
callback(component);
|
|
@@ -179,11 +178,12 @@ export class ClientComponent extends EventEmitter {
|
|
|
179
178
|
if (this.destroyed) {
|
|
180
179
|
return;
|
|
181
180
|
}
|
|
182
|
-
this.emit('beforeRedraw');
|
|
181
|
+
await this.emit('beforeRedraw');
|
|
183
182
|
if (this.redrawRequest !== null) {
|
|
184
183
|
this.redrawRequest.abort();
|
|
185
184
|
this.redrawRequest = null;
|
|
186
185
|
}
|
|
186
|
+
this.unbindOwn();
|
|
187
187
|
const redrawRequest = new NetRequest('POST', window.structuredClientConfig.componentRender, {
|
|
188
188
|
'content-type': 'application/json'
|
|
189
189
|
});
|
|
@@ -204,19 +204,14 @@ export class ClientComponent extends EventEmitter {
|
|
|
204
204
|
for (let i = 0; i < childrenOld.length; i++) {
|
|
205
205
|
const child = childrenOld[i];
|
|
206
206
|
childStoreChangeCallbacks[child.getData('componentId')] = child.store.onChangeCallbacks();
|
|
207
|
-
await child.
|
|
207
|
+
await child.destroy();
|
|
208
208
|
}
|
|
209
209
|
const componentData = JSON.parse(componentDataJSON);
|
|
210
210
|
this.domNode.innerHTML = componentData.html;
|
|
211
|
-
|
|
212
|
-
this.
|
|
213
|
-
});
|
|
214
|
-
for (const key in componentData.initializers) {
|
|
215
|
-
if (!window.initializers[key]) {
|
|
216
|
-
window.initializers[key] = componentData.initializers[key];
|
|
217
|
-
}
|
|
211
|
+
for (const componentName in componentData.initializers) {
|
|
212
|
+
this.app.registerInitializer(componentName, componentData.initializers[componentName]);
|
|
218
213
|
}
|
|
219
|
-
await this.init(true);
|
|
214
|
+
await this.init(true, componentData.data);
|
|
220
215
|
for (let i = 0; i < this.children.length; i++) {
|
|
221
216
|
const childNew = this.children[i];
|
|
222
217
|
const childNewId = childNew.getData('componentId');
|
|
@@ -229,7 +224,7 @@ export class ClientComponent extends EventEmitter {
|
|
|
229
224
|
});
|
|
230
225
|
}
|
|
231
226
|
}
|
|
232
|
-
this.emit('afterRedraw');
|
|
227
|
+
await this.emit('afterRedraw');
|
|
233
228
|
}
|
|
234
229
|
initConditionals(node) {
|
|
235
230
|
const isSelf = node === undefined;
|
|
@@ -274,6 +269,7 @@ export class ClientComponent extends EventEmitter {
|
|
|
274
269
|
this.initRefs(child);
|
|
275
270
|
}
|
|
276
271
|
});
|
|
272
|
+
this.promoteRefs();
|
|
277
273
|
}
|
|
278
274
|
initModels(node, modelNodes = []) {
|
|
279
275
|
const isSelf = node === undefined;
|
|
@@ -503,19 +499,6 @@ export class ClientComponent extends EventEmitter {
|
|
|
503
499
|
}
|
|
504
500
|
});
|
|
505
501
|
}
|
|
506
|
-
async remove() {
|
|
507
|
-
if (!this.isRoot) {
|
|
508
|
-
const children = Array.from(this.children);
|
|
509
|
-
for (let i = 0; i < children.length; i++) {
|
|
510
|
-
await children[i].remove();
|
|
511
|
-
}
|
|
512
|
-
if (this.parent) {
|
|
513
|
-
this.parent.children.splice(this.parent.children.indexOf(this), 1);
|
|
514
|
-
}
|
|
515
|
-
this.domNode.parentElement?.removeChild(this.domNode);
|
|
516
|
-
await this.destroy();
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
502
|
parentFind(parentName) {
|
|
520
503
|
let parent = this.parent;
|
|
521
504
|
while (true) {
|
|
@@ -578,17 +561,15 @@ export class ClientComponent extends EventEmitter {
|
|
|
578
561
|
unwrap: false
|
|
579
562
|
}));
|
|
580
563
|
const res = JSON.parse(componentDataJSON);
|
|
581
|
-
for (let
|
|
582
|
-
|
|
583
|
-
window.initializers[key] = res.initializers[key];
|
|
584
|
-
}
|
|
564
|
+
for (let componentName in res.initializers) {
|
|
565
|
+
this.app.registerInitializer(componentName, res.initializers[componentName]);
|
|
585
566
|
}
|
|
586
567
|
const tmpContainer = document.createElement('div');
|
|
587
568
|
tmpContainer.innerHTML = res.html;
|
|
588
569
|
const componentNode = tmpContainer.firstChild;
|
|
589
|
-
const component = new ClientComponent(this, componentName, componentNode, this.
|
|
570
|
+
const component = new ClientComponent(this, componentName, componentNode, this.app);
|
|
590
571
|
this.children.push(component);
|
|
591
|
-
await component.init(false);
|
|
572
|
+
await component.init(false, res.data);
|
|
592
573
|
container.appendChild(componentNode);
|
|
593
574
|
return component;
|
|
594
575
|
}
|
|
@@ -775,19 +756,25 @@ export class ClientComponent extends EventEmitter {
|
|
|
775
756
|
this.redrawRequest.abort();
|
|
776
757
|
this.redrawRequest = null;
|
|
777
758
|
}
|
|
778
|
-
this.emit('beforeDestroy');
|
|
759
|
+
await this.emit('beforeDestroy');
|
|
760
|
+
this.domNode.parentElement?.removeChild(this.domNode);
|
|
761
|
+
const children = Array.from(this.children);
|
|
762
|
+
for (let i = 0; i < children.length; i++) {
|
|
763
|
+
await children[i].destroy();
|
|
764
|
+
}
|
|
765
|
+
if (this.parent) {
|
|
766
|
+
this.parent.children.splice(this.parent.children.indexOf(this), 1);
|
|
767
|
+
}
|
|
779
768
|
this.store.destroy();
|
|
780
769
|
this.unbindAll();
|
|
781
|
-
this.
|
|
782
|
-
this.conditionalClassNames = [];
|
|
783
|
-
this.conditionalCallbacks = {};
|
|
784
|
-
this.refs = {};
|
|
785
|
-
this.refsArray = {};
|
|
786
|
-
this.data = {};
|
|
770
|
+
this.reset();
|
|
787
771
|
this.destroyed = true;
|
|
788
|
-
this.emit('afterDestroy');
|
|
772
|
+
await this.emit('afterDestroy');
|
|
789
773
|
this.emitterDestroy();
|
|
790
774
|
}
|
|
775
|
+
async remove() {
|
|
776
|
+
await this.destroy();
|
|
777
|
+
}
|
|
791
778
|
bind(element, event, callback) {
|
|
792
779
|
if (Array.isArray(element)) {
|
|
793
780
|
element.forEach((el) => {
|
|
@@ -801,19 +788,33 @@ export class ClientComponent extends EventEmitter {
|
|
|
801
788
|
});
|
|
802
789
|
return;
|
|
803
790
|
}
|
|
804
|
-
|
|
805
|
-
|
|
791
|
+
if (element instanceof HTMLElement || element instanceof Window) {
|
|
792
|
+
const cb = callback;
|
|
806
793
|
const callbackWrapper = (e) => {
|
|
807
|
-
|
|
794
|
+
cb.apply(this, [
|
|
795
|
+
e,
|
|
796
|
+
element instanceof Window ? undefined : this.attributeData(element),
|
|
797
|
+
element
|
|
798
|
+
]);
|
|
808
799
|
};
|
|
809
800
|
this.bound.push({
|
|
810
801
|
element,
|
|
811
|
-
event,
|
|
802
|
+
event: event,
|
|
812
803
|
callback: callbackWrapper,
|
|
813
804
|
callbackOriginal: callback
|
|
814
805
|
});
|
|
815
806
|
element.addEventListener(event, callbackWrapper);
|
|
816
807
|
}
|
|
808
|
+
else if (element instanceof ClientComponent) {
|
|
809
|
+
const cb = callback;
|
|
810
|
+
this.bound.push({
|
|
811
|
+
element,
|
|
812
|
+
event: event,
|
|
813
|
+
callback: cb,
|
|
814
|
+
callbackOriginal: cb
|
|
815
|
+
});
|
|
816
|
+
element.on(event, cb);
|
|
817
|
+
}
|
|
817
818
|
}
|
|
818
819
|
unbind(element, event, callback) {
|
|
819
820
|
if (Array.isArray(event)) {
|
|
@@ -827,13 +828,25 @@ export class ClientComponent extends EventEmitter {
|
|
|
827
828
|
});
|
|
828
829
|
if (boundIndex > -1) {
|
|
829
830
|
const bound = this.bound[boundIndex];
|
|
830
|
-
bound.element
|
|
831
|
-
|
|
831
|
+
if (bound.element instanceof ClientComponent) {
|
|
832
|
+
bound.element.off(bound.event, bound.callback);
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
bound.element.removeEventListener(bound.event, bound.callback);
|
|
836
|
+
this.bound.splice(boundIndex, 1);
|
|
837
|
+
}
|
|
832
838
|
}
|
|
833
839
|
}
|
|
840
|
+
unbindOwn() {
|
|
841
|
+
this.bound.forEach((bound) => {
|
|
842
|
+
if (bound.element === this) {
|
|
843
|
+
this.unbind(bound.element, bound.event, bound.callback);
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
}
|
|
834
847
|
unbindAll() {
|
|
835
848
|
this.bound.forEach((bound) => {
|
|
836
|
-
bound.element
|
|
849
|
+
this.unbind(bound.element, bound.event, bound.callbackOriginal);
|
|
837
850
|
});
|
|
838
851
|
this.bound = [];
|
|
839
852
|
}
|
|
@@ -10,6 +10,7 @@ export declare class DataStoreView {
|
|
|
10
10
|
get<T>(key: string): T | undefined;
|
|
11
11
|
toggle(key: string): void;
|
|
12
12
|
keys(): Array<string>;
|
|
13
|
+
has(key: string): boolean;
|
|
13
14
|
import(fields?: Array<string>, force?: boolean, triggerListeners?: boolean): void;
|
|
14
15
|
clear(): void;
|
|
15
16
|
destroy(): void;
|
|
@@ -23,7 +23,10 @@ export class DataStoreView {
|
|
|
23
23
|
if (this.destroyed) {
|
|
24
24
|
return [];
|
|
25
25
|
}
|
|
26
|
-
return Object.keys(this.store.get(this.componentId()));
|
|
26
|
+
return Object.keys(this.store.get(this.componentId()) || {});
|
|
27
|
+
}
|
|
28
|
+
has(key) {
|
|
29
|
+
return this.keys().includes(key);
|
|
27
30
|
}
|
|
28
31
|
import(fields, force = false, triggerListeners = true) {
|
|
29
32
|
const fieldsImported = Array.isArray(fields) ? fields : Object.keys(this.component.getData());
|
|
@@ -2,8 +2,9 @@ import { ClientComponent } from "../client/ClientComponent.js";
|
|
|
2
2
|
import { Net } from "../client/Net.js";
|
|
3
3
|
import { Application } from "../server/Application.js";
|
|
4
4
|
import { Component } from "../server/Component.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { EventEmitterCallback } from "./eventEmitter.types.js";
|
|
6
|
+
import { KeysOfUnion, LooseObject } from './general.types.js';
|
|
7
|
+
import { RequestContext } from "./request.types.js";
|
|
7
8
|
export type ComponentEntry = {
|
|
8
9
|
name: string;
|
|
9
10
|
path: {
|
|
@@ -21,18 +22,18 @@ export type ComponentEntry = {
|
|
|
21
22
|
static: boolean;
|
|
22
23
|
renderTagName?: string;
|
|
23
24
|
exportData: boolean;
|
|
24
|
-
exportFields?:
|
|
25
|
+
exportFields?: ReadonlyArray<string>;
|
|
25
26
|
attributes?: Record<string, string>;
|
|
26
27
|
initializer?: InitializerFunction;
|
|
27
28
|
};
|
|
28
|
-
export interface ComponentScaffold {
|
|
29
|
+
export interface ComponentScaffold<T extends LooseObject = LooseObject, K extends KeysOfUnion<T> = KeysOfUnion<T>> {
|
|
29
30
|
tagName?: string;
|
|
30
31
|
exportData?: boolean;
|
|
31
|
-
exportFields?:
|
|
32
|
+
exportFields?: ReadonlyArray<K>;
|
|
32
33
|
static?: boolean;
|
|
33
34
|
deferred?: (data: Record<string, any>, ctx: RequestContext | undefined, app: Application) => boolean;
|
|
34
35
|
attributes?: Record<string, string>;
|
|
35
|
-
getData: (this: ComponentScaffold, data:
|
|
36
|
+
getData: (this: ComponentScaffold, data: LooseObject, ctx: undefined | RequestContext, app: Application, component: Component) => Promise<T | void>;
|
|
36
37
|
[key: string]: any;
|
|
37
38
|
}
|
|
38
39
|
export type ClientComponentTransition = {
|
|
@@ -42,11 +43,11 @@ export type ClientComponentTransition = {
|
|
|
42
43
|
};
|
|
43
44
|
export type ClientComponentTransitionEvent = 'show' | 'hide';
|
|
44
45
|
export type ClientComponentTransitions = Record<ClientComponentTransitionEvent, ClientComponentTransition>;
|
|
45
|
-
export type ClientComponentBoundEvent<T extends LooseObject | undefined
|
|
46
|
-
element:
|
|
46
|
+
export type ClientComponentBoundEvent<T extends LooseObject | undefined, E extends HTMLElement | Window | ClientComponent> = {
|
|
47
|
+
element: E;
|
|
47
48
|
event: keyof HTMLElementEventMap;
|
|
48
|
-
callback: (e: Event) => void;
|
|
49
|
-
callbackOriginal: ClientComponentEventCallback<T>;
|
|
49
|
+
callback: E extends ClientComponent ? EventEmitterCallback<T> : (e: Event) => void;
|
|
50
|
+
callbackOriginal: E extends ClientComponent ? EventEmitterCallback<T> : ClientComponentEventCallback<T>;
|
|
50
51
|
};
|
|
51
52
|
export type ClientComponentEventCallback<T> = (e: Event, data: T, element: HTMLElement | Window) => void;
|
|
52
53
|
export type InitializerFunction = (this: ClientComponent, ctx: InitializerFunctionContext) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type EventEmitterCallback<T> = (payload: T, eventName: string) => void
|
|
1
|
+
export type EventEmitterCallback<T> = (payload: T, eventName: string) => void | Promise<void>;
|
package/package.json
CHANGED
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"type": "module",
|
|
21
21
|
"main": "build/index",
|
|
22
|
-
"version": "1.1.
|
|
22
|
+
"version": "1.1.5",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"develop": "tsc --watch",
|
|
25
25
|
"startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,hbs,css index.js",
|
|
26
26
|
"start": "cd build && node index.js",
|
|
27
27
|
"compileAndPack": "tsc && npm pack",
|
|
28
|
-
"compileAndPublish": "tsc && npm publish"
|
|
28
|
+
"compileAndPublish": "rm -r build && tsc && npm publish"
|
|
29
29
|
},
|
|
30
30
|
"bin": {
|
|
31
31
|
"structured": "./build/system/bin/structured.js"
|