@zcomponent/core 0.0.13 → 0.0.15
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/lib/actionbehavior.js +2 -2
- package/lib/behavior.d.ts +0 -1
- package/lib/behavior.js +1 -2
- package/lib/component.d.ts +1 -2
- package/lib/component.js +1 -2
- package/lib/contexts/canvascontext.d.ts +2 -0
- package/lib/contexts/canvascontext.js +4 -3
- package/lib/contexts/environmentcontext.d.ts +10 -0
- package/lib/contexts/environmentcontext.js +13 -1
- package/lib/contexts/loadcontext.d.ts +5 -0
- package/lib/contexts/loadcontext.js +5 -0
- package/lib/data.d.ts +6 -1
- package/lib/data.js +82 -0
- package/lib/emitter.d.ts +25 -0
- package/lib/emitter.js +69 -0
- package/lib/entity.d.ts +14 -3
- package/lib/entity.js +35 -16
- package/lib/event.d.ts +2 -17
- package/lib/event.js +3 -53
- package/lib/interfaces.d.ts +30 -6
- package/lib/interfaces.js +6 -1
- package/lib/observable.d.ts +3 -6
- package/lib/observable.js +7 -32
- package/lib/selectors.d.ts +15 -3
- package/lib/selectors.js +78 -7
- package/lib/types.d.ts +31 -4
- package/lib/types.js +61 -0
- package/lib/zcomponent.d.ts +8 -2
- package/lib/zcomponent.js +101 -18
- package/package.json +4 -3
package/lib/actionbehavior.js
CHANGED
|
@@ -24,7 +24,7 @@ export class ActionBehavior extends Behavior {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
const env = contextManager.get(EnvironmentContext);
|
|
27
|
-
this.register(env.editTime, this._updateRegistration);
|
|
28
|
-
this.register(this.enabledResolved, this._updateRegistration);
|
|
27
|
+
this.register(env.editTime, this._updateRegistration, { bindWhenDisabled: true });
|
|
28
|
+
this.register(this.enabledResolved, this._updateRegistration, { bindWhenDisabled: true });
|
|
29
29
|
}
|
|
30
30
|
}
|
package/lib/behavior.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export type BehaviorConstructorProps = {
|
|
|
7
7
|
[id: string]: unknown;
|
|
8
8
|
};
|
|
9
9
|
export declare class Behavior<InstanceType extends Component = Component> extends Entity {
|
|
10
|
-
protected readonly contextManager: ContextManager;
|
|
11
10
|
readonly instance: InstanceType;
|
|
12
11
|
/**
|
|
13
12
|
* Constructs this behavior
|
package/lib/behavior.js
CHANGED
|
@@ -7,8 +7,7 @@ export class Behavior extends Entity {
|
|
|
7
7
|
* @param instance The instance of the component that this behavior is attached to
|
|
8
8
|
*/
|
|
9
9
|
constructor(contextManager, instance) {
|
|
10
|
-
super();
|
|
11
|
-
this.contextManager = contextManager;
|
|
10
|
+
super(contextManager);
|
|
12
11
|
this.instance = instance;
|
|
13
12
|
this._updateEnabledResolved = () => {
|
|
14
13
|
let newValue = this.enabled.value;
|
package/lib/component.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type ConstructorForComponent<ComponentType extends Component = Component>
|
|
|
7
7
|
export type ComponentChild<ComponentType extends Component> = [ConstructorForComponent<ComponentType>, ComponentType extends Component<any, infer U> ? U : never] | [
|
|
8
8
|
ConstructorForComponent<ComponentType>,
|
|
9
9
|
ComponentType extends Component<any, infer U> ? U : never,
|
|
10
|
-
Observable<ComponentType>
|
|
10
|
+
Observable<ComponentType | undefined>
|
|
11
11
|
];
|
|
12
12
|
export type ComponentChildren = ComponentChild<Component>[];
|
|
13
13
|
export interface ConstructorProps {
|
|
@@ -15,7 +15,6 @@ export interface ConstructorProps {
|
|
|
15
15
|
children?: ComponentChildren;
|
|
16
16
|
}
|
|
17
17
|
export declare class Component<ElementType = any, ConstructorPropsType extends ConstructorProps = ConstructorProps> extends Entity {
|
|
18
|
-
readonly contextManager: ContextManager;
|
|
19
18
|
protected constructorProps?: ConstructorPropsType | undefined;
|
|
20
19
|
/**
|
|
21
20
|
* The raw element(s) that this component exposes
|
package/lib/component.js
CHANGED
|
@@ -3,8 +3,7 @@ import { Entity } from './entity';
|
|
|
3
3
|
import { Observable } from './observable';
|
|
4
4
|
export class Component extends Entity {
|
|
5
5
|
constructor(contextManager, constructorProps) {
|
|
6
|
-
super();
|
|
7
|
-
this.contextManager = contextManager;
|
|
6
|
+
super(contextManager);
|
|
8
7
|
this.constructorProps = constructorProps;
|
|
9
8
|
this.children = [];
|
|
10
9
|
/**
|
|
@@ -5,6 +5,7 @@ export interface CanvasContextOptions {
|
|
|
5
5
|
canvas?: HTMLCanvasElement;
|
|
6
6
|
overlay?: HTMLDivElement;
|
|
7
7
|
}
|
|
8
|
+
/** @zcontext */
|
|
8
9
|
export declare class CanvasContext extends Context {
|
|
9
10
|
constructorProps: CanvasContextOptions;
|
|
10
11
|
onBeforeRender: Event<[number]>;
|
|
@@ -12,6 +13,7 @@ export declare class CanvasContext extends Context {
|
|
|
12
13
|
canvas: HTMLCanvasElement;
|
|
13
14
|
overlayDefault: HTMLDivElement;
|
|
14
15
|
overlay: Observable<HTMLDivElement>;
|
|
16
|
+
/** @zui */
|
|
15
17
|
size: Observable<[number, number]>;
|
|
16
18
|
private _resizeObserver;
|
|
17
19
|
constructor(contextManager: ContextManager, constructorProps: CanvasContextOptions);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Context } from '../context';
|
|
2
2
|
import { Event } from '../event';
|
|
3
3
|
import { Observable } from '../observable';
|
|
4
|
+
/** @zcontext */
|
|
4
5
|
export class CanvasContext extends Context {
|
|
5
6
|
constructor(contextManager, constructorProps) {
|
|
6
7
|
super(contextManager, constructorProps);
|
|
@@ -36,7 +37,7 @@ export class CanvasContext extends Context {
|
|
|
36
37
|
this.size = new Observable([this.canvas.clientWidth, this.canvas.clientHeight]);
|
|
37
38
|
this._resizeObserver.observe(this.canvas);
|
|
38
39
|
let lastRect;
|
|
39
|
-
this.onBeforeRender.
|
|
40
|
+
this.onBeforeRender.addListener(() => {
|
|
40
41
|
const rect = this.canvas.getBoundingClientRect();
|
|
41
42
|
if (lastRect && lastRect.top === rect.top && lastRect.left === rect.left && lastRect.width === rect.width && lastRect.height === rect.height)
|
|
42
43
|
return;
|
|
@@ -48,8 +49,8 @@ export class CanvasContext extends Context {
|
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
51
|
dispose() {
|
|
51
|
-
this.onBeforeRender.
|
|
52
|
-
this.onAfterRender.
|
|
52
|
+
this.onBeforeRender.clearListeners();
|
|
53
|
+
this.onAfterRender.clearListeners();
|
|
53
54
|
this._resizeObserver.disconnect();
|
|
54
55
|
if (!this.constructorProps.canvas)
|
|
55
56
|
this.canvas.remove();
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { ContextManager, Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
+
/** @zcontext */
|
|
3
4
|
export declare class EnvironmentContext extends Context {
|
|
5
|
+
/** @zprop */
|
|
4
6
|
designTime: Observable<boolean, never>;
|
|
7
|
+
/** @zprop */
|
|
5
8
|
editTime: Observable<boolean, never>;
|
|
9
|
+
/** @zprop */
|
|
10
|
+
runTime: Observable<boolean, never>;
|
|
11
|
+
/** @zprop */
|
|
12
|
+
developmentBuild: Observable<boolean, never>;
|
|
13
|
+
/** @zprop */
|
|
14
|
+
productionBuild: Observable<boolean, never>;
|
|
6
15
|
}
|
|
7
16
|
export declare function isDesignTime(ctx: ContextManager): boolean;
|
|
8
17
|
export declare function isEditTime(ctx: ContextManager): boolean;
|
|
9
18
|
export declare function isDevelopmentBuild(ctx: ContextManager): boolean;
|
|
19
|
+
export declare function isProductionBuild(ctx: ContextManager): boolean;
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
+
/** @zcontext */
|
|
3
4
|
export class EnvironmentContext extends Context {
|
|
4
5
|
constructor() {
|
|
5
6
|
super(...arguments);
|
|
7
|
+
/** @zprop */
|
|
6
8
|
this.designTime = new Observable(false);
|
|
9
|
+
/** @zprop */
|
|
7
10
|
this.editTime = new Observable(false);
|
|
11
|
+
/** @zprop */
|
|
12
|
+
this.runTime = new Observable(true);
|
|
13
|
+
/** @zprop */
|
|
14
|
+
this.developmentBuild = new Observable(typeof process !== 'undefined' && process?.env?.NODE_ENV === 'development');
|
|
15
|
+
/** @zprop */
|
|
16
|
+
this.productionBuild = new Observable(!this.developmentBuild.value);
|
|
8
17
|
}
|
|
9
18
|
}
|
|
10
19
|
export function isDesignTime(ctx) {
|
|
@@ -14,5 +23,8 @@ export function isEditTime(ctx) {
|
|
|
14
23
|
return ctx.get(EnvironmentContext).editTime.value;
|
|
15
24
|
}
|
|
16
25
|
export function isDevelopmentBuild(ctx) {
|
|
17
|
-
return (
|
|
26
|
+
return ctx.get(EnvironmentContext).developmentBuild.value;
|
|
27
|
+
}
|
|
28
|
+
export function isProductionBuild(ctx) {
|
|
29
|
+
return ctx.get(EnvironmentContext).productionBuild.value;
|
|
18
30
|
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { ContextManager, Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
+
/** @zcontext */
|
|
3
4
|
export declare class LoadContext extends Context {
|
|
5
|
+
/** @zui */
|
|
4
6
|
isConstructed: Observable<boolean, never>;
|
|
7
|
+
/** @zui */
|
|
5
8
|
isLoaded: Observable<boolean, never>;
|
|
9
|
+
/** @zui */
|
|
6
10
|
isStarted: Observable<boolean, never>;
|
|
11
|
+
/** @zui */
|
|
7
12
|
progressPercent: Observable<number, never>;
|
|
8
13
|
private _startedResolved;
|
|
9
14
|
started: Promise<void>;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
+
/** @zcontext */
|
|
3
4
|
export class LoadContext extends Context {
|
|
4
5
|
constructor() {
|
|
5
6
|
super(...arguments);
|
|
7
|
+
/** @zui */
|
|
6
8
|
this.isConstructed = new Observable(false);
|
|
9
|
+
/** @zui */
|
|
7
10
|
this.isLoaded = new Observable(false);
|
|
11
|
+
/** @zui */
|
|
8
12
|
this.isStarted = new Observable(false);
|
|
13
|
+
/** @zui */
|
|
9
14
|
this.progressPercent = new Observable(0);
|
|
10
15
|
this.started = new Promise(resolve => this._startedResolved = resolve);
|
|
11
16
|
this._loadables = new Set();
|
package/lib/data.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { BehaviorByID, BehaviorData, ComputedHierarchy, NodeByID, NodeData, ZComponentData } from "./interfaces";
|
|
1
|
+
import { BehaviorByID, BehaviorData, ComputedHierarchy, EntityPropOverride, NodeByID, NodeData, ZComponentData } from "./interfaces";
|
|
2
|
+
import { Prop } from "./types";
|
|
2
3
|
export declare function computeNodeHierarchy(nodes: NodeByID): ComputedHierarchy;
|
|
3
4
|
export declare function computeBehaviorHierarchy(behaviors: BehaviorByID): ComputedHierarchy;
|
|
4
5
|
export declare function addNode(zcomp: ZComponentData, info: NodeDataCombined): void;
|
|
5
6
|
export declare function addBehavior(zcomp: ZComponentData, info: BehaviorDataCombined): void;
|
|
7
|
+
export declare function updateComponentProp(zcomp: ZComponentData, prop: string, isConstructorProp: boolean, newValue: Prop | undefined, newIsConstructorProp: boolean): void;
|
|
8
|
+
export declare function addEntityPropOverride(zcomp: ZComponentData, o: EntityPropOverride): void;
|
|
9
|
+
export declare function deleteEntityPropOverride(zcomp: ZComponentData, id: string): void;
|
|
10
|
+
export declare function clone<T>(obj: T): T;
|
|
6
11
|
export declare function addEntity(zcomp: ZComponentData, id: string, info: EntityDataCombined): void;
|
|
7
12
|
export declare function moveNodes(zcomp: ZComponentData, nodeIDs: string[], newParentID: string, indx: number): void;
|
|
8
13
|
export declare function deleteNode(zcomp: ZComponentData, id: string): void;
|
package/lib/data.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { generateKeyBetween, generateNKeysBetween } from "./fractionalindexing";
|
|
2
|
+
import { EntityPropOverrideType } from "./interfaces";
|
|
2
3
|
// Simple memoizing of computed hierarchy
|
|
3
4
|
const computedHierarchies = new Map();
|
|
4
5
|
const computedBehaviors = new Map();
|
|
@@ -66,6 +67,80 @@ export function addBehavior(zcomp, info) {
|
|
|
66
67
|
addEntity(zcomp, info.data.id, info);
|
|
67
68
|
computedBehaviors.delete(zcomp.behaviors);
|
|
68
69
|
}
|
|
70
|
+
export function updateComponentProp(zcomp, prop, isConstructorProp, newValue, newIsConstructorProp) {
|
|
71
|
+
if (zcomp.constructorProps === undefined)
|
|
72
|
+
zcomp.constructorProps = {};
|
|
73
|
+
if (newValue === undefined) {
|
|
74
|
+
if (isConstructorProp)
|
|
75
|
+
delete zcomp.constructorProps[prop];
|
|
76
|
+
else
|
|
77
|
+
delete zcomp.props[prop];
|
|
78
|
+
if (zcomp.entityPropOverrides) {
|
|
79
|
+
for (const [id, override] of Object.entries(zcomp.entityPropOverrides)) {
|
|
80
|
+
if (override.type !== EntityPropOverrideType.ComponentProp)
|
|
81
|
+
continue;
|
|
82
|
+
if (override.isConstructorProp !== isConstructorProp)
|
|
83
|
+
continue;
|
|
84
|
+
if (override.propName !== prop)
|
|
85
|
+
continue;
|
|
86
|
+
delete zcomp.entityPropOverrides[id];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (newValue.name !== prop || isConstructorProp !== newIsConstructorProp) {
|
|
92
|
+
if (isConstructorProp)
|
|
93
|
+
delete zcomp.constructorProps[prop];
|
|
94
|
+
else
|
|
95
|
+
delete zcomp.props[prop];
|
|
96
|
+
if (zcomp.entityPropOverrides) {
|
|
97
|
+
for (const [id, override] of Object.entries(zcomp.entityPropOverrides)) {
|
|
98
|
+
if (override.type !== EntityPropOverrideType.ComponentProp)
|
|
99
|
+
continue;
|
|
100
|
+
if (override.isConstructorProp !== isConstructorProp)
|
|
101
|
+
continue;
|
|
102
|
+
if (override.propName !== prop)
|
|
103
|
+
continue;
|
|
104
|
+
delete zcomp.entityPropOverrides[id];
|
|
105
|
+
if (!(override.entityPropIsConstructor && !newIsConstructorProp)) {
|
|
106
|
+
const newOverride = clone(override);
|
|
107
|
+
newOverride.propName = newValue.name;
|
|
108
|
+
newOverride.id = idForEntityPropOverride(override);
|
|
109
|
+
zcomp.entityPropOverrides[newOverride.id] = newOverride;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
newValue.type.isObservable = !newIsConstructorProp;
|
|
115
|
+
if (newIsConstructorProp)
|
|
116
|
+
zcomp.constructorProps[newValue.name] = newValue;
|
|
117
|
+
else
|
|
118
|
+
zcomp.props[newValue.name] = newValue;
|
|
119
|
+
}
|
|
120
|
+
export function addEntityPropOverride(zcomp, o) {
|
|
121
|
+
if (!zcomp.entityPropOverrides)
|
|
122
|
+
zcomp.entityPropOverrides = {};
|
|
123
|
+
o.id = idForEntityPropOverride(o);
|
|
124
|
+
zcomp.entityPropOverrides[o.id] = o;
|
|
125
|
+
}
|
|
126
|
+
export function deleteEntityPropOverride(zcomp, id) {
|
|
127
|
+
if (!zcomp.entityPropOverrides)
|
|
128
|
+
return;
|
|
129
|
+
delete zcomp.entityPropOverrides[id];
|
|
130
|
+
}
|
|
131
|
+
function idForEntityPropOverride(override) {
|
|
132
|
+
return override.type + ":" + (override.entityPropIsConstructor ? 'constructorprop' : 'prop') + ":" + override.entityID + ":" + override.entityPropPath.join('.');
|
|
133
|
+
}
|
|
134
|
+
export function clone(obj) {
|
|
135
|
+
try {
|
|
136
|
+
if (typeof structuredClone !== 'undefined')
|
|
137
|
+
return structuredClone(obj);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Ignore
|
|
141
|
+
}
|
|
142
|
+
return JSON.parse(JSON.stringify(obj));
|
|
143
|
+
}
|
|
69
144
|
export function addEntity(zcomp, id, info) {
|
|
70
145
|
zcomp.entityProps[id] = info.props;
|
|
71
146
|
zcomp.entityConstructorProps[id] = info.constructorProps;
|
|
@@ -265,6 +340,13 @@ export function changeNodeScriptName(zcomp, id, newScriptName) {
|
|
|
265
340
|
export function deleteEntity(zcomp, id) {
|
|
266
341
|
delete zcomp.entityProps[id];
|
|
267
342
|
delete zcomp.entityConstructorProps[id];
|
|
343
|
+
if (zcomp.entityPropOverrides) {
|
|
344
|
+
for (const [overrideID, override] of Object.entries(zcomp.entityPropOverrides)) {
|
|
345
|
+
if (override.entityID !== id)
|
|
346
|
+
continue;
|
|
347
|
+
delete zcomp.entityPropOverrides[overrideID];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
268
350
|
}
|
|
269
351
|
export function forEachNodeAncestor(zcomp, id, fn) {
|
|
270
352
|
const node = zcomp.nodes[id];
|
package/lib/emitter.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Observable } from "./observable";
|
|
2
|
+
export declare class Emitter<Args extends Array<any> = []> {
|
|
3
|
+
hasListeners: Observable<boolean, never>;
|
|
4
|
+
private _funcs;
|
|
5
|
+
private _emitting;
|
|
6
|
+
private _toUnbind;
|
|
7
|
+
private _needsSort;
|
|
8
|
+
clearListeners(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Add a new handler function
|
|
11
|
+
* @param f - The callback function to be bound.
|
|
12
|
+
*/
|
|
13
|
+
addListener(f: (...args: Args) => void, priority?: number): void;
|
|
14
|
+
/**
|
|
15
|
+
* Unbind an existing function
|
|
16
|
+
* @param f - The callback function to be unbound.
|
|
17
|
+
*/
|
|
18
|
+
removeListener(f: (...args: Args) => void): void;
|
|
19
|
+
/**
|
|
20
|
+
* Emit an event
|
|
21
|
+
*
|
|
22
|
+
* @param a - The argument to pass to handler functions.
|
|
23
|
+
*/
|
|
24
|
+
protected _emit(...args: Args): void;
|
|
25
|
+
}
|
package/lib/emitter.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Observable } from "./observable";
|
|
2
|
+
export class Emitter {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.hasListeners = new Observable(false);
|
|
5
|
+
this._funcs = [];
|
|
6
|
+
this._emitting = false;
|
|
7
|
+
this._toUnbind = new Set();
|
|
8
|
+
this._needsSort = false;
|
|
9
|
+
}
|
|
10
|
+
clearListeners() {
|
|
11
|
+
this._funcs = [];
|
|
12
|
+
this.hasListeners.value = false;
|
|
13
|
+
this._needsSort = false;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Add a new handler function
|
|
17
|
+
* @param f - The callback function to be bound.
|
|
18
|
+
*/
|
|
19
|
+
addListener(f, priority = 0) {
|
|
20
|
+
this._funcs.push([f, priority]);
|
|
21
|
+
this._needsSort = true;
|
|
22
|
+
if (!this.hasListeners.value)
|
|
23
|
+
this.hasListeners.value = true;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Unbind an existing function
|
|
27
|
+
* @param f - The callback function to be unbound.
|
|
28
|
+
*/
|
|
29
|
+
removeListener(f) {
|
|
30
|
+
if (this._emitting) {
|
|
31
|
+
this._toUnbind.add(f);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this._toUnbind.delete(f);
|
|
35
|
+
const indx = this._funcs.findIndex(entry => entry[0] === f);
|
|
36
|
+
if (indx > -1) {
|
|
37
|
+
this._funcs.splice(indx, 1);
|
|
38
|
+
}
|
|
39
|
+
if (this._funcs.length === 0 && this.hasListeners.value)
|
|
40
|
+
this.hasListeners.value = false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Emit an event
|
|
44
|
+
*
|
|
45
|
+
* @param a - The argument to pass to handler functions.
|
|
46
|
+
*/
|
|
47
|
+
_emit(...args) {
|
|
48
|
+
if (this._needsSort) {
|
|
49
|
+
this._funcs.sort((a, b) => b[1] - a[1]);
|
|
50
|
+
this._needsSort = false;
|
|
51
|
+
}
|
|
52
|
+
this._emitting = true;
|
|
53
|
+
for (let i = 0, total = this._funcs.length; i < total; i++) {
|
|
54
|
+
const fn = this._funcs[i][0];
|
|
55
|
+
try {
|
|
56
|
+
if (this._toUnbind.has(fn))
|
|
57
|
+
continue;
|
|
58
|
+
fn(...args);
|
|
59
|
+
}
|
|
60
|
+
catch (ex) {
|
|
61
|
+
console.log('Exception in event handler', ex);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
this._emitting = false;
|
|
65
|
+
if (this._toUnbind.size > 0) {
|
|
66
|
+
this._toUnbind.forEach(fn => this.removeListener(fn));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
package/lib/entity.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { ConstructorForComponent } from "./component";
|
|
2
|
+
import { ContextManager } from "./context";
|
|
2
3
|
import { Event } from "./event";
|
|
3
4
|
import { Observable } from "./observable";
|
|
4
5
|
import { ZComponent } from "./zcomponent";
|
|
5
6
|
export declare class Entity {
|
|
7
|
+
readonly contextManager: ContextManager;
|
|
6
8
|
private _registered;
|
|
9
|
+
private _handlersBound;
|
|
7
10
|
private _zcomponent;
|
|
8
11
|
private _disposed;
|
|
9
12
|
/**
|
|
10
13
|
* An event that is fired as the last act of this entity being destroyed.
|
|
11
14
|
*/
|
|
12
15
|
readonly onDispose: Event<[]>;
|
|
13
|
-
constructor();
|
|
16
|
+
constructor(contextManager: ContextManager);
|
|
14
17
|
get disposed(): boolean;
|
|
15
18
|
private set disposed(value);
|
|
16
19
|
/**
|
|
@@ -62,6 +65,7 @@ export declare class Entity {
|
|
|
62
65
|
getZComponentInstance<T extends ZComponent = ZComponent>(type?: ConstructorForComponent<T>): T;
|
|
63
66
|
/**
|
|
64
67
|
* Register a function to be called when an Event is fired, or an Observable's value changes.
|
|
68
|
+
* The function will only be bound to the underlying Event or Observable while this entity is enabled.
|
|
65
69
|
*
|
|
66
70
|
* Using this function, rather than attaching your handler directly to the Event or Observable,
|
|
67
71
|
* ensures your handler is automatically released when this entity is disposed.
|
|
@@ -69,8 +73,10 @@ export declare class Entity {
|
|
|
69
73
|
* @param evt The Event or Observable to listen to
|
|
70
74
|
* @param fn A function that will be called when the event fires, or the Observable value changes
|
|
71
75
|
*/
|
|
72
|
-
register<Args extends Array<any>>(evt: Event<Args>, fn: (...args: Args) => void): any;
|
|
73
|
-
register<
|
|
76
|
+
register<Args extends Array<any>>(evt: Event<Args>, fn: (...args: Args) => void, priority?: number): any;
|
|
77
|
+
register<Args extends Array<any>>(evt: Event<Args>, fn: (...args: Args) => void, options?: RegisterOptions): any;
|
|
78
|
+
register<Type>(observable: Observable<Type>, fn: (v: Type) => void, priority?: number): any;
|
|
79
|
+
register<Type>(observable: Observable<Type>, fn: (v: Type) => void, options?: RegisterOptions): any;
|
|
74
80
|
/**
|
|
75
81
|
* Unregisters a function that was previously registered to an Event or Observable.
|
|
76
82
|
*
|
|
@@ -79,6 +85,7 @@ export declare class Entity {
|
|
|
79
85
|
*/
|
|
80
86
|
unregister<Args extends Array<any>>(evt: Event<Args>, fn: (...args: Args) => void): any;
|
|
81
87
|
unregister<Type>(observable: Observable<Type>, fn: (v: Type) => void): any;
|
|
88
|
+
private _updateHandlers;
|
|
82
89
|
/**
|
|
83
90
|
* Destroy this entity, cleaning up any resources that it has created and
|
|
84
91
|
* handler functions or callbacks it has registered.
|
|
@@ -100,3 +107,7 @@ export declare class Entity {
|
|
|
100
107
|
dispose(): never;
|
|
101
108
|
private static callSuperDispose;
|
|
102
109
|
}
|
|
110
|
+
export interface RegisterOptions {
|
|
111
|
+
priority?: number;
|
|
112
|
+
bindWhenDisabled?: boolean;
|
|
113
|
+
}
|
package/lib/entity.js
CHANGED
|
@@ -2,8 +2,10 @@ import { Event } from "./event";
|
|
|
2
2
|
import { Observable } from "./observable";
|
|
3
3
|
import { getCurrentZComponentConstruction } from "./zcomponentconstruction";
|
|
4
4
|
export class Entity {
|
|
5
|
-
constructor() {
|
|
5
|
+
constructor(contextManager) {
|
|
6
|
+
this.contextManager = contextManager;
|
|
6
7
|
this._registered = [];
|
|
8
|
+
this._handlersBound = false;
|
|
7
9
|
this._disposed = false;
|
|
8
10
|
/**
|
|
9
11
|
* An event that is fired as the last act of this entity being destroyed.
|
|
@@ -45,7 +47,24 @@ export class Entity {
|
|
|
45
47
|
* Disabled entities will typically remain visible (if they have a visible appearance).
|
|
46
48
|
*/
|
|
47
49
|
this.enabledResolved = new Observable(true);
|
|
50
|
+
this._updateHandlers = (enabled) => {
|
|
51
|
+
if (enabled && !this._handlersBound) {
|
|
52
|
+
for (const [e, fn, priority] of this._registered) {
|
|
53
|
+
e.addListener(fn, priority);
|
|
54
|
+
}
|
|
55
|
+
this._handlersBound = true;
|
|
56
|
+
}
|
|
57
|
+
if (!enabled && this._handlersBound) {
|
|
58
|
+
for (const [e, fn, _, bindWhenDisabled] of this._registered) {
|
|
59
|
+
if (bindWhenDisabled)
|
|
60
|
+
continue;
|
|
61
|
+
e.removeListener(fn);
|
|
62
|
+
}
|
|
63
|
+
this._handlersBound = false;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
48
66
|
this._zcomponent = getCurrentZComponentConstruction();
|
|
67
|
+
this.enabledResolved.addListener(this._updateHandlers);
|
|
49
68
|
}
|
|
50
69
|
get disposed() {
|
|
51
70
|
return this._disposed;
|
|
@@ -72,18 +91,20 @@ export class Entity {
|
|
|
72
91
|
return this._zcomponent;
|
|
73
92
|
throw new Error("getZComponentInstance called in entity passing wrong kind of ZComponent");
|
|
74
93
|
}
|
|
75
|
-
register(e, fn) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
e
|
|
80
|
-
|
|
94
|
+
register(e, fn, priorityOrOptions) {
|
|
95
|
+
const priority = (typeof priorityOrOptions === 'number' ? priorityOrOptions : priorityOrOptions?.priority);
|
|
96
|
+
const bindWhenDisabled = (typeof priorityOrOptions === 'number' ? false : priorityOrOptions?.bindWhenDisabled);
|
|
97
|
+
for (const entry of this._registered) {
|
|
98
|
+
if (entry[0] === e && entry[1] === fn)
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this._registered.push([e, fn, priority, bindWhenDisabled ?? false]);
|
|
102
|
+
if (this._handlersBound || bindWhenDisabled) {
|
|
103
|
+
e.addListener(fn, priority);
|
|
104
|
+
}
|
|
81
105
|
}
|
|
82
106
|
unregister(e, fn) {
|
|
83
|
-
|
|
84
|
-
e.unbindfn(fn);
|
|
85
|
-
else if (e instanceof Observable)
|
|
86
|
-
e.removeWithValue(fn);
|
|
107
|
+
e.removeListener(fn);
|
|
87
108
|
this._registered = this._registered.filter(entry => (entry[0] !== e || entry[1] !== fn));
|
|
88
109
|
}
|
|
89
110
|
/**
|
|
@@ -105,15 +126,13 @@ export class Entity {
|
|
|
105
126
|
* @returns The result of a call to super.dispose()
|
|
106
127
|
*/
|
|
107
128
|
dispose() {
|
|
129
|
+
this.enabledResolved.removeListener(this._updateHandlers);
|
|
108
130
|
for (const entry of this._registered) {
|
|
109
|
-
|
|
110
|
-
entry[0].unbindfn(entry[1]);
|
|
111
|
-
else if (entry[0] instanceof Observable)
|
|
112
|
-
entry[0].removeWithValue(entry[1]);
|
|
131
|
+
entry[0].removeListener(entry[1]);
|
|
113
132
|
}
|
|
114
133
|
this._registered = [];
|
|
115
134
|
this.onDispose.emit();
|
|
116
|
-
this.onDispose.
|
|
135
|
+
this.onDispose.clearListeners();
|
|
117
136
|
this.disposed = true;
|
|
118
137
|
return undefined;
|
|
119
138
|
}
|
package/lib/event.d.ts
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class Event<Args extends Array<any> = []> {
|
|
3
|
-
hasBindings: Observable<boolean, never>;
|
|
4
|
-
private _funcs;
|
|
5
|
-
private _emitting;
|
|
6
|
-
private _toUnbind;
|
|
7
|
-
clear(): void;
|
|
8
|
-
/**
|
|
9
|
-
* Bind new handler function.
|
|
10
|
-
* @param f - The callback function to be bound.
|
|
11
|
-
*/
|
|
12
|
-
bindfn(f: (...args: Args) => void): void;
|
|
13
|
-
/**
|
|
14
|
-
* Unbind an existing function.
|
|
15
|
-
* @param f - The callback function to be unbound.
|
|
16
|
-
*/
|
|
17
|
-
unbindfn(f: (...args: Args) => void): void;
|
|
1
|
+
import { Emitter } from "./emitter";
|
|
2
|
+
export declare class Event<Args extends Array<any> = []> extends Emitter<Args> {
|
|
18
3
|
/**
|
|
19
4
|
* Emit an event.
|
|
20
5
|
*
|
package/lib/event.js
CHANGED
|
@@ -1,61 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export class Event {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.hasBindings = new Observable(false);
|
|
5
|
-
this._funcs = [];
|
|
6
|
-
this._emitting = false;
|
|
7
|
-
this._toUnbind = new Set();
|
|
8
|
-
}
|
|
9
|
-
clear() {
|
|
10
|
-
this._funcs = [];
|
|
11
|
-
this.hasBindings.value = false;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Bind new handler function.
|
|
15
|
-
* @param f - The callback function to be bound.
|
|
16
|
-
*/
|
|
17
|
-
bindfn(f) {
|
|
18
|
-
this._funcs.push(f);
|
|
19
|
-
if (!this.hasBindings.value)
|
|
20
|
-
this.hasBindings.value = true;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Unbind an existing function.
|
|
24
|
-
* @param f - The callback function to be unbound.
|
|
25
|
-
*/
|
|
26
|
-
unbindfn(f) {
|
|
27
|
-
if (this._emitting) {
|
|
28
|
-
this._toUnbind.add(f);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
this._toUnbind.delete(f);
|
|
32
|
-
const indx = this._funcs.indexOf(f);
|
|
33
|
-
if (indx > -1) {
|
|
34
|
-
this._funcs.splice(indx, 1);
|
|
35
|
-
}
|
|
36
|
-
if (this._funcs.length === 0 && this.hasBindings.value)
|
|
37
|
-
this.hasBindings.value = false;
|
|
38
|
-
}
|
|
1
|
+
import { Emitter } from "./emitter";
|
|
2
|
+
export class Event extends Emitter {
|
|
39
3
|
/**
|
|
40
4
|
* Emit an event.
|
|
41
5
|
*
|
|
42
6
|
* @param a - The argument to pass to handler functions.
|
|
43
7
|
*/
|
|
44
8
|
emit(...args) {
|
|
45
|
-
|
|
46
|
-
for (let i = 0, total = this._funcs.length; i < total; i++) {
|
|
47
|
-
try {
|
|
48
|
-
if (this._toUnbind.has(this._funcs[i]))
|
|
49
|
-
continue;
|
|
50
|
-
this._funcs[i](...args);
|
|
51
|
-
}
|
|
52
|
-
catch (ex) {
|
|
53
|
-
console.log('Exception in event handler', ex);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
this._emitting = false;
|
|
57
|
-
if (this._toUnbind.size > 0) {
|
|
58
|
-
this._toUnbind.forEach(fn => this.unbindfn(fn));
|
|
59
|
-
}
|
|
9
|
+
super._emit(...args);
|
|
60
10
|
}
|
|
61
11
|
}
|