@expressive/mvc 1.0.0-beta.37 → 1.0.0-beta.38

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
@@ -35,7 +35,7 @@ declare class Subscriber<T extends Stateful = any> {
35
35
  active: boolean;
36
36
  dependant: Set<Listener>;
37
37
  watch: { [key in Model.Event<T, Model>]: true | Callback; };
38
- constructor(parent: Controller<T> | T, onUpdate: Controller.OnEvent);
38
+ constructor(target: Controller<T> | T, onUpdate: Controller.OnEvent);
39
39
  }
40
40
 
41
41
  declare const CONTROL: unique symbol;
@@ -205,13 +205,14 @@ type Instruction<T> = (this: Controller, key: string, thisArg: Controller) =>
205
205
  | Instruction.ExplicitDescriptor
206
206
  | Instruction.Descriptor<T>
207
207
  | Instruction.RecursiveDescriptor<T>
208
+ | boolean
208
209
  | void;
209
210
 
210
211
  declare namespace Instruction {
211
212
  type Getter<T> = (state: T, within?: Subscriber) => T;
212
213
  type Setter<T> = (value: T, state: any) => boolean | void;
213
214
 
214
- type Runner<T> = (this: Controller, key: string, on: Controller) => Instruction.Descriptor<T> | undefined;
215
+ type Runner<T> = (this: Controller, key: string, on: Controller) => Instruction.Descriptor<T> | boolean | undefined;
215
216
 
216
217
  interface Descriptor<T> {
217
218
  configurable?: boolean;
@@ -444,8 +445,8 @@ declare class MVC extends Model {
444
445
  static new<T extends Class>(this: T, callback?: (instance: InstanceOf<T>) => void): InstanceOf<T>;
445
446
  static use<T extends Class, I extends InstanceOf<T>>(this: T, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
446
447
  static use<T extends Class, I extends InstanceOf<T>>(this: T, callback?: (instance: I) => void): I;
447
- static uses<T extends typeof MVC, I extends InstanceOf<T>, D extends Partial<I>>(this: T, data: D, only?: (keyof D)[]): InstanceOf<T>;
448
- static using<T extends typeof MVC, I extends InstanceOf<T>, D extends Partial<I>>(this: T, data: D, only?: (keyof D)[]): InstanceOf<T>;
448
+ static uses<T extends typeof MVC, I extends InstanceOf<T>, D extends Partial<I>>(this: T, data: D, only?: (keyof D & string)[]): InstanceOf<T>;
449
+ static using<T extends typeof MVC, I extends InstanceOf<T>, D extends Partial<I>>(this: T, data: D, only?: (keyof D & string)[]): InstanceOf<T>;
449
450
  static meta<T extends Class>(this: T): T;
450
451
  static meta<T extends Class, K extends keyof T>(this: T, key: K, expect: true): Exclude<T[K], undefined>;
451
452
  static meta<T extends Class, K extends keyof T>(this: T, key: K, expect?: boolean): T[K];
@@ -561,10 +562,12 @@ declare function useFrom<T extends Stateful, R>(source: (() => T) | T, compute:
561
562
 
562
563
  declare function useInContext<T extends typeof Model>(Type: T, arg?: boolean | string): any;
563
564
 
564
- declare function useModel<T extends Stateful>(source: (() => T) | T, watch?: Model.Field<T>[], callback?: (instance: T) => void): T;
565
- declare function useModel<T extends Stateful>(source: (() => T) | T, callback?: (instance: T) => void): T;
566
565
  declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
567
566
  declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, callback?: (instance: I) => void): I;
567
+ declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
568
+ declare function useModel<T extends Stateful>(source: (() => T) | T, watch?: Model.Field<T>[], callback?: (instance: T) => void): T;
569
+ declare function useModel<T extends Stateful>(source: (() => T) | T, callback?: (instance: T) => void): T;
570
+ declare function useModel<T extends Stateful>(source: (() => T) | T, apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
568
571
 
569
572
  declare namespace useTap {
570
573
  interface Tappable {
package/lib/index.esm.js CHANGED
@@ -113,13 +113,15 @@ class Controller {
113
113
  Pending.delete(entry);
114
114
  delete subject[key];
115
115
  const desc = instruction.call(this, key, this);
116
- if (!desc)
116
+ if (desc === false)
117
117
  return;
118
- if ("value" in desc)
119
- state[key] = desc.value;
120
- onSet = desc.set;
121
- onGet = desc.get;
122
- enumerable = desc.enumerable;
118
+ if (typeof desc == "object") {
119
+ if ("value" in desc)
120
+ state[key] = desc.value;
121
+ onSet = desc.set;
122
+ onGet = desc.get;
123
+ enumerable = desc.enumerable;
124
+ }
123
125
  }
124
126
  else
125
127
  state[key] = entry;
@@ -244,16 +246,15 @@ function control(subject, cb) {
244
246
  }
245
247
 
246
248
  class Subscriber {
247
- constructor(parent, onUpdate) {
249
+ constructor(target, onUpdate) {
248
250
  this.onUpdate = onUpdate;
249
251
  this.active = false;
250
252
  this.dependant = new Set();
251
253
  this.watch = {};
252
- if (!(parent instanceof Controller))
253
- parent = control(parent);
254
- let reset;
254
+ const parent = target instanceof Controller
255
+ ? target : control(target);
255
256
  const proxy = create(parent.proxy);
256
- const controller = parent;
257
+ let reset;
257
258
  define(proxy, LOCAL, this);
258
259
  defineProperty(this, "proxy", {
259
260
  configurable: true,
@@ -263,29 +264,29 @@ class Subscriber {
263
264
  return proxy;
264
265
  }
265
266
  });
266
- const onEvent = (key) => {
267
+ const release = parent.addListener(key => {
267
268
  const handler = this.watch[key];
268
- if (!handler)
269
+ if (!handler || !this.active)
269
270
  return;
270
271
  if (typeof handler == "function")
271
272
  handler();
272
- const notify = this.onUpdate(key, controller);
273
+ const notify = this.onUpdate(key, parent);
273
274
  const getWhy = (keys) => {
274
275
  reset = applyUpdate(proxy, keys.filter(k => k in this.watch));
275
276
  };
276
277
  if (notify) {
277
- controller.requestUpdate(getWhy);
278
- controller.requestUpdate(notify);
278
+ parent.requestUpdate(getWhy);
279
+ parent.requestUpdate(notify);
279
280
  }
280
- };
281
+ });
281
282
  this.commit = () => {
282
- const release = controller.addListener(onEvent);
283
283
  this.active = true;
284
284
  this.dependant.forEach(x => x.commit());
285
- return this.release = () => {
286
- this.dependant.forEach(x => x.release());
287
- release();
288
- };
285
+ return this.release;
286
+ };
287
+ this.release = () => {
288
+ this.dependant.forEach(x => x.release());
289
+ release();
289
290
  };
290
291
  }
291
292
  }
@@ -376,9 +377,8 @@ function prepare(parent, key, source, setter, getter) {
376
377
  configurable: true,
377
378
  enumerable: true
378
379
  });
379
- return getter
380
- ? () => getter(parent, key)
381
- : {};
380
+ if (getter)
381
+ return () => getter(parent, key);
382
382
  }
383
383
  function ensure(on, keys) {
384
384
  for (const key of keys) {
@@ -552,18 +552,17 @@ function apply(fn, label) {
552
552
  const placeholder = Symbol(`${name} instruction`);
553
553
  function setup(key) {
554
554
  let output = fn.call(this, key, this);
555
- if (!output)
556
- return;
557
- if ("explicit" in output) {
555
+ if (typeof output == "function")
556
+ return { get: output };
557
+ if (typeof output !== "object")
558
+ return output || undefined;
559
+ if ("explicit" in output && output.explicit) {
558
560
  defineProperty(this.subject, key, output);
559
- return;
561
+ return false;
560
562
  }
561
563
  if ("recursive" in output)
562
564
  output = Object.assign(Object.assign({}, output), { get: recursive(this, key) });
563
- if (typeof output == "function")
564
- return { get: output };
565
- else
566
- return output;
565
+ return output;
567
566
  }
568
567
  Pending.set(placeholder, setup);
569
568
  return placeholder;
@@ -983,9 +982,9 @@ function use(init) {
983
982
  return state[0];
984
983
  }
985
984
 
986
- function useModel(source, arg, callback) {
985
+ function useModel(source, arg, arg2) {
987
986
  const instance = React.useMemo(() => {
988
- const cb = callback || arg;
987
+ const cb = arg2 || arg;
989
988
  const instance = typeof source == "function" ?
990
989
  source.prototype instanceof Model ?
991
990
  new source() :
@@ -1009,9 +1008,18 @@ function useModel(source, arg, callback) {
1009
1008
  return instance;
1010
1009
  }
1011
1010
  else {
1012
- const local = use(refresh => {
1013
- return new Subscriber(instance, () => refresh);
1014
- });
1011
+ const local = use(refresh => (new Subscriber(instance, () => refresh)));
1012
+ if (typeof arg == "object") {
1013
+ local.active = false;
1014
+ if (typeof arg2 !== "object")
1015
+ arg2 = getOwnPropertyNames(instance);
1016
+ for (const key of arg2)
1017
+ if (key in arg)
1018
+ instance[key] = arg[key];
1019
+ React.useLayoutEffect(() => {
1020
+ local.active = true;
1021
+ });
1022
+ }
1015
1023
  React.useLayoutEffect(() => {
1016
1024
  local.commit();
1017
1025
  return () => {
@@ -1094,10 +1102,11 @@ function useTap(source, path, expect) {
1094
1102
  }
1095
1103
  return sub;
1096
1104
  });
1097
- React.useLayoutEffect(() => local.commit(), []);
1105
+ React.useLayoutEffect(local.commit, []);
1098
1106
  return local.proxy;
1099
1107
  }
1100
1108
 
1109
+ /* istanbul ignore file */
1101
1110
  class MVC extends Model {
1102
1111
  tap(path, expect) {
1103
1112
  return useTap(this, path, expect);
@@ -1202,7 +1211,7 @@ function RenderFunction(props) {
1202
1211
  return {};
1203
1212
  });
1204
1213
  if (hook.commit)
1205
- React.useLayoutEffect(() => hook.commit(), []);
1214
+ React.useLayoutEffect(hook.commit, []);
1206
1215
  return props.render(hook.proxy);
1207
1216
  }
1208
1217