cogsbox-state 0.5.482 → 0.5.484
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 +4 -3
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.js +360 -363
- package/dist/CogsState.js.map +1 -1
- package/dist/CogsStateClient.d.ts +2 -2
- package/dist/CogsStateClient.d.ts.map +1 -1
- package/dist/CogsStateClient.js.map +1 -1
- package/dist/Components.d.ts +3 -3
- package/dist/Components.d.ts.map +1 -1
- package/dist/Components.js +202 -201
- package/dist/Components.js.map +1 -1
- package/dist/PluginRunner.d.ts +2 -2
- package/dist/PluginRunner.d.ts.map +1 -1
- package/dist/PluginRunner.js +86 -85
- package/dist/PluginRunner.js.map +1 -1
- package/dist/pluginStore.d.ts +1 -0
- package/dist/pluginStore.d.ts.map +1 -1
- package/dist/pluginStore.js +22 -18
- package/dist/pluginStore.js.map +1 -1
- package/dist/plugins.d.ts +4 -4
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +124 -118
- package/dist/store.js.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +68 -74
- package/src/CogsStateClient.tsx +2 -2
- package/src/Components.tsx +17 -9
- package/src/PluginRunner.tsx +33 -35
- package/src/pluginStore.ts +7 -1
- package/src/plugins.ts +5 -6
- package/src/store.ts +24 -7
package/src/CogsState.tsx
CHANGED
|
@@ -721,33 +721,19 @@ function setOptions<StateKey, Opt>({
|
|
|
721
721
|
if (needToAdd) {
|
|
722
722
|
setInitialStateOptions(stateKey as string, mergedOptions);
|
|
723
723
|
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
initialOptions?.validation?.
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (!hadSchema && (hasNewSchemaV4 || hasNewSchemaV3)) {
|
|
736
|
-
if (hasNewSchemaV4) {
|
|
737
|
-
updateShadowTypeInfo(
|
|
738
|
-
stateKey as string,
|
|
739
|
-
mergedOptions.validation.zodSchemaV4,
|
|
740
|
-
'zod4'
|
|
741
|
-
);
|
|
742
|
-
} else if (hasNewSchemaV3) {
|
|
743
|
-
updateShadowTypeInfo(
|
|
744
|
-
stateKey as string,
|
|
745
|
-
mergedOptions.validation.zodSchemaV3,
|
|
746
|
-
'zod3'
|
|
747
|
-
);
|
|
724
|
+
const schemaV4 = mergedOptions.validation?.zodSchemaV4;
|
|
725
|
+
const schemaV3 = mergedOptions.validation?.zodSchemaV3;
|
|
726
|
+
const schemaChanged =
|
|
727
|
+
schemaV4 !== initialOptions?.validation?.zodSchemaV4 ||
|
|
728
|
+
schemaV3 !== initialOptions?.validation?.zodSchemaV3;
|
|
729
|
+
|
|
730
|
+
if (schemaChanged && (schemaV4 || schemaV3)) {
|
|
731
|
+
if (schemaV4) {
|
|
732
|
+
updateShadowTypeInfo(stateKey as string, schemaV4, 'zod4');
|
|
733
|
+
} else if (schemaV3) {
|
|
734
|
+
updateShadowTypeInfo(stateKey as string, schemaV3, 'zod3');
|
|
748
735
|
}
|
|
749
736
|
|
|
750
|
-
// Notify components to re-render with updated validation
|
|
751
737
|
notifyComponents(stateKey as string);
|
|
752
738
|
}
|
|
753
739
|
}
|
|
@@ -828,31 +814,42 @@ type KeyedKeys<P> = {
|
|
|
828
814
|
: never;
|
|
829
815
|
}[keyof P];
|
|
830
816
|
|
|
817
|
+
type PluginOptionEntry<
|
|
818
|
+
P,
|
|
819
|
+
StateKey extends PropertyKey,
|
|
820
|
+
> = P extends undefined
|
|
821
|
+
? never
|
|
822
|
+
: P extends Record<string, any>
|
|
823
|
+
? Prettify<
|
|
824
|
+
Partial<Pick<P, Exclude<keyof P, KeyedKeys<P>>>> & {
|
|
825
|
+
[K in KeyedKeys<P> as StateKey extends keyof NonNullable<
|
|
826
|
+
P[K]
|
|
827
|
+
>['map']
|
|
828
|
+
? NonNullable<P[K]>['map'][StateKey] extends undefined
|
|
829
|
+
? never
|
|
830
|
+
: keyof NonNullable<P[K]>['map'][StateKey] extends never
|
|
831
|
+
? never
|
|
832
|
+
: K
|
|
833
|
+
: never]: CleanIntersection<
|
|
834
|
+
StateKey extends keyof NonNullable<P[K]>['map']
|
|
835
|
+
? NonNullable<P[K]>['map'][StateKey]
|
|
836
|
+
: never
|
|
837
|
+
>;
|
|
838
|
+
}
|
|
839
|
+
>
|
|
840
|
+
: P extends object
|
|
841
|
+
? Partial<P> extends P
|
|
842
|
+
? Partial<P>
|
|
843
|
+
: P
|
|
844
|
+
: P;
|
|
845
|
+
|
|
831
846
|
type PluginOptionsForState<
|
|
832
847
|
PluginOptions,
|
|
833
848
|
StateKey extends PropertyKey,
|
|
834
849
|
> = {
|
|
835
|
-
[PName in keyof PluginOptions
|
|
836
|
-
?
|
|
837
|
-
|
|
838
|
-
Partial<Pick<P, Exclude<keyof P, KeyedKeys<P>>>> & {
|
|
839
|
-
[K in KeyedKeys<P> as StateKey extends keyof NonNullable<
|
|
840
|
-
P[K]
|
|
841
|
-
>['map']
|
|
842
|
-
? NonNullable<P[K]>['map'][StateKey] extends undefined
|
|
843
|
-
? never
|
|
844
|
-
: keyof NonNullable<P[K]>['map'][StateKey] extends never
|
|
845
|
-
? never
|
|
846
|
-
: K
|
|
847
|
-
: never]: CleanIntersection<
|
|
848
|
-
StateKey extends keyof NonNullable<P[K]>['map']
|
|
849
|
-
? NonNullable<P[K]>['map'][StateKey]
|
|
850
|
-
: never
|
|
851
|
-
>;
|
|
852
|
-
}
|
|
853
|
-
>
|
|
854
|
-
: P
|
|
855
|
-
: never;
|
|
850
|
+
[PName in keyof PluginOptions as PluginOptions[PName] extends undefined
|
|
851
|
+
? never
|
|
852
|
+
: PName]?: PluginOptionEntry<PluginOptions[PName], StateKey>;
|
|
856
853
|
};
|
|
857
854
|
|
|
858
855
|
type UseCogsStateOptions<
|
|
@@ -987,29 +984,8 @@ export const createCogsState = <
|
|
|
987
984
|
const useCogsState = <StateKey extends StateKeys>(
|
|
988
985
|
stateKey: StateKey,
|
|
989
986
|
options?: Prettify<
|
|
990
|
-
OptionsType<StateSlice<StateKey>, never> &
|
|
991
|
-
|
|
992
|
-
? P extends Record<string, any>
|
|
993
|
-
? Prettify<
|
|
994
|
-
Partial<Pick<P, Exclude<keyof P, KeyedKeys<P>>>> & {
|
|
995
|
-
[K in KeyedKeys<P> as StateKey extends keyof NonNullable<
|
|
996
|
-
P[K]
|
|
997
|
-
>['map']
|
|
998
|
-
? NonNullable<P[K]>['map'][StateKey] extends undefined
|
|
999
|
-
? never
|
|
1000
|
-
: keyof NonNullable<P[K]>['map'][StateKey] extends never
|
|
1001
|
-
? never
|
|
1002
|
-
: K
|
|
1003
|
-
: never]: CleanIntersection<
|
|
1004
|
-
StateKey extends keyof NonNullable<P[K]>['map']
|
|
1005
|
-
? NonNullable<P[K]>['map'][StateKey]
|
|
1006
|
-
: never
|
|
1007
|
-
>;
|
|
1008
|
-
}
|
|
1009
|
-
>
|
|
1010
|
-
: P
|
|
1011
|
-
: never;
|
|
1012
|
-
}
|
|
987
|
+
OptionsType<StateSlice<StateKey>, never> &
|
|
988
|
+
PluginOptionsForState<PluginOptions, StateKey>
|
|
1013
989
|
>
|
|
1014
990
|
): StateObject<StateSlice<StateKey>> => {
|
|
1015
991
|
const [componentId] = useState(options?.componentId ?? uuidv4());
|
|
@@ -1040,23 +1016,33 @@ export const createCogsState = <
|
|
|
1040
1016
|
serverState: options?.serverState,
|
|
1041
1017
|
});
|
|
1042
1018
|
|
|
1043
|
-
|
|
1019
|
+
useLayoutEffect(() => {
|
|
1044
1020
|
if (options) {
|
|
1045
1021
|
pluginStore
|
|
1046
1022
|
.getState()
|
|
1047
1023
|
.setPluginOptionsForState(stateKey as string, options);
|
|
1048
1024
|
}
|
|
1049
1025
|
}, [stateKey, options]);
|
|
1050
|
-
|
|
1026
|
+
|
|
1027
|
+
useLayoutEffect(() => {
|
|
1051
1028
|
pluginStore
|
|
1052
1029
|
.getState()
|
|
1053
|
-
.
|
|
1030
|
+
.registerStateHandler(stateKey as string, updater as any);
|
|
1054
1031
|
|
|
1055
1032
|
return () => {
|
|
1056
|
-
pluginStore.getState().
|
|
1033
|
+
pluginStore.getState().unregisterStateHandler(stateKey as string);
|
|
1057
1034
|
};
|
|
1058
1035
|
}, [stateKey, updater]);
|
|
1059
1036
|
|
|
1037
|
+
useLayoutEffect(() => {
|
|
1038
|
+
const validation = getInitialOptions(stateKey as string)?.validation;
|
|
1039
|
+
if (validation?.zodSchemaV4) {
|
|
1040
|
+
updateShadowTypeInfo(stateKey as string, validation.zodSchemaV4, 'zod4');
|
|
1041
|
+
} else if (validation?.zodSchemaV3) {
|
|
1042
|
+
updateShadowTypeInfo(stateKey as string, validation.zodSchemaV3, 'zod3');
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
|
|
1060
1046
|
return updater as StateObject<StateSlice<StateKey>>;
|
|
1061
1047
|
};
|
|
1062
1048
|
|
|
@@ -1737,7 +1723,7 @@ export function useCogsStateFn<
|
|
|
1737
1723
|
defaultState?: TStateObject;
|
|
1738
1724
|
syncOptions?: SyncOptionsType<any>;
|
|
1739
1725
|
} & OptionsType<TStateObject> = {}
|
|
1740
|
-
) {
|
|
1726
|
+
): StateObject<TStateObject, TPlugins> {
|
|
1741
1727
|
const [reactiveForce, forceUpdate] = useState({}); //this is the key to reactivity
|
|
1742
1728
|
const { sessionId } = useCogsConfig();
|
|
1743
1729
|
let noStateKey = stateKey ? false : true;
|
|
@@ -1937,6 +1923,14 @@ export function useCogsStateFn<
|
|
|
1937
1923
|
|
|
1938
1924
|
const { value: resolvedState, source, timestamp } = resolveInitialState();
|
|
1939
1925
|
initializeShadowState(thisKey, resolvedState);
|
|
1926
|
+
|
|
1927
|
+
const validation = getInitialOptions(thisKey as string)?.validation;
|
|
1928
|
+
if (validation?.zodSchemaV4) {
|
|
1929
|
+
updateShadowTypeInfo(thisKey as string, validation.zodSchemaV4, 'zod4');
|
|
1930
|
+
} else if (validation?.zodSchemaV3) {
|
|
1931
|
+
updateShadowTypeInfo(thisKey as string, validation.zodSchemaV3, 'zod3');
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1940
1934
|
setShadowMetadata(thisKey, [], {
|
|
1941
1935
|
stateSource: source,
|
|
1942
1936
|
lastServerSync: source === 'server' ? timestamp : undefined,
|
package/src/CogsStateClient.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import React, { createContext, useContext } from "react";
|
|
3
|
+
import React, { createContext, useContext, type ReactNode } from "react";
|
|
4
4
|
type ConfigType = { sessionId?: string };
|
|
5
5
|
export const config: ConfigType = {
|
|
6
6
|
sessionId: undefined,
|
|
@@ -14,7 +14,7 @@ export function CogsStateClient({
|
|
|
14
14
|
children,
|
|
15
15
|
sessionId,
|
|
16
16
|
}: {
|
|
17
|
-
children:
|
|
17
|
+
children: ReactNode;
|
|
18
18
|
sessionId?: string;
|
|
19
19
|
}) {
|
|
20
20
|
return (
|
package/src/Components.tsx
CHANGED
|
@@ -20,6 +20,7 @@ import React, {
|
|
|
20
20
|
useRef,
|
|
21
21
|
useState,
|
|
22
22
|
useMemo,
|
|
23
|
+
type ReactNode,
|
|
23
24
|
} from 'react';
|
|
24
25
|
import { getGlobalStore, ValidationError, ValidationSeverity } from './store';
|
|
25
26
|
import { useInView } from 'react-intersection-observer';
|
|
@@ -46,7 +47,7 @@ export type ValidationWrapperProps = {
|
|
|
46
47
|
formOpts?: FormOptsType;
|
|
47
48
|
path: string[];
|
|
48
49
|
stateKey: string;
|
|
49
|
-
children:
|
|
50
|
+
children: ReactNode;
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export function ValidationWrapper({
|
|
@@ -241,7 +242,7 @@ export function FormElementWrapper({
|
|
|
241
242
|
componentId: string;
|
|
242
243
|
meta?: any;
|
|
243
244
|
}) => any;
|
|
244
|
-
renderFn: (params: FormElementParams<any>) =>
|
|
245
|
+
renderFn: (params: FormElementParams<any>) => ReactNode;
|
|
245
246
|
formOpts?: FormOptsType;
|
|
246
247
|
setState: any;
|
|
247
248
|
}) {
|
|
@@ -335,21 +336,28 @@ export function FormElementWrapper({
|
|
|
335
336
|
|
|
336
337
|
const debouncedUpdate = useCallback(
|
|
337
338
|
(newValue: any) => {
|
|
339
|
+
const liveTypeInfo =
|
|
340
|
+
getGlobalStore.getState().getShadowNode(stateKey, path)?._meta
|
|
341
|
+
?.typeInfo ?? typeInfo;
|
|
342
|
+
|
|
338
343
|
// Type conversion logic (keep existing)
|
|
339
|
-
if (
|
|
340
|
-
if (
|
|
344
|
+
if (liveTypeInfo) {
|
|
345
|
+
if (liveTypeInfo.type === 'number' && typeof newValue === 'string') {
|
|
341
346
|
newValue =
|
|
342
347
|
newValue === ''
|
|
343
|
-
?
|
|
348
|
+
? liveTypeInfo.nullable
|
|
344
349
|
? null
|
|
345
|
-
: (
|
|
350
|
+
: (liveTypeInfo.default ?? 0)
|
|
346
351
|
: Number(newValue);
|
|
347
352
|
} else if (
|
|
348
|
-
|
|
353
|
+
liveTypeInfo.type === 'boolean' &&
|
|
349
354
|
typeof newValue === 'string'
|
|
350
355
|
) {
|
|
351
356
|
newValue = newValue === 'true' || newValue === '1';
|
|
352
|
-
} else if (
|
|
357
|
+
} else if (
|
|
358
|
+
liveTypeInfo.type === 'date' &&
|
|
359
|
+
typeof newValue === 'string'
|
|
360
|
+
) {
|
|
353
361
|
newValue = new Date(newValue);
|
|
354
362
|
}
|
|
355
363
|
} else {
|
|
@@ -626,7 +634,7 @@ export function IsolatedComponentWrapper({
|
|
|
626
634
|
}
|
|
627
635
|
// 1. Define the MINIMAL props needed.
|
|
628
636
|
type PluginWrapperProps = {
|
|
629
|
-
children:
|
|
637
|
+
children: ReactNode;
|
|
630
638
|
stateKey: string;
|
|
631
639
|
path: string[];
|
|
632
640
|
pluginName: string;
|
package/src/PluginRunner.tsx
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useEffect,
|
|
3
|
+
useLayoutEffect,
|
|
4
|
+
useMemo,
|
|
5
|
+
useState,
|
|
6
|
+
useRef,
|
|
7
|
+
useSyncExternalStore,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from 'react';
|
|
2
10
|
import { ClientActivityEvent, pluginStore } from './pluginStore';
|
|
3
11
|
import { isDeepEqual } from './utility';
|
|
4
12
|
import {
|
|
@@ -68,7 +76,7 @@ const PluginInstance = React.memo(
|
|
|
68
76
|
const lastProcessedOptionsRef = useRef<any>();
|
|
69
77
|
const [isInitialTransform, setIsInitialTransform] = useState(true);
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
useLayoutEffect(() => {
|
|
72
80
|
if (plugin.transformState) {
|
|
73
81
|
if (!isDeepEqual(options, lastProcessedOptionsRef.current)) {
|
|
74
82
|
plugin.transformState({
|
|
@@ -168,52 +176,42 @@ const PluginInstance = React.memo(
|
|
|
168
176
|
* The main orchestrator component. It reads from the central pluginStore
|
|
169
177
|
* and renders a `PluginInstance` controller for each active plugin.
|
|
170
178
|
*/
|
|
171
|
-
export function PluginRunner({ children }: { children:
|
|
172
|
-
// A simple way to force a re-render when the store changes.
|
|
173
|
-
const [, forceUpdate] = useReducer((c) => c + 1, 0);
|
|
174
|
-
|
|
175
|
-
// Subscribe to the store. When plugins or their options are added/removed,
|
|
176
|
-
// this component will re-render to update the list of PluginInstances.
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
const unsubscribe = pluginStore.subscribe(forceUpdate);
|
|
179
|
-
|
|
180
|
-
return unsubscribe;
|
|
181
|
-
}, []);
|
|
182
|
-
|
|
179
|
+
export function PluginRunner({ children }: { children: ReactNode }) {
|
|
183
180
|
const { pluginOptions, stateHandlers, registeredPlugins } =
|
|
184
|
-
|
|
181
|
+
useSyncExternalStore(
|
|
182
|
+
pluginStore.subscribe,
|
|
183
|
+
() => pluginStore.getState(),
|
|
184
|
+
() => pluginStore.getState()
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const pluginNeedsRunner = (
|
|
188
|
+
plugin: CogsPlugin<any, any, any, any, any, any, any>
|
|
189
|
+
) =>
|
|
190
|
+
!!(
|
|
191
|
+
plugin.useHook ||
|
|
192
|
+
plugin.transformState ||
|
|
193
|
+
plugin.onUpdate ||
|
|
194
|
+
plugin.onFormUpdate
|
|
195
|
+
);
|
|
185
196
|
|
|
186
197
|
return (
|
|
187
198
|
<>
|
|
188
|
-
{
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
*/}
|
|
193
|
-
{Array.from(pluginOptions.entries()).map(([stateKey, pluginMap]) => {
|
|
194
|
-
const stateHandler = stateHandlers.get(stateKey);
|
|
195
|
-
if (!stateHandler) {
|
|
196
|
-
return null; // Don't render a runner if the state handler isn't ready.
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return Array.from(pluginMap.entries()).map(([pluginName, options]) => {
|
|
200
|
-
const plugin = registeredPlugins.find((p) => p.name === pluginName);
|
|
201
|
-
if (!plugin) {
|
|
202
|
-
return null; // Don't render if the plugin is not in the registered list.
|
|
203
|
-
}
|
|
199
|
+
{Array.from(stateHandlers.entries()).flatMap(([stateKey, stateHandler]) =>
|
|
200
|
+
registeredPlugins.filter(pluginNeedsRunner).map((plugin) => {
|
|
201
|
+
const options =
|
|
202
|
+
pluginOptions.get(stateKey)?.get(plugin.name) ?? {};
|
|
204
203
|
|
|
205
|
-
// Render a dedicated, memoized controller for this specific plugin configuration.
|
|
206
204
|
return (
|
|
207
205
|
<PluginInstance
|
|
208
|
-
key={`${stateKey}:${
|
|
206
|
+
key={`${stateKey}:${plugin.name}`}
|
|
209
207
|
stateKey={stateKey}
|
|
210
208
|
plugin={plugin}
|
|
211
209
|
options={options}
|
|
212
210
|
stateHandler={stateHandler}
|
|
213
211
|
/>
|
|
214
212
|
);
|
|
215
|
-
})
|
|
216
|
-
|
|
213
|
+
})
|
|
214
|
+
)}
|
|
217
215
|
|
|
218
216
|
{children}
|
|
219
217
|
</>
|
package/src/pluginStore.ts
CHANGED
|
@@ -39,6 +39,7 @@ export type ClientActivityEvent = {
|
|
|
39
39
|
type PluginRegistryStore = {
|
|
40
40
|
stateHandlers: Map<string, StateObject<any>>; // stateKey -> handler
|
|
41
41
|
registerStateHandler: (stateKey: string, handler: StateObject<any>) => void;
|
|
42
|
+
unregisterStateHandler: (stateKey: string) => void;
|
|
42
43
|
registeredPlugins: readonly CogsPlugin<any, any, any, any, any>[];
|
|
43
44
|
setRegisteredPlugins: (
|
|
44
45
|
plugins: readonly CogsPlugin<any, any, any, any, any>[]
|
|
@@ -78,7 +79,12 @@ export const pluginStore = create<PluginRegistryStore>((set, get) => ({
|
|
|
78
79
|
set((state) => {
|
|
79
80
|
const newMap = new Map(state.stateHandlers);
|
|
80
81
|
newMap.set(stateKey, handler);
|
|
81
|
-
|
|
82
|
+
return { stateHandlers: newMap };
|
|
83
|
+
}),
|
|
84
|
+
unregisterStateHandler: (stateKey) =>
|
|
85
|
+
set((state) => {
|
|
86
|
+
const newMap = new Map(state.stateHandlers);
|
|
87
|
+
newMap.delete(stateKey);
|
|
82
88
|
return { stateHandlers: newMap };
|
|
83
89
|
}),
|
|
84
90
|
registeredPlugins: [],
|
package/src/plugins.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import type
|
|
2
|
+
import type { ReactNode, RefObject } from 'react';
|
|
3
3
|
import { StateObject, UpdateTypeDetail } from './CogsState';
|
|
4
4
|
import {
|
|
5
5
|
getGlobalStore,
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
setAllFieldsDisabled,
|
|
8
8
|
} from './store';
|
|
9
9
|
import { ClientActivityEvent } from './pluginStore';
|
|
10
|
-
import { RefObject } from 'react';
|
|
11
10
|
|
|
12
11
|
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
13
12
|
|
|
@@ -228,7 +227,7 @@ export type FormWrapperParams<
|
|
|
228
227
|
TFieldMetaData,
|
|
229
228
|
TStateSlice = any,
|
|
230
229
|
> = ScopedMetadataMethods<TFieldMetaData> & {
|
|
231
|
-
element:
|
|
230
|
+
element: ReactNode;
|
|
232
231
|
path: string[];
|
|
233
232
|
stateKey: string;
|
|
234
233
|
options: TOptions;
|
|
@@ -307,7 +306,7 @@ export type CogsPlugin<
|
|
|
307
306
|
TFieldMetaData,
|
|
308
307
|
any
|
|
309
308
|
>
|
|
310
|
-
) =>
|
|
309
|
+
) => ReactNode;
|
|
311
310
|
|
|
312
311
|
chainMethods?: TChainMethods;
|
|
313
312
|
};
|
|
@@ -602,7 +601,7 @@ export type PluginFormWrapperFn<
|
|
|
602
601
|
TFieldMetaData,
|
|
603
602
|
any
|
|
604
603
|
>
|
|
605
|
-
) =>
|
|
604
|
+
) => ReactNode;
|
|
606
605
|
|
|
607
606
|
export type CogsPluginBuilder<
|
|
608
607
|
TName extends string,
|
|
@@ -774,7 +773,7 @@ export type CogsPluginBuilder<
|
|
|
774
773
|
true,
|
|
775
774
|
TNewState
|
|
776
775
|
>;
|
|
777
|
-
});
|
|
776
|
+
});
|
|
778
777
|
|
|
779
778
|
export type CreatePluginStart<
|
|
780
779
|
TName extends string,
|
package/src/store.ts
CHANGED
|
@@ -316,16 +316,25 @@ function getTypeFromZodSchema(
|
|
|
316
316
|
|
|
317
317
|
const typeIdentifier = def.typeName || def.type || current._type;
|
|
318
318
|
|
|
319
|
-
// --- START: THE CRITICAL FIX FOR ZodUnion ---
|
|
320
319
|
if (typeIdentifier === 'ZodUnion' || typeIdentifier === 'union') {
|
|
321
320
|
if (def.options && def.options.length > 0) {
|
|
322
|
-
|
|
323
|
-
|
|
321
|
+
const preferredOption = def.options.find((option: any) => {
|
|
322
|
+
const optionDef = option?.def || option?._def;
|
|
323
|
+
const optionType =
|
|
324
|
+
optionDef?.typeName || optionDef?.type || option?._type;
|
|
325
|
+
return (
|
|
326
|
+
optionType !== 'ZodNull' &&
|
|
327
|
+
optionType !== 'null' &&
|
|
328
|
+
optionType !== 'ZodUndefined' &&
|
|
329
|
+
optionType !== 'undefined'
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
current = preferredOption ?? def.options[0];
|
|
333
|
+
continue;
|
|
324
334
|
} else {
|
|
325
|
-
break;
|
|
335
|
+
break;
|
|
326
336
|
}
|
|
327
337
|
}
|
|
328
|
-
// --- END: THE CRITICAL FIX ---
|
|
329
338
|
|
|
330
339
|
if (typeIdentifier === 'ZodOptional' || typeIdentifier === 'optional') {
|
|
331
340
|
isOptional = true;
|
|
@@ -684,9 +693,10 @@ function getSchemaAtPath(schema: any, path: string[]): any {
|
|
|
684
693
|
const typeIdentifier = def?.typeName || def?.type || containerSchema._type;
|
|
685
694
|
|
|
686
695
|
if (typeIdentifier === 'ZodObject' || typeIdentifier === 'object') {
|
|
687
|
-
|
|
696
|
+
const rawShape =
|
|
697
|
+
def?.shape ?? containerSchema.shape ?? containerSchema._shape;
|
|
688
698
|
const shape =
|
|
689
|
-
|
|
699
|
+
typeof rawShape === 'function' ? rawShape() : rawShape;
|
|
690
700
|
currentSchema = shape?.[segment];
|
|
691
701
|
} else if (typeIdentifier === 'ZodArray' || typeIdentifier === 'array') {
|
|
692
702
|
// For arrays, the next schema is always the element's schema.
|
|
@@ -1006,6 +1016,13 @@ export const getGlobalStore = create<CogsGlobalState>((set, get) => ({
|
|
|
1006
1016
|
|
|
1007
1017
|
const storageKey = Array.isArray(initialState) ? `[${key}` : key;
|
|
1008
1018
|
shadowStateStore.set(storageKey, newRoot);
|
|
1019
|
+
|
|
1020
|
+
const latestOptions = get().getInitialOptions(key);
|
|
1021
|
+
if (latestOptions?.validation?.zodSchemaV4) {
|
|
1022
|
+
updateShadowTypeInfo(key, latestOptions.validation.zodSchemaV4, 'zod4');
|
|
1023
|
+
} else if (latestOptions?.validation?.zodSchemaV3) {
|
|
1024
|
+
updateShadowTypeInfo(key, latestOptions.validation.zodSchemaV3, 'zod3');
|
|
1025
|
+
}
|
|
1009
1026
|
},
|
|
1010
1027
|
getShadowNode: (key: string, path: string[]): ShadowNode | undefined => {
|
|
1011
1028
|
let current: any =
|