preact-sigma 2.0.1 → 2.1.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/README.md +1 -0
- package/dist/index.d.mts +17 -7
- package/dist/index.mjs +8 -1
- package/llms.txt +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -164,5 +164,6 @@ In Preact, the same constructor can be used with `useSigma(() => new TodoList(),
|
|
|
164
164
|
- Use `computed(...)` for argument-free derived state, and use queries for reactive reads that need parameters.
|
|
165
165
|
- Put writes in actions. A draft boundary is any point where sigma cannot keep reusing the current draft. `emit()`, `await`, and any action call other than a same-instance sync nested action call are draft boundaries, so call `this.commit()` before those boundaries when pending writes should become public.
|
|
166
166
|
- Use `snapshot(instance)` and `replaceState(instance, snapshot)` for committed-state replay. They work on top-level state keys and stay outside action semantics.
|
|
167
|
+
- Use `ref(value)` when a value should stay by reference in sigma's `Draft` and `Immutable` types. It only changes typing and does not change Immer's runtime drafting or freezing behavior.
|
|
167
168
|
- Use `immerable` on custom classes only when they should participate in Immer drafting. `setAutoFreeze(false)` disables sigma's runtime deep-freezing when you need published state to stay unfrozen.
|
|
168
169
|
- Use `setup(...)` for owned side effects, and always return cleanup resources for anything the instance starts.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { ReadonlySignal, action, batch, computed, effect, untracked } from "@preact/signals";
|
|
2
2
|
import { Patch, freeze, immerable } from "immer";
|
|
3
3
|
|
|
4
|
+
//#region src/internal/symbols.d.ts
|
|
5
|
+
declare const sigmaStateBrand: unique symbol;
|
|
6
|
+
declare const sigmaEventsBrand: unique symbol;
|
|
7
|
+
declare const sigmaRefBrand: unique symbol;
|
|
8
|
+
//#endregion
|
|
4
9
|
//#region src/immer.d.ts
|
|
5
10
|
type PrimitiveType = number | string | boolean;
|
|
6
11
|
/** Object types that should never be mapped */
|
|
@@ -18,6 +23,7 @@ type IfAvailable<T, Fallback = void> = true | false extends (T extends never ? t
|
|
|
18
23
|
* Set
|
|
19
24
|
*/
|
|
20
25
|
type WeakReferences = IfAvailable<WeakMap<any, any>> | IfAvailable<WeakSet<any>>;
|
|
26
|
+
type HasSigmaRefBrand<T> = [T] extends [object] ? typeof sigmaRefBrand extends keyof T ? true : false : false;
|
|
21
27
|
type WritableDraft<T> = T extends any[] ? number extends T["length"] ? Draft<T[number]>[] : WritableNonArrayDraft<T> : WritableNonArrayDraft<T>;
|
|
22
28
|
type WritableNonArrayDraft<T> = { -readonly [K in keyof T]: T[K] extends infer V ? (V extends object ? Draft<V> : V) : never };
|
|
23
29
|
/**
|
|
@@ -25,17 +31,13 @@ type WritableNonArrayDraft<T> = { -readonly [K in keyof T]: T[K] extends infer V
|
|
|
25
31
|
*
|
|
26
32
|
* Use this instead of `immer.Draft`
|
|
27
33
|
*/
|
|
28
|
-
type Draft<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap<infer K, infer V> ? Map<Draft<K>, Draft<V>> : T extends ReadonlySet<infer V> ? Set<Draft<V>> : T extends WeakReferences ? T : T extends object ? WritableDraft<T> : T;
|
|
34
|
+
type Draft<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : HasSigmaRefBrand<T> extends true ? T : T extends ReadonlyMap<infer K, infer V> ? Map<Draft<K>, Draft<V>> : T extends ReadonlySet<infer V> ? Set<Draft<V>> : T extends WeakReferences ? T : T extends object ? WritableDraft<T> : T;
|
|
29
35
|
/**
|
|
30
36
|
* Convert a mutable type into a readonly type.
|
|
31
37
|
*
|
|
32
38
|
* Use this instead of `immer.Immutable`
|
|
33
39
|
*/
|
|
34
|
-
type Immutable<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> : T extends ReadonlySet<infer V> ? ReadonlySet<Immutable<V>> : T extends WeakReferences ? T : T extends object ? { readonly [K in keyof T]: Immutable<T[K]> } : T;
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/internal/symbols.d.ts
|
|
37
|
-
declare const sigmaStateBrand: unique symbol;
|
|
38
|
-
declare const sigmaEventsBrand: unique symbol;
|
|
40
|
+
type Immutable<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : HasSigmaRefBrand<T> extends true ? T : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> : T extends ReadonlySet<infer V> ? ReadonlySet<Immutable<V>> : T extends WeakReferences ? T : T extends object ? { readonly [K in keyof T]: Immutable<T[K]> } : T;
|
|
39
41
|
//#endregion
|
|
40
42
|
//#region src/internal/types.d.ts
|
|
41
43
|
type AnyFunction = (...args: any[]) => any;
|
|
@@ -45,6 +47,7 @@ type DefaultStateValue<TValue> = TValue | DefaultStateInitializer<TValue>;
|
|
|
45
47
|
type Disposable = {
|
|
46
48
|
[Symbol.dispose](): void;
|
|
47
49
|
};
|
|
50
|
+
/** A type brand added by `ref(...)`. */
|
|
48
51
|
/** The event map shape used by sigma types. */
|
|
49
52
|
type AnyEvents = Record<string, object | void>;
|
|
50
53
|
/** The top-level state object shape used by sigma types. */
|
|
@@ -143,6 +146,13 @@ declare function replaceState<T extends AnySigmaState>(publicInstance: T, nextSt
|
|
|
143
146
|
//#region src/framework.d.ts
|
|
144
147
|
/** Checks whether a value is a sigma-state instance. */
|
|
145
148
|
declare function isSigmaState(value: unknown): value is AnySigmaState;
|
|
149
|
+
/**
|
|
150
|
+
* Returns `value` unchanged and marks its type so sigma's Draft and Immutable
|
|
151
|
+
* helpers keep it by reference instead of recursively immerizing it.
|
|
152
|
+
*/
|
|
153
|
+
declare function ref<T extends object>(value: T): T & {
|
|
154
|
+
[sigmaRefBrand]?: true;
|
|
155
|
+
};
|
|
146
156
|
/** Creates a standalone tracked query function with the same signature as `fn`. */
|
|
147
157
|
declare function query<TArgs extends any[], TResult>(fn: (this: void, ...args: TArgs) => TResult): typeof fn;
|
|
148
158
|
/**
|
|
@@ -226,4 +236,4 @@ declare function useSigma<T extends AnySigmaState>(create: () => T, setupArgs?:
|
|
|
226
236
|
/** Attaches an event listener in a component and cleans it up when dependencies change. */
|
|
227
237
|
declare function useListener<TTarget extends EventTarget | AnySigmaState, TEvent extends InferEventType<TTarget>>(target: TTarget | null, name: TEvent, listener: InferListener<TTarget, TEvent>): void;
|
|
228
238
|
//#endregion
|
|
229
|
-
export { type AnyDefaultState, type AnyEvents, type AnyResource, type AnySigmaState, type AnySigmaStateWithEvents, type AnyState, InferEventType, InferListener, type InferSetupArgs, type SigmaObserveChange, type SigmaObserveOptions, type SigmaState, SigmaType, action, batch, computed, effect, freeze, immerable, isSigmaState, listen, query, replaceState, setAutoFreeze, snapshot, untracked, useListener, useSigma };
|
|
239
|
+
export { type AnyDefaultState, type AnyEvents, type AnyResource, type AnySigmaState, type AnySigmaStateWithEvents, type AnyState, InferEventType, InferListener, type InferSetupArgs, type SigmaObserveChange, type SigmaObserveOptions, type SigmaState, SigmaType, action, batch, computed, effect, freeze, immerable, isSigmaState, listen, query, ref, replaceState, setAutoFreeze, snapshot, untracked, useListener, useSigma };
|
package/dist/index.mjs
CHANGED
|
@@ -520,6 +520,13 @@ Object.defineProperty(Sigma.prototype, sigmaStateBrand, { value: true });
|
|
|
520
520
|
function isSigmaState(value) {
|
|
521
521
|
return Boolean(value && typeof value === "object" && value[sigmaStateBrand]);
|
|
522
522
|
}
|
|
523
|
+
/**
|
|
524
|
+
* Returns `value` unchanged and marks its type so sigma's Draft and Immutable
|
|
525
|
+
* helpers keep it by reference instead of recursively immerizing it.
|
|
526
|
+
*/
|
|
527
|
+
function ref(value) {
|
|
528
|
+
return value;
|
|
529
|
+
}
|
|
523
530
|
/** Creates a standalone tracked query function with the same signature as `fn`. */
|
|
524
531
|
function query(fn) {
|
|
525
532
|
return ((...args) => computed$1(() => fn(...args)).value);
|
|
@@ -626,4 +633,4 @@ function useListener(target, name, listener) {
|
|
|
626
633
|
}, [target, name]);
|
|
627
634
|
}
|
|
628
635
|
//#endregion
|
|
629
|
-
export { SigmaType, action, batch, computed, effect, freeze, immerable, isSigmaState, listen, query, replaceState, setAutoFreeze, snapshot, untracked, useListener, useSigma };
|
|
636
|
+
export { SigmaType, action, batch, computed, effect, freeze, immerable, isSigmaState, listen, query, ref, replaceState, setAutoFreeze, snapshot, untracked, useListener, useSigma };
|
package/llms.txt
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- `state property`: A top-level property from `TState`, such as `draft` in `{ draft: string }`.
|
|
8
8
|
- `computed`: A tracked getter declared with `.computed({ ... })`.
|
|
9
9
|
- `query`: A tracked method declared with `.queries({ ... })` or created with `query(fn)`.
|
|
10
|
+
- `ref`: A helper that keeps a value by reference in sigma's `Draft` and `Immutable` types without changing runtime behavior.
|
|
10
11
|
- `action`: A method declared with `.actions({ ... })` that reads and writes through one Immer draft for one synchronous call.
|
|
11
12
|
- `draft boundary`: Any point where sigma cannot keep reusing the current draft.
|
|
12
13
|
- `setup handler`: A function declared with `.setup(fn)` that returns an array of cleanup resources.
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
|
|
18
19
|
- For state shape, inference, and instance shape, read `Start Here`, `Inference`, `SigmaType`, and `Public Instance Shape`.
|
|
19
20
|
- For mutation semantics, read `Critical Rules`, `actions`, `immerable`, and `setAutoFreeze`.
|
|
21
|
+
- For type-level by-reference values, read `ref`.
|
|
20
22
|
- For side effects and events, read `setup`, `Events`, `listen`, `useListener`, and `useSigma`.
|
|
21
23
|
- For committed-state utilities, read `observe`, `snapshot`, and `replaceState`.
|
|
22
24
|
|
|
@@ -60,6 +62,7 @@ import {
|
|
|
60
62
|
isSigmaState,
|
|
61
63
|
listen,
|
|
62
64
|
query,
|
|
65
|
+
ref,
|
|
63
66
|
replaceState,
|
|
64
67
|
setAutoFreeze,
|
|
65
68
|
snapshot,
|
|
@@ -325,6 +328,17 @@ Behavior:
|
|
|
325
328
|
- custom class instances without a true `[immerable]` property stay outside that freeze path
|
|
326
329
|
- plain objects, arrays, `Map`, and `Set` already participate in normal Immer drafting without extra markers
|
|
327
330
|
|
|
331
|
+
## `ref(value)`
|
|
332
|
+
|
|
333
|
+
`ref(value)` returns `value` unchanged and marks its type so sigma's `Draft` and `Immutable` helpers keep that value by reference.
|
|
334
|
+
|
|
335
|
+
Behavior:
|
|
336
|
+
|
|
337
|
+
- it has no runtime effect
|
|
338
|
+
- it only changes sigma's local `Draft` and `Immutable` typing
|
|
339
|
+
- it prevents type-level recursive immerization for that value
|
|
340
|
+
- it does not change whether Immer drafts or freezes the value at runtime
|
|
341
|
+
|
|
328
342
|
## `query(fn)`
|
|
329
343
|
|
|
330
344
|
`query(fn)` creates a standalone tracked query helper.
|