cogsbox-state 0.5.484 → 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/src/CogsState.tsx CHANGED
@@ -158,6 +158,7 @@ export type EndType<
158
158
  errors: ValidationError[],
159
159
  source?: 'client' | 'sync_engine' | 'api'
160
160
  ) => void;
161
+ $clearZodValidationPaths: (paths: string[][]) => void;
161
162
  $clearValidation: (paths?: string[]) => void;
162
163
  $applyOperation: (
163
164
  operation: UpdateTypeDetail,
@@ -3393,31 +3394,60 @@ function createProxyHandler<
3393
3394
  zodErrors: any[],
3394
3395
  source: 'client' | 'sync_engine' | 'api'
3395
3396
  ) => {
3397
+ const store = getGlobalStore.getState();
3396
3398
  zodErrors.forEach((error) => {
3399
+ const errorPath = error.path.map(String);
3397
3400
  const currentMeta =
3398
- getGlobalStore
3399
- .getState()
3400
- .getShadowMetadata(stateKey, error.path) || {};
3401
+ store.getShadowMetadata(stateKey, errorPath) || {};
3401
3402
 
3402
- getGlobalStore
3403
- .getState()
3404
- .setShadowMetadata(stateKey, error.path, {
3405
- ...currentMeta,
3406
- validation: {
3407
- status: 'INVALID',
3408
- errors: [
3409
- {
3410
- source: source || 'client',
3411
- message: error.message,
3412
- severity: 'error',
3413
- code: error.code,
3414
- },
3415
- ],
3416
- lastValidated: Date.now(),
3417
- validatedValue: undefined,
3418
- },
3419
- });
3403
+ store.setShadowMetadata(stateKey, errorPath, {
3404
+ ...currentMeta,
3405
+ validation: {
3406
+ status: 'INVALID',
3407
+ errors: [
3408
+ {
3409
+ source: source || 'client',
3410
+ message: error.message,
3411
+ severity: 'error',
3412
+ code: error.code,
3413
+ },
3414
+ ],
3415
+ lastValidated: Date.now(),
3416
+ validatedValue: undefined,
3417
+ },
3418
+ });
3419
+ store.notifyPathSubscribers(
3420
+ [stateKey, ...errorPath].join('.'),
3421
+ { type: 'VALIDATION_UPDATE' }
3422
+ );
3423
+ });
3424
+ notifyComponents(stateKey);
3425
+ };
3426
+ }
3427
+
3428
+ if (prop === '$clearZodValidationPaths') {
3429
+ return (paths: string[][]) => {
3430
+ const store = getGlobalStore.getState();
3431
+ paths.forEach((targetPath) => {
3432
+ const currentMeta =
3433
+ store.getShadowMetadata(stateKey, targetPath) || {};
3434
+ if (!currentMeta.validation) return;
3435
+
3436
+ store.setShadowMetadata(stateKey, targetPath, {
3437
+ ...currentMeta,
3438
+ validation: {
3439
+ status: 'NOT_VALIDATED',
3440
+ errors: [],
3441
+ lastValidated: Date.now(),
3442
+ validatedValue: undefined,
3443
+ },
3444
+ });
3445
+ store.notifyPathSubscribers(
3446
+ [stateKey, ...targetPath].join('.'),
3447
+ { type: 'VALIDATION_CLEAR' }
3448
+ );
3420
3449
  });
3450
+ notifyComponents(stateKey);
3421
3451
  };
3422
3452
  }
3423
3453
 
@@ -483,10 +483,7 @@ export function FormElementWrapper({
483
483
  clearTimeout(debounceTimeoutRef.current);
484
484
  debounceTimeoutRef.current = null;
485
485
  isCurrentlyDebouncing.current = false;
486
- setState(localValue, path, {
487
- updateType: 'update',
488
- validationTrigger: 'onBlur',
489
- });
486
+ setState(localValue, path, { updateType: 'update' });
490
487
  }
491
488
 
492
489
  // Clear element's current activity
@@ -500,10 +497,26 @@ export function FormElementWrapper({
500
497
  meta?.clientActivityState?.elements?.get(componentId)?.currentActivity
501
498
  ?.startTime;
502
499
 
503
- // Notify plugins
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
504
517
  notifyFormUpdate({
505
518
  stateKey,
506
- activityType: 'blur', // Changed from 'type'
519
+ activityType: 'blur',
507
520
  path,
508
521
  timestamp: Date.now(),
509
522
  duration: focusStartTime ? Date.now() - focusStartTime : undefined,
@@ -511,21 +524,6 @@ export function FormElementWrapper({
511
524
  duration: focusStartTime ? Date.now() - focusStartTime : 0,
512
525
  },
513
526
  });
514
-
515
- // Run validation if configured
516
- const validationOptions = getInitialOptions(stateKey)?.validation;
517
- if (validationOptions?.onBlur) {
518
- const virtualOperation: UpdateTypeDetail = {
519
- stateKey,
520
- path,
521
- newValue: localValue,
522
- updateType: 'update',
523
- timeStamp: Date.now(),
524
- status: 'new',
525
- oldValue: globalStateValue,
526
- };
527
- runValidation(virtualOperation, 'onBlur');
528
- }
529
527
  }, [localValue, setState, path, stateKey, componentId, globalStateValue]);
530
528
 
531
529
  const baseState = rebuildStateShape({
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);