@expressive/mvc 0.8.0 → 0.8.1
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/index.d.ts +21 -18
- package/lib/index.esm.js +65 -66
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +65 -66
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -11,14 +11,19 @@ declare type Listener = {
|
|
|
11
11
|
declare class Subscriber<T extends {} = any> {
|
|
12
12
|
parent: Control<T>;
|
|
13
13
|
onUpdate: Control.OnEvent;
|
|
14
|
+
static get<T extends {}>(from: T): Model.Subscriber<T> | undefined;
|
|
14
15
|
proxy: T;
|
|
15
|
-
commit: () => Callback;
|
|
16
16
|
release: Callback;
|
|
17
|
+
latest?: Model.Event<T>[];
|
|
17
18
|
active: boolean;
|
|
18
19
|
dependant: Set<Listener>;
|
|
19
|
-
|
|
20
|
-
static get<T extends {}>(from: T): Subscriber<T> | undefined;
|
|
20
|
+
watch: Map<any, boolean | (() => true | void)>;
|
|
21
21
|
constructor(parent: Control<T>, onUpdate: Control.OnEvent);
|
|
22
|
+
get using(): Model.Values<T>;
|
|
23
|
+
assign(apply: Model.Compat<T>, keys?: any): void;
|
|
24
|
+
add(key: any, value?: boolean | Callback): void;
|
|
25
|
+
commit: () => () => void;
|
|
26
|
+
private event;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
declare namespace Model {
|
|
@@ -133,6 +138,7 @@ declare class Control<T extends {} = any> {
|
|
|
133
138
|
frame: Set<string>;
|
|
134
139
|
waiting: Set<Callback>;
|
|
135
140
|
followers: Set<Model.Control.OnEvent<any>>;
|
|
141
|
+
latest?: Model.Event<T>[];
|
|
136
142
|
constructor(subject: T);
|
|
137
143
|
subscribe(callback: Control.OnEvent<T>): Model.Subscriber<T>;
|
|
138
144
|
watch(key: keyof T & string): void;
|
|
@@ -179,7 +185,7 @@ declare namespace Instruction {
|
|
|
179
185
|
* Run instruction as controller sets itself up.
|
|
180
186
|
* This will specialize the behavior of a given property.
|
|
181
187
|
*/
|
|
182
|
-
declare function add<T = any>(instruction: Instruction<
|
|
188
|
+
declare function add<T = any>(instruction: Instruction<any>, label?: string): T;
|
|
183
189
|
|
|
184
190
|
declare type Async<T = any> = (...args: any[]) => Promise<T>;
|
|
185
191
|
/**
|
|
@@ -419,15 +425,15 @@ declare class MVC extends Model {
|
|
|
419
425
|
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
|
|
420
426
|
}
|
|
421
427
|
|
|
422
|
-
declare const LOCAL
|
|
423
|
-
declare const STATE
|
|
424
|
-
declare const UPDATE
|
|
425
|
-
declare const CONTROL
|
|
428
|
+
declare const LOCAL = "$debug local";
|
|
429
|
+
declare const STATE = "$debug state";
|
|
430
|
+
declare const UPDATE = "$debug update";
|
|
431
|
+
declare const CONTROL = "$debug controller";
|
|
426
432
|
declare const Debug: {
|
|
427
|
-
readonly CONTROL:
|
|
428
|
-
readonly LOCAL:
|
|
429
|
-
readonly STATE:
|
|
430
|
-
readonly UPDATE:
|
|
433
|
+
readonly CONTROL: "$debug controller";
|
|
434
|
+
readonly LOCAL: "$debug local";
|
|
435
|
+
readonly STATE: "$debug state";
|
|
436
|
+
readonly UPDATE: "$debug update";
|
|
431
437
|
};
|
|
432
438
|
declare type Debug<T extends {}> = T & {
|
|
433
439
|
/** Controller for this instance. */
|
|
@@ -573,12 +579,9 @@ declare function tap<T extends Model>(Type: Model.Type<T>, required?: boolean):
|
|
|
573
579
|
declare function useFrom<T extends {}, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect: true): Exclude<R, undefined>;
|
|
574
580
|
declare function useFrom<T extends {}, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect?: boolean): R;
|
|
575
581
|
|
|
576
|
-
declare function useModel<T extends Model>(source: Model.Type<T
|
|
577
|
-
declare function useModel<T extends Model>(source: Model.Type<T
|
|
578
|
-
declare function useModel<T extends Model>(source: Model.Type<T
|
|
579
|
-
declare function useModel<T extends Model>(source: () => T, watch?: Model.Field<T>[], callback?: (instance: T) => void): T;
|
|
580
|
-
declare function useModel<T extends Model>(source: () => T, callback?: (instance: T) => void): T;
|
|
581
|
-
declare function useModel<T extends Model>(source: () => T, apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
|
|
582
|
+
declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), callback?: (instance: T) => void): T;
|
|
583
|
+
declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), watch: Model.Field<T>[], callback?: (instance: T) => void): T;
|
|
584
|
+
declare function useModel<T extends Model>(source: Model.Type<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
|
|
582
585
|
|
|
583
586
|
declare namespace useTap {
|
|
584
587
|
type Source<T extends Model> = T | Model.Type<T> | (() => T | Model.Type<T>);
|
package/lib/index.esm.js
CHANGED
|
@@ -187,20 +187,21 @@ class Subscriber {
|
|
|
187
187
|
this.onUpdate = onUpdate;
|
|
188
188
|
this.active = false;
|
|
189
189
|
this.dependant = new Set();
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
190
|
+
this.watch = new Map();
|
|
191
|
+
this.commit = () => {
|
|
192
|
+
const release = this.parent.addListener(this.event);
|
|
193
|
+
this.active = true;
|
|
194
|
+
this.dependant.forEach(x => x.commit());
|
|
195
|
+
return this.release = () => {
|
|
196
|
+
this.dependant.forEach(x => x.release());
|
|
197
|
+
release();
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
this.event = (key) => {
|
|
201
201
|
if (!this.active)
|
|
202
202
|
return;
|
|
203
|
-
const
|
|
203
|
+
const { parent, watch } = this;
|
|
204
|
+
const handler = watch.get(key);
|
|
204
205
|
let notify;
|
|
205
206
|
if (typeof handler == "function") {
|
|
206
207
|
const callback = handler();
|
|
@@ -211,49 +212,47 @@ class Subscriber {
|
|
|
211
212
|
notify = this.onUpdate(key, parent);
|
|
212
213
|
if (!notify)
|
|
213
214
|
return;
|
|
214
|
-
parent.waiting.add(() =>
|
|
215
|
+
parent.waiting.add(() => {
|
|
216
|
+
this.latest = parent.latest.filter(k => watch.has(k));
|
|
217
|
+
});
|
|
215
218
|
parent.waiting.add(notify);
|
|
216
|
-
});
|
|
217
|
-
this.add = (key, value) => {
|
|
218
|
-
if (value !== undefined)
|
|
219
|
-
using.set(key, value);
|
|
220
|
-
else if (!using.has(key))
|
|
221
|
-
using.set(key, true);
|
|
222
|
-
};
|
|
223
|
-
this.commit = () => {
|
|
224
|
-
this.active = true;
|
|
225
|
-
this.dependant.forEach(x => x.commit());
|
|
226
|
-
return this.release;
|
|
227
|
-
};
|
|
228
|
-
this.release = () => {
|
|
229
|
-
this.dependant.forEach(x => x.release());
|
|
230
|
-
release();
|
|
231
219
|
};
|
|
220
|
+
const proxy = create(parent.subject);
|
|
221
|
+
const reset = () => this.latest = undefined;
|
|
222
|
+
REGISTER$1.set(proxy, this);
|
|
223
|
+
defineProperty(this, "proxy", {
|
|
224
|
+
configurable: true,
|
|
225
|
+
get() {
|
|
226
|
+
setTimeout(reset, 0);
|
|
227
|
+
return proxy;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
232
230
|
}
|
|
233
231
|
static get(from) {
|
|
234
232
|
return REGISTER$1.get(from);
|
|
235
233
|
}
|
|
234
|
+
get using() {
|
|
235
|
+
return Array.from(this.watch.keys());
|
|
236
|
+
}
|
|
237
|
+
assign(apply, keys) {
|
|
238
|
+
const { waiting, subject } = this.parent;
|
|
239
|
+
this.active = false;
|
|
240
|
+
if (typeof keys !== "object")
|
|
241
|
+
keys = getOwnPropertyNames(subject);
|
|
242
|
+
for (const key of keys)
|
|
243
|
+
if (key in apply)
|
|
244
|
+
subject[key] = apply[key];
|
|
245
|
+
waiting.add(() => this.active = true);
|
|
246
|
+
}
|
|
247
|
+
add(key, value) {
|
|
248
|
+
if (value !== undefined)
|
|
249
|
+
this.watch.set(key, value);
|
|
250
|
+
else if (!this.watch.has(key))
|
|
251
|
+
this.watch.set(key, true);
|
|
252
|
+
}
|
|
236
253
|
}
|
|
237
254
|
|
|
238
255
|
const REGISTER = new WeakMap();
|
|
239
|
-
const UPDATE$1 = new WeakMap();
|
|
240
|
-
function getUpdate(subject) {
|
|
241
|
-
return UPDATE$1.get(subject);
|
|
242
|
-
}
|
|
243
|
-
function setUpdate(subject, keys) {
|
|
244
|
-
UPDATE$1.set(subject, Array.from(keys));
|
|
245
|
-
setTimeout(() => UPDATE$1.delete(subject), 0);
|
|
246
|
-
}
|
|
247
|
-
/** Ensure a local update is dropped after use. */
|
|
248
|
-
function hasUpdate(proxy) {
|
|
249
|
-
if (UPDATE$1.has(proxy))
|
|
250
|
-
setTimeout(() => UPDATE$1.delete(proxy), 0);
|
|
251
|
-
}
|
|
252
|
-
/** Set local update for a subscribed context. */
|
|
253
|
-
function addUpdate(proxy, using) {
|
|
254
|
-
const parent = UPDATE$1.get(getPrototypeOf(proxy));
|
|
255
|
-
UPDATE$1.set(proxy, parent.filter(k => using.has(k)));
|
|
256
|
-
}
|
|
257
256
|
class Control {
|
|
258
257
|
constructor(subject) {
|
|
259
258
|
this.subject = subject;
|
|
@@ -320,7 +319,8 @@ class Control {
|
|
|
320
319
|
else if (!frame.size)
|
|
321
320
|
setTimeout(() => {
|
|
322
321
|
flush(this);
|
|
323
|
-
|
|
322
|
+
this.latest = Array.from(frame);
|
|
323
|
+
setTimeout(() => this.latest = undefined, 0);
|
|
324
324
|
frame.clear();
|
|
325
325
|
for (const notify of waiting)
|
|
326
326
|
try {
|
|
@@ -371,12 +371,16 @@ class Control {
|
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
const PENDING = new Map();
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Run instruction as controller sets itself up.
|
|
376
|
+
* This will specialize the behavior of a given property.
|
|
377
|
+
*/
|
|
378
|
+
function add(instruction, label) {
|
|
379
|
+
const name = label || instruction.name || "pending";
|
|
376
380
|
const placeholder = Symbol(`${name} instruction`);
|
|
377
381
|
function setup(key) {
|
|
378
382
|
const { subject, state } = this;
|
|
379
|
-
let output =
|
|
383
|
+
let output = instruction.call(this, key, this);
|
|
380
384
|
if (typeof output == "function")
|
|
381
385
|
output = { get: output };
|
|
382
386
|
if (typeof output != "object")
|
|
@@ -929,7 +933,7 @@ class Model {
|
|
|
929
933
|
}
|
|
930
934
|
else if (keys.includes(key)) {
|
|
931
935
|
removeListener();
|
|
932
|
-
return () => resolve(single ? control.state.get(key) :
|
|
936
|
+
return () => resolve(single ? control.state.get(key) : control.latest);
|
|
933
937
|
}
|
|
934
938
|
});
|
|
935
939
|
});
|
|
@@ -949,7 +953,7 @@ class Model {
|
|
|
949
953
|
catch (e) { }
|
|
950
954
|
const callback = single
|
|
951
955
|
? () => { argument.call(this, control.state.get(select), select); }
|
|
952
|
-
: () => { argument.call(this,
|
|
956
|
+
: () => { argument.call(this, control.latest); };
|
|
953
957
|
const onEvent = once
|
|
954
958
|
? () => {
|
|
955
959
|
removeListener();
|
|
@@ -1034,7 +1038,7 @@ class Model {
|
|
|
1034
1038
|
throw Oops$5.NoChaining();
|
|
1035
1039
|
if (frame.size || arg1 !== false)
|
|
1036
1040
|
waiting.add(() => {
|
|
1037
|
-
callback(
|
|
1041
|
+
callback(control.latest);
|
|
1038
1042
|
});
|
|
1039
1043
|
else
|
|
1040
1044
|
callback(false);
|
|
@@ -1227,14 +1231,8 @@ function useModel(source, arg, arg2) {
|
|
|
1227
1231
|
return instance;
|
|
1228
1232
|
}
|
|
1229
1233
|
const local = use(refresh => (Control.for(instance).subscribe(() => refresh)));
|
|
1230
|
-
if (typeof arg == "object")
|
|
1231
|
-
local.
|
|
1232
|
-
if (typeof arg2 !== "object")
|
|
1233
|
-
arg2 = getOwnPropertyNames(instance);
|
|
1234
|
-
for (const key of arg2)
|
|
1235
|
-
if (key in arg)
|
|
1236
|
-
instance[key] = arg[key];
|
|
1237
|
-
}
|
|
1234
|
+
if (typeof arg == "object")
|
|
1235
|
+
local.assign(arg, arg2);
|
|
1238
1236
|
React.useLayoutEffect(() => {
|
|
1239
1237
|
local.commit();
|
|
1240
1238
|
return () => {
|
|
@@ -1324,10 +1322,10 @@ class MVC extends Model {
|
|
|
1324
1322
|
}
|
|
1325
1323
|
}
|
|
1326
1324
|
|
|
1327
|
-
const LOCAL =
|
|
1328
|
-
const STATE =
|
|
1329
|
-
const UPDATE =
|
|
1330
|
-
const CONTROL =
|
|
1325
|
+
const LOCAL = "$debug local";
|
|
1326
|
+
const STATE = "$debug state";
|
|
1327
|
+
const UPDATE = "$debug update";
|
|
1328
|
+
const CONTROL = "$debug controller";
|
|
1331
1329
|
Object.defineProperties(Model.prototype, {
|
|
1332
1330
|
[CONTROL]: {
|
|
1333
1331
|
get() {
|
|
@@ -1349,7 +1347,8 @@ Object.defineProperties(Model.prototype, {
|
|
|
1349
1347
|
},
|
|
1350
1348
|
[UPDATE]: {
|
|
1351
1349
|
get() {
|
|
1352
|
-
|
|
1350
|
+
const source = Subscriber.get(this) || Control.get(this);
|
|
1351
|
+
return source && source.latest;
|
|
1353
1352
|
}
|
|
1354
1353
|
}
|
|
1355
1354
|
});
|