react-store-input 0.4.0 → 0.6.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/CHANGELOG.md +33 -1
- package/README.md +66 -32
- package/dist/index.d.mts +30 -31
- package/dist/index.d.ts +30 -31
- package/dist/index.js +132 -175
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +130 -175
- package/dist/index.mjs.map +1 -1
- package/dist/text-editor.d.mts +1 -1
- package/dist/text-editor.d.ts +1 -1
- package/dist/text-editor.js +131 -43
- package/dist/text-editor.js.map +1 -1
- package/dist/text-editor.mjs +132 -44
- package/dist/text-editor.mjs.map +1 -1
- package/package.json +4 -4
package/dist/text-editor.mjs
CHANGED
|
@@ -1,38 +1,133 @@
|
|
|
1
1
|
// src/editor/text_editor.tsx
|
|
2
2
|
import {
|
|
3
3
|
TextEditor as GwTextEditor
|
|
4
|
-
} from "gw-
|
|
5
|
-
import {
|
|
4
|
+
} from "gw-rich-text-editor";
|
|
5
|
+
import { ok } from "gw-result";
|
|
6
|
+
import { useImperativeHandle, useMemo, useRef as useRef2 } from "react";
|
|
6
7
|
|
|
7
|
-
// src/
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// src/binding/binding.ts
|
|
9
|
+
function defineBinding(binding) {
|
|
10
|
+
return binding;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/binding/codec.ts
|
|
14
|
+
function defineCodec(codec) {
|
|
15
|
+
return codec;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/binding/lens.ts
|
|
19
|
+
function readPath(value, path) {
|
|
20
|
+
return path.reduce((current, key) => current[key], value);
|
|
21
|
+
}
|
|
22
|
+
function writePath(state, path, value) {
|
|
23
|
+
const parent = path.slice(0, -1).reduce((current, key) => current[key], state);
|
|
24
|
+
parent[path.at(-1)] = value;
|
|
25
|
+
}
|
|
26
|
+
function createPathLens(path) {
|
|
27
|
+
return {
|
|
28
|
+
get: (state) => readPath(state, path),
|
|
29
|
+
set: (state, value) => writePath(state, path, value),
|
|
30
|
+
prop: (key) => createPathLens([...path, key])
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function stateLens() {
|
|
34
|
+
return {
|
|
35
|
+
prop: (key) => createPathLens([key])
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/binding/use_store_binding.tsx
|
|
40
|
+
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
41
|
+
function equalStoreValue(previous, next) {
|
|
42
|
+
if (Object.is(previous, next)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (previous instanceof Date && next instanceof Date) {
|
|
46
|
+
return Object.is(previous.getTime(), next.getTime());
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(previous) && Array.isArray(next)) {
|
|
49
|
+
return previous.length === next.length && previous.every((value, index) => Object.is(value, next[index]));
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function useStoreBinding(store, binding, options = {}) {
|
|
10
54
|
const dispatchKey = useId();
|
|
11
|
-
const
|
|
55
|
+
const [initialValue] = useState(() => binding.codec.format(binding.lens.get(store.state)));
|
|
56
|
+
const [meta, setMeta] = useState({ valid: true });
|
|
57
|
+
const metaRef = useRef(meta);
|
|
58
|
+
const optionsRef = useRef(options);
|
|
12
59
|
const subscribedStoreRef = useRef(null);
|
|
60
|
+
const subscribedBindingRef = useRef(binding);
|
|
13
61
|
useEffect(() => {
|
|
14
|
-
|
|
15
|
-
}, [
|
|
62
|
+
optionsRef.current = options;
|
|
63
|
+
}, [options]);
|
|
16
64
|
useEffect(() => {
|
|
17
|
-
const isReplacement = subscribedStoreRef.current !== null && subscribedStoreRef.current !== store;
|
|
65
|
+
const isReplacement = subscribedStoreRef.current !== null && (subscribedStoreRef.current !== store || subscribedBindingRef.current !== binding);
|
|
18
66
|
subscribedStoreRef.current = store;
|
|
67
|
+
subscribedBindingRef.current = binding;
|
|
68
|
+
const sync = (state) => {
|
|
69
|
+
if (!metaRef.current.valid) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const value = binding.lens.get(state);
|
|
73
|
+
optionsRef.current.onStoreChange?.(binding.codec.format(value), value);
|
|
74
|
+
};
|
|
19
75
|
const unsubscribe = store.subscribe((state, key) => {
|
|
20
76
|
if (key !== dispatchKey) {
|
|
21
|
-
|
|
77
|
+
sync(state);
|
|
22
78
|
}
|
|
23
79
|
});
|
|
24
80
|
if (isReplacement) {
|
|
25
|
-
|
|
81
|
+
sync(store.state);
|
|
26
82
|
}
|
|
27
83
|
return unsubscribe;
|
|
28
|
-
}, [dispatchKey, store]);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
84
|
+
}, [binding, dispatchKey, store]);
|
|
85
|
+
const setValue = useCallback(
|
|
86
|
+
(value) => {
|
|
87
|
+
const currentValue = binding.lens.get(store.state);
|
|
88
|
+
const equals = binding.codec.equals ?? equalStoreValue;
|
|
89
|
+
if (equals(currentValue, value)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
store.dispatch((state) => binding.lens.set(state, value), { key: dispatchKey });
|
|
93
|
+
},
|
|
94
|
+
[binding, dispatchKey, store]
|
|
95
|
+
);
|
|
96
|
+
const commit = useCallback(
|
|
97
|
+
(input) => {
|
|
98
|
+
const result = binding.codec.parse(input);
|
|
99
|
+
if (result.isErr) {
|
|
100
|
+
const invalidMeta = {
|
|
101
|
+
valid: false,
|
|
102
|
+
error: result.error
|
|
103
|
+
};
|
|
104
|
+
metaRef.current = invalidMeta;
|
|
105
|
+
setMeta(invalidMeta);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
const validMeta = { valid: true };
|
|
109
|
+
metaRef.current = validMeta;
|
|
110
|
+
setMeta((current) => current.valid ? current : validMeta);
|
|
111
|
+
setValue(result.value);
|
|
112
|
+
return result;
|
|
113
|
+
},
|
|
114
|
+
[binding, setValue]
|
|
115
|
+
);
|
|
116
|
+
const reset = useCallback(
|
|
117
|
+
(value) => {
|
|
118
|
+
const validMeta = { valid: true };
|
|
119
|
+
metaRef.current = validMeta;
|
|
120
|
+
setMeta((current) => current.valid ? current : validMeta);
|
|
121
|
+
setValue(value);
|
|
122
|
+
},
|
|
123
|
+
[setValue]
|
|
124
|
+
);
|
|
125
|
+
return {
|
|
126
|
+
initialValue,
|
|
127
|
+
meta,
|
|
128
|
+
commit,
|
|
129
|
+
reset
|
|
130
|
+
};
|
|
36
131
|
}
|
|
37
132
|
|
|
38
133
|
// src/editor/text_editor.tsx
|
|
@@ -45,41 +140,34 @@ function TextEditor({
|
|
|
45
140
|
...props
|
|
46
141
|
}) {
|
|
47
142
|
const controllerRef = useRef2(null);
|
|
48
|
-
useImperativeHandle(
|
|
49
|
-
|
|
50
|
-
(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (controller.value !== result) {
|
|
61
|
-
controller.value = result;
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
onDispatch: (state) => {
|
|
143
|
+
useImperativeHandle(ref, () => controllerRef.current, []);
|
|
144
|
+
const binding = useMemo(() => {
|
|
145
|
+
return defineBinding({
|
|
146
|
+
lens: stateLens().prop(name),
|
|
147
|
+
codec: defineCodec({
|
|
148
|
+
format: (value) => typeof value === "string" ? value : "",
|
|
149
|
+
parse: (value) => ok(value)
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
}, [name]);
|
|
153
|
+
const { commit, initialValue } = useStoreBinding(store, binding, {
|
|
154
|
+
onStoreChange: (value) => {
|
|
65
155
|
const controller = controllerRef.current;
|
|
66
|
-
if (
|
|
67
|
-
|
|
156
|
+
if (controller && controller.value !== value) {
|
|
157
|
+
controller.value = value;
|
|
68
158
|
}
|
|
69
|
-
state[name] = controller.value;
|
|
70
159
|
}
|
|
71
160
|
});
|
|
72
|
-
const getDefaultValue = () => store.state[name];
|
|
73
161
|
return /* @__PURE__ */ jsx(
|
|
74
162
|
GwTextEditor,
|
|
75
163
|
{
|
|
76
164
|
...props,
|
|
77
165
|
ref: controllerRef,
|
|
78
166
|
name: String(name),
|
|
79
|
-
defaultValue: defaultValue ??
|
|
80
|
-
onChange: (
|
|
81
|
-
|
|
82
|
-
props.onChange?.(
|
|
167
|
+
defaultValue: defaultValue ?? initialValue,
|
|
168
|
+
onChange: (value) => {
|
|
169
|
+
commit(value);
|
|
170
|
+
props.onChange?.(value);
|
|
83
171
|
}
|
|
84
172
|
}
|
|
85
173
|
);
|
package/dist/text-editor.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editor/text_editor.tsx","../src/store/use_store_controller.tsx"],"sourcesContent":["import {\n TextEditor as GwTextEditor,\n TextEditorController,\n type TextEditorProps as GwTextEditorProps,\n} from \"gw-react-text-editor\";\nimport { useImperativeHandle, useRef } from \"react\";\nimport type { Store } from \"gw-store\";\nimport { useStoreController } from \"../store/use_store_controller\";\n\nexport type TextEditorProps<TState extends object> = Omit<\n GwTextEditorProps,\n \"name\"\n> & {\n store: Store<TState>;\n name: keyof TState;\n};\n\nexport function TextEditor<TState extends object>({\n store,\n name,\n defaultValue,\n ref,\n ...props\n}: TextEditorProps<TState>) {\n const controllerRef = useRef<TextEditorController>(null);\n\n useImperativeHandle(\n ref,\n () => controllerRef.current as TextEditorController,\n [],\n );\n\n const { dispatch } = useStoreController<TState>(store, {\n onSubscribe: (state) => {\n const controller = controllerRef.current;\n\n if (!controller) {\n return;\n }\n\n const result = (state[name as never] as unknown as string) || \"\";\n\n if (controller.value !== result) {\n controller.value = result;\n }\n },\n onDispatch: (state) => {\n const controller = controllerRef.current;\n\n if (!controller) {\n return;\n }\n\n state[name as never] = controller.value as unknown as never;\n },\n });\n\n const getDefaultValue = () =>\n store.state[name as never] as unknown as string;\n\n return (\n <GwTextEditor\n {...props}\n ref={controllerRef}\n name={String(name)}\n defaultValue={defaultValue ?? getDefaultValue()}\n onChange={(event) => {\n dispatch();\n props.onChange?.(event);\n }}\n />\n );\n}\n","import { useCallback, useEffect, useId, useRef } from \"react\";\nimport type { Draft, Immutable } from \"immer\";\nimport type { Store } from \"gw-store\";\n\nexport type StoreControllerProps<TState extends object> = {\n onSubscribe: (state: Immutable<TState>) => void;\n onDispatch: (state: Draft<TState>) => void;\n};\n\nexport function useStoreController<TState extends object>(\n store: Store<TState>,\n props: StoreControllerProps<TState>,\n) {\n const dispatchKey = useId();\n const propsRef = useRef(props);\n const subscribedStoreRef = useRef<Store<TState> | null>(null);\n\n useEffect(() => {\n propsRef.current = props;\n }, [props]);\n\n useEffect(() => {\n const isReplacement =\n subscribedStoreRef.current !== null && subscribedStoreRef.current !== store;\n subscribedStoreRef.current = store;\n\n const unsubscribe = store.subscribe((state, key) => {\n if (key !== dispatchKey) {\n propsRef.current.onSubscribe(state);\n }\n });\n\n if (isReplacement) {\n propsRef.current.onSubscribe(store.state);\n }\n\n return unsubscribe;\n }, [dispatchKey, store]);\n\n const dispatch = useCallback(() => {\n store.dispatch(\n (state) => propsRef.current.onDispatch(state),\n { key: dispatchKey },\n );\n }, [dispatchKey, store]);\n\n return { dispatch };\n}\n"],"mappings":";AAAA;AAAA,EACE,cAAc;AAAA,OAGT;AACP,SAAS,qBAAqB,UAAAA,eAAc;;;ACL5C,SAAS,aAAa,WAAW,OAAO,cAAc;AAS/C,SAAS,mBACd,OACA,OACA;AACA,QAAM,cAAc,MAAM;AAC1B,QAAM,WAAW,OAAO,KAAK;AAC7B,QAAM,qBAAqB,OAA6B,IAAI;AAE5D,YAAU,MAAM;AACd,aAAS,UAAU;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,UAAM,gBACJ,mBAAmB,YAAY,QAAQ,mBAAmB,YAAY;AACxE,uBAAmB,UAAU;AAE7B,UAAM,cAAc,MAAM,UAAU,CAAC,OAAO,QAAQ;AAClD,UAAI,QAAQ,aAAa;AACvB,iBAAS,QAAQ,YAAY,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAED,QAAI,eAAe;AACjB,eAAS,QAAQ,YAAY,MAAM,KAAK;AAAA,IAC1C;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,aAAa,KAAK,CAAC;AAEvB,QAAM,WAAW,YAAY,MAAM;AACjC,UAAM;AAAA,MACJ,CAAC,UAAU,SAAS,QAAQ,WAAW,KAAK;AAAA,MAC5C,EAAE,KAAK,YAAY;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,aAAa,KAAK,CAAC;AAEvB,SAAO,EAAE,SAAS;AACpB;;;ADcI;AA5CG,SAAS,WAAkC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA4B;AAC1B,QAAM,gBAAgBC,QAA6B,IAAI;AAEvD;AAAA,IACE;AAAA,IACA,MAAM,cAAc;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,QAAM,EAAE,SAAS,IAAI,mBAA2B,OAAO;AAAA,IACrD,aAAa,CAAC,UAAU;AACtB,YAAM,aAAa,cAAc;AAEjC,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAEA,YAAM,SAAU,MAAM,IAAa,KAA2B;AAE9D,UAAI,WAAW,UAAU,QAAQ;AAC/B,mBAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAAA,IACA,YAAY,CAAC,UAAU;AACrB,YAAM,aAAa,cAAc;AAEjC,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAEA,YAAM,IAAa,IAAI,WAAW;AAAA,IACpC;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,MACtB,MAAM,MAAM,IAAa;AAE3B,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,KAAK;AAAA,MACL,MAAM,OAAO,IAAI;AAAA,MACjB,cAAc,gBAAgB,gBAAgB;AAAA,MAC9C,UAAU,CAAC,UAAU;AACnB,iBAAS;AACT,cAAM,WAAW,KAAK;AAAA,MACxB;AAAA;AAAA,EACF;AAEJ;","names":["useRef","useRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/editor/text_editor.tsx","../src/binding/binding.ts","../src/binding/codec.ts","../src/binding/lens.ts","../src/binding/use_store_binding.tsx"],"sourcesContent":["import {\n TextEditor as GwTextEditor,\n TextEditorController,\n type TextEditorProps as GwTextEditorProps,\n} from \"gw-rich-text-editor\";\nimport { ok } from \"gw-result\";\nimport { useImperativeHandle, useMemo, useRef } from \"react\";\nimport type { Store } from \"gw-store\";\nimport { defineBinding } from \"../binding/binding\";\nimport { defineCodec } from \"../binding/codec\";\nimport { stateLens } from \"../binding/lens\";\nimport { useStoreBinding } from \"../binding/use_store_binding\";\n\nexport type TextEditorProps<TState extends object> = Omit<GwTextEditorProps, \"name\"> & {\n store: Store<TState>;\n name: keyof TState;\n};\n\nexport function TextEditor<TState extends object>({\n store,\n name,\n defaultValue,\n ref,\n ...props\n}: TextEditorProps<TState>) {\n const controllerRef = useRef<TextEditorController>(null);\n\n useImperativeHandle(ref, () => controllerRef.current as TextEditorController, []);\n\n const binding = useMemo(() => {\n type TValue = TState[typeof name];\n return defineBinding({\n lens: stateLens<TState>().prop(name),\n codec: defineCodec<TValue, string>({\n format: (value) => (typeof value === \"string\" ? value : \"\"),\n parse: (value) => ok(value as TValue),\n }),\n });\n }, [name]);\n\n const { commit, initialValue } = useStoreBinding(store, binding, {\n onStoreChange: (value) => {\n const controller = controllerRef.current;\n\n if (controller && controller.value !== value) {\n controller.value = value;\n }\n },\n });\n\n return (\n <GwTextEditor\n {...props}\n ref={controllerRef}\n name={String(name)}\n defaultValue={defaultValue ?? initialValue}\n onChange={(value) => {\n commit(value);\n props.onChange?.(value);\n }}\n />\n );\n}\n","import type { Codec } from \"./codec\";\nimport type { Lens } from \"./lens\";\n\nexport type InputBinding<TState extends object, TValue, TInput, TError = never> = {\n lens: Lens<TState, TValue>;\n codec: Codec<TValue, TInput, TError>;\n};\n\nexport function defineBinding<TState extends object, TValue, TInput, TError = never>(\n binding: InputBinding<TState, TValue, TInput, TError>,\n) {\n return binding;\n}\n","import type { Result } from \"gw-result\";\n\nexport type Codec<TValue, TInput, TError = never> = {\n format: (value: TValue) => TInput;\n parse: (input: TInput) => Result<TValue, TError>;\n equals?: (previous: TValue, next: TValue) => boolean;\n};\n\nexport function defineCodec<TValue, TInput, TError = never>(codec: Codec<TValue, TInput, TError>) {\n return codec;\n}\n","import type { Draft, Immutable } from \"immer\";\n\nexport type Lens<TState extends object, TValue> = {\n get: (state: Immutable<TState>) => TValue;\n set: (state: Draft<TState>, value: TValue) => void;\n};\n\nexport type LensBuilder<TState extends object, TValue> = Lens<TState, TValue> &\n (TValue extends object\n ? {\n prop<TKey extends keyof TValue>(key: TKey): LensBuilder<TState, TValue[TKey]>;\n }\n : object);\n\nexport type StateLens<TState extends object> = {\n prop<TKey extends keyof TState>(key: TKey): LensBuilder<TState, TState[TKey]>;\n};\n\nexport function defineLens<TState extends object, TValue>(lens: Lens<TState, TValue>) {\n return lens;\n}\n\nfunction readPath(value: unknown, path: readonly PropertyKey[]) {\n return path.reduce<unknown>((current, key) => (current as Record<PropertyKey, unknown>)[key], value);\n}\n\nfunction writePath(state: unknown, path: readonly PropertyKey[], value: unknown) {\n const parent = path\n .slice(0, -1)\n .reduce<\n Record<PropertyKey, unknown>\n >((current, key) => current[key] as Record<PropertyKey, unknown>, state as Record<PropertyKey, unknown>);\n parent[path.at(-1) as PropertyKey] = value;\n}\n\nfunction createPathLens<TState extends object, TValue>(path: readonly PropertyKey[]): LensBuilder<TState, TValue> {\n return {\n get: (state: Immutable<TState>) => readPath(state, path) as TValue,\n set: (state: Draft<TState>, value: TValue) => writePath(state, path, value),\n prop: (key: PropertyKey) => createPathLens([...path, key]),\n } as unknown as LensBuilder<TState, TValue>;\n}\n\nexport function stateLens<TState extends object>(): StateLens<TState> {\n return {\n prop: (key) => createPathLens<TState, TState[typeof key]>([key]),\n };\n}\n","import { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { Immutable } from \"immer\";\nimport type { Result } from \"gw-result\";\nimport type { Store } from \"gw-store\";\nimport type { InputBinding } from \"./binding\";\n\nexport type StoreBindingMeta<TError> = { valid: true; error?: never } | { valid: false; error: TError };\n\nexport type StoreBindingOptions<TValue, TInput> = {\n onStoreChange?: (input: TInput, value: TValue) => void;\n};\n\nexport type StoreBindingResult<TValue, TInput, TError> = {\n initialValue: TInput;\n meta: StoreBindingMeta<TError>;\n commit: (input: TInput) => Result<TValue, TError>;\n reset: (value: TValue) => void;\n};\n\nfunction equalStoreValue(previous: unknown, next: unknown) {\n if (Object.is(previous, next)) {\n return true;\n }\n\n if (previous instanceof Date && next instanceof Date) {\n return Object.is(previous.getTime(), next.getTime());\n }\n\n if (Array.isArray(previous) && Array.isArray(next)) {\n return previous.length === next.length && previous.every((value, index) => Object.is(value, next[index]));\n }\n\n return false;\n}\n\nexport function useStoreBinding<TState extends object, TValue, TInput, TError>(\n store: Store<TState>,\n binding: InputBinding<TState, TValue, TInput, TError>,\n options: StoreBindingOptions<TValue, TInput> = {},\n): StoreBindingResult<TValue, TInput, TError> {\n const dispatchKey = useId();\n const [initialValue] = useState(() => binding.codec.format(binding.lens.get(store.state)));\n const [meta, setMeta] = useState<StoreBindingMeta<TError>>({ valid: true });\n const metaRef = useRef<StoreBindingMeta<TError>>(meta);\n const optionsRef = useRef(options);\n const subscribedStoreRef = useRef<Store<TState> | null>(null);\n const subscribedBindingRef = useRef(binding);\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n const isReplacement =\n subscribedStoreRef.current !== null &&\n (subscribedStoreRef.current !== store || subscribedBindingRef.current !== binding);\n\n subscribedStoreRef.current = store;\n subscribedBindingRef.current = binding;\n\n const sync = (state: Immutable<TState>) => {\n if (!metaRef.current.valid) {\n return;\n }\n\n const value = binding.lens.get(state);\n optionsRef.current.onStoreChange?.(binding.codec.format(value), value);\n };\n\n const unsubscribe = store.subscribe((state, key) => {\n if (key !== dispatchKey) {\n sync(state);\n }\n });\n\n if (isReplacement) {\n sync(store.state);\n }\n\n return unsubscribe;\n }, [binding, dispatchKey, store]);\n\n const setValue = useCallback(\n (value: TValue) => {\n const currentValue = binding.lens.get(store.state);\n const equals = binding.codec.equals ?? equalStoreValue;\n\n if (equals(currentValue, value)) {\n return;\n }\n\n store.dispatch((state) => binding.lens.set(state, value), { key: dispatchKey });\n },\n [binding, dispatchKey, store],\n );\n\n const commit = useCallback(\n (input: TInput) => {\n const result = binding.codec.parse(input);\n\n if (result.isErr) {\n const invalidMeta: StoreBindingMeta<TError> = {\n valid: false,\n error: result.error,\n };\n metaRef.current = invalidMeta;\n setMeta(invalidMeta);\n return result;\n }\n\n const validMeta: StoreBindingMeta<TError> = { valid: true };\n metaRef.current = validMeta;\n setMeta((current) => (current.valid ? current : validMeta));\n setValue(result.value);\n return result;\n },\n [binding, setValue],\n );\n\n const reset = useCallback(\n (value: TValue) => {\n const validMeta: StoreBindingMeta<TError> = { valid: true };\n metaRef.current = validMeta;\n setMeta((current) => (current.valid ? current : validMeta));\n setValue(value);\n },\n [setValue],\n );\n\n return {\n initialValue,\n meta,\n commit,\n reset,\n };\n}\n"],"mappings":"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","names":["useRef","useRef"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-store-input",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Typed React form inputs backed by a small immutable store",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"@types/react-dom": "^18.3.1 || ^19.2.1",
|
|
74
74
|
"eslint": "^9.39.5",
|
|
75
75
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
76
|
-
"gw-
|
|
76
|
+
"gw-rich-text-editor": "^0.1.4",
|
|
77
77
|
"jsdom": "^24.1.3",
|
|
78
78
|
"react": "^19.2.8",
|
|
79
79
|
"react-dom": "^19.2.8",
|
|
@@ -82,12 +82,12 @@
|
|
|
82
82
|
"typescript-eslint": "^8.65.0"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
|
-
"gw-
|
|
85
|
+
"gw-rich-text-editor": "^0.1.4",
|
|
86
86
|
"react": ">=18.0.0 <20.0.0",
|
|
87
87
|
"react-dom": ">=18.0.0 <20.0.0"
|
|
88
88
|
},
|
|
89
89
|
"peerDependenciesMeta": {
|
|
90
|
-
"gw-
|
|
90
|
+
"gw-rich-text-editor": {
|
|
91
91
|
"optional": true
|
|
92
92
|
}
|
|
93
93
|
},
|