j-templates 7.0.93 → 7.0.95
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/domNodeConfig.js +40 -9
- package/DOM/elements.d.ts +98 -768
- package/DOM/elements.js +8 -2
- package/Node/nodeConfig.d.ts +1 -0
- package/Node/vNode.d.ts +4 -15
- package/Node/vNode.js +47 -31
- package/Node/vNode.types.d.ts +15 -3
- package/Node/vNode.types.js +5 -1
- package/Store/Store/storeSync.js +1 -1
- package/Store/Tree/observableNode.d.ts +2 -1
- package/Store/Tree/observableNode.js +42 -8
- package/Store/Tree/observableScope.d.ts +2 -4
- package/Store/Tree/observableScope.js +7 -8
- package/Utils/decorators.js +5 -2
- package/Utils/emitter.js +2 -4
- package/Utils/json.d.ts +2 -2
- package/Utils/json.js +1 -2
- package/Utils/scheduling.d.ts +4 -0
- package/Utils/scheduling.js +26 -0
- package/Utils/thread.js +3 -5
- package/package.json +1 -1
- package/DOM/window.d.ts +0 -1
- package/DOM/window.js +0 -12
- package/Utils/distinctArray.d.ts +0 -12
- package/Utils/distinctArray.js +0 -49
- /package/{Utils → _not_used}/array.d.ts +0 -0
- /package/{Utils → _not_used}/array.js +0 -0
- /package/{Utils → _not_used}/avlTree.d.ts +0 -0
- /package/{Utils → _not_used}/avlTree.js +0 -0
package/DOM/elements.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dt = exports.dl = exports.li = exports.ol = exports.ul = exports.rp = exports.rt = exports.dfn = exports.time = exports.abbr = exports.small = exports.mark = exports.sup = exports.sub = exports.ins = exports.del = exports.strike = exports.s = exports.u = exports.em = exports.i = exports.strong = exports.b = exports.a = exports.q = exports.cite = exports._var = exports.samp = exports.kbd = exports.code = exports.pre = exports.p = exports.h6 = exports.h5 = exports.h4 = exports.h3 = exports.h2 = exports.h1 = exports.address = exports.blockquote = exports.hr = exports.footer = exports.header = exports.main = exports.nav = exports.aside = exports.article = exports.section = exports.span = exports.div = void 0;
|
|
4
|
-
exports.text = exports.slot = exports.template = exports.area = exports.map = exports.svg = exports.canvas = exports.menu = exports.dialog = exports.summary = exports.details = exports.iframe = exports.param = exports.object = exports.embed = exports.track = exports.video = exports.audio = exports.source = exports.picture = exports.figcaption = exports.figure = exports.img = exports.meter = exports.progress = exports.output = exports.datalist = exports.legend = exports.fieldset = exports.label = exports.optgroup = exports.option = exports.select = exports.button = exports.textarea = exports.input = exports.form = exports.colgroup = exports.col = exports.td = exports.th = exports.tr = exports.tfoot = exports.tbody = exports.thead = exports.table = exports.dd = void 0;
|
|
4
|
+
exports.text = exports.fragment = exports.slot = exports.template = exports.area = exports.map = exports.svg = exports.canvas = exports.menu = exports.dialog = exports.summary = exports.details = exports.iframe = exports.param = exports.object = exports.embed = exports.track = exports.video = exports.audio = exports.source = exports.picture = exports.figcaption = exports.figure = exports.img = exports.meter = exports.progress = exports.output = exports.datalist = exports.legend = exports.fieldset = exports.label = exports.optgroup = exports.option = exports.select = exports.button = exports.textarea = exports.input = exports.form = exports.colgroup = exports.col = exports.td = exports.th = exports.tr = exports.tfoot = exports.tbody = exports.thead = exports.table = exports.dd = void 0;
|
|
5
5
|
const vNode_1 = require("../Node/vNode");
|
|
6
|
+
const vNode_types_1 = require("../Node/vNode.types");
|
|
6
7
|
// Layout
|
|
7
8
|
exports.div = vNode_1.vNode.ToFunction("div");
|
|
8
9
|
exports.span = vNode_1.vNode.ToFunction("span");
|
|
@@ -109,8 +110,13 @@ exports.area = vNode_1.vNode.ToFunction("area");
|
|
|
109
110
|
// Meta content
|
|
110
111
|
exports.template = vNode_1.vNode.ToFunction("template");
|
|
111
112
|
exports.slot = vNode_1.vNode.ToFunction("slot");
|
|
113
|
+
const fragmentElement = vNode_1.vNode.ToFunction(vNode_types_1.FRAGMENT_NODE);
|
|
114
|
+
const fragment = function (config, children) {
|
|
115
|
+
return fragmentElement(config, children);
|
|
116
|
+
};
|
|
117
|
+
exports.fragment = fragment;
|
|
112
118
|
// Text node
|
|
113
|
-
const textElement = vNode_1.vNode.ToFunction(
|
|
119
|
+
const textElement = vNode_1.vNode.ToFunction(vNode_types_1.TEXT_NODE);
|
|
114
120
|
const text = function (callback) {
|
|
115
121
|
return textElement({ props: () => ({ nodeValue: callback() }) });
|
|
116
122
|
};
|
package/Node/nodeConfig.d.ts
CHANGED
|
@@ -42,5 +42,6 @@ export interface INodeConfig {
|
|
|
42
42
|
getNextSibling(target: any): any;
|
|
43
43
|
replaceChildren(target: any, children: any[]): void;
|
|
44
44
|
reconcileChildren(target: any, children: any[]): void;
|
|
45
|
+
reconcileRange(target: any, start: any, end: any, children: any[]): void;
|
|
45
46
|
}
|
|
46
47
|
export declare const NodeConfig: INodeConfig;
|
package/Node/vNode.d.ts
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { vNode as vNodeType, vNodeDefinition, FunctionOr, vNodeEvents, vNodeChildrenFunction, vElementNode } from "./vNode.types";
|
|
3
|
-
type vNodeConfig<P = HTMLElement, E = HTMLElementEventMap, T = never> = {
|
|
4
|
-
props?: FunctionOr<RecursivePartial<P>>;
|
|
5
|
-
attrs?: FunctionOr<{
|
|
6
|
-
[name: string]: string;
|
|
7
|
-
}>;
|
|
8
|
-
on?: FunctionOr<vNodeEvents<E>>;
|
|
9
|
-
data?: () => T | Array<T> | Promise<Array<T>> | Promise<T>;
|
|
10
|
-
};
|
|
1
|
+
import { vNode as vNodeType, vNodeDefinition, vNodeChildrenFunction, vElementNode, vNodeConfig, TEXT_NODE, FRAGMENT_NODE } from "./vNode.types";
|
|
11
2
|
export declare namespace vNode {
|
|
12
3
|
function Create<P = HTMLElement, E = HTMLElementEventMap, T = never>(definition: vNodeDefinition<P, E, T>): vElementNode;
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
function InitAll(vnodes: vNodeType[]): void;
|
|
4
|
+
function Init(vnode: vNodeType, parentNode?: vElementNode): void;
|
|
5
|
+
function InitAll(vnodes: vNodeType[], parentNode?: vElementNode): void;
|
|
16
6
|
function Destroy(vnode: vNodeType): void;
|
|
17
7
|
function DestroyAll(vnodes: vNodeType[]): void;
|
|
18
|
-
function ToFunction<P = HTMLElement, E = HTMLElementEventMap>(type: string, namespace?: string): <T>(config: vNodeConfig<P, E, T>, children?: vNodeType[] | vNodeChildrenFunction<T>) => vElementNode;
|
|
8
|
+
function ToFunction<P = HTMLElement, E = HTMLElementEventMap>(type: string | typeof TEXT_NODE | typeof FRAGMENT_NODE, namespace?: string): <T>(config: vNodeConfig<P, E, T>, children?: vNodeType[] | vNodeChildrenFunction<T>) => vElementNode;
|
|
19
9
|
function Attach(node: any, vnode: vNodeType): vNodeType;
|
|
20
10
|
}
|
|
21
|
-
export {};
|
package/Node/vNode.js
CHANGED
|
@@ -20,6 +20,7 @@ var vNode;
|
|
|
20
20
|
return new injector_1.Injector();
|
|
21
21
|
})
|
|
22
22
|
: (injector_1.Injector.Current() ?? new injector_1.Injector()),
|
|
23
|
+
parentNode: null,
|
|
23
24
|
node: definition.node ?? null,
|
|
24
25
|
children: null,
|
|
25
26
|
destroyed: false,
|
|
@@ -29,29 +30,15 @@ var vNode;
|
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
vNode.Create = Create;
|
|
32
|
-
function
|
|
33
|
-
return {
|
|
34
|
-
definition: null,
|
|
35
|
-
type: "text",
|
|
36
|
-
injector: null,
|
|
37
|
-
node: nodeConfig_1.NodeConfig.createTextNode(text),
|
|
38
|
-
children: null,
|
|
39
|
-
destroyed: false,
|
|
40
|
-
onDestroyed: null,
|
|
41
|
-
component: null,
|
|
42
|
-
scopes: [],
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
vNode.CreateText = CreateText;
|
|
46
|
-
function Init(vnode) {
|
|
33
|
+
function Init(vnode, parentNode = null) {
|
|
47
34
|
if ((0, vNode_types_1.isStringNode)(vnode) || vnode.definition === null)
|
|
48
35
|
return;
|
|
49
|
-
InitNode(vnode);
|
|
36
|
+
InitNode(vnode, parentNode);
|
|
50
37
|
}
|
|
51
38
|
vNode.Init = Init;
|
|
52
|
-
function InitAll(vnodes) {
|
|
39
|
+
function InitAll(vnodes, parentNode = null) {
|
|
53
40
|
for (let x = 0; x < vnodes.length; x++)
|
|
54
|
-
Init(vnodes[x]);
|
|
41
|
+
Init(vnodes[x], parentNode);
|
|
55
42
|
}
|
|
56
43
|
vNode.InitAll = InitAll;
|
|
57
44
|
function Destroy(vnode) {
|
|
@@ -85,6 +72,9 @@ var vNode;
|
|
|
85
72
|
}
|
|
86
73
|
vNode.ToFunction = ToFunction;
|
|
87
74
|
function Attach(node, vnode) {
|
|
75
|
+
if (vnode.type === vNode_types_1.FRAGMENT_NODE)
|
|
76
|
+
throw new Error("Cannot attach a fragment directly. A fragment has no DOM node — " +
|
|
77
|
+
"wrap it in a real element (e.g. div) before attaching.");
|
|
88
78
|
Init(vnode);
|
|
89
79
|
nodeConfig_1.NodeConfig.addChild(node, vnode.node);
|
|
90
80
|
return vnode;
|
|
@@ -94,11 +84,21 @@ var vNode;
|
|
|
94
84
|
function ComponentChildren() {
|
|
95
85
|
return this.Template();
|
|
96
86
|
}
|
|
97
|
-
function InitNode(vnode) {
|
|
87
|
+
function InitNode(vnode, parentNode) {
|
|
98
88
|
const { type, namespace, props, attrs, on, data, componentFactory, children, childrenArray, } = vnode.definition;
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
let node = null;
|
|
90
|
+
switch (vnode.type) {
|
|
91
|
+
case vNode_types_1.FRAGMENT_NODE:
|
|
92
|
+
break;
|
|
93
|
+
case vNode_types_1.TEXT_NODE:
|
|
94
|
+
vnode.node = node = vnode.definition.node ?? nodeConfig_1.NodeConfig.createTextNode();
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
vnode.node = node = vnode.definition.node ?? nodeConfig_1.NodeConfig.createNode(type, namespace);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
101
100
|
vnode.definition = null;
|
|
101
|
+
vnode.parentNode = parentNode;
|
|
102
102
|
if (props) {
|
|
103
103
|
if (typeof props === "function") {
|
|
104
104
|
const assignProperties = nodeConfig_1.NodeConfig.createPropertyAssignment(node);
|
|
@@ -139,7 +139,7 @@ function InitNode(vnode) {
|
|
|
139
139
|
}
|
|
140
140
|
else if (childrenArray) {
|
|
141
141
|
vnode.children = childrenArray;
|
|
142
|
-
vNode.InitAll(childrenArray);
|
|
142
|
+
vNode.InitAll(childrenArray, vnode);
|
|
143
143
|
}
|
|
144
144
|
else if (children) {
|
|
145
145
|
Children(vnode, children, data);
|
|
@@ -174,6 +174,9 @@ function CreateChildrenScope(vnode, children, data) {
|
|
|
174
174
|
}
|
|
175
175
|
return Store_1.ObservableScope.Create(DynamicChildrenFunction.bind(null, vnode.injector, children, data));
|
|
176
176
|
}
|
|
177
|
+
function ToVNodeType(children) {
|
|
178
|
+
return typeof children === "string" ? { type: vNode_types_1.STRING_NODE, node: children } : children;
|
|
179
|
+
}
|
|
177
180
|
function GetNextNodes(injector, children, data) {
|
|
178
181
|
return ToVNodeType(injector_1.Injector.Scope(injector, children, data));
|
|
179
182
|
}
|
|
@@ -201,11 +204,13 @@ function ToArray(result) {
|
|
|
201
204
|
return result;
|
|
202
205
|
return [result];
|
|
203
206
|
}
|
|
204
|
-
function ToVNodeType(children) {
|
|
205
|
-
return typeof children === "string" ? { type: "string", node: children } : children;
|
|
206
|
-
}
|
|
207
207
|
function GetNode(vnode) {
|
|
208
|
-
|
|
208
|
+
switch (vnode.type) {
|
|
209
|
+
case vNode_types_1.FRAGMENT_NODE:
|
|
210
|
+
return vnode.children.flatMap(GetNode);
|
|
211
|
+
default:
|
|
212
|
+
return vnode.node;
|
|
213
|
+
}
|
|
209
214
|
}
|
|
210
215
|
function UpdateChildren(vnode, init = false, skipInit = false) {
|
|
211
216
|
if (!vnode.children)
|
|
@@ -220,22 +225,33 @@ function UpdateChildren(vnode, init = false, skipInit = false) {
|
|
|
220
225
|
(0, thread_1.Schedule)(function () {
|
|
221
226
|
if (vnode.destroyed || children !== vnode.children)
|
|
222
227
|
return;
|
|
223
|
-
vNode.Init(childNode);
|
|
228
|
+
vNode.Init(childNode, vnode);
|
|
224
229
|
});
|
|
225
230
|
}
|
|
226
231
|
}
|
|
227
232
|
(0, thread_1.Thread)(function (async) {
|
|
228
233
|
if (vnode.destroyed || children !== vnode.children)
|
|
229
234
|
return;
|
|
230
|
-
if (init
|
|
231
|
-
|
|
235
|
+
if (init) {
|
|
236
|
+
if (vnode.node !== null)
|
|
237
|
+
nodeConfig_1.NodeConfig.reconcileChildren(vnode.node, vnode.children.flatMap(GetNode));
|
|
232
238
|
}
|
|
233
|
-
else
|
|
239
|
+
else if (!async) {
|
|
240
|
+
let reconcileNode = vnode;
|
|
241
|
+
while (reconcileNode.node === null)
|
|
242
|
+
reconcileNode = reconcileNode.parentNode;
|
|
243
|
+
nodeConfig_1.NodeConfig.reconcileChildren(reconcileNode.node, reconcileNode.children.flatMap(GetNode));
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
234
246
|
nodeConfig_1.NodeConfig.scheduleUpdate(function () {
|
|
235
247
|
if (vnode.destroyed || children !== vnode.children)
|
|
236
248
|
return;
|
|
237
|
-
|
|
249
|
+
let reconcileNode = vnode;
|
|
250
|
+
while (reconcileNode.node === null)
|
|
251
|
+
reconcileNode = reconcileNode.parentNode;
|
|
252
|
+
nodeConfig_1.NodeConfig.reconcileChildren(reconcileNode.node, reconcileNode.children.flatMap(GetNode));
|
|
238
253
|
});
|
|
254
|
+
}
|
|
239
255
|
});
|
|
240
256
|
});
|
|
241
257
|
}
|
package/Node/vNode.types.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { IObservableScope } from "../Store/Tree/observableScope";
|
|
|
3
3
|
import { Injector } from "../Utils/injector";
|
|
4
4
|
import { RecursivePartial } from "../Utils/utils.types";
|
|
5
5
|
import { Emitter } from "../Utils/emitter";
|
|
6
|
+
export declare const STRING_NODE: unique symbol;
|
|
7
|
+
export declare const TEXT_NODE: unique symbol;
|
|
8
|
+
export declare const FRAGMENT_NODE: unique symbol;
|
|
6
9
|
export type FunctionOr<T> = {
|
|
7
10
|
(): T | Promise<T>;
|
|
8
11
|
} | T;
|
|
@@ -14,14 +17,23 @@ export type vNodeEvents<E extends {
|
|
|
14
17
|
};
|
|
15
18
|
};
|
|
16
19
|
export type vNodeChildrenFunction<T> = ((data: T) => vNode | vNode[]) | ((data: T) => string);
|
|
20
|
+
export type vNodeConfig<P = HTMLElement, E = HTMLElementEventMap, T = never> = {
|
|
21
|
+
props?: FunctionOr<RecursivePartial<P>>;
|
|
22
|
+
attrs?: FunctionOr<{
|
|
23
|
+
[name: string]: string;
|
|
24
|
+
}>;
|
|
25
|
+
on?: FunctionOr<vNodeEvents<E>>;
|
|
26
|
+
data?: () => T | Array<T> | Promise<Array<T>> | Promise<T>;
|
|
27
|
+
};
|
|
17
28
|
export type vStringNode = {
|
|
18
|
-
type:
|
|
29
|
+
type: typeof STRING_NODE;
|
|
19
30
|
node: string;
|
|
20
31
|
};
|
|
21
32
|
export type vElementNode = {
|
|
22
|
-
type: string;
|
|
33
|
+
type: string | typeof TEXT_NODE | typeof FRAGMENT_NODE;
|
|
23
34
|
definition: vNodeDefinition<any, any, any>;
|
|
24
35
|
injector: Injector;
|
|
36
|
+
parentNode: vElementNode | null;
|
|
25
37
|
node: Node | null;
|
|
26
38
|
children: vNode[];
|
|
27
39
|
destroyed: boolean;
|
|
@@ -32,7 +44,7 @@ export type vElementNode = {
|
|
|
32
44
|
export type vNode = vStringNode | vElementNode;
|
|
33
45
|
export declare function isStringNode(vnode: vNode): vnode is vStringNode;
|
|
34
46
|
export type vNodeDefinition<P = HTMLElement, E = HTMLElementEventMap, T = never> = {
|
|
35
|
-
type: string;
|
|
47
|
+
type: string | typeof TEXT_NODE | typeof FRAGMENT_NODE;
|
|
36
48
|
node?: Node;
|
|
37
49
|
namespace: string | null;
|
|
38
50
|
props?: FunctionOr<RecursivePartial<P>>;
|
package/Node/vNode.types.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FRAGMENT_NODE = exports.TEXT_NODE = exports.STRING_NODE = void 0;
|
|
3
4
|
exports.isStringNode = isStringNode;
|
|
5
|
+
exports.STRING_NODE = Symbol("STRING_NODE");
|
|
6
|
+
exports.TEXT_NODE = Symbol("TEXT_NODE");
|
|
7
|
+
exports.FRAGMENT_NODE = Symbol("FRAGMENT_NODE");
|
|
4
8
|
function isStringNode(vnode) {
|
|
5
|
-
return vnode.type ===
|
|
9
|
+
return vnode.type === exports.STRING_NODE;
|
|
6
10
|
}
|
package/Store/Store/storeSync.js
CHANGED
|
@@ -49,10 +49,10 @@ class StoreSync extends store_1.Store {
|
|
|
49
49
|
* @throws Will throw an error if no key is provided for the data.
|
|
50
50
|
*/
|
|
51
51
|
Write(data, key) {
|
|
52
|
-
// data = JsonDeepClone(data);
|
|
53
52
|
key = key || this.keyFunc?.(data);
|
|
54
53
|
if (!key)
|
|
55
54
|
throw "No key provided for data";
|
|
55
|
+
data = observableNode_1.ObservableNode.Unwrap(data);
|
|
56
56
|
const diffResult = this.diff.DiffPath(key, data);
|
|
57
57
|
this.UpdateRootMap(diffResult);
|
|
58
58
|
}
|
|
@@ -8,6 +8,7 @@ export declare namespace ObservableNode {
|
|
|
8
8
|
* @returns The unwrapped raw value without proxy wrappers.
|
|
9
9
|
*/
|
|
10
10
|
function Unwrap<T>(value: T): T;
|
|
11
|
+
function Clone<T>(value: T): T;
|
|
11
12
|
/**
|
|
12
13
|
* Creates an observable node from a plain value.
|
|
13
14
|
* Wraps the value in a proxy that tracks changes and enables reactive updates.
|
|
@@ -22,7 +23,7 @@ export declare namespace ObservableNode {
|
|
|
22
23
|
* @param value The observable node to touch.
|
|
23
24
|
* @param prop Optional property name or index to touch a specific nested property.
|
|
24
25
|
*/
|
|
25
|
-
function
|
|
26
|
+
function Update(value: unknown, prop?: string | number | symbol): void;
|
|
26
27
|
function Apply(rootNode: any, update: any): void;
|
|
27
28
|
/**
|
|
28
29
|
* Applies a JSON diff result to an observable node, efficiently updating only changed properties.
|
|
@@ -42,11 +42,20 @@ function ownKeys(value) {
|
|
|
42
42
|
function ownKeysArray(value) {
|
|
43
43
|
return Object.keys(value[NODE_VALUE]);
|
|
44
44
|
}
|
|
45
|
+
function TouchValue(value, prop = OBJECT_SCOPE) {
|
|
46
|
+
const wrapper = wrapperCache.get(value);
|
|
47
|
+
if (wrapper) {
|
|
48
|
+
const scope = wrapper[prop] ?? wrapper[OBJECT_SCOPE];
|
|
49
|
+
observableScope_1.ObservableScope.Touch(scope);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
45
52
|
function UnwrapProxy(value, type = (0, json_2.JsonType)(value)) {
|
|
46
53
|
if (type === "value")
|
|
47
54
|
return value;
|
|
48
|
-
if (value[IS_NODE])
|
|
49
|
-
|
|
55
|
+
if (value[IS_NODE]) {
|
|
56
|
+
const nodeValue = value[NODE_VALUE];
|
|
57
|
+
return nodeValue;
|
|
58
|
+
}
|
|
50
59
|
switch (type) {
|
|
51
60
|
case "object": {
|
|
52
61
|
const keys = Object.keys(value);
|
|
@@ -62,6 +71,27 @@ function UnwrapProxy(value, type = (0, json_2.JsonType)(value)) {
|
|
|
62
71
|
}
|
|
63
72
|
return value;
|
|
64
73
|
}
|
|
74
|
+
function CloneProxy(value, type = (0, json_2.JsonType)(value)) {
|
|
75
|
+
if (type === "value")
|
|
76
|
+
return value;
|
|
77
|
+
if (value[IS_NODE]) {
|
|
78
|
+
return (0, json_1.JsonDeepClone)(value);
|
|
79
|
+
}
|
|
80
|
+
switch (type) {
|
|
81
|
+
case "object": {
|
|
82
|
+
const keys = Object.keys(value);
|
|
83
|
+
for (let x = 0; x < keys.length; x++)
|
|
84
|
+
value[keys[x]] = CloneProxy(value[keys[x]]);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case "array": {
|
|
88
|
+
for (let x = 0; x < value.length; x++)
|
|
89
|
+
value[x] = CloneProxy(value[x]);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
65
95
|
function CreateProxyFactory(alias) {
|
|
66
96
|
function ToJsonCopy(value) {
|
|
67
97
|
const type = (0, json_2.JsonType)(value);
|
|
@@ -146,7 +176,7 @@ function CreateProxyFactory(alias) {
|
|
|
146
176
|
case NODE_VALUE:
|
|
147
177
|
return object[NODE_VALUE];
|
|
148
178
|
default: {
|
|
149
|
-
const scope = object[OBJECT_SCOPE];
|
|
179
|
+
const scope = object[OBJECT_SCOPE];
|
|
150
180
|
const array = observableScope_1.ObservableScope.Value(scope);
|
|
151
181
|
const arrayValue = array[prop];
|
|
152
182
|
if (typeof prop === "symbol")
|
|
@@ -264,6 +294,10 @@ var ObservableNode;
|
|
|
264
294
|
return UnwrapProxy(value);
|
|
265
295
|
}
|
|
266
296
|
ObservableNode.Unwrap = Unwrap;
|
|
297
|
+
function Clone(value) {
|
|
298
|
+
return CloneProxy(value);
|
|
299
|
+
}
|
|
300
|
+
ObservableNode.Clone = Clone;
|
|
267
301
|
/**
|
|
268
302
|
* Creates an observable node from a plain value.
|
|
269
303
|
* Wraps the value in a proxy that tracks changes and enables reactive updates.
|
|
@@ -281,14 +315,14 @@ var ObservableNode;
|
|
|
281
315
|
* @param value The observable node to touch.
|
|
282
316
|
* @param prop Optional property name or index to touch a specific nested property.
|
|
283
317
|
*/
|
|
284
|
-
function
|
|
318
|
+
function Update(value, prop = OBJECT_SCOPE) {
|
|
285
319
|
const wrapper = wrapperCache.get(value);
|
|
286
320
|
if (wrapper) {
|
|
287
321
|
const scope = wrapper[prop] ?? wrapper[OBJECT_SCOPE];
|
|
288
322
|
observableScope_1.ObservableScope.Update(scope);
|
|
289
323
|
}
|
|
290
324
|
}
|
|
291
|
-
ObservableNode.
|
|
325
|
+
ObservableNode.Update = Update;
|
|
292
326
|
function Apply(rootNode, update) {
|
|
293
327
|
const root = rootNode[NODE_VALUE];
|
|
294
328
|
const diff = (0, json_1.JsonDiff)(update, root);
|
|
@@ -313,7 +347,7 @@ var ObservableNode;
|
|
|
313
347
|
switch (rootType) {
|
|
314
348
|
case "array": {
|
|
315
349
|
root.splice(0, root.length, ...rootPatch);
|
|
316
|
-
ObservableNode.
|
|
350
|
+
ObservableNode.Update(root);
|
|
317
351
|
break;
|
|
318
352
|
}
|
|
319
353
|
case "object": {
|
|
@@ -324,7 +358,7 @@ var ObservableNode;
|
|
|
324
358
|
delete root[keys[x]];
|
|
325
359
|
Object.assign(root, rootPatch);
|
|
326
360
|
for (let x = 0; x < keys.length; x++)
|
|
327
|
-
ObservableNode.
|
|
361
|
+
ObservableNode.Update(root, keys[x]);
|
|
328
362
|
break;
|
|
329
363
|
}
|
|
330
364
|
case "value":
|
|
@@ -352,7 +386,7 @@ var ObservableNode;
|
|
|
352
386
|
}
|
|
353
387
|
const assignValue = pathTuples[y][1];
|
|
354
388
|
assignValue[path[y]] = value;
|
|
355
|
-
ObservableNode.
|
|
389
|
+
ObservableNode.Update(assignValue, path[y]);
|
|
356
390
|
}
|
|
357
391
|
}
|
|
358
392
|
ObservableNode.ApplyDiff = ApplyDiff;
|
|
@@ -117,14 +117,12 @@ export declare namespace ObservableScope {
|
|
|
117
117
|
* Creates a new observable scope from a value function.
|
|
118
118
|
* @template T The type of value returned by the function.
|
|
119
119
|
* @param valueFunction Function that returns the scope's value. Can be async.
|
|
120
|
-
* @param greedy Whether updates should be batched via microtask queue. Defaults to false.
|
|
121
|
-
* @param force If true, always creates a dynamic scope even without dependencies. Defaults to false.
|
|
122
120
|
* @returns A new observable scope.
|
|
123
121
|
*/
|
|
124
122
|
function Create<T>(valueFunction: {
|
|
125
123
|
(): T | Promise<T>;
|
|
126
124
|
}): IObservableScope<T>;
|
|
127
|
-
function
|
|
125
|
+
function Gated<T>(valueFunction: {
|
|
128
126
|
(): T | Promise<T>;
|
|
129
127
|
}): IObservableScope<T>;
|
|
130
128
|
function Basic<T>(valueFunction: {
|
|
@@ -161,7 +159,7 @@ export declare namespace ObservableScope {
|
|
|
161
159
|
* @param scope The scope to watch for changes.
|
|
162
160
|
* @param callback Function to invoke when the scope's value changes.
|
|
163
161
|
*/
|
|
164
|
-
function Watch<T>(scope: IObservableScope<T>, callback: (scope: IObservableScope<T>) => void): void;
|
|
162
|
+
function Watch<T>(scope: IObservableScope<T> | IBasicObservableScope<T>, callback: (scope: IObservableScope<T>) => void): void;
|
|
165
163
|
/**
|
|
166
164
|
* Unsubscribes from changes on a dynamic scope.
|
|
167
165
|
* @template T The type of value stored in the scope.
|
|
@@ -7,6 +7,7 @@ exports.GateScope = GateScope;
|
|
|
7
7
|
exports.PeekScope = PeekScope;
|
|
8
8
|
const emitter_1 = require("../../Utils/emitter");
|
|
9
9
|
const functions_1 = require("../../Utils/functions");
|
|
10
|
+
const scheduling_1 = require("../../Utils/scheduling");
|
|
10
11
|
function Invoke(param, callback) {
|
|
11
12
|
return callback(param);
|
|
12
13
|
}
|
|
@@ -87,9 +88,9 @@ function ProcessScopeQueue() {
|
|
|
87
88
|
* @param scope The scope to queue for update.
|
|
88
89
|
*/
|
|
89
90
|
function OnSetQueued(scope) {
|
|
90
|
-
if (scopeQueue.length === 0)
|
|
91
|
-
queueMicrotask(ProcessScopeQueue);
|
|
92
91
|
scopeQueue.push(scope);
|
|
92
|
+
if (scopeQueue.length === 1)
|
|
93
|
+
(0, scheduling_1._queueMicrotask)(ProcessScopeQueue);
|
|
93
94
|
}
|
|
94
95
|
/**
|
|
95
96
|
* Marks a scope as dirty and triggers update behavior based on scope type.
|
|
@@ -284,7 +285,7 @@ function ExecuteScope(scope) {
|
|
|
284
285
|
function ExecuteFunction(callback, greedy) {
|
|
285
286
|
const async = (0, functions_1.IsAsync)(callback);
|
|
286
287
|
const state = WatchFunction(callback, null, null, null);
|
|
287
|
-
if (async || state.emitters !== null) {
|
|
288
|
+
if (greedy || async || state.emitters !== null) {
|
|
288
289
|
const scope = CreateDynamicScope(callback, greedy, async ? null : state.value);
|
|
289
290
|
scope.scopes = state.nextScopes;
|
|
290
291
|
scope.mappedScopes = state.nextMappedScopes;
|
|
@@ -539,18 +540,16 @@ var ObservableScope;
|
|
|
539
540
|
* Creates a new observable scope from a value function.
|
|
540
541
|
* @template T The type of value returned by the function.
|
|
541
542
|
* @param valueFunction Function that returns the scope's value. Can be async.
|
|
542
|
-
* @param greedy Whether updates should be batched via microtask queue. Defaults to false.
|
|
543
|
-
* @param force If true, always creates a dynamic scope even without dependencies. Defaults to false.
|
|
544
543
|
* @returns A new observable scope.
|
|
545
544
|
*/
|
|
546
545
|
function Create(valueFunction) {
|
|
547
546
|
return ExecuteFunction(valueFunction, false);
|
|
548
547
|
}
|
|
549
548
|
ObservableScope.Create = Create;
|
|
550
|
-
function
|
|
549
|
+
function Gated(valueFunction) {
|
|
551
550
|
return ExecuteFunction(valueFunction, true);
|
|
552
551
|
}
|
|
553
|
-
ObservableScope.
|
|
552
|
+
ObservableScope.Gated = Gated;
|
|
554
553
|
function Basic(valueFunction) {
|
|
555
554
|
return CreateBasicScope(valueFunction);
|
|
556
555
|
}
|
|
@@ -646,7 +645,7 @@ var ObservableScope;
|
|
|
646
645
|
if (!scope || scope.destroyed || scope.type === "static")
|
|
647
646
|
return;
|
|
648
647
|
if (scope.type === "basic") {
|
|
649
|
-
emitter_1.Emitter.Emit(scope.emitter,
|
|
648
|
+
emitter_1.Emitter.Emit(scope.emitter, scope);
|
|
650
649
|
return;
|
|
651
650
|
}
|
|
652
651
|
scope.setCallback();
|
package/Utils/decorators.js
CHANGED
|
@@ -134,7 +134,10 @@ function GetDestroyArrayForPrototype(prototype, create = true) {
|
|
|
134
134
|
return array;
|
|
135
135
|
}
|
|
136
136
|
function CreateComputedScope(getter, store, defaultValue) {
|
|
137
|
-
const getterScope = observableScope_1.ObservableScope.
|
|
137
|
+
const getterScope = observableScope_1.ObservableScope.Gated(function () {
|
|
138
|
+
const value = getter();
|
|
139
|
+
return observableNode_1.ObservableNode.Clone(value);
|
|
140
|
+
});
|
|
138
141
|
observableScope_1.ObservableScope.Watch(getterScope, (scope) => {
|
|
139
142
|
const data = observableScope_1.ObservableScope.Peek(scope);
|
|
140
143
|
store.Write(data, "root");
|
|
@@ -814,7 +817,7 @@ function WatchDecorator(target, propertyKey, descriptor, scopeFunction) {
|
|
|
814
817
|
function scopeFunctionWrapper() {
|
|
815
818
|
return scopeFunction(instance);
|
|
816
819
|
}
|
|
817
|
-
const scope = observableScope_1.ObservableScope.
|
|
820
|
+
const scope = observableScope_1.ObservableScope.Gated(scopeFunctionWrapper);
|
|
818
821
|
const propertyMap = GetScopeMapForInstance(this);
|
|
819
822
|
propertyMap[propertyKey] = [scope, undefined];
|
|
820
823
|
observableScope_1.ObservableScope.Watch(scope, function (scope) {
|
package/Utils/emitter.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Emitter = void 0;
|
|
4
|
-
const
|
|
5
|
-
? requestIdleCallback
|
|
6
|
-
: setTimeout;
|
|
4
|
+
const scheduling_1 = require("./scheduling");
|
|
7
5
|
const pendingCompactEmitters = new Set();
|
|
8
6
|
function Compact(emitter) {
|
|
9
7
|
if (emitter.length === 1 || emitter[0] === 0)
|
|
@@ -16,7 +14,7 @@ function ScheduleCompact() {
|
|
|
16
14
|
if (compactScheduled)
|
|
17
15
|
return;
|
|
18
16
|
compactScheduled = true;
|
|
19
|
-
|
|
17
|
+
(0, scheduling_1._requestIdleCallback)(PerformCompact);
|
|
20
18
|
}
|
|
21
19
|
function PerformCompact() {
|
|
22
20
|
compactScheduled = false;
|
package/Utils/json.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type JsonDiffFactoryResult = ReturnType<typeof JsonDiffFactory>;
|
|
|
16
16
|
export declare function JsonDiffFactory(): {
|
|
17
17
|
JsonDiff: <T>(newValue: T, oldValue: T, rootPath?: string, initResult?: JsonDiffResult<T>) => JsonDiffResult<T>;
|
|
18
18
|
JsonType: (value: any) => "object" | "value" | "array";
|
|
19
|
-
JsonDeepClone: <T>(value: T) => T;
|
|
19
|
+
JsonDeepClone: <T>(value: T, type?: string) => T;
|
|
20
20
|
JsonMerge: (source: unknown, patch: unknown) => unknown;
|
|
21
21
|
};
|
|
22
|
-
export declare const JsonDiff: <T>(newValue: T, oldValue: T, rootPath?: string, initResult?: JsonDiffResult<T>) => JsonDiffResult<T>, JsonType: (value: any) => "object" | "value" | "array", JsonDeepClone: <T>(value: T) => T, JsonMerge: (source: unknown, patch: unknown) => unknown;
|
|
22
|
+
export declare const JsonDiff: <T>(newValue: T, oldValue: T, rootPath?: string, initResult?: JsonDiffResult<T>) => JsonDiffResult<T>, JsonType: (value: any) => "object" | "value" | "array", JsonDeepClone: <T>(value: T, type?: string) => T, JsonMerge: (source: unknown, patch: unknown) => unknown;
|
package/Utils/json.js
CHANGED
|
@@ -84,8 +84,7 @@ function JsonDiffFactory() {
|
|
|
84
84
|
* @param value - The value to clone
|
|
85
85
|
* @returns A deep clone of the value
|
|
86
86
|
*/
|
|
87
|
-
function JsonDeepClone(value) {
|
|
88
|
-
const type = JsonType(value);
|
|
87
|
+
function JsonDeepClone(value, type = JsonType(value)) {
|
|
89
88
|
switch (type) {
|
|
90
89
|
case "array": {
|
|
91
90
|
const typed = value;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const _requestAnimationFrame: typeof window.requestAnimationFrame;
|
|
2
|
+
export declare const _setTimeout: typeof window.setTimeout;
|
|
3
|
+
export declare const _queueMicrotask: typeof window.queueMicrotask;
|
|
4
|
+
export declare const _requestIdleCallback: typeof window.requestIdleCallback;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports._requestIdleCallback = exports._queueMicrotask = exports._setTimeout = exports._requestAnimationFrame = void 0;
|
|
4
|
+
const IMMEDIATE_OVERRIDE = typeof process !== "undefined" ?
|
|
5
|
+
process.env.SYNC_SCHEDULING === 'true' :
|
|
6
|
+
false;
|
|
7
|
+
exports._requestAnimationFrame = IMMEDIATE_OVERRIDE ?
|
|
8
|
+
function immediateRequestAnimationFrame(callback) {
|
|
9
|
+
callback(0);
|
|
10
|
+
return 0;
|
|
11
|
+
} : window.requestAnimationFrame;
|
|
12
|
+
exports._setTimeout = IMMEDIATE_OVERRIDE ?
|
|
13
|
+
function immediateSetTimeout(handler, timeout, ...args) {
|
|
14
|
+
if (typeof handler === "function")
|
|
15
|
+
handler(...args);
|
|
16
|
+
return 0;
|
|
17
|
+
} : window.setTimeout;
|
|
18
|
+
exports._queueMicrotask = IMMEDIATE_OVERRIDE ?
|
|
19
|
+
function immediateQueueMicrotask(callback) {
|
|
20
|
+
callback();
|
|
21
|
+
} : window.queueMicrotask;
|
|
22
|
+
exports._requestIdleCallback = IMMEDIATE_OVERRIDE ?
|
|
23
|
+
function immediateRequestIdleCallback(callback, options) {
|
|
24
|
+
callback({ didTimeout: false, timeRemaining: () => 0 });
|
|
25
|
+
return 0;
|
|
26
|
+
} : window.requestIdleCallback ?? window.setTimeout;
|
package/Utils/thread.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.Synch = Synch;
|
|
|
7
7
|
exports.Thread = Thread;
|
|
8
8
|
exports.ThreadAsync = ThreadAsync;
|
|
9
9
|
const list_1 = require("./list");
|
|
10
|
+
const scheduling_1 = require("./scheduling");
|
|
10
11
|
// Constants
|
|
11
12
|
/**
|
|
12
13
|
* The maximum time allowed for work execution in milliseconds
|
|
@@ -19,9 +20,6 @@ const contextQueue = list_1.List.Create();
|
|
|
19
20
|
// State variables
|
|
20
21
|
let threadContext = null;
|
|
21
22
|
let timeoutRunning = false;
|
|
22
|
-
// Callback scheduling functions
|
|
23
|
-
const scheduleInitialCallback = queueMicrotask;
|
|
24
|
-
const scheduleCallback = setTimeout;
|
|
25
23
|
/**
|
|
26
24
|
* Calculates the remaining time until the deadline
|
|
27
25
|
* @param this - The deadline object
|
|
@@ -49,7 +47,7 @@ function ProcessQueue(deadline = createDeadline()) {
|
|
|
49
47
|
while (deadline.timeRemaining() > 0 && (ctx = list_1.List.Pop(contextQueue)))
|
|
50
48
|
DoWork(ctx, deadline);
|
|
51
49
|
if (contextQueue.size > 0)
|
|
52
|
-
|
|
50
|
+
(0, scheduling_1._setTimeout)(ProcessQueue);
|
|
53
51
|
else
|
|
54
52
|
timeoutRunning = false;
|
|
55
53
|
}
|
|
@@ -62,7 +60,7 @@ function ScheduleWork(ctx) {
|
|
|
62
60
|
if (timeoutRunning)
|
|
63
61
|
return;
|
|
64
62
|
timeoutRunning = true;
|
|
65
|
-
|
|
63
|
+
(0, scheduling_1._queueMicrotask)(ProcessQueue);
|
|
66
64
|
}
|
|
67
65
|
/**
|
|
68
66
|
* Invokes a callback in the specified thread context
|
package/package.json
CHANGED
package/DOM/window.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const wndw: Window;
|
package/DOM/window.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wndw = void 0;
|
|
4
|
-
function jsdomWindow() {
|
|
5
|
-
try {
|
|
6
|
-
return require("jsdom").JSDOM("").window;
|
|
7
|
-
}
|
|
8
|
-
catch (err) {
|
|
9
|
-
return undefined;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
exports.wndw = typeof window !== "undefined" ? window : jsdomWindow();
|