cogsbox-state 0.5.423 → 0.5.425
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/CogsState.d.ts +0 -3
- package/dist/CogsState.jsx +684 -676
- package/dist/CogsState.jsx.map +1 -1
- package/dist/Functions.d.ts +1 -2
- package/dist/Functions.jsx +87 -90
- package/dist/Functions.jsx.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +32 -15
- package/src/Functions.tsx +5 -7
package/dist/Functions.d.ts
CHANGED
|
@@ -17,10 +17,9 @@ interface FormControlComponentProps<TStateObject> {
|
|
|
17
17
|
stateKey: string;
|
|
18
18
|
}
|
|
19
19
|
export declare const FormControlComponent: <TStateObject>({ setState, path, child, formOpts, stateKey, }: FormControlComponentProps<TStateObject>) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
-
export declare function ValidationWrapper({ formOpts, path,
|
|
20
|
+
export declare function ValidationWrapper({ formOpts, path, stateKey, children, validIndices, }: {
|
|
21
21
|
formOpts?: FormOptsType;
|
|
22
22
|
path: string[];
|
|
23
|
-
validationKey: string;
|
|
24
23
|
stateKey?: string;
|
|
25
24
|
children: React.ReactNode;
|
|
26
25
|
validIndices?: number[];
|
package/dist/Functions.jsx
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as V, Fragment as M } from "react/jsx-runtime";
|
|
2
2
|
import "./CogsState.jsx";
|
|
3
|
-
import { getNestedValue as N, isFunction as
|
|
4
|
-
import I, { useRef as b, useState as
|
|
5
|
-
import { getGlobalStore as
|
|
3
|
+
import { getNestedValue as N, isFunction as O, updateNestedProperty as T } from "./utility.js";
|
|
4
|
+
import I, { useRef as b, useState as U, useEffect as R } from "react";
|
|
5
|
+
import { getGlobalStore as m, formRefStore as L } from "./store.js";
|
|
6
6
|
import { validateZodPathFunc as W } from "./useValidateZodPath.js";
|
|
7
|
-
function j(
|
|
8
|
-
|
|
7
|
+
function j(r, e, t, n) {
|
|
8
|
+
r(
|
|
9
9
|
(o) => {
|
|
10
|
-
if (
|
|
10
|
+
if (O(e)) {
|
|
11
11
|
const u = e(N(o, t));
|
|
12
12
|
let i = T(t, o, u);
|
|
13
13
|
return typeof i == "string" && (i = i.trim()), i;
|
|
@@ -18,19 +18,19 @@ function j(n, e, t, r) {
|
|
|
18
18
|
},
|
|
19
19
|
t,
|
|
20
20
|
{ updateType: "update" },
|
|
21
|
-
|
|
21
|
+
n
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
|
-
function p(
|
|
25
|
-
const u =
|
|
26
|
-
|
|
24
|
+
function p(r, e, t, n, o) {
|
|
25
|
+
const u = m.getState().getNestedState(n, t);
|
|
26
|
+
r(
|
|
27
27
|
(i) => {
|
|
28
|
-
let
|
|
29
|
-
return
|
|
30
|
-
Number(o) == 0 ? o :
|
|
28
|
+
let c = !t || t.length == 0 ? i : N(i, [...t]), s = [...c];
|
|
29
|
+
return s.splice(
|
|
30
|
+
Number(o) == 0 ? o : c.length,
|
|
31
31
|
0,
|
|
32
|
-
|
|
33
|
-
), t.length == 0 ?
|
|
32
|
+
O(e) ? e(c) : e
|
|
33
|
+
), t.length == 0 ? s : T([...t], i, s);
|
|
34
34
|
},
|
|
35
35
|
[
|
|
36
36
|
...t,
|
|
@@ -41,98 +41,98 @@ function p(n, e, t, r, o) {
|
|
|
41
41
|
}
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
|
-
function ee(
|
|
45
|
-
const o =
|
|
46
|
-
|
|
44
|
+
function ee(r, e, t, n) {
|
|
45
|
+
const o = m.getState().getNestedState(t, e);
|
|
46
|
+
r(
|
|
47
47
|
(u) => {
|
|
48
48
|
const i = N(u, [...e]);
|
|
49
|
-
if (
|
|
50
|
-
throw new Error(`Index ${
|
|
51
|
-
const
|
|
52
|
-
...i.slice(0,
|
|
53
|
-
...i.slice(
|
|
49
|
+
if (n < 0 || n >= i?.length)
|
|
50
|
+
throw new Error(`Index ${n} does not exist in the array.`);
|
|
51
|
+
const c = n || Number(n) == 0 ? n : i.length - 1, s = [
|
|
52
|
+
...i.slice(0, c),
|
|
53
|
+
...i.slice(c + 1)
|
|
54
54
|
];
|
|
55
|
-
return e.length == 0 ?
|
|
55
|
+
return e.length == 0 ? s : T([...e], u, s);
|
|
56
56
|
},
|
|
57
57
|
[
|
|
58
58
|
...e,
|
|
59
|
-
|
|
59
|
+
n || n === 0 ? n?.toString() : (o.length - 1).toString()
|
|
60
60
|
],
|
|
61
61
|
{ updateType: "cut" }
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
|
-
const w = (
|
|
65
|
-
const [
|
|
66
|
-
() => e(
|
|
67
|
-
), u = b(
|
|
64
|
+
const w = (r, e, t = (n, o) => JSON.stringify(n) === JSON.stringify(o)) => {
|
|
65
|
+
const [n, o] = U(
|
|
66
|
+
() => e(m.getState(), r)
|
|
67
|
+
), u = b(n), i = b(r);
|
|
68
68
|
return R(() => {
|
|
69
|
-
i.current =
|
|
70
|
-
const
|
|
71
|
-
const g = e(
|
|
69
|
+
i.current = r, o(e(m.getState(), r));
|
|
70
|
+
const c = (f) => {
|
|
71
|
+
const g = e(f, i.current);
|
|
72
72
|
t(u.current, g) || (u.current = g, o(g));
|
|
73
|
-
},
|
|
73
|
+
}, s = m.subscribe(c);
|
|
74
74
|
return () => {
|
|
75
|
-
|
|
75
|
+
s();
|
|
76
76
|
};
|
|
77
|
-
}, [
|
|
78
|
-
}, Z = (
|
|
79
|
-
const
|
|
77
|
+
}, [r]), n;
|
|
78
|
+
}, Z = (r, e, t) => {
|
|
79
|
+
const n = r + "." + (e.length > 0 ? [e.join(".")] : []) + (t && t.length > 0 ? "." + t : "");
|
|
80
80
|
return w(
|
|
81
|
-
|
|
81
|
+
n,
|
|
82
82
|
(u, i) => u.getValidationErrors(i) || []
|
|
83
83
|
);
|
|
84
|
-
}, q = (
|
|
85
|
-
const t = `${
|
|
84
|
+
}, q = (r, e) => {
|
|
85
|
+
const t = `${r}:${e.join(".")}`;
|
|
86
86
|
return w(
|
|
87
87
|
t,
|
|
88
|
-
(
|
|
88
|
+
(n, o) => n.getSyncInfo(o)
|
|
89
89
|
);
|
|
90
|
-
}, H = (
|
|
91
|
-
`${
|
|
92
|
-
(t,
|
|
90
|
+
}, H = (r, e) => w(
|
|
91
|
+
`${r}:${e.join(".")}`,
|
|
92
|
+
(t, n) => t.getNestedState(r, e)
|
|
93
93
|
), te = ({
|
|
94
|
-
setState:
|
|
94
|
+
setState: r,
|
|
95
95
|
// This is the real effectiveSetState from the hook
|
|
96
96
|
path: e,
|
|
97
97
|
child: t,
|
|
98
|
-
formOpts:
|
|
98
|
+
formOpts: n,
|
|
99
99
|
stateKey: o
|
|
100
100
|
}) => {
|
|
101
|
-
const { registerFormRef: u, getFormRef: i } =
|
|
102
|
-
getValidationErrors:
|
|
103
|
-
addValidationError:
|
|
104
|
-
getInitialOptions:
|
|
101
|
+
const { registerFormRef: u, getFormRef: i } = L.getState(), {
|
|
102
|
+
getValidationErrors: c,
|
|
103
|
+
addValidationError: s,
|
|
104
|
+
getInitialOptions: f,
|
|
105
105
|
removeValidationError: g
|
|
106
|
-
} =
|
|
107
|
-
|
|
108
|
-
const
|
|
106
|
+
} = m.getState(), C = o + "." + e.join("."), $ = b(null), k = i(C);
|
|
107
|
+
k || u(C, $);
|
|
108
|
+
const z = k || $, v = H(o, e), [E, B] = U(v), S = b(!1), l = b(null);
|
|
109
109
|
R(() => {
|
|
110
|
-
!S.current &&
|
|
111
|
-
}, [
|
|
110
|
+
!S.current && v !== E && B(v);
|
|
111
|
+
}, [v]), R(() => () => {
|
|
112
112
|
l.current && (clearTimeout(l.current), l.current = null, S.current = !1);
|
|
113
113
|
}, []);
|
|
114
114
|
const G = (a) => {
|
|
115
115
|
if (B(a), S.current = !0, a === "") {
|
|
116
|
-
l.current && (clearTimeout(l.current), l.current = null), j(
|
|
116
|
+
l.current && (clearTimeout(l.current), l.current = null), j(r, a, e, d), S.current = !1;
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
l.current && clearTimeout(l.current), l.current = setTimeout(
|
|
120
120
|
() => {
|
|
121
|
-
S.current = !1, j(
|
|
121
|
+
S.current = !1, j(r, a, e, d);
|
|
122
122
|
},
|
|
123
|
-
|
|
123
|
+
n?.debounceTime ?? (typeof v == "boolean" ? 20 : 200)
|
|
124
124
|
);
|
|
125
|
-
},
|
|
126
|
-
if (!
|
|
125
|
+
}, y = f(o);
|
|
126
|
+
if (!y?.validation?.key)
|
|
127
127
|
throw new Error("Validation key not found.");
|
|
128
|
-
const
|
|
129
|
-
if (l.current && (clearTimeout(l.current), l.current = null, S.current = !1, j(
|
|
130
|
-
g(
|
|
128
|
+
const d = y.validation.key, A = y.validation.onBlur === !0, D = async () => {
|
|
129
|
+
if (l.current && (clearTimeout(l.current), l.current = null, S.current = !1, j(r, E, e, d)), !(!y.validation?.zodSchema || !A)) {
|
|
130
|
+
g(d + "." + e.join("."));
|
|
131
131
|
try {
|
|
132
|
-
const a =
|
|
132
|
+
const a = m.getState().getNestedState(o, e);
|
|
133
133
|
await W(
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
d,
|
|
135
|
+
y.validation.zodSchema,
|
|
136
136
|
e,
|
|
137
137
|
a
|
|
138
138
|
);
|
|
@@ -140,18 +140,18 @@ const w = (n, e, t = (r, o) => JSON.stringify(r) === JSON.stringify(o)) => {
|
|
|
140
140
|
console.error("Validation error on blur:", a);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
}, F = q(o, e),
|
|
143
|
+
}, F = q(o, e), J = F ? { ...F, date: new Date(F.timeStamp) } : null, P = t({
|
|
144
144
|
// --- START CHANGES ---
|
|
145
145
|
get: () => E,
|
|
146
146
|
// Get should return the immediate local value
|
|
147
147
|
set: G,
|
|
148
148
|
// Use the new debounced updater
|
|
149
149
|
// --- END CHANGES ---
|
|
150
|
-
syncStatus:
|
|
150
|
+
syncStatus: J,
|
|
151
151
|
path: e,
|
|
152
|
-
validationErrors: () =>
|
|
152
|
+
validationErrors: () => c(d + "." + e.join(".")),
|
|
153
153
|
addValidationError: (a) => {
|
|
154
|
-
g(
|
|
154
|
+
g(d + "." + e.join(".")), s(d + "." + e.join("."), a ?? "");
|
|
155
155
|
},
|
|
156
156
|
inputProps: {
|
|
157
157
|
// --- START CHANGES ---
|
|
@@ -160,37 +160,34 @@ const w = (n, e, t = (r, o) => JSON.stringify(r) === JSON.stringify(o)) => {
|
|
|
160
160
|
onChange: (a) => G(a.target.value),
|
|
161
161
|
// Use debounced updater
|
|
162
162
|
// --- END CHANGES ---
|
|
163
|
-
onBlur:
|
|
164
|
-
ref:
|
|
163
|
+
onBlur: D,
|
|
164
|
+
ref: z
|
|
165
165
|
}
|
|
166
166
|
});
|
|
167
|
-
return /* @__PURE__ */ V(M, { children: /* @__PURE__ */ V(Q, { formOpts:
|
|
167
|
+
return /* @__PURE__ */ V(M, { children: /* @__PURE__ */ V(Q, { formOpts: n, path: e, stateKey: o, children: P }) });
|
|
168
168
|
};
|
|
169
169
|
function Q({
|
|
170
|
-
formOpts:
|
|
170
|
+
formOpts: r,
|
|
171
171
|
path: e,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
validIndices: u
|
|
172
|
+
stateKey: t,
|
|
173
|
+
children: n,
|
|
174
|
+
validIndices: o
|
|
176
175
|
}) {
|
|
177
|
-
const { getInitialOptions:
|
|
178
|
-
|
|
176
|
+
const { getInitialOptions: u } = m.getState(), i = u(t), c = i?.validation?.key ?? t, s = Z(
|
|
177
|
+
c,
|
|
179
178
|
e,
|
|
180
|
-
|
|
181
|
-
),
|
|
179
|
+
o
|
|
180
|
+
), f = [];
|
|
182
181
|
if (s) {
|
|
183
182
|
const g = s.join(", ");
|
|
184
|
-
|
|
183
|
+
f.includes(g) || f.push(g);
|
|
185
184
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
children: /* @__PURE__ */ V(I.Fragment, { children: o }, e.toString()),
|
|
185
|
+
return /* @__PURE__ */ V(M, { children: i?.formElements?.validation && !r?.validation?.disable ? i.formElements.validation({
|
|
186
|
+
children: /* @__PURE__ */ V(I.Fragment, { children: n }, e.toString()),
|
|
189
187
|
active: s.length > 0,
|
|
190
|
-
message:
|
|
191
|
-
path: e
|
|
192
|
-
|
|
193
|
-
}) : /* @__PURE__ */ V(I.Fragment, { children: o }, e.toString()) });
|
|
188
|
+
message: r?.validation?.hideMessage ? "" : r?.validation?.message ? r?.validation?.message : f.map((g) => g).join(", "),
|
|
189
|
+
path: e
|
|
190
|
+
}) : /* @__PURE__ */ V(I.Fragment, { children: n }, e.toString()) });
|
|
194
191
|
}
|
|
195
192
|
export {
|
|
196
193
|
te as FormControlComponent,
|
package/dist/Functions.jsx.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Functions.jsx","sources":["../src/Functions.tsx"],"sourcesContent":["import {\r\n notifyComponent,\r\n type EffectiveSetState,\r\n type FormElementParams,\r\n type FormOptsType,\r\n type UpdateArg,\r\n type UpdateOpts,\r\n} from \"./CogsState\";\r\n\r\nimport { getNestedValue, isFunction, updateNestedProperty } from \"./utility\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\nimport React from \"react\";\r\nimport { getGlobalStore, formRefStore } from \"./store\";\r\nimport { validateZodPathFunc } from \"./useValidateZodPath\";\r\n\r\nexport function updateFn<U>(\r\n setState: EffectiveSetState<U>,\r\n payload: UpdateArg<U>,\r\n path: string[],\r\n validationKey?: string\r\n): void {\r\n setState(\r\n (prevState) => {\r\n if (isFunction<U>(payload)) {\r\n const nestedValue = payload(getNestedValue(prevState, path));\r\n let value = updateNestedProperty(path, prevState, nestedValue);\r\n if (typeof value == \"string\") {\r\n value = value.trim();\r\n }\r\n return value;\r\n } else {\r\n let value =\r\n !path || path.length == 0\r\n ? payload\r\n : updateNestedProperty(path, prevState, payload);\r\n if (typeof value == \"string\") {\r\n value = value.trim();\r\n }\r\n return value;\r\n }\r\n },\r\n path,\r\n { updateType: \"update\" },\r\n validationKey\r\n );\r\n}\r\n\r\nexport function pushFunc<U>(\r\n setState: EffectiveSetState<U>,\r\n payload: UpdateArg<U>,\r\n path: string[],\r\n stateKey: string,\r\n index?: number\r\n): void {\r\n const array = getGlobalStore.getState().getNestedState(stateKey, path) as U[];\r\n setState(\r\n (prevState) => {\r\n let arrayToUpdate =\r\n !path || path.length == 0\r\n ? prevState\r\n : getNestedValue(prevState, [...path]);\r\n let returnedArray = [...arrayToUpdate];\r\n\r\n returnedArray.splice(\r\n index || Number(index) == 0 ? index : arrayToUpdate.length,\r\n 0,\r\n isFunction<U>(payload)\r\n ? payload(index == -1 ? undefined : arrayToUpdate)\r\n : payload\r\n );\r\n const value =\r\n path.length == 0\r\n ? returnedArray\r\n : updateNestedProperty([...path], prevState, returnedArray);\r\n\r\n return value as U;\r\n },\r\n [\r\n ...path,\r\n index || index === 0 ? index?.toString() : (array!.length - 1).toString(),\r\n ],\r\n {\r\n updateType: \"insert\",\r\n }\r\n );\r\n}\r\n\r\nexport function cutFunc<U>(\r\n setState: EffectiveSetState<U>,\r\n path: string[],\r\n stateKey: string,\r\n index: number\r\n): void {\r\n const array = getGlobalStore.getState().getNestedState(stateKey, path) as U[];\r\n setState(\r\n (prevState) => {\r\n const arrayToUpdate = getNestedValue(prevState, [...path]);\r\n if (index < 0 || index >= arrayToUpdate?.length) {\r\n throw new Error(`Index ${index} does not exist in the array.`);\r\n }\r\n const indexToCut =\r\n index || Number(index) == 0 ? index : arrayToUpdate.length - 1;\r\n\r\n const updatedArray = [\r\n ...arrayToUpdate.slice(0, indexToCut),\r\n ...arrayToUpdate.slice(indexToCut + 1),\r\n ] as U;\r\n\r\n return path.length == 0\r\n ? updatedArray\r\n : updateNestedProperty([...path], prevState, updatedArray);\r\n },\r\n [\r\n ...path,\r\n index || index === 0 ? index?.toString() : (array!.length - 1).toString(),\r\n ],\r\n { updateType: \"cut\" }\r\n );\r\n}\r\n\r\nexport const useStoreSubscription = <T,>(\r\n fullPath: string,\r\n selector: (\r\n store: ReturnType<typeof getGlobalStore.getState>,\r\n path: string\r\n ) => T,\r\n compare: (a: T, b: T) => boolean = (a, b) =>\r\n JSON.stringify(a) === JSON.stringify(b)\r\n) => {\r\n const [value, setValue] = useState<T>(() =>\r\n selector(getGlobalStore.getState(), fullPath)\r\n );\r\n const previousValueRef = useRef<T>(value);\r\n const fullPathRef = useRef(fullPath);\r\n useEffect(() => {\r\n fullPathRef.current = fullPath; // Ensure latest fullPath is always used\r\n\r\n setValue(selector(getGlobalStore.getState(), fullPath));\r\n\r\n const callback = (store: any) => {\r\n const newValue = selector(store, fullPathRef.current);\r\n\r\n if (!compare(previousValueRef.current, newValue)) {\r\n previousValueRef.current = newValue;\r\n setValue(newValue);\r\n }\r\n };\r\n const unsubscribe = getGlobalStore.subscribe(callback);\r\n return () => {\r\n unsubscribe();\r\n };\r\n }, [fullPath]);\r\n return value;\r\n};\r\nexport const useGetValidationErrors = (\r\n validationKey: string,\r\n path: string[],\r\n validIndices?: number[]\r\n) => {\r\n const fullPath =\r\n validationKey +\r\n \".\" +\r\n (path.length > 0 ? [path.join(\".\")] : []) +\r\n (validIndices && validIndices.length > 0 ? \".\" + validIndices : \"\");\r\n\r\n const returnresult = useStoreSubscription(\r\n fullPath,\r\n (store, path) => store.getValidationErrors(path) || []\r\n );\r\n\r\n return returnresult;\r\n};\r\n\r\nexport const useGetSyncInfo = (key: string, path: string[]) => {\r\n const syncKey = `${key}:${path.join(\".\")}`;\r\n return useStoreSubscription(syncKey, (store, path) =>\r\n store.getSyncInfo(path)\r\n );\r\n};\r\nexport const useGetKeyState = (key: string, path: string[]) => {\r\n return useStoreSubscription(`${key}:${path.join(\".\")}`, (store, fullPath) =>\r\n store.getNestedState(key, path)\r\n );\r\n};\r\ninterface FormControlComponentProps<TStateObject> {\r\n setState: EffectiveSetState<TStateObject>;\r\n\r\n path: string[];\r\n child: (obj: FormElementParams<TStateObject>) => JSX.Element;\r\n formOpts?: FormOptsType;\r\n stateKey: string;\r\n}\r\n// Find FormControlComponent in your Functions.ts or equivalent file\r\n\r\nexport const FormControlComponent = <TStateObject,>({\r\n setState, // This is the real effectiveSetState from the hook\r\n path,\r\n child,\r\n formOpts,\r\n stateKey,\r\n}: FormControlComponentProps<TStateObject>) => {\r\n const { registerFormRef, getFormRef } = formRefStore.getState();\r\n const {\r\n getValidationErrors,\r\n addValidationError,\r\n getInitialOptions,\r\n removeValidationError,\r\n } = getGlobalStore.getState();\r\n\r\n const refKey = stateKey + \".\" + path.join(\".\");\r\n const localFormRef = useRef<HTMLInputElement>(null);\r\n const existingRef = getFormRef(refKey);\r\n if (!existingRef) {\r\n registerFormRef(refKey, localFormRef);\r\n }\r\n const formRef = existingRef || localFormRef;\r\n\r\n // --- START CHANGES ---\r\n\r\n const globalStateValue = useGetKeyState(stateKey, path);\r\n const [localValue, setLocalValue] = useState<any>(globalStateValue);\r\n const isCurrentlyDebouncing = useRef(false);\r\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n // Effect to sync local state if global state changes externally\r\n useEffect(() => {\r\n // Only update local if not actively debouncing a local change\r\n if (!isCurrentlyDebouncing.current && globalStateValue !== localValue) {\r\n setLocalValue(globalStateValue);\r\n }\r\n }, [globalStateValue]); // Removed localValue dependency\r\n\r\n // Effect for cleanup\r\n useEffect(() => {\r\n return () => {\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n debounceTimeoutRef.current = null; // Explicitly nullify\r\n isCurrentlyDebouncing.current = false;\r\n }\r\n };\r\n }, []);\r\n\r\n const debouncedUpdater = (payload: UpdateArg<TStateObject>) => {\r\n setLocalValue(payload); // Update local state immediately\r\n isCurrentlyDebouncing.current = true;\r\n\r\n if (payload === \"\") {\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current); // Clear pending timer\r\n debounceTimeoutRef.current = null;\r\n }\r\n updateFn(setState, payload, path, validationKey); // Update global state NOW\r\n isCurrentlyDebouncing.current = false; // No longer debouncing\r\n return; // Don't proceed to set another timeout\r\n }\r\n\r\n // If not empty, proceed with normal debouncing\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n }\r\n\r\n debounceTimeoutRef.current = setTimeout(\r\n () => {\r\n isCurrentlyDebouncing.current = false;\r\n updateFn(setState, payload, path, validationKey);\r\n },\r\n formOpts?.debounceTime ??\r\n (typeof globalStateValue == \"boolean\" ? 20 : 200)\r\n );\r\n };\r\n\r\n const initialOptions = getInitialOptions(stateKey);\r\n if (!initialOptions?.validation?.key) {\r\n throw new Error(\"Validation key not found.\");\r\n }\r\n const validationKey = initialOptions.validation.key;\r\n const validateOnBlur = initialOptions.validation.onBlur === true;\r\n\r\n const handleBlur = async () => {\r\n // --- Ensure latest value is flushed if debouncing ---\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current); // Clear pending timer\r\n debounceTimeoutRef.current = null;\r\n isCurrentlyDebouncing.current = false;\r\n // Ensure the absolute latest local value is committed on blur\r\n updateFn(setState, localValue, path, validationKey);\r\n }\r\n // --- End modification ---\r\n\r\n if (!initialOptions.validation?.zodSchema || !validateOnBlur) return;\r\n removeValidationError(validationKey + \".\" + path.join(\".\"));\r\n try {\r\n // Use the potentially just flushed value\r\n const fieldValue = getGlobalStore\r\n .getState()\r\n .getNestedState(stateKey, path);\r\n await validateZodPathFunc(\r\n validationKey,\r\n initialOptions.validation.zodSchema,\r\n path,\r\n fieldValue\r\n );\r\n // forceUpdate might be needed if validation state update doesn't trigger render\r\n // Consider using useGetValidationErrors hook result directly for validation display\r\n } catch (error) {\r\n console.error(\"Validation error on blur:\", error);\r\n }\r\n };\r\n\r\n const rawSyncStatus = useGetSyncInfo(stateKey, path);\r\n const syncStatus = rawSyncStatus\r\n ? { ...rawSyncStatus, date: new Date(rawSyncStatus.timeStamp) }\r\n : null;\r\n\r\n const childElement = child({\r\n // --- START CHANGES ---\r\n get: () => localValue, // Get should return the immediate local value\r\n set: debouncedUpdater, // Use the new debounced updater\r\n // --- END CHANGES ---\r\n syncStatus,\r\n path: path,\r\n validationErrors: () =>\r\n getValidationErrors(validationKey + \".\" + path.join(\".\")),\r\n addValidationError: (message?: string) => {\r\n removeValidationError(validationKey + \".\" + path.join(\".\"));\r\n addValidationError(validationKey + \".\" + path.join(\".\"), message ?? \"\");\r\n },\r\n inputProps: {\r\n // --- START CHANGES ---\r\n value: localValue ?? \"\", // Input value is always the local state\r\n onChange: (e: any) => debouncedUpdater(e.target.value), // Use debounced updater\r\n // --- END CHANGES ---\r\n onBlur: handleBlur,\r\n ref: formRef,\r\n },\r\n });\r\n\r\n return (\r\n <>\r\n <ValidationWrapper {...{ formOpts, path, validationKey, stateKey }}>\r\n {childElement}\r\n </ValidationWrapper>\r\n </>\r\n );\r\n};\r\nexport function ValidationWrapper({\r\n formOpts,\r\n path,\r\n validationKey,\r\n stateKey,\r\n children,\r\n validIndices,\r\n}: {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n validationKey: string;\r\n stateKey?: string;\r\n children: React.ReactNode;\r\n validIndices?: number[];\r\n}) {\r\n const { getInitialOptions } = getGlobalStore.getState();\r\n\r\n const validationErrors = useGetValidationErrors(\r\n validationKey,\r\n path,\r\n validIndices\r\n );\r\n // console.log(\r\n // \"validationErrors ValidationWrapper\",\r\n // stateKey,\r\n // validationKey,\r\n // path,\r\n // validationErrors\r\n // );\r\n const thesMessages: string[] = [];\r\n\r\n if (validationErrors) {\r\n const newMessage = validationErrors!.join(\", \");\r\n if (!thesMessages.includes(newMessage)) {\r\n thesMessages.push(newMessage);\r\n }\r\n }\r\n const thisStateOpts = getInitialOptions(stateKey!);\r\n\r\n return (\r\n <>\r\n {thisStateOpts?.formElements?.validation &&\r\n !formOpts?.validation?.disable ? (\r\n thisStateOpts.formElements!.validation!({\r\n children: (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n ),\r\n active: validationErrors.length > 0 ? true : false,\r\n message: formOpts?.validation?.hideMessage\r\n ? \"\"\r\n : formOpts?.validation?.message\r\n ? formOpts?.validation?.message\r\n : thesMessages.map((m) => m).join(\", \"),\r\n path: path,\r\n\r\n ...(formOpts?.key && { key: formOpts?.key }),\r\n })\r\n ) : (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["updateFn","setState","payload","path","validationKey","prevState","isFunction","nestedValue","getNestedValue","value","updateNestedProperty","pushFunc","stateKey","index","array","getGlobalStore","arrayToUpdate","returnedArray","cutFunc","indexToCut","updatedArray","useStoreSubscription","fullPath","selector","compare","a","b","setValue","useState","previousValueRef","useRef","fullPathRef","useEffect","callback","store","newValue","unsubscribe","useGetValidationErrors","validIndices","useGetSyncInfo","key","syncKey","useGetKeyState","FormControlComponent","child","formOpts","registerFormRef","getFormRef","formRefStore","getValidationErrors","addValidationError","getInitialOptions","removeValidationError","refKey","localFormRef","existingRef","formRef","globalStateValue","localValue","setLocalValue","isCurrentlyDebouncing","debounceTimeoutRef","debouncedUpdater","initialOptions","validateOnBlur","handleBlur","fieldValue","validateZodPathFunc","error","rawSyncStatus","syncStatus","childElement","message","e","jsx","Fragment","ValidationWrapper","children","validationErrors","thesMessages","newMessage","thisStateOpts","React","m"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Functions.jsx","sources":["../src/Functions.tsx"],"sourcesContent":["import {\r\n notifyComponent,\r\n type EffectiveSetState,\r\n type FormElementParams,\r\n type FormOptsType,\r\n type UpdateArg,\r\n type UpdateOpts,\r\n} from \"./CogsState\";\r\n\r\nimport { getNestedValue, isFunction, updateNestedProperty } from \"./utility\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\nimport React from \"react\";\r\nimport { getGlobalStore, formRefStore } from \"./store\";\r\nimport { validateZodPathFunc } from \"./useValidateZodPath\";\r\n\r\nexport function updateFn<U>(\r\n setState: EffectiveSetState<U>,\r\n payload: UpdateArg<U>,\r\n path: string[],\r\n validationKey?: string\r\n): void {\r\n setState(\r\n (prevState) => {\r\n if (isFunction<U>(payload)) {\r\n const nestedValue = payload(getNestedValue(prevState, path));\r\n let value = updateNestedProperty(path, prevState, nestedValue);\r\n if (typeof value == \"string\") {\r\n value = value.trim();\r\n }\r\n return value;\r\n } else {\r\n let value =\r\n !path || path.length == 0\r\n ? payload\r\n : updateNestedProperty(path, prevState, payload);\r\n if (typeof value == \"string\") {\r\n value = value.trim();\r\n }\r\n return value;\r\n }\r\n },\r\n path,\r\n { updateType: \"update\" },\r\n validationKey\r\n );\r\n}\r\n\r\nexport function pushFunc<U>(\r\n setState: EffectiveSetState<U>,\r\n payload: UpdateArg<U>,\r\n path: string[],\r\n stateKey: string,\r\n index?: number\r\n): void {\r\n const array = getGlobalStore.getState().getNestedState(stateKey, path) as U[];\r\n setState(\r\n (prevState) => {\r\n let arrayToUpdate =\r\n !path || path.length == 0\r\n ? prevState\r\n : getNestedValue(prevState, [...path]);\r\n let returnedArray = [...arrayToUpdate];\r\n\r\n returnedArray.splice(\r\n index || Number(index) == 0 ? index : arrayToUpdate.length,\r\n 0,\r\n isFunction<U>(payload)\r\n ? payload(index == -1 ? undefined : arrayToUpdate)\r\n : payload\r\n );\r\n const value =\r\n path.length == 0\r\n ? returnedArray\r\n : updateNestedProperty([...path], prevState, returnedArray);\r\n\r\n return value as U;\r\n },\r\n [\r\n ...path,\r\n index || index === 0 ? index?.toString() : (array!.length - 1).toString(),\r\n ],\r\n {\r\n updateType: \"insert\",\r\n }\r\n );\r\n}\r\n\r\nexport function cutFunc<U>(\r\n setState: EffectiveSetState<U>,\r\n path: string[],\r\n stateKey: string,\r\n index: number\r\n): void {\r\n const array = getGlobalStore.getState().getNestedState(stateKey, path) as U[];\r\n setState(\r\n (prevState) => {\r\n const arrayToUpdate = getNestedValue(prevState, [...path]);\r\n if (index < 0 || index >= arrayToUpdate?.length) {\r\n throw new Error(`Index ${index} does not exist in the array.`);\r\n }\r\n const indexToCut =\r\n index || Number(index) == 0 ? index : arrayToUpdate.length - 1;\r\n\r\n const updatedArray = [\r\n ...arrayToUpdate.slice(0, indexToCut),\r\n ...arrayToUpdate.slice(indexToCut + 1),\r\n ] as U;\r\n\r\n return path.length == 0\r\n ? updatedArray\r\n : updateNestedProperty([...path], prevState, updatedArray);\r\n },\r\n [\r\n ...path,\r\n index || index === 0 ? index?.toString() : (array!.length - 1).toString(),\r\n ],\r\n { updateType: \"cut\" }\r\n );\r\n}\r\n\r\nexport const useStoreSubscription = <T,>(\r\n fullPath: string,\r\n selector: (\r\n store: ReturnType<typeof getGlobalStore.getState>,\r\n path: string\r\n ) => T,\r\n compare: (a: T, b: T) => boolean = (a, b) =>\r\n JSON.stringify(a) === JSON.stringify(b)\r\n) => {\r\n const [value, setValue] = useState<T>(() =>\r\n selector(getGlobalStore.getState(), fullPath)\r\n );\r\n const previousValueRef = useRef<T>(value);\r\n const fullPathRef = useRef(fullPath);\r\n useEffect(() => {\r\n fullPathRef.current = fullPath; // Ensure latest fullPath is always used\r\n\r\n setValue(selector(getGlobalStore.getState(), fullPath));\r\n\r\n const callback = (store: any) => {\r\n const newValue = selector(store, fullPathRef.current);\r\n\r\n if (!compare(previousValueRef.current, newValue)) {\r\n previousValueRef.current = newValue;\r\n setValue(newValue);\r\n }\r\n };\r\n const unsubscribe = getGlobalStore.subscribe(callback);\r\n return () => {\r\n unsubscribe();\r\n };\r\n }, [fullPath]);\r\n return value;\r\n};\r\nexport const useGetValidationErrors = (\r\n validationKey: string,\r\n path: string[],\r\n validIndices?: number[]\r\n) => {\r\n const fullPath =\r\n validationKey +\r\n \".\" +\r\n (path.length > 0 ? [path.join(\".\")] : []) +\r\n (validIndices && validIndices.length > 0 ? \".\" + validIndices : \"\");\r\n\r\n const returnresult = useStoreSubscription(\r\n fullPath,\r\n (store, path) => store.getValidationErrors(path) || []\r\n );\r\n\r\n return returnresult;\r\n};\r\n\r\nexport const useGetSyncInfo = (key: string, path: string[]) => {\r\n const syncKey = `${key}:${path.join(\".\")}`;\r\n return useStoreSubscription(syncKey, (store, path) =>\r\n store.getSyncInfo(path)\r\n );\r\n};\r\nexport const useGetKeyState = (key: string, path: string[]) => {\r\n return useStoreSubscription(`${key}:${path.join(\".\")}`, (store, fullPath) =>\r\n store.getNestedState(key, path)\r\n );\r\n};\r\ninterface FormControlComponentProps<TStateObject> {\r\n setState: EffectiveSetState<TStateObject>;\r\n\r\n path: string[];\r\n child: (obj: FormElementParams<TStateObject>) => JSX.Element;\r\n formOpts?: FormOptsType;\r\n stateKey: string;\r\n}\r\n// Find FormControlComponent in your Functions.ts or equivalent file\r\n\r\nexport const FormControlComponent = <TStateObject,>({\r\n setState, // This is the real effectiveSetState from the hook\r\n path,\r\n child,\r\n formOpts,\r\n stateKey,\r\n}: FormControlComponentProps<TStateObject>) => {\r\n const { registerFormRef, getFormRef } = formRefStore.getState();\r\n const {\r\n getValidationErrors,\r\n addValidationError,\r\n getInitialOptions,\r\n removeValidationError,\r\n } = getGlobalStore.getState();\r\n\r\n const refKey = stateKey + \".\" + path.join(\".\");\r\n const localFormRef = useRef<HTMLInputElement>(null);\r\n const existingRef = getFormRef(refKey);\r\n if (!existingRef) {\r\n registerFormRef(refKey, localFormRef);\r\n }\r\n const formRef = existingRef || localFormRef;\r\n\r\n // --- START CHANGES ---\r\n\r\n const globalStateValue = useGetKeyState(stateKey, path);\r\n const [localValue, setLocalValue] = useState<any>(globalStateValue);\r\n const isCurrentlyDebouncing = useRef(false);\r\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n // Effect to sync local state if global state changes externally\r\n useEffect(() => {\r\n // Only update local if not actively debouncing a local change\r\n if (!isCurrentlyDebouncing.current && globalStateValue !== localValue) {\r\n setLocalValue(globalStateValue);\r\n }\r\n }, [globalStateValue]); // Removed localValue dependency\r\n\r\n // Effect for cleanup\r\n useEffect(() => {\r\n return () => {\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n debounceTimeoutRef.current = null; // Explicitly nullify\r\n isCurrentlyDebouncing.current = false;\r\n }\r\n };\r\n }, []);\r\n\r\n const debouncedUpdater = (payload: UpdateArg<TStateObject>) => {\r\n setLocalValue(payload); // Update local state immediately\r\n isCurrentlyDebouncing.current = true;\r\n\r\n if (payload === \"\") {\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current); // Clear pending timer\r\n debounceTimeoutRef.current = null;\r\n }\r\n updateFn(setState, payload, path, validationKey); // Update global state NOW\r\n isCurrentlyDebouncing.current = false; // No longer debouncing\r\n return; // Don't proceed to set another timeout\r\n }\r\n\r\n // If not empty, proceed with normal debouncing\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n }\r\n\r\n debounceTimeoutRef.current = setTimeout(\r\n () => {\r\n isCurrentlyDebouncing.current = false;\r\n updateFn(setState, payload, path, validationKey);\r\n },\r\n formOpts?.debounceTime ??\r\n (typeof globalStateValue == \"boolean\" ? 20 : 200)\r\n );\r\n };\r\n\r\n const initialOptions = getInitialOptions(stateKey);\r\n if (!initialOptions?.validation?.key) {\r\n throw new Error(\"Validation key not found.\");\r\n }\r\n const validationKey = initialOptions.validation.key;\r\n const validateOnBlur = initialOptions.validation.onBlur === true;\r\n\r\n const handleBlur = async () => {\r\n // --- Ensure latest value is flushed if debouncing ---\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current); // Clear pending timer\r\n debounceTimeoutRef.current = null;\r\n isCurrentlyDebouncing.current = false;\r\n // Ensure the absolute latest local value is committed on blur\r\n updateFn(setState, localValue, path, validationKey);\r\n }\r\n // --- End modification ---\r\n\r\n if (!initialOptions.validation?.zodSchema || !validateOnBlur) return;\r\n removeValidationError(validationKey + \".\" + path.join(\".\"));\r\n try {\r\n // Use the potentially just flushed value\r\n const fieldValue = getGlobalStore\r\n .getState()\r\n .getNestedState(stateKey, path);\r\n await validateZodPathFunc(\r\n validationKey,\r\n initialOptions.validation.zodSchema,\r\n path,\r\n fieldValue\r\n );\r\n // forceUpdate might be needed if validation state update doesn't trigger render\r\n // Consider using useGetValidationErrors hook result directly for validation display\r\n } catch (error) {\r\n console.error(\"Validation error on blur:\", error);\r\n }\r\n };\r\n\r\n const rawSyncStatus = useGetSyncInfo(stateKey, path);\r\n const syncStatus = rawSyncStatus\r\n ? { ...rawSyncStatus, date: new Date(rawSyncStatus.timeStamp) }\r\n : null;\r\n\r\n const childElement = child({\r\n // --- START CHANGES ---\r\n get: () => localValue, // Get should return the immediate local value\r\n set: debouncedUpdater, // Use the new debounced updater\r\n // --- END CHANGES ---\r\n syncStatus,\r\n path: path,\r\n validationErrors: () =>\r\n getValidationErrors(validationKey + \".\" + path.join(\".\")),\r\n addValidationError: (message?: string) => {\r\n removeValidationError(validationKey + \".\" + path.join(\".\"));\r\n addValidationError(validationKey + \".\" + path.join(\".\"), message ?? \"\");\r\n },\r\n inputProps: {\r\n // --- START CHANGES ---\r\n value: localValue ?? \"\", // Input value is always the local state\r\n onChange: (e: any) => debouncedUpdater(e.target.value), // Use debounced updater\r\n // --- END CHANGES ---\r\n onBlur: handleBlur,\r\n ref: formRef,\r\n },\r\n });\r\n\r\n return (\r\n <>\r\n <ValidationWrapper {...{ formOpts, path, stateKey }}>\r\n {childElement}\r\n </ValidationWrapper>\r\n </>\r\n );\r\n};\r\nexport function ValidationWrapper({\r\n formOpts,\r\n path,\r\n\r\n stateKey,\r\n children,\r\n validIndices,\r\n}: {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n\r\n stateKey?: string;\r\n children: React.ReactNode;\r\n validIndices?: number[];\r\n}) {\r\n const { getInitialOptions } = getGlobalStore.getState();\r\n const thisStateOpts = getInitialOptions(stateKey!);\r\n const validationKey = thisStateOpts?.validation?.key ?? stateKey!;\r\n const validationErrors = useGetValidationErrors(\r\n validationKey,\r\n path,\r\n validIndices\r\n );\r\n // console.log(\r\n // \"validationErrors ValidationWrapper\",\r\n // stateKey,\r\n // validationKey,\r\n // path,\r\n // validationErrors\r\n // );\r\n const thesMessages: string[] = [];\r\n\r\n if (validationErrors) {\r\n const newMessage = validationErrors!.join(\", \");\r\n if (!thesMessages.includes(newMessage)) {\r\n thesMessages.push(newMessage);\r\n }\r\n }\r\n\r\n return (\r\n <>\r\n {thisStateOpts?.formElements?.validation &&\r\n !formOpts?.validation?.disable ? (\r\n thisStateOpts.formElements!.validation!({\r\n children: (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n ),\r\n active: validationErrors.length > 0 ? true : false,\r\n message: formOpts?.validation?.hideMessage\r\n ? \"\"\r\n : formOpts?.validation?.message\r\n ? formOpts?.validation?.message\r\n : thesMessages.map((m) => m).join(\", \"),\r\n path: path,\r\n })\r\n ) : (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["updateFn","setState","payload","path","validationKey","prevState","isFunction","nestedValue","getNestedValue","value","updateNestedProperty","pushFunc","stateKey","index","array","getGlobalStore","arrayToUpdate","returnedArray","cutFunc","indexToCut","updatedArray","useStoreSubscription","fullPath","selector","compare","a","b","setValue","useState","previousValueRef","useRef","fullPathRef","useEffect","callback","store","newValue","unsubscribe","useGetValidationErrors","validIndices","useGetSyncInfo","key","syncKey","useGetKeyState","FormControlComponent","child","formOpts","registerFormRef","getFormRef","formRefStore","getValidationErrors","addValidationError","getInitialOptions","removeValidationError","refKey","localFormRef","existingRef","formRef","globalStateValue","localValue","setLocalValue","isCurrentlyDebouncing","debounceTimeoutRef","debouncedUpdater","initialOptions","validateOnBlur","handleBlur","fieldValue","validateZodPathFunc","error","rawSyncStatus","syncStatus","childElement","message","e","jsx","Fragment","ValidationWrapper","children","thisStateOpts","validationErrors","thesMessages","newMessage","React","m"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -229,7 +229,6 @@ export type ArrayEndType<TShape extends unknown> = {
|
|
|
229
229
|
} & EndType<TShape>;
|
|
230
230
|
|
|
231
231
|
export type FormOptsType = {
|
|
232
|
-
key?: string;
|
|
233
232
|
validation?: {
|
|
234
233
|
hideMessage?: boolean;
|
|
235
234
|
message?: string;
|
|
@@ -237,9 +236,7 @@ export type FormOptsType = {
|
|
|
237
236
|
props?: GenericObject;
|
|
238
237
|
disable?: boolean;
|
|
239
238
|
};
|
|
240
|
-
formElements?: boolean;
|
|
241
239
|
debounceTime?: number;
|
|
242
|
-
stateServerDifferences?: string[][];
|
|
243
240
|
};
|
|
244
241
|
|
|
245
242
|
export type FormControl<T> = (obj: FormElementParams<T>) => JSX.Element;
|
|
@@ -1824,7 +1821,7 @@ function createProxyHandler<T>(
|
|
|
1824
1821
|
const wasAtBottomRef = useRef(true);
|
|
1825
1822
|
const userHasScrolledAwayRef = useRef(false);
|
|
1826
1823
|
const previousCountRef = useRef(0);
|
|
1827
|
-
|
|
1824
|
+
const lastRangeRef = useRef(range);
|
|
1828
1825
|
// Subscribe to shadow state updates
|
|
1829
1826
|
useEffect(() => {
|
|
1830
1827
|
const unsubscribe = getGlobalStore
|
|
@@ -1956,7 +1953,7 @@ function createProxyHandler<T>(
|
|
|
1956
1953
|
userHasScrolledAwayRef.current = true;
|
|
1957
1954
|
}
|
|
1958
1955
|
|
|
1959
|
-
// If user scrolls back to bottom,
|
|
1956
|
+
// If user scrolls back to bottom, cle
|
|
1960
1957
|
if (distanceFromBottom < 5) {
|
|
1961
1958
|
userHasScrolledAwayRef.current = false;
|
|
1962
1959
|
}
|
|
@@ -1979,10 +1976,26 @@ function createProxyHandler<T>(
|
|
|
1979
1976
|
endIndex = i;
|
|
1980
1977
|
}
|
|
1981
1978
|
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1979
|
+
const newStartIndex = Math.max(0, startIndex);
|
|
1980
|
+
const newEndIndex = Math.min(
|
|
1981
|
+
totalCount,
|
|
1982
|
+
endIndex + 1 + overscan
|
|
1983
|
+
);
|
|
1984
|
+
|
|
1985
|
+
// THE FIX: Only update state if the visible range of items has changed.
|
|
1986
|
+
if (
|
|
1987
|
+
newStartIndex !== lastRangeRef.current.startIndex ||
|
|
1988
|
+
newEndIndex !== lastRangeRef.current.endIndex
|
|
1989
|
+
) {
|
|
1990
|
+
lastRangeRef.current = {
|
|
1991
|
+
startIndex: newStartIndex,
|
|
1992
|
+
endIndex: newEndIndex,
|
|
1993
|
+
};
|
|
1994
|
+
setRange({
|
|
1995
|
+
startIndex: newStartIndex,
|
|
1996
|
+
endIndex: newEndIndex,
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1986
1999
|
};
|
|
1987
2000
|
|
|
1988
2001
|
container.addEventListener("scroll", handleScroll, {
|
|
@@ -2153,7 +2166,8 @@ function createProxyHandler<T>(
|
|
|
2153
2166
|
index: { localIndex: number; originalIndex: number },
|
|
2154
2167
|
array: T,
|
|
2155
2168
|
arraySetter: StateObject<T>
|
|
2156
|
-
) => any
|
|
2169
|
+
) => any,
|
|
2170
|
+
formOpts?: FormOptsType
|
|
2157
2171
|
) => {
|
|
2158
2172
|
const arrayToMap = getGlobalStore
|
|
2159
2173
|
.getState()
|
|
@@ -2180,6 +2194,7 @@ function createProxyHandler<T>(
|
|
|
2180
2194
|
key: originalIndex,
|
|
2181
2195
|
stateKey,
|
|
2182
2196
|
itemComponentId,
|
|
2197
|
+
formOpts,
|
|
2183
2198
|
itemPath: finalPath,
|
|
2184
2199
|
children: callbackfn(
|
|
2185
2200
|
item,
|
|
@@ -2716,10 +2731,6 @@ function createProxyHandler<T>(
|
|
|
2716
2731
|
hideMessage ? { validation: { message: "" } } : undefined
|
|
2717
2732
|
}
|
|
2718
2733
|
path={path}
|
|
2719
|
-
validationKey={
|
|
2720
|
-
getGlobalStore.getState().getInitialOptions(stateKey)
|
|
2721
|
-
?.validation?.key || ""
|
|
2722
|
-
}
|
|
2723
2734
|
stateKey={stateKey}
|
|
2724
2735
|
validIndices={meta?.validIndices}
|
|
2725
2736
|
>
|
|
@@ -2936,11 +2947,13 @@ function CogsItemWrapper({
|
|
|
2936
2947
|
stateKey,
|
|
2937
2948
|
itemComponentId,
|
|
2938
2949
|
itemPath,
|
|
2950
|
+
formOpts,
|
|
2939
2951
|
children,
|
|
2940
2952
|
}: {
|
|
2941
2953
|
stateKey: string;
|
|
2942
2954
|
itemComponentId: string;
|
|
2943
2955
|
itemPath: string[];
|
|
2956
|
+
formOpts?: FormOptsType;
|
|
2944
2957
|
children: React.ReactNode;
|
|
2945
2958
|
}) {
|
|
2946
2959
|
// This hook handles the re-rendering when the item's own data changes.
|
|
@@ -3006,5 +3019,9 @@ function CogsItemWrapper({
|
|
|
3006
3019
|
}, [stateKey, itemComponentId, itemPath.join(".")]);
|
|
3007
3020
|
|
|
3008
3021
|
// The rendered output is a simple div that gets measured.
|
|
3009
|
-
return
|
|
3022
|
+
return (
|
|
3023
|
+
<ValidationWrapper {...{ formOpts, path: itemPath, stateKey }}>
|
|
3024
|
+
{children}
|
|
3025
|
+
</ValidationWrapper>
|
|
3026
|
+
);
|
|
3010
3027
|
}
|
package/src/Functions.tsx
CHANGED
|
@@ -338,7 +338,7 @@ export const FormControlComponent = <TStateObject,>({
|
|
|
338
338
|
|
|
339
339
|
return (
|
|
340
340
|
<>
|
|
341
|
-
<ValidationWrapper {...{ formOpts, path,
|
|
341
|
+
<ValidationWrapper {...{ formOpts, path, stateKey }}>
|
|
342
342
|
{childElement}
|
|
343
343
|
</ValidationWrapper>
|
|
344
344
|
</>
|
|
@@ -347,20 +347,21 @@ export const FormControlComponent = <TStateObject,>({
|
|
|
347
347
|
export function ValidationWrapper({
|
|
348
348
|
formOpts,
|
|
349
349
|
path,
|
|
350
|
-
|
|
350
|
+
|
|
351
351
|
stateKey,
|
|
352
352
|
children,
|
|
353
353
|
validIndices,
|
|
354
354
|
}: {
|
|
355
355
|
formOpts?: FormOptsType;
|
|
356
356
|
path: string[];
|
|
357
|
-
|
|
357
|
+
|
|
358
358
|
stateKey?: string;
|
|
359
359
|
children: React.ReactNode;
|
|
360
360
|
validIndices?: number[];
|
|
361
361
|
}) {
|
|
362
362
|
const { getInitialOptions } = getGlobalStore.getState();
|
|
363
|
-
|
|
363
|
+
const thisStateOpts = getInitialOptions(stateKey!);
|
|
364
|
+
const validationKey = thisStateOpts?.validation?.key ?? stateKey!;
|
|
364
365
|
const validationErrors = useGetValidationErrors(
|
|
365
366
|
validationKey,
|
|
366
367
|
path,
|
|
@@ -381,7 +382,6 @@ export function ValidationWrapper({
|
|
|
381
382
|
thesMessages.push(newMessage);
|
|
382
383
|
}
|
|
383
384
|
}
|
|
384
|
-
const thisStateOpts = getInitialOptions(stateKey!);
|
|
385
385
|
|
|
386
386
|
return (
|
|
387
387
|
<>
|
|
@@ -398,8 +398,6 @@ export function ValidationWrapper({
|
|
|
398
398
|
? formOpts?.validation?.message
|
|
399
399
|
: thesMessages.map((m) => m).join(", "),
|
|
400
400
|
path: path,
|
|
401
|
-
|
|
402
|
-
...(formOpts?.key && { key: formOpts?.key }),
|
|
403
401
|
})
|
|
404
402
|
) : (
|
|
405
403
|
<React.Fragment key={path.toString()}>{children}</React.Fragment>
|