cogsbox-state 0.5.483 → 0.5.485
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 +1 -0
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.js +599 -579
- package/dist/CogsState.js.map +1 -1
- package/dist/Components.d.ts.map +1 -1
- package/dist/Components.js +213 -213
- package/dist/Components.js.map +1 -1
- package/dist/PluginRunner.d.ts.map +1 -1
- package/dist/PluginRunner.js +44 -44
- package/dist/PluginRunner.js.map +1 -1
- package/dist/plugins.d.ts +2 -0
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +92 -91
- 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 +82 -48
- package/src/Components.tsx +32 -27
- package/src/PluginRunner.tsx +2 -1
- package/src/plugins.ts +3 -0
- package/src/store.ts +24 -7
package/src/Components.tsx
CHANGED
|
@@ -336,21 +336,28 @@ export function FormElementWrapper({
|
|
|
336
336
|
|
|
337
337
|
const debouncedUpdate = useCallback(
|
|
338
338
|
(newValue: any) => {
|
|
339
|
+
const liveTypeInfo =
|
|
340
|
+
getGlobalStore.getState().getShadowNode(stateKey, path)?._meta
|
|
341
|
+
?.typeInfo ?? typeInfo;
|
|
342
|
+
|
|
339
343
|
// Type conversion logic (keep existing)
|
|
340
|
-
if (
|
|
341
|
-
if (
|
|
344
|
+
if (liveTypeInfo) {
|
|
345
|
+
if (liveTypeInfo.type === 'number' && typeof newValue === 'string') {
|
|
342
346
|
newValue =
|
|
343
347
|
newValue === ''
|
|
344
|
-
?
|
|
348
|
+
? liveTypeInfo.nullable
|
|
345
349
|
? null
|
|
346
|
-
: (
|
|
350
|
+
: (liveTypeInfo.default ?? 0)
|
|
347
351
|
: Number(newValue);
|
|
348
352
|
} else if (
|
|
349
|
-
|
|
353
|
+
liveTypeInfo.type === 'boolean' &&
|
|
350
354
|
typeof newValue === 'string'
|
|
351
355
|
) {
|
|
352
356
|
newValue = newValue === 'true' || newValue === '1';
|
|
353
|
-
} else if (
|
|
357
|
+
} else if (
|
|
358
|
+
liveTypeInfo.type === 'date' &&
|
|
359
|
+
typeof newValue === 'string'
|
|
360
|
+
) {
|
|
354
361
|
newValue = new Date(newValue);
|
|
355
362
|
}
|
|
356
363
|
} else {
|
|
@@ -476,10 +483,7 @@ export function FormElementWrapper({
|
|
|
476
483
|
clearTimeout(debounceTimeoutRef.current);
|
|
477
484
|
debounceTimeoutRef.current = null;
|
|
478
485
|
isCurrentlyDebouncing.current = false;
|
|
479
|
-
setState(localValue, path, {
|
|
480
|
-
updateType: 'update',
|
|
481
|
-
validationTrigger: 'onBlur',
|
|
482
|
-
});
|
|
486
|
+
setState(localValue, path, { updateType: 'update' });
|
|
483
487
|
}
|
|
484
488
|
|
|
485
489
|
// Clear element's current activity
|
|
@@ -493,10 +497,26 @@ export function FormElementWrapper({
|
|
|
493
497
|
meta?.clientActivityState?.elements?.get(componentId)?.currentActivity
|
|
494
498
|
?.startTime;
|
|
495
499
|
|
|
496
|
-
|
|
500
|
+
const validationOptions = getInitialOptions(stateKey)?.validation;
|
|
501
|
+
if (validationOptions?.onBlur) {
|
|
502
|
+
runValidation(
|
|
503
|
+
{
|
|
504
|
+
stateKey,
|
|
505
|
+
path,
|
|
506
|
+
newValue: localValue,
|
|
507
|
+
updateType: 'update',
|
|
508
|
+
timeStamp: Date.now(),
|
|
509
|
+
status: 'new',
|
|
510
|
+
oldValue: globalStateValue,
|
|
511
|
+
},
|
|
512
|
+
'onBlur'
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Refine / plugin validation runs after field validation so it wins on conflict
|
|
497
517
|
notifyFormUpdate({
|
|
498
518
|
stateKey,
|
|
499
|
-
activityType: 'blur',
|
|
519
|
+
activityType: 'blur',
|
|
500
520
|
path,
|
|
501
521
|
timestamp: Date.now(),
|
|
502
522
|
duration: focusStartTime ? Date.now() - focusStartTime : undefined,
|
|
@@ -504,21 +524,6 @@ export function FormElementWrapper({
|
|
|
504
524
|
duration: focusStartTime ? Date.now() - focusStartTime : 0,
|
|
505
525
|
},
|
|
506
526
|
});
|
|
507
|
-
|
|
508
|
-
// Run validation if configured
|
|
509
|
-
const validationOptions = getInitialOptions(stateKey)?.validation;
|
|
510
|
-
if (validationOptions?.onBlur) {
|
|
511
|
-
const virtualOperation: UpdateTypeDetail = {
|
|
512
|
-
stateKey,
|
|
513
|
-
path,
|
|
514
|
-
newValue: localValue,
|
|
515
|
-
updateType: 'update',
|
|
516
|
-
timeStamp: Date.now(),
|
|
517
|
-
status: 'new',
|
|
518
|
-
oldValue: globalStateValue,
|
|
519
|
-
};
|
|
520
|
-
runValidation(virtualOperation, 'onBlur');
|
|
521
|
-
}
|
|
522
527
|
}, [localValue, setState, path, stateKey, componentId, globalStateValue]);
|
|
523
528
|
|
|
524
529
|
const baseState = rebuildStateShape({
|
package/src/PluginRunner.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, {
|
|
2
2
|
useEffect,
|
|
3
|
+
useLayoutEffect,
|
|
3
4
|
useMemo,
|
|
4
5
|
useState,
|
|
5
6
|
useRef,
|
|
@@ -75,7 +76,7 @@ const PluginInstance = React.memo(
|
|
|
75
76
|
const lastProcessedOptionsRef = useRef<any>();
|
|
76
77
|
const [isInitialTransform, setIsInitialTransform] = useState(true);
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
useLayoutEffect(() => {
|
|
79
80
|
if (plugin.transformState) {
|
|
80
81
|
if (!isDeepEqual(options, lastProcessedOptionsRef.current)) {
|
|
81
82
|
plugin.transformState({
|
package/src/plugins.ts
CHANGED
|
@@ -89,6 +89,7 @@ type DeconstructedCogsMethods<TStateSlice = any> = {
|
|
|
89
89
|
initialiseShadowState: (data: any) => void;
|
|
90
90
|
applyOperation: (patch: any, meta?: { dontUpdate?: boolean }) => void;
|
|
91
91
|
addZodErrors: (errors: any[]) => void;
|
|
92
|
+
clearZodErrors: (paths: string[][]) => void;
|
|
92
93
|
getState: () => TStateSlice;
|
|
93
94
|
setOptions: (options: any) => void;
|
|
94
95
|
};
|
|
@@ -104,6 +105,8 @@ export function toDeconstructedMethods(stateHandler: StateObject<any>) {
|
|
|
104
105
|
applyOperation: (patch: any, meta?: { dontUpdate?: boolean }) =>
|
|
105
106
|
stateHandler.$applyOperation(patch, meta),
|
|
106
107
|
addZodErrors: (errors: any[]) => stateHandler.$addZodValidation(errors),
|
|
108
|
+
clearZodErrors: (paths: string[][]) =>
|
|
109
|
+
stateHandler.$clearZodValidationPaths(paths),
|
|
107
110
|
getState: () => stateHandler.$get(),
|
|
108
111
|
setOptions: (opts: any) => {
|
|
109
112
|
stateHandler.$setOptions(opts);
|
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 =
|