react-state-basis 0.4.2 → 0.5.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 CHANGED
@@ -4,111 +4,43 @@
4
4
 
5
5
  <div align="center">
6
6
 
7
- # 📐 react-state-basis
8
- ### Runtime Architectural Auditor & State Profiler for React
7
+ # react-state-basis
8
+ ### Runtime Architectural Auditor for React
9
+
10
+ **Basis tracks when state updates (never what) to catch architectural debt that standard tools miss, while keeping your data private.**
9
11
 
10
12
  [![npm version](https://img.shields.io/npm/v/react-state-basis.svg?style=flat-square)](https://www.npmjs.com/package/react-state-basis)
11
13
  [![GitHub stars](https://img.shields.io/github/stars/liovic/react-state-basis.svg?style=flat-square)](https://github.com/liovic/react-state-basis/stargazers)
12
14
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
13
15
 
14
- **Basis tracks the rhythm of state updates, not the data. It identifies redundant patterns and sync-leaks that standard tools miss.**
15
-
16
- > Stop relying on architectural intuition. Start measuring architectural debt.
17
-
18
16
  </div>
19
17
 
20
18
  ---
21
19
 
22
- ## What Does It Do?
23
-
24
- **react-state-basis** watches your React app in development and flags common architectural issues:
25
-
26
- - **Redundant state** - Two states that always update together
27
- - **Update chains** - Effects that trigger more state updates (double renders)
28
- - **Infinite loops** - Circular dependencies that freeze your browser
29
- - **Tight coupling** - State variables that should be independent but aren't
30
-
31
- It works by tracking *when* state updates happen (temporal patterns), not *what* the values are.
32
-
33
- ---
34
-
35
- ## Quick Example
36
- ```tsx
37
- // ❌ Basis will flag this
38
- const [user, setUser] = useState(null);
39
- const [isLoggedIn, setIsLoggedIn] = useState(false);
40
-
41
- useEffect(() => {
42
- setIsLoggedIn(!!user); // Double render - flagged as sync leak
43
- }, [user]);
44
-
45
- // ✅ Better
46
- const [user, setUser] = useState(null);
47
- const isLoggedIn = !!user; // Computed, no second render
48
- ```
49
-
50
- ---
51
-
52
- ## See It Work
53
-
54
- The optional HUD shows your state basis matrix in real-time:
55
-
56
- <p align="center">
57
- <img src="./assets/react-state-basis-demo.gif" width="800" alt="React State Basis Demo" />
58
- </p>
59
-
60
- ---
61
-
62
- ## Real-World Audits
63
-
64
- Basis has been tested on major open-source projects to validate detection accuracy:
65
-
66
- ### Excalidraw (114k+ ⭐)
67
- **Detected:** Causal Sync Leak in theme state synchronization
68
- **Issue:** A `useEffect` was manually syncing theme state, causing an unnecessary double render on every theme toggle
69
- **Fix:** [PR #10637](https://github.com/excalidraw/excalidraw/pull/10637) - Replaced with a computed value
70
-
71
- <p align="center">
72
- <img src="./assets/excalidraw-audit.png" width="800" alt="Excalidraw Audit" />
73
- </p>
74
-
75
- ### shadcn-admin (10k+ ⭐)
76
- **Detected:** Redundant state pattern in mobile detection hooks
77
- **Issue:** Viewport resize events were being synchronized via effects rather than direct subscriptions
78
- **Fix:** [PR #274](https://github.com/satnaing/shadcn-admin/pull/274) - Optimized subscription pattern
79
-
80
- <p align="center">
81
- <img src="./assets/shadcn-admin.png" width="800" alt="shadcn Admin Audit" />
82
- </p>
83
-
84
- > **Note:** These are proposed architectural improvements. Basis points out patterns worth investigating - the final decision rests with the maintainer.
85
-
86
- ---
87
-
88
- ## Setup (Vite)
20
+ ## Quick Start
89
21
 
90
22
  ### 1. Install
91
23
  ```bash
92
24
  npm i react-state-basis
93
25
  ```
94
26
 
95
- ### 2. Add to `vite.config.ts`
96
- ```tsx
97
- import { defineConfig } from 'vite';
98
- import react from '@vitejs/plugin-react';
27
+ ### 2. Setup (Vite)
28
+ Add the plugin to your `vite.config.ts`. The Babel plugin auto-labels your hooks—you continue importing from `react` as normal.
29
+
30
+ ```ts
99
31
  import { basis } from 'react-state-basis/vite';
100
32
 
101
33
  export default defineConfig({
102
34
  plugins: [
103
- react({
104
- babel: { plugins: [['react-state-basis/plugin']] }
35
+ react({
36
+ babel: { plugins: [['react-state-basis/plugin']] }
105
37
  }),
106
38
  basis()
107
39
  ]
108
40
  });
109
41
  ```
110
42
 
111
- ### 3. Wrap your app
43
+ ### 3. Initialize
112
44
  ```tsx
113
45
  import { BasisProvider } from 'react-state-basis';
114
46
 
@@ -119,301 +51,109 @@ root.render(
119
51
  );
120
52
  ```
121
53
 
122
- ### 4. Verify It's Working
54
+ ### 4. Verify the Signal
55
+ Drop this pattern into any component. Basis will identify the rhythm of the debt within ~100ms.
123
56
 
124
- Add this test pattern to any component:
125
57
  ```tsx
126
58
  const [a, setA] = useState(0);
127
59
  const [b, setB] = useState(0);
128
60
 
129
61
  useEffect(() => {
130
- setB(a); // Basis will flag this
62
+ setB(a); // BASIS: "Double Render Detected"
131
63
  }, [a]);
132
- ```
133
64
 
134
- Trigger an update (e.g., click a button that calls `setA(1)`). You should see a console alert within ~100ms.
135
-
136
- ---
137
-
138
- ## What You'll See
139
-
140
- ### Console Alerts
141
-
142
- **Redundant Pattern:**
143
- Detected when two variables move in perfect unison.
144
- ```
145
- 📐 BASIS | REDUNDANT PATTERN
146
- 📍 Location: TodoList.tsx
147
- Observation: "todos" and "count" move together.
148
- One is likely a direct mirror of the other. Confidence: 94%
149
- Action: Refactor "count" to useMemo.
65
+ return <button onClick={() => setA(a + 1)}>Pulse Basis</button>;
150
66
  ```
151
67
 
152
- **Sync Leak (Causal Chain):**
153
- Detected when one variable consistently triggers another with a temporal lag.
68
+ Click the button. You should see this in your console within ~100ms:
154
69
  ```
155
- 💡 BASIS | DETECTED SYNC LEAK
156
- 📍 Location: AuthProvider.tsx
157
- Flow: user Effect isLoggedIn
158
- Context: The engine detected a consistent 20ms lag between these updates.
159
- Result: This creates a Double Render Cycle.
70
+ BASIS | DOUBLE RENDER
71
+ 📍 Location: YourComponent.tsx
72
+ Issue: a triggers b in a separate frame.
73
+ Fix: Derive b during the first render.
160
74
  ```
161
75
 
162
- **Infinite Loop:**
163
- Detected when a variable updates too rapidly (circuit breaker).
164
- ```
165
- 🛑 BASIS CRITICAL | CIRCUIT BREAKER
166
- Infinite oscillation detected on: "counter"
167
- Execution halted to prevent browser thread lock.
168
- ```
169
-
170
- ### Health Report
171
-
172
- Check your entire app's state architecture:
173
- ```tsx
174
- window.printBasisReport();
175
- ```
176
-
177
- Shows:
178
- - **Health Score** - Percentage of independent vs. synchronized state
179
- - **Synchronized Clusters** - Groups of variables that move together
180
- - **Correlation Matrix** - Full pairwise similarity analysis (for <15 variables)
181
-
182
- ### Hardware Telemetry
183
-
184
- Verify engine efficiency and heap stability in real-time:
185
-
186
- ```tsx
187
- window.getBasisMetrics();
188
- ```
189
-
190
- Returns: Engine execution time, active hook count, and current memory allocation strategy.
191
-
192
76
  ---
193
77
 
194
- ## How It Works (v0.4.x)
78
+ ## Visual Proof
195
79
 
196
- ### Temporal Cross-Correlation
80
+ The optional HUD shows your **State Basis Matrix** in real-time. Purple pulses ($\Omega$) are Context anchors; Red pulses (!) are redundant shadows.
197
81
 
198
- Basis tracks **when** state updates occur, creating a 50-tick timeline for each variable:
199
- ```
200
- useState("count"): [0,0,1,0,0,1,1,0,...] (updates at ticks 2, 5, 6)
201
- useState("total"): [0,0,1,0,0,1,1,0,...] (same pattern)
202
- ↑ Redundant: identical temporal signature
203
- ```
204
-
205
- For every pair of variables, Basis checks three temporal relationships:
206
-
207
- 1. **Synchronous (Redundancy):** Do they update in the same tick?
208
- ```
209
- A: [0,1,0,1,0,...]
210
- B: [0,1,0,1,0,...] → Flagged as redundant
211
- ```
212
-
213
- 2. **Lead-Lag (A → B):** Does B consistently follow A in the next tick?
214
- ```
215
- A: [0,1,0,1,0,...]
216
- B: [0,0,1,0,1,...] → B follows A (sync leak detected)
217
- ```
218
-
219
- 3. **Lead-Lag (B → A):** Does A consistently follow B?
220
- ```
221
- A: [0,0,1,0,1,...]
222
- B: [0,1,0,1,0,...] → A follows B (reverse causality)
223
- ```
224
-
225
- The engine uses **offset-based comparison** to check these patterns without allocating temporary arrays, ensuring minimal overhead even at high frame rates.
226
-
227
- ### Performance Optimizations
228
-
229
- - **Idle Filtering:** Only analyzes variables with 2+ updates, reducing pairwise comparisons by ~90% in typical applications (measured on Excalidraw's 47-hook codebase)
230
- - **Batched Analysis:** Runs every 5 ticks (~100ms) to avoid impacting frame budget
231
- - **Console Throttling:** Same alert won't repeat within 5 seconds
232
- - **Zero Production Overhead:** Entire library is replaced with no-op shims in production builds
82
+ <p align="center">
83
+ <img src="./assets/050Basis.gif" width="800" alt="Basis v0.5.0 Demo" />
84
+ </p>
233
85
 
234
- ### What Gets Flagged?
86
+ ---
235
87
 
236
- **Redundant Pattern Example:**
237
- ```tsx
238
- // ❌ Before (Basis flags this)
239
- const [count, setCount] = useState(0);
240
- const [doubled, setDoubled] = useState(0);
88
+ ## What Basis Detects
241
89
 
242
- useEffect(() => {
243
- setDoubled(count * 2);
244
- }, [count]);
90
+ Basis treats every hook as a signal to catch these architectural violations:
245
91
 
246
- // After (Basis suggestion)
247
- const [count, setCount] = useState(0);
248
- const doubled = useMemo(() => count * 2, [count]);
249
- ```
92
+ - **Ω Context Mirroring** - Local state shadowing global context
93
+ - **♊ Duplicate State** - Independent variables that always update together
94
+ - **⚡ Sync Leaks** - 1-frame delays forcing double renders
95
+ - **🛑 Recursive Oscillation** - Infinite loops (with circuit breaker)
250
96
 
251
- **Sync Leak Example:**
252
- ```tsx
253
- // ❌ Before (causes double render)
254
- const [user, setUser] = useState(null);
255
- const [isLoggedIn, setIsLoggedIn] = useState(false);
256
-
257
- useEffect(() => {
258
- setIsLoggedIn(!!user);
259
- }, [user]);
260
-
261
- // ✅ After (single render)
262
- const [user, setUser] = useState(null);
263
- const isLoggedIn = !!user; // Derived, no effect needed
264
- ```
97
+ [**See examples & fixes →**](https://github.com/liovic/react-state-basis/wiki/03%3A-The-Forensic-Catalog)
265
98
 
266
99
  ---
267
100
 
268
- ## Production Safety
269
-
270
- In production builds, the entire tool is replaced with zero-op shims. **Zero runtime overhead. Zero bundle size increase.**
271
- ```json
272
- // package.json - automatic based on NODE_ENV
273
- "exports": {
274
- ".": {
275
- "development": "./dist/index.mjs",
276
- "production": "./dist/production.mjs", // No-op shims
277
- "default": "./dist/production.mjs"
278
- }
279
- }
280
- ```
101
+ ## Reports & Telemetry
281
102
 
282
- ---
103
+ ### Architectural Health Report
104
+ Check your entire app's state architecture by running `window.printBasisReport()` in the console.
283
105
 
284
- ## When to Skip Files
106
+ * **Efficiency Score:** Ratio of independent signals to total hooks.
107
+ * **Entangled Clusters:** Groups of variables that move in sync (Boolean Explosion).
108
+ * **Correlation Matrix:** Raw pairwise similarity data for deep-dive forensics.
285
109
 
286
- Add `// @basis-ignore` at the top of a file to disable instrumentation:
287
- ```tsx
288
- // @basis-ignore
289
- // This file contains external protocols or hardware-bound synchronization outside the scope of architectural auditing.
290
- ```
291
-
292
- **Good candidates for skipping:**
293
- - **High-frequency animations** (>60fps state updates)
294
- - **WebSocket message handlers** (rapid, intentional updates)
295
- - **Canvas/WebGL render loops** (performance-critical paths)
296
- - **Intentional synchronization** (e.g., React Query → local cache mirrors)
297
- - **Third-party library wrappers** (where you don't control the architecture)
110
+ ### Hardware Telemetry
111
+ Verify engine efficiency and heap stability in real-time via `window.getBasisMetrics()`.
298
112
 
299
113
  ---
300
114
 
301
- ## Comparison to Other Tools
115
+ ## Real-World Evidence
302
116
 
303
- | Tool | Focus | When to Use |
304
- |------|-------|-------------|
305
- | **React DevTools** | Component hierarchy & values | Debugging specific components |
306
- | **Why Did You Render** | Re-render optimization | Performance tuning renders |
307
- | **ESLint exhaustive-deps** | Static dependency analysis | Preventing missing deps |
308
- | **react-state-basis** | **Temporal state relationships** | **Finding redundant state & effect chains** |
117
+ Basis is verified against industry-standard codebases to ensure high-fidelity detection:
309
118
 
310
- These tools are complementary - use them together for best results.
119
+ * **Excalidraw (114k⭐)** - Caught a theme-sync leak forcing a double-render on every toggle. [**PR #10637**](https://github.com/excalidraw/excalidraw/pull/10637)
120
+ * **shadcn-admin (10k⭐)** - Detected redundant state pattern in viewport detection hooks. [**PR #274**](https://github.com/satnaing/shadcn-admin/pull/274)
311
121
 
312
122
  ---
313
123
 
314
- ## Performance Impact (Measured)
315
-
316
- **Development Mode**
317
-
318
- **Basis is designed to be statistically invisible to the main thread.**
124
+ ## Performance & Privacy
319
125
 
320
- The v0.4.2 **Flat Memory Architecture** utilizes `Uint8Array` Ring Buffers to eliminate Garbage Collection (GC) churn and provide constant-time $O(1)$ telemetry recording.
126
+ **Development:** <1ms overhead per update cycle, zero heap growth
127
+ **Production:** ~0.01ms per hook (monitoring disabled, ~2-3KB bundle)
128
+ **Privacy:** Only tracks update timing, never state values
321
129
 
322
- ### Audited Benchmarks
323
-
324
- These metrics were recorded during a **20-minute high-frequency endurance audit** (1.2M state pulses) using the built-in **Stress Lab**.
325
-
326
- * **Logic Execution Overhead:** < 1.0ms per 100-hook update cycle.
327
- * **Memory Profile:** **0 Delta heap growth.** (Static allocation via Ring Buffers).
328
- * **Interaction Latency (INP):** ~56ms during continuous 50-hook concurrency tests (Green Zone).
329
- * **Drawing Efficiency:** ~15ms drawing cost via Path2D GPU-batching.
330
-
331
- > 🔍 **Forensic Proof:** Detailed heap snapshots, modulo-tax analysis, and linearized math benchmarks are documented in the [**v0.4.2 Performance RFC (#33)**](https://github.com/liovic/react-state-basis/issues/33).
332
-
333
- <p align="center">
334
- <img src="./assets/perf.gif" width="800" alt="Basis Stress Lab" />
335
- </p>
336
-
337
-
338
-
339
- **Production Mode:**
340
- - Overhead: ~0.01ms per hook call (negligible wrapper overhead)
341
- - Bundle size: ~2-3 KB minified (no-op wrappers only, no analysis engine)
342
- - Monitoring logic: 100% removed
343
- - HUD component: 100% removed
130
+ [**See benchmarks →**](https://github.com/liovic/react-state-basis/wiki/Performance-Forensics)
344
131
 
345
132
  ---
346
133
 
347
- ## Limitations (v0.4.x)
134
+ ## Documentation & Theory
348
135
 
349
- **What works well:**
350
- - ✅ Detecting synchronous redundant state
351
- - ✅ Flagging effect-driven update chains (A → Effect → B)
352
- - ✅ Catching infinite loops before browser freeze
353
- - ✅ Distinguishing causality from redundancy
354
-
355
- **Known edge cases:**
356
- - ⚠️ **Async gaps:** Updates delayed by >40ms (e.g., slow API responses) may appear independent
357
- - ⚠️ **Intentional sync:** Sometimes synchronization is required for library compatibility
358
- - ⚠️ **Complex multi-way dependencies:** Three or more interconnected states might not show full relationship graph
359
- - ⚠️ **Requires judgment:** Tool points out patterns worth investigating - you decide if they're issues
360
-
361
- **Heuristic interpretation requires context. Always verify architectural intent before refactoring.**.
136
+ Basis is built on heuristics inspired by **Linear Algebra** and **Signal Processing**. To understand the underlying math, visit the [**Full Wiki**](https://github.com/liovic/react-state-basis/wiki).
362
137
 
363
138
  ---
364
139
 
365
140
  ## Roadmap
366
141
 
367
- ### v0.4.x
368
- - [x] **v0.4.0**: Temporal Cross-Correlation Engine (Lead-Lag Analysis)
369
- - [x] **v0.4.1:** Density Filtering (Eliminate false positives from animations/sliders)
370
- - [x] v0.4.2: Ring Buffer (Zero-jank memory management for 500+ hooks) [**v0.4.2 Performance RFC (#33)**](https://github.com/liovic/react-state-basis/issues/33)
142
+ Each era of Basis answers a different architectural question:
371
143
 
144
+ ✓ **v0.4.x** - The Correlation Era - *Are these states moving together?*
145
+ → **v0.5.x** - The Decomposition Era - *Is this local state just a copy of Context?*
146
+ **v0.6.x** - The Graph Era - *Which bug should I fix first for maximum impact?*
147
+ **v0.7.x** - The Information Era - *Does this state carry real information, or is it derivative?*
148
+ **v0.8.x** - The Manifold Era - *How many hooks does your component actually need?*
372
149
 
373
- ### v0.5.0 (Planned)
374
- - [ ] Zustand & Redux middleware integration
375
- - [ ] Visual dependency graph in HUD
376
- - [ ] Historical trend tracking across sessions
377
150
 
378
- ### Future Ideas
379
- - [ ] Domain isolation analysis (detect feature boundaries)
380
- - [ ] Export audit reports for team reviews
381
- - [ ] CI integration for architectural regressions
382
-
383
- ---
384
-
385
- ## FAQ
386
-
387
- **Q: Will this slow down my app?**
388
- A: Only in development (~0.3ms per update). Production builds have zero overhead.
389
-
390
- **Q: Do I have to change my code?**
391
- A: No. The Babel plugin instruments hooks automatically.
392
-
393
- **Q: What if it flags something that's not a problem?**
394
- A: Use your judgment. Basis is a diagnostic tool that points out patterns worth investigating - not all flagged patterns are bugs.
395
-
396
- **Q: How is this different from Redux DevTools?**
397
- A: Redux DevTools shows state values and action history. Basis shows temporal relationships between state variables, regardless of what state management library you use.
398
-
399
- **Q: Why "basis"?**
400
- A: In linear algebra, a "basis" is a minimal set of independent vectors. The name reflects the goal of finding your app's minimal independent state - removing redundancy.
401
-
402
- **Q: How is this different from Redux DevTools?**
403
- A: Redux DevTools is a **Journal** - it logs specific values and actions within a Redux store. Basis is an **Architectural Auditor** - it instruments React's core primitives (useState, useReducer, useEffect) to detect hidden relationships between entirely separate components and hooks, even when they don't share a store. Redux DevTools answers "what changed and why?" while Basis answers "is this state architecture clean?"
404
-
405
- ---
406
-
407
- ## Contributing
408
-
409
- Found a bug? Have an idea? Open an issue or PR.
410
-
411
- For technical details on how the detection works, see the [Wiki](https://github.com/liovic/react-state-basis/wiki).
151
+ [**More info**](https://github.com/liovic/react-state-basis/wiki/Roadmap)
412
152
 
413
153
  ---
414
154
 
415
155
  <div align="center">
416
156
 
417
- Built by [LP](https://github.com/liovic) • MIT License
157
+ Built by [LP](https://github.com/liovic) • [MIT License](https://opensource.org/licenses/MIT)
418
158
 
419
- </div>
159
+ </div>
package/dist/index.d.mts CHANGED
@@ -3,39 +3,37 @@ import React__default, { ReactNode } from 'react';
3
3
  export { basis } from './vite-plugin.mjs';
4
4
  import 'vite';
5
5
 
6
- declare const configureBasis: (c: any) => void;
7
6
  /**
8
- * DISPLAY: window.printBasisReport()
7
+ * Standard React Reducer type inference helpers.
9
8
  */
10
- declare const printBasisHealthReport: (threshold?: number) => void;
11
- declare const getBasisMetrics: () => {
12
- engine: string;
13
- hooks: number;
14
- load: number;
15
- analysis_ms: string;
16
- };
17
-
18
9
  type GetReducerState<R extends React.Reducer<any, any>> = R extends React.Reducer<infer S, any> ? S : never;
19
10
  type GetReducerAction<R extends React.Reducer<any, any>> = R extends React.Reducer<any, infer A> ? A : never;
20
11
  declare function useState<S>(initialState: S | (() => S), label?: string): [S, React.Dispatch<React.SetStateAction<S>>];
21
- declare function useRef<T>(initialValue: T): React.RefObject<T>;
22
- declare function useRef<T>(initialValue: T | null): React.RefObject<T>;
23
- declare function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
24
- declare function useReducer<R extends React.Reducer<any, any>, I>(reducer: R, initialArg: I, init?: any, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
12
+ /**
13
+ * PUBLIC OVERLOAD: Lazy initialization
14
+ */
15
+ declare function useReducer<R extends React.Reducer<any, any>, I>(reducer: R, initializerArg: I, initializer: (arg: I) => GetReducerState<R>, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
16
+ /**
17
+ * PUBLIC OVERLOAD: Direct initialization
18
+ */
19
+ declare function useReducer<R extends React.Reducer<any, any>>(reducer: R, initialState: GetReducerState<R>, initializer?: undefined, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
20
+ declare function createContext<T>(defaultValue: T, label?: string): React.Context<T>;
21
+ declare function useContext<T>(context: React.Context<T>): T;
25
22
  declare function useMemo<T>(factory: () => T, deps: React.DependencyList | undefined, label?: string): T;
26
- declare function useCallback<T extends (...args: any[]) => any>(callback: T, deps: React.DependencyList, label?: string): T;
23
+ declare function useCallback<T extends (...args: unknown[]) => unknown>(callback: T, deps: React.DependencyList, label?: string): T;
27
24
  declare function useEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
28
25
  declare function useLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
29
- declare function useTransition(_label?: string): [boolean, (callback: () => void) => void];
30
- declare function useDeferredValue<T>(value: T, initialValueOrLabel?: T | string, label?: string): T;
31
- declare const useId: (label?: string) => string;
26
+ declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
27
+ declare function useActionState<State, Payload>(action: (state: State, payload: Payload) => Promise<State> | State, initialState: State, permalink?: string, label?: string): [state: State, dispatch: (payload: Payload) => void, isPending: boolean];
28
+ declare const useRef: typeof React.useRef;
29
+ declare const useId: typeof React.useId;
32
30
  declare const useDebugValue: typeof React.useDebugValue;
33
31
  declare const useImperativeHandle: typeof React.useImperativeHandle;
34
32
  declare const useInsertionEffect: typeof React.useInsertionEffect;
35
- declare const useSyncExternalStore: any;
36
- declare function use<T>(usable: React.Usable<T>): T;
37
- declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
38
- declare function useActionState<State, Payload>(action: (state: State, payload: Payload) => Promise<State> | State, initialState: State, permalink?: string, label?: string): [state: State, dispatch: (payload: Payload) => void, isPending: boolean];
33
+ declare const useSyncExternalStore: typeof React.useSyncExternalStore;
34
+ declare const useTransition: typeof React.useTransition;
35
+ declare const useDeferredValue: typeof React.useDeferredValue;
36
+ declare const use: <T>(usable: React.Usable<T>) => T;
39
37
 
40
38
  interface BasisProviderProps {
41
39
  children: ReactNode;
@@ -46,4 +44,13 @@ declare const useBasisConfig: () => {
46
44
  debug: boolean;
47
45
  };
48
46
 
49
- export { BasisProvider, configureBasis, getBasisMetrics, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };
47
+ declare const configureBasis: (c: any) => void;
48
+ declare const printBasisHealthReport: (threshold?: number) => void;
49
+ declare const getBasisMetrics: () => {
50
+ engine: string;
51
+ hooks: number;
52
+ analysis_ms: string;
53
+ entropy: string;
54
+ };
55
+
56
+ export { BasisProvider, configureBasis, createContext, getBasisMetrics, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useContext, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };
package/dist/index.d.ts CHANGED
@@ -3,39 +3,37 @@ import React__default, { ReactNode } from 'react';
3
3
  export { basis } from './vite-plugin.js';
4
4
  import 'vite';
5
5
 
6
- declare const configureBasis: (c: any) => void;
7
6
  /**
8
- * DISPLAY: window.printBasisReport()
7
+ * Standard React Reducer type inference helpers.
9
8
  */
10
- declare const printBasisHealthReport: (threshold?: number) => void;
11
- declare const getBasisMetrics: () => {
12
- engine: string;
13
- hooks: number;
14
- load: number;
15
- analysis_ms: string;
16
- };
17
-
18
9
  type GetReducerState<R extends React.Reducer<any, any>> = R extends React.Reducer<infer S, any> ? S : never;
19
10
  type GetReducerAction<R extends React.Reducer<any, any>> = R extends React.Reducer<any, infer A> ? A : never;
20
11
  declare function useState<S>(initialState: S | (() => S), label?: string): [S, React.Dispatch<React.SetStateAction<S>>];
21
- declare function useRef<T>(initialValue: T): React.RefObject<T>;
22
- declare function useRef<T>(initialValue: T | null): React.RefObject<T>;
23
- declare function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
24
- declare function useReducer<R extends React.Reducer<any, any>, I>(reducer: R, initialArg: I, init?: any, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
12
+ /**
13
+ * PUBLIC OVERLOAD: Lazy initialization
14
+ */
15
+ declare function useReducer<R extends React.Reducer<any, any>, I>(reducer: R, initializerArg: I, initializer: (arg: I) => GetReducerState<R>, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
16
+ /**
17
+ * PUBLIC OVERLOAD: Direct initialization
18
+ */
19
+ declare function useReducer<R extends React.Reducer<any, any>>(reducer: R, initialState: GetReducerState<R>, initializer?: undefined, label?: string): [GetReducerState<R>, React.Dispatch<GetReducerAction<R>>];
20
+ declare function createContext<T>(defaultValue: T, label?: string): React.Context<T>;
21
+ declare function useContext<T>(context: React.Context<T>): T;
25
22
  declare function useMemo<T>(factory: () => T, deps: React.DependencyList | undefined, label?: string): T;
26
- declare function useCallback<T extends (...args: any[]) => any>(callback: T, deps: React.DependencyList, label?: string): T;
23
+ declare function useCallback<T extends (...args: unknown[]) => unknown>(callback: T, deps: React.DependencyList, label?: string): T;
27
24
  declare function useEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
28
25
  declare function useLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
29
- declare function useTransition(_label?: string): [boolean, (callback: () => void) => void];
30
- declare function useDeferredValue<T>(value: T, initialValueOrLabel?: T | string, label?: string): T;
31
- declare const useId: (label?: string) => string;
26
+ declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
27
+ declare function useActionState<State, Payload>(action: (state: State, payload: Payload) => Promise<State> | State, initialState: State, permalink?: string, label?: string): [state: State, dispatch: (payload: Payload) => void, isPending: boolean];
28
+ declare const useRef: typeof React.useRef;
29
+ declare const useId: typeof React.useId;
32
30
  declare const useDebugValue: typeof React.useDebugValue;
33
31
  declare const useImperativeHandle: typeof React.useImperativeHandle;
34
32
  declare const useInsertionEffect: typeof React.useInsertionEffect;
35
- declare const useSyncExternalStore: any;
36
- declare function use<T>(usable: React.Usable<T>): T;
37
- declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
38
- declare function useActionState<State, Payload>(action: (state: State, payload: Payload) => Promise<State> | State, initialState: State, permalink?: string, label?: string): [state: State, dispatch: (payload: Payload) => void, isPending: boolean];
33
+ declare const useSyncExternalStore: typeof React.useSyncExternalStore;
34
+ declare const useTransition: typeof React.useTransition;
35
+ declare const useDeferredValue: typeof React.useDeferredValue;
36
+ declare const use: <T>(usable: React.Usable<T>) => T;
39
37
 
40
38
  interface BasisProviderProps {
41
39
  children: ReactNode;
@@ -46,4 +44,13 @@ declare const useBasisConfig: () => {
46
44
  debug: boolean;
47
45
  };
48
46
 
49
- export { BasisProvider, configureBasis, getBasisMetrics, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };
47
+ declare const configureBasis: (c: any) => void;
48
+ declare const printBasisHealthReport: (threshold?: number) => void;
49
+ declare const getBasisMetrics: () => {
50
+ engine: string;
51
+ hooks: number;
52
+ analysis_ms: string;
53
+ entropy: string;
54
+ };
55
+
56
+ export { BasisProvider, configureBasis, createContext, getBasisMetrics, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useContext, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };