cogsbox-state 0.5.468 → 0.5.470

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.
@@ -8,7 +8,12 @@ import React, {
8
8
  useRef,
9
9
  useState,
10
10
  } from 'react';
11
- import { formRefStore, getGlobalStore, ValidationError } from './store';
11
+ import {
12
+ formRefStore,
13
+ getGlobalStore,
14
+ ValidationError,
15
+ ValidationSeverity,
16
+ } from './store';
12
17
  import { useInView } from 'react-intersection-observer';
13
18
  import { v4 as uuidv4 } from 'uuid';
14
19
  import { isDeepEqual } from './utility';
@@ -60,7 +65,12 @@ export function ValidationWrapper({
60
65
 
61
66
  // Use first error, or first warning if no errors
62
67
  const message = errorMessages[0] || warningMessages[0];
63
-
68
+ const primarySeverity: ValidationSeverity =
69
+ errorMessages.length > 0
70
+ ? 'error'
71
+ : warningMessages.length > 0
72
+ ? 'warning'
73
+ : undefined;
64
74
  return (
65
75
  <>
66
76
  {thisStateOpts?.formElements?.validation &&
@@ -73,7 +83,7 @@ export function ValidationWrapper({
73
83
  message: formOpts?.validation?.hideMessage
74
84
  ? ''
75
85
  : formOpts?.validation?.message || message || '',
76
-
86
+ severity: primarySeverity,
77
87
  hasErrors: errorMessages.length > 0,
78
88
  hasWarnings: warningMessages.length > 0,
79
89
  allErrors: errors,
@@ -450,7 +460,7 @@ export function FormElementWrapper({
450
460
 
451
461
  const stateWithInputProps = new Proxy(baseState, {
452
462
  get(target, prop) {
453
- if (prop === 'inputProps') {
463
+ if (prop === '$inputProps') {
454
464
  return {
455
465
  value: localValue ?? '',
456
466
  onChange: (e: any) => {
@@ -540,3 +550,44 @@ const useImageLoaded = (ref: RefObject<HTMLElement>): boolean => {
540
550
 
541
551
  return loaded;
542
552
  };
553
+ // Components.tsx
554
+
555
+ // Generic isolated component wrapper
556
+ export function IsolatedComponentWrapper({
557
+ stateKey,
558
+ path,
559
+ rebuildStateShape,
560
+ renderFn,
561
+ }: {
562
+ stateKey: string;
563
+ path: string[];
564
+ rebuildStateShape: (options: {
565
+ path: string[];
566
+ componentId: string;
567
+ meta?: any;
568
+ }) => any;
569
+ renderFn: (state: any) => React.ReactNode;
570
+ }) {
571
+ const [componentId] = useState(() => uuidv4());
572
+ const [, forceUpdate] = useState({});
573
+
574
+ const stateKeyPathKey = [stateKey, ...path].join('.');
575
+ useRegisterComponent(stateKey, componentId, forceUpdate);
576
+
577
+ useEffect(() => {
578
+ const unsubscribe = getGlobalStore
579
+ .getState()
580
+ .subscribeToPath(stateKeyPathKey, () => {
581
+ forceUpdate({});
582
+ });
583
+ return () => unsubscribe();
584
+ }, [stateKeyPathKey]);
585
+
586
+ const baseState = rebuildStateShape({
587
+ path: path,
588
+ componentId: componentId,
589
+ meta: undefined,
590
+ });
591
+
592
+ return <>{renderFn(baseState)}</>;
593
+ }
package/src/store.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { create } from 'zustand';
2
- import { ulid } from 'ulid';
2
+
3
3
  import type {
4
4
  OptionsType,
5
5
  ReactivityType,
@@ -85,11 +85,11 @@ export type ValidationStatus =
85
85
  | 'VALIDATING'
86
86
  | 'VALID'
87
87
  | 'INVALID';
88
-
88
+ export type ValidationSeverity = 'warning' | 'error' | undefined;
89
89
  export type ValidationError = {
90
90
  source: 'client' | 'sync_engine' | 'api';
91
91
  message: string;
92
- severity: 'warning' | 'error';
92
+ severity: ValidationSeverity;
93
93
  code?: string;
94
94
  };
95
95
 
@@ -266,7 +266,7 @@ export function buildShadowNode(value: any): ShadowNode {
266
266
  const idKeys: string[] = [];
267
267
 
268
268
  value.forEach((item) => {
269
- const itemId = `id:${ulid()}`;
269
+ const itemId = `id:${generateId()}`;
270
270
  arrayNode[itemId] = buildShadowNode(item);
271
271
  idKeys.push(itemId);
272
272
  });
@@ -292,6 +292,11 @@ export function buildShadowNode(value: any): ShadowNode {
292
292
 
293
293
  // Module-level mutable store
294
294
  const shadowStateStore = new Map<string, ShadowNode>();
295
+ let globalCounter = 0;
296
+
297
+ export function generateId(prefix = 'id'): string {
298
+ return `${prefix}:${(globalCounter++).toString(36)}`;
299
+ }
295
300
 
296
301
  export const getGlobalStore = create<CogsGlobalState>((set, get) => ({
297
302
  // Remove shadowStateStore from Zustand state
@@ -550,7 +555,7 @@ export const getGlobalStore = create<CogsGlobalState>((set, get) => ({
550
555
  return;
551
556
  }
552
557
 
553
- const newItemId = `id:${ulid()}`;
558
+ const newItemId = `id:${generateId()}`;
554
559
  const itemsToAdd = { [newItemId]: buildShadowNode(newItem) };
555
560
 
556
561
  // Mutate the array directly
@@ -595,7 +600,7 @@ export const getGlobalStore = create<CogsGlobalState>((set, get) => ({
595
600
  const newIds: string[] = [];
596
601
 
597
602
  newItems.forEach((item) => {
598
- const newItemId = `id:${ulid()}`;
603
+ const newItemId = `id:${generateId()}`;
599
604
  newIds.push(newItemId);
600
605
  itemsToAdd[newItemId] = buildShadowNode(item);
601
606
  });