ustor 0.3.0 → 0.3.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 CHANGED
@@ -473,22 +473,23 @@ npm run profile
473
473
 
474
474
  ## React
475
475
 
476
- Install React and import the optional hooks:
476
+ Install React and import the optional hook:
477
477
 
478
478
  ```bash
479
479
  npm install react
480
480
  ```
481
481
 
482
482
  ```jsx
483
- import { useSignal, useStore } from "ustor/react";
483
+ import { useSelector } from "ustor/react";
484
484
 
485
485
  // Uses the Preact configuration from Quickstart, including api.effect.
486
486
  const state = store({ count: 1, items: [1, 2] });
487
+ const selectCount = () => state.count;
487
488
  const selectTotal = () => state.items.reduce((sum, value) => sum + value, 0);
488
489
 
489
490
  export function Counter() {
490
- const count = useSignal(state.$count);
491
- const total = useStore(selectTotal);
491
+ const count = useSelector(selectCount);
492
+ const total = useSelector(selectTotal);
492
493
 
493
494
  return (
494
495
  <button onClick={() => { state.count++; state.items.push(state.count); }}>
@@ -498,18 +499,18 @@ export function Counter() {
498
499
  }
499
500
  ```
500
501
 
501
- - `useSignal(signal)` subscribes to one `$property` signal.
502
- - `useStore(selector)` tracks all compatible signal reads in the selector, including array versions.
502
+ - `useSelector(selector)` is the single React hook for both simple properties and derived values.
503
+ - It tracks all compatible signal reads in the selector, including array versions.
503
504
  - Selectors must return a primitive or stable reference, not a fresh object on every read.
504
505
  - Keep selector functions stable with `useCallback` when they are created inside a component.
505
506
  - React is an optional peer dependency and is excluded from the core bundle.
506
507
  - StrictMode and unmount cleanup are tested.
507
508
 
508
- Plain property reads do not schedule React renders by themselves; use the hooks or another React binding.
509
+ Plain property reads do not schedule React renders by themselves; use the hook or another React binding.
509
510
 
510
511
  ## SSR and Next.js
511
512
 
512
- Yes. `useStore` and `useSignal` provide a server snapshot through `useSyncExternalStore`. Server rendering creates no effects; subscriptions start on the client.
513
+ Yes. `useSelector` provides a server snapshot through `useSyncExternalStore`. Server rendering creates no effects; subscriptions start on the client.
513
514
 
514
515
  The test suite verifies:
515
516
 
@@ -520,14 +521,14 @@ The test suite verifies:
520
521
 
521
522
  ### Next.js App Router example
522
523
 
523
- Use the hooks in a **Client Component**. Create request- or component-owned state instead of exporting a request-specific singleton.
524
+ Use the hook in a **Client Component**. Create request- or component-owned state instead of exporting a request-specific singleton.
524
525
 
525
526
  ```jsx
526
527
  "use client";
527
528
 
528
529
  import { useCallback, useState } from "react";
529
530
  import { store } from "ustor";
530
- import { useSignal, useStore } from "ustor/react";
531
+ import { useSelector } from "ustor/react";
531
532
  // Import your shared adapter configuration once:
532
533
  // import "@/lib/ustor-setup";
533
534
 
@@ -536,12 +537,13 @@ export default function Counter({ initialCount }) {
536
537
  count: initialCount,
537
538
  items: [1, 2],
538
539
  }));
540
+ const selectCount = useCallback(() => state.count, [state]);
539
541
  const selectTotal = useCallback(
540
542
  () => state.items.reduce((sum, value) => sum + value, 0),
541
543
  [state],
542
544
  );
543
- const count = useSignal(state.$count);
544
- const total = useStore(selectTotal);
545
+ const count = useSelector(selectCount);
546
+ const total = useSelector(selectTotal);
545
547
 
546
548
  return (
547
549
  <button onClick={() => { state.count++; state.items.push(1); }}>
@@ -577,7 +579,7 @@ Declarations are included for both entry points; no separate `@types/ustor` pack
577
579
 
578
580
  ```typescript
579
581
  import { store } from "ustor";
580
- import { useStore } from "ustor/react";
582
+ import { useSelector } from "ustor/react";
581
583
 
582
584
  const state = store({
583
585
  count: 1,
@@ -591,14 +593,13 @@ state.count = 2; // valid
591
593
 
592
594
  const doubled: number = state.double;
593
595
  const text: string = state.nested.text;
594
- const total = useStore(() => state.list.reduce((sum, value) => sum + value, 0));
596
+ const total = useSelector(() => state.list.reduce((sum, value) => sum + value, 0));
595
597
  ```
596
598
 
597
599
  Exported type utilities:
598
600
 
599
601
  - `SignalApi<Signal, Computed>` for custom adapters.
600
602
  - `Store<T>` for reactive store inference.
601
- - `SignalValue<Signal>` for React signal-value inference.
602
603
 
603
604
  Run the repository's strict compile-time tests with:
604
605
 
package/dist/react.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("react");const r={},t=t=>{const c=e.useCallback(e=>{if(!r.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let c=!0;return r.effect(()=>{t(),c?c=!1:e()})},[t]);return e.useSyncExternalStore(c,t,t)};exports.useSignal=c=>{const s=e.useCallback(()=>r.get(c),[c]);return t(s)},exports.useStore=t;
1
+ "use strict";var e=require("react");const r={};exports.useSelector=t=>{const c=e.useCallback(e=>{if(!r.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let c=!0;return r.effect(()=>{t(),c?c=!1:e()})},[t]);return e.useSyncExternalStore(c,t,t)};
package/dist/react.es.js CHANGED
@@ -1 +1 @@
1
- import{useCallback as t,useSyncExternalStore as r}from"react";const e={},o=o=>{const c=t(t=>{if(!e.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let r=!0;return e.effect(()=>{o(),r?r=!1:t()})},[o]);return r(c,o,o)},c=r=>{const c=t(()=>e.get(r),[r]);return o(c)};export{c as useSignal,o as useStore};
1
+ import{useCallback as r,useSyncExternalStore as t}from"react";const e={},o=o=>{const c=r(r=>{if(!e.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let t=!0;return e.effect(()=>{o(),t?t=!1:r()})},[o]);return t(c,o,o)};export{o as useSelector};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ustor",
3
3
  "description": "A tiny, dependency-free reactive store with pluggable signal adapters and optional React hooks.",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "source": "./src/index.js",
7
7
  "types": "./types/index.d.ts",
package/types/react.d.ts CHANGED
@@ -1,17 +1,2 @@
1
- export type SignalValue<Signal> = Signal extends { state: readonly (infer Value)[] }
2
- ? Value
3
- : Signal extends { value: infer Value }
4
- ? Value
5
- : Signal extends { get(): infer Value }
6
- ? Value
7
- : Signal extends () => infer Value
8
- ? Value
9
- : Signal extends readonly [() => infer Value, ...any[]]
10
- ? Value
11
- : unknown;
12
-
13
1
  /** Subscribe to a selector that returns a primitive or stable reference. */
14
- export declare function useStore<Value>(selector: () => Value): Value;
15
-
16
- /** Subscribe to one underlying signal exposed as state.$property. */
17
- export declare function useSignal<Signal>(signal: Signal): SignalValue<Signal>;
2
+ export declare function useSelector<Value>(selector: () => Value): Value;