react-state-basis 0.4.1 → 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,287 +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
-
134
- Trigger an update (e.g., click a button that calls `setA(1)`). You should see a console alert within ~100ms.
135
-
136
- ---
137
64
 
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
76
  ---
183
77
 
184
- ## How It Works (v0.4.0)
78
+ ## Visual Proof
185
79
 
186
- ### 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.
187
81
 
188
- Basis tracks **when** state updates occur, creating a 50-tick timeline for each variable:
189
- ```
190
- useState("count"): [0,0,1,0,0,1,1,0,...] (updates at ticks 2, 5, 6)
191
- useState("total"): [0,0,1,0,0,1,1,0,...] (same pattern)
192
- ↑ Redundant: identical temporal signature
193
- ```
194
-
195
- For every pair of variables, Basis checks three temporal relationships:
196
-
197
- 1. **Synchronous (Redundancy):** Do they update in the same tick?
198
- ```
199
- A: [0,1,0,1,0,...]
200
- B: [0,1,0,1,0,...] → Flagged as redundant
201
- ```
202
-
203
- 2. **Lead-Lag (A → B):** Does B consistently follow A in the next tick?
204
- ```
205
- A: [0,1,0,1,0,...]
206
- B: [0,0,1,0,1,...] → B follows A (sync leak detected)
207
- ```
208
-
209
- 3. **Lead-Lag (B → A):** Does A consistently follow B?
210
- ```
211
- A: [0,0,1,0,1,...]
212
- B: [0,1,0,1,0,...] → A follows B (reverse causality)
213
- ```
214
-
215
- The engine uses **offset-based comparison** to check these patterns without allocating temporary arrays, ensuring minimal overhead even at high frame rates.
216
-
217
- ### Performance Optimizations
218
-
219
- - **Idle Filtering:** Only analyzes variables with 2+ updates, reducing pairwise comparisons by ~90% in typical applications (measured on Excalidraw's 47-hook codebase)
220
- - **Batched Analysis:** Runs every 5 ticks (~100ms) to avoid impacting frame budget
221
- - **Console Throttling:** Same alert won't repeat within 5 seconds
222
- - **Zero Production Overhead:** Entire library is replaced with no-op shims in production builds
223
-
224
- ### What Gets Flagged?
82
+ <p align="center">
83
+ <img src="./assets/050Basis.gif" width="800" alt="Basis v0.5.0 Demo" />
84
+ </p>
225
85
 
226
- **Redundant Pattern Example:**
227
- ```tsx
228
- // ❌ Before (Basis flags this)
229
- const [count, setCount] = useState(0);
230
- const [doubled, setDoubled] = useState(0);
86
+ ---
231
87
 
232
- useEffect(() => {
233
- setDoubled(count * 2);
234
- }, [count]);
88
+ ## What Basis Detects
235
89
 
236
- // After (Basis suggestion)
237
- const [count, setCount] = useState(0);
238
- const doubled = useMemo(() => count * 2, [count]);
239
- ```
90
+ Basis treats every hook as a signal to catch these architectural violations:
240
91
 
241
- **Sync Leak Example:**
242
- ```tsx
243
- // Before (causes double render)
244
- const [user, setUser] = useState(null);
245
- const [isLoggedIn, setIsLoggedIn] = useState(false);
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)
246
96
 
247
- useEffect(() => {
248
- setIsLoggedIn(!!user);
249
- }, [user]);
250
-
251
- // ✅ After (single render)
252
- const [user, setUser] = useState(null);
253
- const isLoggedIn = !!user; // Derived, no effect needed
254
- ```
97
+ [**See examples & fixes →**](https://github.com/liovic/react-state-basis/wiki/03%3A-The-Forensic-Catalog)
255
98
 
256
99
  ---
257
100
 
258
- ## Production Safety
259
-
260
- In production builds, the entire tool is replaced with zero-op shims. **Zero runtime overhead. Zero bundle size increase.**
261
- ```json
262
- // package.json - automatic based on NODE_ENV
263
- "exports": {
264
- ".": {
265
- "development": "./dist/index.mjs",
266
- "production": "./dist/production.mjs", // No-op shims
267
- "default": "./dist/production.mjs"
268
- }
269
- }
270
- ```
101
+ ## Reports & Telemetry
271
102
 
272
- ---
103
+ ### Architectural Health Report
104
+ Check your entire app's state architecture by running `window.printBasisReport()` in the console.
273
105
 
274
- ## 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.
275
109
 
276
- Add `// @basis-ignore` at the top of a file to disable instrumentation:
277
- ```tsx
278
- // @basis-ignore
279
- // This file uses third-party library wrappers or hardware-bound synchronization that Basis shouldn't audit.
280
- ```
281
-
282
- **Good candidates for skipping:**
283
- - **High-frequency animations** (>60fps state updates)
284
- - **WebSocket message handlers** (rapid, intentional updates)
285
- - **Canvas/WebGL render loops** (performance-critical paths)
286
- - **Intentional synchronization** (e.g., React Query → local cache mirrors)
287
- - **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()`.
288
112
 
289
113
  ---
290
114
 
291
- ## Comparison to Other Tools
115
+ ## Real-World Evidence
292
116
 
293
- | Tool | Focus | When to Use |
294
- |------|-------|-------------|
295
- | **React DevTools** | Component hierarchy & values | Debugging specific components |
296
- | **Why Did You Render** | Re-render optimization | Performance tuning renders |
297
- | **ESLint exhaustive-deps** | Static dependency analysis | Preventing missing deps |
298
- | **react-state-basis** | **Temporal state relationships** | **Finding redundant state & effect chains** |
117
+ Basis is verified against industry-standard codebases to ensure high-fidelity detection:
299
118
 
300
- 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)
301
121
 
302
122
  ---
303
123
 
304
- ## Performance Impact (Measured)
305
-
306
- **Development Mode**
307
-
308
- These measurements were taken using the built-in **Stress Lab** with 100 active hooks and continuous state updates, observed in Chrome DevTools Performance and Web Vitals panels.
124
+ ## Performance & Privacy
309
125
 
310
- Location: `/example`
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
311
129
 
312
- **Observed impact:**
313
-
314
- * **Per update overhead:** < 0.05ms (O(1) Map-based tracking)
315
- * **Analysis pass:** ~1.0ms (Zero-copy pointer math)
316
- * **Frame budget impact:** ~2% during active 100-hook stress testing
317
- * **Latency (INP):** 80ms (v0.4.0) vs 464ms (v0.3.x legacy engine)
318
-
319
- > Results will vary by hardware, browser, and workload. Use the Stress Lab to reproduce and compare Basis ON vs OFF in your own environment.
320
-
321
- <p align="center">
322
- <img src="./assets/react-state-basis-stress.gif" width="800" alt="shadcn Admin Audit" />
323
- </p>
324
-
325
-
326
- **Production Mode:**
327
- - Overhead: ~0.01ms per hook call (negligible wrapper overhead)
328
- - Bundle size: ~2-3 KB minified (no-op wrappers only, no analysis engine)
329
- - Monitoring logic: 100% removed
330
- - HUD component: 100% removed
130
+ [**See benchmarks →**](https://github.com/liovic/react-state-basis/wiki/Performance-Forensics)
331
131
 
332
132
  ---
333
133
 
334
- ## Limitations (v0.4.x)
134
+ ## Documentation & Theory
335
135
 
336
- **What works well:**
337
- - ✅ Detecting synchronous redundant state
338
- - ✅ Flagging effect-driven update chains (A → Effect → B)
339
- - ✅ Catching infinite loops before browser freeze
340
- - ✅ Distinguishing causality from redundancy
341
-
342
- **Known edge cases:**
343
- - ⚠️ **Async gaps:** Updates delayed by >40ms (e.g., slow API responses) may appear independent
344
- - ⚠️ **Intentional sync:** Sometimes synchronization is required for library compatibility
345
- - ⚠️ **Complex multi-way dependencies:** Three or more interconnected states might not show full relationship graph
346
- - ⚠️ **Requires judgment:** Tool points out patterns worth investigating - you decide if they're issues
347
-
348
- **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).
349
137
 
350
138
  ---
351
139
 
352
140
  ## Roadmap
353
141
 
354
- ### v0.4.x
355
- - [x] **v0.4.0**: Temporal Cross-Correlation Engine (Lead-Lag Analysis)
356
- - [x] **v0.4.1:** Density Filtering (Eliminate false positives from animations/sliders)
357
- - [ ] v0.4.2: Ring Buffer (Zero-jank memory management for 500+ hooks)
358
-
359
- ### v0.5.0 (Planned)
360
- - [ ] Zustand & Redux middleware integration
361
- - [ ] Visual dependency graph in HUD
362
- - [ ] Historical trend tracking across sessions
142
+ Each era of Basis answers a different architectural question:
363
143
 
364
- ### Future Ideas
365
- - [ ] Domain isolation analysis (detect feature boundaries)
366
- - [ ] Export audit reports for team reviews
367
- - [ ] CI integration for architectural regressions
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?*
368
149
 
369
- ---
370
-
371
- ## FAQ
372
-
373
- **Q: Will this slow down my app?**
374
- A: Only in development (~0.3ms per update). Production builds have zero overhead.
375
-
376
- **Q: Do I have to change my code?**
377
- A: No. The Babel plugin instruments hooks automatically.
378
-
379
- **Q: What if it flags something that's not a problem?**
380
- A: Use your judgment. Basis is a diagnostic tool that points out patterns worth investigating - not all flagged patterns are bugs.
381
-
382
- **Q: How is this different from Redux DevTools?**
383
- A: Redux DevTools shows state values and action history. Basis shows temporal relationships between state variables, regardless of what state management library you use.
384
-
385
- **Q: Why "basis"?**
386
- 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.
387
150
 
388
- **Q: How is this different from Redux DevTools?**
389
- 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?"
390
-
391
- ---
392
-
393
- ## Contributing
394
-
395
- Found a bug? Have an idea? Open an issue or PR.
396
-
397
- 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)
398
152
 
399
153
  ---
400
154
 
401
155
  <div align="center">
402
156
 
403
- Built by [LP](https://github.com/liovic) • MIT License
157
+ Built by [LP](https://github.com/liovic) • [MIT License](https://opensource.org/licenses/MIT)
404
158
 
405
- </div>
159
+ </div>
package/dist/index.d.mts CHANGED
@@ -3,27 +3,37 @@ import React__default, { ReactNode } from 'react';
3
3
  export { basis } from './vite-plugin.mjs';
4
4
  import 'vite';
5
5
 
6
+ /**
7
+ * Standard React Reducer type inference helpers.
8
+ */
6
9
  type GetReducerState<R extends React.Reducer<any, any>> = R extends React.Reducer<infer S, any> ? S : never;
7
10
  type GetReducerAction<R extends React.Reducer<any, any>> = R extends React.Reducer<any, infer A> ? A : never;
8
11
  declare function useState<S>(initialState: S | (() => S), label?: string): [S, React.Dispatch<React.SetStateAction<S>>];
9
- declare function useRef<T>(initialValue: T): React.RefObject<T>;
10
- declare function useRef<T>(initialValue: T | null): React.RefObject<T>;
11
- declare function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
12
- 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;
13
22
  declare function useMemo<T>(factory: () => T, deps: React.DependencyList | undefined, label?: string): T;
14
- 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;
15
24
  declare function useEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
16
25
  declare function useLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
17
- declare function useTransition(_label?: string): [boolean, (callback: () => void) => void];
18
- declare function useDeferredValue<T>(value: T, initialValueOrLabel?: T | string, label?: string): T;
19
- 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;
20
30
  declare const useDebugValue: typeof React.useDebugValue;
21
31
  declare const useImperativeHandle: typeof React.useImperativeHandle;
22
32
  declare const useInsertionEffect: typeof React.useInsertionEffect;
23
- declare const useSyncExternalStore: any;
24
- declare function use<T>(usable: React.Usable<T>): T;
25
- declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
26
- 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;
27
37
 
28
38
  interface BasisProviderProps {
29
39
  children: ReactNode;
@@ -34,9 +44,13 @@ declare const useBasisConfig: () => {
34
44
  debug: boolean;
35
45
  };
36
46
 
37
- declare const configureBasis: (newConfig: Partial<{
38
- debug: boolean;
39
- }>) => void;
47
+ declare const configureBasis: (c: any) => void;
40
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
+ };
41
55
 
42
- export { BasisProvider, configureBasis, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };
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,27 +3,37 @@ import React__default, { ReactNode } from 'react';
3
3
  export { basis } from './vite-plugin.js';
4
4
  import 'vite';
5
5
 
6
+ /**
7
+ * Standard React Reducer type inference helpers.
8
+ */
6
9
  type GetReducerState<R extends React.Reducer<any, any>> = R extends React.Reducer<infer S, any> ? S : never;
7
10
  type GetReducerAction<R extends React.Reducer<any, any>> = R extends React.Reducer<any, infer A> ? A : never;
8
11
  declare function useState<S>(initialState: S | (() => S), label?: string): [S, React.Dispatch<React.SetStateAction<S>>];
9
- declare function useRef<T>(initialValue: T): React.RefObject<T>;
10
- declare function useRef<T>(initialValue: T | null): React.RefObject<T>;
11
- declare function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;
12
- 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;
13
22
  declare function useMemo<T>(factory: () => T, deps: React.DependencyList | undefined, label?: string): T;
14
- 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;
15
24
  declare function useEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
16
25
  declare function useLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList, label?: string): void;
17
- declare function useTransition(_label?: string): [boolean, (callback: () => void) => void];
18
- declare function useDeferredValue<T>(value: T, initialValueOrLabel?: T | string, label?: string): T;
19
- 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;
20
30
  declare const useDebugValue: typeof React.useDebugValue;
21
31
  declare const useImperativeHandle: typeof React.useImperativeHandle;
22
32
  declare const useInsertionEffect: typeof React.useInsertionEffect;
23
- declare const useSyncExternalStore: any;
24
- declare function use<T>(usable: React.Usable<T>): T;
25
- declare function useOptimistic<S, P>(passthrough: S, reducer?: (state: S, payload: P) => S, label?: string): [S, (payload: P) => void];
26
- 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;
27
37
 
28
38
  interface BasisProviderProps {
29
39
  children: ReactNode;
@@ -34,9 +44,13 @@ declare const useBasisConfig: () => {
34
44
  debug: boolean;
35
45
  };
36
46
 
37
- declare const configureBasis: (newConfig: Partial<{
38
- debug: boolean;
39
- }>) => void;
47
+ declare const configureBasis: (c: any) => void;
40
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
+ };
41
55
 
42
- export { BasisProvider, configureBasis, printBasisHealthReport, use, useActionState, useBasisConfig, useCallback, useDebugValue, useDeferredValue, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useOptimistic, useReducer, useRef, useState, useSyncExternalStore, useTransition };
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 };