juststore 0.4.1 → 0.4.3
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/dist/atom.d.ts +46 -0
- package/dist/atom.js +136 -0
- package/dist/form.d.ts +23 -11
- package/dist/form.js +51 -58
- package/dist/impl.d.ts +27 -9
- package/dist/impl.js +117 -214
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/kv_store.d.ts +29 -0
- package/dist/kv_store.js +119 -0
- package/dist/mixed_state.js +15 -1
- package/dist/node.d.ts +4 -4
- package/dist/node.js +2 -2
- package/dist/root.d.ts +4 -4
- package/dist/root.js +31 -25
- package/dist/stable_keys.d.ts +4 -0
- package/dist/stable_keys.js +31 -0
- package/dist/types.d.ts +20 -20
- package/package.json +1 -1
package/dist/atom.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export { createAtom, type Atom };
|
|
2
|
+
/**
|
|
3
|
+
* An atom is a value that can be subscribed to and updated.
|
|
4
|
+
*
|
|
5
|
+
* @param T - The type of the value
|
|
6
|
+
* @returns The atom
|
|
7
|
+
*/
|
|
8
|
+
type Atom<T> = {
|
|
9
|
+
/** The current value. */
|
|
10
|
+
readonly value: T;
|
|
11
|
+
/** Subscribe to the value. */
|
|
12
|
+
use: () => T;
|
|
13
|
+
/** Set the value. */
|
|
14
|
+
set: (value: T) => void;
|
|
15
|
+
/** Reset the value to the default value. */
|
|
16
|
+
reset: () => void;
|
|
17
|
+
/** Subscribe to the value.with a callback function. */
|
|
18
|
+
subscribe: (listener: (value: T) => void) => () => void;
|
|
19
|
+
/** Render the value. */
|
|
20
|
+
Render: ({ children }: {
|
|
21
|
+
children: (value: T, setValue: (value: T) => void) => React.ReactNode;
|
|
22
|
+
}) => React.ReactNode;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates an atom with a given id and default value.
|
|
26
|
+
*
|
|
27
|
+
* @param id - The id of the atom
|
|
28
|
+
* @param defaultValue - The default value of the atom
|
|
29
|
+
* @returns The atom
|
|
30
|
+
* @example
|
|
31
|
+
* const stateA = createAtom(useId(), false)
|
|
32
|
+
* return (
|
|
33
|
+
* <>
|
|
34
|
+
* <ComponentA/>
|
|
35
|
+
* <ComponentB/>
|
|
36
|
+
* <stateA.Render>
|
|
37
|
+
* {(value, setValue) => (
|
|
38
|
+
* <button onClick={() => setValue(!value)}>{value ? 'Hide' : 'Show'}</button>
|
|
39
|
+
* )}
|
|
40
|
+
* </stateA.Render>
|
|
41
|
+
* <ComponentC/>
|
|
42
|
+
* <ComponentD/>
|
|
43
|
+
* </>
|
|
44
|
+
* )
|
|
45
|
+
*/
|
|
46
|
+
declare function createAtom<T>(id: string, defaultValue: T, persistent?: boolean): Atom<T>;
|
package/dist/atom.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
import { getSnapshot, updateSnapshot } from './impl';
|
|
3
|
+
export { createAtom };
|
|
4
|
+
/**
|
|
5
|
+
* Creates an atom with a given id and default value.
|
|
6
|
+
*
|
|
7
|
+
* @param id - The id of the atom
|
|
8
|
+
* @param defaultValue - The default value of the atom
|
|
9
|
+
* @returns The atom
|
|
10
|
+
* @example
|
|
11
|
+
* const stateA = createAtom(useId(), false)
|
|
12
|
+
* return (
|
|
13
|
+
* <>
|
|
14
|
+
* <ComponentA/>
|
|
15
|
+
* <ComponentB/>
|
|
16
|
+
* <stateA.Render>
|
|
17
|
+
* {(value, setValue) => (
|
|
18
|
+
* <button onClick={() => setValue(!value)}>{value ? 'Hide' : 'Show'}</button>
|
|
19
|
+
* )}
|
|
20
|
+
* </stateA.Render>
|
|
21
|
+
* <ComponentC/>
|
|
22
|
+
* <ComponentD/>
|
|
23
|
+
* </>
|
|
24
|
+
* )
|
|
25
|
+
*/
|
|
26
|
+
function createAtom(id, defaultValue, persistent = false) {
|
|
27
|
+
const key = `atom:${id}`;
|
|
28
|
+
const memoryOnly = !persistent;
|
|
29
|
+
// set the default value
|
|
30
|
+
// so getAtom will never return undefined
|
|
31
|
+
if (getAtom(key, memoryOnly) === undefined) {
|
|
32
|
+
setAtom(key, defaultValue, memoryOnly);
|
|
33
|
+
}
|
|
34
|
+
const atomProxy = new Proxy({}, {
|
|
35
|
+
get(target, prop) {
|
|
36
|
+
const cacheKey = `_${String(prop)}`;
|
|
37
|
+
if (cacheKey in target) {
|
|
38
|
+
// return cached methods first
|
|
39
|
+
return target[cacheKey];
|
|
40
|
+
}
|
|
41
|
+
if (prop === 'value') {
|
|
42
|
+
return getAtom(key, memoryOnly);
|
|
43
|
+
}
|
|
44
|
+
if (prop === 'use') {
|
|
45
|
+
return (target._use ??= () => useAtom(key, memoryOnly));
|
|
46
|
+
}
|
|
47
|
+
if (prop === 'set') {
|
|
48
|
+
return (target._set ??= (value) => setAtom(key, value, memoryOnly));
|
|
49
|
+
}
|
|
50
|
+
if (prop === 'reset') {
|
|
51
|
+
return (target._reset ??= () => setAtom(key, defaultValue, memoryOnly));
|
|
52
|
+
}
|
|
53
|
+
if (prop === 'subscribe') {
|
|
54
|
+
return (target._subscribe ??= (listener) => subscribeAtom(key, memoryOnly, listener));
|
|
55
|
+
}
|
|
56
|
+
if (prop === 'Render') {
|
|
57
|
+
return (target._Render ??= ({ children }) => children(useAtom(key, memoryOnly), (value) => setAtom(key, value, memoryOnly)));
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return atomProxy;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* React hook that subscribes to and reads a value at a path.
|
|
66
|
+
*
|
|
67
|
+
* Uses useSyncExternalStore for tear-free reads and automatic re-rendering
|
|
68
|
+
* when the subscribed value changes.
|
|
69
|
+
*
|
|
70
|
+
* @param key - The namespace
|
|
71
|
+
* @param memoryOnly - When true, skips localStorage persistence
|
|
72
|
+
* @returns The current value at the namespace, or the default value if not set
|
|
73
|
+
*/
|
|
74
|
+
function useAtom(key, memoryOnly = true) {
|
|
75
|
+
const value = useSyncExternalStore(listener => subscribeAtom(key, memoryOnly, listener), () => getSnapshot(key, memoryOnly), () => getSnapshot(key, memoryOnly));
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Gets a value from an atom.
|
|
80
|
+
*
|
|
81
|
+
* @param key - The namespace
|
|
82
|
+
* @returns The value, or the default value if not set
|
|
83
|
+
*/
|
|
84
|
+
function getAtom(key, memoryOnly = true) {
|
|
85
|
+
return getSnapshot(key, memoryOnly);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Sets a value at a specific path within a namespace.
|
|
89
|
+
*
|
|
90
|
+
* @param key - The namespace
|
|
91
|
+
* @param value - The value to set
|
|
92
|
+
* @param memoryOnly - When true, skips localStorage persistence
|
|
93
|
+
*/
|
|
94
|
+
function setAtom(key, value, memoryOnly = true) {
|
|
95
|
+
updateSnapshot(key, value, memoryOnly);
|
|
96
|
+
notifyAtom(key);
|
|
97
|
+
}
|
|
98
|
+
const listeners = new Map();
|
|
99
|
+
/**
|
|
100
|
+
* Subscribes to changes for an atom.
|
|
101
|
+
*
|
|
102
|
+
* @param key - The full key path to subscribe to
|
|
103
|
+
* @param listener - Callback invoked when the value changes
|
|
104
|
+
* @returns An unsubscribe function to remove the listener
|
|
105
|
+
*/
|
|
106
|
+
function subscribeAtom(key, memoryOnly, listener) {
|
|
107
|
+
let listenerSet = listeners.get(key);
|
|
108
|
+
if (!listenerSet) {
|
|
109
|
+
listenerSet = new Set();
|
|
110
|
+
listeners.set(key, listenerSet);
|
|
111
|
+
}
|
|
112
|
+
const atomListener = () => listener(getAtom(key, memoryOnly));
|
|
113
|
+
listenerSet.add(atomListener);
|
|
114
|
+
return () => {
|
|
115
|
+
const keyListeners = listeners.get(key);
|
|
116
|
+
if (keyListeners) {
|
|
117
|
+
keyListeners.delete(atomListener);
|
|
118
|
+
if (keyListeners.size === 0) {
|
|
119
|
+
listeners.delete(key);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Notifies all listeners for an atom.
|
|
126
|
+
*
|
|
127
|
+
* @param namespace - The namespace
|
|
128
|
+
*/
|
|
129
|
+
function notifyAtom(namespace) {
|
|
130
|
+
const listenerSet = listeners.get(namespace);
|
|
131
|
+
if (!listenerSet)
|
|
132
|
+
return;
|
|
133
|
+
for (const listener of listenerSet) {
|
|
134
|
+
listener();
|
|
135
|
+
}
|
|
136
|
+
}
|
package/dist/form.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FieldPath, FieldPathValue, FieldValues, IsEqual } from './path';
|
|
2
|
-
import type { ArrayProxy, IsNullable, MaybeNullable, ObjectMutationMethods, ValueState } from './types';
|
|
3
|
-
export { useForm, type CreateFormOptions, type DeepNonNullable, type FormArrayState, type FormObjectState, type FormState, type FormStore, type FormValueState };
|
|
2
|
+
import type { ArrayProxy, DerivedStateProps, IsNullable, MaybeNullable, ObjectMutationMethods, Prettify, ValueState } from './types';
|
|
3
|
+
export { createForm, useForm, type CreateFormOptions, type DeepNonNullable, type FormArrayState, type FormObjectState, type FormState, type FormStore, type FormValueState };
|
|
4
4
|
/**
|
|
5
5
|
* Common form field methods available on every form state node.
|
|
6
6
|
*/
|
|
@@ -13,7 +13,12 @@ type FormCommon = {
|
|
|
13
13
|
setError: (error: string | undefined) => void;
|
|
14
14
|
};
|
|
15
15
|
type FormState<T> = IsEqual<T, unknown> extends true ? never : [NonNullable<T>] extends [readonly (infer U)[]] ? FormArrayState<U, IsNullable<T>> : [NonNullable<T>] extends [FieldValues] ? FormObjectState<NonNullable<T>, IsNullable<T>> : FormValueState<T>;
|
|
16
|
-
|
|
16
|
+
type FormReadOnlyState<T> = Prettify<Pick<FormValueState<Readonly<Required<T>>>, 'value' | 'use' | 'useCompute' | 'Render' | 'Show' | 'error' | 'setError'>>;
|
|
17
|
+
interface FormValueState<T> extends Omit<ValueState<T>, 'ensureArray' | 'ensureObject' | 'withDefault' | 'derived'>, FormCommon {
|
|
18
|
+
/** Ensure the value is an array. */
|
|
19
|
+
ensureArray(): NonNullable<T> extends (infer U)[] ? FormArrayState<U> : never;
|
|
20
|
+
/** Ensure the value is an object. */
|
|
21
|
+
ensureObject(): NonNullable<T> extends FieldValues ? FormObjectState<NonNullable<T>> : never;
|
|
17
22
|
/** Return a new state with a default value, and make the type non-nullable */
|
|
18
23
|
withDefault(defaultValue: T): FormState<NonNullable<T>>;
|
|
19
24
|
/** Virtual state derived from the current value.
|
|
@@ -28,15 +33,19 @@ interface FormValueState<T> extends Omit<ValueState<T>, 'withDefault' | 'derived
|
|
|
28
33
|
* state.set(10) // sets the derived value
|
|
29
34
|
* state.reset() // resets the derived value
|
|
30
35
|
*/
|
|
31
|
-
derived: <R>({ from, to }:
|
|
32
|
-
from?: (value: T | undefined) => R;
|
|
33
|
-
to?: (value: R) => T | undefined;
|
|
34
|
-
}) => FormState<R>;
|
|
36
|
+
derived: <R>({ from, to }: DerivedStateProps<T, R>) => FormState<R>;
|
|
35
37
|
}
|
|
36
|
-
type
|
|
37
|
-
|
|
38
|
+
type FormObjectProxy<T extends FieldValues> = {
|
|
39
|
+
/** Virtual state for the object's keys.
|
|
40
|
+
*
|
|
41
|
+
* This does NOT read from a real `keys` property on the stored object; it results in a stable array of keys.
|
|
42
|
+
*/
|
|
43
|
+
readonly keys: FormReadOnlyState<FieldPath<T>[]>;
|
|
44
|
+
} & {
|
|
38
45
|
[K in keyof T]-?: FormState<T[K]>;
|
|
39
|
-
}
|
|
46
|
+
};
|
|
47
|
+
type FormArrayState<T, Nullable extends boolean = false> = IsEqual<T, unknown> extends true ? never : FormValueState<MaybeNullable<T[], Nullable>> & ArrayProxy<T, FormState<T>>;
|
|
48
|
+
type FormObjectState<T extends FieldValues, Nullable extends boolean = false> = FormObjectProxy<T> & FormValueState<MaybeNullable<T, Nullable>> & ObjectMutationMethods;
|
|
40
49
|
/** Type for nested objects with proxy methods */
|
|
41
50
|
type DeepNonNullable<T> = [NonNullable<T>] extends [readonly (infer U)[]] ? U[] : [NonNullable<T>] extends [FieldValues] ? {
|
|
42
51
|
[K in keyof NonNullable<T>]-?: DeepNonNullable<NonNullable<T>[K]>;
|
|
@@ -52,12 +61,14 @@ type FormStore<T extends FieldValues> = FormState<T> & {
|
|
|
52
61
|
};
|
|
53
62
|
type NoEmptyValidator = 'not-empty';
|
|
54
63
|
type RegexValidator = RegExp;
|
|
55
|
-
type FunctionValidator<T extends FieldValues> = (value: FieldPathValue<T, FieldPath<T
|
|
64
|
+
type FunctionValidator<T extends FieldValues> = (value: FieldPathValue<T, FieldPath<T>>, state: FormStore<T>) => string | undefined;
|
|
56
65
|
type Validator<T extends FieldValues> = NoEmptyValidator | RegexValidator | FunctionValidator<T>;
|
|
57
66
|
type FieldConfig<T extends FieldValues> = {
|
|
58
67
|
validate?: Validator<T>;
|
|
59
68
|
};
|
|
60
69
|
type CreateFormOptions<T extends FieldValues> = Partial<Record<FieldPath<T>, FieldConfig<T>>>;
|
|
70
|
+
type UnsubscribeFn = () => void;
|
|
71
|
+
type UnsubscribeFns = UnsubscribeFn[];
|
|
61
72
|
/**
|
|
62
73
|
* React hook that creates a form store with validation support.
|
|
63
74
|
*
|
|
@@ -83,3 +94,4 @@ type CreateFormOptions<T extends FieldValues> = Partial<Record<FieldPath<T>, Fie
|
|
|
83
94
|
* </form>
|
|
84
95
|
*/
|
|
85
96
|
declare function useForm<T extends FieldValues>(defaultValue: T, fieldConfigs?: CreateFormOptions<T>): FormStore<T>;
|
|
97
|
+
declare function createForm<T extends FieldValues>(namespace: string, defaultValue: T, fieldConfigs?: CreateFormOptions<T>): [FormStore<T>, UnsubscribeFns];
|
package/dist/form.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useEffect, useId, useMemo } from 'react';
|
|
|
5
5
|
import { getSnapshot, produce } from './impl';
|
|
6
6
|
import { createNode } from './node';
|
|
7
7
|
import { createStoreRoot } from './root';
|
|
8
|
-
export { useForm };
|
|
8
|
+
export { createForm, useForm };
|
|
9
9
|
/**
|
|
10
10
|
* React hook that creates a form store with validation support.
|
|
11
11
|
*
|
|
@@ -33,61 +33,57 @@ export { useForm };
|
|
|
33
33
|
function useForm(defaultValue, fieldConfigs = {}) {
|
|
34
34
|
const formId = useId();
|
|
35
35
|
const namespace = `form:${formId}`;
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const [form, unsubscribeFns] = useMemo(() => createForm(namespace, defaultValue, fieldConfigs), [namespace, defaultValue, fieldConfigs]);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
return () => {
|
|
39
|
+
for (const unsubscribe of unsubscribeFns) {
|
|
40
|
+
unsubscribe();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}, [unsubscribeFns]);
|
|
44
|
+
return form;
|
|
45
|
+
}
|
|
46
|
+
function createForm(namespace, defaultValue, fieldConfigs = {}) {
|
|
47
|
+
const errorNamespace = `_juststore_form_errors.${namespace}`;
|
|
38
48
|
const errorStore = createStoreRoot(errorNamespace, {}, { memoryOnly: true });
|
|
39
|
-
const
|
|
49
|
+
const storeApi = createStoreRoot(namespace, defaultValue, { memoryOnly: true });
|
|
50
|
+
const formApi = {
|
|
40
51
|
clearErrors: () => produce(errorNamespace, undefined, false, true),
|
|
41
52
|
handleSubmit: (onSubmit) => (e) => {
|
|
42
53
|
e.preventDefault();
|
|
43
54
|
// disable submit if there are errors
|
|
44
|
-
if (Object.keys(getSnapshot(errorNamespace) ?? {}).length === 0) {
|
|
45
|
-
onSubmit(getSnapshot(namespace));
|
|
55
|
+
if (Object.keys(getSnapshot(errorNamespace, true) ?? {}).length === 0) {
|
|
56
|
+
onSubmit(getSnapshot(namespace, true));
|
|
46
57
|
}
|
|
47
58
|
}
|
|
48
|
-
}
|
|
49
|
-
const store =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (prop in storeApi) {
|
|
55
|
-
return storeApi[prop];
|
|
56
|
-
}
|
|
57
|
-
if (typeof prop === 'string') {
|
|
58
|
-
return createFormProxy(storeApi, errorStore, prop);
|
|
59
|
+
};
|
|
60
|
+
const store = createFormProxy(storeApi, errorStore);
|
|
61
|
+
const proxy = new Proxy(formApi, {
|
|
62
|
+
get(target, prop) {
|
|
63
|
+
if (prop in target) {
|
|
64
|
+
return target[prop];
|
|
59
65
|
}
|
|
60
|
-
return
|
|
66
|
+
return store[prop];
|
|
61
67
|
}
|
|
62
|
-
})
|
|
63
|
-
const unsubscribeFns =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
unsubscribeFns.push(unsubscribe);
|
|
79
|
-
}
|
|
68
|
+
});
|
|
69
|
+
const unsubscribeFns = [];
|
|
70
|
+
for (const entry of Object.entries(fieldConfigs)) {
|
|
71
|
+
const [path, config] = entry;
|
|
72
|
+
const validator = getValidator(path, config?.validate);
|
|
73
|
+
if (validator) {
|
|
74
|
+
const unsubscribe = storeApi.subscribe(path, value => {
|
|
75
|
+
const error = validator(value, store);
|
|
76
|
+
if (!error) {
|
|
77
|
+
errorStore.reset(path);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
errorStore.set(path, error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
unsubscribeFns.push(unsubscribe);
|
|
80
84
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
return () => {
|
|
85
|
-
for (const unsubscribe of unsubscribeFns) {
|
|
86
|
-
unsubscribe();
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}, [unsubscribeFns]);
|
|
90
|
-
return store;
|
|
85
|
+
}
|
|
86
|
+
return [proxy, unsubscribeFns];
|
|
91
87
|
}
|
|
92
88
|
/**
|
|
93
89
|
* Creates a form proxy node that extends the base node with error handling.
|
|
@@ -97,26 +93,23 @@ function useForm(defaultValue, fieldConfigs = {}) {
|
|
|
97
93
|
* @param path - The field path
|
|
98
94
|
* @returns A proxy with both state methods and error methods
|
|
99
95
|
*/
|
|
100
|
-
|
|
96
|
+
function createFormProxy(storeApi, errorStore) {
|
|
101
97
|
const proxyCache = new Map();
|
|
102
|
-
|
|
103
|
-
const getError = () => errorStore.value(path);
|
|
104
|
-
const setError = (error) => {
|
|
105
|
-
errorStore.set(path, error);
|
|
106
|
-
return true;
|
|
107
|
-
};
|
|
108
|
-
return createNode(storeApi, path, proxyCache, {
|
|
98
|
+
return createNode(storeApi, '', proxyCache, {
|
|
109
99
|
useError: {
|
|
110
|
-
get: () =>
|
|
100
|
+
get: (path) => () => errorStore.use(path)
|
|
111
101
|
},
|
|
112
102
|
error: {
|
|
113
|
-
get:
|
|
103
|
+
get: (path) => errorStore.value(path)
|
|
114
104
|
},
|
|
115
105
|
setError: {
|
|
116
|
-
get: () =>
|
|
106
|
+
get: (path) => (error) => {
|
|
107
|
+
errorStore.set(path, error, false);
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
117
110
|
}
|
|
118
111
|
});
|
|
119
|
-
}
|
|
112
|
+
}
|
|
120
113
|
/**
|
|
121
114
|
* Converts a validator configuration into a validation function.
|
|
122
115
|
*
|
package/dist/impl.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { FieldPath, FieldPathValue, FieldValues } from './path';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare function
|
|
2
|
+
import { getStableKeys, setExternalKeyOrder } from './stable_keys';
|
|
3
|
+
export { getNestedValue, getSnapshot, getStableKeys, isClass, isEqual, isRecord, joinPath, notifyListeners, produce, rename, setExternalKeyOrder, setLeaf, setNestedValue, subscribe, testReset, updateSnapshot, useDebounce, useObject };
|
|
4
|
+
declare function testReset(): void;
|
|
5
5
|
declare function isClass(value: unknown): boolean;
|
|
6
|
+
declare function isRecord(value: unknown): boolean;
|
|
6
7
|
/** Compare two values for equality
|
|
7
8
|
* @description
|
|
8
9
|
* - react-fast-compare for non-class instances
|
|
@@ -20,8 +21,25 @@ declare function isEqual(a: unknown, b: unknown): boolean;
|
|
|
20
21
|
* @returns Combined key string (e.g., "app.user.name")
|
|
21
22
|
*/
|
|
22
23
|
declare function joinPath(namespace: string, path?: string): string;
|
|
24
|
+
/** Snapshot getter used by React's useSyncExternalStore. */
|
|
25
|
+
declare function getSnapshot(key: string, memoryOnly: boolean): unknown;
|
|
26
|
+
/** Updates the snapshot of a key. */
|
|
27
|
+
declare function updateSnapshot(key: string, value: unknown, memoryOnly: boolean): void;
|
|
23
28
|
/** Get a nested value from an object/array using a dot-separated path. */
|
|
24
29
|
declare function getNestedValue(obj: unknown, path: string): unknown;
|
|
30
|
+
/**
|
|
31
|
+
* Immutably sets or deletes a nested value using a dot-separated path.
|
|
32
|
+
*
|
|
33
|
+
* Creates intermediate objects or arrays as needed based on whether the next
|
|
34
|
+
* path segment is numeric. When value is undefined, the key is deleted from
|
|
35
|
+
* objects or the index is spliced from arrays.
|
|
36
|
+
*
|
|
37
|
+
* @param obj - The root object to update
|
|
38
|
+
* @param path - Dot-separated path to the target location
|
|
39
|
+
* @param value - The value to set, or undefined to delete
|
|
40
|
+
* @returns A new root object with the change applied
|
|
41
|
+
*/
|
|
42
|
+
declare function setNestedValue(obj: unknown, path: string, value: unknown): unknown;
|
|
25
43
|
/**
|
|
26
44
|
* Notifies all relevant listeners when a value changes.
|
|
27
45
|
*
|
|
@@ -38,8 +56,6 @@ declare function notifyListeners(key: string, oldValue: unknown, newValue: unkno
|
|
|
38
56
|
skipChildren?: boolean | undefined;
|
|
39
57
|
forceNotify?: boolean | undefined;
|
|
40
58
|
}): void;
|
|
41
|
-
/** Snapshot getter used by React's useSyncExternalStore. */
|
|
42
|
-
declare function getSnapshot(key: string): unknown;
|
|
43
59
|
/**
|
|
44
60
|
* Subscribes to changes for a specific key.
|
|
45
61
|
*
|
|
@@ -59,7 +75,7 @@ declare function subscribe(key: string, listener: () => void): () => void;
|
|
|
59
75
|
* @param skipUpdate - When true, skips notifying listeners
|
|
60
76
|
* @param memoryOnly - When true, skips localStorage persistence
|
|
61
77
|
*/
|
|
62
|
-
declare function produce(key: string, value: unknown, skipUpdate
|
|
78
|
+
declare function produce(key: string, value: unknown, skipUpdate: boolean, memoryOnly: boolean): void;
|
|
63
79
|
/**
|
|
64
80
|
* Renames a key in an object.
|
|
65
81
|
*
|
|
@@ -73,7 +89,7 @@ declare function produce(key: string, value: unknown, skipUpdate?: boolean, memo
|
|
|
73
89
|
* @param oldKey - The old key to rename
|
|
74
90
|
* @param newKey - The new key to rename to
|
|
75
91
|
*/
|
|
76
|
-
declare function rename(path: string, oldKey: string, newKey: string): void;
|
|
92
|
+
declare function rename(path: string, oldKey: string, newKey: string, memoryOnly: boolean): void;
|
|
77
93
|
/**
|
|
78
94
|
* React hook that subscribes to and reads a value at a path.
|
|
79
95
|
*
|
|
@@ -82,9 +98,10 @@ declare function rename(path: string, oldKey: string, newKey: string): void;
|
|
|
82
98
|
*
|
|
83
99
|
* @param key - The namespace or full key
|
|
84
100
|
* @param path - Optional path within the namespace
|
|
101
|
+
* @param memoryOnly - When true, skips localStorage persistence
|
|
85
102
|
* @returns The current value at the path, or undefined if not set
|
|
86
103
|
*/
|
|
87
|
-
declare function useObject<T extends FieldValues, P extends FieldPath<T>>(key: string, path
|
|
104
|
+
declare function useObject<T extends FieldValues, P extends FieldPath<T>>(key: string, path: P | undefined, memoryOnly: boolean): FieldPathValue<T, P> | undefined;
|
|
88
105
|
/**
|
|
89
106
|
* React hook that subscribes to a value with debounced updates.
|
|
90
107
|
*
|
|
@@ -94,9 +111,10 @@ declare function useObject<T extends FieldValues, P extends FieldPath<T>>(key: s
|
|
|
94
111
|
* @param key - The namespace or full key
|
|
95
112
|
* @param path - Path within the namespace
|
|
96
113
|
* @param delay - Debounce delay in milliseconds
|
|
114
|
+
* @param memoryOnly - When true, skips localStorage persistence
|
|
97
115
|
* @returns The debounced value at the path
|
|
98
116
|
*/
|
|
99
|
-
declare function useDebounce<T extends FieldValues, P extends FieldPath<T>>(key: string, path: P, delay: number): FieldPathValue<T, P> | undefined;
|
|
117
|
+
declare function useDebounce<T extends FieldValues, P extends FieldPath<T>>(key: string, path: P, delay: number, memoryOnly: boolean): FieldPathValue<T, P> | undefined;
|
|
100
118
|
/**
|
|
101
119
|
* Sets a value at a specific path within a namespace.
|
|
102
120
|
*
|