@expressive/mvc 0.13.1 → 0.15.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 CHANGED
@@ -61,7 +61,10 @@ declare namespace Model {
61
61
  export { Subscriber };
62
62
  /** Including but not limited to T. */
63
63
  type Extends<T> = T | (string & Record<never, never>);
64
- export type Type<T extends Model = Model> = typeof Model & (new () => T);
64
+ /** Any typeof Model, using class constructor as the reference. */
65
+ export type Type<T extends Model = Model> = (new (...args: any[]) => T);
66
+ /** A typeof Model, specifically one which may be created without arguments. */
67
+ export type Constructor<T extends Model = Model> = (new () => T) & typeof Model;
65
68
  export type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
66
69
  /** Exotic value, actual value is contained. */
67
70
  export type Ref<T = any> = {
@@ -105,7 +108,7 @@ declare namespace Model {
105
108
  export type Get<T, K extends Key<T> = Key<T>> = {
106
109
  [P in K]: Value<T[P]>;
107
110
  };
108
- export type Export<T, E extends Model = Model> = {
111
+ export type Export<T> = {
109
112
  [P in Key<T>]: Value<T[P]>;
110
113
  };
111
114
  }
@@ -386,7 +389,7 @@ declare function use<T extends Model>(from: () => T, required: boolean): T;
386
389
  /**
387
390
  * Create a new child instance of model.
388
391
  */
389
- declare function use<T extends Model>(Type: Model.Type<T>, callback?: (i: T) => void): T;
392
+ declare function use<T extends Model>(Type: Model.Constructor<T>, callback?: (i: T) => void): T;
390
393
  /**
391
394
  * Create a managed child from factory function.
392
395
  */
@@ -417,6 +420,22 @@ declare function has<T extends Model>(Type: Model.Type<T>, required?: true): T;
417
420
 
418
421
  declare namespace MVC {
419
422
  type EffectCallback<T = MVC> = (found: T) => Callback | void;
423
+ type ForceUpdate = {
424
+ /** Force an update in current component. */
425
+ (): void;
426
+ /**
427
+ * Force an update and again after promise either resolves or rejects.
428
+ * Will return a duplicate of given Promise, which resolves after refresh.
429
+ */
430
+ <T = void>(passthru?: Promise<T>): Promise<T>;
431
+ /**
432
+ * Force a update while calling async function.
433
+ * A refresh will occur both before and after given function.
434
+ * Any actions performed before first `await` will occur before refresh!
435
+ */
436
+ <T = void>(invoke?: () => Promise<T>): Promise<T>;
437
+ };
438
+ type TapCallback<T extends Model, R> = (this: T, model: T, update: MVC.ForceUpdate) => R;
420
439
  }
421
440
  declare class MVC extends Model {
422
441
  end(force?: boolean): boolean | void;
@@ -457,11 +476,11 @@ declare class MVC extends Model {
457
476
  static tap<T extends MVC>(this: Model.Type<T>): T;
458
477
  static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect: true): Exclude<T[K], undefined>;
459
478
  static tap<T extends MVC, K extends Model.Key<T>>(this: Model.Type<T>, key: K, expect?: boolean): NoVoid<T[K]>;
460
- static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => () => R): NoVoid<R>;
461
- static tap<T extends MVC, R>(this: Model.Type<T>, connect: (this: T, model: T) => (() => R) | null): NoVoid<R> | null;
462
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
463
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): NoVoid<R> | null;
464
- static tap<T extends MVC, R>(this: Model.Type<T>, compute: (this: T, model: T) => R, expect?: boolean): NoVoid<R>;
479
+ static tap<T extends MVC, R>(this: Model.Type<T>, connect: MVC.TapCallback<T, () => R>): NoVoid<R>;
480
+ static tap<T extends MVC, R>(this: Model.Type<T>, connect: MVC.TapCallback<T, (() => R) | null>): NoVoid<R> | null;
481
+ static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
482
+ static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
483
+ static tap<T extends MVC, R>(this: Model.Type<T>, compute: MVC.TapCallback<T, R>, expect?: boolean): NoVoid<R>;
465
484
  static use<I extends MVC>(this: Model.Type<I>, watch: Model.Key<I>[], callback?: (instance: I) => void): I;
466
485
  static use<I extends MVC>(this: Model.Type<I>, callback?: (instance: I) => void): I;
467
486
  static use<I extends MVC>(this: Model.Type<I>, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
@@ -477,21 +496,22 @@ declare class MVC extends Model {
477
496
  declare function useContext<T extends Model>(Type: Model.Type<T>, required: false): T | undefined;
478
497
  declare function useContext<T extends Model>(Type: Model.Type<T>, required?: boolean): T;
479
498
 
480
- declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), callback?: (instance: T) => void): T;
481
- declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), watch: Model.Key<T>[], callback?: (instance: T) => void): T;
482
- declare function useNew<T extends Model>(source: Model.Type<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
499
+ declare function useNew<T extends Model>(source: Model.Constructor<T> | (() => T), callback?: (instance: T) => void): T;
500
+ declare function useNew<T extends Model>(source: Model.Constructor<T> | (() => T), watch: Model.Key<T>[], callback?: (instance: T) => void): T;
501
+ declare function useNew<T extends Model>(source: Model.Constructor<T> | (() => T), apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
483
502
 
484
503
  declare namespace useTap {
485
504
  type Source<T extends Model> = T | Model.Type<T> | (() => T | Model.Type<T>);
505
+ type Callback<T extends Model, R> = (this: T, model: T, update: MVC.ForceUpdate) => R;
486
506
  }
487
507
  declare function useTap<T extends Model>(source: useTap.Source<T>): T;
488
508
  declare function useTap<T extends Model, K extends Model.Key<T>>(source: useTap.Source<T>, path: K, expect: true): Exclude<T[K], undefined>;
489
509
  declare function useTap<T extends Model, K extends Model.Key<T>>(source: useTap.Source<T>, path: K, expect?: boolean): NoVoid<T[K]>;
490
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => () => R): NoVoid<R>;
491
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: (this: T, model: T) => (() => R) | null): NoVoid<R> | null;
492
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R> | R, expect: true): Exclude<R, undefined>;
493
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => Promise<R>, expect?: boolean): NoVoid<R> | null;
494
- declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: (this: T, model: T) => R, expect?: boolean): NoVoid<R>;
510
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: useTap.Callback<T, () => R>): NoVoid<R>;
511
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, connect: useTap.Callback<T, (() => R) | null>): NoVoid<R> | null;
512
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: useTap.Callback<T, Promise<R> | R>, expect: true): Exclude<R, undefined>;
513
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: useTap.Callback<T, Promise<R>>, expect?: boolean): NoVoid<R> | null;
514
+ declare function useTap<T extends Model, R>(source: useTap.Source<T>, compute: useTap.Callback<T, R>, expect?: boolean): NoVoid<R>;
495
515
 
