j-templates 7.0.65 → 7.0.66
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/DOM/index.js +1 -0
- package/DOM/svgElements.js +12 -0
- package/Node/component.d.ts +70 -7
- package/Node/component.js +106 -10
- package/Node/vNode.js +24 -8
- package/Node/vNode.types.d.ts +1 -3
- package/Store/Store/storeAsync.d.ts +78 -0
- package/Store/Store/storeAsync.js +74 -0
- package/Store/Store/storeSync.d.ts +62 -0
- package/Store/Store/storeSync.js +58 -0
- package/Store/Tree/observableScope.d.ts +2 -2
- package/Store/Tree/observableScope.js +4 -4
- package/Utils/animation.d.ts +43 -0
- package/Utils/animation.js +50 -3
- package/Utils/array.d.ts +48 -0
- package/Utils/array.js +56 -0
- package/Utils/decorators.d.ts +140 -5
- package/Utils/decorators.js +274 -27
- package/Utils/injector.d.ts +24 -0
- package/Utils/injector.js +24 -0
- package/Utils/list.js +4 -4
- package/Utils/router.js +110 -0
- package/Utils/thread.d.ts +75 -0
- package/Utils/thread.js +79 -0
- package/package.json +1 -1
package/Store/Store/storeSync.js
CHANGED
|
@@ -5,11 +5,49 @@ const json_1 = require("../../Utils/json");
|
|
|
5
5
|
const diffSync_1 = require("../Diff/diffSync");
|
|
6
6
|
const observableNode_1 = require("../Tree/observableNode");
|
|
7
7
|
const store_1 = require("./store");
|
|
8
|
+
/**
|
|
9
|
+
* StoreSync class extends the base Store class to provide synchronous data management operations.
|
|
10
|
+
* This class handles writing, patching, pushing, and splicing data in a synchronous manner.
|
|
11
|
+
*
|
|
12
|
+
* StoreSync is designed to work with observable data structures, allowing for efficient updates
|
|
13
|
+
* and notifications when data changes. It is particularly useful for scenarios where synchronous
|
|
14
|
+
* operations are preferred or required.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Creating a StoreSync instance
|
|
18
|
+
* const store = new StoreSync();
|
|
19
|
+
*
|
|
20
|
+
* // Writing data to the store
|
|
21
|
+
* store.Write({ name: "John", age: 30 }, "user");
|
|
22
|
+
*
|
|
23
|
+
* // Patching existing data
|
|
24
|
+
* store.Patch("user", { age: 31 });
|
|
25
|
+
*
|
|
26
|
+
* // Pushing data into an array
|
|
27
|
+
* store.Push("user.array", { id: 1 }, { id: 2 });
|
|
28
|
+
*
|
|
29
|
+
* // Splicing an array
|
|
30
|
+
* const deletedItems = store.Splice("user.array", 0, 1, { id: 3 });
|
|
31
|
+
*
|
|
32
|
+
* @see Store
|
|
33
|
+
* @see StoreAsync
|
|
34
|
+
* @see DiffSync
|
|
35
|
+
*/
|
|
8
36
|
class StoreSync extends store_1.Store {
|
|
37
|
+
/**
|
|
38
|
+
* Creates an instance of StoreSync.
|
|
39
|
+
* @param keyFunc Optional function to generate a key for a given data value.
|
|
40
|
+
*/
|
|
9
41
|
constructor(keyFunc) {
|
|
10
42
|
super(keyFunc);
|
|
11
43
|
this.diff = new diffSync_1.DiffSync(keyFunc);
|
|
12
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Writes data to the store synchronously.
|
|
47
|
+
* @param data The data to be written. Can be of any type.
|
|
48
|
+
* @param key Optional key for the data. If not provided, the keyFunc will be used to generate a key.
|
|
49
|
+
* @throws Will throw an error if no key is provided for the data.
|
|
50
|
+
*/
|
|
13
51
|
Write(data, key) {
|
|
14
52
|
data = (0, json_1.JsonDeepClone)(data);
|
|
15
53
|
key = key || this.keyFunc?.(data);
|
|
@@ -18,6 +56,12 @@ class StoreSync extends store_1.Store {
|
|
|
18
56
|
const diffResult = this.diff.DiffPath(key, data);
|
|
19
57
|
this.UpdateRootMap(diffResult);
|
|
20
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Patches an existing value in the store with new data synchronously.
|
|
61
|
+
* @param key The key of the value to be patched.
|
|
62
|
+
* @param patch The patch data to be merged with the existing value.
|
|
63
|
+
* @throws Will throw an error if the value to be patched is undefined.
|
|
64
|
+
*/
|
|
21
65
|
Patch(key, patch) {
|
|
22
66
|
const value = this.Get(key);
|
|
23
67
|
if (value === undefined)
|
|
@@ -27,6 +71,11 @@ class StoreSync extends store_1.Store {
|
|
|
27
71
|
const diffResult = this.diff.DiffPath(key, mergedJson);
|
|
28
72
|
this.UpdateRootMap(diffResult);
|
|
29
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Pushes data into an array stored at the specified key synchronously.
|
|
76
|
+
* @param key The key of the array where data will be pushed.
|
|
77
|
+
* @param data The data items to be pushed into the array.
|
|
78
|
+
*/
|
|
30
79
|
Push(key, ...data) {
|
|
31
80
|
const arr = this.Get(key);
|
|
32
81
|
const batch = data.map(function (d, i) {
|
|
@@ -38,6 +87,15 @@ class StoreSync extends store_1.Store {
|
|
|
38
87
|
const diffResult = this.diff.DiffBatch(batch);
|
|
39
88
|
this.UpdateRootMap(diffResult);
|
|
40
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Splices an array stored at the specified key with new data synchronously.
|
|
92
|
+
* This method modifies the array by deleting elements and inserting new ones at the specified position.
|
|
93
|
+
* @param key The key of the array to be spliced.
|
|
94
|
+
* @param start The position at which to start changing the array.
|
|
95
|
+
* @param deleteCount Optional number of elements to delete. If not provided, all elements from start to end will be deleted.
|
|
96
|
+
* @param items Optional elements to insert into the array.
|
|
97
|
+
* @returns The array of deleted elements.
|
|
98
|
+
*/
|
|
41
99
|
Splice(key, start, deleteCount, ...items) {
|
|
42
100
|
const arr = this.Get(key);
|
|
43
101
|
const arrValue = arr[observableNode_1.GET_OBSERVABLE_VALUE];
|
|
@@ -42,14 +42,14 @@ export interface IObservableScope<T> extends IDestroyable {
|
|
|
42
42
|
onDestroyed: Emitter | null;
|
|
43
43
|
destroyed: boolean;
|
|
44
44
|
}
|
|
45
|
-
export declare function CalcScope<T>(callback: () => T, idOverride?: string):
|
|
45
|
+
export declare function CalcScope<T>(callback: () => T, idOverride?: string): T;
|
|
46
46
|
export declare namespace ObservableScope {
|
|
47
47
|
function Create<T>(valueFunction: {
|
|
48
48
|
(): T | Promise<T>;
|
|
49
49
|
}, calc?: boolean): IObservableScope<T>;
|
|
50
50
|
function CreateIf<T>(valueFunction: {
|
|
51
51
|
(): T | Promise<T>;
|
|
52
|
-
}): [T, IObservableScope<T> | null];
|
|
52
|
+
}, greedy?: boolean): [T, IObservableScope<T> | null];
|
|
53
53
|
function Register(emitter: Emitter): void;
|
|
54
54
|
function Init<T>(scope: IObservableScope<T>): void;
|
|
55
55
|
function Peek<T>(scope: IObservableScope<T>): T;
|
|
@@ -65,14 +65,14 @@ function WatchScope(scope) {
|
|
|
65
65
|
watchState = parent;
|
|
66
66
|
return value;
|
|
67
67
|
}
|
|
68
|
-
function WatchFunction(func) {
|
|
68
|
+
function WatchFunction(func, greedy) {
|
|
69
69
|
const parent = watchState;
|
|
70
70
|
watchState = [[], null, null];
|
|
71
71
|
const async = (0, functions_1.IsAsync)(func);
|
|
72
72
|
const result = func();
|
|
73
73
|
let scope = null;
|
|
74
74
|
if (watchState[0].length > 0 || async) {
|
|
75
|
-
scope = ObservableScope.Create(func);
|
|
75
|
+
scope = ObservableScope.Create(func, greedy);
|
|
76
76
|
UpdateEmitters(scope, watchState[0]);
|
|
77
77
|
scope.calcScopes = watchState[2];
|
|
78
78
|
UpdateValue(scope, result);
|
|
@@ -118,8 +118,8 @@ function CalcScope(callback, idOverride) {
|
|
|
118
118
|
return scope;
|
|
119
119
|
}
|
|
120
120
|
ObservableScope.Create = Create;
|
|
121
|
-
function CreateIf(valueFunction) {
|
|
122
|
-
return WatchFunction(valueFunction);
|
|
121
|
+
function CreateIf(valueFunction, greedy = false) {
|
|
122
|
+
return WatchFunction(valueFunction, greedy);
|
|
123
123
|
}
|
|
124
124
|
ObservableScope.CreateIf = CreateIf;
|
|
125
125
|
function Register(emitter) {
|
package/Utils/animation.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { IDestroyable } from "./utils.types";
|
|
2
|
+
/**
|
|
3
|
+
* Supported animation functions.
|
|
4
|
+
*/
|
|
2
5
|
export declare enum AnimationType {
|
|
3
6
|
Linear = 0,
|
|
4
7
|
EaseIn = 1
|
|
5
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Class for handling interpolation for basic animations.
|
|
11
|
+
*/
|
|
6
12
|
export declare class Animation implements IDestroyable {
|
|
7
13
|
private type;
|
|
8
14
|
private running;
|
|
@@ -13,16 +19,53 @@ export declare class Animation implements IDestroyable {
|
|
|
13
19
|
private animationDuration;
|
|
14
20
|
private animationUpdate;
|
|
15
21
|
private animationRun;
|
|
22
|
+
/**
|
|
23
|
+
* Is the animation currently running.
|
|
24
|
+
*/
|
|
16
25
|
get Running(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The starting value of the current animation.
|
|
28
|
+
*/
|
|
17
29
|
get Start(): number;
|
|
30
|
+
/**
|
|
31
|
+
* The ending value of the current animation.
|
|
32
|
+
*/
|
|
18
33
|
get End(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Is this animation enabled.
|
|
36
|
+
*/
|
|
19
37
|
get Enabled(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* @param type Interpolation function
|
|
40
|
+
* @param duration The duration of the Animation
|
|
41
|
+
* @param update Callback invoked during the animation with the next value
|
|
42
|
+
*/
|
|
20
43
|
constructor(type: AnimationType, duration: number, update: {
|
|
21
44
|
(next: number): void;
|
|
22
45
|
});
|
|
46
|
+
/**
|
|
47
|
+
* Start an animation. Calls the passed `update` callback for each animation frame
|
|
48
|
+
* with interpolated values based on the passed `AnimationType`.
|
|
49
|
+
*
|
|
50
|
+
* @param start initial animation value
|
|
51
|
+
* @param end ending animation value
|
|
52
|
+
* @returns Promise<void> that resolves once the animation is complete
|
|
53
|
+
*/
|
|
23
54
|
Animate(start: number, end: number): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Disables the Animation. Cancels the animation if it is running.
|
|
57
|
+
*/
|
|
24
58
|
Disable(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Enables the Animation.
|
|
61
|
+
*/
|
|
25
62
|
Enable(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Cancels the Animation if it is running by clearing any sheduled timeout events.
|
|
65
|
+
*/
|
|
26
66
|
Cancel(): void;
|
|
67
|
+
/**
|
|
68
|
+
* IDestroyable. Cancels the animation.
|
|
69
|
+
*/
|
|
27
70
|
Destroy(): void;
|
|
28
71
|
}
|
package/Utils/animation.js
CHANGED
|
@@ -20,24 +20,47 @@ var StepFunctions;
|
|
|
20
20
|
}
|
|
21
21
|
StepFunctions.Linear = Linear;
|
|
22
22
|
})(StepFunctions || (StepFunctions = {}));
|
|
23
|
+
/**
|
|
24
|
+
* Supported animation functions.
|
|
25
|
+
*/
|
|
23
26
|
var AnimationType;
|
|
24
27
|
(function (AnimationType) {
|
|
25
28
|
AnimationType[AnimationType["Linear"] = 0] = "Linear";
|
|
26
29
|
AnimationType[AnimationType["EaseIn"] = 1] = "EaseIn";
|
|
27
30
|
})(AnimationType || (exports.AnimationType = AnimationType = {}));
|
|
31
|
+
/**
|
|
32
|
+
* Class for handling interpolation for basic animations.
|
|
33
|
+
*/
|
|
28
34
|
class Animation {
|
|
35
|
+
/**
|
|
36
|
+
* Is the animation currently running.
|
|
37
|
+
*/
|
|
29
38
|
get Running() {
|
|
30
39
|
return this.running;
|
|
31
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* The starting value of the current animation.
|
|
43
|
+
*/
|
|
32
44
|
get Start() {
|
|
33
45
|
return this.start;
|
|
34
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* The ending value of the current animation.
|
|
49
|
+
*/
|
|
35
50
|
get End() {
|
|
36
51
|
return this.end;
|
|
37
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Is this animation enabled.
|
|
55
|
+
*/
|
|
38
56
|
get Enabled() {
|
|
39
57
|
return this.enabled;
|
|
40
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* @param type Interpolation function
|
|
61
|
+
* @param duration The duration of the Animation
|
|
62
|
+
* @param update Callback invoked during the animation with the next value
|
|
63
|
+
*/
|
|
41
64
|
constructor(type, duration, update) {
|
|
42
65
|
this.animationStart = 0;
|
|
43
66
|
this.animationRun = null;
|
|
@@ -49,13 +72,23 @@ class Animation {
|
|
|
49
72
|
this.animationDuration = duration;
|
|
50
73
|
this.animationUpdate = nodeConfig_1.NodeConfig.wrapPriorityUpdates(update);
|
|
51
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Start an animation. Calls the passed `update` callback for each animation frame
|
|
77
|
+
* with interpolated values based on the passed `AnimationType`.
|
|
78
|
+
*
|
|
79
|
+
* @param start initial animation value
|
|
80
|
+
* @param end ending animation value
|
|
81
|
+
* @returns Promise<void> that resolves once the animation is complete
|
|
82
|
+
*/
|
|
52
83
|
Animate(start, end) {
|
|
53
84
|
if (!this.enabled)
|
|
54
85
|
return;
|
|
86
|
+
this.Cancel();
|
|
55
87
|
const diff = end - start;
|
|
56
|
-
if (diff === 0)
|
|
88
|
+
if (diff === 0) {
|
|
89
|
+
this.animationUpdate(end);
|
|
57
90
|
return;
|
|
58
|
-
|
|
91
|
+
}
|
|
59
92
|
this.animationStart = Date.now();
|
|
60
93
|
this.running = true;
|
|
61
94
|
this.start = start;
|
|
@@ -63,8 +96,10 @@ class Animation {
|
|
|
63
96
|
return new Promise((resolve) => {
|
|
64
97
|
const stepFunc = StepFunctions[AnimationType[this.type]];
|
|
65
98
|
const animationRun = () => {
|
|
66
|
-
if (this.animationRun !== animationRun)
|
|
99
|
+
if (this.animationRun !== animationRun) {
|
|
100
|
+
resolve();
|
|
67
101
|
return;
|
|
102
|
+
}
|
|
68
103
|
const percent = stepFunc(this.animationStart, this.animationDuration);
|
|
69
104
|
const step = percent * diff;
|
|
70
105
|
const next = this.start + step;
|
|
@@ -81,19 +116,31 @@ class Animation {
|
|
|
81
116
|
this.Cancel();
|
|
82
117
|
});
|
|
83
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Disables the Animation. Cancels the animation if it is running.
|
|
121
|
+
*/
|
|
84
122
|
Disable() {
|
|
85
123
|
this.Cancel();
|
|
86
124
|
this.enabled = false;
|
|
87
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Enables the Animation.
|
|
128
|
+
*/
|
|
88
129
|
Enable() {
|
|
89
130
|
this.enabled = true;
|
|
90
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Cancels the Animation if it is running by clearing any sheduled timeout events.
|
|
134
|
+
*/
|
|
91
135
|
Cancel() {
|
|
92
136
|
this.running = false;
|
|
93
137
|
this.start = null;
|
|
94
138
|
this.end = null;
|
|
95
139
|
this.animationRun = null;
|
|
96
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* IDestroyable. Cancels the animation.
|
|
143
|
+
*/
|
|
97
144
|
Destroy() {
|
|
98
145
|
this.Disable();
|
|
99
146
|
}
|
package/Utils/array.d.ts
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removes all null values from an array starting from a specified index.
|
|
3
|
+
* This function modifies the array in-place by shifting non-null elements
|
|
4
|
+
* to fill the gaps left by removed null values, then truncating the array.
|
|
5
|
+
*
|
|
6
|
+
* @param array - The array from which to remove null values. Can contain mixed types including null.
|
|
7
|
+
* @param startIndex - The index to start removing null values from (default: 0).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const arr = [1, null, 2, null, 3, null, 4];
|
|
12
|
+
* RemoveNulls(arr); // Removes all null values, result: [1, 2, 3, 4]
|
|
13
|
+
*
|
|
14
|
+
* const arr2 = [null, null, 1, null, 2];
|
|
15
|
+
* RemoveNulls(arr2, 2); // Starts from index 2, result: [null, null, 1, 2]
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
1
18
|
export declare function RemoveNulls(array: (unknown | null)[], startIndex?: number): void;
|
|
2
19
|
export declare function ArrayDiff(source: any[], target: any[]): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Reconciles two sorted arrays by applying add and remove operations to transition
|
|
22
|
+
* from the left array to the right array. Elements are compared based on their first
|
|
23
|
+
* element (index 0) which must be a number.
|
|
24
|
+
*
|
|
25
|
+
* This function efficiently handles the process of updating a sorted collection by:
|
|
26
|
+
* - Removing elements that exist in the left array but not in the right array
|
|
27
|
+
* - Adding elements that exist in the right array but not in the left array
|
|
28
|
+
*
|
|
29
|
+
* @template T - A tuple type where the first element is a number (T extends [number])
|
|
30
|
+
* @param left - The initial sorted array of tuples
|
|
31
|
+
* @param right - The target sorted array of tuples
|
|
32
|
+
* @param add - Callback function to handle adding elements
|
|
33
|
+
* @param remove - Callback function to handle removing elements
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const left = [[1, 'a'], [3, 'c']];
|
|
38
|
+
* const right = [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
39
|
+
* const added: number[] = [];
|
|
40
|
+
* const removed: number[] = [];
|
|
41
|
+
*
|
|
42
|
+
* ReconcileSortedEmitters(
|
|
43
|
+
* left,
|
|
44
|
+
* right,
|
|
45
|
+
* (value) => added.push(value[0]),
|
|
46
|
+
* (value) => removed.push(value[0])
|
|
47
|
+
* );
|
|
48
|
+
* // Adds [2, 4] and removes [1]
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
3
51
|
export declare function ReconcileSortedEmitters<T extends [number]>(left: T[], right: T[], add: (value: T) => void, remove: (value: T) => void): void;
|
|
4
52
|
export declare function InsertionSortTuples<T extends [number, ...any[]]>(arr: T[]): T[];
|
|
5
53
|
export declare function ReconcileSortedArrays<T>(left: T[], right: T[], add: (value: T) => void, remove: (value: T) => void): void;
|
package/Utils/array.js
CHANGED
|
@@ -5,6 +5,23 @@ exports.ArrayDiff = ArrayDiff;
|
|
|
5
5
|
exports.ReconcileSortedEmitters = ReconcileSortedEmitters;
|
|
6
6
|
exports.InsertionSortTuples = InsertionSortTuples;
|
|
7
7
|
exports.ReconcileSortedArrays = ReconcileSortedArrays;
|
|
8
|
+
/**
|
|
9
|
+
* Removes all null values from an array starting from a specified index.
|
|
10
|
+
* This function modifies the array in-place by shifting non-null elements
|
|
11
|
+
* to fill the gaps left by removed null values, then truncating the array.
|
|
12
|
+
*
|
|
13
|
+
* @param array - The array from which to remove null values. Can contain mixed types including null.
|
|
14
|
+
* @param startIndex - The index to start removing null values from (default: 0).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const arr = [1, null, 2, null, 3, null, 4];
|
|
19
|
+
* RemoveNulls(arr); // Removes all null values, result: [1, 2, 3, 4]
|
|
20
|
+
*
|
|
21
|
+
* const arr2 = [null, null, 1, null, 2];
|
|
22
|
+
* RemoveNulls(arr2, 2); // Starts from index 2, result: [null, null, 1, 2]
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
8
25
|
function RemoveNulls(array, startIndex = 0) {
|
|
9
26
|
let nullIndex = startIndex;
|
|
10
27
|
for (; nullIndex < array.length && array[nullIndex] !== null; nullIndex++) { }
|
|
@@ -27,6 +44,37 @@ function ArrayDiff(source, target) {
|
|
|
27
44
|
for (; x < source.length && source[x] === target[x]; x++) { }
|
|
28
45
|
return x < source.length;
|
|
29
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Reconciles two sorted arrays by applying add and remove operations to transition
|
|
49
|
+
* from the left array to the right array. Elements are compared based on their first
|
|
50
|
+
* element (index 0) which must be a number.
|
|
51
|
+
*
|
|
52
|
+
* This function efficiently handles the process of updating a sorted collection by:
|
|
53
|
+
* - Removing elements that exist in the left array but not in the right array
|
|
54
|
+
* - Adding elements that exist in the right array but not in the left array
|
|
55
|
+
*
|
|
56
|
+
* @template T - A tuple type where the first element is a number (T extends [number])
|
|
57
|
+
* @param left - The initial sorted array of tuples
|
|
58
|
+
* @param right - The target sorted array of tuples
|
|
59
|
+
* @param add - Callback function to handle adding elements
|
|
60
|
+
* @param remove - Callback function to handle removing elements
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const left = [[1, 'a'], [3, 'c']];
|
|
65
|
+
* const right = [[2, 'b'], [3, 'c'], [4, 'd']];
|
|
66
|
+
* const added: number[] = [];
|
|
67
|
+
* const removed: number[] = [];
|
|
68
|
+
*
|
|
69
|
+
* ReconcileSortedEmitters(
|
|
70
|
+
* left,
|
|
71
|
+
* right,
|
|
72
|
+
* (value) => added.push(value[0]),
|
|
73
|
+
* (value) => removed.push(value[0])
|
|
74
|
+
* );
|
|
75
|
+
* // Adds [2, 4] and removes [1]
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
30
78
|
function ReconcileSortedEmitters(left, right, add, remove) {
|
|
31
79
|
let leftIndex = 0;
|
|
32
80
|
let rightIndex = 0;
|
|
@@ -53,13 +101,21 @@ function ReconcileSortedEmitters(left, right, add, remove) {
|
|
|
53
101
|
}
|
|
54
102
|
function InsertionSortTuples(arr) {
|
|
55
103
|
const n = arr.length;
|
|
104
|
+
// Start from the second element (index 1) as the first element (index 0)
|
|
105
|
+
// is trivially sorted by itself.
|
|
56
106
|
for (let i = 1; i < n; i++) {
|
|
107
|
+
// Pick up the current element to be inserted
|
|
57
108
|
const currentItem = arr[i];
|
|
109
|
+
// This is the index of the last element in the sorted sub-array
|
|
58
110
|
let j = i - 1;
|
|
111
|
+
// Move elements of the sorted sub-array that are greater than currentItem,
|
|
112
|
+
// to one position ahead of their current position.
|
|
113
|
+
// We compare using the first element of the tuples (currentItem[0]).
|
|
59
114
|
while (j >= 0 && arr[j][0] > currentItem[0]) {
|
|
60
115
|
arr[j + 1] = arr[j];
|
|
61
116
|
j--;
|
|
62
117
|
}
|
|
118
|
+
// Place the currentItem in its correct position in the sorted sub-array
|
|
63
119
|
arr[j + 1] = currentItem;
|
|
64
120
|
}
|
|
65
121
|
return arr;
|
package/Utils/decorators.d.ts
CHANGED
|
@@ -1,17 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module provides decorators for managing state, computed values, and dependency injection in components.
|
|
3
|
+
* These decorators are designed to work with observable data structures, allowing for efficient updates and notifications.
|
|
4
|
+
*
|
|
5
|
+
* @module Utils/Decorators
|
|
6
|
+
* @see ObservableScope
|
|
7
|
+
* @see ObservableNode
|
|
8
|
+
* @see StoreAsync
|
|
9
|
+
* @see StoreSync
|
|
10
|
+
* @see Component
|
|
11
|
+
*/
|
|
1
12
|
import { IDestroyable } from "./utils.types";
|
|
2
|
-
import {
|
|
13
|
+
import { Injector } from "./injector";
|
|
14
|
+
/**
|
|
15
|
+
* Computed decorator factory for creating synchronous computed properties.
|
|
16
|
+
* A computed property is derived from other properties and automatically updates when its dependencies change.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* class MyComponent extends Component {
|
|
20
|
+
* @Computed({ count: 0 })
|
|
21
|
+
* get myComputed(): { count: number } {
|
|
22
|
+
* return { count: this.myStateValue };
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* @param defaultValue The default value to be used if the computed property is not defined.
|
|
27
|
+
* @returns A property decorator that can be applied to a getter method.
|
|
28
|
+
* @throws Will throw an error if the property is not a getter or if it has a setter.
|
|
29
|
+
* @remarks The computed value is backed by a StoreSync instance, which caches the latest result of the getter. When any of the getter's dependencies change, the StoreSync is updated and the computed property reflects the new value synchronously. The provided `defaultValue` is returned until the first evaluation completes.
|
|
30
|
+
*/
|
|
3
31
|
export declare function Computed<T extends WeakKey, K extends keyof T, V extends T[K]>(defaultValue: V): (target: T, propertyKey: K, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
32
|
+
/**
|
|
33
|
+
* ComputedAsync decorator factory for creating asynchronous computed properties.
|
|
34
|
+
* A computed property is derived from other properties and automatically updates when its dependencies change.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* class MyComponent extends Component {
|
|
38
|
+
* @ComputedAsync({ items: [] })
|
|
39
|
+
* get myAsyncComputed(): { items: any[] } {
|
|
40
|
+
* return { items: this.myStateValue };
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* @param defaultValue The default value to be used if the computed property is not defined.
|
|
45
|
+
* @returns A property decorator that can be applied to a getter method.
|
|
46
|
+
* @throws Will throw an error if the property is not a getter or if it has a setter.
|
|
47
|
+
* @remarks The computed value is backed by a StoreAsync instance, which caches the result of the asynchronous getter. When dependencies change, the StoreAsync updates and the computed property resolves to the latest value. The provided `defaultValue` is returned until the async computation completes.
|
|
48
|
+
*/
|
|
4
49
|
export declare function ComputedAsync<T extends WeakKey, K extends keyof T, V extends T[K]>(defaultValue: V): (target: T, propertyKey: K, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
50
|
+
/**
|
|
51
|
+
* State decorator factory for creating state properties.
|
|
52
|
+
* A state property is a reactive value that can be read and written synchronously.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* class MyComponent extends Component {
|
|
56
|
+
* @State()
|
|
57
|
+
* myState: { count: number } = { count: 0 };
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* @returns A property decorator that can be applied to a property.
|
|
61
|
+
* @remarks The State decorator creates an ObservableNode to store the value. Updates to the property automatically notify any watchers of dependent scopes, making it ideal for mutable complex data structures that need to trigger reactivity.
|
|
62
|
+
*/
|
|
5
63
|
export declare function State(): any;
|
|
64
|
+
/**
|
|
65
|
+
* Value decorator factory for creating value properties.
|
|
66
|
+
* A value property is a reactive value that can be read and written synchronously.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* class MyComponent extends Component {
|
|
70
|
+
* @Value()
|
|
71
|
+
* myValue: string = "Hello";
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* @returns A property decorator that can be applied to a property.
|
|
75
|
+
* @remarks The Value decorator lazily creates a scoped ObservableScope whose getter returns the stored value. The setter updates the stored value and invokes ObservableScope.Update on the scope, causing any dependent computed or scope decorators to re-evaluate.
|
|
76
|
+
*/
|
|
6
77
|
export declare function Value(): any;
|
|
78
|
+
/**
|
|
79
|
+
* Scope decorator factory for creating scope properties.
|
|
80
|
+
* A scope property is a reactive value that can be read and written synchronously.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* class MyComponent extends Component {
|
|
84
|
+
* @Scope()
|
|
85
|
+
* get myScopeValue(): string {
|
|
86
|
+
* return this.myStateValue + "!";
|
|
87
|
+
* }
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* @returns A property decorator that can be applied to a getter method.
|
|
91
|
+
* @throws Will throw an error if the property is not a getter or if it has a setter.
|
|
92
|
+
*/
|
|
7
93
|
export declare function Scope(): typeof ScopeDecorator;
|
|
94
|
+
/**
|
|
95
|
+
* Scope decorator implementation for creating scope properties.
|
|
96
|
+
* @private
|
|
97
|
+
* @param target The target object.
|
|
98
|
+
* @param propertyKey The property key.
|
|
99
|
+
* @param descriptor The property descriptor.
|
|
100
|
+
* @returns A property descriptor that replaces the original descriptor with a scope implementation.
|
|
101
|
+
* @throws Will throw an error if the property is not a getter or if it has a setter.
|
|
102
|
+
*/
|
|
8
103
|
declare function ScopeDecorator<T, K extends string>(target: T, propertyKey: K, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
9
|
-
export declare function
|
|
10
|
-
|
|
11
|
-
|
|
104
|
+
export declare function Watch<S extends (instance: T) => any, T extends Record<K, (value: ReturnType<S>) => any>, K extends string>(scope: S): (target: T, propertyKey: K, descriptor: PropertyDescriptor) => void;
|
|
105
|
+
type ConstructorToken<I> = {
|
|
106
|
+
new (...args: any[]): I;
|
|
107
|
+
} | (abstract new (...args: any[]) => I);
|
|
108
|
+
/**
|
|
109
|
+
* Inject decorator factory for creating dependency-injected properties.
|
|
110
|
+
* An injected property is automatically provided by the framework's dependency injection system.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* class MyComponent extends Component {
|
|
114
|
+
* @Inject(Token)
|
|
115
|
+
* property: ServiceForToken;
|
|
116
|
+
* }
|
|
117
|
+
*
|
|
118
|
+
* // Setting the value in the class definition
|
|
119
|
+
* class MyComponent extends Component {
|
|
120
|
+
* @Inject(Token)
|
|
121
|
+
* property: ServiceForToken = new ServiceForToken();
|
|
122
|
+
* }
|
|
123
|
+
*
|
|
124
|
+
* @param type The constructor type of the dependency to be injected.
|
|
125
|
+
* @returns A property decorator that can be applied to a property.
|
|
126
|
+
*/
|
|
127
|
+
export declare function Inject<I, T extends Record<K, I> & {
|
|
128
|
+
Injector: Injector;
|
|
129
|
+
}, K extends string>(type: ConstructorToken<I>): (target: T, propertyKey: K, descriptor?: PropertyDescriptor) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Destroy decorator factory for marking a property to be destroyed when the component is destroyed.
|
|
132
|
+
* @example
|
|
133
|
+
* class MyComponent extends Component {
|
|
134
|
+
* @Destroy()
|
|
135
|
+
* timer: Timer;
|
|
136
|
+
* }
|
|
137
|
+
*/
|
|
12
138
|
export declare function Destroy(): typeof DestroyDecorator;
|
|
139
|
+
export declare namespace Bound {
|
|
140
|
+
function All<T extends WeakKey>(value: T): void;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Utility to destroy all observable scopes and invoke destroy on marked properties of an instance.
|
|
144
|
+
* @param value The instance to clean up.
|
|
145
|
+
* @example
|
|
146
|
+
* Destroy.All(this);
|
|
147
|
+
*/
|
|
13
148
|
export declare namespace Destroy {
|
|
14
|
-
function All<T extends WeakKey
|
|
149
|
+
function All<T extends WeakKey>(value: T): void;
|
|
15
150
|
}
|
|
16
151
|
declare function DestroyDecorator<T extends Record<K, IDestroyable>, K extends string>(target: T, propertyKey: K): any;
|
|
17
152
|
export {};
|