synstate 6.1.1 → 6.2.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/README.md +2 -2
- package/dist/core/authoring.d.mts +3 -3
- package/dist/core/class/child-observable-class.d.mts +24 -25
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +41 -42
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/create-child-observable.d.mts +27 -29
- package/dist/core/class/create-child-observable.d.mts.map +1 -1
- package/dist/core/class/create-child-observable.mjs.map +1 -1
- package/dist/core/class/create-root-observable.d.mts +11 -11
- package/dist/core/class/manager-observable-class.d.mts +6 -6
- package/dist/core/class/manager-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +29 -31
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +0 -2
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/observable-node.d.mts +3 -4
- package/dist/core/class/observable-node.d.mts.map +1 -1
- package/dist/core/class/observable-node.mjs +0 -1
- package/dist/core/class/observable-node.mjs.map +1 -1
- package/dist/core/class/propagation-state.d.mts +6 -8
- package/dist/core/class/propagation-state.d.mts.map +1 -1
- package/dist/core/class/propagation-state.mjs +0 -2
- package/dist/core/class/propagation-state.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts +4 -4
- package/dist/core/combine/derive.d.mts +7 -8
- package/dist/core/combine/derive.d.mts.map +1 -1
- package/dist/core/combine/derive.mjs +0 -1
- package/dist/core/combine/derive.mjs.map +1 -1
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +3 -3
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts +3 -3
- package/dist/core/create/counter.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs.map +1 -1
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/keep-equal-parts.d.mts +14 -15
- package/dist/core/operators/keep-equal-parts.d.mts.map +1 -1
- package/dist/core/operators/keep-equal-parts.mjs +0 -1
- package/dist/core/operators/keep-equal-parts.mjs.map +1 -1
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +3 -3
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/take.mjs.map +1 -1
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
- package/dist/core/predefined/operators/map-to.d.mts +3 -4
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-to.mjs +0 -1
- package/dist/core/predefined/operators/map-to.mjs.map +1 -1
- package/dist/core/scope/scope.d.mts +4 -4
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-family.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +5 -5
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/utils/current-scope.d.mts +6 -6
- package/dist/core/utils/id-maker.d.mts +2 -2
- package/dist/core/utils/observable-brand.d.mts +5 -5
- package/dist/utils/create-boolean-state.d.mts +2 -2
- package/dist/utils/create-reducer.d.mts +18 -18
- package/dist/utils/create-state.d.mts +2 -2
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/state-source.d.mts +3 -3
- package/package.json +9 -9
- package/src/core/authoring.mts +3 -3
- package/src/core/class/child-observable-class.mts +86 -87
- package/src/core/class/circular-dependency-comparison.test.mts +2 -2
- package/src/core/class/create-child-observable.mts +27 -29
- package/src/core/class/create-root-observable.mts +11 -11
- package/src/core/class/manager-observable-class.mts +12 -12
- package/src/core/class/observable-base-class.mts +33 -35
- package/src/core/class/observable-node.mts +3 -4
- package/src/core/class/propagation-state.mts +26 -28
- package/src/core/class/remove-completed.test.mts +2 -2
- package/src/core/class/root-observable-class.mts +9 -9
- package/src/core/class/unobserved-write.test.mts +4 -4
- package/src/core/combine/derive.mts +10 -11
- package/src/core/combine/merge.mts +2 -2
- package/src/core/combine/zip.mts +7 -7
- package/src/core/create/counter.mts +5 -5
- package/src/core/create/from-abortable-promise.mts +2 -2
- package/src/core/create/from-promise.mts +2 -2
- package/src/core/create/from-subscribable.mts +2 -2
- package/src/core/create/source.mts +5 -5
- package/src/core/create/timer.mts +2 -2
- package/src/core/operators/audit.mts +2 -2
- package/src/core/operators/debounce.mts +2 -2
- package/src/core/operators/filter.mts +4 -4
- package/src/core/operators/keep-equal-parts.mts +16 -17
- package/src/core/operators/map.mts +2 -2
- package/src/core/operators/merge-map.mts +5 -5
- package/src/core/operators/pairwise.mts +4 -4
- package/src/core/operators/scan.mts +2 -2
- package/src/core/operators/skip-if-no-change.mts +4 -4
- package/src/core/operators/skip-until.mts +4 -4
- package/src/core/operators/skip-while.mts +2 -2
- package/src/core/operators/switch-map.mts +5 -5
- package/src/core/operators/take-until.mts +2 -2
- package/src/core/operators/take-while.mts +2 -2
- package/src/core/operators/take.mts +2 -2
- package/src/core/operators/throttle.mts +2 -2
- package/src/core/operators/with-buffered-from.mts +2 -2
- package/src/core/operators/with-current-value-from.mts +2 -2
- package/src/core/operators/with-initial-value.mts +2 -2
- package/src/core/predefined/operators/attach-index.mts +2 -2
- package/src/core/predefined/operators/map-to.mts +3 -4
- package/src/core/scope/scope.mts +6 -6
- package/src/core/types/observable-family.mts +4 -5
- package/src/core/types/observable.mts +7 -7
- package/src/core/utils/current-scope.mts +8 -8
- package/src/core/utils/id-maker.mts +2 -2
- package/src/core/utils/observable-brand.mts +5 -5
- package/src/utils/create-boolean-state.mts +2 -2
- package/src/utils/create-reducer.mts +18 -18
- package/src/utils/create-state.mts +4 -4
- package/src/utils/create-state.test.mts +2 -2
- package/src/utils/state-source.mts +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Sumi bans classes, `this`, method syntax and writes to `this` outside a
|
|
2
|
-
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
|
|
3
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -4,10 +4,9 @@ import type { KeepInitialValueOperator } from '../../types/index.mjs';
|
|
|
4
4
|
/**
|
|
5
5
|
* Maps all emitted values to a constant value, ignoring the source values.
|
|
6
6
|
* Emits on every source value although the value never changes — where
|
|
7
|
-
* `map(() => value)` would stop every result after the first as equal — so
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `'reset'`, not `string`.
|
|
7
|
+
* `map(() => value)` would stop every result after the first as equal — so it
|
|
8
|
+
* is the one for turning events into a value. The value's type is inferred as
|
|
9
|
+
* written, as with `as const`: `mapTo('reset')` gives `'reset'`, not `string`.
|
|
11
10
|
*
|
|
12
11
|
* @template A - The type of values from the source
|
|
13
12
|
* @template B - The type of the constant value
|
package/src/core/scope/scope.mts
CHANGED
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
* disposed gives a scope that is born disposed, with a warning.
|
|
24
24
|
*
|
|
25
25
|
* Intended for authors of libraries built on synstate rather than for
|
|
26
|
-
* application code; state defined at module level belongs to no scope and
|
|
27
|
-
*
|
|
26
|
+
* application code; state defined at module level belongs to no scope and lives
|
|
27
|
+
* as long as the page.
|
|
28
28
|
*
|
|
29
29
|
* `run` and `dispose` read the scope they are called on, so call them on it
|
|
30
30
|
* (`scope.dispose()`) rather than taking them off it.
|
|
@@ -50,8 +50,8 @@ export const getCurrentScope = (): Scope | undefined =>
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Registers `cleanup` to be called when the current scope is disposed. Cleanups
|
|
53
|
-
* run after the child scopes are disposed and before the owned observables
|
|
54
|
-
*
|
|
53
|
+
* run after the child scopes are disposed and before the owned observables are,
|
|
54
|
+
* newest first.
|
|
55
55
|
*
|
|
56
56
|
* Outside every scope it warns and registers nothing.
|
|
57
57
|
*
|
|
@@ -85,8 +85,8 @@ export const untracked = <R,>(body: () => R): R =>
|
|
|
85
85
|
* A scope is created for every row and branch of a UI, so creating one has to
|
|
86
86
|
* be cheap. It used to be a set of closures with a `Set` of children, a `Set`
|
|
87
87
|
* of owned observables and a record in a `WeakMap`; it is now one object whose
|
|
88
|
-
* methods live on the prototype and whose lists are arrays made when the
|
|
89
|
-
*
|
|
88
|
+
* methods live on the prototype and whose lists are arrays made when the first
|
|
89
|
+
* entry arrives.
|
|
90
90
|
*
|
|
91
91
|
* Whatever leaves a list on its own (a child scope disposed by itself, an
|
|
92
92
|
* observable that completed) is not looked up and spliced out: it only counts
|
|
@@ -65,11 +65,10 @@ export type ScanOperatorObservable<A, B> = InitializedSyncChildObservable<
|
|
|
65
65
|
|
|
66
66
|
// SyncChildObservable
|
|
67
67
|
|
|
68
|
-
// The helpers stay in a namespace so their names do not crowd the module
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
// they check.
|
|
68
|
+
// The helpers stay in a namespace so their names do not crowd the module scope.
|
|
69
|
+
// A namespace holding only types is erasable, so it passes `erasableSyntaxOnly`
|
|
70
|
+
// (TS1294); the `expectType` assertions are call statements, which is why they
|
|
71
|
+
// sit below it rather than beside the types they check.
|
|
73
72
|
namespace SynStateInternals {
|
|
74
73
|
type Cast<A> = A extends NonEmptyUnknownList ? A : never;
|
|
75
74
|
|
|
@@ -32,8 +32,8 @@ type CreateObservableType<A, Kind extends ObservableKind> = Readonly<{
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* One more than the deepest observable this one is derived from; 0 for a
|
|
35
|
-
* root. An update reaches observables in ascending depth, so every parent
|
|
36
|
-
*
|
|
35
|
+
* root. An update reaches observables in ascending depth, so every parent has
|
|
36
|
+
* emitted before its child reads it.
|
|
37
37
|
*/
|
|
38
38
|
depth: Kind extends 'root' ? 0 : number;
|
|
39
39
|
|
|
@@ -173,9 +173,9 @@ export type Operator<A, B> =
|
|
|
173
173
|
| KeepInitialValueOperator<A, B>;
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
|
-
* Tells an observable made by synstate from any other value, by the brand
|
|
177
|
-
*
|
|
178
|
-
*
|
|
176
|
+
* Tells an observable made by synstate from any other value, by the brand every
|
|
177
|
+
* observable carries. Checking for a `subscribe` method instead would also
|
|
178
|
+
* accept plain values that happen to have one.
|
|
179
179
|
*
|
|
180
180
|
* @example
|
|
181
181
|
*
|
|
@@ -223,8 +223,8 @@ export type WrapInitialized<A extends readonly unknown[]> = Readonly<{
|
|
|
223
223
|
// type GetDestTypeOfOperator<Op extends Operator<unknown, unknown>> =
|
|
224
224
|
// Op extends Operator<unknown, infer B> ? B : never;
|
|
225
225
|
|
|
226
|
-
// Only the members meant for users are public; the rest live on the
|
|
227
|
-
//
|
|
226
|
+
// Only the members meant for users are public; the rest live on the internal
|
|
227
|
+
// node types in `core/class` (#2117).
|
|
228
228
|
expectType<
|
|
229
229
|
keyof Observable<unknown>,
|
|
230
230
|
| typeof observableBrand
|
|
@@ -7,10 +7,10 @@ export type ScopeMember = Readonly<{
|
|
|
7
7
|
}>;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* The side of a scope the rest of the core talks to, on top of its public
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* The side of a scope the rest of the core talks to, on top of its public face
|
|
11
|
+
* {@link Scope}. Kept out of the public API (`core/utils/**` is excluded from
|
|
12
|
+
* index generation), so that only `createScope` and its siblings decide what a
|
|
13
|
+
* scope owns.
|
|
14
14
|
*/
|
|
15
15
|
export type ScopeInternals = Scope &
|
|
16
16
|
Readonly<{
|
|
@@ -18,8 +18,8 @@ export type ScopeInternals = Scope &
|
|
|
18
18
|
adopt: (node: ScopeMember) => void;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Tells the scope that one of the nodes it adopted completed on its own,
|
|
22
|
-
*
|
|
21
|
+
* Tells the scope that one of the nodes it adopted completed on its own, so
|
|
22
|
+
* that the scope can drop it and keep no reference to it. The node is
|
|
23
23
|
* completed (`isCompleted`) by the time it calls this.
|
|
24
24
|
*/
|
|
25
25
|
release: () => void;
|
|
@@ -28,8 +28,8 @@ export type ScopeInternals = Scope &
|
|
|
28
28
|
}>;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* The scope whose `run` is executing. A field rather than a module-level
|
|
32
|
-
*
|
|
31
|
+
* The scope whose `run` is executing. A field rather than a module-level `let`,
|
|
32
|
+
* so that the one place writing it is visibly this object.
|
|
33
33
|
*/
|
|
34
34
|
const mut_slot: { current: ScopeInternals | undefined } = {
|
|
35
35
|
current: undefined,
|
|
@@ -12,8 +12,8 @@ export const notUpdatedYet: UpdateToken =
|
|
|
12
12
|
/**
|
|
13
13
|
* Issues the token of a write that opens no update, because nothing observes
|
|
14
14
|
* the observable written to (`setNextIfUnobserved`). Nothing is ever queued
|
|
15
|
-
* with it, so it is a token and not a queue, unlike the tokens
|
|
16
|
-
*
|
|
15
|
+
* with it, so it is a token and not a queue, unlike the tokens `openUpdate`
|
|
16
|
+
* issues.
|
|
17
17
|
*/
|
|
18
18
|
export const issueUnqueuedToken = (): UpdateToken =>
|
|
19
19
|
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The key every observable carries, set to `true` by `assembleObservable`. It
|
|
3
|
-
* lets `isObservable` tell an observable from any other value at run time —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* lets `isObservable` tell an observable from any other value at run time — a
|
|
4
|
+
* `subscribe` method is not enough, since plain values may have one — and, as a
|
|
5
|
+
* type, makes the public observable types impossible to satisfy with an object
|
|
6
|
+
* literal: an imitation passed to an operator would lack the internal members
|
|
7
|
+
* propagation reads and fail at run time instead of at compile time.
|
|
8
8
|
*
|
|
9
9
|
* `Symbol.for`, so that an observable made by another copy of synstate in the
|
|
10
10
|
* same program is still recognized.
|
|
@@ -18,8 +18,8 @@ import { createState } from './create-state.mjs';
|
|
|
18
18
|
* import { useObservableValue } from 'synstate-react-hooks';
|
|
19
19
|
*
|
|
20
20
|
* // Menu drawer open/close state.
|
|
21
|
-
* // setTrue and setFalse can be passed directly as callbacks
|
|
22
|
-
* //
|
|
21
|
+
* // setTrue and setFalse can be passed directly as callbacks — no need to
|
|
22
|
+
* // create wrapper functions like `() => setState(true)`.
|
|
23
23
|
* const [menuOpen$, { setTrue: openMenu, setFalse: closeMenu }] =
|
|
24
24
|
* createBooleanState(false);
|
|
25
25
|
*
|
|
@@ -111,18 +111,18 @@ export const createReducer = <S, A>(
|
|
|
111
111
|
*/
|
|
112
112
|
export type StateOptions<S> = Readonly<{
|
|
113
113
|
/**
|
|
114
|
-
* Whether the next state is the same as the current one. When it says so,
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* identity: `setState` and the like return the current state rather than
|
|
118
|
-
*
|
|
114
|
+
* Whether the next state is the same as the current one. When it says so, the
|
|
115
|
+
* update is not passed on — no subscriber, and nothing derived from the
|
|
116
|
+
* state, is told of it — and the current state is kept, along with its
|
|
117
|
+
* identity: `setState` and the like return the current state rather than the
|
|
118
|
+
* next.
|
|
119
119
|
*
|
|
120
120
|
* Decide here, where the state is held, rather than downstream with
|
|
121
|
-
* `skipIfNoChange`: an update passed on here reaches whatever reads the
|
|
122
|
-
*
|
|
121
|
+
* `skipIfNoChange`: an update passed on here reaches whatever reads the state
|
|
122
|
+
* directly before any operator can thin it out.
|
|
123
123
|
*
|
|
124
|
-
* Defaults to `Object.is`, so writing the value already held passes
|
|
125
|
-
*
|
|
124
|
+
* Defaults to `Object.is`, so writing the value already held passes nothing
|
|
125
|
+
* on. Pass `() => false` to pass on every update, equal or not.
|
|
126
126
|
*
|
|
127
127
|
* @param current - The state held now
|
|
128
128
|
* @param next - The state the update would set
|
|
@@ -132,8 +132,8 @@ export type StateOptions<S> = Readonly<{
|
|
|
132
132
|
/**
|
|
133
133
|
* Whether an update keeps the parts of the state it did not change. With
|
|
134
134
|
* `true`, the next state is compared with the current one before it is
|
|
135
|
-
* written, and every part of it deeply equal to the same part of the
|
|
136
|
-
*
|
|
135
|
+
* written, and every part of it deeply equal to the same part of the current
|
|
136
|
+
* state is replaced by that part (`replaceEqualDeep` of
|
|
137
137
|
* ts-data-forge): a reader of an unchanged part keeps the object it has, so
|
|
138
138
|
* `map`, comparing with `Object.is`, stops there. When the whole next state is
|
|
139
139
|
* deeply equal, the current state is kept and nothing is passed on, so
|
|
@@ -146,14 +146,14 @@ export type StateOptions<S> = Readonly<{
|
|
|
146
146
|
* arrays are walked into; a `Map`, a `Set`, a `Date` or a class instance is
|
|
147
147
|
* compared and kept whole.
|
|
148
148
|
*
|
|
149
|
-
* Prefer this over `keepEqualParts()` downstream: keeping the parts where
|
|
150
|
-
*
|
|
151
|
-
*
|
|
149
|
+
* Prefer this over `keepEqualParts()` downstream: keeping the parts where the
|
|
150
|
+
* state is written means no update with nothing in it is passed on at all,
|
|
151
|
+
* and nothing downstream has anything to undo.
|
|
152
152
|
*
|
|
153
|
-
* Defaults to `false`: the next state is written as given. With it on,
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
153
|
+
* Defaults to `false`: the next state is written as given. With it on, each
|
|
154
|
+
* update compares deeply every part of the next state that is not the very
|
|
155
|
+
* object of the current one; a state whose updates already keep what they do
|
|
156
|
+
* not change, as `{ ...prev, x }` does, gains nothing from it.
|
|
157
157
|
*/
|
|
158
158
|
keepEqualParts?: boolean | ReplaceEqualDeepOptions;
|
|
159
159
|
}>;
|
|
@@ -107,8 +107,8 @@ import { createStateSource } from './state-source.mjs';
|
|
|
107
107
|
*
|
|
108
108
|
* assert.strictEqual(report.getSnapshot().value, held);
|
|
109
109
|
*
|
|
110
|
-
* // An edited title: a new report and a new array, while the summary is
|
|
111
|
-
* //
|
|
110
|
+
* // An edited title: a new report and a new array, while the summary is the
|
|
111
|
+
* // one held, so `summary` is not told of it.
|
|
112
112
|
* setReport({
|
|
113
113
|
* summary: { open: 1 },
|
|
114
114
|
* pulls: [{ number: 1, title: 'one (edited)' }],
|
|
@@ -146,8 +146,8 @@ export const createState = <S,>(
|
|
|
146
146
|
options,
|
|
147
147
|
);
|
|
148
148
|
|
|
149
|
-
// Each compares with the state the write started from, as `dispatch`
|
|
150
|
-
//
|
|
149
|
+
// Each compares with the state the write started from, as `dispatch` does,
|
|
150
|
+
// and builds nothing on the way.
|
|
151
151
|
const updateState = (updateFn: (prev: S) => S): S => {
|
|
152
152
|
const currentState = getSnapshot();
|
|
153
153
|
|
|
@@ -54,8 +54,8 @@ describe(createState, () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
// What `equals` is for: whatever reads the state, directly or through
|
|
57
|
-
// anything derived from it, is told only of a real change, and an equal
|
|
58
|
-
//
|
|
57
|
+
// anything derived from it, is told only of a real change, and an equal value
|
|
58
|
+
// written over the current one leaves the object that is there.
|
|
59
59
|
test('keeps the current object when `equals` finds the next one equal to it', () => {
|
|
60
60
|
const [state, setState, { getSnapshot }] = createState<readonly number[]>(
|
|
61
61
|
[1, 2],
|
|
@@ -3,9 +3,9 @@ import { source, type InitializedSourceObservable } from '../core/index.mjs';
|
|
|
3
3
|
import type { StateOptions } from './create-reducer.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* What `createState` and `createReducer` are both built on: the source
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* What `createState` and `createReducer` are both built on: the source holding
|
|
7
|
+
* the state, its current value, and `commit`, the one way either writes it.
|
|
8
|
+
* `commit` writes `reduced` unless `equals` finds it the same as
|
|
9
9
|
* `currentState`, after keeping the parts of `currentState` it did not change
|
|
10
10
|
* when `keepEqualParts` asks for that, and returns the state written, or
|
|
11
11
|
* `currentState` when nothing was.
|