@expressive/mvc 0.24.2 → 0.25.0
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 +12 -17
- package/lib/index.esm.js +41 -44
- package/lib/index.js +41 -44
- package/package.json +2 -2
package/lib/index.d.ts
CHANGED
|
@@ -57,16 +57,17 @@ declare namespace Control {
|
|
|
57
57
|
type Getter<T> = (source: Model) => T;
|
|
58
58
|
type Setter<T> = (value: T) => boolean | void;
|
|
59
59
|
type PropertyDescriptor<T = any> = {
|
|
60
|
-
enumerable?: boolean;
|
|
61
|
-
value?: T;
|
|
62
60
|
get?: Getter<T>;
|
|
63
61
|
set?: Setter<T> | false;
|
|
62
|
+
enumerable?: boolean;
|
|
63
|
+
value?: T;
|
|
64
64
|
};
|
|
65
|
+
type Callback = (control: Control) => void;
|
|
65
66
|
/**
|
|
66
67
|
* Callback for Controller.for() static method.
|
|
67
68
|
* Returned callback is forwarded.
|
|
68
69
|
*/
|
|
69
|
-
type OnReady<T extends {}> = (control: Control<T>) =>
|
|
70
|
+
type OnReady<T extends {}> = (control: Control<T>) => (() => void) | void;
|
|
70
71
|
type RequestRefresh = (update: (tick: number) => number) => void;
|
|
71
72
|
type GetContext = (target: Model) => (callback: (got: Context) => void) => void;
|
|
72
73
|
type GetAdapter<T> = (refresh: RequestRefresh, context: Context) => {
|
|
@@ -75,15 +76,14 @@ declare namespace Control {
|
|
|
75
76
|
} | void;
|
|
76
77
|
type GetHook = <T>(adapter: GetAdapter<T>) => T | null;
|
|
77
78
|
type UseAdapter<T extends Model, R> = (refresh: RequestRefresh) => {
|
|
78
|
-
|
|
79
|
+
instance: T;
|
|
79
80
|
mount: () => (() => void) | void;
|
|
80
81
|
render: R;
|
|
81
82
|
};
|
|
82
83
|
type UseHook = <T extends Model, R>(adapter: UseAdapter<T, R>) => R;
|
|
83
84
|
}
|
|
84
85
|
declare class Control<T extends {} = any> {
|
|
85
|
-
|
|
86
|
-
id: string | number;
|
|
86
|
+
static ready: Set<Control.Callback>;
|
|
87
87
|
static after: Set<Callback>;
|
|
88
88
|
static before: Set<Callback>;
|
|
89
89
|
static pending: Set<Callback>;
|
|
@@ -93,6 +93,8 @@ declare class Control<T extends {} = any> {
|
|
|
93
93
|
static for: typeof control;
|
|
94
94
|
static apply: typeof apply;
|
|
95
95
|
static watch: typeof watch;
|
|
96
|
+
id: string | number;
|
|
97
|
+
subject: T;
|
|
96
98
|
state: {
|
|
97
99
|
[key: string]: any;
|
|
98
100
|
};
|
|
@@ -154,19 +156,12 @@ type Debug<T extends Model = Model> = T & {
|
|
|
154
156
|
|
|
155
157
|
/** Type may not be undefined - instead will be null. */
|
|
156
158
|
type NoVoid<T> = T extends undefined | void ? null : T;
|
|
157
|
-
|
|
158
|
-
/** Fetch instance of this class in passive mode. Will not subscribe to events. */
|
|
159
|
+
/** Fetch instance of this class from context. */
|
|
159
160
|
declare function get$1<T extends Model>(this: Model.Type<T>, ignoreUpdates?: true): T;
|
|
160
161
|
/** Fetch instance of this class optionally. May be undefined, but will never subscribe. */
|
|
161
162
|
declare function get$1<T extends Model>(this: Model.Type<T>, required: boolean): T | undefined;
|
|
162
|
-
declare function get$1<T extends Model, R
|
|
163
|
-
declare function get$1<T extends Model, R
|
|
164
|
-
declare function get$1<T extends Model, R extends []>(this: Model.Type<T>, factory: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
165
|
-
declare function get$1<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, () => R>): NoVoid<R>;
|
|
166
|
-
declare function get$1<T extends Model, R>(this: Model.Type<T>, init: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
167
|
-
declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
|
|
168
|
-
declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
|
|
169
|
-
declare function get$1<T extends Model, R>(this: Model.Type<T>, compute: Model.GetCallback<T, R>, expect?: boolean): NoVoid<R>;
|
|
163
|
+
declare function get$1<T extends Model, R>(this: Model.Type<T>, factory: Model.GetCallback<T, (() => R) | R | Promise<R>>): NoVoid<R>;
|
|
164
|
+
declare function get$1<T extends Model, R>(this: Model.Type<T>, factory: Model.GetCallback<T, (() => R) | null>): NoVoid<R> | null;
|
|
170
165
|
|
|
171
166
|
declare function use$1<T extends Model>(this: Model.New<T>, callback?: (instance: T) => void, repeat?: boolean): T;
|
|
172
167
|
declare function use$1<T extends Model>(this: Model.New<T>, apply?: Model.Compat<T>, repeat?: boolean): T;
|
|
@@ -251,7 +246,7 @@ declare class Model {
|
|
|
251
246
|
get<P extends Model.Key<this>>(select: Iterable<P>): Model.Get<this, P>;
|
|
252
247
|
get<P extends Model.Key<this>>(select: P, listener: (this: this, value: this[P]) => void): Callback;
|
|
253
248
|
get<P extends Model.Key<this>>(select: Iterable<P>, listener: (this: this, value: Model.Get<this, P>) => void): Callback;
|
|
254
|
-
set<T extends Model.Compat<this>>(source: T,
|
|
249
|
+
set<T extends Model.Compat<this>>(source: T, only?: (keyof T)[]): Promise<Model.Key<T>[]>;
|
|
255
250
|
set<K extends Model.Event<this>>(key: K, value?: Model.ValueOf<this, K>): Promise<Model.Event<this>[] | false>;
|
|
256
251
|
/** Mark this instance for garbage collection. */
|
|
257
252
|
null(): void;
|
package/lib/index.esm.js
CHANGED
|
@@ -197,18 +197,18 @@ function awaitUpdate(source, select, timeout) {
|
|
|
197
197
|
const Oops$6 = issues({
|
|
198
198
|
NotFound: (name) => `Could not find ${name} in context.`
|
|
199
199
|
});
|
|
200
|
-
function get$1(
|
|
200
|
+
function get$1(argument) {
|
|
201
201
|
return Control.get((dispatch, context) => {
|
|
202
202
|
const refresh = () => dispatch(x => x + 1);
|
|
203
203
|
let onUpdate;
|
|
204
204
|
let value;
|
|
205
|
-
if (typeof
|
|
205
|
+
if (typeof argument !== "function") {
|
|
206
206
|
const got = context.get(this);
|
|
207
207
|
if (got)
|
|
208
|
-
value =
|
|
208
|
+
value = argument === undefined
|
|
209
209
|
? Control.watch(got, k => k ? onUpdate : undefined)
|
|
210
210
|
: got;
|
|
211
|
-
else if (
|
|
211
|
+
else if (argument !== false)
|
|
212
212
|
throw Oops$6.NotFound(this);
|
|
213
213
|
return {
|
|
214
214
|
mount() {
|
|
@@ -218,7 +218,7 @@ function get$1(arg1, arg2) {
|
|
|
218
218
|
render: () => value
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
|
-
let compute =
|
|
221
|
+
let compute = argument;
|
|
222
222
|
let suspense;
|
|
223
223
|
let getValue;
|
|
224
224
|
let factory;
|
|
@@ -268,7 +268,7 @@ function get$1(arg1, arg2) {
|
|
|
268
268
|
else
|
|
269
269
|
onUpdate = () => {
|
|
270
270
|
const next = getValue();
|
|
271
|
-
if (
|
|
271
|
+
if (value !== next)
|
|
272
272
|
didUpdate(next);
|
|
273
273
|
};
|
|
274
274
|
return {
|
|
@@ -278,30 +278,25 @@ function get$1(arg1, arg2) {
|
|
|
278
278
|
render: () => {
|
|
279
279
|
if (value !== undefined)
|
|
280
280
|
return value;
|
|
281
|
-
if (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
281
|
+
if (onUpdate)
|
|
282
|
+
return null;
|
|
283
|
+
throw new Promise(res => {
|
|
284
|
+
suspense = res;
|
|
285
|
+
});
|
|
286
286
|
}
|
|
287
287
|
};
|
|
288
288
|
});
|
|
289
|
-
}
|
|
290
|
-
/** Values are not equal for purposes of a refresh. */
|
|
291
|
-
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
292
|
-
!Array.isArray(b) ||
|
|
293
|
-
a.length !== b.length ||
|
|
294
|
-
a.some((x, i) => x !== b[i])));
|
|
289
|
+
}
|
|
295
290
|
|
|
296
|
-
function use$1(
|
|
291
|
+
function use$1(apply, repeat) {
|
|
297
292
|
const render = Control.use(dispatch => {
|
|
298
293
|
const instance = this.new();
|
|
299
294
|
const local = Control.watch(instance, () => onUpdate);
|
|
300
295
|
const refresh = () => dispatch(x => x + 1);
|
|
301
296
|
let onUpdate;
|
|
302
|
-
let
|
|
297
|
+
let shouldApply = !!apply;
|
|
303
298
|
return {
|
|
304
|
-
|
|
299
|
+
instance,
|
|
305
300
|
mount() {
|
|
306
301
|
onUpdate = refresh;
|
|
307
302
|
return () => {
|
|
@@ -310,7 +305,7 @@ function use$1(arg1, arg2) {
|
|
|
310
305
|
};
|
|
311
306
|
},
|
|
312
307
|
render(props) {
|
|
313
|
-
if (
|
|
308
|
+
if (shouldApply) {
|
|
314
309
|
onUpdate = undefined;
|
|
315
310
|
if (typeof props == "function")
|
|
316
311
|
props(instance);
|
|
@@ -318,15 +313,15 @@ function use$1(arg1, arg2) {
|
|
|
318
313
|
for (const key in instance)
|
|
319
314
|
if (props.hasOwnProperty(key))
|
|
320
315
|
instance[key] = props[key];
|
|
321
|
-
if (!
|
|
322
|
-
|
|
316
|
+
if (!repeat)
|
|
317
|
+
shouldApply = false;
|
|
323
318
|
instance.on(0).then(() => onUpdate = refresh);
|
|
324
319
|
}
|
|
325
320
|
return local;
|
|
326
321
|
}
|
|
327
322
|
};
|
|
328
323
|
});
|
|
329
|
-
return render(
|
|
324
|
+
return render(apply);
|
|
330
325
|
}
|
|
331
326
|
|
|
332
327
|
class Model {
|
|
@@ -427,17 +422,20 @@ const Oops$5 = issues({
|
|
|
427
422
|
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
428
423
|
});
|
|
429
424
|
const INSTRUCTION = new Map();
|
|
425
|
+
const PENDING$1 = new WeakMap();
|
|
430
426
|
const REGISTER = new WeakMap();
|
|
431
427
|
const OBSERVER = new WeakMap();
|
|
432
428
|
const PARENTS = new WeakMap();
|
|
433
429
|
class Control {
|
|
434
|
-
constructor(subject, id
|
|
435
|
-
this.
|
|
436
|
-
this.id = id;
|
|
430
|
+
constructor(subject, id) {
|
|
431
|
+
this.state = {};
|
|
437
432
|
this.frame = new Set();
|
|
438
433
|
this.followers = new Set();
|
|
439
434
|
this.observers = new Map([["", this.followers]]);
|
|
435
|
+
this.id = typeof id == "undefined" ? uid() : id;
|
|
436
|
+
this.subject = subject;
|
|
440
437
|
REGISTER.set(subject, this);
|
|
438
|
+
PENDING$1.set(this, new Set(Control.ready));
|
|
441
439
|
}
|
|
442
440
|
add(key) {
|
|
443
441
|
const { value } = getOwnPropertyDescriptor(this.subject, key);
|
|
@@ -529,31 +527,30 @@ class Control {
|
|
|
529
527
|
this.observers.clear();
|
|
530
528
|
}
|
|
531
529
|
}
|
|
530
|
+
Control.ready = new Set();
|
|
532
531
|
Control.after = new Set();
|
|
533
532
|
Control.before = new Set();
|
|
534
533
|
Control.pending = new Set();
|
|
535
534
|
Control.for = control;
|
|
536
535
|
Control.apply = apply;
|
|
537
536
|
Control.watch = watch;
|
|
538
|
-
const PENDING_INIT = new WeakMap();
|
|
539
537
|
function control(subject, ready) {
|
|
540
538
|
const control = REGISTER.get(subject.is);
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
control.state = {};
|
|
539
|
+
const pending = PENDING$1.get(control);
|
|
540
|
+
if (typeof ready == "function") {
|
|
541
|
+
if (!pending)
|
|
542
|
+
return ready(control);
|
|
543
|
+
let done;
|
|
544
|
+
pending.add(() => done = ready(control));
|
|
545
|
+
return () => done && done();
|
|
546
|
+
}
|
|
547
|
+
if (pending && ready) {
|
|
548
|
+
PENDING$1.delete(control);
|
|
552
549
|
for (const key in control.subject)
|
|
553
550
|
control.add(key);
|
|
554
|
-
|
|
551
|
+
pending.forEach(cb => cb(control));
|
|
555
552
|
}
|
|
556
|
-
return
|
|
553
|
+
return control;
|
|
557
554
|
}
|
|
558
555
|
function requestUpdateFrame(event) {
|
|
559
556
|
const { after, before, pending } = Control;
|
|
@@ -586,10 +583,10 @@ function setRecursive(on, key, value) {
|
|
|
586
583
|
on.watch(key, { set });
|
|
587
584
|
set(value);
|
|
588
585
|
}
|
|
589
|
-
function parent(child,
|
|
590
|
-
if (!
|
|
586
|
+
function parent(child, assign) {
|
|
587
|
+
if (!assign)
|
|
591
588
|
return PARENTS.get(child);
|
|
592
|
-
PARENTS.set(child,
|
|
589
|
+
PARENTS.set(child, assign);
|
|
593
590
|
}
|
|
594
591
|
function watch(on, cb) {
|
|
595
592
|
if (!on.hasOwnProperty("is"))
|
package/lib/index.js
CHANGED
|
@@ -201,18 +201,18 @@ function awaitUpdate(source, select, timeout) {
|
|
|
201
201
|
const Oops$6 = issues({
|
|
202
202
|
NotFound: (name) => `Could not find ${name} in context.`
|
|
203
203
|
});
|
|
204
|
-
function get$1(
|
|
204
|
+
function get$1(argument) {
|
|
205
205
|
return Control.get((dispatch, context) => {
|
|
206
206
|
const refresh = () => dispatch(x => x + 1);
|
|
207
207
|
let onUpdate;
|
|
208
208
|
let value;
|
|
209
|
-
if (typeof
|
|
209
|
+
if (typeof argument !== "function") {
|
|
210
210
|
const got = context.get(this);
|
|
211
211
|
if (got)
|
|
212
|
-
value =
|
|
212
|
+
value = argument === undefined
|
|
213
213
|
? Control.watch(got, k => k ? onUpdate : undefined)
|
|
214
214
|
: got;
|
|
215
|
-
else if (
|
|
215
|
+
else if (argument !== false)
|
|
216
216
|
throw Oops$6.NotFound(this);
|
|
217
217
|
return {
|
|
218
218
|
mount() {
|
|
@@ -222,7 +222,7 @@ function get$1(arg1, arg2) {
|
|
|
222
222
|
render: () => value
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
|
-
let compute =
|
|
225
|
+
let compute = argument;
|
|
226
226
|
let suspense;
|
|
227
227
|
let getValue;
|
|
228
228
|
let factory;
|
|
@@ -272,7 +272,7 @@ function get$1(arg1, arg2) {
|
|
|
272
272
|
else
|
|
273
273
|
onUpdate = () => {
|
|
274
274
|
const next = getValue();
|
|
275
|
-
if (
|
|
275
|
+
if (value !== next)
|
|
276
276
|
didUpdate(next);
|
|
277
277
|
};
|
|
278
278
|
return {
|
|
@@ -282,30 +282,25 @@ function get$1(arg1, arg2) {
|
|
|
282
282
|
render: () => {
|
|
283
283
|
if (value !== undefined)
|
|
284
284
|
return value;
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
285
|
+
if (onUpdate)
|
|
286
|
+
return null;
|
|
287
|
+
throw new Promise(res => {
|
|
288
|
+
suspense = res;
|
|
289
|
+
});
|
|
290
290
|
}
|
|
291
291
|
};
|
|
292
292
|
});
|
|
293
|
-
}
|
|
294
|
-
/** Values are not equal for purposes of a refresh. */
|
|
295
|
-
const notEqual = (a, b) => (b !== a && (!Array.isArray(a) ||
|
|
296
|
-
!Array.isArray(b) ||
|
|
297
|
-
a.length !== b.length ||
|
|
298
|
-
a.some((x, i) => x !== b[i])));
|
|
293
|
+
}
|
|
299
294
|
|
|
300
|
-
function use$1(
|
|
295
|
+
function use$1(apply, repeat) {
|
|
301
296
|
const render = Control.use(dispatch => {
|
|
302
297
|
const instance = this.new();
|
|
303
298
|
const local = Control.watch(instance, () => onUpdate);
|
|
304
299
|
const refresh = () => dispatch(x => x + 1);
|
|
305
300
|
let onUpdate;
|
|
306
|
-
let
|
|
301
|
+
let shouldApply = !!apply;
|
|
307
302
|
return {
|
|
308
|
-
|
|
303
|
+
instance,
|
|
309
304
|
mount() {
|
|
310
305
|
onUpdate = refresh;
|
|
311
306
|
return () => {
|
|
@@ -314,7 +309,7 @@ function use$1(arg1, arg2) {
|
|
|
314
309
|
};
|
|
315
310
|
},
|
|
316
311
|
render(props) {
|
|
317
|
-
if (
|
|
312
|
+
if (shouldApply) {
|
|
318
313
|
onUpdate = undefined;
|
|
319
314
|
if (typeof props == "function")
|
|
320
315
|
props(instance);
|
|
@@ -322,15 +317,15 @@ function use$1(arg1, arg2) {
|
|
|
322
317
|
for (const key in instance)
|
|
323
318
|
if (props.hasOwnProperty(key))
|
|
324
319
|
instance[key] = props[key];
|
|
325
|
-
if (!
|
|
326
|
-
|
|
320
|
+
if (!repeat)
|
|
321
|
+
shouldApply = false;
|
|
327
322
|
instance.on(0).then(() => onUpdate = refresh);
|
|
328
323
|
}
|
|
329
324
|
return local;
|
|
330
325
|
}
|
|
331
326
|
};
|
|
332
327
|
});
|
|
333
|
-
return render(
|
|
328
|
+
return render(apply);
|
|
334
329
|
}
|
|
335
330
|
|
|
336
331
|
class Model {
|
|
@@ -431,17 +426,20 @@ const Oops$5 = issues({
|
|
|
431
426
|
BadAssignment: (parent, expected, got) => `${parent} expected Model of type ${expected} but got ${got}.`,
|
|
432
427
|
});
|
|
433
428
|
const INSTRUCTION = new Map();
|
|
429
|
+
const PENDING$1 = new WeakMap();
|
|
434
430
|
const REGISTER = new WeakMap();
|
|
435
431
|
const OBSERVER = new WeakMap();
|
|
436
432
|
const PARENTS = new WeakMap();
|
|
437
433
|
class Control {
|
|
438
|
-
constructor(subject, id
|
|
439
|
-
this.
|
|
440
|
-
this.id = id;
|
|
434
|
+
constructor(subject, id) {
|
|
435
|
+
this.state = {};
|
|
441
436
|
this.frame = new Set();
|
|
442
437
|
this.followers = new Set();
|
|
443
438
|
this.observers = new Map([["", this.followers]]);
|
|
439
|
+
this.id = typeof id == "undefined" ? uid() : id;
|
|
440
|
+
this.subject = subject;
|
|
444
441
|
REGISTER.set(subject, this);
|
|
442
|
+
PENDING$1.set(this, new Set(Control.ready));
|
|
445
443
|
}
|
|
446
444
|
add(key) {
|
|
447
445
|
const { value } = getOwnPropertyDescriptor(this.subject, key);
|
|
@@ -533,31 +531,30 @@ class Control {
|
|
|
533
531
|
this.observers.clear();
|
|
534
532
|
}
|
|
535
533
|
}
|
|
534
|
+
Control.ready = new Set();
|
|
536
535
|
Control.after = new Set();
|
|
537
536
|
Control.before = new Set();
|
|
538
537
|
Control.pending = new Set();
|
|
539
538
|
Control.for = control;
|
|
540
539
|
Control.apply = apply;
|
|
541
540
|
Control.watch = watch;
|
|
542
|
-
const PENDING_INIT = new WeakMap();
|
|
543
541
|
function control(subject, ready) {
|
|
544
542
|
const control = REGISTER.get(subject.is);
|
|
545
|
-
const
|
|
546
|
-
if (
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
control.state = {};
|
|
543
|
+
const pending = PENDING$1.get(control);
|
|
544
|
+
if (typeof ready == "function") {
|
|
545
|
+
if (!pending)
|
|
546
|
+
return ready(control);
|
|
547
|
+
let done;
|
|
548
|
+
pending.add(() => done = ready(control));
|
|
549
|
+
return () => done && done();
|
|
550
|
+
}
|
|
551
|
+
if (pending && ready) {
|
|
552
|
+
PENDING$1.delete(control);
|
|
556
553
|
for (const key in control.subject)
|
|
557
554
|
control.add(key);
|
|
558
|
-
|
|
555
|
+
pending.forEach(cb => cb(control));
|
|
559
556
|
}
|
|
560
|
-
return
|
|
557
|
+
return control;
|
|
561
558
|
}
|
|
562
559
|
function requestUpdateFrame(event) {
|
|
563
560
|
const { after, before, pending } = Control;
|
|
@@ -590,10 +587,10 @@ function setRecursive(on, key, value) {
|
|
|
590
587
|
on.watch(key, { set });
|
|
591
588
|
set(value);
|
|
592
589
|
}
|
|
593
|
-
function parent(child,
|
|
594
|
-
if (!
|
|
590
|
+
function parent(child, assign) {
|
|
591
|
+
if (!assign)
|
|
595
592
|
return PARENTS.get(child);
|
|
596
|
-
PARENTS.set(child,
|
|
593
|
+
PARENTS.set(child, assign);
|
|
597
594
|
}
|
|
598
595
|
function watch(on, cb) {
|
|
599
596
|
if (!on.hasOwnProperty("is"))
|
package/package.json
CHANGED