@zcomponent/core 0.0.25 → 0.0.27
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/context.d.ts +1 -0
- package/lib/context.js +6 -1
- package/lib/contexts/loadcontext.d.ts +36 -1
- package/lib/contexts/loadcontext.js +55 -4
- package/lib/observable.d.ts +3 -3
- package/lib/observable.js +5 -3
- package/package.json +1 -1
package/lib/context.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare class ContextManager {
|
|
|
38
38
|
fork<T extends new (contextManager: ContextManager, props: {}) => any>(ctx: ConstructorWithOnlyOptional<T>): [ContextManager, InstanceType<T>];
|
|
39
39
|
fork<T extends new (contextManager: ContextManager, props: {}) => any>(ctx: T, props: ConstructorParameters<T>[1]): [ContextManager, InstanceType<T>];
|
|
40
40
|
forkMultiple<T extends ConstructorWithProps[]>(...ctx: T): [ContextManager, InstancesOfConstructorsWithProps<T>];
|
|
41
|
+
emptyFork(): ContextManager;
|
|
41
42
|
delete(ctx: ContextConstructor): void;
|
|
42
43
|
private _keyForContext;
|
|
43
44
|
}
|
package/lib/context.js
CHANGED
|
@@ -51,7 +51,7 @@ export class ContextManager {
|
|
|
51
51
|
ret._byKey = Object.create(this._byKey);
|
|
52
52
|
const key = this._keyForContext(ctx);
|
|
53
53
|
const instance = new ctx(this, props ?? {});
|
|
54
|
-
|
|
54
|
+
ret._byKey[key] = instance;
|
|
55
55
|
return [ret, instance];
|
|
56
56
|
}
|
|
57
57
|
forkMultiple(...ctx) {
|
|
@@ -67,6 +67,11 @@ export class ContextManager {
|
|
|
67
67
|
}
|
|
68
68
|
return [ret, instances];
|
|
69
69
|
}
|
|
70
|
+
emptyFork() {
|
|
71
|
+
const ret = new ContextManager();
|
|
72
|
+
ret._byKey = Object.create(this._byKey);
|
|
73
|
+
return ret;
|
|
74
|
+
}
|
|
70
75
|
delete(ctx) {
|
|
71
76
|
const key = this._keyForContext(ctx);
|
|
72
77
|
const existing = this._byKey[key];
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { ContextManager, Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* LoadContext exposes to components and behaviors key moments during the initialization of the experience,
|
|
5
|
+
* and allows them to register long-running processes that should take place on any loading screen.
|
|
6
|
+
*
|
|
7
|
+
* There are several related, yet distinct, moments during initializatin that may be useful. In each case a `Promise`
|
|
8
|
+
* and an `Observable<boolean>` are exposed for use in components and behaviors.
|
|
9
|
+
*
|
|
10
|
+
* - `constructed` occurs when the root component's constructor (and thus any recursive children) has finished.
|
|
11
|
+
* This often takes place very soon after page load - when the experience's `<script>` has initialized. It's unlikely
|
|
12
|
+
* that the experience is ready to run as assets and other dependencies may still be being downloaded. If the
|
|
13
|
+
* experience features a splash page, this moment will almost certainly occur before the user taps on the
|
|
14
|
+
* launch button.
|
|
15
|
+
*
|
|
16
|
+
* - `launched` occurs when the user taps on a splash screen's 'launch' button or, in the case that there's no launch
|
|
17
|
+
* button, after construction. It's unlikely that the experience is ready to run as assets and other dependencies may
|
|
18
|
+
* still be being downloaded. This moment is useful for showing permission dialogs to the user since it occurs after
|
|
19
|
+
* they have indicated that they wish to proceed with the experience and is concurrent with any asset loading.
|
|
20
|
+
*
|
|
21
|
+
* - `started` occurs once both the loading is complete, and the user has tapped on a 'launch' button (if it exists).
|
|
22
|
+
* It's the moment where any loading screen will be hidden and the experience starts from the perspective of
|
|
23
|
+
* the user. Use this moment to start any audio, video or animation.
|
|
24
|
+
*
|
|
25
|
+
* - `loaded` occurs once all 'loadable' processes have completed (e.g. the downloading of assets). Since asset loading
|
|
26
|
+
* starts as soon as the root component is constructed, this moment may occur before (or after) the user has tapped
|
|
27
|
+
* on any 'launch' button.
|
|
28
|
+
*
|
|
29
|
+
* @zcontext */
|
|
4
30
|
export declare class LoadContext extends Context {
|
|
5
31
|
/** @zui */
|
|
6
32
|
isConstructed: Observable<boolean, never>;
|
|
@@ -9,17 +35,22 @@ export declare class LoadContext extends Context {
|
|
|
9
35
|
/** @zui */
|
|
10
36
|
isStarted: Observable<boolean, never>;
|
|
11
37
|
/** @zui */
|
|
38
|
+
isLaunched: Observable<boolean, never>;
|
|
39
|
+
/** @zui */
|
|
12
40
|
progressPercent: Observable<number, never>;
|
|
13
41
|
private _startedResolved;
|
|
14
42
|
started: Promise<void>;
|
|
15
43
|
private _constructedResolved;
|
|
16
44
|
constructed: Promise<void>;
|
|
45
|
+
private _launchedResolved;
|
|
46
|
+
launched: Promise<void>;
|
|
17
47
|
private _loadables;
|
|
18
48
|
private _startWhenLoaded;
|
|
19
49
|
private _totalLoadables;
|
|
20
50
|
private _loadedCount;
|
|
21
51
|
start(): void;
|
|
22
52
|
constructionComplete(): void;
|
|
53
|
+
launch(): void;
|
|
23
54
|
private _update;
|
|
24
55
|
startWhenLoaded(): void;
|
|
25
56
|
registerLoadable(p: Promise<any>): void;
|
|
@@ -30,10 +61,14 @@ export declare function useIsStarted(mgr: ContextManager): Observable<boolean, n
|
|
|
30
61
|
export declare function isStarted(mgr: ContextManager): boolean;
|
|
31
62
|
export declare function useIsConstructed(mgr: ContextManager): Observable<boolean, never>;
|
|
32
63
|
export declare function isConstructed(mgr: ContextManager): boolean;
|
|
64
|
+
export declare function useIsLaunched(mgr: ContextManager): Observable<boolean, never>;
|
|
65
|
+
export declare function isLaunched(mgr: ContextManager): boolean;
|
|
33
66
|
export declare function useLoadPercent(mgr: ContextManager): Observable<number, never>;
|
|
34
67
|
export declare function registerLoadable(mgr: ContextManager, p: Promise<any>): void;
|
|
35
68
|
export declare function start(mgr: ContextManager): void;
|
|
69
|
+
export declare function launch(mgr: ContextManager): void;
|
|
36
70
|
export declare function startWhenLoaded(mgr: ContextManager): void;
|
|
37
71
|
export declare function started(mgr: ContextManager): Promise<void>;
|
|
38
72
|
export declare function constructed(mgr: ContextManager): Promise<void>;
|
|
73
|
+
export declare function launched(mgr: ContextManager): Promise<void>;
|
|
39
74
|
export declare function constructionComplete(mgr: ContextManager): void;
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { Context } from '../context';
|
|
2
2
|
import { Observable } from '../observable';
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* LoadContext exposes to components and behaviors key moments during the initialization of the experience,
|
|
5
|
+
* and allows them to register long-running processes that should take place on any loading screen.
|
|
6
|
+
*
|
|
7
|
+
* There are several related, yet distinct, moments during initializatin that may be useful. In each case a `Promise`
|
|
8
|
+
* and an `Observable<boolean>` are exposed for use in components and behaviors.
|
|
9
|
+
*
|
|
10
|
+
* - `constructed` occurs when the root component's constructor (and thus any recursive children) has finished.
|
|
11
|
+
* This often takes place very soon after page load - when the experience's `<script>` has initialized. It's unlikely
|
|
12
|
+
* that the experience is ready to run as assets and other dependencies may still be being downloaded. If the
|
|
13
|
+
* experience features a splash page, this moment will almost certainly occur before the user taps on the
|
|
14
|
+
* launch button.
|
|
15
|
+
*
|
|
16
|
+
* - `launched` occurs when the user taps on a splash screen's 'launch' button or, in the case that there's no launch
|
|
17
|
+
* button, after construction. It's unlikely that the experience is ready to run as assets and other dependencies may
|
|
18
|
+
* still be being downloaded. This moment is useful for showing permission dialogs to the user since it occurs after
|
|
19
|
+
* they have indicated that they wish to proceed with the experience and is concurrent with any asset loading.
|
|
20
|
+
*
|
|
21
|
+
* - `started` occurs once both the loading is complete, and the user has tapped on a 'launch' button (if it exists).
|
|
22
|
+
* It's the moment where any loading screen will be hidden and the experience starts from the perspective of
|
|
23
|
+
* the user. Use this moment to start any audio, video or animation.
|
|
24
|
+
*
|
|
25
|
+
* - `loaded` occurs once all 'loadable' processes have completed (e.g. the downloading of assets). Since asset loading
|
|
26
|
+
* starts as soon as the root component is constructed, this moment may occur before (or after) the user has tapped
|
|
27
|
+
* on any 'launch' button.
|
|
28
|
+
*
|
|
29
|
+
* @zcontext */
|
|
4
30
|
export class LoadContext extends Context {
|
|
5
31
|
constructor() {
|
|
6
32
|
super(...arguments);
|
|
@@ -11,9 +37,12 @@ export class LoadContext extends Context {
|
|
|
11
37
|
/** @zui */
|
|
12
38
|
this.isStarted = new Observable(false);
|
|
13
39
|
/** @zui */
|
|
40
|
+
this.isLaunched = new Observable(false);
|
|
41
|
+
/** @zui */
|
|
14
42
|
this.progressPercent = new Observable(0);
|
|
15
43
|
this.started = new Promise(resolve => this._startedResolved = resolve);
|
|
16
44
|
this.constructed = new Promise(resolve => this._constructedResolved = resolve);
|
|
45
|
+
this.launched = new Promise(resolve => this._launchedResolved = resolve);
|
|
17
46
|
this._loadables = new Set();
|
|
18
47
|
this._startWhenLoaded = false;
|
|
19
48
|
this._totalLoadables = 0;
|
|
@@ -22,14 +51,24 @@ export class LoadContext extends Context {
|
|
|
22
51
|
start() {
|
|
23
52
|
if (this.isStarted.value)
|
|
24
53
|
return;
|
|
25
|
-
this.isStarted.value = true;
|
|
26
|
-
this._startedResolved?.();
|
|
27
54
|
if (document.body)
|
|
28
55
|
document.body.classList.add('zcomponent-started');
|
|
56
|
+
this.isStarted.value = true;
|
|
57
|
+
this._startedResolved?.();
|
|
29
58
|
}
|
|
30
59
|
constructionComplete() {
|
|
31
|
-
this.
|
|
60
|
+
if (this.isConstructed.value)
|
|
61
|
+
return;
|
|
32
62
|
this.isConstructed.value = true;
|
|
63
|
+
this._constructedResolved();
|
|
64
|
+
}
|
|
65
|
+
launch() {
|
|
66
|
+
if (this.isLaunched.value)
|
|
67
|
+
return;
|
|
68
|
+
if (document.body)
|
|
69
|
+
document.body.classList.add("zcomponent-launched");
|
|
70
|
+
this.isLaunched.value = true;
|
|
71
|
+
this._launchedResolved();
|
|
33
72
|
}
|
|
34
73
|
_update() {
|
|
35
74
|
if (this._loadables.size > 0 && this.isLoaded.value === true) {
|
|
@@ -84,6 +123,12 @@ export function useIsConstructed(mgr) {
|
|
|
84
123
|
export function isConstructed(mgr) {
|
|
85
124
|
return mgr.get(LoadContext).isConstructed.value;
|
|
86
125
|
}
|
|
126
|
+
export function useIsLaunched(mgr) {
|
|
127
|
+
return mgr.get(LoadContext).isLaunched;
|
|
128
|
+
}
|
|
129
|
+
export function isLaunched(mgr) {
|
|
130
|
+
return mgr.get(LoadContext).isLaunched.value;
|
|
131
|
+
}
|
|
87
132
|
export function useLoadPercent(mgr) {
|
|
88
133
|
return mgr.get(LoadContext).progressPercent;
|
|
89
134
|
}
|
|
@@ -93,6 +138,9 @@ export function registerLoadable(mgr, p) {
|
|
|
93
138
|
export function start(mgr) {
|
|
94
139
|
return mgr.get(LoadContext).start();
|
|
95
140
|
}
|
|
141
|
+
export function launch(mgr) {
|
|
142
|
+
return mgr.get(LoadContext).launch();
|
|
143
|
+
}
|
|
96
144
|
export function startWhenLoaded(mgr) {
|
|
97
145
|
return mgr.get(LoadContext).startWhenLoaded();
|
|
98
146
|
}
|
|
@@ -102,6 +150,9 @@ export function started(mgr) {
|
|
|
102
150
|
export function constructed(mgr) {
|
|
103
151
|
return mgr.get(LoadContext).constructed;
|
|
104
152
|
}
|
|
153
|
+
export function launched(mgr) {
|
|
154
|
+
return mgr.get(LoadContext).launched;
|
|
155
|
+
}
|
|
105
156
|
export function constructionComplete(mgr) {
|
|
106
157
|
return mgr.get(LoadContext).constructionComplete();
|
|
107
158
|
}
|
package/lib/observable.d.ts
CHANGED
|
@@ -44,8 +44,8 @@ export declare class Observable<Type = never, TypeInternal extends any[] | [] |
|
|
|
44
44
|
* @param withHandler - A function that will be called when the value (or any of its recursive descendent keys or elements) is changed
|
|
45
45
|
* @param deep - Set to false to only track changes to the top level `value` itself (and not any of its descendent keys or elements)
|
|
46
46
|
*/
|
|
47
|
-
constructor(def: TypeInternal, withHandler?: ((v: TypeInternal) => void), deep?: boolean);
|
|
48
|
-
constructor(def: Type, withHandler?: ((v: Type) => void), deep?: boolean);
|
|
47
|
+
constructor(def: TypeInternal, withHandler?: ((v: TypeInternal) => void), deep?: boolean, callWithImmediately?: boolean);
|
|
48
|
+
constructor(def: Type, withHandler?: ((v: Type) => void), deep?: boolean, callWithImmediately?: boolean);
|
|
49
49
|
/**
|
|
50
50
|
* Access the current value for this Observable. Changing this value (or, unless deep inspection is disabled, its recursive elements and keys) will trigger any registered handlers to be called with the new value.
|
|
51
51
|
*
|
|
@@ -54,7 +54,7 @@ export declare class Observable<Type = never, TypeInternal extends any[] | [] |
|
|
|
54
54
|
get value(): Resolved<Type, TypeInternal>;
|
|
55
55
|
private _wrap;
|
|
56
56
|
set value(v: Resolved<Type, TypeInternal> | undefined);
|
|
57
|
-
addListener(fn: (v: Resolved<Type, TypeInternal>) => void, priority?: number): void;
|
|
57
|
+
addListener(fn: (v: Resolved<Type, TypeInternal>) => void, priority?: number, callImmediately?: boolean): void;
|
|
58
58
|
private _emitValue;
|
|
59
59
|
}
|
|
60
60
|
export {};
|
package/lib/observable.js
CHANGED
|
@@ -32,7 +32,7 @@ import { Emitter } from "./emitter";
|
|
|
32
32
|
* @typeParam TypeInternal - An internal type used to improve automatic type detection
|
|
33
33
|
*/
|
|
34
34
|
export class Observable extends Emitter {
|
|
35
|
-
constructor(_default, withHandler, _deep = true) {
|
|
35
|
+
constructor(_default, withHandler, _deep = true, callWithImmediately = false) {
|
|
36
36
|
super();
|
|
37
37
|
this._default = _default;
|
|
38
38
|
this._deep = _deep;
|
|
@@ -48,7 +48,7 @@ export class Observable extends Emitter {
|
|
|
48
48
|
}
|
|
49
49
|
this._value = this._wrap(initial);
|
|
50
50
|
if (withHandler)
|
|
51
|
-
this.addListener(withHandler);
|
|
51
|
+
this.addListener(withHandler, 0, callWithImmediately);
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Access the current value for this Observable. Changing this value (or, unless deep inspection is disabled, its recursive elements and keys) will trigger any registered handlers to be called with the new value.
|
|
@@ -116,8 +116,10 @@ export class Observable extends Emitter {
|
|
|
116
116
|
this._value = this._wrap(v);
|
|
117
117
|
this._emitValue();
|
|
118
118
|
}
|
|
119
|
-
addListener(fn, priority = 0) {
|
|
119
|
+
addListener(fn, priority = 0, callImmediately = true) {
|
|
120
120
|
super.addListener(fn);
|
|
121
|
+
if (!callImmediately)
|
|
122
|
+
return;
|
|
121
123
|
try {
|
|
122
124
|
fn(this._value.proxy);
|
|
123
125
|
}
|