@cplieger/reactive 1.1.0 → 1.2.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/LICENSE CHANGED
@@ -689,4 +689,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
689
689
  GNU General Public License for more details.
690
690
 
691
691
  You should have received a copy of the GNU General Public License
692
- along with this program. If not, see <https://www.gnu.org/licenses/>.
692
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
package/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # reactive
2
2
 
3
- [![CI](https://github.com/cplieger/reactive/actions/workflows/ci.yaml/badge.svg)](https://github.com/cplieger/reactive/actions/workflows/ci.yaml)
4
3
  [![npm](https://img.shields.io/npm/v/@cplieger/reactive)](https://www.npmjs.com/package/@cplieger/reactive)
5
4
  [![JSR](https://jsr.io/badges/@cplieger/reactive)](https://jsr.io/@cplieger/reactive)
6
- [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](LICENSE)
5
+ [![Test coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cplieger/reactive/badges/coverage.json)](https://github.com/cplieger/reactive/actions/workflows/coverage.yml)
6
+ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13218/badge)](https://www.bestpractices.dev/projects/13218)
7
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/cplieger/reactive/badge)](https://scorecard.dev/viewer/?uri=github.com/cplieger/reactive)
7
8
 
8
9
  > Signals + collections + DOM-reconciliation micro-framework for TypeScript
9
10
 
@@ -73,7 +74,7 @@ isComputed(doubled); // true
73
74
  - `batch(fn)` — coalesce signal writes; effects flush synchronously at end of outermost batch
74
75
  - `flushSync()` — synchronously drain pending effects (no-op inside batch)
75
76
  - `untracked<T>(fn): T` — run fn without tracking signal reads (like Preact `untracked()` / Solid `untrack()`)
76
- - `on(deps, fn, options?): () => U | undefined` — explicit dependency declaration helper (like Solid `on()`). Pass into `effect()` or `computed()`.
77
+ - `on(deps, fn, options?): () => U` — explicit dependency declaration helper (like Solid `on()`). Returns `() => U`; with `{ defer: true }` the accessor returns `() => U | undefined` (the deferred first call yields `undefined`). A single accessor `() => T` types `value`/`prev` as `T`; an array of accessors types them as `unknown[]`. Pass into `effect()` or `computed()`.
77
78
  - `subscribe(signal, cb): () => void` — subscribe to a signal, calling cb immediately and on every change
78
79
  - `isSignal(value): boolean` — type guard for signals created by `signal()`
79
80
  - `isComputed(value): boolean` — type guard for computed signals
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/reactive",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "exports": {
5
5
  ".": "./src/index.ts"
6
6
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cplieger/reactive",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -13,14 +13,14 @@
13
13
  },
14
14
  "devDependencies": {
15
15
  "@eslint/js": "10.0.1",
16
- "@vitest/coverage-v8": "4.1.8",
17
- "eslint": "10.4.1",
16
+ "@vitest/coverage-v8": "4.1.9",
17
+ "eslint": "10.5.0",
18
18
  "fast-check": "4.8.0",
19
- "happy-dom": "20.10.2",
20
- "prettier": "3.8.3",
19
+ "happy-dom": "20.10.3",
20
+ "prettier": "3.8.4",
21
21
  "typescript": "6.0.3",
22
- "typescript-eslint": "8.60.1",
23
- "vitest": "4.1.8"
22
+ "typescript-eslint": "8.61.1",
23
+ "vitest": "4.1.9"
24
24
  },
25
25
  "description": "Signals + DOM-reconciliation reactive core for TypeScript (zero dependencies)",
26
26
  "license": "GPL-3.0-or-later",
package/src/signal.ts CHANGED
@@ -662,7 +662,39 @@ export function isComputed(value: unknown): value is ReadonlySignal<unknown> {
662
662
  return value !== null && typeof value === "object" && COMPUTED_BRAND in value;
663
663
  }
664
664
 
665
- /** Explicit dependency declaration helper. Mirrors Solid's on(). */
665
+ /** Explicit dependency declaration helper. Mirrors Solid's on().
666
+ *
667
+ * Overloaded so the return type and the `value`/`prev` parameter types stay
668
+ * tight:
669
+ * - Without `defer` (or `{ defer: false }`) the accessor always returns `U`;
670
+ * only the `{ defer: true | boolean }` form widens to `U | undefined`
671
+ * (the deferred first call yields `undefined`).
672
+ * - A single accessor `() => T` correlates `value`/`prev` to `T`; an array of
673
+ * accessors correlates them to `unknown[]`. */
674
+ // Single accessor, non-deferred (or explicit `{ defer: false }`): never undefined.
675
+ export function on<T, U>(
676
+ deps: () => T,
677
+ fn: (value: T, prev: T | undefined, prevResult: U | undefined) => U,
678
+ options?: { defer?: false },
679
+ ): () => U;
680
+ // Single accessor, deferred: first call returns undefined.
681
+ export function on<T, U>(
682
+ deps: () => T,
683
+ fn: (value: T, prev: T | undefined, prevResult: U | undefined) => U,
684
+ options: { defer: boolean },
685
+ ): () => U | undefined;
686
+ // Array of accessors, non-deferred (or explicit `{ defer: false }`): never undefined.
687
+ export function on<U>(
688
+ deps: (() => unknown)[],
689
+ fn: (value: unknown[], prev: unknown[] | undefined, prevResult: U | undefined) => U,
690
+ options?: { defer?: false },
691
+ ): () => U;
692
+ // Array of accessors, deferred: first call returns undefined.
693
+ export function on<U>(
694
+ deps: (() => unknown)[],
695
+ fn: (value: unknown[], prev: unknown[] | undefined, prevResult: U | undefined) => U,
696
+ options: { defer: boolean },
697
+ ): () => U | undefined;
666
698
  export function on<T, U>(
667
699
  deps: (() => T) | (() => unknown)[],
668
700
  fn: (value: T | unknown[], prev: T | unknown[] | undefined, prevResult: U | undefined) => U,