496
516
  declare namespace Consumer {
497
517
  type HasProps<E extends Class> = {
@@ -531,7 +551,7 @@ declare namespace Consumer {
531
551
  declare function Consumer<T extends Class>(props: Consumer.Props<T>): any;
532
552
 
533
553
  declare namespace Provider {
534
- type Item = Model | Model.Type;
554
+ type Item = Model | Model.Constructor;
535
555
  type Multiple<T extends Item = Item> = T[] | {
536
556
  [key: string]: T;
537
557
  };
@@ -540,13 +560,13 @@ declare namespace Provider {
540
560
  for: E;
541
561
  fallback?: React.ReactNode;
542
562
  children?: React.ReactNode | ((instance: I) => React.ReactNode);
543
- and?: Model.Compat<I>;
563
+ use?: Model.Compat<I>;
544
564
  };
545
565
  type MultipleProps<T extends Item> = {
546
566
  for: Multiple<T>;
547
567
  fallback?: React.ReactNode;
548
568
  children?: React.ReactNode;
549
- and?: Model.Compat<Instance<T>>;
569
+ use?: Model.Compat<Instance<T>>;
550
570
  };
551
571
  type Props<T extends Item> = MultipleProps<T> | NormalProps<T>;
552
572
  }
package/lib/index.esm.js CHANGED
@@ -1354,10 +1354,18 @@ function useCompute(source, compute, suspend) {
1354
1354
  const local = use(refresh => {
1355
1355
  const sub = control(source).subscribe(() => update);
1356
1356
  const spy = sub.proxy;
1357
- let value = compute.call(spy, spy);
1358
- let update;
1359
- let retry;
1360
- const set = (next) => {
1357
+ let make = () => compute.call(spy, spy, forceUpdate);
1358
+ function forceUpdate(passthru) {
1359
+ if (typeof passthru == "function")
1360
+ passthru = passthru();
1361
+ if (make)
1362
+ reassign(make());
1363
+ else
1364
+ refresh();
1365
+ if (passthru)
1366
+ return passthru.finally(refresh);
1367
+ }
1368
+ function reassign(next) {
1361
1369
  value = next;
1362
1370
  if (retry) {
1363
1371
  retry();
@@ -1365,13 +1373,14 @@ function useCompute(source, compute, suspend) {
1365
1373
  }
1366
1374
  else
1367
1375
  refresh();
1368
- };
1376
+ }
1377
+ let retry;
1378
+ let update;
1379
+ let value = make();
1369
1380
  if (value === null) {
1370
1381
  sub.watch.clear();
1371
- return {
1372
- proxy: null,
1373
- release: () => { }
1374
- };
1382
+ make = undefined;
1383
+ return;
1375
1384
  }
1376
1385
  if (typeof value == "function") {
1377
1386
  const get = value;
@@ -1380,15 +1389,15 @@ function useCompute(source, compute, suspend) {
1380
1389
  value = get();
1381
1390
  }
1382
1391
  if (value instanceof Promise) {
1383
- value.then(set);
1392
+ value.then(reassign);
1384
1393
  value = undefined;
1385
1394
  }
1386
1395
  else {
1387
1396
  sub.commit();
1388
1397
  update = () => {
1389
- const next = compute.call(spy, spy);
1398
+ const next = make();
1390
1399
  if (value != next)
1391
- set(next);
1400
+ reassign(next);
1392
1401
  };
1393
1402
  }
1394
1403
  defineProperty(sub, "proxy", {
@@ -1402,6 +1411,8 @@ function useCompute(source, compute, suspend) {
1402
1411
  });
1403
1412
  return sub;
1404
1413
  }, deps);
1414
+ if (!local)
1415
+ return null;
1405
1416
  React.useLayoutEffect(() => local.release, deps);
1406
1417
  return local.proxy;
1407
1418
  }
@@ -1517,7 +1528,7 @@ const Oops = issues({
1517
1528
  NoType: () => "Provider 'for' prop must be Model, typeof Model or a collection of them."
1518
1529
  });
1519
1530
  function Provider(props) {
1520
- const context = useNewContext(props.for, props.and);
1531
+ const context = useNewContext(props.for, props.use);
1521
1532
  return (React.createElement(LookupContext.Provider, { value: context }, props.fallback === false
1522
1533
  ? props.children
1523
1534
  : (React.createElement(Suspense, { fallback: props.fallback || null }, props.children))));
package/lib/index.js CHANGED
@@ -1362,10 +1362,18 @@ function useCompute(source, compute, suspend) {
1362
1362
  const local = use(refresh => {
1363
1363
  const sub = control(source).subscribe(() => update);
1364
1364
  const spy = sub.proxy;
1365
- let value = compute.call(spy, spy);
1366
- let update;
1367
- let retry;
1368
- const set = (next) => {
1365
+ let make = () => compute.call(spy, spy, forceUpdate);
1366
+ function forceUpdate(passthru) {
1367
+ if (typeof passthru == "function")
1368
+ passthru = passthru();
1369
+ if (make)
1370
+ reassign(make());
1371
+ else
1372
+ refresh();
1373
+ if (passthru)
1374
+ return passthru.finally(refresh);
1375
+ }
1376
+ function reassign(next) {
1369
1377
  value = next;
1370
1378
  if (retry) {
1371
1379
  retry();
@@ -1373,13 +1381,14 @@ function useCompute(source, compute, suspend) {
1373
1381
  }
1374
1382
  else
1375
1383
  refresh();
1376
- };
1384
+ }
1385
+ let retry;
1386
+ let update;
1387
+ let value = make();
1377
1388
  if (value === null) {
1378
1389
  sub.watch.clear();
1379
- return {
1380
- proxy: null,
1381
- release: () => { }
1382
- };
1390
+ make = undefined;
1391
+ return;
1383
1392
  }
1384
1393
  if (typeof value == "function") {
1385
1394
  const get = value;
@@ -1388,15 +1397,15 @@ function useCompute(source, compute, suspend) {
1388
1397
  value = get();
1389
1398
  }
1390
1399
  if (value instanceof Promise) {
1391
- value.then(set);
1400
+ value.then(reassign);
1392
1401
  value = undefined;
1393
1402
  }
1394
1403
  else {
1395
1404
  sub.commit();
1396
1405
  update = () => {
1397
- const next = compute.call(spy, spy);
1406
+ const next = make();
1398
1407
  if (value != next)
1399
- set(next);
1408
+ reassign(next);
1400
1409
  };
1401
1410
  }
1402
1411
  defineProperty(sub, "proxy", {
@@ -1410,6 +1419,8 @@ function useCompute(source, compute, suspend) {
1410
1419
  });
1411
1420
  return sub;
1412
1421
  }, deps);
1422
+ if (!local)
1423
+ return null;
1413
1424
  React__default["default"].useLayoutEffect(() => local.release, deps);
1414
1425
  return local.proxy;
1415
1426
  }
@@ -1525,7 +1536,7 @@ const Oops = issues({
1525
1536
  NoType: () => "Provider 'for' prop must be Model, typeof Model or a collection of them."
1526
1537
  });
1527
1538
  function Provider(props) {
1528
- const context = useNewContext(props.for, props.and);
1539
+ const context = useNewContext(props.for, props.use);
1529
1540
  return (React__default["default"].createElement(LookupContext.Provider, { value: context }, props.fallback === false
1530
1541
  ? props.children
1531
1542
  : (React__default["default"].createElement(React.Suspense, { fallback: props.fallback || null }, props.children))));
package/package.json CHANGED
@@ -49,5 +49,5 @@
49
49
  "tslib": "^2.3.0",
50
50
  "typescript": "4.6.3"
51
51
  },
52
- "version": "0.13.1"
52
+ "version": "0.15.0"
53
53
  }