@bodil/signal 0.3.5 → 0.4.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/dist/array.d.ts +144 -15
- package/dist/array.js +213 -53
- package/dist/array.js.map +1 -1
- package/dist/index.d.ts +1 -120
- package/dist/index.js +1 -197
- package/dist/index.js.map +1 -1
- package/dist/map.d.ts +130 -0
- package/dist/map.js +227 -0
- package/dist/map.js.map +1 -0
- package/dist/map.test.d.ts +1 -0
- package/dist/map.test.js +52 -0
- package/dist/map.test.js.map +1 -0
- package/dist/signal.d.ts +200 -0
- package/dist/signal.js +263 -0
- package/dist/signal.js.map +1 -0
- package/dist/signal.test.js +6 -6
- package/dist/signal.test.js.map +1 -1
- package/package.json +4 -1
- package/src/array.ts +233 -67
- package/src/index.ts +1 -265
- package/src/map.test.ts +62 -0
- package/src/map.ts +263 -0
- package/src/signal.test.ts +7 -7
- package/src/signal.ts +361 -0
package/dist/array.d.ts
CHANGED
|
@@ -1,33 +1,162 @@
|
|
|
1
|
+
import type { Equals } from "@bodil/core/types";
|
|
1
2
|
import { type Option } from "@bodil/opt";
|
|
2
|
-
|
|
3
|
+
import * as Signal from "./signal";
|
|
4
|
+
declare const instance: unique symbol;
|
|
5
|
+
type InstanceProps<A> = {
|
|
6
|
+
array: Array<A>;
|
|
7
|
+
signal: Signal.State<null>;
|
|
8
|
+
equals?: (a: A, b: A) => boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A read-only view of a {@link Signal.Array}.
|
|
12
|
+
*
|
|
13
|
+
* This acts just like the {@link Signal.Array} it was created from, mirroring
|
|
14
|
+
* the current contents of the source array, but without the ability to modify
|
|
15
|
+
* it.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ReadonlySignalArray<A> implements Iterable<A>, Equals {
|
|
18
|
+
/** @ignore */
|
|
19
|
+
protected readonly [instance]: InstanceProps<A>;
|
|
20
|
+
/** @ignore */
|
|
21
|
+
protected constructor(instanceProps: InstanceProps<A>);
|
|
22
|
+
/**
|
|
23
|
+
* Test whether a value is a `Signal.ReadonlyArray`.
|
|
24
|
+
*/
|
|
25
|
+
static is(value: unknown): value is Signal.ReadonlyArray<unknown>;
|
|
26
|
+
/**
|
|
27
|
+
* Test whether the array is empty.
|
|
28
|
+
*/
|
|
3
29
|
isEmpty(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get the size of the array.
|
|
32
|
+
*/
|
|
4
33
|
size(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Find the index at which the given value first occurs in the array,
|
|
36
|
+
* optionally starting at `fromIndex`. If the value doesn't occur in the
|
|
37
|
+
* array, return `-1`.
|
|
38
|
+
*/
|
|
5
39
|
indexOf(value: A, fromIndex?: number): number;
|
|
40
|
+
/**
|
|
41
|
+
* Find the first index in the array for which the `predicate` function
|
|
42
|
+
* returns true for the value at that index, or `-1` if it never does.
|
|
43
|
+
*/
|
|
6
44
|
findIndex(predicate: (value: A, index: number, obj: Array<A>) => boolean, thisArg?: any): number;
|
|
45
|
+
/**
|
|
46
|
+
* Test whether a value is an array with identical contents to this array.
|
|
47
|
+
*/
|
|
48
|
+
equals(other: unknown): other is Signal.ReadonlyArray<A>;
|
|
49
|
+
/**
|
|
50
|
+
* Copy the contents of this array into a normal {@link Array}.
|
|
51
|
+
*/
|
|
7
52
|
toArray(): Array<A>;
|
|
53
|
+
/**
|
|
54
|
+
* Get the value at the given index, or {@link None} if the index is out of
|
|
55
|
+
* bounds.
|
|
56
|
+
*
|
|
57
|
+
* @throws {@link TypeError} of `index` is not an integer
|
|
58
|
+
*/
|
|
8
59
|
get(index: number): Option<A>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
static from<T>(iterable: Iterable<T>): SignalArray<T>;
|
|
13
|
-
constructor(iterable: Iterable<A>);
|
|
60
|
+
/**
|
|
61
|
+
* Iterate over the contents of the array.
|
|
62
|
+
*/
|
|
14
63
|
[Symbol.iterator](): IteratorObject<A>;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* An array which behaves like a signal.
|
|
67
|
+
*
|
|
68
|
+
* Any read operation on the array, like {@link Signal.Array.get},
|
|
69
|
+
* {@link Signal.Array.size}, or iteration, acts like a
|
|
70
|
+
* {@link Signal.State.get}, registering the array as a dependency in any
|
|
71
|
+
* computed signals or effects it's used in. Correspondingly, any write
|
|
72
|
+
* operation to the array will cause all of these dependencies to update as
|
|
73
|
+
* with a {@link Signal.State.set}.
|
|
74
|
+
*
|
|
75
|
+
* Note that the API of this array is different from the built-in
|
|
76
|
+
* {@link Array}. This is intentional. Additionally, many operations you'd
|
|
77
|
+
* expect to find on an array, like {@link Array.map} or predicates like
|
|
78
|
+
* {@link Array.every}, are missing from the array itself. It's recommended
|
|
79
|
+
* that you access these through {@link Iterator}s instead.
|
|
80
|
+
*
|
|
81
|
+
* Note also that array access doesn't come with any granularity: if you read
|
|
82
|
+
* only a single index from the array inside a computed signal, *any* change to
|
|
83
|
+
* the array causes the signal to recompute, regardless of whether the value at
|
|
84
|
+
* the index you read changed.
|
|
85
|
+
*/
|
|
86
|
+
export declare class SignalArray<A> extends ReadonlySignalArray<A> {
|
|
87
|
+
/**
|
|
88
|
+
* Construct a new array with the contents of the provided iterable.
|
|
89
|
+
*/
|
|
90
|
+
static from<T>(iterable: Iterable<T>): Signal.Array<T>;
|
|
91
|
+
/**
|
|
92
|
+
* Test whether a value is a `Signal.Array`.
|
|
93
|
+
*/
|
|
94
|
+
static is(value: unknown): value is Signal.Array<unknown>;
|
|
95
|
+
/**
|
|
96
|
+
* Construct a new array, optionally filling it with the contents of the
|
|
97
|
+
* provided iterable.
|
|
98
|
+
*/
|
|
99
|
+
constructor(iterable?: Iterable<A>, options?: Signal.Options<A>);
|
|
100
|
+
/**
|
|
101
|
+
* Return a read-only view of the array.
|
|
102
|
+
*/
|
|
103
|
+
readOnly(): Signal.ReadonlyArray<A>;
|
|
104
|
+
/**
|
|
105
|
+
* Write the given value to the given index of the array, overwriting
|
|
106
|
+
* anything that may have been there before.
|
|
107
|
+
*
|
|
108
|
+
* @throws {@link TypeError} if `index` is negative or not an integer
|
|
109
|
+
*/
|
|
110
|
+
set(index: number, value: A): this;
|
|
111
|
+
/**
|
|
112
|
+
* Append the provided values to the end of the array.
|
|
113
|
+
*
|
|
114
|
+
* @returns the number of values that were inserted.
|
|
115
|
+
*/
|
|
23
116
|
push(...values: Array<A>): number;
|
|
117
|
+
/**
|
|
118
|
+
* Prepend the provided values to the start of the array.
|
|
119
|
+
*
|
|
120
|
+
* @returns the number of values that were inserted.
|
|
121
|
+
*/
|
|
24
122
|
unshift(...values: Array<A>): number;
|
|
123
|
+
/**
|
|
124
|
+
* Remove the item at the front of the array and return it.
|
|
125
|
+
*/
|
|
25
126
|
pop(): Option<A>;
|
|
127
|
+
/**
|
|
128
|
+
* Remove the item at the end of the array and return it.
|
|
129
|
+
*/
|
|
26
130
|
shift(): Option<A>;
|
|
27
|
-
|
|
131
|
+
/** @see {@link Array.splice} */
|
|
132
|
+
splice(start: number, deleteCount?: number, ...values: Array<A>): Array<A>;
|
|
133
|
+
/**
|
|
134
|
+
* Insert the given values starting at the given index, shifting the
|
|
135
|
+
* remainder of the array to higher indices accordingly.
|
|
136
|
+
*
|
|
137
|
+
* @throws {@link TypeError} if `index` is not an integer
|
|
138
|
+
*/
|
|
28
139
|
insert(index: number, ...values: Array<A>): this;
|
|
140
|
+
/**
|
|
141
|
+
* Remove the value at the given index and return it. If there's no value at
|
|
142
|
+
* the given index, return {@link None}.
|
|
143
|
+
*
|
|
144
|
+
* @throws {@link TypeError} if `index` is not an integer
|
|
145
|
+
*/
|
|
29
146
|
removeIndex(index: number): Option<A>;
|
|
147
|
+
/**
|
|
148
|
+
* Remove the first occurrence of the given value from the array, if it
|
|
149
|
+
* exists in the array.
|
|
150
|
+
*/
|
|
30
151
|
remove(value: A): Option<A>;
|
|
152
|
+
/**
|
|
153
|
+
* Remove the first value from the array that matches the given predicate
|
|
154
|
+
* function, if any.
|
|
155
|
+
*/
|
|
31
156
|
removeFn(predicate: (value: A, index: number, obj: Array<A>) => boolean): Option<A>;
|
|
157
|
+
/**
|
|
158
|
+
* Discard all values in the array, leaving an empty array.
|
|
159
|
+
*/
|
|
32
160
|
clear(): this;
|
|
33
161
|
}
|
|
162
|
+
export {};
|
package/dist/array.js
CHANGED
|
@@ -1,126 +1,286 @@
|
|
|
1
1
|
import { None, Some } from "@bodil/opt";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import * as Signal from "./signal";
|
|
3
|
+
const instance = Symbol("Signal.Array");
|
|
4
|
+
/**
|
|
5
|
+
* A read-only view of a {@link Signal.Array}.
|
|
6
|
+
*
|
|
7
|
+
* This acts just like the {@link Signal.Array} it was created from, mirroring
|
|
8
|
+
* the current contents of the source array, but without the ability to modify
|
|
9
|
+
* it.
|
|
10
|
+
*/
|
|
11
|
+
export class ReadonlySignalArray {
|
|
12
|
+
/** @ignore */
|
|
13
|
+
constructor(instanceProps) {
|
|
14
|
+
this[instance] = instanceProps;
|
|
8
15
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return Iterator.from(this.#array);
|
|
16
|
+
/**
|
|
17
|
+
* Test whether a value is a `Signal.ReadonlyArray`.
|
|
18
|
+
*/
|
|
19
|
+
static is(value) {
|
|
20
|
+
return value instanceof ReadonlySignalArray;
|
|
15
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Test whether the array is empty.
|
|
24
|
+
*/
|
|
16
25
|
isEmpty() {
|
|
17
|
-
this
|
|
18
|
-
|
|
26
|
+
const self = this[instance];
|
|
27
|
+
self.signal.get();
|
|
28
|
+
return self.array.length === 0;
|
|
19
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the size of the array.
|
|
32
|
+
*/
|
|
20
33
|
size() {
|
|
21
|
-
this
|
|
22
|
-
|
|
34
|
+
const self = this[instance];
|
|
35
|
+
self.signal.get();
|
|
36
|
+
return self.array.length;
|
|
23
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Find the index at which the given value first occurs in the array,
|
|
40
|
+
* optionally starting at `fromIndex`. If the value doesn't occur in the
|
|
41
|
+
* array, return `-1`.
|
|
42
|
+
*/
|
|
24
43
|
indexOf(value, fromIndex) {
|
|
25
|
-
this
|
|
26
|
-
|
|
44
|
+
const self = this[instance];
|
|
45
|
+
self.signal.get();
|
|
46
|
+
return self.array.indexOf(value, fromIndex);
|
|
27
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Find the first index in the array for which the `predicate` function
|
|
50
|
+
* returns true for the value at that index, or `-1` if it never does.
|
|
51
|
+
*/
|
|
28
52
|
findIndex(predicate, thisArg) {
|
|
29
|
-
this
|
|
30
|
-
|
|
53
|
+
const self = this[instance];
|
|
54
|
+
self.signal.get();
|
|
55
|
+
return self.array.findIndex(predicate, thisArg);
|
|
31
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Test whether a value is an array with identical contents to this array.
|
|
59
|
+
*/
|
|
60
|
+
equals(other) {
|
|
61
|
+
if (!ReadonlySignalArray.is(other)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const self = this[instance];
|
|
65
|
+
self.signal.get();
|
|
66
|
+
return (this.size() === other.size() &&
|
|
67
|
+
self.array.every((a, index) => Object.is(a, other.get(index).value)));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Copy the contents of this array into a normal {@link Array}.
|
|
71
|
+
*/
|
|
32
72
|
toArray() {
|
|
33
|
-
this
|
|
34
|
-
|
|
73
|
+
const self = this[instance];
|
|
74
|
+
self.signal.get();
|
|
75
|
+
return self.array.slice();
|
|
35
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the value at the given index, or {@link None} if the index is out of
|
|
79
|
+
* bounds.
|
|
80
|
+
*
|
|
81
|
+
* @throws {@link TypeError} of `index` is not an integer
|
|
82
|
+
*/
|
|
36
83
|
get(index) {
|
|
37
84
|
if (!Number.isInteger(index)) {
|
|
38
85
|
throw new TypeError(`Signal.Array.get: index ${index} is not an integer`);
|
|
39
86
|
}
|
|
40
|
-
this
|
|
41
|
-
|
|
87
|
+
const self = this[instance];
|
|
88
|
+
self.signal.get();
|
|
89
|
+
return Object.hasOwn(this, index) ? Some(self.array[index]) : None;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Iterate over the contents of the array.
|
|
93
|
+
*/
|
|
94
|
+
[Symbol.iterator]() {
|
|
95
|
+
const self = this[instance];
|
|
96
|
+
self.signal.get();
|
|
97
|
+
return Iterator.from(self.array);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* An array which behaves like a signal.
|
|
102
|
+
*
|
|
103
|
+
* Any read operation on the array, like {@link Signal.Array.get},
|
|
104
|
+
* {@link Signal.Array.size}, or iteration, acts like a
|
|
105
|
+
* {@link Signal.State.get}, registering the array as a dependency in any
|
|
106
|
+
* computed signals or effects it's used in. Correspondingly, any write
|
|
107
|
+
* operation to the array will cause all of these dependencies to update as
|
|
108
|
+
* with a {@link Signal.State.set}.
|
|
109
|
+
*
|
|
110
|
+
* Note that the API of this array is different from the built-in
|
|
111
|
+
* {@link Array}. This is intentional. Additionally, many operations you'd
|
|
112
|
+
* expect to find on an array, like {@link Array.map} or predicates like
|
|
113
|
+
* {@link Array.every}, are missing from the array itself. It's recommended
|
|
114
|
+
* that you access these through {@link Iterator}s instead.
|
|
115
|
+
*
|
|
116
|
+
* Note also that array access doesn't come with any granularity: if you read
|
|
117
|
+
* only a single index from the array inside a computed signal, *any* change to
|
|
118
|
+
* the array causes the signal to recompute, regardless of whether the value at
|
|
119
|
+
* the index you read changed.
|
|
120
|
+
*/
|
|
121
|
+
export class SignalArray extends ReadonlySignalArray {
|
|
122
|
+
/**
|
|
123
|
+
* Construct a new array with the contents of the provided iterable.
|
|
124
|
+
*/
|
|
125
|
+
static from(iterable) {
|
|
126
|
+
return new SignalArray(iterable);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Test whether a value is a `Signal.Array`.
|
|
130
|
+
*/
|
|
131
|
+
static is(value) {
|
|
132
|
+
return value instanceof SignalArray;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Construct a new array, optionally filling it with the contents of the
|
|
136
|
+
* provided iterable.
|
|
137
|
+
*/
|
|
138
|
+
constructor(iterable = [], options) {
|
|
139
|
+
super({
|
|
140
|
+
array: Array.from(iterable),
|
|
141
|
+
signal: new Signal.State(null, { equals: () => false }),
|
|
142
|
+
equals: options?.equals,
|
|
143
|
+
});
|
|
42
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Return a read-only view of the array.
|
|
147
|
+
*/
|
|
43
148
|
readOnly() {
|
|
44
|
-
return this;
|
|
149
|
+
return new ReadonlySignalArray(this[instance]);
|
|
45
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Write the given value to the given index of the array, overwriting
|
|
153
|
+
* anything that may have been there before.
|
|
154
|
+
*
|
|
155
|
+
* @throws {@link TypeError} if `index` is negative or not an integer
|
|
156
|
+
*/
|
|
46
157
|
set(index, value) {
|
|
47
158
|
if (!Number.isInteger(index)) {
|
|
48
159
|
throw new TypeError(`Signal.Array.set: index ${index} is not an integer`);
|
|
49
160
|
}
|
|
50
|
-
if (index
|
|
161
|
+
if (index < 0) {
|
|
51
162
|
throw new RangeError(`Signal.Array.set: index ${index} out of bounds`);
|
|
52
163
|
}
|
|
53
|
-
this
|
|
54
|
-
|
|
164
|
+
const self = this[instance];
|
|
165
|
+
if (!(self.equals ?? Object.is)(self.array[index], value)) {
|
|
166
|
+
self.array[index] = value;
|
|
167
|
+
self.signal.set(null);
|
|
168
|
+
}
|
|
169
|
+
return this;
|
|
55
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Append the provided values to the end of the array.
|
|
173
|
+
*
|
|
174
|
+
* @returns the number of values that were inserted.
|
|
175
|
+
*/
|
|
56
176
|
push(...values) {
|
|
57
|
-
const
|
|
58
|
-
|
|
177
|
+
const self = this[instance];
|
|
178
|
+
const result = self.array.push(...values);
|
|
179
|
+
self.signal.set(null);
|
|
59
180
|
return result;
|
|
60
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Prepend the provided values to the start of the array.
|
|
184
|
+
*
|
|
185
|
+
* @returns the number of values that were inserted.
|
|
186
|
+
*/
|
|
61
187
|
unshift(...values) {
|
|
62
|
-
const
|
|
63
|
-
|
|
188
|
+
const self = this[instance];
|
|
189
|
+
const result = self.array.unshift(...values);
|
|
190
|
+
self.signal.set(null);
|
|
64
191
|
return result;
|
|
65
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Remove the item at the front of the array and return it.
|
|
195
|
+
*/
|
|
66
196
|
pop() {
|
|
67
197
|
if (this.isEmpty()) {
|
|
68
198
|
return None;
|
|
69
199
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
200
|
+
const self = this[instance];
|
|
201
|
+
const result = self.array.pop();
|
|
202
|
+
self.signal.set(null);
|
|
72
203
|
return Some(result);
|
|
73
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Remove the item at the end of the array and return it.
|
|
207
|
+
*/
|
|
74
208
|
shift() {
|
|
75
209
|
if (this.isEmpty()) {
|
|
76
210
|
return None;
|
|
77
211
|
}
|
|
78
|
-
const
|
|
79
|
-
|
|
212
|
+
const self = this[instance];
|
|
213
|
+
const result = self.array.shift();
|
|
214
|
+
self.signal.set(null);
|
|
80
215
|
return Some(result);
|
|
81
216
|
}
|
|
217
|
+
/** @see {@link Array.splice} */
|
|
82
218
|
splice(start, deleteCount, ...values) {
|
|
83
219
|
if (!Number.isInteger(start)) {
|
|
84
|
-
throw new TypeError(`Signal.Array.splice:
|
|
220
|
+
throw new TypeError(`Signal.Array.splice: start ${start} is not an integer`);
|
|
85
221
|
}
|
|
86
|
-
if (
|
|
87
|
-
throw new
|
|
222
|
+
if (deleteCount !== undefined && !Number.isInteger(deleteCount)) {
|
|
223
|
+
throw new TypeError(`Signal.Array.splice: deleteCount ${deleteCount} is not an integer`);
|
|
88
224
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
225
|
+
const self = this[instance];
|
|
226
|
+
const result = self.array.splice(start, deleteCount, ...values);
|
|
227
|
+
self.signal.set(null);
|
|
91
228
|
return result;
|
|
92
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Insert the given values starting at the given index, shifting the
|
|
232
|
+
* remainder of the array to higher indices accordingly.
|
|
233
|
+
*
|
|
234
|
+
* @throws {@link TypeError} if `index` is not an integer
|
|
235
|
+
*/
|
|
93
236
|
insert(index, ...values) {
|
|
94
237
|
if (!Number.isInteger(index)) {
|
|
95
238
|
throw new TypeError(`Signal.Array.insert: index ${index} is not an integer`);
|
|
96
239
|
}
|
|
97
|
-
|
|
98
|
-
throw new RangeError(`Signal.Array.insert: index ${index} out of bounds`);
|
|
99
|
-
}
|
|
100
|
-
this.#array.splice(index, 0, ...values);
|
|
101
|
-
this.#signal.set(null);
|
|
240
|
+
this.splice(index, 0, ...values);
|
|
102
241
|
return this;
|
|
103
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Remove the value at the given index and return it. If there's no value at
|
|
245
|
+
* the given index, return {@link None}.
|
|
246
|
+
*
|
|
247
|
+
* @throws {@link TypeError} if `index` is not an integer
|
|
248
|
+
*/
|
|
104
249
|
removeIndex(index) {
|
|
105
250
|
if (!Number.isInteger(index)) {
|
|
106
251
|
throw new TypeError(`Signal.Array.removeIndex: index ${index} is not an integer`);
|
|
107
252
|
}
|
|
108
|
-
if (
|
|
253
|
+
if (!Object.hasOwn(this, index)) {
|
|
109
254
|
return None;
|
|
110
255
|
}
|
|
111
|
-
const
|
|
112
|
-
|
|
256
|
+
const self = this[instance];
|
|
257
|
+
const removed = self.array.splice(index, 1).pop();
|
|
258
|
+
self.signal.set(null);
|
|
113
259
|
return Some(removed);
|
|
114
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Remove the first occurrence of the given value from the array, if it
|
|
263
|
+
* exists in the array.
|
|
264
|
+
*/
|
|
115
265
|
remove(value) {
|
|
116
|
-
|
|
266
|
+
const index = this.indexOf(value);
|
|
267
|
+
return index < 0 ? None : this.removeIndex(index);
|
|
117
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Remove the first value from the array that matches the given predicate
|
|
271
|
+
* function, if any.
|
|
272
|
+
*/
|
|
118
273
|
removeFn(predicate) {
|
|
119
|
-
|
|
274
|
+
const index = this.findIndex(predicate);
|
|
275
|
+
return index < 0 ? None : this.removeIndex(index);
|
|
120
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Discard all values in the array, leaving an empty array.
|
|
279
|
+
*/
|
|
121
280
|
clear() {
|
|
122
|
-
|
|
123
|
-
|
|
281
|
+
const self = this[instance];
|
|
282
|
+
self.array = [];
|
|
283
|
+
self.signal.set(null);
|
|
124
284
|
return this;
|
|
125
285
|
}
|
|
126
286
|
}
|
package/dist/array.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,123 +3,4 @@
|
|
|
3
3
|
* Proposal](https://github.com/tc39/proposal-signals).
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
import { Signal } from "signal-polyfill";
|
|
8
|
-
import { SignalArray } from "./array";
|
|
9
|
-
interface ISignal<A> {
|
|
10
|
-
/**
|
|
11
|
-
* The current value of the signal.
|
|
12
|
-
*
|
|
13
|
-
* When this is read inside a computation function or an effect function,
|
|
14
|
-
* this signal is automatically added to the effect or computed signal as a
|
|
15
|
-
* dependency.
|
|
16
|
-
*/
|
|
17
|
-
readonly value: A;
|
|
18
|
-
/**
|
|
19
|
-
* Construct a {@link Signal.Computed} signal using a mapping function over
|
|
20
|
-
* the current value of this signal.
|
|
21
|
-
*/
|
|
22
|
-
map<B>(fn: (value: A) => B): SignalGlobal.Computed<B>;
|
|
23
|
-
/**
|
|
24
|
-
* Subscribe to changes to the value of this signal.
|
|
25
|
-
*/
|
|
26
|
-
on(callback: (value: A) => void): Disposable;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* A writable state signal.
|
|
30
|
-
*/
|
|
31
|
-
declare class StateSignal<A> extends Signal.State<A> implements ISignal<A> {
|
|
32
|
-
get value(): A;
|
|
33
|
-
set value(value: A);
|
|
34
|
-
/**
|
|
35
|
-
* Update the current value of this signal using a function.
|
|
36
|
-
*/
|
|
37
|
-
update(fn: (value: A) => A): void;
|
|
38
|
-
/**
|
|
39
|
-
* Get a read only version of this signal.
|
|
40
|
-
*/
|
|
41
|
-
readOnly(): SignalGlobal.Computed<A>;
|
|
42
|
-
map<B>(fn: (value: A) => B): SignalGlobal.Computed<B>;
|
|
43
|
-
on(callback: (value: A) => void): Disposable;
|
|
44
|
-
static is(v: unknown): v is SignalGlobal.State<unknown>;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* A read only signal computed from the values of other signals.
|
|
48
|
-
*/
|
|
49
|
-
declare class ComputedSignal<A> extends Signal.Computed<A> implements ISignal<A> {
|
|
50
|
-
get value(): A;
|
|
51
|
-
map<B>(fn: (value: A) => B): SignalGlobal.Computed<B>;
|
|
52
|
-
on(callback: (value: A) => void): Disposable;
|
|
53
|
-
static is(v: unknown): v is SignalGlobal.Computed<unknown>;
|
|
54
|
-
}
|
|
55
|
-
type SignalGlobal<A> = SignalGlobal.State<A> | SignalGlobal.Computed<A>;
|
|
56
|
-
declare const SignalGlobal: (<A>(value: A, options?: Signal.Options<A>) => SignalGlobal.State<A>) & {
|
|
57
|
-
/**
|
|
58
|
-
* Test whether the given value is a signal.
|
|
59
|
-
*/
|
|
60
|
-
is(v: unknown): v is SignalGlobal<unknown>;
|
|
61
|
-
/**
|
|
62
|
-
* Construct a new {@link Signal.Computed} signal using the provided
|
|
63
|
-
* computation function.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* const sig1 = Signal(2);
|
|
67
|
-
* const sig2 = Signal(3);
|
|
68
|
-
* const sum = Signal.computed(() => sig1.get() + sig2.get());
|
|
69
|
-
* assert(sum.get() === 5);
|
|
70
|
-
*/
|
|
71
|
-
computed<A>(fn: (this: SignalGlobal.Computed<A>) => A, options?: Signal.Options<A>): SignalGlobal.Computed<A>;
|
|
72
|
-
/**
|
|
73
|
-
* Suscribe to a signal.
|
|
74
|
-
*
|
|
75
|
-
* The provided callback will be called every time the value of the
|
|
76
|
-
* signal changes.
|
|
77
|
-
*/
|
|
78
|
-
subscribe<A>(signal: SignalGlobal<A>, callback: (value: A) => void): Disposable;
|
|
79
|
-
/**
|
|
80
|
-
* Create an effect responding to signal changes.
|
|
81
|
-
*
|
|
82
|
-
* The provided function will be called immediately, and again every
|
|
83
|
-
* time a signal that was read by the function changes.
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* const sig = Signal("Hello Joe!");
|
|
87
|
-
* effect(() => console.log("Signal value is:", sig.get()));
|
|
88
|
-
* // prints "Signal value is: Hello Joe!"
|
|
89
|
-
* sig.set("Hello Mike!");
|
|
90
|
-
* // prints "Signal value is: Hello Mike!"
|
|
91
|
-
*/
|
|
92
|
-
effect(fn: () => Disposifiable | void): Disposable;
|
|
93
|
-
/**
|
|
94
|
-
* Construct a new {@link Signal.Computed} signal using an async
|
|
95
|
-
* computation function.
|
|
96
|
-
*
|
|
97
|
-
* This returns a promise which will resolve to a
|
|
98
|
-
* {@link Signal.Computed} signal once the promise returned by the
|
|
99
|
-
* computation function resolves, and will update itself whenever
|
|
100
|
-
* subsequent calls to the computation function resolve.
|
|
101
|
-
*
|
|
102
|
-
* The function is provided with an {@link AbortSignal} which any async
|
|
103
|
-
* jobs started from it should abide by. If a signal dependency changes
|
|
104
|
-
* while the job is running, the {@link AbortSignal} will be triggered
|
|
105
|
-
* and the job restarted.
|
|
106
|
-
*/
|
|
107
|
-
asyncComputed<A>(fn: (abort: AbortSignal) => Promise<A>, options?: Signal.Options<A>): Promise<SignalGlobal.Computed<A>>;
|
|
108
|
-
array<A>(values: Iterable<A>): SignalArray<A>;
|
|
109
|
-
State: typeof StateSignal;
|
|
110
|
-
Computed: typeof ComputedSignal;
|
|
111
|
-
Array: typeof SignalArray;
|
|
112
|
-
subtle: typeof Signal.subtle;
|
|
113
|
-
};
|
|
114
|
-
declare namespace SignalGlobal {
|
|
115
|
-
/** @interface */
|
|
116
|
-
type State<A> = StateSignal<A>;
|
|
117
|
-
/** @interface */
|
|
118
|
-
type Computed<A> = ComputedSignal<A>;
|
|
119
|
-
type Array<A> = SignalArray<A>;
|
|
120
|
-
type Options<A> = Signal.Options<A>;
|
|
121
|
-
namespace subtle {
|
|
122
|
-
type Watcher = Signal.subtle.Watcher;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
export { SignalGlobal as Signal };
|
|
6
|
+
export * as Signal from "./signal";
|