cogsbox-state 0.5.432 → 0.5.434

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.
@@ -1,22 +1,9 @@
1
- import { EffectiveSetState, FormElementParams, FormOptsType, UpdateArg } from './CogsState';
1
+ import { FormOptsType } from './CogsState';
2
2
  import { default as React } from 'react';
3
3
  import { getGlobalStore } from './store';
4
4
 
5
- export declare function updateFn<U>(setState: EffectiveSetState<U>, payload: UpdateArg<U>, path: string[], validationKey?: string): void;
6
- export declare function pushFunc<U>(setState: EffectiveSetState<U>, payload: UpdateArg<U>, path: string[], stateKey: string, index?: number): void;
7
- export declare function cutFunc<U>(setState: EffectiveSetState<U>, path: string[], stateKey: string, index: number): void;
8
5
  export declare const useStoreSubscription: <T>(fullPath: string, selector: (store: ReturnType<typeof getGlobalStore.getState>, path: string) => T, compare?: (a: T, b: T) => boolean) => T;
9
6
  export declare const useGetValidationErrors: (validationKey: string, path: string[], validIndices?: number[]) => string[];
10
- export declare const useGetSyncInfo: (key: string, path: string[]) => import('./CogsState').SyncInfo | null;
11
- export declare const useGetKeyState: (key: string, path: string[]) => any;
12
- interface FormControlComponentProps<TStateObject> {
13
- setState: EffectiveSetState<TStateObject>;
14
- path: string[];
15
- child: (obj: FormElementParams<TStateObject>) => JSX.Element;
16
- formOpts?: FormOptsType;
17
- stateKey: string;
18
- }
19
- export declare const FormControlComponent: <TStateObject>({ setState, path, child, formOpts, stateKey, }: FormControlComponentProps<TStateObject>) => import("react/jsx-runtime").JSX.Element;
20
7
  export type ValidationWrapperProps = {
21
8
  formOpts?: FormOptsType;
22
9
  path: string[];
@@ -25,4 +12,3 @@ export type ValidationWrapperProps = {
25
12
  validIndices?: number[];
26
13
  };
27
14
  export declare function ValidationWrapper({ formOpts, path, stateKey, children, validIndices, }: ValidationWrapperProps): import("react/jsx-runtime").JSX.Element;
28
- export {};
@@ -1,201 +1,54 @@
1
- import { jsx as V, Fragment as C } from "react/jsx-runtime";
1
+ import { jsx as m, Fragment as S } from "react/jsx-runtime";
2
2
  import "./CogsState.jsx";
3
- import { isFunction as G, getNestedValue as R, updateNestedPropertyIds as w } from "./utility.js";
4
- import k, { useRef as b, useState as D, useEffect as T } from "react";
5
- import { getGlobalStore as m, formRefStore as x } from "./store.js";
6
- import { validateZodPathFunc as K } from "./useValidateZodPath.js";
7
- import { ulid as L } from "ulid";
8
- function F(n, e, t, r) {
9
- n(
10
- (i) => {
11
- if (G(e)) {
12
- const s = e(R(i, t));
13
- console.group("nestedValue", t, s);
14
- let o = w(t, i, s);
15
- return console.group("updateFn", o), typeof o == "string" && (o = o.trim()), o;
16
- } else {
17
- let s = !t || t.length == 0 ? e : w(t, i, e);
18
- return typeof s == "string" && (s = s.trim()), s;
19
- }
20
- },
21
- t,
22
- { updateType: "update" },
23
- r
24
- );
25
- }
26
- function te(n, e, t, r, i) {
27
- const s = m.getState().getNestedState(r, t) || [], o = G(e) ? e(s) : e;
28
- typeof o == "object" && o !== null && !o.id && (o.id = L());
29
- const f = o.id;
30
- n(
31
- (c) => {
32
- const u = [...R(c, [...t]) || []];
33
- return u.splice(u.length, 0, o), w([...t], c, u);
34
- },
35
- [...t, `id:${f}`],
36
- // Now we use the ID that is guaranteed to be correct.
37
- {
38
- updateType: "insert"
39
- }
40
- );
41
- }
42
- function ne(n, e, t, r) {
43
- const i = [t, ...e].join("."), o = m.getState().shadowStateStore.get(i)?.arrayKeys?.[r];
44
- if (!o)
45
- throw new Error(`No ID found for index ${r} in array`);
46
- n(
47
- (f) => {
48
- const c = R(f, [...e]);
49
- if (r < 0 || r >= c?.length)
50
- throw new Error(`Index ${r} does not exist in the array.`);
51
- const d = [
52
- ...c.slice(0, r),
53
- ...c.slice(r + 1)
54
- ];
55
- return e.length == 0 ? d : w([...e], f, d);
56
- },
57
- [...e, o],
58
- // Use the ID here!
59
- { updateType: "cut" }
60
- );
61
- }
62
- const I = (n, e, t = (r, i) => JSON.stringify(r) === JSON.stringify(i)) => {
63
- const [r, i] = D(
64
- () => e(m.getState(), n)
65
- ), s = b(r), o = b(n);
66
- return T(() => {
67
- o.current = n, i(e(m.getState(), n));
68
- const f = (d) => {
69
- const u = e(d, o.current);
70
- t(s.current, u) || (s.current = u, i(u));
71
- }, c = m.subscribe(f);
3
+ import d, { useState as v, useRef as f, useEffect as b } from "react";
4
+ import { getGlobalStore as l } from "./store.js";
5
+ const p = (t, e, r = (n, o) => JSON.stringify(n) === JSON.stringify(o)) => {
6
+ const [n, o] = v(
7
+ () => e(l.getState(), t)
8
+ ), a = f(n), i = f(t);
9
+ return b(() => {
10
+ i.current = t, o(e(l.getState(), t));
11
+ const g = (c) => {
12
+ const s = e(c, i.current);
13
+ r(a.current, s) || (a.current = s, o(s));
14
+ }, u = l.subscribe(g);
72
15
  return () => {
73
- c();
16
+ u();
74
17
  };
75
- }, [n]), r;
76
- }, W = (n, e, t) => {
77
- const r = n + "." + (e.length > 0 ? [e.join(".")] : []) + (t && t.length > 0 ? "." + t : "");
78
- return I(
79
- r,
80
- (s, o) => s.getValidationErrors(o) || []
18
+ }, [t]), n;
19
+ }, E = (t, e, r) => {
20
+ const n = t + "." + (e.length > 0 ? [e.join(".")] : []) + (r && r.length > 0 ? "." + r : "");
21
+ return p(
22
+ n,
23
+ (a, i) => a.getValidationErrors(i) || []
81
24
  );
82
- }, Z = (n, e) => {
83
- const t = `${n}:${e.join(".")}`;
84
- return I(
85
- t,
86
- (r, i) => r.getSyncInfo(i)
87
- );
88
- }, p = (n, e) => I(
89
- `${n}:${e.join(".")}`,
90
- (t, r) => t.getNestedState(n, e)
91
- ), re = ({
92
- setState: n,
93
- // This is the real effectiveSetState from the hook
94
- path: e,
95
- child: t,
96
- formOpts: r,
97
- stateKey: i
98
- }) => {
99
- const { registerFormRef: s, getFormRef: o } = x.getState(), {
100
- getValidationErrors: f,
101
- addValidationError: c,
102
- getInitialOptions: d,
103
- removeValidationError: u
104
- } = m.getState(), N = i + "." + e.join("."), $ = b(null), B = o(N);
105
- B || s(N, $);
106
- const O = B || $, y = p(i, e), [E, M] = D(y), S = b(!1), a = b(null);
107
- T(() => {
108
- !S.current && y !== E && M(y);
109
- }, [y]), T(() => () => {
110
- a.current && (clearTimeout(a.current), a.current = null, S.current = !1);
111
- }, []);
112
- const U = (l) => {
113
- if (M(l), S.current = !0, l === "") {
114
- a.current && (clearTimeout(a.current), a.current = null), F(n, l, e, g), S.current = !1;
115
- return;
116
- }
117
- a.current && clearTimeout(a.current), a.current = setTimeout(
118
- () => {
119
- S.current = !1, F(n, l, e, g);
120
- },
121
- r?.debounceTime ?? (typeof y == "boolean" ? 20 : 200)
122
- );
123
- }, v = d(i);
124
- if (!v?.validation?.key)
125
- throw new Error("Validation key not found.");
126
- const g = v.validation.key, z = v.validation.onBlur === !0, A = async () => {
127
- if (a.current && (clearTimeout(a.current), a.current = null, S.current = !1, F(n, E, e, g)), !(!v.validation?.zodSchema || !z)) {
128
- u(g + "." + e.join("."));
129
- try {
130
- const l = m.getState().getNestedState(i, e);
131
- await K(
132
- g,
133
- v.validation.zodSchema,
134
- e,
135
- l
136
- );
137
- } catch (l) {
138
- console.error("Validation error on blur:", l);
139
- }
140
- }
141
- }, j = Z(i, e), J = j ? { ...j, date: new Date(j.timeStamp) } : null, P = t({
142
- // --- START CHANGES ---
143
- get: () => E,
144
- // Get should return the immediate local value
145
- set: U,
146
- // Use the new debounced updater
147
- // --- END CHANGES ---
148
- syncStatus: J,
149
- path: e,
150
- validationErrors: () => f(g + "." + e.join(".")),
151
- addValidationError: (l) => {
152
- u(g + "." + e.join(".")), c(g + "." + e.join("."), l ?? "");
153
- },
154
- inputProps: {
155
- // --- START CHANGES ---
156
- value: E ?? "",
157
- // Input value is always the local state
158
- onChange: (l) => U(l.target.value),
159
- // Use debounced updater
160
- // --- END CHANGES ---
161
- onBlur: A,
162
- ref: O
163
- }
164
- });
165
- return /* @__PURE__ */ V(C, { children: /* @__PURE__ */ V(q, { formOpts: r, path: e, stateKey: i, children: P }) });
166
25
  };
167
- function q({
168
- formOpts: n,
26
+ function F({
27
+ formOpts: t,
169
28
  path: e,
170
- stateKey: t,
171
- children: r,
172
- validIndices: i
29
+ stateKey: r,
30
+ children: n,
31
+ validIndices: o
173
32
  }) {
174
- const { getInitialOptions: s } = m.getState(), o = s(t), f = o?.validation?.key ?? t, c = W(
175
- f,
33
+ const { getInitialOptions: a } = l.getState(), i = a(r), g = i?.validation?.key ?? r, u = E(
34
+ g,
176
35
  e,
177
- i
178
- ), d = [];
179
- if (c) {
180
- const u = c.join(", ");
181
- d.includes(u) || d.push(u);
36
+ o
37
+ ), c = [];
38
+ if (u) {
39
+ const s = u.join(", ");
40
+ c.includes(s) || c.push(s);
182
41
  }
183
- return /* @__PURE__ */ V(C, { children: o?.formElements?.validation && !n?.validation?.disable ? o.formElements.validation({
184
- children: /* @__PURE__ */ V(k.Fragment, { children: r }, e.toString()),
185
- active: c.length > 0,
186
- message: n?.validation?.hideMessage ? "" : n?.validation?.message ? n?.validation?.message : d.map((u) => u).join(", "),
42
+ return /* @__PURE__ */ m(S, { children: i?.formElements?.validation && !t?.validation?.disable ? i.formElements.validation({
43
+ children: /* @__PURE__ */ m(d.Fragment, { children: n }, e.toString()),
44
+ active: u.length > 0,
45
+ message: t?.validation?.hideMessage ? "" : t?.validation?.message ? t?.validation?.message : c.map((s) => s).join(", "),
187
46
  path: e
188
- }) : /* @__PURE__ */ V(k.Fragment, { children: r }, e.toString()) });
47
+ }) : /* @__PURE__ */ m(d.Fragment, { children: n }, e.toString()) });
189
48
  }
190
49
  export {
191
- re as FormControlComponent,
192
- q as ValidationWrapper,
193
- ne as cutFunc,
194
- te as pushFunc,
195
- F as updateFn,
196
- p as useGetKeyState,
197
- Z as useGetSyncInfo,
198
- W as useGetValidationErrors,
199
- I as useStoreSubscription
50
+ F as ValidationWrapper,
51
+ E as useGetValidationErrors,
52
+ p as useStoreSubscription
200
53
  };
201
54
  //# sourceMappingURL=Functions.jsx.map
@@ -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 {\r\n getNestedValue,\r\n isFunction,\r\n updateNestedProperty,\r\n updateNestedPropertyIds,\r\n} 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\nimport { ulid } from \"ulid\";\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 console.group(\"nestedValue\", path, nestedValue);\r\n let value = updateNestedPropertyIds(path, prevState, nestedValue);\r\n console.group(\"updateFn\", value);\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 : updateNestedPropertyIds(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\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 // --- THE FIX ---\r\n // 1. Determine the newItem and its ID BEFORE calling setState.\r\n const arrayBeforeUpdate =\r\n (getGlobalStore.getState().getNestedState(stateKey, path) as any[]) || [];\r\n\r\n const newItem = isFunction<U>(payload)\r\n ? payload(arrayBeforeUpdate as any)\r\n : payload;\r\n\r\n // 2. Ensure it has an ID.\r\n if (typeof newItem === \"object\" && newItem !== null && !(newItem as any).id) {\r\n (newItem as any).id = ulid();\r\n }\r\n const finalId = (newItem as any).id;\r\n // --- END OF FIX ---\r\n\r\n setState(\r\n (prevState) => {\r\n // The logic inside here is now much simpler.\r\n // We already have the final `newItem`.\r\n const arrayToUpdate = getNestedValue(prevState, [...path]) || [];\r\n const newArray = [...arrayToUpdate];\r\n newArray.splice(index ?? newArray.length, 0, newItem);\r\n return updateNestedPropertyIds([...path], prevState, newArray);\r\n },\r\n [...path, `id:${finalId}`], // Now we use the ID that is guaranteed to be correct.\r\n {\r\n updateType: \"insert\",\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 // Get the ordered IDs to find the ID for this index\r\n const arrayKey = [stateKey, ...path].join(\".\");\r\n const arrayMeta = getGlobalStore.getState().shadowStateStore.get(arrayKey);\r\n const itemId = arrayMeta?.arrayKeys?.[index];\r\n\r\n if (!itemId) {\r\n throw new Error(`No ID found for index ${index} in array`);\r\n }\r\n\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\r\n const updatedArray = [\r\n ...arrayToUpdate.slice(0, index),\r\n ...arrayToUpdate.slice(index + 1),\r\n ] as U;\r\n\r\n return path.length == 0\r\n ? updatedArray\r\n : updateNestedPropertyIds([...path], prevState, updatedArray);\r\n },\r\n [...path, itemId], // Use the ID here!\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 type ValidationWrapperProps = {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n stateKey: string;\r\n children: React.ReactNode;\r\n validIndices?: number[];\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}: ValidationWrapperProps) {\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","updateNestedPropertyIds","pushFunc","stateKey","index","arrayBeforeUpdate","getGlobalStore","newItem","ulid","finalId","newArray","cutFunc","arrayKey","itemId","arrayToUpdate","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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"}
1
+ {"version":3,"file":"Functions.jsx","sources":["../src/Functions.tsx"],"sourcesContent":["import { type FormOptsType } from './CogsState';\r\n\r\nimport { useEffect, useRef, useState } from 'react';\r\nimport React from 'react';\r\nimport { getGlobalStore } from './store';\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\n// Find FormControlComponent in your Functions.ts or equivalent file\r\n\r\n// export 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// rebuildStateShape,\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// const stateKeyPathKey = [stateKey, ...path].join('.');\r\n// const [, forceUpdate] = useState<any>();\r\n// getGlobalStore.getState().subscribeToPath(stateKeyPathKey, () => {\r\n// forceUpdate({});\r\n// });\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 = getGlobalStore\r\n// .getState()\r\n// .getShadowValue(stateKeyPathKey);\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\r\n// setState(payload, path, { updateType: 'update' });\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// console.log('debouncedUpdater', payload);\r\n// setState(payload, path, { updateType: 'update' });\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\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// setState(localValue, path, { updateType: 'update' });\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// if (!validationKey) return;\r\n// const fieldValue = getGlobalStore\r\n// .getState()\r\n// .getShadowValue(stateKeyPathKey);\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 childElement = child({\r\n// state: setter,\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\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 type ValidationWrapperProps = {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n stateKey: string;\r\n children: React.ReactNode;\r\n validIndices?: number[];\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}: ValidationWrapperProps) {\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":["useStoreSubscription","fullPath","selector","compare","a","b","value","setValue","useState","getGlobalStore","previousValueRef","useRef","fullPathRef","useEffect","callback","store","newValue","unsubscribe","useGetValidationErrors","validationKey","path","validIndices","ValidationWrapper","formOpts","stateKey","children","getInitialOptions","thisStateOpts","validationErrors","thesMessages","newMessage","jsx","Fragment","React","m"],"mappings":";;;;AAMO,MAAMA,IAAuB,CAClCC,GACAC,GAIAC,IAAmC,CAACC,GAAGC,MACrC,KAAK,UAAUD,CAAC,MAAM,KAAK,UAAUC,CAAC,MACrC;AACG,QAAA,CAACC,GAAOC,CAAQ,IAAIC;AAAA,IAAY,MACpCN,EAASO,EAAe,SAAA,GAAYR,CAAQ;AAAA,EAC9C,GACMS,IAAmBC,EAAUL,CAAK,GAClCM,IAAcD,EAAOV,CAAQ;AACnC,SAAAY,EAAU,MAAM;AACd,IAAAD,EAAY,UAAUX,GAEtBM,EAASL,EAASO,EAAe,SAAS,GAAGR,CAAQ,CAAC;AAEhD,UAAAa,IAAW,CAACC,MAAe;AAC/B,YAAMC,IAAWd,EAASa,GAAOH,EAAY,OAAO;AAEpD,MAAKT,EAAQO,EAAiB,SAASM,CAAQ,MAC7CN,EAAiB,UAAUM,GAC3BT,EAASS,CAAQ;AAAA,IAErB,GACMC,IAAcR,EAAe,UAAUK,CAAQ;AACrD,WAAO,MAAM;AACC,MAAAG,EAAA;AAAA,IACd;AAAA,EAAA,GACC,CAAChB,CAAQ,CAAC,GACNK;AACT,GACaY,IAAyB,CACpCC,GACAC,GACAC,MACG;AACH,QAAMpB,IACJkB,IACA,OACCC,EAAK,SAAS,IAAI,CAACA,EAAK,KAAK,GAAG,CAAC,IAAI,CACrC,MAAAC,KAAgBA,EAAa,SAAS,IAAI,MAAMA,IAAe;AAO3D,SALcrB;AAAA,IACnBC;AAAA,IACA,CAACc,GAAOK,MAASL,EAAM,oBAAoBK,CAAI,KAAK,CAAA;AAAA,EACtD;AAGF;AAwKO,SAASE,EAAkB;AAAA,EAChC,UAAAC;AAAA,EACA,MAAAH;AAAA,EAEA,UAAAI;AAAA,EACA,UAAAC;AAAA,EACA,cAAAJ;AACF,GAA2B;AACzB,QAAM,EAAE,mBAAAK,EAAA,IAAsBjB,EAAe,SAAS,GAChDkB,IAAgBD,EAAkBF,CAAS,GAC3CL,IAAgBQ,GAAe,YAAY,OAAOH,GAClDI,IAAmBV;AAAA,IACvBC;AAAA,IACAC;AAAA,IACAC;AAAA,EACF,GAQMQ,IAAyB,CAAC;AAEhC,MAAID,GAAkB;AACd,UAAAE,IAAaF,EAAkB,KAAK,IAAI;AAC9C,IAAKC,EAAa,SAASC,CAAU,KACnCD,EAAa,KAAKC,CAAU;AAAA,EAC9B;AAIA,SAAA,gBAAAC,EAAAC,GAAA,EACG,UAAeL,GAAA,cAAc,cAC9B,CAACJ,GAAU,YAAY,UACrBI,EAAc,aAAc,WAAY;AAAA,IACtC,4BACGM,EAAM,UAAN,EAAsC,UAAAR,KAAlBL,EAAK,UAAsB;AAAA,IAElD,QAAQQ,EAAiB,SAAS;AAAA,IAClC,SAASL,GAAU,YAAY,cAC3B,KACAA,GAAU,YAAY,UACpBA,GAAU,YAAY,UACtBM,EAAa,IAAI,CAACK,MAAMA,CAAC,EAAE,KAAK,IAAI;AAAA,IAC1C,MAAAd;AAAA,EAAA,CACD,IAED,gBAAAW,EAACE,EAAM,UAAN,EAAsC,UAAAR,EAAlB,GAAAL,EAAK,SAAsB,CAAA,GAEpD;AAEJ;"}
package/dist/index.js CHANGED
@@ -1,31 +1,30 @@
1
- import { $cogsSignal as r, $cogsSignalStore as o, addStateOptions as s, createCogsState as n, notifyComponent as a, useCogsStateFn as i } from "./CogsState.jsx";
2
- import { CogsStateClient as f, config as c, useCogsConfig as p } from "./CogsStateClient.jsx";
3
- import { debounce as u, deleteNestedProperty as y, getArrayLengthDifferences as C, getArrayLengthDifferencesArray as S, getDifferences as l, getDifferencesArray as m, getNestedValue as A, isArray as D, isDeepEqual as x, isFunction as N, isObject as F, transformStateFunc as L, updateNestedProperty as P, updateNestedPropertyIds as b } from "./utility.js";
1
+ import { $cogsSignal as r, addStateOptions as o, createCogsState as n, notifyComponent as s, useCogsStateFn as a } from "./CogsState.jsx";
2
+ import { CogsStateClient as g, config as f, useCogsConfig as c } from "./CogsStateClient.jsx";
3
+ import { debounce as d, deepMerge as u, deleteNestedProperty as y, getArrayLengthDifferences as C, getArrayLengthDifferencesArray as l, getDifferences as m, getDifferencesArray as S, getNestedValue as A, isArray as D, isDeepEqual as x, isFunction as F, isObject as L, transformStateFunc as N, updateNestedProperty as b } from "./utility.js";
4
4
  import { useCogsTrpcValidationLink as O } from "./TRPCValidationLink.js";
5
5
  export {
6
6
  r as $cogsSignal,
7
- o as $cogsSignalStore,
8
- f as CogsStateClient,
9
- s as addStateOptions,
10
- c as config,
7
+ g as CogsStateClient,
8
+ o as addStateOptions,
9
+ f as config,
11
10
  n as createCogsState,
12
- u as debounce,
11
+ d as debounce,
12
+ u as deepMerge,
13
13
  y as deleteNestedProperty,
14
14
  C as getArrayLengthDifferences,
15
- S as getArrayLengthDifferencesArray,
16
- l as getDifferences,
17
- m as getDifferencesArray,
15
+ l as getArrayLengthDifferencesArray,
16
+ m as getDifferences,
17
+ S as getDifferencesArray,
18
18
  A as getNestedValue,
19
19
  D as isArray,
20
20
  x as isDeepEqual,
21
- N as isFunction,
22
- F as isObject,
23
- a as notifyComponent,
24
- L as transformStateFunc,
25
- P as updateNestedProperty,
26
- b as updateNestedPropertyIds,
27
- p as useCogsConfig,
28
- i as useCogsStateFn,
21
+ F as isFunction,
22
+ L as isObject,
23
+ s as notifyComponent,
24
+ N as transformStateFunc,
25
+ b as updateNestedProperty,
26
+ c as useCogsConfig,
27
+ a as useCogsStateFn,
29
28
  O as useCogsTrpcValidationLink
30
29
  };
31
30
  //# sourceMappingURL=index.js.map
package/dist/store.d.ts CHANGED
@@ -1,29 +1,17 @@
1
- import { OptionsType, ReactivityType, StateKeys, SyncActionsType, SyncInfo, UpdateTypeDetail } from './CogsState.js';
1
+ import { OptionsType, ReactivityType, SyncInfo, UpdateTypeDetail } from './CogsState.js';
2
+ import { ReactNode } from 'react';
2
3
 
3
- type StateUpdater<StateValue> = StateValue | ((prevValue: StateValue) => StateValue);
4
4
  export type FreshValuesObject = {
5
5
  pathsToValues?: string[];
6
6
  prevValue?: any;
7
7
  newValue?: any;
8
8
  timeStamp: number;
9
9
  };
10
- type SyncLogType = {
11
- timeStamp: number;
12
- };
13
10
  type StateValue = any;
14
11
  export type TrieNode = {
15
12
  subscribers: Set<string>;
16
13
  children: Map<string, TrieNode>;
17
14
  };
18
- export type ComponentsType = {
19
- components: Map<string, {
20
- forceUpdate: () => void;
21
- paths: Set<string>;
22
- deps?: any[];
23
- depsFunction?: (state: any) => any[] | true;
24
- reactiveType: ReactivityType[] | ReactivityType;
25
- }>;
26
- };
27
15
  export type FormRefStoreState = {
28
16
  formRefs: Map<string, React.RefObject<any>>;
29
17
  registerFormRef: (id: string, ref: React.RefObject<any>) => void;
@@ -32,9 +20,24 @@ export type FormRefStoreState = {
32
20
  getFormRefsByStateKey: (stateKey: string) => Map<string, React.RefObject<any>>;
33
21
  };
34
22
  export declare const formRefStore: import('zustand').UseBoundStore<import('zustand').StoreApi<FormRefStoreState>>;
23
+ export type ComponentsType = {
24
+ components?: Map<string, {
25
+ forceUpdate: () => void;
26
+ paths: Set<string>;
27
+ deps?: any[];
28
+ prevDeps?: any[];
29
+ depsFunction?: (state: any) => any[] | true;
30
+ reactiveType: ReactivityType[] | ReactivityType;
31
+ }>;
32
+ };
35
33
  export type ShadowMetadata = {
36
- id: string;
34
+ id?: string;
35
+ stateSource?: 'default' | 'server' | 'localStorage';
36
+ lastServerSync?: number;
37
+ isDirty?: boolean;
38
+ baseServerState?: any;
37
39
  arrayKeys?: string[];
40
+ fields?: Record<string, any>;
38
41
  virtualizer?: {
39
42
  itemHeight?: number;
40
43
  domRef?: HTMLElement | null;
@@ -43,113 +46,112 @@ export type ShadowMetadata = {
43
46
  status: string;
44
47
  };
45
48
  lastUpdated?: number;
49
+ value?: any;
50
+ classSignals?: Array<{
51
+ id: string;
52
+ effect: string;
53
+ lastClasses: string;
54
+ deps: any[];
55
+ }>;
56
+ signals?: Array<{
57
+ instanceId: string;
58
+ parentId: string;
59
+ position: number;
60
+ effect?: string;
61
+ }>;
62
+ mapWrappers?: Array<{
63
+ instanceId: string;
64
+ path: string[];
65
+ componentId: string;
66
+ meta?: any;
67
+ mapFn: (setter: any, index: number, arraySetter: any) => ReactNode;
68
+ containerRef: HTMLDivElement | null;
69
+ rebuildStateShape: any;
70
+ }>;
71
+ transformCaches?: Map<string, {
72
+ validIds: string[];
73
+ computedAt: number;
74
+ transforms: Array<{
75
+ type: 'filter' | 'sort';
76
+ fn: Function;
77
+ }>;
78
+ }>;
79
+ pathComponents?: Set<string>;
80
+ streams?: Map<string, {
81
+ buffer: any[];
82
+ flushTimer: NodeJS.Timeout | null;
83
+ }>;
84
+ } & ComponentsType;
85
+ export type CogsEvent = {
86
+ type: 'INSERT';
87
+ path: string;
88
+ itemKey: string;
89
+ index: number;
90
+ } | {
91
+ type: 'REMOVE';
92
+ path: string;
93
+ itemKey: string;
94
+ } | {
95
+ type: 'UPDATE';
96
+ path: string;
97
+ newValue: any;
98
+ } | {
99
+ type: 'ITEMHEIGHT';
100
+ itemKey: string;
101
+ height: number;
102
+ } | {
103
+ type: 'RELOAD';
104
+ path: string;
46
105
  };
47
106
  export type CogsGlobalState = {
48
107
  shadowStateStore: Map<string, ShadowMetadata>;
108
+ markAsDirty: (key: string, path: string[], options: {
109
+ bubble: boolean;
110
+ }) => void;
49
111
  initializeShadowState: (key: string, initialState: any) => void;
50
112
  updateShadowAtPath: (key: string, path: string[], newValue: any) => void;
51
113
  insertShadowArrayElement: (key: string, arrayPath: string[], newItem: any) => void;
52
114
  removeShadowArrayElement: (key: string, arrayPath: string[]) => void;
115
+ getShadowValue: (key: string, validArrayIds?: string[]) => any;
53
116
  getShadowMetadata: (key: string, path: string[]) => ShadowMetadata | undefined;
54
- setShadowMetadata: (key: string, path: string[], metadata: Omit<ShadowMetadata, "id">) => void;
55
- shadowStateSubscribers: Map<string, Set<() => void>>;
56
- subscribeToShadowState: (key: string, callback: () => void) => () => void;
57
- selectedIndicesMap: Map<string, Map<string, number>>;
58
- getSelectedIndex: (stateKey: string, parentPath: string) => number | undefined;
59
- setSelectedIndex: (stateKey: string, parentPath: string, index: number | undefined) => void;
60
- clearSelectedIndex: ({ stateKey, path, }: {
61
- stateKey: string;
62
- path: string[];
117
+ setShadowMetadata: (key: string, path: string[], metadata: Omit<ShadowMetadata, 'id'>) => void;
118
+ setTransformCache: (key: string, path: string[], cacheKey: string, cacheData: any) => void;
119
+ pathSubscribers: Map<string, Set<(newValue: any) => void>>;
120
+ subscribeToPath: (path: string, callback: (newValue: any) => void) => () => void;
121
+ notifyPathSubscribers: (updatedPath: string, newValue: any) => void;
122
+ selectedIndicesMap: Map<string, string>;
123
+ getSelectedIndex: (stateKey: string, validArrayIds?: string[]) => number;
124
+ setSelectedIndex: (key: string, itemKey: string) => void;
125
+ clearSelectedIndex: ({ arrayKey }: {
126
+ arrayKey: string;
63
127
  }) => void;
64
128
  clearSelectedIndexesForState: (stateKey: string) => void;
65
- updaterState: {
66
- [key: string]: any;
67
- };
68
129
  initialStateOptions: {
69
130
  [key: string]: OptionsType;
70
131
  };
71
- cogsStateStore: {
72
- [key: string]: StateValue;
73
- };
74
- isLoadingGlobal: {
75
- [key: string]: boolean;
76
- };
77
132
  initialStateGlobal: {
78
133
  [key: string]: StateValue;
79
134
  };
80
- iniitialCreatedState: {
81
- [key: string]: StateValue;
82
- };
83
- serverState: {
84
- [key: string]: StateValue;
85
- };
86
- getUpdaterState: (key: string) => StateUpdater<StateValue>;
87
- setUpdaterState: (key: string, newUpdater: any) => void;
88
- getKeyState: <StateKey extends StateKeys>(key: StateKey) => StateValue;
89
- getNestedState: <StateKey extends StateKeys>(key: StateKey, path: string[]) => StateValue;
90
- setState: <StateKey extends StateKeys>(key: StateKey, value: StateUpdater<StateValue>) => void;
91
- setInitialStates: (initialState: StateValue) => void;
92
- setCreatedState: (initialState: StateValue) => void;
93
135
  updateInitialStateGlobal: (key: string, newState: StateValue) => void;
94
- updateInitialCreatedState: (key: string, newState: StateValue) => void;
95
- setIsLoadingGlobal: (key: string, value: boolean) => void;
96
- setServerState: <StateKey extends StateKeys>(key: StateKey, value: StateValue) => void;
97
136
  getInitialOptions: (key: string) => OptionsType | undefined;
98
137
  setInitialStateOptions: (key: string, value: OptionsType) => void;
99
138
  validationErrors: Map<string, string[]>;
100
139
  addValidationError: (path: string, message: string) => void;
101
140
  getValidationErrors: (path: string) => string[];
102
141
  removeValidationError: (path: string) => void;
103
- serverSyncActions: {
104
- [key: string]: SyncActionsType<any>;
105
- };
106
- serverSyncLog: {
107
- [key: string]: SyncLogType[];
108
- };
142
+ serverStateUpdates: Map<string, {
143
+ data: any;
144
+ status: 'loading' | 'success' | 'error';
145
+ timestamp: number;
146
+ }>;
147
+ setServerStateUpdate: (key: string, serverState: any) => void;
109
148
  stateLog: {
110
149
  [key: string]: UpdateTypeDetail[];
111
150
  };
112
151
  syncInfoStore: Map<string, SyncInfo>;
113
- serverSideOrNot: {
114
- [key: string]: boolean;
115
- };
116
- setServerSyncLog: (key: string, newValue: SyncLogType) => void;
117
- setServerSideOrNot: (key: string, value: boolean) => void;
118
- getServerSideOrNot: (key: string) => boolean | undefined;
119
- getThisLocalUpdate: (key: string) => UpdateTypeDetail[] | undefined;
120
- setServerSyncActions: (key: string, value: SyncActionsType<any>) => void;
121
152
  setStateLog: (key: string, updater: (prevUpdates: UpdateTypeDetail[]) => UpdateTypeDetail[]) => void;
122
153
  setSyncInfo: (key: string, syncInfo: SyncInfo) => void;
123
154
  getSyncInfo: (key: string) => SyncInfo | null;
124
- signalDomElements: Map<string, Set<{
125
- instanceId: string;
126
- parentId: string;
127
- position: number;
128
- effect?: string;
129
- map?: string;
130
- }>>;
131
- addSignalElement: (signalId: string, elementInfo: {
132
- instanceId: string;
133
- parentId: string;
134
- position: number;
135
- effect?: string;
136
- map?: string;
137
- }) => void;
138
- removeSignalElement: (signalId: string, instanceId: string) => void;
139
- stateComponents: Map<string, ComponentsType>;
140
- reRenderTriggerPrevValue: Record<string, any>;
141
- reactiveDeps: Record<string, {
142
- deps: any[];
143
- updaters: Set<() => void>;
144
- depsFunction: ((state: any) => any[] | true) | null;
145
- }>;
146
- setReactiveDeps: (key: string, record: {
147
- deps: any[];
148
- updaters: Set<() => void>;
149
- depsFunction: ((state: any) => any[] | true) | null;
150
- }) => void;
151
- deleteReactiveDeps: (key: string) => void;
152
- subscribe: (listener: () => void) => () => void;
153
155
  };
154
156
  export declare const getGlobalStore: import('zustand').UseBoundStore<import('zustand').StoreApi<CogsGlobalState>>;
155
157
  export {};