stunk 2.3.0 → 2.4.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.
Files changed (47) hide show
  1. package/dist/{core/core.d.ts → core-C7jFiHdO.d.ts} +5 -9
  2. package/dist/index.cjs +2 -1
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +171 -0
  5. package/dist/index.d.ts +171 -7
  6. package/dist/index.js +2 -6
  7. package/dist/index.js.map +1 -0
  8. package/dist/middleware/index.d.ts +45 -4
  9. package/dist/middleware/index.js +2 -6
  10. package/dist/middleware/index.js.map +1 -0
  11. package/dist/use-react/index.d.ts +82 -7
  12. package/dist/use-react/index.js +2 -7
  13. package/dist/use-react/index.js.map +1 -0
  14. package/package.json +25 -21
  15. package/dist/core/asyncChunk.d.ts +0 -28
  16. package/dist/core/asyncChunk.js +0 -50
  17. package/dist/core/computed.d.ts +0 -15
  18. package/dist/core/computed.js +0 -58
  19. package/dist/core/core.js +0 -102
  20. package/dist/core/selector.d.ts +0 -17
  21. package/dist/core/selector.js +0 -45
  22. package/dist/core/types.d.ts +0 -16
  23. package/dist/core/types.js +0 -1
  24. package/dist/middleware/history.d.ts +0 -30
  25. package/dist/middleware/history.js +0 -68
  26. package/dist/middleware/logger.d.ts +0 -2
  27. package/dist/middleware/logger.js +0 -4
  28. package/dist/middleware/persistence.d.ts +0 -8
  29. package/dist/middleware/persistence.js +0 -25
  30. package/dist/middleware/validator.d.ts +0 -2
  31. package/dist/middleware/validator.js +0 -6
  32. package/dist/use-react/hooks/useAsyncChunk.d.ts +0 -14
  33. package/dist/use-react/hooks/useAsyncChunk.js +0 -27
  34. package/dist/use-react/hooks/useChunk.d.ts +0 -6
  35. package/dist/use-react/hooks/useChunk.js +0 -26
  36. package/dist/use-react/hooks/useChunkProperty.d.ts +0 -6
  37. package/dist/use-react/hooks/useChunkProperty.js +0 -10
  38. package/dist/use-react/hooks/useChunkValue.d.ts +0 -6
  39. package/dist/use-react/hooks/useChunkValue.js +0 -9
  40. package/dist/use-react/hooks/useChunkValues.d.ts +0 -8
  41. package/dist/use-react/hooks/useChunkValues.js +0 -25
  42. package/dist/use-react/hooks/useComputed.d.ts +0 -7
  43. package/dist/use-react/hooks/useComputed.js +0 -22
  44. package/dist/use-react/hooks/useDerive.d.ts +0 -6
  45. package/dist/use-react/hooks/useDerive.js +0 -17
  46. package/dist/utils.d.ts +0 -15
  47. package/dist/utils.js +0 -113
