cogsbox-state 0.5.462 → 0.5.464
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 -1
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.jsx +1057 -1047
- package/dist/CogsState.jsx.map +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +188 -167
- package/dist/store.js.map +1 -1
- package/package.json +1 -1
- package/src/CogsState.tsx +78 -48
- package/src/store.ts +86 -98
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sources":["../src/store.ts"],"sourcesContent":["import { create } from 'zustand';\r\nimport { ulid } from 'ulid';\r\nimport type {\r\n OptionsType,\r\n ReactivityType,\r\n StateKeys,\r\n SyncInfo,\r\n UpdateTypeDetail,\r\n} from './CogsState.js';\r\n\r\nimport { startTransition, type ReactNode } from 'react';\r\n\r\ntype StateUpdater<StateValue> =\r\n | StateValue\r\n | ((prevValue: StateValue) => StateValue);\r\n\r\nexport type FreshValuesObject = {\r\n pathsToValues?: string[];\r\n prevValue?: any;\r\n newValue?: any;\r\n timeStamp: number;\r\n};\r\n\r\ntype SyncLogType = {\r\n timeStamp: number;\r\n};\r\ntype StateValue = any;\r\n\r\nexport type TrieNode = {\r\n subscribers: Set<string>;\r\n children: Map<string, TrieNode>;\r\n};\r\n\r\nexport type FormRefStoreState = {\r\n formRefs: Map<string, React.RefObject<any>>;\r\n registerFormRef: (id: string, ref: React.RefObject<any>) => void;\r\n getFormRef: (id: string) => React.RefObject<any> | undefined;\r\n removeFormRef: (id: string) => void;\r\n // New method to get all refs for a stateKey\r\n getFormRefsByStateKey: (\r\n stateKey: string\r\n ) => Map<string, React.RefObject<any>>;\r\n};\r\n\r\nexport const formRefStore = create<FormRefStoreState>((set, get) => ({\r\n formRefs: new Map(),\r\n\r\n registerFormRef: (id, ref) =>\r\n set((state) => {\r\n const newRefs = new Map(state.formRefs);\r\n newRefs.set(id, ref);\r\n return { formRefs: newRefs };\r\n }),\r\n\r\n getFormRef: (id) => get().formRefs.get(id),\r\n\r\n removeFormRef: (id) =>\r\n set((state) => {\r\n const newRefs = new Map(state.formRefs);\r\n newRefs.delete(id);\r\n return { formRefs: newRefs };\r\n }),\r\n\r\n // Get all refs that start with the stateKey prefix\r\n getFormRefsByStateKey: (stateKey) => {\r\n const allRefs = get().formRefs;\r\n const stateKeyPrefix = stateKey + '.';\r\n const filteredRefs = new Map();\r\n\r\n allRefs.forEach((ref, id) => {\r\n if (id.startsWith(stateKeyPrefix) || id === stateKey) {\r\n filteredRefs.set(id, ref);\r\n }\r\n });\r\n\r\n return filteredRefs;\r\n },\r\n}));\r\nexport type ComponentsType = {\r\n components?: Map<\r\n string,\r\n {\r\n forceUpdate: () => void;\r\n paths: Set<string>;\r\n deps?: any[];\r\n prevDeps?: any[];\r\n depsFunction?: (state: any) => any[] | true;\r\n reactiveType: ReactivityType[] | ReactivityType;\r\n }\r\n >;\r\n};\r\nexport type ShadowMetadata = {\r\n id?: string;\r\n\r\n stateSource?: 'default' | 'server' | 'localStorage';\r\n lastServerSync?: number;\r\n isDirty?: boolean;\r\n baseServerState?: any;\r\n\r\n arrayKeys?: string[];\r\n\r\n fields?: Record<string, any>;\r\n virtualizer?: {\r\n itemHeight?: number;\r\n domRef?: HTMLElement | null;\r\n };\r\n syncInfo?: { status: string };\r\n validation?: ValidationState;\r\n lastUpdated?: number;\r\n value?: any;\r\n classSignals?: Array<{\r\n // <-- ADD THIS BLOCK\r\n id: string;\r\n effect: string;\r\n lastClasses: string;\r\n deps: any[];\r\n }>;\r\n signals?: Array<{\r\n instanceId: string;\r\n parentId: string;\r\n position: number;\r\n effect?: string;\r\n }>;\r\n mapWrappers?: Array<{\r\n instanceId: string;\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n mapFn: (\r\n setter: any,\r\n index: number,\r\n\r\n arraySetter: any\r\n ) => ReactNode;\r\n containerRef: HTMLDivElement | null;\r\n rebuildStateShape: any;\r\n }>;\r\n transformCaches?: Map<\r\n string,\r\n {\r\n validIds: string[];\r\n computedAt: number;\r\n transforms: Array<{ type: 'filter' | 'sort'; fn: Function }>;\r\n }\r\n >;\r\n pathComponents?: Set<string>;\r\n streams?: Map<\r\n string,\r\n {\r\n buffer: any[];\r\n flushTimer: NodeJS.Timeout | null;\r\n }\r\n >;\r\n} & ComponentsType;\r\n\r\nexport type ValidationStatus =\r\n | 'PRISTINE' // Untouched, matches initial state.\r\n | 'DIRTY' // Changed, but no validation run yet.\r\n | 'VALID_LIVE' // Valid while typing.\r\n | 'INVALID_LIVE' // Gentle error during typing.\r\n | 'VALIDATION_FAILED' // Hard error on blur/submit.\r\n | 'VALID_PENDING_SYNC' // Passed validation, ready for sync.\r\n | 'SYNCING' // Actively being sent to the server.\r\n | 'SYNCED' // Server confirmed success.\r\n | 'SYNC_FAILED'; // Server rejected the data.\r\n\r\nexport type ValidationState = {\r\n status: ValidationStatus;\r\n message?: string;\r\n lastValidated?: number;\r\n validatedValue?: any;\r\n};\r\nexport type CogsEvent =\r\n | { type: 'INSERT'; path: string; itemKey: string; index: number }\r\n | { type: 'REMOVE'; path: string; itemKey: string }\r\n | { type: 'UPDATE'; path: string; newValue: any }\r\n | { type: 'ITEMHEIGHT'; itemKey: string; height: number } // For full re-initializations (e.g., when a component is removed)\r\n | { type: 'RELOAD'; path: string }; // For full re-initializations\r\nexport type CogsGlobalState = {\r\n updateQueue: Set<() => void>;\r\n isFlushScheduled: boolean;\r\n\r\n flushUpdates: () => void;\r\n\r\n // --- Shadow State and Subscription System ---\r\n registerComponent: (\r\n stateKey: string,\r\n componentId: string,\r\n registration: any\r\n ) => void;\r\n unregisterComponent: (stateKey: string, componentId: string) => void;\r\n addPathComponent: (\r\n stateKey: string,\r\n dependencyPath: string[],\r\n fullComponentId: string\r\n ) => void;\r\n shadowStateStore: Map<string, ShadowMetadata>;\r\n\r\n markAsDirty: (\r\n key: string,\r\n path: string[],\r\n options: { bubble: boolean }\r\n ) => void;\r\n // These method signatures stay the same\r\n initializeShadowState: (key: string, initialState: any) => void;\r\n updateShadowAtPath: (key: string, path: string[], newValue: any) => void;\r\n insertShadowArrayElement: (\r\n key: string,\r\n arrayPath: string[],\r\n newItem: any\r\n ) => void;\r\n removeShadowArrayElement: (key: string, arrayPath: string[]) => void;\r\n getShadowValue: (\r\n key: string,\r\n\r\n validArrayIds?: string[]\r\n ) => any;\r\n\r\n getShadowMetadata: (\r\n key: string,\r\n path: string[]\r\n ) => ShadowMetadata | undefined;\r\n setShadowMetadata: (\r\n key: string,\r\n path: string[],\r\n metadata: Omit<ShadowMetadata, 'id'>\r\n ) => void;\r\n setTransformCache: (\r\n key: string,\r\n path: string[],\r\n cacheKey: string,\r\n cacheData: any\r\n ) => void;\r\n\r\n pathSubscribers: Map<string, Set<(newValue: any) => void>>;\r\n subscribeToPath: (\r\n path: string,\r\n callback: (newValue: any) => void\r\n ) => () => void;\r\n notifyPathSubscribers: (updatedPath: string, newValue: any) => void;\r\n\r\n selectedIndicesMap: Map<string, string>; // stateKey -> (parentPath -> selectedIndex)\r\n getSelectedIndex: (stateKey: string, validArrayIds?: string[]) => number;\r\n setSelectedIndex: (key: string, itemKey: string) => void;\r\n clearSelectedIndex: ({ arrayKey }: { arrayKey: string }) => void;\r\n clearSelectedIndexesForState: (stateKey: string) => void;\r\n\r\n // --- Core State and Updaters ---\r\n\r\n initialStateOptions: { [key: string]: OptionsType };\r\n\r\n initialStateGlobal: { [key: string]: StateValue };\r\n\r\n updateInitialStateGlobal: (key: string, newState: StateValue) => void;\r\n\r\n getInitialOptions: (key: string) => OptionsType | undefined;\r\n setInitialStateOptions: (key: string, value: OptionsType) => void;\r\n\r\n // --- Validation ---\r\n\r\n // --- Server Sync and Logging ---\r\n\r\n serverStateUpdates: Map<\r\n string,\r\n {\r\n data: any;\r\n status: 'loading' | 'success' | 'error';\r\n timestamp: number;\r\n }\r\n >;\r\n\r\n setServerStateUpdate: (key: string, serverState: any) => void;\r\n\r\n stateLog: Map<string, Map<string, UpdateTypeDetail>>;\r\n syncInfoStore: Map<string, SyncInfo>;\r\n addStateLog: (key: string, update: UpdateTypeDetail) => void;\r\n\r\n setSyncInfo: (key: string, syncInfo: SyncInfo) => void;\r\n getSyncInfo: (key: string) => SyncInfo | null;\r\n};\r\nconst isSimpleObject = (value: any): boolean => {\r\n if (value === null || typeof value !== 'object') return false;\r\n\r\n // Handle special cases that should be treated as primitives\r\n if (\r\n value instanceof Uint8Array ||\r\n value instanceof Int8Array ||\r\n value instanceof Uint16Array ||\r\n value instanceof Int16Array ||\r\n value instanceof Uint32Array ||\r\n value instanceof Int32Array ||\r\n value instanceof Float32Array ||\r\n value instanceof Float64Array ||\r\n value instanceof ArrayBuffer ||\r\n value instanceof Date ||\r\n value instanceof RegExp ||\r\n value instanceof Map ||\r\n value instanceof Set\r\n ) {\r\n return false; // Treat as primitive\r\n }\r\n\r\n // Arrays and plain objects are complex\r\n return Array.isArray(value) || value.constructor === Object;\r\n};\r\nexport const getGlobalStore = create<CogsGlobalState>((set, get) => ({\r\n updateQueue: new Set<() => void>(),\r\n // A flag to ensure we only schedule the flush once per event-loop tick.\r\n isFlushScheduled: false,\r\n\r\n // This function is called by queueMicrotask to execute all queued updates.\r\n flushUpdates: () => {\r\n const { updateQueue } = get();\r\n\r\n if (updateQueue.size > 0) {\r\n startTransition(() => {\r\n updateQueue.forEach((updateFn) => updateFn());\r\n });\r\n }\r\n\r\n // Clear the queue and reset the flag for the next event loop tick.\r\n set({ updateQueue: new Set(), isFlushScheduled: false });\r\n },\r\n addPathComponent: (stateKey, dependencyPath, fullComponentId) => {\r\n set((state) => {\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n const dependencyKey = [stateKey, ...dependencyPath].join('.');\r\n\r\n // --- Part 1: Update the path's own metadata ---\r\n const pathMeta = newShadowStore.get(dependencyKey) || {};\r\n // Create a *new* Set to ensure immutability\r\n const pathComponents = new Set(pathMeta.pathComponents);\r\n pathComponents.add(fullComponentId);\r\n // Update the metadata for the specific path\r\n newShadowStore.set(dependencyKey, { ...pathMeta, pathComponents });\r\n\r\n // --- Part 2: Update the component's own list of paths ---\r\n const rootMeta = newShadowStore.get(stateKey) || {};\r\n const component = rootMeta.components?.get(fullComponentId);\r\n\r\n // If the component exists, update its `paths` set immutably\r\n if (component) {\r\n const newPaths = new Set(component.paths);\r\n newPaths.add(dependencyKey);\r\n\r\n const newComponentRegistration = { ...component, paths: newPaths };\r\n const newComponentsMap = new Map(rootMeta.components);\r\n newComponentsMap.set(fullComponentId, newComponentRegistration);\r\n\r\n // Update the root metadata with the new components map\r\n newShadowStore.set(stateKey, {\r\n ...rootMeta,\r\n components: newComponentsMap,\r\n });\r\n }\r\n\r\n // Return the final, updated state\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n registerComponent: (stateKey, fullComponentId, registration) => {\r\n set((state) => {\r\n // Create a new Map to ensure Zustand detects the change\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n\r\n // Get the metadata for the ROOT of the state (where the components map lives)\r\n const rootMeta = newShadowStore.get(stateKey) || {};\r\n\r\n // Also clone the components map to avoid direct mutation\r\n const components = new Map(rootMeta.components);\r\n components.set(fullComponentId, registration);\r\n\r\n // Update the root metadata with the new components map\r\n newShadowStore.set(stateKey, { ...rootMeta, components });\r\n\r\n // Return the updated state\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n\r\n unregisterComponent: (stateKey, fullComponentId) => {\r\n set((state) => {\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n const rootMeta = newShadowStore.get(stateKey);\r\n\r\n // If there's no metadata or no components map, do nothing\r\n if (!rootMeta?.components) {\r\n return state; // Return original state, no change needed\r\n }\r\n\r\n const components = new Map(rootMeta.components);\r\n const wasDeleted = components.delete(fullComponentId);\r\n\r\n // Only update state if something was actually deleted\r\n if (wasDeleted) {\r\n newShadowStore.set(stateKey, { ...rootMeta, components });\r\n return { shadowStateStore: newShadowStore };\r\n }\r\n\r\n return state; // Nothing changed\r\n });\r\n },\r\n markAsDirty: (key: string, path: string[], options = { bubble: true }) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n let changed = false;\r\n\r\n const setDirty = (currentPath: string[]) => {\r\n const fullKey = [key, ...currentPath].join('.');\r\n const meta = newShadowStore.get(fullKey);\r\n\r\n // We mark something as dirty if it isn't already.\r\n // The original data source doesn't matter.\r\n if (meta && meta.isDirty !== true) {\r\n newShadowStore.set(fullKey, { ...meta, isDirty: true });\r\n changed = true;\r\n } else if (!meta) {\r\n // If there's no metadata, create it and mark it as dirty.\r\n // This handles newly created fields within an object.\r\n newShadowStore.set(fullKey, { isDirty: true });\r\n changed = true;\r\n }\r\n };\r\n\r\n // 1. Mark the target path itself as dirty.\r\n setDirty(path);\r\n\r\n // 2. If `bubble` is true, walk up the path and mark all parents as dirty.\r\n if (options.bubble) {\r\n let parentPath = [...path];\r\n while (parentPath.length > 0) {\r\n parentPath.pop();\r\n setDirty(parentPath);\r\n }\r\n }\r\n\r\n if (changed) {\r\n set({ shadowStateStore: newShadowStore });\r\n }\r\n },\r\n serverStateUpdates: new Map(),\r\n setServerStateUpdate: (key, serverState) => {\r\n set((state) => {\r\n const newMap = new Map(state.serverStateUpdates);\r\n newMap.set(key, serverState);\r\n return { serverStateUpdates: newMap };\r\n });\r\n\r\n // Notify all subscribers for this key\r\n get().notifyPathSubscribers(key, {\r\n type: 'SERVER_STATE_UPDATE',\r\n serverState,\r\n });\r\n },\r\n shadowStateStore: new Map(),\r\n getShadowNode: (key: string) => get().shadowStateStore.get(key),\r\n pathSubscribers: new Map<string, Set<(newValue: any) => void>>(),\r\n\r\n subscribeToPath: (path, callback) => {\r\n const subscribers = get().pathSubscribers;\r\n const subsForPath = subscribers.get(path) || new Set();\r\n subsForPath.add(callback);\r\n subscribers.set(path, subsForPath);\r\n\r\n return () => {\r\n const currentSubs = get().pathSubscribers.get(path);\r\n if (currentSubs) {\r\n currentSubs.delete(callback);\r\n if (currentSubs.size === 0) {\r\n get().pathSubscribers.delete(path);\r\n }\r\n }\r\n };\r\n },\r\n\r\n notifyPathSubscribers: (updatedPath, newValue) => {\r\n const subscribers = get().pathSubscribers;\r\n const subs = subscribers.get(updatedPath);\r\n\r\n if (subs) {\r\n subs.forEach((callback) => callback(newValue));\r\n }\r\n },\r\n\r\n initializeShadowState: (key: string, initialState: any) => {\r\n set((state) => {\r\n // 1. Make a copy of the current store to modify it\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n\r\n // 2. PRESERVE the existing components map before doing anything else\r\n const existingRootMeta = newShadowStore.get(key);\r\n const preservedComponents = existingRootMeta?.components;\r\n\r\n // 3. Wipe all old shadow entries for this state key\r\n const prefixToDelete = key + '.';\r\n for (const k of Array.from(newShadowStore.keys())) {\r\n if (k === key || k.startsWith(prefixToDelete)) {\r\n newShadowStore.delete(k);\r\n }\r\n }\r\n\r\n // 4. Run your original logic to rebuild the state tree from scratch\r\n const processValue = (value: any, path: string[]) => {\r\n const nodeKey = [key, ...path].join('.');\r\n\r\n if (Array.isArray(value)) {\r\n const childIds: string[] = [];\r\n value.forEach(() => {\r\n const itemId = `id:${ulid()}`;\r\n childIds.push(nodeKey + '.' + itemId);\r\n });\r\n newShadowStore.set(nodeKey, { arrayKeys: childIds });\r\n value.forEach((item, index) => {\r\n const itemId = childIds[index]!.split('.').pop();\r\n processValue(item, [...path!, itemId!]);\r\n });\r\n } else if (isSimpleObject(value)) {\r\n const fields = Object.fromEntries(\r\n Object.keys(value).map((k) => [k, nodeKey + '.' + k])\r\n );\r\n newShadowStore.set(nodeKey, { fields });\r\n Object.keys(value).forEach((k) => {\r\n processValue(value[k], [...path, k]);\r\n });\r\n } else {\r\n newShadowStore.set(nodeKey, { value });\r\n }\r\n };\r\n processValue(initialState, []);\r\n\r\n // 5. RESTORE the preserved components map onto the new root metadata\r\n if (preservedComponents) {\r\n const newRootMeta = newShadowStore.get(key) || {};\r\n newShadowStore.set(key, {\r\n ...newRootMeta,\r\n components: preservedComponents,\r\n });\r\n }\r\n\r\n // 6. Return the completely updated state\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n\r\n getShadowValue: (fullKey: string, validArrayIds?: string[]) => {\r\n // The cache is created here. It's temporary and exists only for this one top-level call.\r\n const memo = new Map<string, any>();\r\n\r\n // This is the inner recursive function that does the real work.\r\n const reconstruct = (keyToBuild: string, ids?: string[]): any => {\r\n // --- STEP 1: Check the cache first ---\r\n // If we have already built the object for this path *during this call*, return it instantly.\r\n if (memo.has(keyToBuild)) {\r\n return memo.get(keyToBuild);\r\n }\r\n\r\n const shadowMeta = get().shadowStateStore.get(keyToBuild);\r\n\r\n if (!shadowMeta) {\r\n return undefined;\r\n }\r\n\r\n if (shadowMeta.value !== undefined) {\r\n return shadowMeta.value;\r\n }\r\n\r\n let result: any; // The value we are about to build.\r\n\r\n if (shadowMeta.arrayKeys) {\r\n const keys = ids ?? shadowMeta.arrayKeys;\r\n // --- IMPORTANT: Set the cache BEFORE the recursive calls ---\r\n // This handles circular references gracefully. We put an empty array in the cache now.\r\n result = [];\r\n memo.set(keyToBuild, result);\r\n // Now, fill the array with the recursively constructed items.\r\n keys.forEach((itemKey) => {\r\n result.push(reconstruct(itemKey)); // Pass the memo cache along implicitly via closure\r\n });\r\n } else if (shadowMeta.fields) {\r\n // --- IMPORTANT: Set the cache BEFORE the recursive calls ---\r\n result = {};\r\n memo.set(keyToBuild, result);\r\n // Now, fill the object with the recursively constructed items.\r\n Object.entries(shadowMeta.fields).forEach(([key, fieldPath]) => {\r\n result[key] = reconstruct(fieldPath as string);\r\n });\r\n } else {\r\n result = undefined;\r\n }\r\n\r\n // Return the final, fully populated result.\r\n return result;\r\n };\r\n\r\n // Start the process by calling the inner function on the root key.\r\n return reconstruct(fullKey, validArrayIds);\r\n },\r\n getShadowMetadata: (\r\n key: string,\r\n path: string[],\r\n validArrayIds?: string[]\r\n ) => {\r\n const fullKey = [key, ...path].join('.');\r\n let data = get().shadowStateStore.get(fullKey);\r\n\r\n return get().shadowStateStore.get(fullKey);\r\n },\r\n\r\n setShadowMetadata: (key, path, metadata) => {\r\n const fullKey = [key, ...path].join('.');\r\n const existingMeta = get().shadowStateStore.get(fullKey);\r\n\r\n // --- THIS IS THE TRAP ---\r\n // If the existing metadata HAS a components map, but the NEW metadata DOES NOT,\r\n // it means we are about to wipe it out. This is the bug.\r\n if (existingMeta?.components && !metadata.components) {\r\n console.group(\r\n '%c🚨 RACE CONDITION DETECTED! 🚨',\r\n 'color: red; font-size: 18px; font-weight: bold;'\r\n );\r\n console.error(\r\n `An overwrite is about to happen on stateKey: \"${key}\" at path: [${path.join(', ')}]`\r\n );\r\n console.log(\r\n 'The EXISTING metadata had a components map:',\r\n existingMeta.components\r\n );\r\n console.log(\r\n 'The NEW metadata is trying to save WITHOUT a components map:',\r\n metadata\r\n );\r\n console.log(\r\n '%cStack trace to the function that caused this overwrite:',\r\n 'font-weight: bold;'\r\n );\r\n console.trace(); // This prints the call stack, leading you to the bad code.\r\n console.groupEnd();\r\n }\r\n // --- END OF TRAP ---\r\n\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const finalMeta = { ...(existingMeta || {}), ...metadata };\r\n newShadowStore.set(fullKey, finalMeta);\r\n set({ shadowStateStore: newShadowStore });\r\n },\r\n setTransformCache: (\r\n key: string,\r\n path: string[],\r\n cacheKey: string,\r\n cacheData: any\r\n ) => {\r\n const fullKey = [key, ...path].join('.');\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const existing = newShadowStore.get(fullKey) || {};\r\n\r\n // Initialize transformCaches if it doesn't exist\r\n if (!existing.transformCaches) {\r\n existing.transformCaches = new Map();\r\n }\r\n\r\n // Update just the specific cache entry\r\n existing.transformCaches.set(cacheKey, cacheData);\r\n\r\n // Update shadow store WITHOUT notifying path subscribers\r\n newShadowStore.set(fullKey, existing);\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n // Don't call notifyPathSubscribers here - cache updates shouldn't trigger renders\r\n },\r\n insertShadowArrayElement: (\r\n key: string,\r\n arrayPath: string[],\r\n newItem: any\r\n ) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const arrayKey = [key, ...arrayPath].join('.');\r\n const parentMeta = newShadowStore.get(arrayKey);\r\n\r\n if (!parentMeta || !parentMeta.arrayKeys) return;\r\n\r\n const newItemId = `id:${ulid()}`;\r\n const fullItemKey = arrayKey + '.' + newItemId;\r\n\r\n // Just add to the end (or at a specific index if provided)\r\n const newArrayKeys = [...parentMeta.arrayKeys];\r\n newArrayKeys.push(fullItemKey); // Or use splice if you have an index\r\n newShadowStore.set(arrayKey, { ...parentMeta, arrayKeys: newArrayKeys });\r\n\r\n // Process the new item - but use the correct logic\r\n const processNewItem = (value: any, path: string[]) => {\r\n const nodeKey = [key, ...path].join('.');\r\n\r\n if (Array.isArray(value)) {\r\n // Handle arrays...\r\n } else if (typeof value === 'object' && value !== null) {\r\n // Create fields mapping\r\n const fields = Object.fromEntries(\r\n Object.keys(value).map((k) => [k, nodeKey + '.' + k])\r\n );\r\n newShadowStore.set(nodeKey, { fields });\r\n\r\n // Process each field\r\n Object.entries(value).forEach(([k, v]) => {\r\n processNewItem(v, [...path, k]);\r\n });\r\n } else {\r\n // Primitive value\r\n newShadowStore.set(nodeKey, { value });\r\n }\r\n };\r\n\r\n processNewItem(newItem, [...arrayPath, newItemId]);\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'INSERT',\r\n path: arrayKey,\r\n itemKey: fullItemKey,\r\n });\r\n },\r\n removeShadowArrayElement: (key: string, itemPath: string[]) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n\r\n // Get the full item key (e.g., \"stateKey.products.id:xxx\")\r\n const itemKey = [key, ...itemPath].join('.');\r\n\r\n // Extract parent path and item ID\r\n const parentPath = itemPath.slice(0, -1);\r\n const parentKey = [key, ...parentPath].join('.');\r\n\r\n // Get parent metadata\r\n const parentMeta = newShadowStore.get(parentKey);\r\n\r\n if (parentMeta && parentMeta.arrayKeys) {\r\n // Find the index of the item to remove\r\n const indexToRemove = parentMeta.arrayKeys.findIndex(\r\n (arrayItemKey) => arrayItemKey === itemKey\r\n );\r\n\r\n if (indexToRemove !== -1) {\r\n // Create new array keys with the item removed\r\n const newArrayKeys = parentMeta.arrayKeys.filter(\r\n (arrayItemKey) => arrayItemKey !== itemKey\r\n );\r\n\r\n // Update parent with new array keys\r\n newShadowStore.set(parentKey, {\r\n ...parentMeta,\r\n arrayKeys: newArrayKeys,\r\n });\r\n\r\n // Delete all data associated with the removed item\r\n const prefixToDelete = itemKey + '.';\r\n for (const k of Array.from(newShadowStore.keys())) {\r\n if (k === itemKey || k.startsWith(prefixToDelete)) {\r\n newShadowStore.delete(k);\r\n }\r\n }\r\n }\r\n }\r\n\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n get().notifyPathSubscribers(parentKey, {\r\n type: 'REMOVE',\r\n path: parentKey,\r\n itemKey: itemKey, // The exact ID of the removed item\r\n });\r\n },\r\n updateShadowAtPath: (key, path, newValue) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const fullKey = [key, ...path].join('.');\r\n\r\n const updateValue = (currentKey: string, valueToSet: any) => {\r\n const meta = newShadowStore.get(currentKey);\r\n\r\n // If it's a simple object with fields, update recursively\r\n if (isSimpleObject(valueToSet) && meta && meta.fields) {\r\n for (const fieldKey in valueToSet) {\r\n if (Object.prototype.hasOwnProperty.call(valueToSet, fieldKey)) {\r\n const childPath = meta.fields[fieldKey];\r\n const childValue = valueToSet[fieldKey];\r\n\r\n if (childPath) {\r\n updateValue(childPath as string, childValue);\r\n }\r\n }\r\n }\r\n } else {\r\n // For primitives (including Uint8Array), just replace the value\r\n // This gives you useState-like behavior\r\n const existing = newShadowStore.get(currentKey) || {};\r\n newShadowStore.set(currentKey, { ...existing, value: valueToSet });\r\n }\r\n };\r\n\r\n updateValue(fullKey, newValue);\r\n get().notifyPathSubscribers(fullKey, { type: 'UPDATE', newValue });\r\n set({ shadowStateStore: newShadowStore });\r\n },\r\n selectedIndicesMap: new Map<string, string>(),\r\n getSelectedIndex: (arrayKey: string, validIds?: string[]): number => {\r\n const itemKey = get().selectedIndicesMap.get(arrayKey);\r\n\r\n if (!itemKey) return -1;\r\n\r\n // Use validIds if provided (for filtered views), otherwise use all arrayKeys\r\n const arrayKeys =\r\n validIds ||\r\n getGlobalStore.getState().getShadowMetadata(arrayKey, [])?.arrayKeys;\r\n\r\n if (!arrayKeys) return -1;\r\n\r\n return arrayKeys.indexOf(itemKey);\r\n },\r\n\r\n setSelectedIndex: (arrayKey: string, itemKey: string | undefined) => {\r\n set((state) => {\r\n const newMap = state.selectedIndicesMap;\r\n\r\n if (itemKey === undefined) {\r\n newMap.delete(arrayKey);\r\n } else {\r\n if (newMap.has(arrayKey)) {\r\n get().notifyPathSubscribers(newMap.get(arrayKey)!, {\r\n type: 'THIS_UNSELECTED',\r\n });\r\n }\r\n newMap.set(arrayKey, itemKey);\r\n\r\n get().notifyPathSubscribers(itemKey, {\r\n type: 'THIS_SELECTED',\r\n });\r\n }\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'GET_SELECTED',\r\n });\r\n return {\r\n ...state,\r\n selectedIndicesMap: newMap,\r\n };\r\n });\r\n },\r\n clearSelectedIndex: ({ arrayKey }: { arrayKey: string }): void => {\r\n set((state) => {\r\n const newMap = state.selectedIndicesMap;\r\n const acutalKey = newMap.get(arrayKey);\r\n if (acutalKey) {\r\n get().notifyPathSubscribers(acutalKey, {\r\n type: 'CLEAR_SELECTION',\r\n });\r\n }\r\n\r\n newMap.delete(arrayKey);\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'CLEAR_SELECTION',\r\n });\r\n return {\r\n ...state,\r\n selectedIndicesMap: newMap,\r\n };\r\n });\r\n },\r\n clearSelectedIndexesForState: (stateKey: string) => {\r\n set((state) => {\r\n const newOuterMap = new Map(state.selectedIndicesMap);\r\n const changed = newOuterMap.delete(stateKey);\r\n if (changed) {\r\n return { selectedIndicesMap: newOuterMap };\r\n } else {\r\n return {};\r\n }\r\n });\r\n },\r\n\r\n initialStateOptions: {},\r\n\r\n stateTimeline: {},\r\n cogsStateStore: {},\r\n stateLog: new Map(),\r\n\r\n initialStateGlobal: {},\r\n\r\n validationErrors: new Map(),\r\n addStateLog: (key, update) => {\r\n set((state) => {\r\n const newLog = new Map(state.stateLog);\r\n const stateLogForKey = new Map(newLog.get(key));\r\n const uniquePathKey = JSON.stringify(update.path);\r\n\r\n const existing = stateLogForKey.get(uniquePathKey);\r\n if (existing) {\r\n // If an update for this path already exists, just modify it. (Fast)\r\n existing.newValue = update.newValue;\r\n existing.timeStamp = update.timeStamp;\r\n } else {\r\n // Otherwise, add the new update. (Fast)\r\n stateLogForKey.set(uniquePathKey, { ...update });\r\n }\r\n\r\n newLog.set(key, stateLogForKey);\r\n return { stateLog: newLog };\r\n });\r\n },\r\n\r\n getInitialOptions: (key) => {\r\n return get().initialStateOptions[key];\r\n },\r\n\r\n setInitialStateOptions: (key, value) => {\r\n set((prev) => ({\r\n initialStateOptions: {\r\n ...prev.initialStateOptions,\r\n [key]: value,\r\n },\r\n }));\r\n },\r\n updateInitialStateGlobal: (key, newState) => {\r\n set((prev) => ({\r\n initialStateGlobal: {\r\n ...prev.initialStateGlobal,\r\n [key]: newState,\r\n },\r\n }));\r\n },\r\n\r\n syncInfoStore: new Map<string, SyncInfo>(),\r\n setSyncInfo: (key: string, syncInfo: SyncInfo) =>\r\n set((state) => {\r\n const newMap = new Map(state.syncInfoStore);\r\n newMap.set(key, syncInfo);\r\n return { ...state, syncInfoStore: newMap };\r\n }),\r\n getSyncInfo: (key: string) => get().syncInfoStore.get(key) || null,\r\n}));\r\n"],"names":["formRefStore","create","set","get","id","ref","state","newRefs","stateKey","allRefs","stateKeyPrefix","filteredRefs","isSimpleObject","value","getGlobalStore","updateQueue","startTransition","updateFn","dependencyPath","fullComponentId","newShadowStore","dependencyKey","pathMeta","pathComponents","rootMeta","component","newPaths","newComponentRegistration","newComponentsMap","registration","components","key","path","options","changed","setDirty","currentPath","fullKey","meta","parentPath","serverState","newMap","callback","subscribers","subsForPath","currentSubs","updatedPath","newValue","subs","initialState","preservedComponents","prefixToDelete","k","processValue","nodeKey","childIds","itemId","ulid","item","index","fields","newRootMeta","validArrayIds","memo","reconstruct","keyToBuild","ids","shadowMeta","result","keys","itemKey","fieldPath","metadata","existingMeta","finalMeta","cacheKey","cacheData","existing","arrayPath","newItem","arrayKey","parentMeta","newItemId","fullItemKey","newArrayKeys","processNewItem","v","itemPath","parentKey","arrayItemKey","updateValue","currentKey","valueToSet","fieldKey","childPath","childValue","validIds","arrayKeys","acutalKey","newOuterMap","update","newLog","stateLogForKey","uniquePathKey","prev","newState","syncInfo"],"mappings":";;;AA4CO,MAAMA,IAAeC,EAA0B,CAACC,GAAKC,OAAS;AAAA,EACnE,8BAAc,IAAA;AAAA,EAEd,iBAAiB,CAACC,GAAIC,MACpBH,EAAI,CAACI,MAAU;AACb,UAAMC,IAAU,IAAI,IAAID,EAAM,QAAQ;AACtC,WAAAC,EAAQ,IAAIH,GAAIC,CAAG,GACZ,EAAE,UAAUE,EAAA;AAAA,EACrB,CAAC;AAAA,EAEH,YAAY,CAACH,MAAOD,IAAM,SAAS,IAAIC,CAAE;AAAA,EAEzC,eAAe,CAACA,MACdF,EAAI,CAACI,MAAU;AACb,UAAMC,IAAU,IAAI,IAAID,EAAM,QAAQ;AACtC,WAAAC,EAAQ,OAAOH,CAAE,GACV,EAAE,UAAUG,EAAA;AAAA,EACrB,CAAC;AAAA;AAAA,EAGH,uBAAuB,CAACC,MAAa;AACnC,UAAMC,IAAUN,IAAM,UAChBO,IAAiBF,IAAW,KAC5BG,wBAAmB,IAAA;AAEzB,WAAAF,EAAQ,QAAQ,CAACJ,GAAKD,MAAO;AAC3B,OAAIA,EAAG,WAAWM,CAAc,KAAKN,MAAOI,MAC1CG,EAAa,IAAIP,GAAIC,CAAG;AAAA,IAE5B,CAAC,GAEMM;AAAA,EACT;AACF,EAAE,GA2MIC,IAAiB,CAACC,MAClBA,MAAU,QAAQ,OAAOA,KAAU,YAIrCA,aAAiB,cACjBA,aAAiB,aACjBA,aAAiB,eACjBA,aAAiB,cACjBA,aAAiB,eACjBA,aAAiB,cACjBA,aAAiB,gBACjBA,aAAiB,gBACjBA,aAAiB,eACjBA,aAAiB,QACjBA,aAAiB,UACjBA,aAAiB,OACjBA,aAAiB,MAEV,KAIF,MAAM,QAAQA,CAAK,KAAKA,EAAM,gBAAgB,QAE1CC,IAAiBb,EAAwB,CAACC,GAAKC,OAAS;AAAA,EACnE,iCAAiB,IAAA;AAAA;AAAA,EAEjB,kBAAkB;AAAA;AAAA,EAGlB,cAAc,MAAM;AAClB,UAAM,EAAE,aAAAY,EAAA,IAAgBZ,EAAA;AAExB,IAAIY,EAAY,OAAO,KACrBC,EAAgB,MAAM;AACpB,MAAAD,EAAY,QAAQ,CAACE,MAAaA,EAAA,CAAU;AAAA,IAC9C,CAAC,GAIHf,EAAI,EAAE,aAAa,oBAAI,OAAO,kBAAkB,IAAO;AAAA,EACzD;AAAA,EACA,kBAAkB,CAACM,GAAUU,GAAgBC,MAAoB;AAC/D,IAAAjB,EAAI,CAACI,MAAU;AACb,YAAMc,IAAiB,IAAI,IAAId,EAAM,gBAAgB,GAC/Ce,IAAgB,CAACb,GAAU,GAAGU,CAAc,EAAE,KAAK,GAAG,GAGtDI,IAAWF,EAAe,IAAIC,CAAa,KAAK,CAAA,GAEhDE,IAAiB,IAAI,IAAID,EAAS,cAAc;AACtD,MAAAC,EAAe,IAAIJ,CAAe,GAElCC,EAAe,IAAIC,GAAe,EAAE,GAAGC,GAAU,gBAAAC,GAAgB;AAGjE,YAAMC,IAAWJ,EAAe,IAAIZ,CAAQ,KAAK,CAAA,GAC3CiB,IAAYD,EAAS,YAAY,IAAIL,CAAe;AAG1D,UAAIM,GAAW;AACb,cAAMC,IAAW,IAAI,IAAID,EAAU,KAAK;AACxC,QAAAC,EAAS,IAAIL,CAAa;AAE1B,cAAMM,IAA2B,EAAE,GAAGF,GAAW,OAAOC,EAAA,GAClDE,IAAmB,IAAI,IAAIJ,EAAS,UAAU;AACpD,QAAAI,EAAiB,IAAIT,GAAiBQ,CAAwB,GAG9DP,EAAe,IAAIZ,GAAU;AAAA,UAC3B,GAAGgB;AAAA,UACH,YAAYI;AAAA,QAAA,CACb;AAAA,MACH;AAGA,aAAO,EAAE,kBAAkBR,EAAA;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EACA,mBAAmB,CAACZ,GAAUW,GAAiBU,MAAiB;AAC9D,IAAA3B,EAAI,CAACI,MAAU;AAEb,YAAMc,IAAiB,IAAI,IAAId,EAAM,gBAAgB,GAG/CkB,IAAWJ,EAAe,IAAIZ,CAAQ,KAAK,CAAA,GAG3CsB,IAAa,IAAI,IAAIN,EAAS,UAAU;AAC9C,aAAAM,EAAW,IAAIX,GAAiBU,CAAY,GAG5CT,EAAe,IAAIZ,GAAU,EAAE,GAAGgB,GAAU,YAAAM,GAAY,GAGjD,EAAE,kBAAkBV,EAAA;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EAEA,qBAAqB,CAACZ,GAAUW,MAAoB;AAClD,IAAAjB,EAAI,CAACI,MAAU;AACb,YAAMc,IAAiB,IAAI,IAAId,EAAM,gBAAgB,GAC/CkB,IAAWJ,EAAe,IAAIZ,CAAQ;AAG5C,UAAI,CAACgB,GAAU;AACb,eAAOlB;AAGT,YAAMwB,IAAa,IAAI,IAAIN,EAAS,UAAU;AAI9C,aAHmBM,EAAW,OAAOX,CAAe,KAIlDC,EAAe,IAAIZ,GAAU,EAAE,GAAGgB,GAAU,YAAAM,GAAY,GACjD,EAAE,kBAAkBV,EAAA,KAGtBd;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EACA,aAAa,CAACyB,GAAaC,GAAgBC,IAAU,EAAE,QAAQ,SAAW;AACxE,UAAMb,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB;AACrD,QAAI+B,IAAU;AAEd,UAAMC,IAAW,CAACC,MAA0B;AAC1C,YAAMC,IAAU,CAACN,GAAK,GAAGK,CAAW,EAAE,KAAK,GAAG,GACxCE,IAAOlB,EAAe,IAAIiB,CAAO;AAIvC,MAAIC,KAAQA,EAAK,YAAY,MAC3BlB,EAAe,IAAIiB,GAAS,EAAE,GAAGC,GAAM,SAAS,IAAM,GACtDJ,IAAU,MACAI,MAGVlB,EAAe,IAAIiB,GAAS,EAAE,SAAS,IAAM,GAC7CH,IAAU;AAAA,IAEd;AAMA,QAHAC,EAASH,CAAI,GAGTC,EAAQ,QAAQ;AAClB,UAAIM,IAAa,CAAC,GAAGP,CAAI;AACzB,aAAOO,EAAW,SAAS;AACzB,QAAAA,EAAW,IAAA,GACXJ,EAASI,CAAU;AAAA,IAEvB;AAEA,IAAIL,KACFhC,EAAI,EAAE,kBAAkBkB,GAAgB;AAAA,EAE5C;AAAA,EACA,wCAAwB,IAAA;AAAA,EACxB,sBAAsB,CAACW,GAAKS,MAAgB;AAC1C,IAAAtC,EAAI,CAACI,MAAU;AACb,YAAMmC,IAAS,IAAI,IAAInC,EAAM,kBAAkB;AAC/C,aAAAmC,EAAO,IAAIV,GAAKS,CAAW,GACpB,EAAE,oBAAoBC,EAAA;AAAA,IAC/B,CAAC,GAGDtC,EAAA,EAAM,sBAAsB4B,GAAK;AAAA,MAC/B,MAAM;AAAA,MACN,aAAAS;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EACA,sCAAsB,IAAA;AAAA,EACtB,eAAe,CAACT,MAAgB5B,IAAM,iBAAiB,IAAI4B,CAAG;AAAA,EAC9D,qCAAqB,IAAA;AAAA,EAErB,iBAAiB,CAACC,GAAMU,MAAa;AACnC,UAAMC,IAAcxC,IAAM,iBACpByC,IAAcD,EAAY,IAAIX,CAAI,yBAAS,IAAA;AACjD,WAAAY,EAAY,IAAIF,CAAQ,GACxBC,EAAY,IAAIX,GAAMY,CAAW,GAE1B,MAAM;AACX,YAAMC,IAAc1C,EAAA,EAAM,gBAAgB,IAAI6B,CAAI;AAClD,MAAIa,MACFA,EAAY,OAAOH,CAAQ,GACvBG,EAAY,SAAS,KACvB1C,IAAM,gBAAgB,OAAO6B,CAAI;AAAA,IAGvC;AAAA,EACF;AAAA,EAEA,uBAAuB,CAACc,GAAaC,MAAa;AAEhD,UAAMC,IADc7C,IAAM,gBACD,IAAI2C,CAAW;AAExC,IAAIE,KACFA,EAAK,QAAQ,CAACN,MAAaA,EAASK,CAAQ,CAAC;AAAA,EAEjD;AAAA,EAEA,uBAAuB,CAAChB,GAAakB,MAAsB;AACzD,IAAA/C,EAAI,CAACI,MAAU;AAEb,YAAMc,IAAiB,IAAI,IAAId,EAAM,gBAAgB,GAI/C4C,IADmB9B,EAAe,IAAIW,CAAG,GACD,YAGxCoB,IAAiBpB,IAAM;AAC7B,iBAAWqB,KAAK,MAAM,KAAKhC,EAAe,KAAA,CAAM;AAC9C,SAAIgC,MAAMrB,KAAOqB,EAAE,WAAWD,CAAc,MAC1C/B,EAAe,OAAOgC,CAAC;AAK3B,YAAMC,IAAe,CAACxC,GAAYmB,MAAmB;AACnD,cAAMsB,IAAU,CAACvB,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG;AAEvC,YAAI,MAAM,QAAQnB,CAAK,GAAG;AACxB,gBAAM0C,IAAqB,CAAA;AAC3B,UAAA1C,EAAM,QAAQ,MAAM;AAClB,kBAAM2C,IAAS,MAAMC,EAAA,CAAM;AAC3B,YAAAF,EAAS,KAAKD,IAAU,MAAME,CAAM;AAAA,UACtC,CAAC,GACDpC,EAAe,IAAIkC,GAAS,EAAE,WAAWC,GAAU,GACnD1C,EAAM,QAAQ,CAAC6C,GAAMC,MAAU;AAC7B,kBAAMH,IAASD,EAASI,CAAK,EAAG,MAAM,GAAG,EAAE,IAAA;AAC3C,YAAAN,EAAaK,GAAM,CAAC,GAAG1B,GAAOwB,CAAO,CAAC;AAAA,UACxC,CAAC;AAAA,QACH,WAAW5C,EAAeC,CAAK,GAAG;AAChC,gBAAM+C,IAAS,OAAO;AAAA,YACpB,OAAO,KAAK/C,CAAK,EAAE,IAAI,CAACuC,MAAM,CAACA,GAAGE,IAAU,MAAMF,CAAC,CAAC;AAAA,UAAA;AAEtD,UAAAhC,EAAe,IAAIkC,GAAS,EAAE,QAAAM,EAAA,CAAQ,GACtC,OAAO,KAAK/C,CAAK,EAAE,QAAQ,CAACuC,MAAM;AAChC,YAAAC,EAAaxC,EAAMuC,CAAC,GAAG,CAAC,GAAGpB,GAAMoB,CAAC,CAAC;AAAA,UACrC,CAAC;AAAA,QACH;AACE,UAAAhC,EAAe,IAAIkC,GAAS,EAAE,OAAAzC,EAAA,CAAO;AAAA,MAEzC;AAIA,UAHAwC,EAAaJ,GAAc,EAAE,GAGzBC,GAAqB;AACvB,cAAMW,IAAczC,EAAe,IAAIW,CAAG,KAAK,CAAA;AAC/C,QAAAX,EAAe,IAAIW,GAAK;AAAA,UACtB,GAAG8B;AAAA,UACH,YAAYX;AAAA,QAAA,CACb;AAAA,MACH;AAGA,aAAO,EAAE,kBAAkB9B,EAAA;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EAEA,gBAAgB,CAACiB,GAAiByB,MAA6B;AAE7D,UAAMC,wBAAW,IAAA,GAGXC,IAAc,CAACC,GAAoBC,MAAwB;AAG/D,UAAIH,EAAK,IAAIE,CAAU;AACrB,eAAOF,EAAK,IAAIE,CAAU;AAG5B,YAAME,IAAahE,EAAA,EAAM,iBAAiB,IAAI8D,CAAU;AAExD,UAAI,CAACE;AACH;AAGF,UAAIA,EAAW,UAAU;AACvB,eAAOA,EAAW;AAGpB,UAAIC;AAEJ,UAAID,EAAW,WAAW;AACxB,cAAME,IAAOH,KAAOC,EAAW;AAG/B,QAAAC,IAAS,CAAA,GACTL,EAAK,IAAIE,GAAYG,CAAM,GAE3BC,EAAK,QAAQ,CAACC,MAAY;AACxB,UAAAF,EAAO,KAAKJ,EAAYM,CAAO,CAAC;AAAA,QAClC,CAAC;AAAA,MACH,MAAA,CAAWH,EAAW,UAEpBC,IAAS,CAAA,GACTL,EAAK,IAAIE,GAAYG,CAAM,GAE3B,OAAO,QAAQD,EAAW,MAAM,EAAE,QAAQ,CAAC,CAACpC,GAAKwC,CAAS,MAAM;AAC9D,QAAAH,EAAOrC,CAAG,IAAIiC,EAAYO,CAAmB;AAAA,MAC/C,CAAC,KAEDH,IAAS;AAIX,aAAOA;AAAA,IACT;AAGA,WAAOJ,EAAY3B,GAASyB,CAAa;AAAA,EAC3C;AAAA,EACA,mBAAmB,CACjB/B,GACAC,GACA8B,MACG;AACH,UAAMzB,IAAU,CAACN,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG;AAC5B,WAAA7B,EAAA,EAAM,iBAAiB,IAAIkC,CAAO,GAEtClC,EAAA,EAAM,iBAAiB,IAAIkC,CAAO;AAAA,EAC3C;AAAA,EAEA,mBAAmB,CAACN,GAAKC,GAAMwC,MAAa;AAC1C,UAAMnC,IAAU,CAACN,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG,GACjCyC,IAAetE,EAAA,EAAM,iBAAiB,IAAIkC,CAAO;AAKvD,IAAIoC,GAAc,cAAc,CAACD,EAAS,eACxC,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,IAAA,GAEF,QAAQ;AAAA,MACN,iDAAiDzC,CAAG,eAAeC,EAAK,KAAK,IAAI,CAAC;AAAA,IAAA,GAEpF,QAAQ;AAAA,MACN;AAAA,MACAyC,EAAa;AAAA,IAAA,GAEf,QAAQ;AAAA,MACN;AAAA,MACAD;AAAA,IAAA,GAEF,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,IAAA,GAEF,QAAQ,MAAA,GACR,QAAQ,SAAA;AAIV,UAAMpD,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB,GAC/CuE,IAAY,EAAE,GAAID,KAAgB,CAAA,GAAK,GAAGD,EAAA;AAChD,IAAApD,EAAe,IAAIiB,GAASqC,CAAS,GACrCxE,EAAI,EAAE,kBAAkBkB,GAAgB;AAAA,EAC1C;AAAA,EACA,mBAAmB,CACjBW,GACAC,GACA2C,GACAC,MACG;AACH,UAAMvC,IAAU,CAACN,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG,GACjCZ,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB,GAC/C0E,IAAWzD,EAAe,IAAIiB,CAAO,KAAK,CAAA;AAGhD,IAAKwC,EAAS,oBACZA,EAAS,sCAAsB,IAAA,IAIjCA,EAAS,gBAAgB,IAAIF,GAAUC,CAAS,GAGhDxD,EAAe,IAAIiB,GAASwC,CAAQ,GACpC3E,EAAI,EAAE,kBAAkBkB,GAAgB;AAAA,EAG1C;AAAA,EACA,0BAA0B,CACxBW,GACA+C,GACAC,MACG;AACH,UAAM3D,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB,GAC/C6E,IAAW,CAACjD,GAAK,GAAG+C,CAAS,EAAE,KAAK,GAAG,GACvCG,IAAa7D,EAAe,IAAI4D,CAAQ;AAE9C,QAAI,CAACC,KAAc,CAACA,EAAW,UAAW;AAE1C,UAAMC,IAAY,MAAMzB,EAAA,CAAM,IACxB0B,IAAcH,IAAW,MAAME,GAG/BE,IAAe,CAAC,GAAGH,EAAW,SAAS;AAC7C,IAAAG,EAAa,KAAKD,CAAW,GAC7B/D,EAAe,IAAI4D,GAAU,EAAE,GAAGC,GAAY,WAAWG,GAAc;AAGvE,UAAMC,IAAiB,CAACxE,GAAYmB,MAAmB;AACrD,YAAMsB,IAAU,CAACvB,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG;AAEvC,UAAI,OAAM,QAAQnB,CAAK,EAEvB,KAAW,OAAOA,KAAU,YAAYA,MAAU,MAAM;AAEtD,cAAM+C,IAAS,OAAO;AAAA,UACpB,OAAO,KAAK/C,CAAK,EAAE,IAAI,CAACuC,MAAM,CAACA,GAAGE,IAAU,MAAMF,CAAC,CAAC;AAAA,QAAA;AAEtD,QAAAhC,EAAe,IAAIkC,GAAS,EAAE,QAAAM,EAAA,CAAQ,GAGtC,OAAO,QAAQ/C,CAAK,EAAE,QAAQ,CAAC,CAACuC,GAAGkC,CAAC,MAAM;AACxC,UAAAD,EAAeC,GAAG,CAAC,GAAGtD,GAAMoB,CAAC,CAAC;AAAA,QAChC,CAAC;AAAA,MACH;AAEE,QAAAhC,EAAe,IAAIkC,GAAS,EAAE,OAAAzC,EAAA,CAAO;AAAA,IAEzC;AAEA,IAAAwE,EAAeN,GAAS,CAAC,GAAGD,GAAWI,CAAS,CAAC,GACjDhF,EAAI,EAAE,kBAAkBkB,GAAgB,GAExCjB,EAAA,EAAM,sBAAsB6E,GAAU;AAAA,MACpC,MAAM;AAAA,MACN,MAAMA;AAAA,MACN,SAASG;AAAA,IAAA,CACV;AAAA,EACH;AAAA,EACA,0BAA0B,CAACpD,GAAawD,MAAuB;AAC7D,UAAMnE,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB,GAG/CmE,IAAU,CAACvC,GAAK,GAAGwD,CAAQ,EAAE,KAAK,GAAG,GAGrChD,IAAagD,EAAS,MAAM,GAAG,EAAE,GACjCC,IAAY,CAACzD,GAAK,GAAGQ,CAAU,EAAE,KAAK,GAAG,GAGzC0C,IAAa7D,EAAe,IAAIoE,CAAS;AAE/C,QAAIP,KAAcA,EAAW,aAELA,EAAW,UAAU;AAAA,MACzC,CAACQ,MAAiBA,MAAiBnB;AAAA,IAAA,MAGf,IAAI;AAExB,YAAMc,IAAeH,EAAW,UAAU;AAAA,QACxC,CAACQ,MAAiBA,MAAiBnB;AAAA,MAAA;AAIrC,MAAAlD,EAAe,IAAIoE,GAAW;AAAA,QAC5B,GAAGP;AAAA,QACH,WAAWG;AAAA,MAAA,CACZ;AAGD,YAAMjC,IAAiBmB,IAAU;AACjC,iBAAWlB,KAAK,MAAM,KAAKhC,EAAe,KAAA,CAAM;AAC9C,SAAIgC,MAAMkB,KAAWlB,EAAE,WAAWD,CAAc,MAC9C/B,EAAe,OAAOgC,CAAC;AAAA,IAG7B;AAGF,IAAAlD,EAAI,EAAE,kBAAkBkB,GAAgB,GAExCjB,EAAA,EAAM,sBAAsBqF,GAAW;AAAA,MACrC,MAAM;AAAA,MACN,MAAMA;AAAA,MACN,SAAAlB;AAAA;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EACA,oBAAoB,CAACvC,GAAKC,GAAMe,MAAa;AAC3C,UAAM3B,IAAiB,IAAI,IAAIjB,EAAA,EAAM,gBAAgB,GAC/CkC,IAAU,CAACN,GAAK,GAAGC,CAAI,EAAE,KAAK,GAAG,GAEjC0D,IAAc,CAACC,GAAoBC,MAAoB;AAC3D,YAAMtD,IAAOlB,EAAe,IAAIuE,CAAU;AAG1C,UAAI/E,EAAegF,CAAU,KAAKtD,KAAQA,EAAK;AAC7C,mBAAWuD,KAAYD;AACrB,cAAI,OAAO,UAAU,eAAe,KAAKA,GAAYC,CAAQ,GAAG;AAC9D,kBAAMC,IAAYxD,EAAK,OAAOuD,CAAQ,GAChCE,IAAaH,EAAWC,CAAQ;AAEtC,YAAIC,KACFJ,EAAYI,GAAqBC,CAAU;AAAA,UAE/C;AAAA,aAEG;AAGL,cAAMlB,IAAWzD,EAAe,IAAIuE,CAAU,KAAK,CAAA;AACnD,QAAAvE,EAAe,IAAIuE,GAAY,EAAE,GAAGd,GAAU,OAAOe,GAAY;AAAA,MACnE;AAAA,IACF;AAEA,IAAAF,EAAYrD,GAASU,CAAQ,GAC7B5C,EAAA,EAAM,sBAAsBkC,GAAS,EAAE,MAAM,UAAU,UAAAU,GAAU,GACjE7C,EAAI,EAAE,kBAAkBkB,GAAgB;AAAA,EAC1C;AAAA,EACA,wCAAwB,IAAA;AAAA,EACxB,kBAAkB,CAAC4D,GAAkBgB,MAAgC;AACnE,UAAM1B,IAAUnE,EAAA,EAAM,mBAAmB,IAAI6E,CAAQ;AAErD,QAAI,CAACV,EAAS,QAAO;AAGrB,UAAM2B,IACJD,KACAlF,EAAe,SAAA,EAAW,kBAAkBkE,GAAU,CAAA,CAAE,GAAG;AAE7D,WAAKiB,IAEEA,EAAU,QAAQ3B,CAAO,IAFT;AAAA,EAGzB;AAAA,EAEA,kBAAkB,CAACU,GAAkBV,MAAgC;AACnE,IAAApE,EAAI,CAACI,MAAU;AACb,YAAMmC,IAASnC,EAAM;AAErB,aAAIgE,MAAY,SACd7B,EAAO,OAAOuC,CAAQ,KAElBvC,EAAO,IAAIuC,CAAQ,KACrB7E,EAAA,EAAM,sBAAsBsC,EAAO,IAAIuC,CAAQ,GAAI;AAAA,QACjD,MAAM;AAAA,MAAA,CACP,GAEHvC,EAAO,IAAIuC,GAAUV,CAAO,GAE5BnE,EAAA,EAAM,sBAAsBmE,GAAS;AAAA,QACnC,MAAM;AAAA,MAAA,CACP,IAEHnE,EAAA,EAAM,sBAAsB6E,GAAU;AAAA,QACpC,MAAM;AAAA,MAAA,CACP,GACM;AAAA,QACL,GAAG1E;AAAA,QACH,oBAAoBmC;AAAA,MAAA;AAAA,IAExB,CAAC;AAAA,EACH;AAAA,EACA,oBAAoB,CAAC,EAAE,UAAAuC,QAA2C;AAChE,IAAA9E,EAAI,CAACI,MAAU;AACb,YAAMmC,IAASnC,EAAM,oBACf4F,IAAYzD,EAAO,IAAIuC,CAAQ;AACrC,aAAIkB,KACF/F,EAAA,EAAM,sBAAsB+F,GAAW;AAAA,QACrC,MAAM;AAAA,MAAA,CACP,GAGHzD,EAAO,OAAOuC,CAAQ,GACtB7E,EAAA,EAAM,sBAAsB6E,GAAU;AAAA,QACpC,MAAM;AAAA,MAAA,CACP,GACM;AAAA,QACL,GAAG1E;AAAA,QACH,oBAAoBmC;AAAA,MAAA;AAAA,IAExB,CAAC;AAAA,EACH;AAAA,EACA,8BAA8B,CAACjC,MAAqB;AAClD,IAAAN,EAAI,CAACI,MAAU;AACb,YAAM6F,IAAc,IAAI,IAAI7F,EAAM,kBAAkB;AAEpD,aADgB6F,EAAY,OAAO3F,CAAQ,IAElC,EAAE,oBAAoB2F,EAAA,IAEtB,CAAA;AAAA,IAEX,CAAC;AAAA,EACH;AAAA,EAEA,qBAAqB,CAAA;AAAA,EAErB,eAAe,CAAA;AAAA,EACf,gBAAgB,CAAA;AAAA,EAChB,8BAAc,IAAA;AAAA,EAEd,oBAAoB,CAAA;AAAA,EAEpB,sCAAsB,IAAA;AAAA,EACtB,aAAa,CAACpE,GAAKqE,MAAW;AAC5B,IAAAlG,EAAI,CAACI,MAAU;AACb,YAAM+F,IAAS,IAAI,IAAI/F,EAAM,QAAQ,GAC/BgG,IAAiB,IAAI,IAAID,EAAO,IAAItE,CAAG,CAAC,GACxCwE,IAAgB,KAAK,UAAUH,EAAO,IAAI,GAE1CvB,IAAWyB,EAAe,IAAIC,CAAa;AACjD,aAAI1B,KAEFA,EAAS,WAAWuB,EAAO,UAC3BvB,EAAS,YAAYuB,EAAO,aAG5BE,EAAe,IAAIC,GAAe,EAAE,GAAGH,GAAQ,GAGjDC,EAAO,IAAItE,GAAKuE,CAAc,GACvB,EAAE,UAAUD,EAAA;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,mBAAmB,CAACtE,MACX5B,EAAA,EAAM,oBAAoB4B,CAAG;AAAA,EAGtC,wBAAwB,CAACA,GAAKlB,MAAU;AACtC,IAAAX,EAAI,CAACsG,OAAU;AAAA,MACb,qBAAqB;AAAA,QACnB,GAAGA,EAAK;AAAA,QACR,CAACzE,CAAG,GAAGlB;AAAA,MAAA;AAAA,IACT,EACA;AAAA,EACJ;AAAA,EACA,0BAA0B,CAACkB,GAAK0E,MAAa;AAC3C,IAAAvG,EAAI,CAACsG,OAAU;AAAA,MACb,oBAAoB;AAAA,QAClB,GAAGA,EAAK;AAAA,QACR,CAACzE,CAAG,GAAG0E;AAAA,MAAA;AAAA,IACT,EACA;AAAA,EACJ;AAAA,EAEA,mCAAmB,IAAA;AAAA,EACnB,aAAa,CAAC1E,GAAa2E,MACzBxG,EAAI,CAACI,MAAU;AACb,UAAMmC,IAAS,IAAI,IAAInC,EAAM,aAAa;AAC1C,WAAAmC,EAAO,IAAIV,GAAK2E,CAAQ,GACjB,EAAE,GAAGpG,GAAO,eAAemC,EAAA;AAAA,EACpC,CAAC;AAAA,EACH,aAAa,CAACV,MAAgB5B,EAAA,EAAM,cAAc,IAAI4B,CAAG,KAAK;AAChE,EAAE;"}
|
|
1
|
+
{"version":3,"file":"store.js","sources":["../src/store.ts"],"sourcesContent":["import { create } from 'zustand';\r\nimport { ulid } from 'ulid';\r\nimport type {\r\n OptionsType,\r\n ReactivityType,\r\n StateKeys,\r\n SyncInfo,\r\n UpdateTypeDetail,\r\n} from './CogsState.js';\r\n\r\nimport { startTransition, type ReactNode } from 'react';\r\n\r\ntype StateUpdater<StateValue> =\r\n | StateValue\r\n | ((prevValue: StateValue) => StateValue);\r\n\r\nexport type FreshValuesObject = {\r\n pathsToValues?: string[];\r\n prevValue?: any;\r\n newValue?: any;\r\n timeStamp: number;\r\n};\r\n\r\ntype SyncLogType = {\r\n timeStamp: number;\r\n};\r\ntype StateValue = any;\r\n\r\nexport type TrieNode = {\r\n subscribers: Set<string>;\r\n children: Map<string, TrieNode>;\r\n};\r\n\r\nexport type FormRefStoreState = {\r\n formRefs: Map<string, React.RefObject<any>>;\r\n registerFormRef: (id: string, ref: React.RefObject<any>) => void;\r\n getFormRef: (id: string) => React.RefObject<any> | undefined;\r\n removeFormRef: (id: string) => void;\r\n // New method to get all refs for a stateKey\r\n getFormRefsByStateKey: (\r\n stateKey: string\r\n ) => Map<string, React.RefObject<any>>;\r\n};\r\n\r\nexport const formRefStore = create<FormRefStoreState>((set, get) => ({\r\n formRefs: new Map(),\r\n\r\n registerFormRef: (id, ref) =>\r\n set((state) => {\r\n const newRefs = new Map(state.formRefs);\r\n newRefs.set(id, ref);\r\n return { formRefs: newRefs };\r\n }),\r\n\r\n getFormRef: (id) => get().formRefs.get(id),\r\n\r\n removeFormRef: (id) =>\r\n set((state) => {\r\n const newRefs = new Map(state.formRefs);\r\n newRefs.delete(id);\r\n return { formRefs: newRefs };\r\n }),\r\n\r\n // Get all refs that start with the stateKey prefix\r\n getFormRefsByStateKey: (stateKey) => {\r\n const allRefs = get().formRefs;\r\n const stateKeyPrefix = stateKey + '.';\r\n const filteredRefs = new Map();\r\n\r\n allRefs.forEach((ref, id) => {\r\n if (id.startsWith(stateKeyPrefix) || id === stateKey) {\r\n filteredRefs.set(id, ref);\r\n }\r\n });\r\n\r\n return filteredRefs;\r\n },\r\n}));\r\nexport type ComponentsType = {\r\n components?: Map<\r\n string,\r\n {\r\n forceUpdate: () => void;\r\n paths: Set<string>;\r\n deps?: any[];\r\n prevDeps?: any[];\r\n depsFunction?: (state: any) => any[] | true;\r\n reactiveType: ReactivityType[] | ReactivityType;\r\n }\r\n >;\r\n};\r\nexport type ShadowMetadata = {\r\n id?: string;\r\n\r\n stateSource?: 'default' | 'server' | 'localStorage';\r\n lastServerSync?: number;\r\n isDirty?: boolean;\r\n baseServerState?: any;\r\n\r\n arrayKeys?: string[];\r\n\r\n fields?: Record<string, any>;\r\n virtualizer?: {\r\n itemHeight?: number;\r\n domRef?: HTMLElement | null;\r\n };\r\n syncInfo?: { status: string };\r\n validation?: ValidationState;\r\n lastUpdated?: number;\r\n value?: any;\r\n classSignals?: Array<{\r\n id: string;\r\n effect: string;\r\n lastClasses: string;\r\n deps: any[];\r\n }>;\r\n signals?: Array<{\r\n instanceId: string;\r\n parentId: string;\r\n position: number;\r\n effect?: string;\r\n }>;\r\n mapWrappers?: Array<{\r\n instanceId: string;\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n mapFn: (\r\n setter: any,\r\n index: number,\r\n\r\n arraySetter: any\r\n ) => ReactNode;\r\n containerRef: HTMLDivElement | null;\r\n rebuildStateShape: any;\r\n }>;\r\n transformCaches?: Map<\r\n string,\r\n {\r\n validIds: string[];\r\n computedAt: number;\r\n transforms: Array<{ type: 'filter' | 'sort'; fn: Function }>;\r\n }\r\n >;\r\n pathComponents?: Set<string>;\r\n streams?: Map<\r\n string,\r\n {\r\n buffer: any[];\r\n flushTimer: NodeJS.Timeout | null;\r\n }\r\n >;\r\n} & ComponentsType;\r\n\r\nexport type ValidationStatus =\r\n | 'PRISTINE' // Untouched, matches initial state.\r\n | 'DIRTY' // Changed, but no validation run yet.\r\n | 'VALID_LIVE' // Valid while typing.\r\n | 'INVALID_LIVE' // Gentle error during typing.\r\n | 'VALIDATION_FAILED' // Hard error on blur/submit.\r\n | 'VALID_PENDING_SYNC' // Passed validation, ready for sync.\r\n | 'SYNCING' // Actively being sent to the server.\r\n | 'SYNCED' // Server confirmed success.\r\n | 'SYNC_FAILED'; // Server rejected the data.\r\n\r\nexport type ValidationState = {\r\n status: ValidationStatus;\r\n message?: string;\r\n lastValidated?: number;\r\n validatedValue?: any;\r\n};\r\nexport type CogsEvent =\r\n | { type: 'INSERT'; path: string; itemKey: string; index: number }\r\n | { type: 'REMOVE'; path: string; itemKey: string }\r\n | { type: 'UPDATE'; path: string; newValue: any }\r\n | { type: 'ITEMHEIGHT'; itemKey: string; height: number }\r\n | { type: 'RELOAD'; path: string };\r\nexport type CogsGlobalState = {\r\n updateQueue: Set<() => void>;\r\n isFlushScheduled: boolean;\r\n\r\n flushUpdates: () => void;\r\n\r\n // --- Shadow State and Subscription System ---\r\n registerComponent: (\r\n stateKey: string,\r\n componentId: string,\r\n registration: any\r\n ) => void;\r\n unregisterComponent: (stateKey: string, componentId: string) => void;\r\n addPathComponent: (\r\n stateKey: string,\r\n dependencyPath: string[],\r\n fullComponentId: string\r\n ) => void;\r\n shadowStateStore: Map<string, ShadowMetadata>;\r\n\r\n markAsDirty: (\r\n key: string,\r\n path: string[],\r\n options: { bubble: boolean }\r\n ) => void;\r\n // These method signatures stay the same\r\n initializeShadowState: (key: string, initialState: any) => void;\r\n updateShadowAtPath: (key: string, path: string[], newValue: any) => void;\r\n insertShadowArrayElement: (\r\n key: string,\r\n arrayPath: string[],\r\n newItem: any\r\n ) => void;\r\n removeShadowArrayElement: (key: string, arrayPath: string[]) => void;\r\n getShadowValue: (\r\n key: string,\r\n\r\n validArrayIds?: string[]\r\n ) => any;\r\n\r\n getShadowMetadata: (\r\n key: string,\r\n path: string[]\r\n ) => ShadowMetadata | undefined;\r\n setShadowMetadata: (\r\n key: string,\r\n path: string[],\r\n metadata: Omit<ShadowMetadata, 'id'>\r\n ) => void;\r\n setTransformCache: (\r\n key: string,\r\n path: string[],\r\n cacheKey: string,\r\n cacheData: any\r\n ) => void;\r\n\r\n pathSubscribers: Map<string, Set<(newValue: any) => void>>;\r\n subscribeToPath: (\r\n path: string,\r\n callback: (newValue: any) => void\r\n ) => () => void;\r\n notifyPathSubscribers: (updatedPath: string, newValue: any) => void;\r\n\r\n selectedIndicesMap: Map<string, string>; // stateKey -> (parentPath -> selectedIndex)\r\n getSelectedIndex: (stateKey: string, validArrayIds?: string[]) => number;\r\n setSelectedIndex: (key: string, itemKey: string) => void;\r\n clearSelectedIndex: ({ arrayKey }: { arrayKey: string }) => void;\r\n clearSelectedIndexesForState: (stateKey: string) => void;\r\n\r\n // --- Core State and Updaters ---\r\n\r\n initialStateOptions: { [key: string]: OptionsType };\r\n\r\n initialStateGlobal: { [key: string]: StateValue };\r\n\r\n updateInitialStateGlobal: (key: string, newState: StateValue) => void;\r\n\r\n getInitialOptions: (key: string) => OptionsType | undefined;\r\n setInitialStateOptions: (key: string, value: OptionsType) => void;\r\n\r\n serverStateUpdates: Map<\r\n string,\r\n {\r\n data: any;\r\n status: 'loading' | 'success' | 'error';\r\n timestamp: number;\r\n }\r\n >;\r\n\r\n setServerStateUpdate: (key: string, serverState: any) => void;\r\n\r\n stateLog: Map<string, Map<string, UpdateTypeDetail>>;\r\n syncInfoStore: Map<string, SyncInfo>;\r\n addStateLog: (key: string, update: UpdateTypeDetail) => void;\r\n\r\n setSyncInfo: (key: string, syncInfo: SyncInfo) => void;\r\n getSyncInfo: (key: string) => SyncInfo | null;\r\n};\r\nconst isSimpleObject = (value: any): boolean => {\r\n // Most common cases first\r\n if (value === null || typeof value !== 'object') return false;\r\n\r\n // Arrays are simple objects\r\n if (Array.isArray(value)) return true;\r\n\r\n // Plain objects second most common\r\n if (value.constructor === Object) return true;\r\n\r\n // Everything else is not simple\r\n return false;\r\n};\r\nexport const getGlobalStore = create<CogsGlobalState>((set, get) => ({\r\n updateQueue: new Set<() => void>(),\r\n // A flag to ensure we only schedule the flush once per event-loop tick.\r\n isFlushScheduled: false,\r\n\r\n // This function is called by queueMicrotask to execute all queued updates.\r\n flushUpdates: () => {\r\n const { updateQueue } = get();\r\n\r\n if (updateQueue.size > 0) {\r\n startTransition(() => {\r\n updateQueue.forEach((updateFn) => updateFn());\r\n });\r\n }\r\n\r\n // Clear the queue and reset the flag for the next event loop tick.\r\n set({ updateQueue: new Set(), isFlushScheduled: false });\r\n },\r\n addPathComponent: (stateKey, dependencyPath, fullComponentId) => {\r\n set((state) => {\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n const dependencyKey = [stateKey, ...dependencyPath].join('.');\r\n\r\n // --- Part 1: Update the path's own metadata ---\r\n const pathMeta = newShadowStore.get(dependencyKey) || {};\r\n // Create a *new* Set to ensure immutability\r\n const pathComponents = new Set(pathMeta.pathComponents);\r\n pathComponents.add(fullComponentId);\r\n // Update the metadata for the specific path\r\n newShadowStore.set(dependencyKey, { ...pathMeta, pathComponents });\r\n\r\n // --- Part 2: Update the component's own list of paths ---\r\n const rootMeta = newShadowStore.get(stateKey) || {};\r\n const component = rootMeta.components?.get(fullComponentId);\r\n\r\n // If the component exists, update its `paths` set immutably\r\n if (component) {\r\n const newPaths = new Set(component.paths);\r\n newPaths.add(dependencyKey);\r\n\r\n const newComponentRegistration = { ...component, paths: newPaths };\r\n const newComponentsMap = new Map(rootMeta.components);\r\n newComponentsMap.set(fullComponentId, newComponentRegistration);\r\n\r\n // Update the root metadata with the new components map\r\n newShadowStore.set(stateKey, {\r\n ...rootMeta,\r\n components: newComponentsMap,\r\n });\r\n }\r\n\r\n // Return the final, updated state\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n registerComponent: (stateKey, fullComponentId, registration) => {\r\n set((state) => {\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n const rootMeta = newShadowStore.get(stateKey) || {};\r\n const components = new Map(rootMeta.components);\r\n components.set(fullComponentId, registration);\r\n newShadowStore.set(stateKey, { ...rootMeta, components });\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n\r\n unregisterComponent: (stateKey, fullComponentId) => {\r\n set((state) => {\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n const rootMeta = newShadowStore.get(stateKey);\r\n if (!rootMeta?.components) {\r\n return state; // Return original state, no change needed\r\n }\r\n\r\n const components = new Map(rootMeta.components);\r\n const wasDeleted = components.delete(fullComponentId);\r\n\r\n // Only update state if something was actually deleted\r\n if (wasDeleted) {\r\n newShadowStore.set(stateKey, { ...rootMeta, components });\r\n return { shadowStateStore: newShadowStore };\r\n }\r\n\r\n return state; // Nothing changed\r\n });\r\n },\r\n markAsDirty: (key: string, path: string[], options = { bubble: true }) => {\r\n const { shadowStateStore } = get();\r\n const updates = new Map<string, ShadowMetadata>();\r\n\r\n const setDirty = (currentPath: string[]) => {\r\n const fullKey = [key, ...currentPath].join('.');\r\n const meta = shadowStateStore.get(fullKey) || {};\r\n\r\n // If already dirty, no need to update\r\n if (meta.isDirty === true) {\r\n return true; // Return true to indicate parent is dirty\r\n }\r\n\r\n updates.set(fullKey, { ...meta, isDirty: true });\r\n return false; // Not previously dirty\r\n };\r\n\r\n // Mark the target path\r\n setDirty(path);\r\n\r\n // Bubble up if requested\r\n if (options.bubble) {\r\n let parentPath = [...path];\r\n while (parentPath.length > 0) {\r\n parentPath.pop();\r\n const wasDirty = setDirty(parentPath);\r\n if (wasDirty) {\r\n break; // Stop bubbling if parent was already dirty\r\n }\r\n }\r\n }\r\n\r\n // Apply all updates at once\r\n if (updates.size > 0) {\r\n set((state) => {\r\n updates.forEach((meta, key) => {\r\n state.shadowStateStore.set(key, meta);\r\n });\r\n return state;\r\n });\r\n }\r\n },\r\n serverStateUpdates: new Map(),\r\n setServerStateUpdate: (key, serverState) => {\r\n set((state) => {\r\n const newMap = new Map(state.serverStateUpdates);\r\n newMap.set(key, serverState);\r\n return { serverStateUpdates: newMap };\r\n });\r\n\r\n // Notify all subscribers for this key\r\n get().notifyPathSubscribers(key, {\r\n type: 'SERVER_STATE_UPDATE',\r\n serverState,\r\n });\r\n },\r\n shadowStateStore: new Map(),\r\n getShadowNode: (key: string) => get().shadowStateStore.get(key),\r\n pathSubscribers: new Map<string, Set<(newValue: any) => void>>(),\r\n\r\n subscribeToPath: (path, callback) => {\r\n const subscribers = get().pathSubscribers;\r\n const subsForPath = subscribers.get(path) || new Set();\r\n subsForPath.add(callback);\r\n subscribers.set(path, subsForPath);\r\n\r\n return () => {\r\n const currentSubs = get().pathSubscribers.get(path);\r\n if (currentSubs) {\r\n currentSubs.delete(callback);\r\n if (currentSubs.size === 0) {\r\n get().pathSubscribers.delete(path);\r\n }\r\n }\r\n };\r\n },\r\n\r\n notifyPathSubscribers: (updatedPath, newValue) => {\r\n const subscribers = get().pathSubscribers;\r\n const subs = subscribers.get(updatedPath);\r\n\r\n if (subs) {\r\n subs.forEach((callback) => callback(newValue));\r\n }\r\n },\r\n\r\n initializeShadowState: (key: string, initialState: any) => {\r\n set((state) => {\r\n // 1. Make a copy of the current store to modify it\r\n const newShadowStore = new Map(state.shadowStateStore);\r\n console.log('initializeShadowState');\r\n // 2. PRESERVE the existing components map before doing anything else\r\n const existingRootMeta = newShadowStore.get(key);\r\n const preservedComponents = existingRootMeta?.components;\r\n\r\n // 3. Wipe all old shadow entries for this state key\r\n const prefixToDelete = key + '.';\r\n for (const k of Array.from(newShadowStore.keys())) {\r\n if (k === key || k.startsWith(prefixToDelete)) {\r\n newShadowStore.delete(k);\r\n }\r\n }\r\n\r\n // 4. Run your original logic to rebuild the state tree from scratch\r\n const processValue = (value: any, path: string[]) => {\r\n const nodeKey = [key, ...path].join('.');\r\n\r\n if (Array.isArray(value)) {\r\n const childIds: string[] = [];\r\n value.forEach(() => {\r\n const itemId = `id:${ulid()}`;\r\n childIds.push(nodeKey + '.' + itemId);\r\n });\r\n newShadowStore.set(nodeKey, { arrayKeys: childIds });\r\n value.forEach((item, index) => {\r\n const itemId = childIds[index]!.split('.').pop();\r\n processValue(item, [...path!, itemId!]);\r\n });\r\n } else if (isSimpleObject(value)) {\r\n const fields = Object.fromEntries(\r\n Object.keys(value).map((k) => [k, nodeKey + '.' + k])\r\n );\r\n newShadowStore.set(nodeKey, { fields });\r\n Object.keys(value).forEach((k) => {\r\n processValue(value[k], [...path, k]);\r\n });\r\n } else {\r\n newShadowStore.set(nodeKey, { value });\r\n }\r\n };\r\n processValue(initialState, []);\r\n\r\n // 5. RESTORE the preserved components map onto the new root metadata\r\n if (preservedComponents) {\r\n const newRootMeta = newShadowStore.get(key) || {};\r\n newShadowStore.set(key, {\r\n ...newRootMeta,\r\n components: preservedComponents,\r\n });\r\n }\r\n\r\n // 6. Return the completely updated state\r\n return { shadowStateStore: newShadowStore };\r\n });\r\n },\r\n\r\n getShadowValue: (fullKey: string, validArrayIds?: string[]) => {\r\n const memo = new Map<string, any>();\r\n const reconstruct = (keyToBuild: string, ids?: string[]): any => {\r\n if (memo.has(keyToBuild)) {\r\n return memo.get(keyToBuild);\r\n }\r\n\r\n const shadowMeta = get().shadowStateStore.get(keyToBuild);\r\n if (!shadowMeta) {\r\n return undefined;\r\n }\r\n\r\n if (shadowMeta.value !== undefined) {\r\n return shadowMeta.value;\r\n }\r\n\r\n let result: any; // The value we are about to build.\r\n\r\n if (shadowMeta.arrayKeys) {\r\n const keys = ids ?? shadowMeta.arrayKeys;\r\n result = [];\r\n memo.set(keyToBuild, result);\r\n keys.forEach((itemKey) => {\r\n result.push(reconstruct(itemKey));\r\n });\r\n } else if (shadowMeta.fields) {\r\n result = {};\r\n memo.set(keyToBuild, result);\r\n Object.entries(shadowMeta.fields).forEach(([key, fieldPath]) => {\r\n result[key] = reconstruct(fieldPath as string);\r\n });\r\n } else {\r\n result = undefined;\r\n }\r\n\r\n // Return the final, fully populated result.\r\n return result;\r\n };\r\n\r\n // Start the process by calling the inner function on the root key.\r\n return reconstruct(fullKey, validArrayIds);\r\n },\r\n getShadowMetadata: (key: string, path: string[]) => {\r\n const fullKey = [key, ...path].join('.');\r\n\r\n return get().shadowStateStore.get(fullKey);\r\n },\r\n\r\n setShadowMetadata: (key, path, metadata) => {\r\n const fullKey = [key, ...path].join('.');\r\n const existingMeta = get().shadowStateStore.get(fullKey);\r\n\r\n // --- THIS IS THE TRAP ---\r\n // If the existing metadata HAS a components map, but the NEW metadata DOES NOT,\r\n // it means we are about to wipe it out. This is the bug.\r\n if (existingMeta?.components && !metadata.components) {\r\n console.group(\r\n '%c🚨 RACE CONDITION DETECTED! 🚨',\r\n 'color: red; font-size: 18px; font-weight: bold;'\r\n );\r\n console.error(\r\n `An overwrite is about to happen on stateKey: \"${key}\" at path: [${path.join(', ')}]`\r\n );\r\n console.log(\r\n 'The EXISTING metadata had a components map:',\r\n existingMeta.components\r\n );\r\n console.log(\r\n 'The NEW metadata is trying to save WITHOUT a components map:',\r\n metadata\r\n );\r\n console.log(\r\n '%cStack trace to the function that caused this overwrite:',\r\n 'font-weight: bold;'\r\n );\r\n console.trace(); // This prints the call stack, leading you to the bad code.\r\n console.groupEnd();\r\n }\r\n // --- END OF TRAP ---\r\n\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const finalMeta = { ...(existingMeta || {}), ...metadata };\r\n newShadowStore.set(fullKey, finalMeta);\r\n set({ shadowStateStore: newShadowStore });\r\n },\r\n setTransformCache: (\r\n key: string,\r\n path: string[],\r\n cacheKey: string,\r\n cacheData: any\r\n ) => {\r\n const fullKey = [key, ...path].join('.');\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const existing = newShadowStore.get(fullKey) || {};\r\n\r\n // Initialize transformCaches if it doesn't exist\r\n if (!existing.transformCaches) {\r\n existing.transformCaches = new Map();\r\n }\r\n\r\n // Update just the specific cache entry\r\n existing.transformCaches.set(cacheKey, cacheData);\r\n\r\n // Update shadow store WITHOUT notifying path subscribers\r\n newShadowStore.set(fullKey, existing);\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n // Don't call notifyPathSubscribers here - cache updates shouldn't trigger renders\r\n },\r\n insertShadowArrayElement: (\r\n key: string,\r\n arrayPath: string[],\r\n newItem: any\r\n ) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n const arrayKey = [key, ...arrayPath].join('.');\r\n const parentMeta = newShadowStore.get(arrayKey);\r\n\r\n if (!parentMeta || !parentMeta.arrayKeys) return;\r\n\r\n const newItemId = `id:${ulid()}`;\r\n const fullItemKey = arrayKey + '.' + newItemId;\r\n\r\n // Just add to the end (or at a specific index if provided)\r\n const newArrayKeys = [...parentMeta.arrayKeys];\r\n newArrayKeys.push(fullItemKey); // Or use splice if you have an index\r\n newShadowStore.set(arrayKey, { ...parentMeta, arrayKeys: newArrayKeys });\r\n\r\n // Process the new item - but use the correct logic\r\n const processNewItem = (value: any, path: string[]) => {\r\n const nodeKey = [key, ...path].join('.');\r\n\r\n if (Array.isArray(value)) {\r\n // Handle arrays...\r\n } else if (typeof value === 'object' && value !== null) {\r\n // Create fields mapping\r\n const fields = Object.fromEntries(\r\n Object.keys(value).map((k) => [k, nodeKey + '.' + k])\r\n );\r\n newShadowStore.set(nodeKey, { fields });\r\n\r\n // Process each field\r\n Object.entries(value).forEach(([k, v]) => {\r\n processNewItem(v, [...path, k]);\r\n });\r\n } else {\r\n // Primitive value\r\n newShadowStore.set(nodeKey, { value });\r\n }\r\n };\r\n\r\n processNewItem(newItem, [...arrayPath, newItemId]);\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'INSERT',\r\n path: arrayKey,\r\n itemKey: fullItemKey,\r\n });\r\n },\r\n removeShadowArrayElement: (key: string, itemPath: string[]) => {\r\n const newShadowStore = new Map(get().shadowStateStore);\r\n\r\n // Get the full item key (e.g., \"stateKey.products.id:xxx\")\r\n const itemKey = [key, ...itemPath].join('.');\r\n\r\n // Extract parent path and item ID\r\n const parentPath = itemPath.slice(0, -1);\r\n const parentKey = [key, ...parentPath].join('.');\r\n\r\n // Get parent metadata\r\n const parentMeta = newShadowStore.get(parentKey);\r\n\r\n if (parentMeta && parentMeta.arrayKeys) {\r\n // Find the index of the item to remove\r\n const indexToRemove = parentMeta.arrayKeys.findIndex(\r\n (arrayItemKey) => arrayItemKey === itemKey\r\n );\r\n\r\n if (indexToRemove !== -1) {\r\n // Create new array keys with the item removed\r\n const newArrayKeys = parentMeta.arrayKeys.filter(\r\n (arrayItemKey) => arrayItemKey !== itemKey\r\n );\r\n\r\n // Update parent with new array keys\r\n newShadowStore.set(parentKey, {\r\n ...parentMeta,\r\n arrayKeys: newArrayKeys,\r\n });\r\n\r\n // Delete all data associated with the removed item\r\n const prefixToDelete = itemKey + '.';\r\n for (const k of Array.from(newShadowStore.keys())) {\r\n if (k === itemKey || k.startsWith(prefixToDelete)) {\r\n newShadowStore.delete(k);\r\n }\r\n }\r\n }\r\n }\r\n\r\n set({ shadowStateStore: newShadowStore });\r\n\r\n get().notifyPathSubscribers(parentKey, {\r\n type: 'REMOVE',\r\n path: parentKey,\r\n itemKey: itemKey, // The exact ID of the removed item\r\n });\r\n },\r\n\r\n updateShadowAtPath: (key, path, newValue) => {\r\n const fullKey = [key, ...path].join('.');\r\n\r\n // Optimization: Only update if value actually changed\r\n const existingMeta = get().shadowStateStore.get(fullKey);\r\n if (existingMeta?.value === newValue && !isSimpleObject(newValue)) {\r\n return; // Skip update for unchanged primitives\r\n }\r\n\r\n // CHANGE: Don't clone the entire Map, just update in place\r\n set((state) => {\r\n const store = state.shadowStateStore;\r\n\r\n if (!isSimpleObject(newValue)) {\r\n const meta = store.get(fullKey) || {};\r\n store.set(fullKey, { ...meta, value: newValue });\r\n } else {\r\n // Handle objects by iterating\r\n const processObject = (currentPath: string[], objectToSet: any) => {\r\n const currentFullKey = [key, ...currentPath].join('.');\r\n const meta = store.get(currentFullKey);\r\n\r\n if (meta && meta.fields) {\r\n for (const fieldKey in objectToSet) {\r\n if (Object.prototype.hasOwnProperty.call(objectToSet, fieldKey)) {\r\n const childValue = objectToSet[fieldKey];\r\n const childFullPath = meta.fields[fieldKey];\r\n\r\n if (childFullPath) {\r\n if (isSimpleObject(childValue)) {\r\n processObject(\r\n childFullPath.split('.').slice(1),\r\n childValue\r\n );\r\n } else {\r\n const existingChildMeta = store.get(childFullPath) || {};\r\n store.set(childFullPath, {\r\n ...existingChildMeta,\r\n value: childValue,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n };\r\n\r\n processObject(path, newValue);\r\n }\r\n\r\n // Only notify after all changes are made\r\n get().notifyPathSubscribers(fullKey, { type: 'UPDATE', newValue });\r\n\r\n // Return same reference if using Zustand's immer middleware\r\n return state;\r\n });\r\n },\r\n selectedIndicesMap: new Map<string, string>(),\r\n getSelectedIndex: (arrayKey: string, validIds?: string[]): number => {\r\n const itemKey = get().selectedIndicesMap.get(arrayKey);\r\n\r\n if (!itemKey) return -1;\r\n\r\n // Use validIds if provided (for filtered views), otherwise use all arrayKeys\r\n const arrayKeys =\r\n validIds ||\r\n getGlobalStore.getState().getShadowMetadata(arrayKey, [])?.arrayKeys;\r\n\r\n if (!arrayKeys) return -1;\r\n\r\n return arrayKeys.indexOf(itemKey);\r\n },\r\n\r\n setSelectedIndex: (arrayKey: string, itemKey: string | undefined) => {\r\n set((state) => {\r\n const newMap = state.selectedIndicesMap;\r\n\r\n if (itemKey === undefined) {\r\n newMap.delete(arrayKey);\r\n } else {\r\n if (newMap.has(arrayKey)) {\r\n get().notifyPathSubscribers(newMap.get(arrayKey)!, {\r\n type: 'THIS_UNSELECTED',\r\n });\r\n }\r\n newMap.set(arrayKey, itemKey);\r\n\r\n get().notifyPathSubscribers(itemKey, {\r\n type: 'THIS_SELECTED',\r\n });\r\n }\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'GET_SELECTED',\r\n });\r\n return {\r\n ...state,\r\n selectedIndicesMap: newMap,\r\n };\r\n });\r\n },\r\n clearSelectedIndex: ({ arrayKey }: { arrayKey: string }): void => {\r\n set((state) => {\r\n const newMap = state.selectedIndicesMap;\r\n const acutalKey = newMap.get(arrayKey);\r\n if (acutalKey) {\r\n get().notifyPathSubscribers(acutalKey, {\r\n type: 'CLEAR_SELECTION',\r\n });\r\n }\r\n\r\n newMap.delete(arrayKey);\r\n get().notifyPathSubscribers(arrayKey, {\r\n type: 'CLEAR_SELECTION',\r\n });\r\n return {\r\n ...state,\r\n selectedIndicesMap: newMap,\r\n };\r\n });\r\n },\r\n clearSelectedIndexesForState: (stateKey: string) => {\r\n set((state) => {\r\n const newOuterMap = new Map(state.selectedIndicesMap);\r\n const changed = newOuterMap.delete(stateKey);\r\n if (changed) {\r\n return { selectedIndicesMap: newOuterMap };\r\n } else {\r\n return {};\r\n }\r\n });\r\n },\r\n\r\n initialStateOptions: {},\r\n\r\n stateTimeline: {},\r\n cogsStateStore: {},\r\n stateLog: new Map(),\r\n\r\n initialStateGlobal: {},\r\n\r\n validationErrors: new Map(),\r\n addStateLog: (key, update) => {\r\n set((state) => {\r\n const newLog = new Map(state.stateLog);\r\n const stateLogForKey = new Map(newLog.get(key));\r\n const uniquePathKey = JSON.stringify(update.path);\r\n\r\n const existing = stateLogForKey.get(uniquePathKey);\r\n if (existing) {\r\n // If an update for this path already exists, just modify it. (Fast)\r\n existing.newValue = update.newValue;\r\n existing.timeStamp = update.timeStamp;\r\n } else {\r\n // Otherwise, add the new update. (Fast)\r\n stateLogForKey.set(uniquePathKey, { ...update });\r\n }\r\n\r\n newLog.set(key, stateLogForKey);\r\n return { stateLog: newLog };\r\n });\r\n },\r\n\r\n getInitialOptions: (key) => {\r\n return get().initialStateOptions[key];\r\n },\r\n\r\n setInitialStateOptions: (key, value) => {\r\n set((prev) => ({\r\n initialStateOptions: {\r\n ...prev.initialStateOptions,\r\n [key]: value,\r\n },\r\n }));\r\n },\r\n updateInitialStateGlobal: (key, newState) => {\r\n set((prev) => ({\r\n initialStateGlobal: {\r\n ...prev.initialStateGlobal,\r\n [key]: newState,\r\n },\r\n }));\r\n },\r\n\r\n syncInfoStore: new Map<string, SyncInfo>(),\r\n setSyncInfo: (key: string, syncInfo: SyncInfo) =>\r\n set((state) => {\r\n const newMap = new Map(state.syncInfoStore);\r\n newMap.set(key, syncInfo);\r\n return { ...state, syncInfoStore: newMap };\r\n }),\r\n getSyncInfo: (key: string) => get().syncInfoStore.get(key) || null,\r\n}));\r\n"],"names":["formRefStore","create","set","get","id","ref","state","newRefs","stateKey","allRefs","stateKeyPrefix","filteredRefs","isSimpleObject","value","getGlobalStore","updateQueue","startTransition","updateFn","dependencyPath","fullComponentId","newShadowStore","dependencyKey","pathMeta","pathComponents","rootMeta","component","newPaths","newComponentRegistration","newComponentsMap","registration","components","key","path","options","shadowStateStore","updates","setDirty","currentPath","fullKey","meta","parentPath","serverState","newMap","callback","subscribers","subsForPath","currentSubs","updatedPath","newValue","subs","initialState","preservedComponents","prefixToDelete","k","processValue","nodeKey","childIds","itemId","ulid","item","index","fields","newRootMeta","validArrayIds","memo","reconstruct","keyToBuild","ids","shadowMeta","result","keys","itemKey","fieldPath","metadata","existingMeta","finalMeta","cacheKey","cacheData","existing","arrayPath","newItem","arrayKey","parentMeta","newItemId","fullItemKey","newArrayKeys","processNewItem","v","itemPath","parentKey","arrayItemKey","store","processObject","objectToSet","currentFullKey","fieldKey","childValue","childFullPath","existingChildMeta","validIds","arrayKeys","acutalKey","newOuterMap","update","newLog","stateLogForKey","uniquePathKey","prev","newState","syncInfo"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -572,26 +572,21 @@ export const createCogsState = <State extends Record<StateKeys, unknown>>(
|
|
|
572
572
|
}
|
|
573
573
|
) => {
|
|
574
574
|
let newInitialState = initialState;
|
|
575
|
-
console.log('optsc', opt?.__useSync);
|
|
576
575
|
const [statePart, initialOptionsPart] =
|
|
577
576
|
transformStateFunc<State>(newInitialState);
|
|
578
577
|
|
|
579
|
-
// Store notifications if provided
|
|
580
578
|
if (opt?.__fromSyncSchema && opt?.__syncNotifications) {
|
|
581
579
|
getGlobalStore
|
|
582
580
|
.getState()
|
|
583
581
|
.setInitialStateOptions('__notifications', opt.__syncNotifications);
|
|
584
582
|
}
|
|
585
583
|
|
|
586
|
-
// Store apiParams map if provided
|
|
587
584
|
if (opt?.__fromSyncSchema && opt?.__apiParamsMap) {
|
|
588
585
|
getGlobalStore
|
|
589
586
|
.getState()
|
|
590
587
|
.setInitialStateOptions('__apiParamsMap', opt.__apiParamsMap);
|
|
591
588
|
}
|
|
592
589
|
|
|
593
|
-
// ... rest of your existing createCogsState code unchanged ...
|
|
594
|
-
|
|
595
590
|
Object.keys(statePart).forEach((key) => {
|
|
596
591
|
let existingOptions = initialOptionsPart[key] || {};
|
|
597
592
|
|
|
@@ -972,6 +967,8 @@ function markEntireStateAsServerSynced(
|
|
|
972
967
|
});
|
|
973
968
|
}
|
|
974
969
|
}
|
|
970
|
+
let updateBatchQueue = new Map<string, Array<UpdateArg<any>>>();
|
|
971
|
+
let batchFlushScheduled = false;
|
|
975
972
|
|
|
976
973
|
export function useCogsStateFn<TStateObject extends unknown>(
|
|
977
974
|
stateObject: TStateObject,
|
|
@@ -988,7 +985,6 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
988
985
|
dependencies,
|
|
989
986
|
serverState,
|
|
990
987
|
__useSync,
|
|
991
|
-
syncOptions,
|
|
992
988
|
}: {
|
|
993
989
|
stateKey?: string;
|
|
994
990
|
componentId?: string;
|
|
@@ -999,10 +995,8 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
999
995
|
) {
|
|
1000
996
|
const [reactiveForce, forceUpdate] = useState({}); //this is the key to reactivity
|
|
1001
997
|
const { sessionId } = useCogsConfig();
|
|
1002
|
-
|
|
1003
998
|
let noStateKey = stateKey ? false : true;
|
|
1004
999
|
const [thisKey] = useState(stateKey ?? uuidv4());
|
|
1005
|
-
|
|
1006
1000
|
const componentIdRef = useRef(componentId ?? uuidv4());
|
|
1007
1001
|
const latestInitialOptionsRef = useRef<OptionsType<TStateObject> | null>(
|
|
1008
1002
|
null
|
|
@@ -1012,9 +1006,6 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1012
1006
|
|
|
1013
1007
|
useEffect(() => {
|
|
1014
1008
|
if (syncUpdate && syncUpdate.stateKey === thisKey && syncUpdate.path?.[0]) {
|
|
1015
|
-
// Update the actual state value
|
|
1016
|
-
|
|
1017
|
-
// Create combined key and update sync info
|
|
1018
1009
|
const syncKey = `${syncUpdate.stateKey}:${syncUpdate.path.join('.')}`;
|
|
1019
1010
|
getGlobalStore.getState().setSyncInfo(syncKey, {
|
|
1020
1011
|
timeStamp: syncUpdate.timeStamp!,
|
|
@@ -1324,7 +1315,6 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1324
1315
|
updateObj: UpdateOptions
|
|
1325
1316
|
) => {
|
|
1326
1317
|
const fullPath = [thisKey, ...path].join('.');
|
|
1327
|
-
|
|
1328
1318
|
const store = getGlobalStore.getState();
|
|
1329
1319
|
|
|
1330
1320
|
const shadowMeta = store.getShadowMetadata(thisKey, path);
|
|
@@ -1354,12 +1344,8 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1354
1344
|
switch (updateObj.updateType) {
|
|
1355
1345
|
case 'insert': {
|
|
1356
1346
|
store.insertShadowArrayElement(thisKey, path, newUpdate.newValue);
|
|
1357
|
-
// The array at `path` has been modified. Mark it AND all its parents as dirty.
|
|
1358
1347
|
store.markAsDirty(thisKey, path, { bubble: true });
|
|
1359
|
-
|
|
1360
|
-
// ALSO mark the newly inserted item itself as dirty
|
|
1361
|
-
// Get the new item's path and mark it as dirty
|
|
1362
|
-
const arrayMeta = store.getShadowMetadata(thisKey, path);
|
|
1348
|
+
const arrayMeta = shadowMeta;
|
|
1363
1349
|
if (arrayMeta?.arrayKeys) {
|
|
1364
1350
|
const newItemKey =
|
|
1365
1351
|
arrayMeta.arrayKeys[arrayMeta.arrayKeys.length - 1];
|
|
@@ -1383,6 +1369,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1383
1369
|
break;
|
|
1384
1370
|
}
|
|
1385
1371
|
}
|
|
1372
|
+
|
|
1386
1373
|
const shouldSync = updateObj.sync !== false;
|
|
1387
1374
|
|
|
1388
1375
|
if (shouldSync && syncApiRef.current && syncApiRef.current.connected) {
|
|
@@ -1536,6 +1523,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1536
1523
|
});
|
|
1537
1524
|
}
|
|
1538
1525
|
}
|
|
1526
|
+
|
|
1539
1527
|
if (updateObj.updateType === 'cut') {
|
|
1540
1528
|
const arrayPath = path.slice(0, -1);
|
|
1541
1529
|
const arrayMeta = store.getShadowMetadata(thisKey, arrayPath);
|
|
@@ -1740,6 +1728,7 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1740
1728
|
}
|
|
1741
1729
|
});
|
|
1742
1730
|
notifiedComponents.clear();
|
|
1731
|
+
|
|
1743
1732
|
addStateLog(thisKey, newUpdate);
|
|
1744
1733
|
|
|
1745
1734
|
saveToLocalStorage(
|
|
@@ -1761,12 +1750,14 @@ export function useCogsStateFn<TStateObject extends unknown>(
|
|
|
1761
1750
|
}
|
|
1762
1751
|
|
|
1763
1752
|
const updaterFinal = useMemo(() => {
|
|
1764
|
-
|
|
1753
|
+
const handler = createProxyHandler<TStateObject>(
|
|
1765
1754
|
thisKey,
|
|
1766
1755
|
effectiveSetState,
|
|
1767
1756
|
componentIdRef.current,
|
|
1768
1757
|
sessionId
|
|
1769
1758
|
);
|
|
1759
|
+
|
|
1760
|
+
return handler;
|
|
1770
1761
|
}, [thisKey, sessionId]);
|
|
1771
1762
|
|
|
1772
1763
|
const cogsSyncFn = __useSync;
|
|
@@ -1813,12 +1804,9 @@ function hashTransforms(transforms: any[]) {
|
|
|
1813
1804
|
if (!transforms || transforms.length === 0) {
|
|
1814
1805
|
return '';
|
|
1815
1806
|
}
|
|
1816
|
-
// This creates a string representation of the transforms AND their dependencies.
|
|
1817
|
-
// Example: "filter['red']sort['score','asc']"
|
|
1818
1807
|
return transforms
|
|
1819
1808
|
.map(
|
|
1820
1809
|
(transform) =>
|
|
1821
|
-
// Safely stringify dependencies. An empty array becomes '[]'.
|
|
1822
1810
|
`${transform.type}${JSON.stringify(transform.dependencies || [])}`
|
|
1823
1811
|
)
|
|
1824
1812
|
.join('');
|
|
@@ -1861,8 +1849,6 @@ const registerComponentDependency = (
|
|
|
1861
1849
|
const fullComponentId = `${stateKey}////${componentId}`;
|
|
1862
1850
|
const { addPathComponent, getShadowMetadata } = getGlobalStore.getState();
|
|
1863
1851
|
|
|
1864
|
-
// First, check if the component should even be registered.
|
|
1865
|
-
// This check is safe to do outside the setter.
|
|
1866
1852
|
const rootMeta = getShadowMetadata(stateKey, []);
|
|
1867
1853
|
const component = rootMeta?.components?.get(fullComponentId);
|
|
1868
1854
|
|
|
@@ -1878,7 +1864,6 @@ const registerComponentDependency = (
|
|
|
1878
1864
|
return;
|
|
1879
1865
|
}
|
|
1880
1866
|
|
|
1881
|
-
// Now, call the single, safe, atomic function to perform the update.
|
|
1882
1867
|
addPathComponent(stateKey, dependencyPath, fullComponentId);
|
|
1883
1868
|
};
|
|
1884
1869
|
const notifySelectionComponents = (
|
|
@@ -1936,6 +1921,8 @@ function createProxyHandler<T>(
|
|
|
1936
1921
|
const proxyCache = new Map<string, any>();
|
|
1937
1922
|
let stateVersion = 0;
|
|
1938
1923
|
|
|
1924
|
+
let recursionTimerName: string | null = null;
|
|
1925
|
+
|
|
1939
1926
|
function rebuildStateShape({
|
|
1940
1927
|
path = [],
|
|
1941
1928
|
meta,
|
|
@@ -1949,10 +1936,13 @@ function createProxyHandler<T>(
|
|
|
1949
1936
|
? JSON.stringify(meta.validIds || meta.transforms)
|
|
1950
1937
|
: '';
|
|
1951
1938
|
const cacheKey = path.join('.') + ':' + derivationSignature;
|
|
1952
|
-
|
|
1939
|
+
console.log('PROXY CACHE KEY ', cacheKey);
|
|
1953
1940
|
if (proxyCache.has(cacheKey)) {
|
|
1941
|
+
console.log('PROXY CACHE HIT');
|
|
1954
1942
|
return proxyCache.get(cacheKey);
|
|
1955
1943
|
}
|
|
1944
|
+
const stateKeyPathKey = [stateKey, ...path].join('.');
|
|
1945
|
+
|
|
1956
1946
|
type CallableStateObject<T> = {
|
|
1957
1947
|
(): T;
|
|
1958
1948
|
} & {
|
|
@@ -1967,14 +1957,7 @@ function createProxyHandler<T>(
|
|
|
1967
1957
|
// This is a placeholder for the proxy.
|
|
1968
1958
|
|
|
1969
1959
|
const handler = {
|
|
1970
|
-
apply(target: any, thisArg: any, args: any[]) {
|
|
1971
|
-
//return getGlobalStore().getShadowValue(stateKey, path);
|
|
1972
|
-
},
|
|
1973
|
-
|
|
1974
1960
|
get(target: any, prop: string) {
|
|
1975
|
-
// V--------- THE CRUCIAL FIX IS HERE ---------V
|
|
1976
|
-
// This handles requests for internal functions on the proxy,
|
|
1977
|
-
// returning the function itself instead of treating it as state.
|
|
1978
1961
|
if (prop === '_rebuildStateShape') {
|
|
1979
1962
|
return rebuildStateShape;
|
|
1980
1963
|
}
|
|
@@ -3599,28 +3582,77 @@ function createProxyHandler<T>(
|
|
|
3599
3582
|
if (prop === '_path') return path;
|
|
3600
3583
|
if (prop === 'update') {
|
|
3601
3584
|
return (payload: UpdateArg<T>) => {
|
|
3602
|
-
//
|
|
3603
|
-
|
|
3585
|
+
// Check if we're in a React event handler
|
|
3586
|
+
const error = new Error();
|
|
3587
|
+
const stack = error.stack || '';
|
|
3588
|
+
const inReactEvent =
|
|
3589
|
+
stack.includes('onClick') ||
|
|
3590
|
+
stack.includes('dispatchEvent') ||
|
|
3591
|
+
stack.includes('batchedUpdates');
|
|
3592
|
+
|
|
3593
|
+
// Only batch if we're in a React event
|
|
3594
|
+
if (inReactEvent) {
|
|
3595
|
+
const batchKey = `${stateKey}.${path.join('.')}`;
|
|
3596
|
+
|
|
3597
|
+
// Schedule flush if not already scheduled
|
|
3598
|
+
if (!batchFlushScheduled) {
|
|
3599
|
+
updateBatchQueue.clear();
|
|
3600
|
+
batchFlushScheduled = true;
|
|
3601
|
+
|
|
3602
|
+
queueMicrotask(() => {
|
|
3603
|
+
// Process all batched updates
|
|
3604
|
+
for (const [key, updates] of updateBatchQueue) {
|
|
3605
|
+
const parts = key.split('.');
|
|
3606
|
+
const batchStateKey = parts[0];
|
|
3607
|
+
const batchPath = parts.slice(1);
|
|
3608
|
+
|
|
3609
|
+
// Compose all updates for this path
|
|
3610
|
+
const composedUpdate = updates.reduce(
|
|
3611
|
+
(composed, update) => {
|
|
3612
|
+
if (
|
|
3613
|
+
typeof update === 'function' &&
|
|
3614
|
+
typeof composed === 'function'
|
|
3615
|
+
) {
|
|
3616
|
+
// Compose functions
|
|
3617
|
+
return (state: any) => update(composed(state));
|
|
3618
|
+
}
|
|
3619
|
+
// If not functions, last one wins
|
|
3620
|
+
return update;
|
|
3621
|
+
}
|
|
3622
|
+
);
|
|
3623
|
+
|
|
3624
|
+
// Call effectiveSetState ONCE with composed update
|
|
3625
|
+
effectiveSetState(composedUpdate as any, batchPath, {
|
|
3626
|
+
updateType: 'update',
|
|
3627
|
+
});
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
updateBatchQueue.clear();
|
|
3631
|
+
batchFlushScheduled = false;
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
|
|
3635
|
+
// Add to batch
|
|
3636
|
+
const existing = updateBatchQueue.get(batchKey) || [];
|
|
3637
|
+
existing.push(payload);
|
|
3638
|
+
updateBatchQueue.set(batchKey, existing);
|
|
3639
|
+
} else {
|
|
3640
|
+
effectiveSetState(payload as any, path, { updateType: 'update' });
|
|
3641
|
+
}
|
|
3604
3642
|
|
|
3605
3643
|
return {
|
|
3606
|
-
/**
|
|
3607
|
-
* Marks this specific item, which was just updated, as 'synced' (not dirty).
|
|
3608
|
-
*/
|
|
3609
3644
|
synced: () => {
|
|
3610
|
-
// This function "remembers" the path of the item that was just updated.
|
|
3611
3645
|
const shadowMeta = getGlobalStore
|
|
3612
3646
|
.getState()
|
|
3613
3647
|
.getShadowMetadata(stateKey, path);
|
|
3614
3648
|
|
|
3615
|
-
// It updates ONLY the metadata for that specific item.
|
|
3616
3649
|
getGlobalStore.getState().setShadowMetadata(stateKey, path, {
|
|
3617
3650
|
...shadowMeta,
|
|
3618
|
-
isDirty: false,
|
|
3619
|
-
stateSource: 'server',
|
|
3620
|
-
lastServerSync: Date.now(),
|
|
3651
|
+
isDirty: false,
|
|
3652
|
+
stateSource: 'server',
|
|
3653
|
+
lastServerSync: Date.now(),
|
|
3621
3654
|
});
|
|
3622
3655
|
|
|
3623
|
-
// Force a re-render for components watching this path
|
|
3624
3656
|
const fullPath = [stateKey, ...path].join('.');
|
|
3625
3657
|
getGlobalStore.getState().notifyPathSubscribers(fullPath, {
|
|
3626
3658
|
type: 'SYNC_STATUS_CHANGE',
|
|
@@ -3633,13 +3665,10 @@ function createProxyHandler<T>(
|
|
|
3633
3665
|
|
|
3634
3666
|
if (prop === 'toggle') {
|
|
3635
3667
|
const currentValueAtPath = getGlobalStore
|
|
3636
|
-
.getState()
|
|
3637
|
-
.getShadowValue([stateKey, ...path].join('.'));
|
|
3638
|
-
const currentState = getGlobalStore
|
|
3639
3668
|
.getState()
|
|
3640
3669
|
.getShadowValue([stateKey, ...path].join('.'), meta?.validIds);
|
|
3641
|
-
|
|
3642
|
-
if (typeof
|
|
3670
|
+
|
|
3671
|
+
if (typeof currentValueAtPath != 'boolean') {
|
|
3643
3672
|
throw new Error('toggle() can only be used on boolean values');
|
|
3644
3673
|
}
|
|
3645
3674
|
return () => {
|
|
@@ -3676,6 +3705,7 @@ function createProxyHandler<T>(
|
|
|
3676
3705
|
|
|
3677
3706
|
const proxyInstance = new Proxy(baseFunction, handler);
|
|
3678
3707
|
proxyCache.set(cacheKey, proxyInstance);
|
|
3708
|
+
|
|
3679
3709
|
return proxyInstance;
|
|
3680
3710
|
}
|
|
3681
3711
|
|