@expressive/mvc 0.28.0 → 0.29.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 CHANGED
@@ -58,13 +58,15 @@ declare global {
58
58
  }
59
59
  }
60
60
 
61
+ type OnValue<T, P extends Model.Key<T>> = (this: T, value: T[P], updated: Model.Event<T>[]) => void;
62
+ type OnValues<T, P extends Model.Key<T>> = (this: T, value: Model.Export<T, P>, updated: Model.Event<T>[]) => void;
61
63
  interface Observable {
62
64
  get(): Model.Export<this>;
63
65
  get(effect: Model.Effect<this>): Callback;
64
66
  get<P extends Model.Key<this>>(select: P): this[P];
65
- get<P extends Model.Key<this>>(select: Iterable<P>): Model.Export<this, P>;
66
- get<P extends Model.Key<this>>(select: P, onUpdate: (this: this, value: this[P], updated: Model.Event<this>[]) => void, once?: boolean): Callback;
67
- get<P extends Model.Key<this>>(select: Iterable<P>, onUpdate: (this: this, value: Model.Export<this, P>, updated: Model.Event<this>[]) => void, once?: boolean): Callback;
67
+ get<P extends Model.Key<this>>(select: P, onUpdate: OnValue<this, P>, once?: boolean): Callback;
68
+ get<P extends Model.Key<this>>(select: P[]): Model.Export<this, P>;
69
+ get<P extends Model.Key<this>>(select: P[], onUpdate: OnValues<this, P>, once?: boolean): Callback;
68
70
  set(): Promise<Model.Event<this>[]>;
69
71
  set(timeout: number): Promise<Model.Event<this>[] | false>;
70
72
  set<T extends Model.Values<this>>(source: T, only?: (keyof T)[]): Promise<Model.Event<T>[] | false>;
@@ -93,7 +95,7 @@ declare namespace Model {
93
95
  /** Including but not limited to `keyof T` which are not methods or defined by base Model. */
94
96
  type Event<T> = Key<T> | (string & {});
95
97
  /** Actual value stored in state. */
96
- type Value<R> = R extends Ref<infer T> ? T : R;
98
+ type Value<R> = R extends Ref<infer T> ? T : R extends Observable ? Export<R> : R;
97
99
  /** Object comperable to data found in T. */
98
100
  type Values<T> = {
99
101
  [P in Key<T>]?: Value<T[P]>;
@@ -137,7 +139,7 @@ declare class Model {
137
139
  *
138
140
  * Will determine if provided class is a subtype of this one.
139
141
  */
140
- static isTypeof<T extends Model.Type>(this: T, maybe: any): maybe is T;
142
+ static is<T extends Model.Type>(this: T, maybe: any): maybe is T;
141
143
  }
142
144
 
143
145
  declare namespace get {
@@ -174,9 +176,9 @@ declare function get<R, T>(compute: (property: string, on: T) => (this: T, state
174
176
  declare function get<R, T>(compute: (property: string, on: T) => (this: T, state: T) => R): R;
175
177
 
176
178
  declare namespace ref {
177
- type Callback<T> = (argument: T) => ((next: T) => void) | Promise<void> | void | boolean;
179
+ type Callback<T> = (argument: T) => ((next: T | null) => void) | Promise<void> | void | boolean;
178
180
  interface Object<T = any> {
179
- (next: T): void;
181
+ (next: T | null): void;
180
182
  current: T | null;
181
183
  }
182
184
  /** Object with references to all managed values of `T`. */
@@ -214,6 +216,16 @@ declare function ref<O extends Model, R>(target: O, mapper: (key: Model.Key<O>)
214
216
  * @param callback - Optional callback to synchronously fire when reference is first set or does update.
215
217
  */
216
218
  declare function ref<T = HTMLElement>(callback?: ref.Callback<T>): ref.Object<T>;
219
+ /**
220
+ * Creates a ref-compatible property.
221
+ * Will persist value, and updates to this are made part of controller event-stream.
222
+ *
223
+ * *Output is simultaneously a ref-function and ref-object, use as needed.*
224
+ *
225
+ * @param callback - Optional callback to synchronously fire when reference is first set or does update.
226
+ * @param ignoreNull - Default `true`. If `false`, will still callback with `null`.
227
+ */
228
+ declare function ref<T = HTMLElement>(callback: ref.Callback<T | null>, ignoreNull: boolean): ref.Object<T>;
217
229
 
218
230
  declare namespace set {
219
231
  type Callback<T, S = any> = (this: S, argument: T) => ((next: T) => void) | Promise<any> | void | boolean;
package/lib/index.esm.js CHANGED
@@ -40,7 +40,7 @@ function issues(register) {
40
40
  return Library;
41
41
  }
42
42
 
43
- const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
43
+ const { assign, create, defineProperties, defineProperty, entries, keys, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
44
44
 
45
45
  const Oops$7 = issues({
46
46
  NotFound: (name) => `Could not find ${name} in context.`
@@ -259,7 +259,7 @@ function createValueEffect(callback) {
259
259
  return function (value) {
260
260
  if (typeof unSet == "function")
261
261
  unSet(value);
262
- const out = callback.call(this, value, this);
262
+ const out = callback.call(this, value);
263
263
  if (typeof out == "boolean")
264
264
  return out;
265
265
  if (!out || out instanceof Promise)
@@ -275,18 +275,20 @@ function getMethod(argument, callback, once) {
275
275
  if (typeof argument == "function")
276
276
  return createEffect(this, argument);
277
277
  const self = control(this, true);
278
- function get() {
279
- if (typeof argument == "string")
280
- return self.state[argument];
281
- if (!argument)
282
- return Object.assign({}, self.state);
283
- const output = {};
284
- for (const key of argument)
285
- output[key] = self.state[key];
286
- return output;
278
+ function get(key) {
279
+ const value = self.state[key];
280
+ return value instanceof Model ? value.get() : value;
287
281
  }
282
+ const extract = typeof argument == "string"
283
+ ? () => get(argument)
284
+ : () => {
285
+ const output = {};
286
+ for (const key of argument || keys(self.state))
287
+ output[key] = get(key);
288
+ return output;
289
+ };
288
290
  if (typeof callback != "function")
289
- return get();
291
+ return extract();
290
292
  const select = typeof argument == "string" ? [argument] : argument;
291
293
  if (select)
292
294
  for (const key of select)
@@ -302,7 +304,7 @@ function getMethod(argument, callback, once) {
302
304
  if (!select || select.includes(key)) {
303
305
  if (once)
304
306
  remove();
305
- return () => callback(get(), self.latest);
307
+ return () => callback(extract(), self.latest);
306
308
  }
307
309
  });
308
310
  return remove;
@@ -370,20 +372,38 @@ class Model {
370
372
  *
371
373
  * Will determine if provided class is a subtype of this one.
372
374
  */
373
- static isTypeof(maybe) {
375
+ static is(maybe) {
374
376
  return (typeof maybe == "function" &&
375
377
  maybe.prototype instanceof this);
376
378
  }
377
379
  }
378
380
  Model.get = get$1;
379
381
  Model.use = use$1;
382
+ defineProperty(Model, "toString", {
383
+ value() {
384
+ return this.name;
385
+ }
386
+ });
380
387
  defineProperties(Model.prototype, {
381
388
  get: { value: getMethod },
382
389
  set: { value: setMethod },
390
+ toString: {
391
+ configurable: true,
392
+ value() {
393
+ return `${this.constructor.name}-${control(this).id}`;
394
+ }
395
+ }
396
+ });
397
+ /* TODO: Remove below on 1.0.0 release. */
398
+ defineProperty(Model, "isTypeof", {
399
+ get() {
400
+ throw new Error("Model.isTypeof method was renamed. Use Model.is instead.");
401
+ }
402
+ });
403
+ defineProperties(Model.prototype, {
383
404
  is: {
384
405
  configurable: true,
385
406
  get() {
386
- // TODO: Remove this method on 1.0
387
407
  throw new Error("Model.is property is now is only available from a hook.");
388
408
  }
389
409
  },
@@ -391,20 +411,8 @@ defineProperties(Model.prototype, {
391
411
  configurable: true,
392
412
  writable: true,
393
413
  value() {
394
- // TODO: Remove this method on 1.0
395
414
  throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
396
415
  }
397
- },
398
- toString: {
399
- configurable: true,
400
- value() {
401
- return `${this.constructor.name}-${control(this).id}`;
402
- }
403
- }
404
- });
405
- defineProperty(Model, "toString", {
406
- value() {
407
- return this.name;
408
416
  }
409
417
  });
410
418
 
@@ -649,7 +657,7 @@ function get(arg0, arg1) {
649
657
  let source = cb => cb(subject);
650
658
  if (arg0 instanceof Model)
651
659
  subject = arg0;
652
- else if (Model.isTypeof(arg0)) {
660
+ else if (Model.is(arg0)) {
653
661
  const hasParent = parent(subject);
654
662
  if (!hasParent) {
655
663
  if (arg1 === true)
@@ -770,11 +778,9 @@ Control.before.add(flushComputed);
770
778
  function ref(arg, mapper) {
771
779
  return apply((key, source) => {
772
780
  let value = {};
773
- if (typeof arg != "object")
774
- value = createRef(source, key, arg);
775
- else
781
+ if (typeof arg == "object")
776
782
  for (const key in control(arg, true).state) {
777
- defineProperty(value, key, mapper ? {
783
+ defineProperty(value, key, typeof mapper == "function" ? {
778
784
  configurable: true,
779
785
  get() {
780
786
  const out = mapper(key);
@@ -785,6 +791,10 @@ function ref(arg, mapper) {
785
791
  value: createRef(source, key)
786
792
  });
787
793
  }
794
+ else
795
+ value = createRef(source, key, arg && mapper !== false
796
+ ? (x) => x !== null ? arg(x) : undefined
797
+ : arg);
788
798
  source.state[key] = undefined;
789
799
  source.observers.set(key, new Set());
790
800
  defineProperty(source.subject, key, { value });
package/lib/index.js CHANGED
@@ -44,7 +44,7 @@ function issues(register) {
44
44
  return Library;
45
45
  }
46
46
 
47
- const { assign, create, defineProperties, defineProperty, entries, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
47
+ const { assign, create, defineProperties, defineProperty, entries, keys, getPrototypeOf, getOwnPropertyDescriptor, getOwnPropertySymbols, values } = Object;
48
48
 
49
49
  const Oops$7 = issues({
50
50
  NotFound: (name) => `Could not find ${name} in context.`
@@ -263,7 +263,7 @@ function createValueEffect(callback) {
263
263
  return function (value) {
264
264
  if (typeof unSet == "function")
265
265
  unSet(value);
266
- const out = callback.call(this, value, this);
266
+ const out = callback.call(this, value);
267
267
  if (typeof out == "boolean")
268
268
  return out;
269
269
  if (!out || out instanceof Promise)
@@ -279,18 +279,20 @@ function getMethod(argument, callback, once) {
279
279
  if (typeof argument == "function")
280
280
  return createEffect(this, argument);
281
281
  const self = control(this, true);
282
- function get() {
283
- if (typeof argument == "string")
284
- return self.state[argument];
285
- if (!argument)
286
- return Object.assign({}, self.state);
287
- const output = {};
288
- for (const key of argument)
289
- output[key] = self.state[key];
290
- return output;
282
+ function get(key) {
283
+ const value = self.state[key];
284
+ return value instanceof Model ? value.get() : value;
291
285
  }
286
+ const extract = typeof argument == "string"
287
+ ? () => get(argument)
288
+ : () => {
289
+ const output = {};
290
+ for (const key of argument || keys(self.state))
291
+ output[key] = get(key);
292
+ return output;
293
+ };
292
294
  if (typeof callback != "function")
293
- return get();
295
+ return extract();
294
296
  const select = typeof argument == "string" ? [argument] : argument;
295
297
  if (select)
296
298
  for (const key of select)
@@ -306,7 +308,7 @@ function getMethod(argument, callback, once) {
306
308
  if (!select || select.includes(key)) {
307
309
  if (once)
308
310
  remove();
309
- return () => callback(get(), self.latest);
311
+ return () => callback(extract(), self.latest);
310
312
  }
311
313
  });
312
314
  return remove;
@@ -374,20 +376,38 @@ class Model {
374
376
  *
375
377
  * Will determine if provided class is a subtype of this one.
376
378
  */
377
- static isTypeof(maybe) {
379
+ static is(maybe) {
378
380
  return (typeof maybe == "function" &&
379
381
  maybe.prototype instanceof this);
380
382
  }
381
383
  }
382
384
  Model.get = get$1;
383
385
  Model.use = use$1;
386
+ defineProperty(Model, "toString", {
387
+ value() {
388
+ return this.name;
389
+ }
390
+ });
384
391
  defineProperties(Model.prototype, {
385
392
  get: { value: getMethod },
386
393
  set: { value: setMethod },
394
+ toString: {
395
+ configurable: true,
396
+ value() {
397
+ return `${this.constructor.name}-${control(this).id}`;
398
+ }
399
+ }
400
+ });
401
+ /* TODO: Remove below on 1.0.0 release. */
402
+ defineProperty(Model, "isTypeof", {
403
+ get() {
404
+ throw new Error("Model.isTypeof method was renamed. Use Model.is instead.");
405
+ }
406
+ });
407
+ defineProperties(Model.prototype, {
387
408
  is: {
388
409
  configurable: true,
389
410
  get() {
390
- // TODO: Remove this method on 1.0
391
411
  throw new Error("Model.is property is now is only available from a hook.");
392
412
  }
393
413
  },
@@ -395,20 +415,8 @@ defineProperties(Model.prototype, {
395
415
  configurable: true,
396
416
  writable: true,
397
417
  value() {
398
- // TODO: Remove this method on 1.0
399
418
  throw new Error("Model.on() is deprecated. Use Model.get or Model.set instead.");
400
419
  }
401
- },
402
- toString: {
403
- configurable: true,
404
- value() {
405
- return `${this.constructor.name}-${control(this).id}`;
406
- }
407
- }
408
- });
409
- defineProperty(Model, "toString", {
410
- value() {
411
- return this.name;
412
420
  }
413
421
  });
414
422
 
@@ -653,7 +661,7 @@ function get(arg0, arg1) {
653
661
  let source = cb => cb(subject);
654
662
  if (arg0 instanceof Model)
655
663
  subject = arg0;
656
- else if (Model.isTypeof(arg0)) {
664
+ else if (Model.is(arg0)) {
657
665
  const hasParent = parent(subject);
658
666
  if (!hasParent) {
659
667
  if (arg1 === true)
@@ -774,11 +782,9 @@ Control.before.add(flushComputed);
774
782
  function ref(arg, mapper) {
775
783
  return apply((key, source) => {
776
784
  let value = {};
777
- if (typeof arg != "object")
778
- value = createRef(source, key, arg);
779
- else
785
+ if (typeof arg == "object")
780
786
  for (const key in control(arg, true).state) {
781
- defineProperty(value, key, mapper ? {
787
+ defineProperty(value, key, typeof mapper == "function" ? {
782
788
  configurable: true,
783
789
  get() {
784
790
  const out = mapper(key);
@@ -789,6 +795,10 @@ function ref(arg, mapper) {
789
795
  value: createRef(source, key)
790
796
  });
791
797
  }
798
+ else
799
+ value = createRef(source, key, arg && mapper !== false
800
+ ? (x) => x !== null ? arg(x) : undefined
801
+ : arg);
792
802
  source.state[key] = undefined;
793
803
  source.observers.set(key, new Set());
794
804
  defineProperty(source.subject, key, { value });
package/package.json CHANGED
@@ -26,6 +26,6 @@
26
26
  "prebuild": "rm -rf lib/",
27
27
  "preversion": "npm run test && npm run build"
28
28
  },
29
- "version": "0.28.0",
30
- "gitHead": "76939c2aa0ea5b471ff6fa90e9f4fa65e5e85c3f"
29
+ "version": "0.29.1",
30
+ "gitHead": "bc5ef985433d6f7d198eda375cda9e8a055ca0d0"
31
31
  }