@@ -1,58 +0,0 @@
1
- import { chunk } from "./core";
2
- import { shallowEqual } from "../utils";
3
- export function computed(dependencies, computeFn) {
4
- const dependencyValues = dependencies.map(dep => dep.get());
5
- let cachedValue = computeFn(...dependencyValues);
6
- const computedChunk = chunk(cachedValue);
7
- const originalSet = computedChunk.set;
8
- let isDirty = false;
9
- // Direct synchronous recomputation
10
- const recompute = () => {
11
- let hasChanges = false;
12
- for (let i = 0; i < dependencies.length; i++) {
13
- const newValue = dependencies[i].get();
14
- if (newValue !== dependencyValues[i]) {
15
- dependencyValues[i] = newValue;
16
- hasChanges = true;
17
- }
18
- }
19
- if (hasChanges) {
20
- const newValue = computeFn(...dependencyValues);
21
- // Fast path for primitives only. Avoids shallowEqual for performance.
22
- if (newValue !== cachedValue) {
23
- // Only use shallowEqual for objects when needed
24
- if (typeof newValue !== 'object' || typeof cachedValue !== 'object' || !shallowEqual(newValue, cachedValue)) {
25
- cachedValue = newValue;
26
- originalSet(newValue);
27
- }
28
- }
29
- isDirty = false;
30
- }
31
- };
32
- const unsubs = dependencies.map(dep => dep.subscribe(() => {
33
- isDirty = true;
34
- recompute();
35
- }));
36
- return {
37
- ...computedChunk,
38
- get: () => {
39
- if (isDirty)
40
- recompute();
41
- return cachedValue;
42
- },
43
- recompute,
44
- isDirty: () => isDirty,
45
- set: () => { throw new Error('Cannot set values directly on computed. Modify the source chunk instead.'); },
46
- reset: () => {
47
- dependencies.forEach(dep => {
48
- if (typeof dep.reset === 'function') {
49
- dep.reset();
50
- }
51
- });
52
- isDirty = true;
53
- recompute();
54
- return cachedValue;
55
- },
56
- destroy: () => { unsubs.forEach(unsub => unsub()); computedChunk.destroy?.(); }
57
- };
58
- }
package/dist/core/core.js DELETED
@@ -1,102 +0,0 @@
1
- import { processMiddleware } from "../utils";
2
- let isBatching = false;
3
- const dirtyChunks = new Set();
4
- const chunkRegistry = new Map();
5
- let chunkIdCounter = 0;
6
- /**
7
- * Batch multiple chunk updates into a single re-render.
8
- * Useful for updating multiple chunks at once without causing multiple re-renders.
9
- */
10
- export function batch(callback) {
11
- const wasBatchingBefore = isBatching;
12
- isBatching = true;
13
- try {
14
- callback();
15
- }
16
- finally {
17
- if (!wasBatchingBefore) {
18
- isBatching = false;
19
- const chunks = Array.from(dirtyChunks); // Snapshot to avoid mutation issues
20
- dirtyChunks.clear(); // Clear early to prevent re-adds
21
- chunks.forEach(id => {
22
- const chunk = chunkRegistry.get(id);
23
- if (chunk)
24
- chunk.notify();
25
- });
26
- }
27
- }
28
- }
29
- export function chunk(initialValue, middleware = []) {
30
- if (initialValue === undefined || initialValue === null) {
31
- throw new Error("Initial value cannot be undefined or null.");
32
- }
33
- let value = initialValue;
34
- const subscribers = new Set();
35
- const chunkId = chunkIdCounter++;
36
- const notify = () => {
37
- subscribers.forEach(subscriber => subscriber(value));
38
- };
39
- chunkRegistry.set(chunkId, { notify });
40
- const notifySubscribers = () => {
41
- if (subscribers.size === 0)
42
- return; // Skip if no subscribers
43
- if (isBatching) {
44
- dirtyChunks.add(chunkId);
45
- }
46
- else {
47
- notify();
48
- }
49
- };
50
- const get = () => value;
51
- const set = (newValueOrUpdater) => {
52
- let newValue;
53
- if (typeof newValueOrUpdater === 'function') {
54
- newValue = newValueOrUpdater(value);
55
- }
56
- else {
57
- newValue = newValueOrUpdater;
58
- }
59
- const processedValue = processMiddleware(newValue, middleware);
60
- if (processedValue !== value) {
61
- value = processedValue;
62
- notifySubscribers();
63
- }
64
- };
65
- const subscribe = (callback) => {
66
- if (typeof callback !== "function") {
67
- throw new Error("Callback must be a function.");
68
- }
69
- subscribers.add(callback);
70
- callback(value);
71
- return () => subscribers.delete(callback);
72
- };
73
- const reset = () => {
74
- value = initialValue;
75
- notifySubscribers();
76
- };
77
- const destroy = () => {
78
- subscribers.clear();
79
- value = initialValue;
80
- dirtyChunks.delete(chunkId);
81
- chunkRegistry.delete(chunkId);
82
- };
83
- const derive = (fn) => {
84
- if (typeof fn !== "function") {
85
- throw new Error("Derive function must be a function.");
86
- }
87
- const initialDerivedValue = fn(value);
88
- const derivedChunk = chunk(initialDerivedValue);
89
- const unsubscribe = subscribe(() => {
90
- const newDerivedValue = fn(value);
91
- derivedChunk.set(newDerivedValue);
92
- });
93
- // Add a cleanup method to the derived chunk
94
- const originalDestroy = derivedChunk.destroy;
95
- derivedChunk.destroy = () => {
96
- unsubscribe();
97
- originalDestroy();
98
- };
99
- return derivedChunk;
100
- };
101
- return { get, set, subscribe, derive, reset, destroy };
102
- }
@@ -1,17 +0,0 @@
1
- import { Chunk } from "./core";
2
- export interface SelectOptions {
3
- /**
4
- * Configuration options for selector functions.
5
- * @property {boolean} [useShallowEqual] - When true, performs a shallow equality check
6
- * on the derived selector results to prevent unnecessary updates.
7
- */
8
- useShallowEqual?: boolean;
9
- }
10
- /**
11
- * Creates a derived read-only chunk based on a selector function.
12
- * @param sourceChunk The source chunk to derive from.
13
- * @param selector A function that extracts part of the source value.
14
- * @param options Optional settings for shallow equality comparison.
15
- * @returns A read-only derived chunk.
16
- */
17
- export declare function select<T, S>(sourceChunk: Chunk<T>, selector: (value: T) => S, options?: SelectOptions): Chunk<S>;
@@ -1,45 +0,0 @@
1
- import { shallowEqual } from "../utils";
2
- import { chunk } from "./core";
3
- /**
4
- * Creates a derived read-only chunk based on a selector function.
5
- * @param sourceChunk The source chunk to derive from.
6
- * @param selector A function that extracts part of the source value.
7
- * @param options Optional settings for shallow equality comparison.
8
- * @returns A read-only derived chunk.
9
- */
10
- export function select(sourceChunk, selector, options = {}) {
11
- const { useShallowEqual = false } = options;
12
- let prevSourceValue = sourceChunk.get();
13
- let currentResult = selector(prevSourceValue);
14
- const derivedChunk = chunk(currentResult);
15
- const update = () => {
16
- const newSourceValue = sourceChunk.get();
17
- const newResult = selector(newSourceValue);
18
- // Always update the reference to source value
19
- prevSourceValue = newSourceValue;
20
- // Check if the result has changed
21
- const resultChanged = useShallowEqual
22
- ? !shallowEqual(newResult, currentResult)
23
- : newResult !== currentResult;
24
- if (resultChanged) {
25
- currentResult = newResult;
26
- derivedChunk.set(newResult);
27
- }
28
- };
29
- const unsubscribe = sourceChunk.subscribe(update);
30
- return {
31
- get: () => derivedChunk.get(),
32
- set: () => {
33
- throw new Error('Cannot set values directly on a selector. Modify the source chunk instead.');
34
- },
35
- subscribe: derivedChunk.subscribe,
36
- derive: (fn) => select(derivedChunk, fn, options), // Pass options to nested selectors
37
- reset: () => {
38
- throw new Error('Cannot reset a selector chunk. Reset the source chunk instead.');
39
- },
40
- destroy: () => {
41
- unsubscribe();
42
- derivedChunk.destroy();
43
- }
44
- };
45
- }
@@ -1,16 +0,0 @@
1
- import { AsyncChunk } from "./asyncChunk";
2
- export type AsyncChunkOpt<T, E extends Error> = {
3
- initialData?: T | null;
4
- onError?: (error: E) => void;
5
- retryCount?: number;
6
- retryDelay?: number;
7
- };
8
- export type InferAsyncData<T> = T extends AsyncChunk<infer U, Error> ? U : never;
9
- export type CombinedData<T> = {
10
- [K in keyof T]: InferAsyncData<T[K]> | null;
11
- };
12
- export type CombinedState<T> = {
13
- loading: boolean;
14
- error: Error | null;
15
- data: CombinedData<T>;
16
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,30 +0,0 @@
1
- import { Chunk } from "../core/core";
2
- export interface ChunkWithHistory<T> extends Chunk<T> {
3
- /**
4
- * Reverts to the previous state (if available).
5
- */
6
- undo: () => void;
7
- /**
8
- * Moves to the next state (if available).
9
- */
10
- redo: () => void;
11
- /**
12
- * Returns true if there is a previous state to revert to.
13
- */
14
- canUndo: () => boolean;
15
- /**
16
- * Returns true if there is a next state to move to.
17
- */
18
- canRedo: () => boolean;
19
- /**
20
- * Returns an array of all the values in the history.
21
- */
22
- getHistory: () => T[];
23
- /**
24
- * Clears the history, keeping only the current value.
25
- */
26
- clearHistory: () => void;
27
- }
28
- export declare function withHistory<T>(baseChunk: Chunk<T>, options?: {
29
- maxHistory?: number;
30
- }): ChunkWithHistory<T>;
@@ -1,68 +0,0 @@
1
- export function withHistory(baseChunk, options = {}) {
2
- const { maxHistory = 100 } = options;
3
- const history = [baseChunk.get()];
4
- let currentIndex = 0;
5
- let isHistoryAction = false;
6
- const historyChunk = {
7
- ...baseChunk,
8
- set: (newValueOrUpdater) => {
9
- if (isHistoryAction) {
10
- baseChunk.set(newValueOrUpdater);
11
- return;
12
- }
13
- // Process the value or updater function
14
- let newValue;
15
- if (typeof newValueOrUpdater === 'function') {
16
- // Get current value and apply the updater function
17
- const currentValue = baseChunk.get();
18
- newValue = newValueOrUpdater(currentValue);
19
- }
20
- else {
21
- // Use directly as the new value
22
- newValue = newValueOrUpdater;
23
- }
24
- history.splice(currentIndex + 1);
25
- history.push(newValue);
26
- // Limit history size
27
- if (history.length > maxHistory) {
28
- console.warn("History limit reached. Removing oldest entries.");
29
- const removeCount = history.length - maxHistory;
30
- history.splice(0, removeCount);
31
- currentIndex = Math.max(0, currentIndex - removeCount);
32
- }
33
- currentIndex = history.length - 1;
34
- baseChunk.set(newValue);
35
- },
36
- undo: () => {
37
- if (!historyChunk.canUndo())
38
- return;
39
- isHistoryAction = true;
40
- currentIndex--;
41
- historyChunk.set(history[currentIndex]);
42
- isHistoryAction = false;
43
- },
44
- redo: () => {
45
- if (!historyChunk.canRedo())
46
- return;
47
- isHistoryAction = true;
48
- currentIndex++;
49
- historyChunk.set(history[currentIndex]);
50
- isHistoryAction = false;
51
- },
52
- canUndo: () => currentIndex > 0,
53
- canRedo: () => currentIndex < history.length - 1,
54
- getHistory: () => [...history],
55
- clearHistory: () => {
56
- const currentValue = baseChunk.get();
57
- history.length = 0;
58
- history.push(currentValue);
59
- currentIndex = 0;
60
- },
61
- // Override destroy to clean up history
62
- destroy: () => {
63
- history.length = 0;
64
- baseChunk.destroy();
65
- }
66
- };
67
- return historyChunk;
68
- }
@@ -1,2 +0,0 @@
1
- import { Middleware } from "../core/core";
2
- export declare const logger: Middleware<any>;
@@ -1,4 +0,0 @@
1
- export const logger = (value, next) => {
2
- console.log("Setting value:", value);
3
- next(value);
4
- };
@@ -1,8 +0,0 @@
1
- import { Chunk } from "../core/core";
2
- export interface PersistOptions<T> {
3
- key: string;
4
- storage?: Storage;
5
- serialize?: (value: T) => string;
6
- deserialize?: (value: string) => T;
7
- }
8
- export declare function withPersistence<T>(baseChunk: Chunk<T>, options: PersistOptions<T>): Chunk<T>;
@@ -1,25 +0,0 @@
1
- export function withPersistence(baseChunk, options) {
2
- const { key, storage = localStorage, serialize = JSON.stringify, deserialize = JSON.parse, } = options;
3
- // Try to load initial state from storage
4
- try {
5
- const savedChunk = storage.getItem(key);
6
- if (savedChunk) {
7
- const parsed = deserialize(savedChunk);
8
- baseChunk.set(parsed);
9
- }
10
- }
11
- catch (error) {
12
- console.error('Failed to load persisted state:', error);
13
- }
14
- // Save to storage
15
- baseChunk.subscribe((newValue) => {
16
- try {
17
- const serialized = serialize(newValue);
18
- storage.setItem(key, serialized);
19
- }
20
- catch (error) {
21
- console.log('Failed to persist chunk', error);
22
- }
23
- });
24
- return baseChunk;
25
- }
@@ -1,2 +0,0 @@
1
- import { Middleware } from "../core/core";
2
- export declare const nonNegativeValidator: Middleware<number>;
@@ -1,6 +0,0 @@
1
- export const nonNegativeValidator = (value, next) => {
2
- if (value < 0) {
3
- throw new Error("Value must be non-negative!");
4
- }
5
- next(value); // If validation passes, proceed with the update
6
- };
@@ -1,14 +0,0 @@
1
- import { AsyncChunk, AsyncState } from "../../core/asyncChunk";
2
- /**
3
- * A hook that handles asynchronous state with built-in reactivity.
4
- * Provides loading, error, and data states.
5
- */
6
- export declare function useAsyncChunk<T, E extends Error>(asyncChunk: AsyncChunk<T, E>): {
7
- state: AsyncState<T, E>;
8
- data: T | null;
9
- loading: boolean;
10
- error: E | null;
11
- reload: () => Promise<void>;
12
- mutate: (mutator: (currentData: T | null) => T) => void;
13
- reset: () => void;
14
- };
@@ -1,27 +0,0 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- /**
3
- * A hook that handles asynchronous state with built-in reactivity.
4
- * Provides loading, error, and data states.
5
- */
6
- export function useAsyncChunk(asyncChunk) {
7
- const [state, setState] = useState(() => asyncChunk.get());
8
- useEffect(() => {
9
- const unsubscribe = asyncChunk.subscribe((newState) => {
10
- setState(newState);
11
- });
12
- return () => unsubscribe();
13
- }, [asyncChunk]);
14
- const reload = useCallback(() => asyncChunk.reload(), [asyncChunk]);
15
- const mutate = useCallback((mutator) => asyncChunk.mutate(mutator), [asyncChunk]);
16
- const reset = useCallback(() => asyncChunk.reset(), [asyncChunk]);
17
- const { data, loading, error } = state;
18
- return {
19
- state,
20
- data,
21
- loading,
22
- error,
23
- reload,
24
- mutate,
25
- reset,
26
- };
27
- }
@@ -1,6 +0,0 @@
1
- import type { Chunk } from "../../core/core";
2
- /**
3
- * A lightweight hook that subscribes to a chunk and returns its current value, along with setters, selector, reset and destroy.
4
- * Ensures reactivity and prevents unnecessary re-renders.
5
- */
6
- export declare function useChunk<T, S = T>(chunk: Chunk<T>, selector?: (value: T) => S): readonly [S, (valueOrUpdater: T | ((currentValue: T) => T)) => void, () => void, () => void];
@@ -1,26 +0,0 @@
1
- import { useState, useEffect, useCallback } from "react";
2
- import { select } from "../../core/selector";
3
- /**
4
- * A lightweight hook that subscribes to a chunk and returns its current value, along with setters, selector, reset and destroy.
5
- * Ensures reactivity and prevents unnecessary re-renders.
6
- */
7
- export function useChunk(chunk, selector) {
8
- const selectedChunk = selector ? select(chunk, selector) : chunk;
9
- const [state, setState] = useState(() => selectedChunk.get());
10
- useEffect(() => {
11
- const unsubscribe = selectedChunk.subscribe((newValue) => {
12
- setState(() => newValue);
13
- });
14
- return () => unsubscribe();
15
- }, [selectedChunk]);
16
- const set = useCallback((valueOrUpdater) => {
17
- chunk.set(valueOrUpdater);
18
- }, [chunk]);
19
- const reset = useCallback(() => {
20
- chunk.reset();
21
- }, [chunk]);
22
- const destroy = useCallback(() => {
23
- chunk.destroy();
24
- }, [chunk]);
25
- return [state, set, reset, destroy];
26
- }
@@ -1,6 +0,0 @@
1
- import type { Chunk } from "../../core/core";
2
- /**
3
- * A hook that subscribes to a specific property of a chunk.
4
- * This optimizes renders by only updating when the selected property changes.
5
- */
6
- export declare function useChunkProperty<T, K extends keyof T>(chunk: Chunk<T>, property: K): T[K];
@@ -1,10 +0,0 @@
1
- import { useMemo } from "react";
2
- import { useChunkValue } from "./useChunkValue";
3
- /**
4
- * A hook that subscribes to a specific property of a chunk.
5
- * This optimizes renders by only updating when the selected property changes.
6
- */
7
- export function useChunkProperty(chunk, property) {
8
- const selector = useMemo(() => (state) => state[property], [property]);
9
- return useChunkValue(chunk, selector);
10
- }
@@ -1,6 +0,0 @@
1
- import type { Chunk } from "../../core/core";
2
- /**
3
- * A lightweight hook that subscribes to a chunk and returns only its current value.
4
- * Useful for read-only components that don't need to update the chunk.
5
- */
6
- export declare function useChunkValue<T, S = T>(chunk: Chunk<T>, selector?: (value: T) => S): S;
@@ -1,9 +0,0 @@
1
- import { useChunk } from "./useChunk";
2
- /**
3
- * A lightweight hook that subscribes to a chunk and returns only its current value.
4
- * Useful for read-only components that don't need to update the chunk.
5
- */
6
- export function useChunkValue(chunk, selector) {
7
- const [value] = useChunk(chunk, selector);
8
- return value;
9
- }
@@ -1,8 +0,0 @@
1
- import type { Chunk } from "../../core/core";
2
- /**
3
- * Hook to read values from multiple chunks at once.
4
- * Only re-renders when any of the chunk values change.
5
- */
6
- export declare function useChunkValues<T extends Chunk<any>[]>(chunks: [...T]): {
7
- [K in keyof T]: T[K] extends Chunk<infer U> ? U : never;
8
- };
@@ -1,25 +0,0 @@
1
- import { useState, useEffect } from "react";
2
- /**
3
- * Hook to read values from multiple chunks at once.
4
- * Only re-renders when any of the chunk values change.
5
- */
6
- export function useChunkValues(chunks) {
7
- const [values, setValues] = useState(() => {
8
- return chunks.map(chunk => chunk.get());
9
- });
10
- useEffect(() => {
11
- const unsubscribes = chunks.map((chunk, index) => {
12
- return chunk.subscribe((newValue) => {
13
- setValues(prev => {
14
- const newValues = [...prev];
15
- newValues[index] = newValue;
16
- return newValues;
17
- });
18
- });
19
- });
20
- return () => {
21
- unsubscribes.forEach(unsubscribe => unsubscribe());
22
- };
23
- }, [chunks]);
24
- return values;
25
- }
@@ -1,7 +0,0 @@
1
- import { DependencyValues } from "../../core/computed";
2
- import type { Chunk } from "../../core/core";
3
- /**
4
- * A hook that computes a value based on multiple chunks.
5
- * Automatically re-computes when any dependency changes.
6
- */
7
- export declare function useComputed<TDeps extends Chunk<any>[], TResult>(dependencies: [...TDeps], computeFn: (...args: DependencyValues<TDeps>) => TResult): TResult;
@@ -1,22 +0,0 @@
1
- import { useState, useEffect, useMemo } from "react";
2
- import { computed } from "../../core/computed";
3
- /**
4
- * A hook that computes a value based on multiple chunks.
5
- * Automatically re-computes when any dependency changes.
6
- */
7
- export function useComputed(dependencies, computeFn) {
8
- // Create the computed value - memoize it based on dependencies to prevent recreation
9
- const computedValue = useMemo(() => computed(dependencies, computeFn),
10
- // eslint-disable-next-line react-hooks/exhaustive-deps
11
- [...dependencies]);
12
- const [state, setState] = useState(() => computedValue.get());
13
- useEffect(() => {
14
- const unsubscribe = computedValue.subscribe((newValue) => {
15
- setState(newValue);
16
- });
17
- return () => {
18
- unsubscribe();
19
- };
20
- }, [computedValue]);
21
- return state;
22
- }
@@ -1,6 +0,0 @@
1
- import type { Chunk } from "../../core/core";
2
- /**
3
- * A hook for creating a read-only derived value from a chunk.
4
- * Ensures reactivity and updates when the source chunk changes.
5
- */
6
- export declare function useDerive<T, D>(chunk: Chunk<T>, fn: (value: T) => D): D;
@@ -1,17 +0,0 @@
1
- import { useEffect, useMemo, useRef } from "react";
2
- import { useChunk } from "./useChunk";
3
- /**
4
- * A hook for creating a read-only derived value from a chunk.
5
- * Ensures reactivity and updates when the source chunk changes.
6
- */
7
- export function useDerive(chunk, fn) {
8
- const fnRef = useRef(fn);
9
- useEffect(() => {
10
- fnRef.current = fn;
11
- }, [fn]);
12
- const derivedChunk = useMemo(() => {
13
- return chunk.derive((value) => fnRef.current(value));
14
- }, [chunk]);
15
- const [derivedValue] = useChunk(derivedChunk);
16
- return derivedValue;
17
- }
package/dist/utils.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import { Chunk, Middleware } from "./core/core";
2
- import { AsyncChunk } from "./core/asyncChunk";
3
- import { InferAsyncData } from "./core/types";
4
- export declare function isValidChunkValue(value: any): boolean;
5
- export declare function isChunk<T>(value: any): value is Chunk<T>;
6
- export declare function once<T>(fn: () => T): () => T;
7
- export declare function combineAsyncChunks<T extends Record<string, AsyncChunk<any>>>(chunks: T): Chunk<{
8
- loading: boolean;
9
- error: Error | null;
10
- data: {
11
- [K in keyof T]: InferAsyncData<T[K]> | null;
12
- };
13
- }>;
14
- export declare function processMiddleware<T>(initialValue: T, middleware?: Middleware<T>[]): T;
15
- export declare function shallowEqual<T>(a: T, b: T): boolean;