@expressive/mvc 1.0.0-beta.4 → 1.0.0-beta.40
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/README.md +10 -1
- package/lib/index.d.ts +592 -0
- package/lib/index.esm.js +1267 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +1117 -863
- package/lib/index.js.map +1 -0
- package/package.json +20 -20
- package/types/controller.d.ts +0 -56
- package/types/index.d.ts +0 -9
- package/types/instructions.d.ts +0 -106
- package/types/lifecycle.d.ts +0 -30
- package/types/model.d.ts +0 -336
- package/types/react.d.ts +0 -46
- package/types/selector.ts +0 -29
- package/types/types.d.ts +0 -14
package/README.md
CHANGED
|
@@ -24,10 +24,19 @@
|
|
|
24
24
|
</p>
|
|
25
25
|
|
|
26
26
|
<br/>
|
|
27
|
-
<
|
|
27
|
+
<p align="center">
|
|
28
|
+
<b>Have suggestions, need help or just want to discuss?</b><br/><br/>
|
|
29
|
+
<a href="https://join.slack.com/t/expressivejs/shared_invite/zt-s2j5cdhz-gffKn3bTATMbXf~iq4pvHg" alt="Join Slack">
|
|
30
|
+
<img src="https://img.shields.io/badge/Slack-Come%20say%20hi!-blueviolet" />
|
|
31
|
+
</a>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<br/>
|
|
35
|
+
<h1 id="overview-section">Overview</h1>
|
|
28
36
|
|
|
29
37
|
Classes which extend `Model` can manage behavior for components. Custom models are easy to define, use and even provide. While hooks are great, state and logic are not a part of well-formed JSX. Models help wrap that stuff in robust, portable controllers instead.
|
|
30
38
|
|
|
39
|
+
|
|
31
40
|
<br/>
|
|
32
41
|
|
|
33
42
|
## How to use
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
declare type Async<T = any> = (...args: any[]) => Promise<T>;
|
|
4
|
+
/**
|
|
5
|
+
* Sets an exotic method with managed ready-state. Property accepts an async function.
|
|
6
|
+
*
|
|
7
|
+
* When an act-method is invoked, its `active` property to true for duration of call.
|
|
8
|
+
* This is emitted as an update to property, both when called and after returns (or throws).
|
|
9
|
+
*
|
|
10
|
+
* **Note:** Subsequent calls will immediately throw if one is still pending.
|
|
11
|
+
*
|
|
12
|
+
* @param action - Action to fire when resulting property is invoked.
|
|
13
|
+
*/
|
|
14
|
+
declare function act(action: Async): typeof action & {
|
|
15
|
+
active: boolean;
|
|
16
|
+
};
|
|
17
|
+
declare function act<S>(action: Async<S>): typeof action & {
|
|
18
|
+
active: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type Callback = () => void;
|
|
22
|
+
type Class = new (...args: any[]) => any;
|
|
23
|
+
type InstanceOf<T> = T extends { prototype: infer U } ? U : never;
|
|
24
|
+
type RequestCallback<T extends string = string> = (keys: readonly T[]) => void;
|
|
25
|
+
|
|
26
|
+
declare type Listener = {
|
|
27
|
+
commit(): void;
|
|
28
|
+
release(): void;
|
|
29
|
+
};
|
|
30
|
+
declare class Subscriber<T extends Stateful = any> {
|
|
31
|
+
onUpdate: Controller.OnEvent;
|
|
32
|
+
proxy: T;
|
|
33
|
+
release: Callback;
|
|
34
|
+
commit: () => () => void;
|
|
35
|
+
active: boolean;
|
|
36
|
+
dependant: Set<Listener>;
|
|
37
|
+
watch: { [key in Model.Event<T, Model>]: true | Callback; };
|
|
38
|
+
constructor(target: Controller<T> | T, onUpdate: Controller.OnEvent);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare const CONTROL: unique symbol;
|
|
42
|
+
declare const WHY: unique symbol;
|
|
43
|
+
declare const LOCAL: unique symbol;
|
|
44
|
+
declare const STATE: unique symbol;
|
|
45
|
+
interface Stateful {
|
|
46
|
+
/** Controller for this instance. */
|
|
47
|
+
[CONTROL]: Controller;
|
|
48
|
+
/** Current subscriber (if present) while used in a live context (e.g. hook or effect). */
|
|
49
|
+
[LOCAL]?: Subscriber;
|
|
50
|
+
/** Current state of this instance. */
|
|
51
|
+
[STATE]?: this;
|
|
52
|
+
/**
|
|
53
|
+
* Last update causing a refresh to subscribers.
|
|
54
|
+
*
|
|
55
|
+
* If accessed directly, will contain all keys from last push.
|
|
56
|
+
* If within a subscribed function, will contain only keys which explicitly caused a refresh.
|
|
57
|
+
*/
|
|
58
|
+
[WHY]?: readonly Model.Event<this>[];
|
|
59
|
+
}
|
|
60
|
+
declare namespace Model {
|
|
61
|
+
/** Including but not limited to T. */
|
|
62
|
+
type Extends<T> = T | (string & Record<never, never>);
|
|
63
|
+
export { Controller };
|
|
64
|
+
export { Subscriber };
|
|
65
|
+
export type OnUpdate<T, P> = (this: T, value: ValueOf<keyof T, P>, changed: P) => void;
|
|
66
|
+
export type Effect<T> = (this: T, argument: T) => Callback | Promise<any> | void;
|
|
67
|
+
/** Exotic value, actual value is contained. */
|
|
68
|
+
export interface Ref<T = any> {
|
|
69
|
+
(next: T): void;
|
|
70
|
+
current: T | null;
|
|
71
|
+
}
|
|
72
|
+
/** Properties of T, of which are methods. */
|
|
73
|
+
export type Methods<T> = {
|
|
74
|
+
[K in keyof T]: T[K] extends Ref ? never : T[K] extends Function ? K : never;
|
|
75
|
+
}[keyof T];
|
|
76
|
+
/**
|
|
77
|
+
* Subset of `keyof T` which are not methods or defined by base Model U.
|
|
78
|
+
*
|
|
79
|
+
* **Note**: This excludes all keys which are not of type `string` (only those are managed).
|
|
80
|
+
**/
|
|
81
|
+
export type Field<T, U extends Model = Model> = Exclude<keyof T & string, keyof U>;
|
|
82
|
+
/**
|
|
83
|
+
* Including but not limited to `keyof T` which are not methods or defined by base Model.
|
|
84
|
+
**/
|
|
85
|
+
export type Event<T, U extends Model = Model> = Extends<Field<T, U>>;
|
|
86
|
+
/** Object containing managed entries found in T. */
|
|
87
|
+
export type Entries<T, U extends Model = Model> = Pick<T, Field<T, U>>;
|
|
88
|
+
/** Object comperable to data found in T. */
|
|
89
|
+
export type Compat<T, U extends Model = Model> = Partial<Entries<T, U>>;
|
|
90
|
+
/** Actual value stored in state. */
|
|
91
|
+
export type Value<R> = R extends Ref<infer T> ? T : R;
|
|
92
|
+
/** Actual value belonging to a managed property. */
|
|
93
|
+
export type ValueOf<T extends {}, K> = K extends keyof T ? Value<T[K]> : undefined;
|
|
94
|
+
/**
|
|
95
|
+
* Values from current state of given controller.
|
|
96
|
+
*
|
|
97
|
+
* Differs from `Entries` as values here will drill into "real" values held by exotics like ref.
|
|
98
|
+
*/
|
|
99
|
+
export type Values<T, K extends Field<T, Model> = Field<T, Model>> = {
|
|
100
|
+
[P in K]: Value<T[P]>;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
interface Model extends Stateful {
|
|
104
|
+
/**
|
|
105
|
+
* Circular reference to `this` controller.
|
|
106
|
+
*
|
|
107
|
+
* Useful to obtain full reference where one has already destructured.
|
|
108
|
+
*/
|
|
109
|
+
get: this;
|
|
110
|
+
/**
|
|
111
|
+
* Circular reference to `this` controller.
|
|
112
|
+
*
|
|
113
|
+
* Shortcut is mainly to update values, while having destructured already.
|
|
114
|
+
*/
|
|
115
|
+
set: this;
|
|
116
|
+
}
|
|
117
|
+
declare class Model {
|
|
118
|
+
static [CONTROL]: Controller;
|
|
119
|
+
static [WHY]: readonly string[];
|
|
120
|
+
constructor();
|
|
121
|
+
get [STATE](): this;
|
|
122
|
+
get [WHY](): readonly string[] | undefined;
|
|
123
|
+
on<P = Model.Event<this>>(event: (key: P) => RequestCallback | void): Callback;
|
|
124
|
+
on<P = Model.Event<this>>(keys: [], listener: Model.OnUpdate<this, P>, squash?: boolean, once?: boolean): Callback;
|
|
125
|
+
on<P = Model.Event<this>>(keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
|
|
126
|
+
on(keys: [], listener: unknown, squash: boolean, once?: boolean): Callback;
|
|
127
|
+
on<P extends Model.Event<this>>(key: P | P[], listener: Model.OnUpdate<this, P>, squash?: boolean, once?: boolean): Callback;
|
|
128
|
+
on<P extends Model.Event<this>>(key: P | P[], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
|
|
129
|
+
on<P extends Model.Event<this>>(key: P | P[], listener: unknown, squash: boolean, once?: boolean): Callback;
|
|
130
|
+
once<P = Model.Event<this>>(keys: [], listener: Model.OnUpdate<this, P>, squash?: false, once?: boolean): Callback;
|
|
131
|
+
once<P = Model.Event<this>>(keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
|
|
132
|
+
once<P = Model.Event<this>>(keys: [], listener: (keys: P[]) => void, squash: true, once?: boolean): Callback;
|
|
133
|
+
once(keys: [], listener: unknown, squash: boolean, once?: boolean): Callback;
|
|
134
|
+
once<P extends Model.Event<this>>(key: P | P[], listener: Model.OnUpdate<this, P>, squash?: false): Callback;
|
|
135
|
+
once<P extends Model.Event<this>>(key: P | P[], listener: (keys: P[]) => void, squash: true): Callback;
|
|
136
|
+
once<P extends Model.Event<this>>(key: P | P[], listener: unknown, squash: boolean): Callback;
|
|
137
|
+
once<P extends Model.Event<this>>(key: P | P[]): Promise<P[]>;
|
|
138
|
+
effect(callback: Model.Effect<this>): Callback;
|
|
139
|
+
effect(callback: Model.Effect<this>, select: []): Callback;
|
|
140
|
+
effect(callback: Model.Effect<this>, select: Model.Event<this>[]): Callback;
|
|
141
|
+
import<O extends Model.Compat<this>>(source: O, select?: (keyof O)[]): void;
|
|
142
|
+
export(): Model.Values<this>;
|
|
143
|
+
export<P extends Model.Field<this>>(select: P[]): Model.Values<this, P>;
|
|
144
|
+
update(): PromiseLike<readonly Model.Event<this>[] | false>;
|
|
145
|
+
update(strict: true): Promise<readonly Model.Event<this>[]>;
|
|
146
|
+
update(strict: false): Promise<false>;
|
|
147
|
+
update(strict: boolean): Promise<readonly Model.Event<this>[] | false>;
|
|
148
|
+
update(keys: Model.Event<this>): PromiseLike<readonly Model.Event<this>[]>;
|
|
149
|
+
update(keys: Model.Event<this>, callMethod: boolean): PromiseLike<readonly Model.Event<this>[]>;
|
|
150
|
+
update<T>(keys: Model.Event<this>, argument: T): PromiseLike<readonly Model.Event<this>[]>;
|
|
151
|
+
/**
|
|
152
|
+
* Mark this instance for garbage-collection and send `willDestroy` event to all listeners.
|
|
153
|
+
*/
|
|
154
|
+
destroy(): void;
|
|
155
|
+
toString(): string;
|
|
156
|
+
/**
|
|
157
|
+
* Creates a new instance of this controller.
|
|
158
|
+
*
|
|
159
|
+
* Beyond `new this(...)`, method will activate managed-state.
|
|
160
|
+
*
|
|
161
|
+
* @param args - arguments sent to constructor
|
|
162
|
+
*/
|
|
163
|
+
static create<T extends Class>(this: T, ...args: any[]): InstanceOf<T>;
|
|
164
|
+
/**
|
|
165
|
+
* Static equivalent of `x instanceof this`.
|
|
166
|
+
*
|
|
167
|
+
* Will determine if provided class is a subtype of this one.
|
|
168
|
+
*/
|
|
169
|
+
static isTypeof<T extends new () => Model>(this: T, maybe: any): maybe is T;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
declare namespace Controller {
|
|
173
|
+
type OnEvent<T = any> = (key: Model.Event<T>, source: Controller) => RequestCallback | void;
|
|
174
|
+
type OnValue<T = any, S = Model.Values<T>> = (this: T, value: any, state: S) => boolean | void;
|
|
175
|
+
}
|
|
176
|
+
declare class Controller<T extends Stateful = any> {
|
|
177
|
+
subject: T;
|
|
178
|
+
proxy: Model.Entries<T>;
|
|
179
|
+
state: Model.Values<T, Exclude<keyof T & string, keyof Model>>;
|
|
180
|
+
frame: Set<string>;
|
|
181
|
+
waiting: Set<RequestCallback<string>>;
|
|
182
|
+
onDestroy: Set<Callback>;
|
|
183
|
+
protected followers: Set<Model.Controller.OnEvent<any>>;
|
|
184
|
+
constructor(subject: T);
|
|
185
|
+
start(): void;
|
|
186
|
+
stop(): void;
|
|
187
|
+
private manage;
|
|
188
|
+
ref(key: Model.Field<T>, handler?: Controller.OnValue<T>): (value: any) => void;
|
|
189
|
+
addListener(listener: Controller.OnEvent<T>): () => void;
|
|
190
|
+
emit(keys: readonly Model.Event<T>[]): void;
|
|
191
|
+
update(key: Model.Event<T>, value?: any): void;
|
|
192
|
+
requestUpdate(): PromiseLike<readonly Model.Event<T>[] | false>;
|
|
193
|
+
requestUpdate(strict: true): Promise<readonly Model.Event<T>[]>;
|
|
194
|
+
requestUpdate(strict: false): Promise<false>;
|
|
195
|
+
requestUpdate(strict: boolean): Promise<readonly Model.Event<T>[] | false>;
|
|
196
|
+
requestUpdate(callback: (keys: readonly Model.Event<T>[]) => void): void;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Property initializer, will run upon instance creation.
|
|
201
|
+
* Optional returned callback will run when once upon first access.
|
|
202
|
+
*/
|
|
203
|
+
type Instruction<T> = (this: Controller, key: string, thisArg: Controller) =>
|
|
204
|
+
| Instruction.Getter<T>
|
|
205
|
+
| Instruction.ExplicitDescriptor
|
|
206
|
+
| Instruction.Descriptor<T>
|
|
207
|
+
| Instruction.RecursiveDescriptor<T>
|
|
208
|
+
| boolean
|
|
209
|
+
| void;
|
|
210
|
+
|
|
211
|
+
declare namespace Instruction {
|
|
212
|
+
type Getter<T> = (state: T, within?: Subscriber) => T;
|
|
213
|
+
type Setter<T> = (value: T, state: any) => boolean | void;
|
|
214
|
+
|
|
215
|
+
type Runner<T> = (this: Controller, key: string, on: Controller) => Instruction.Descriptor<T> | boolean | undefined;
|
|
216
|
+
|
|
217
|
+
interface Descriptor<T> {
|
|
218
|
+
configurable?: boolean;
|
|
219
|
+
enumerable?: boolean;
|
|
220
|
+
value?: T;
|
|
221
|
+
writable?: boolean;
|
|
222
|
+
get?: Getter<T>;
|
|
223
|
+
set?: Setter<T> | false | void;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
interface ExplicitDescriptor extends PropertyDescriptor {
|
|
227
|
+
explicit: true;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface RecursiveDescriptor<T> {
|
|
231
|
+
recursive: true;
|
|
232
|
+
enumerable?: boolean;
|
|
233
|
+
value?: T;
|
|
234
|
+
set?: Setter<T> | false | void;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Run instruction as controller sets itself up.
|
|
240
|
+
* This will specialize the behavior of a given property.
|
|
241
|
+
*/
|
|
242
|
+
declare function apply<T = any>(instruction: Instruction<T>, name?: string): T;
|
|
243
|
+
|
|
244
|
+
declare namespace from {
|
|
245
|
+
type Function<T, O = any> = (this: O, on: O) => T;
|
|
246
|
+
type Factory<T, O = any> = (key: string) => Function<T, O>;
|
|
247
|
+
type Getter = (controller: Controller, key: string) => any;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Implement a computed value; output will be generated by provided function.
|
|
251
|
+
*
|
|
252
|
+
* @param source - Source model from which computed value will be a subscriber.
|
|
253
|
+
* @param compute - Compute function. Bound to a subscriber-proxy of source, returns output value. Will update automatically as input values change.
|
|
254
|
+
* @param suspend - Value will throw suspense when evaulating to undefined.
|
|
255
|
+
*/
|
|
256
|
+
declare function from<R, T>(source: T, compute: (this: T, on: T) => R, suspend: true): Exclude<R, undefined>;
|
|
257
|
+
declare function from<R, T>(source: T, compute: (this: T, on: T) => R, suspend?: boolean): R;
|
|
258
|
+
/**
|
|
259
|
+
* Implement a computed value; output is returned by function from provided factory.
|
|
260
|
+
*
|
|
261
|
+
* @param compute - Factory function to generate a getter to subscribe dependancies.
|
|
262
|
+
* @param suspend - Value will throw suspense when evaulating to undefined.
|
|
263
|
+
*/
|
|
264
|
+
declare function from<R, T>(compute: (property: string) => (this: T, state: T) => R, suspend: true): Exclude<R, undefined>;
|
|
265
|
+
declare function from<R, T>(compute: (property: string) => (this: T, state: T) => R, suspend?: boolean): R;
|
|
266
|
+
|
|
267
|
+
declare namespace ref {
|
|
268
|
+
type Callback<T, S = any> = (this: S, argument: T) => ((next: T) => void) | Promise<void> | void | boolean;
|
|
269
|
+
interface Object<T = any> {
|
|
270
|
+
(next: T): void;
|
|
271
|
+
current: T | null;
|
|
272
|
+
}
|
|
273
|
+
/** Object with references to all managed values of `T`. */
|
|
274
|
+
type Proxy<T extends Model> = {
|
|
275
|
+
[P in Model.Field<T>]: Model.Ref<T[P]>;
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Creates an object with references to all managed values.
|
|
280
|
+
* Each property will set value in state when invoked.
|
|
281
|
+
*
|
|
282
|
+
* *Properties are simultaneously a ref-function and ref-object, use as needed.*
|
|
283
|
+
*
|
|
284
|
+
* @param target - Source model from which to reference values.
|
|
285
|
+
*/
|
|
286
|
+
declare function ref<T extends Model>(target: T): ref.Proxy<T>;
|
|
287
|
+
/**
|
|
288
|
+
* Creates a ref-compatible property.
|
|
289
|
+
* Will persist value, and updates to this are made part of controller event-stream.
|
|
290
|
+
*
|
|
291
|
+
* *Output is simultaneously a ref-function and ref-object, use as needed.*
|
|
292
|
+
*
|
|
293
|
+
* @param callback - Optional callback to synchronously fire when reference is first set or does update.
|
|
294
|
+
*/
|
|
295
|
+
declare function ref<T = HTMLElement>(callback?: ref.Callback<T>): ref.Object<T>;
|
|
296
|
+
declare function ref<T, S>(callback?: ref.Callback<T, S>): ref.Object<T>;
|
|
297
|
+
|
|
298
|
+
declare namespace set {
|
|
299
|
+
type Factory<T, S = unknown> = (this: S, key: string, subject: S) => T;
|
|
300
|
+
type Callback<T, S = any> = (this: S, argument: T) => ((next: T) => void) | Promise<any> | void | boolean;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Set property with a placeholder.
|
|
304
|
+
*
|
|
305
|
+
* Property cannot be accessed until it is defined. If accessed while undefined, a hybrid
|
|
306
|
+
* `Promise`/`Error` (ala: [Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html)) will be thrown.
|
|
307
|
+
*/
|
|
308
|
+
declare function set<T = any>(): T;
|
|
309
|
+
/**
|
|
310
|
+
* Set property with starting value `undefined`.
|
|
311
|
+
*
|
|
312
|
+
* If required and accessed while still empty, React Suspense will be thrown.
|
|
313
|
+
* Property will reject any assignment of undefined.
|
|
314
|
+
*
|
|
315
|
+
* @param value - Starting value of host property (undefined).
|
|
316
|
+
* @param required - Property will suspend callee if undefined at time of access.
|
|
317
|
+
*/
|
|
318
|
+
declare function set<T>(value: undefined, required: false): T | undefined;
|
|
319
|
+
declare function set<T>(value: undefined, required?: boolean): T;
|
|
320
|
+
declare function set<T>(value: undefined, onUpdate: set.Callback<T>): T | undefined;
|
|
321
|
+
declare function set<T, S>(value: undefined, onUpdate: set.Callback<T, S>): T | undefined;
|
|
322
|
+
/**
|
|
323
|
+
* Set property with an async function.
|
|
324
|
+
*
|
|
325
|
+
* Property cannot be accessed until factory resolves, yeilding a result.
|
|
326
|
+
* If accessed while processing, React Suspense will be thrown.
|
|
327
|
+
*
|
|
328
|
+
* - `required: true` (default) -
|
|
329
|
+
* Run factory immediately upon creation of model instance.
|
|
330
|
+
* - `required: false` -
|
|
331
|
+
* Run factory only if/when accessed.
|
|
332
|
+
* Value will always throw suspense at least once - use with caution.
|
|
333
|
+
*
|
|
334
|
+
* @param factory - Callback run to derrive property value.
|
|
335
|
+
* @param required - (default: true) Run factory immediately on creation, otherwise on access.
|
|
336
|
+
*/
|
|
337
|
+
declare function set<T>(factory: set.Factory<Promise<T>>, required: false): T | undefined;
|
|
338
|
+
declare function set<T, S>(factory: set.Factory<Promise<T>, S>, required: false): T | undefined;
|
|
339
|
+
declare function set<T>(factory: set.Factory<Promise<T>>, required?: boolean): T;
|
|
340
|
+
declare function set<T, S>(factory: set.Factory<Promise<T>, S>, required?: boolean): T;
|
|
341
|
+
declare function set<T>(value: set.Factory<Promise<T>>, onUpdate: set.Callback<T>): T;
|
|
342
|
+
declare function set<T, S>(value: set.Factory<Promise<T>, S>, onUpdate: set.Callback<T, S>): T;
|
|
343
|
+
/**
|
|
344
|
+
* Set property with a factory function.
|
|
345
|
+
*
|
|
346
|
+
* - `required: true` (default) -
|
|
347
|
+
* Run factory immediately upon creation of model instance.
|
|
348
|
+
* - `required: false` -
|
|
349
|
+
* Run factory only if/when accessed.
|
|
350
|
+
* Value will always throw suspense at least once - use with caution.
|
|
351
|
+
*
|
|
352
|
+
* @param factory - Callback run to derrive property value.
|
|
353
|
+
* @param required - (default: true) Run factory immediately on creation, otherwise on access.
|
|
354
|
+
*/
|
|
355
|
+
declare function set<T>(factory: set.Factory<T>, required: false): T | undefined;
|
|
356
|
+
declare function set<T, S>(factory: set.Factory<T, S>, required: false): T | undefined;
|
|
357
|
+
declare function set<T>(factory: set.Factory<T>, required?: boolean): T;
|
|
358
|
+
declare function set<T, S>(factory: set.Factory<T, S>, required?: boolean): T;
|
|
359
|
+
declare function set<T>(value: set.Factory<T>, onUpdate: set.Callback<T>): T;
|
|
360
|
+
declare function set<T, S>(value: set.Factory<T, S>, onUpdate: set.Callback<T, S>): T;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Create a placeholder for specified Model type.
|
|
364
|
+
*/
|
|
365
|
+
declare function use<T extends Model>(): T | undefined;
|
|
366
|
+
/**
|
|
367
|
+
* Create a new child instance of model.
|
|
368
|
+
*/
|
|
369
|
+
declare function use<T extends Class>(Type: T, callback?: (i: InstanceOf<T>) => void): InstanceOf<T>;
|
|
370
|
+
/**
|
|
371
|
+
* Create a managed child from factory function.
|
|
372
|
+
*/
|
|
373
|
+
declare function use<T extends {}>(from: () => T, callback?: (i: T) => void): T;
|
|
374
|
+
/**
|
|
375
|
+
* Create child-instance relationship with provided model.
|
|
376
|
+
*
|
|
377
|
+
* Note: If `peer` is not already initialized before parent is
|
|
378
|
+
* (created with `new` as opposed to create method), that model will
|
|
379
|
+
* attach this via `parent()` instruction. It will not, however, if
|
|
380
|
+
* already active.
|
|
381
|
+
*/
|
|
382
|
+
declare function use<T extends {}>(peer: T, callback?: (i: T) => void): T;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Fetches and assigns the controller which spawned this host.
|
|
386
|
+
* When parent assigns an instance via `use()` directive, it
|
|
387
|
+
* will be made available to child upon this request.
|
|
388
|
+
*
|
|
389
|
+
* @param Expects - Type of controller compatible with this class.
|
|
390
|
+
* @param required - Throw if controller is created independantly.
|
|
391
|
+
*/
|
|
392
|
+
declare function parent<T extends typeof Model>(Expects: T, required: false): InstanceOf<T> | undefined;
|
|
393
|
+
declare function parent<T extends typeof Model>(Expects: T, required?: true): InstanceOf<T>;
|
|
394
|
+
|
|
395
|
+
declare class MVC extends Model {
|
|
396
|
+
static [CONTROL]: Controller;
|
|
397
|
+
/** Attaches this controller to a component. */
|
|
398
|
+
tap(): this;
|
|
399
|
+
tap<K extends Model.Field<this>>(key: K, expect: true): Exclude<this[K], undefined>;
|
|
400
|
+
tap<K extends Model.Field<this>>(key: K, expect?: boolean): this[K];
|
|
401
|
+
tap<T>(from: (this: this, state: this) => Promise<T>, expect: true): Exclude<T, undefined>;
|
|
402
|
+
tap<T>(from: (this: this, state: this) => Promise<T>, expect?: boolean): T | undefined;
|
|
403
|
+
tap<T>(from: (this: this, state: this) => T, expect: true): Exclude<T, undefined>;
|
|
404
|
+
tap<T>(from: (this: this, state: this) => T, expect?: boolean): T;
|
|
405
|
+
/**
|
|
406
|
+
* **React Hook** - Subscribe to instance of controller within a component.
|
|
407
|
+
*
|
|
408
|
+
* @param callback - Run once before subscription begins.
|
|
409
|
+
*/
|
|
410
|
+
use(watch: Model.Field<this>[], callback?: (instance: this) => void): this;
|
|
411
|
+
use(callback?: (instance: this) => void): this;
|
|
412
|
+
/**
|
|
413
|
+
* **React Hook** - Fetch most instance of this controller from context, if it exists.
|
|
414
|
+
*
|
|
415
|
+
* @param required - If false, may return undefined.
|
|
416
|
+
*/
|
|
417
|
+
static get<T extends Class>(this: T, required?: true): InstanceOf<T>;
|
|
418
|
+
/**
|
|
419
|
+
* **React Hook** - Fetch most instance of this controller from context.
|
|
420
|
+
*
|
|
421
|
+
* @param required - Unless false, will throw where instance cannot be found.
|
|
422
|
+
*/
|
|
423
|
+
static get<T extends Class>(this: T, required: boolean): InstanceOf<T> | undefined;
|
|
424
|
+
/**
|
|
425
|
+
* **React Hook** - Fetch specific value from instance of this controller in context.
|
|
426
|
+
*/
|
|
427
|
+
static get<T extends Class, I extends InstanceOf<T>, K extends Model.Field<I>>(this: T, key: K): I[K];
|
|
428
|
+
/**
|
|
429
|
+
* **React Hook** - Fetch and subscribe to instance of this controller within ambient component.
|
|
430
|
+
*/
|
|
431
|
+
static tap<T extends Class>(this: T): InstanceOf<T>;
|
|
432
|
+
static tap<T extends Class, I extends InstanceOf<T>, K extends Model.Field<I>>(this: T, key: K, expect: true): Exclude<I[K], undefined>;
|
|
433
|
+
static tap<T extends Class, I extends InstanceOf<T>, K extends Model.Field<I>>(this: T, key: K, expect?: boolean): I[K];
|
|
434
|
+
static tap<T, M extends Class, I extends InstanceOf<M>>(this: M, from: (this: I, state: I) => Promise<T>, expect: true): Exclude<T, undefined>;
|
|
435
|
+
static tap<T, M extends Class, I extends InstanceOf<M>>(this: M, from: (this: I, state: I) => Promise<T>, expect?: boolean): T;
|
|
436
|
+
static tap<T, M extends Class, I extends InstanceOf<M>>(this: M, from: (this: I, state: I) => T, expect: true): Exclude<T, undefined>;
|
|
437
|
+
static tap<T, M extends Class, I extends InstanceOf<M>>(this: M, from: (this: I, state: I) => T, expect?: boolean): T;
|
|
438
|
+
/**
|
|
439
|
+
* **React Hook** - Spawn and maintain a controller from within a component.
|
|
440
|
+
*
|
|
441
|
+
* More efficient than `use()` if you don't need hook-based features.
|
|
442
|
+
*
|
|
443
|
+
* @param callback - Run after creation of instance.
|
|
444
|
+
*/
|
|
445
|
+
static new<T extends Class>(this: T, callback?: (instance: InstanceOf<T>) => void): InstanceOf<T>;
|
|
446
|
+
static use<T extends Class, I extends InstanceOf<T>>(this: T, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
|
|
447
|
+
static use<T extends Class, I extends InstanceOf<T>>(this: T, callback?: (instance: I) => void): I;
|
|
448
|
+
static use<T extends Class, I extends InstanceOf<T>>(this: T, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
449
|
+
/**
|
|
450
|
+
* @deprecated consider doing this manually - not worth minor efficiency gain over using.
|
|
451
|
+
*/
|
|
452
|
+
static uses<T extends typeof MVC, I extends InstanceOf<T>, D extends Model.Compat<I>>(this: T, apply: D, keys?: (keyof D)[]): InstanceOf<T>;
|
|
453
|
+
/**
|
|
454
|
+
* @deprecated is now replaced by overload of `use` method.
|
|
455
|
+
*/
|
|
456
|
+
static using<T extends typeof MVC, I extends InstanceOf<T>>(this: T, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
457
|
+
static meta<T extends Class>(this: T): T;
|
|
458
|
+
static meta<T extends Class, K extends keyof T>(this: T, key: K, expect: true): Exclude<T[K], undefined>;
|
|
459
|
+
static meta<T extends Class, K extends keyof T>(this: T, key: K, expect?: boolean): T[K];
|
|
460
|
+
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect: true): Exclude<T, undefined>;
|
|
461
|
+
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => Promise<T>, expect?: boolean): T;
|
|
462
|
+
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect: true): Exclude<T, undefined>;
|
|
463
|
+
static meta<T, M extends Class>(this: M, from: (this: M, state: M) => T, expect?: boolean): T;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
declare namespace Consumer {
|
|
467
|
+
type HasProps<E extends Class> = {
|
|
468
|
+
/** Type of controller to fetch from context. */
|
|
469
|
+
of: E;
|
|
470
|
+
/**
|
|
471
|
+
* Getter function. Is called on every natural render of this component.
|
|
472
|
+
* Will throw if usable instance cannot be found in context.
|
|
473
|
+
*/
|
|
474
|
+
has: (value: InstanceType<E>) => void;
|
|
475
|
+
};
|
|
476
|
+
type GetProps<E extends Class> = {
|
|
477
|
+
/** Type of controller to fetch from context. */
|
|
478
|
+
of: E;
|
|
479
|
+
/** Getter function. Is called on every natural render of this component. */
|
|
480
|
+
get: (value: InstanceType<E> | undefined) => void;
|
|
481
|
+
};
|
|
482
|
+
type RenderProps<E extends Class> = {
|
|
483
|
+
/** Type of controller to fetch from context. */
|
|
484
|
+
of: E;
|
|
485
|
+
/**
|
|
486
|
+
* Render function, will receive instance of desired controller.
|
|
487
|
+
*
|
|
488
|
+
* Similar to `tap()`, updates to properties accessed in
|
|
489
|
+
* this function will cause a refresh when they change.
|
|
490
|
+
*/
|
|
491
|
+
children: (value: InstanceType<E>) => React.ReactElement<any, any> | null;
|
|
492
|
+
};
|
|
493
|
+
type Props<T extends Class> = HasProps<T> | GetProps<T> | RenderProps<T>;
|
|
494
|
+
}
|
|
495
|
+
declare function Consumer<T extends Class>(props: Consumer.Props<T>): any;
|
|
496
|
+
|
|
497
|
+
declare type Collection = Array<Model | typeof Model> | {
|
|
498
|
+
[anything: string]: Model | typeof Model;
|
|
499
|
+
};
|
|
500
|
+
declare class Lookup {
|
|
501
|
+
private table;
|
|
502
|
+
get local(): Model[];
|
|
503
|
+
private key;
|
|
504
|
+
get(T: typeof Model): any;
|
|
505
|
+
push(I: Model | typeof Model | Collection): this;
|
|
506
|
+
register(I: Model | typeof Model): Model;
|
|
507
|
+
pop(): void;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
declare namespace Provider {
|
|
511
|
+
type Item = Model | typeof Model;
|
|
512
|
+
type Collection<T extends Item> = T[] | {
|
|
513
|
+
[key: string]: T;
|
|
514
|
+
};
|
|
515
|
+
type Existent<E> = E extends Class ? InstanceType<E> : E extends Model ? E : never;
|
|
516
|
+
type NormalProps<E, I = Existent<E>> = {
|
|
517
|
+
of: E;
|
|
518
|
+
children: React.ReactNode | ((instance: I) => React.ReactNode);
|
|
519
|
+
} & Model.Compat<I>;
|
|
520
|
+
type MultipleProps<T extends Item> = {
|
|
521
|
+
of: Collection<T>;
|
|
522
|
+
children?: React.ReactNode | (() => React.ReactNode);
|
|
523
|
+
} & Model.Compat<Existent<T>>;
|
|
524
|
+
type Props<T extends Item> = MultipleProps<T> | NormalProps<T>;
|
|
525
|
+
}
|
|
526
|
+
declare function Provider<T extends Provider.Item>(props: Provider.Props<T>): React.FunctionComponentElement<React.ProviderProps<Lookup>>;
|
|
527
|
+
|
|
528
|
+
declare class Global extends MVC {
|
|
529
|
+
static create<T extends Class>(this: T, ...args: any[]): InstanceOf<T>;
|
|
530
|
+
/**
|
|
531
|
+
* Update the active instance of this class.
|
|
532
|
+
* Returns a thenable; resolves after successful update.
|
|
533
|
+
* If instance does not already exist, one will be created.
|
|
534
|
+
*/
|
|
535
|
+
static set<T extends typeof Global>(this: T, updates: Partial<InstanceOf<T>>): PromiseLike<false | readonly Model.Event<Global, Model>[]>;
|
|
536
|
+
static get(arg?: boolean | string): any;
|
|
537
|
+
/** Destroy current instance of Global, if it exists. */
|
|
538
|
+
static reset(): void;
|
|
539
|
+
destroy(): void;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Find and attach most applicable instance of Model via context.
|
|
544
|
+
*
|
|
545
|
+
* Host controller will search element-hierarchy relative to where it spawned.
|
|
546
|
+
*
|
|
547
|
+
* @param Type - Type of model to find from context
|
|
548
|
+
* @param callback -
|
|
549
|
+
* - Invoked after context is scanned, is passed result - either found or undefined.
|
|
550
|
+
* - If argument is inadequate, but required, your implemention should simply throw.
|
|
551
|
+
* - If inadequate and not required, conditionally return false.
|
|
552
|
+
*/
|
|
553
|
+
declare function tap<T extends Class>(Type: T, callback?: (instance?: InstanceOf<T>) => void | true): InstanceOf<T>;
|
|
554
|
+
declare function tap<T extends Class>(Type: T, callback?: (instance?: InstanceOf<T>) => void | boolean): InstanceOf<T> | undefined;
|
|
555
|
+
/**
|
|
556
|
+
* Find and attach most applicable instance of Model via context.
|
|
557
|
+
*
|
|
558
|
+
* Expects a `<Provider>` of target controller to exist.
|
|
559
|
+
* Host controller will search element-hierarchy relative to where it spawned.
|
|
560
|
+
*
|
|
561
|
+
* @param Type - Type of controller to attach to property.
|
|
562
|
+
* @param required - Throw if instance of Type cannot be found.
|
|
563
|
+
*/
|
|
564
|
+
declare function tap<T extends Class>(Type: T, required: true): InstanceOf<T>;
|
|
565
|
+
declare function tap<T extends Class>(Type: T, required?: boolean): InstanceOf<T> | undefined;
|
|
566
|
+
|
|
567
|
+
declare function useFrom<T extends Stateful, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect: true): Exclude<R, undefined>;
|
|
568
|
+
declare function useFrom<T extends Stateful, R>(source: (() => T) | T, compute: (this: T, from: T) => R, expect?: boolean): R;
|
|
569
|
+
|
|
570
|
+
declare function useInContext<T extends typeof Model>(Type: T, arg?: boolean | string): any;
|
|
571
|
+
|
|
572
|
+
declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, watch: Model.Field<I>[], callback?: (instance: I) => void): I;
|
|
573
|
+
declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, callback?: (instance: I) => void): I;
|
|
574
|
+
declare function useModel<T extends Class, I extends InstanceOf<T>>(source: T, apply: Model.Compat<I>, keys?: Model.Event<I>[]): I;
|
|
575
|
+
declare function useModel<T extends Stateful>(source: (() => T) | T, watch?: Model.Field<T>[], callback?: (instance: T) => void): T;
|
|
576
|
+
declare function useModel<T extends Stateful>(source: (() => T) | T, callback?: (instance: T) => void): T;
|
|
577
|
+
declare function useModel<T extends Stateful>(source: (() => T) | T, apply: Model.Compat<T>, keys?: Model.Event<T>[]): T;
|
|
578
|
+
|
|
579
|
+
declare namespace useTap {
|
|
580
|
+
interface Tappable {
|
|
581
|
+
new (): Stateful;
|
|
582
|
+
new (...args: any[]): Stateful;
|
|
583
|
+
get?: () => Stateful;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
declare function useTap<T extends Stateful>(source: T | (() => T)): T;
|
|
587
|
+
declare function useTap<T extends Stateful, K extends Model.Field<T>>(source: T | (() => T) | useTap.Tappable, path: K, expect: true): Exclude<T[K], undefined>;
|
|
588
|
+
declare function useTap<T extends Stateful, K extends Model.Field<T>>(source: T | (() => T) | useTap.Tappable, path: K, expect?: boolean): T[K];
|
|
589
|
+
declare function useTap<T extends Stateful, R>(source: T | (() => T) | useTap.Tappable, compute: (this: T, from: T) => R, expect: true): Exclude<R, undefined>;
|
|
590
|
+
declare function useTap<T extends Stateful, R>(source: T | (() => T) | useTap.Tappable, compute: (this: T, from: T) => R, expect?: boolean): R;
|
|
591
|
+
|
|
592
|
+
export { CONTROL, Consumer, Global, LOCAL, MVC as Model, Provider, STATE, Stateful, WHY, act, apply, MVC as default, from, parent, ref, set, tap, use, useFrom, useInContext, useModel, useTap };
|