Skip to content

Commit b667adf

Browse files
committedNov 25, 2019
added in-code docs
1 parent 852cf71 commit b667adf

7 files changed

+218
-18
lines changed
 

‎src/agent/deep.ts

+11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ import { KeyedDeep } from "./keyed-deep";
77

88
export function deep(state: State): SimpleDeep;
99
export function deep(state: State, key: KeyFunc): KeyedDeep;
10+
/**
11+
*
12+
* Creates a [deep state](https://connective.dev/docs/deep) from given state.
13+
* You can track indexes, properties and keyed entities on deep states as bound
14+
* reactive states.
15+
* [Checkout the docs](https://connective.dev/docs/deep) for examples and further information.
16+
*
17+
* @param state the state to be used as the basis of the returned deep state
18+
* @param key the key function to be used to track entities in the deep state
19+
*
20+
*/
1021
export function deep(state: State, key?: KeyFunc): SimpleDeep | KeyedDeep {
1122
if (key) return new KeyedDeep(state, key);
1223
else return new SimpleDeep(state);

‎src/agent/keyed-deep.ts

+64-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,24 @@ import { SimpleDeep, DeepAccessor } from "./simple-deep";
1414
import { State, EqualityFunc } from "./state";
1515

1616

17+
/**
18+
*
19+
* Represents a [keyed deep state](https://connective.dev/docs/deep#keyed-deep).
20+
*
21+
*/
1722
export class KeyedDeep extends SimpleDeep {
1823
private _keyMap: KeyMap = {};
1924

2025
constructor(state: State, keyfunc: KeyFunc);
2126
constructor(accessor: DeepAccessor, keyfunc: KeyFunc, compare?: EqualityFunc);
2227
constructor(stateOrAccessor: State | DeepAccessor, keyfunc: KeyFunc, compare?: EqualityFunc | undefined);
23-
28+
/**
29+
*
30+
* @param stateOrAccessor underlying state of this deep state or a state tree accessor (for sub-states)
31+
* @param keyfunc key function to be used to track entities within the state's value
32+
* @param compare equality function used to detect changes. If state is passed as first argument this is ignored.
33+
*
34+
*/
2435
constructor(stateOrAccessor: State | DeepAccessor, readonly keyfunc: KeyFunc, compare?: EqualityFunc | undefined) {
2536
super(stateOrAccessor, compare, {
2637
inputs: ['value'],
@@ -30,14 +41,23 @@ export class KeyedDeep extends SimpleDeep {
3041

3142
public key(key: string | number): SimpleDeep;
3243
public key(key: string | number, subkeyfunc: KeyFunc): KeyedDeep;
44+
/**
45+
*
46+
* Creates a sub-state bound to entity identified by given key. Entity `x` is
47+
* said to be identified by key `k` if `state.keyfunc(x) === k`.
48+
*
49+
* @param key the identifier of the entity to track
50+
* @param subkeyfunc a key function for the sub-state. provide IF the sub-state also needs to be keyed.
51+
*
52+
*/
3353
public key(key: string | number, subkeyfunc?: KeyFunc): SimpleDeep | KeyedDeep {
3454
let initialized = false;
3555
let _this = this;
3656

3757
this.output; // --> wire output before hand
3858

3959
let accessor: DeepAccessor = {
40-
initial: (_this._keyMap[key] || {item: undefined}).item
60+
initial: (_this._keyMap[key] || {item: undefined}).item
4161
|| (Object.values(this.value) || []).find((i: any) => this.keyfunc(i) == key),
4262
get: group(_this.changes, _this.reemit).to(map(() => (_this._keyMap[key] || {item: undefined}).item)),
4363
set: sink((v, context) => {
@@ -67,11 +87,20 @@ export class KeyedDeep extends SimpleDeep {
6787
else return new SimpleDeep(accessor, this.state.compare);
6888
}
6989

90+
/**
91+
*
92+
* Returns a [pin](https://connective.dev/docs/pin) that reflects the reactive value of
93+
* the index of entity identified by given key in the state's value. Entity `x` is said
94+
* to be identified by key `k` if `state.keyfunc(x) === k`.
95+
*
96+
* @param key the key to identify target entity with
97+
*
98+
*/
7099
public index(key: string | number) {
71100
let initial: string | number;
72101

73102
if (this._keyMap[key]) initial = this._keyMap[key].index;
74-
else initial = ((Object.entries(this.value) || []).find(([index, item]) => this.keyfunc(item) == key)
103+
else initial = ((Object.entries(this.value) || []).find(([index, item]) => this.keyfunc(item) == key)
75104
|| [-1, undefined])[0];
76105

77106
return group(
@@ -80,16 +109,47 @@ export class KeyedDeep extends SimpleDeep {
80109
).to(pipe(distinctUntilKeyChanged('value')));
81110
}
82111

112+
/**
113+
*
114+
* Will bind the underlying state, and cause deep change-detection to happen upon
115+
* changes of the state value. [Read this](https://connective.dev/docs/deep#change-detection)
116+
* for more information on deep change-detection.
117+
*
118+
* If this is a sub-state, also enables up-propagation
119+
* of state value, causing the parent state to pick up changes made to the value of this
120+
* sub-state. [Read this](https://connective.dev/docs/deep#two-way-keyed) for more details
121+
* and examples.
122+
*
123+
*/
83124
bind() {
84125
super.bind();
85126
this.track(this.changes.subscribe());
86127
return this;
87128
}
88129

130+
/**
131+
*
132+
* Keys that entities within the value of the state are identified with. Entity
133+
* `x` is said to be indetified with key `k` if `state.keyfunc(x) === k`.
134+
*
135+
* **WARNING** the keys will not be calculcated unless deep change-detection is active.
136+
* You can ensure deep change-detection is active by subscribing on `.changes` or
137+
* calling `.bind()`. [Read this](https://connective.dev/docs/deep#change-detection)
138+
* for more information on deep change-detection.
139+
*
140+
*/
89141
public get keys() {
90-
return Object.keys(this._keyMap);
142+
return Object.keys(this._keyMap);
91143
}
92144

145+
/**
146+
*
147+
* A [pin](https://connective.dev/docs/pin) that emits changes to this deep state's list value.
148+
* These changes include entities being added to the list, removed from it or moved around in it.
149+
* [Read this](https://connective.dev/docs/deep#change-detection) for more information on
150+
* deep change-detection.
151+
*
152+
*/
93153
public get changes() { return this.out('changes'); }
94154

95155
protected createOutput(label: string): PinLike {

‎src/agent/simple-deep.ts

+59-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,25 @@ import { Signature } from "./signature";
1515

1616
export interface DeepAccessor {
1717
initial: any;
18-
set: PinLike;
18+
set: PinLike;
1919
get: PinLike;
2020
bind(): void;
2121
}
2222

2323

24+
/**
25+
*
26+
* Represents non-keyed (simple) [deep states](https://connective.dev/docs/deep).
27+
*
28+
*/
2429
export class SimpleDeep extends Agent {
30+
/**
31+
*
32+
* can be used to force re-emission of state value.
33+
*
34+
*/
2535
readonly reemit: Source;
36+
2637
protected state: State;
2738
protected accessor: DeepAccessor;
2839
private downPropageteKey: string;
@@ -32,6 +43,13 @@ export class SimpleDeep extends Agent {
3243
constructor(accessor: DeepAccessor, compare?: EqualityFunc);
3344
constructor(stateOrAccessor: State | DeepAccessor, compare?: EqualityFunc | undefined);
3445
constructor(stateOrAccessor: State | DeepAccessor, compare?: EqualityFunc | undefined, signature?: Signature);
46+
/**
47+
*
48+
* @param stateOrAccessor underlying state of this deep state or a state tree accessor (for sub-states)
49+
* @param compare equality function used to detect changes. If state is passed as first argument this is ignored.
50+
* @param signature the signature of the state, to be overriden by child classes.
51+
*
52+
*/
3553
constructor(stateOrAccessor: State | DeepAccessor, compare?: EqualityFunc | undefined, signature?: Signature) {
3654
super(signature || {
3755
inputs: ['value'],
@@ -60,13 +78,21 @@ export class SimpleDeep extends Agent {
6078
}
6179
}
6280

81+
/**
82+
*
83+
* Creates a sub-state for given index/property.
84+
* [Read this](https://connective.dev/docs/deep) for more details
85+
*
86+
* @param index
87+
*
88+
*/
6389
public sub(index: string | number): SimpleDeep {
6490
let initialized = false;
6591
let _this = this;
6692

6793
return new SimpleDeep({
6894
initial: (_this.value || [])[index],
69-
get: _this.output.to(map((v: any) => (v || [])[index])),
95+
get: _this.output.to(map((v: any) => (v || [])[index])),
7096
set: sink((v, context) => {
7197
try {
7298
if (!_this.value) _this.value = [];
@@ -88,14 +114,45 @@ export class SimpleDeep extends Agent {
88114
}, this.state.compare);
89115
}
90116

117+
/**
118+
*
119+
* Allows reading or updating state's value directly.
120+
*
121+
*/
91122
public get value(): any { return this.state.value; }
92123
public set value(v: any) { this.state.value = v; }
93124

125+
/**
126+
*
127+
* The equality function used by this deep state. Is used for change detection.
128+
*
129+
*/
94130
public get compare() { return this.state.compare; }
95131

132+
/**
133+
*
134+
* Shortcut for `.in('value')`, on which the state receives new values.
135+
* [Read this](https://connective.dev/docs/state#signature) for more details.
136+
*
137+
*/
96138
get input() { return this.in('value'); }
139+
140+
/**
141+
*
142+
* Shortcut for `.out('value')`, on which the state emits new values.
143+
* [Read this](https://connective.dev/docs/state#signature) for more details.
144+
*
145+
*/
97146
get output() { return this.out('value'); }
98147

148+
/**
149+
*
150+
* Binds the underlying state. If this is a sub-state, it will also
151+
* allow up-propagation of state value, causing the parent state to pick up
152+
* changes made to the value of this sub-state. [Read this](https://connective.dev/docs/deep#two-way-data)
153+
* for more details and examples.
154+
*
155+
*/
99156
bind() {
100157
if (!this.bound) {
101158
if (this.accessor) this.accessor.bind();

‎src/agent/state.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ export class State extends Agent implements Bindable {
9191
get output() { return this.out('value'); }
9292

9393
/**
94-
*
94+
*
9595
* Allows reading or updating `State`'s value directly. It will be equal
9696
* to the latest value emitted by the `State`, and setting it, if the value
9797
* has changed truly, will cause the `State` to emit the new value.
98-
*
98+
*
9999
*/
100100
public get value() { return (this._subject.value.value !== _Unset)?(this._subject.value.value):undefined }
101101
public set value(v: any) { this._injector.send(v); }
@@ -112,10 +112,10 @@ export class State extends Agent implements Bindable {
112112
}
113113

114114
/**
115-
*
116-
* @note `State`'s `.clear()` also causes a complete
115+
*
116+
* @note `State`'s `.clear()` also causes a complete
117117
* notification to be sent to observers.
118-
*
118+
*
119119
*/
120120
public clear(): this {
121121
this._subject.complete();
@@ -150,7 +150,7 @@ export function state(initial: any, compare: EqualityFunc): State;
150150
*
151151
*/
152152
export function state(initialOrCompare?: any | EqualityFunc | undefined, compare?: EqualityFunc | undefined) {
153-
return new State(initialOrCompare, compare);
153+
return new State(initialOrCompare, compare);
154154
}
155155

156156

‎src/agent/test/keyed-deep.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe('KeyedDeep', () => {
121121
let gc2 = c2.sub('name').bind(); let rgc2 = 0; gc2.subscribe(() => rgc2++);
122122

123123
r.should.equal(1); // --> initial value
124-
rc1.should.equal(1);
124+
rc1.should.equal(1);
125125
rgc1.should.equal(1);
126126
rc2.should.equal(1);
127127
rgc2.should.equal(1);

‎src/agent/test/simple-deep.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('SimpleDeep', () => {
174174
let gc2 = c2.sub('y').bind(); let rgc2 = 0; gc2.subscribe(() => rgc2++);
175175

176176
r.should.equal(1); // --> initial value
177-
rc1.should.equal(1);
177+
rc1.should.equal(1);
178178
rgc1.should.equal(1);
179179
rc2.should.equal(1);
180180
rgc2.should.equal(1);

‎src/util/keyed-array-diff.ts

+76-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,82 @@
11
export type KeyFunc = (obj: any) => string | number;
22
export type KeyMap = {[key: string]: {item: any, index: string}};
33

4-
export type AdditionList = {index: string, item: any}[];
5-
export type DeletionList = {index: string, item: any}[];
6-
export type MoveList = {oldIndex: string, newIndex: string, item: any}[];
7-
export type ChangeMap = { additions: AdditionList, deletions: DeletionList, moves: MoveList };
4+
export type AdditionList = {
5+
/**
6+
*
7+
* The index that the item was added on.
8+
*
9+
*/
10+
index: string,
11+
12+
/**
13+
*
14+
* The added item
15+
*
16+
*/
17+
item: any
18+
}[];
19+
20+
export type DeletionList = {
21+
/**
22+
*
23+
* The index the deleted item used to be on
24+
*
25+
*/
26+
index: string,
27+
28+
/**
29+
*
30+
* The deleted item
31+
*
32+
*/
33+
item: any
34+
}[];
35+
36+
export type MoveList = {
37+
/**
38+
*
39+
* The index the item used to be on
40+
*
41+
*/
42+
oldIndex: string,
43+
/**
44+
*
45+
* The new index of the item
46+
*
47+
*/
48+
newIndex: string,
49+
50+
/**
51+
*
52+
* The moved item
53+
*
54+
*/
55+
item: any
56+
}[];
57+
58+
export type ChangeMap = {
59+
/**
60+
*
61+
* List of items added to the list
62+
*
63+
*/
64+
additions: AdditionList,
65+
66+
/**
67+
*
68+
* List of items removed from the list
69+
*
70+
*/
71+
deletions: DeletionList,
72+
73+
/**
74+
*
75+
* List of items moved around in the list
76+
*
77+
*/
78+
moves: MoveList
79+
};
880

981

1082
export function diff(value: any, oldKeyMap: KeyMap, keyfunc: KeyFunc): {

0 commit comments

Comments
 (0)
Failed to load comments.