cogsbox-state 0.5.475-canary.1 → 0.5.475-canary.10
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 +21 -37
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.jsx +926 -1058
- package/dist/CogsState.jsx.map +1 -1
- package/dist/Components.d.ts +5 -6
- package/dist/Components.d.ts.map +1 -1
- package/dist/Components.jsx +171 -164
- package/dist/Components.jsx.map +1 -1
- package/package.json +2 -2
- package/src/CogsState.tsx +105 -65
- package/src/Components.tsx +27 -14
package/dist/Components.jsx.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Components.jsx","sources":["../src/Components.tsx"],"sourcesContent":["import {\r\n FormElementParams,\r\n StateObject,\r\n UpdateTypeDetail,\r\n type FormOptsType,\r\n} from './CogsState';\r\nimport { pluginStore } from './pluginStore';\r\nimport {\r\n createMetadataContext,\r\n createScopedMetadataContext,\r\n toDeconstructedMethods,\r\n} from './plugins';\r\nimport React, {\r\n memo,\r\n RefObject,\r\n useCallback,\r\n useEffect,\r\n useLayoutEffect,\r\n useRef,\r\n useState,\r\n useMemo,\r\n} from 'react';\r\nimport { getGlobalStore, ValidationError, ValidationSeverity } from './store';\r\nimport { useInView } from 'react-intersection-observer';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport { isDeepEqual } from './utility';\r\nimport { runValidation } from './validation';\r\n\r\nconst {\r\n getInitialOptions,\r\n\r\n getShadowMetadata,\r\n setShadowMetadata,\r\n getShadowValue,\r\n\r\n registerComponent,\r\n unregisterComponent,\r\n\r\n notifyPathSubscribers,\r\n subscribeToPath,\r\n} = getGlobalStore.getState();\r\nconst { stateHandlers, notifyFormUpdate } = pluginStore.getState();\r\n\r\nexport type ValidationWrapperProps = {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n stateKey: string;\r\n children: React.ReactNode;\r\n};\r\n\r\nexport function ValidationWrapper({\r\n formOpts,\r\n path,\r\n stateKey,\r\n children,\r\n}: ValidationWrapperProps) {\r\n const { getInitialOptions, getShadowMetadata, getShadowValue } =\r\n getGlobalStore.getState();\r\n const thisStateOpts = getInitialOptions(stateKey!);\r\n\r\n const shadowMeta = getShadowMetadata(stateKey!, path);\r\n const validationState = shadowMeta?.validation;\r\n\r\n const status = validationState?.status || 'NOT_VALIDATED';\r\n\r\n const errors = (validationState?.errors || []).map((err) => ({\r\n ...err,\r\n path: path,\r\n })) as ValidationError[];\r\n const errorMessages = errors\r\n .filter((err) => err.severity === 'error')\r\n .map((err) => err.message);\r\n const warningMessages = errors\r\n .filter((err) => err.severity === 'warning')\r\n .map((err) => err.message);\r\n\r\n // Use first error, or first warning if no errors\r\n const message = errorMessages[0] || warningMessages[0];\r\n const primarySeverity: ValidationSeverity =\r\n errorMessages.length > 0\r\n ? 'error'\r\n : warningMessages.length > 0\r\n ? 'warning'\r\n : undefined;\r\n const { registeredPlugins } = pluginStore.getState();\r\n const pluginsApi: any = {};\r\n\r\n // We iterate over ALL registered plugins in the app.\r\n registeredPlugins.forEach((plugin) => {\r\n // A plugin is considered \"active\" for this state key if its name\r\n // exists as a key in the options (e.g., options.syncPlugin exists).\r\n if (thisStateOpts && thisStateOpts.hasOwnProperty(plugin.name)) {\r\n const pluginName = plugin.name;\r\n\r\n // Now we can safely build the API for this active plugin.\r\n const hookData = pluginStore\r\n .getState()\r\n .getHookResult(stateKey, pluginName);\r\n\r\n const scopedMetadata = createScopedMetadataContext(\r\n stateKey,\r\n pluginName,\r\n path\r\n );\r\n\r\n pluginsApi[pluginName] = {\r\n hookData,\r\n getFieldMetaData: scopedMetadata.getFieldMetaData,\r\n setFieldMetaData: scopedMetadata.setFieldMetaData,\r\n };\r\n }\r\n });\r\n return (\r\n <>\r\n {thisStateOpts?.formElements?.validation &&\r\n !formOpts?.validation?.disable ? (\r\n thisStateOpts.formElements!.validation!({\r\n children: (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n ),\r\n status, // Now passes the new ValidationStatus type\r\n message: formOpts?.validation?.hideMessage\r\n ? ''\r\n : formOpts?.validation?.message || message || '',\r\n severity: primarySeverity,\r\n hasErrors: errorMessages.length > 0,\r\n hasWarnings: warningMessages.length > 0,\r\n allErrors: errors,\r\n path: path,\r\n getData: () => getShadowValue(stateKey!, path),\r\n plugins: pluginsApi,\r\n })\r\n ) : (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n )}\r\n </>\r\n );\r\n}\r\nexport const MemoizedCogsItemWrapper = memo(\r\n ListItemWrapper,\r\n (prevProps, nextProps) => {\r\n // Re-render if any of these change:\r\n return (\r\n prevProps.itemPath.join('.') === nextProps.itemPath.join('.') &&\r\n prevProps.stateKey === nextProps.stateKey &&\r\n prevProps.itemComponentId === nextProps.itemComponentId &&\r\n prevProps.localIndex === nextProps.localIndex\r\n );\r\n }\r\n);\r\nexport function ListItemWrapper({\r\n stateKey,\r\n itemComponentId,\r\n itemPath,\r\n localIndex,\r\n arraySetter,\r\n rebuildStateShape,\r\n renderFn,\r\n}: {\r\n stateKey: string;\r\n itemComponentId: string;\r\n itemPath: string[];\r\n localIndex: number;\r\n arraySetter: any;\r\n\r\n rebuildStateShape: (options: {\r\n currentState: any;\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n }) => any;\r\n renderFn: (\r\n setter: any,\r\n index: number,\r\n\r\n arraySetter: any\r\n ) => React.ReactNode;\r\n}) {\r\n const [, forceUpdate] = useState({});\r\n const { ref: inViewRef, inView } = useInView();\r\n const elementRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const imagesLoaded = useImageLoaded(elementRef);\r\n const hasReportedInitialHeight = useRef(false);\r\n const fullKey = [stateKey, ...itemPath].join('.');\r\n useRegisterComponent(stateKey, itemComponentId, forceUpdate);\r\n\r\n const setRefs = useCallback(\r\n (element: HTMLDivElement | null) => {\r\n elementRef.current = element;\r\n inViewRef(element); // This is the ref from useInView\r\n },\r\n [inViewRef]\r\n );\r\n\r\n useEffect(() => {\r\n const unsubscribe = subscribeToPath(fullKey, (e) => {\r\n forceUpdate({});\r\n });\r\n return () => unsubscribe();\r\n }, [fullKey]);\r\n useEffect(() => {\r\n if (!inView || !imagesLoaded || hasReportedInitialHeight.current) {\r\n return;\r\n }\r\n\r\n const element = elementRef.current;\r\n if (element && element.offsetHeight > 0) {\r\n hasReportedInitialHeight.current = true;\r\n const newHeight = element.offsetHeight;\r\n\r\n setShadowMetadata(stateKey, itemPath, {\r\n virtualizer: {\r\n itemHeight: newHeight,\r\n domRef: element,\r\n },\r\n });\r\n\r\n const arrayPath = itemPath.slice(0, -1);\r\n const arrayPathKey = [stateKey, ...arrayPath].join('.');\r\n notifyPathSubscribers(arrayPathKey, {\r\n type: 'ITEMHEIGHT',\r\n itemKey: itemPath.join('.'),\r\n\r\n ref: elementRef.current,\r\n });\r\n }\r\n }, [inView, imagesLoaded, stateKey, itemPath]);\r\n\r\n const itemValue = getShadowValue(stateKey, itemPath);\r\n\r\n if (itemValue === undefined) {\r\n return null;\r\n }\r\n\r\n const itemSetter = rebuildStateShape({\r\n currentState: itemValue,\r\n path: itemPath,\r\n componentId: itemComponentId,\r\n });\r\n const children = renderFn(itemSetter, localIndex, arraySetter);\r\n\r\n return <div ref={setRefs}>{children}</div>;\r\n}\r\n\r\nexport function FormElementWrapper({\r\n stateKey,\r\n path,\r\n rebuildStateShape,\r\n renderFn,\r\n formOpts,\r\n setState,\r\n}: {\r\n stateKey: string;\r\n path: string[];\r\n rebuildStateShape: (options: {\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n }) => any;\r\n renderFn: (params: FormElementParams<any>) => React.ReactNode;\r\n formOpts?: FormOptsType;\r\n setState: any;\r\n}) {\r\n const componentId = useRef(uuidv4()).current;\r\n\r\n const [, forceUpdate] = useState({});\r\n const formElementRef = useRef<any>(null);\r\n const stateKeyPathKey = [stateKey, ...path].join('.');\r\n useRegisterComponent(stateKey, componentId, forceUpdate);\r\n // Get the shadow node to access typeInfo and schema\r\n const shadowNode = getGlobalStore.getState().getShadowNode(stateKey, path);\r\n const typeInfo = shadowNode?._meta?.typeInfo;\r\n\r\n const globalStateValue = getShadowValue(stateKey, path);\r\n const [localValue, setLocalValue] = useState<any>(globalStateValue);\r\n const isCurrentlyDebouncing = useRef(false);\r\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n useEffect(() => {\r\n if (\r\n !isCurrentlyDebouncing.current &&\r\n !isDeepEqual(globalStateValue, localValue)\r\n ) {\r\n setLocalValue(globalStateValue);\r\n }\r\n }, [globalStateValue]);\r\n\r\n useEffect(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Initialize clientActivityState if needed\r\n const currentMeta = getShadowMetadata(stateKey, path) || {};\r\n if (!currentMeta.clientActivityState) {\r\n currentMeta.clientActivityState = { elements: new Map() };\r\n }\r\n\r\n // Detect element type from the ref\r\n const detectElementType = () => {\r\n const el = formElementRef.current;\r\n if (!el) return 'input';\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName === 'textarea') return 'textarea';\r\n if (tagName === 'select') return 'select';\r\n if (tagName === 'input') {\r\n const type = (el as HTMLInputElement).type;\r\n if (type === 'checkbox') return 'checkbox';\r\n if (type === 'radio') return 'radio';\r\n if (type === 'range') return 'range';\r\n if (type === 'file') return 'file';\r\n }\r\n return 'input';\r\n };\r\n\r\n // Add this element to the Map\r\n currentMeta.clientActivityState.elements.set(componentId, {\r\n domRef: formElementRef,\r\n elementType: detectElementType(),\r\n inputType: formElementRef.current?.type,\r\n mountedAt: Date.now(),\r\n });\r\n\r\n setShadowMetadata(stateKey, path, currentMeta);\r\n\r\n // Subscribe to path updates\r\n const unsubscribe = getGlobalStore\r\n .getState()\r\n .subscribeToPath(stateKeyPathKey, (newValue) => {\r\n if (!isCurrentlyDebouncing.current && localValue !== newValue) {\r\n forceUpdate({});\r\n }\r\n });\r\n\r\n // Cleanup\r\n return () => {\r\n unsubscribe();\r\n\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n isCurrentlyDebouncing.current = false;\r\n }\r\n\r\n // Remove element from Map\r\n const meta = getGlobalStore.getState().getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements) {\r\n meta.clientActivityState.elements.delete(componentId);\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n };\r\n }, []);\r\n\r\n const debouncedUpdate = useCallback(\r\n (newValue: any) => {\r\n // Type conversion logic (keep existing)\r\n if (typeInfo) {\r\n if (typeInfo.type === 'number' && typeof newValue === 'string') {\r\n newValue =\r\n newValue === ''\r\n ? typeInfo.nullable\r\n ? null\r\n : (typeInfo.default ?? 0)\r\n : Number(newValue);\r\n } else if (\r\n typeInfo.type === 'boolean' &&\r\n typeof newValue === 'string'\r\n ) {\r\n newValue = newValue === 'true' || newValue === '1';\r\n } else if (typeInfo.type === 'date' && typeof newValue === 'string') {\r\n newValue = new Date(newValue);\r\n }\r\n } else {\r\n const currentType = typeof globalStateValue;\r\n if (currentType === 'number' && typeof newValue === 'string') {\r\n newValue = newValue === '' ? 0 : Number(newValue);\r\n }\r\n }\r\n\r\n setLocalValue(newValue);\r\n\r\n // Update input activity details\r\n const { getShadowMetadata, setShadowMetadata } =\r\n getGlobalStore.getState();\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId);\r\n if (element && element.currentActivity?.type === 'focus') {\r\n element!.currentActivity.details = {\r\n ...element!.currentActivity.details,\r\n value: newValue,\r\n previousValue:\r\n element!.currentActivity.details?.value || globalStateValue,\r\n inputLength:\r\n typeof newValue === 'string' ? newValue.length : undefined,\r\n keystrokeCount:\r\n (element!.currentActivity.details?.keystrokeCount || 0) + 1,\r\n };\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n }\r\n const element = meta?.clientActivityState?.elements?.get(componentId);\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'input', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n details: {\r\n value: newValue,\r\n inputLength:\r\n typeof newValue === 'string' ? newValue.length : undefined,\r\n isComposing: false, // You'd need to track this from the actual input event\r\n isPasting: false, // You'd need to track this from paste events\r\n keystrokeCount:\r\n (element?.currentActivity?.details?.keystrokeCount || 0) + 1,\r\n },\r\n });\r\n // Validation (keep existing)\r\n const virtualOperation: UpdateTypeDetail = {\r\n stateKey,\r\n path,\r\n newValue: newValue,\r\n updateType: 'update',\r\n timeStamp: Date.now(),\r\n status: 'new',\r\n oldValue: globalStateValue,\r\n };\r\n runValidation(virtualOperation, 'onChange');\r\n\r\n // Debounce state update (keep existing)\r\n isCurrentlyDebouncing.current = true;\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n }\r\n\r\n const debounceTime = formOpts?.debounceTime ?? 200;\r\n debounceTimeoutRef.current = setTimeout(() => {\r\n isCurrentlyDebouncing.current = false;\r\n setState(newValue, path, {\r\n updateType: 'update',\r\n validationTrigger: 'onChange',\r\n });\r\n }, debounceTime);\r\n },\r\n [\r\n setState,\r\n path,\r\n formOpts?.debounceTime,\r\n typeInfo,\r\n globalStateValue,\r\n stateKey,\r\n componentId,\r\n ]\r\n );\r\n\r\n const handleFocus = useCallback(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Update element's current activity\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId)!;\r\n element.currentActivity = {\r\n type: 'focus',\r\n startTime: Date.now(),\r\n details: {\r\n value: localValue,\r\n inputLength:\r\n typeof localValue === 'string' ? localValue.length : undefined,\r\n },\r\n };\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'focus', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n details: {\r\n cursorPosition: formElementRef.current?.selectionStart,\r\n },\r\n });\r\n }, [stateKey, path, componentId, localValue]);\r\n const handleBlur = useCallback(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Clear debounce if active\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n debounceTimeoutRef.current = null;\r\n isCurrentlyDebouncing.current = false;\r\n setState(localValue, path, {\r\n updateType: 'update',\r\n validationTrigger: 'onBlur',\r\n });\r\n }\r\n\r\n // Clear element's current activity\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId)!;\r\n element.currentActivity = undefined;\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n const focusStartTime =\r\n meta?.clientActivityState?.elements?.get(componentId)?.currentActivity\r\n ?.startTime;\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'blur', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n duration: focusStartTime ? Date.now() - focusStartTime : undefined,\r\n details: {\r\n duration: focusStartTime ? Date.now() - focusStartTime : 0,\r\n },\r\n });\r\n\r\n // Run validation if configured\r\n const validationOptions = getInitialOptions(stateKey)?.validation;\r\n if (validationOptions?.onBlur) {\r\n const virtualOperation: UpdateTypeDetail = {\r\n stateKey,\r\n path,\r\n newValue: localValue,\r\n updateType: 'update',\r\n timeStamp: Date.now(),\r\n status: 'new',\r\n oldValue: globalStateValue,\r\n };\r\n runValidation(virtualOperation, 'onBlur');\r\n }\r\n }, [localValue, setState, path, stateKey, componentId, globalStateValue]);\r\n\r\n const baseState = rebuildStateShape({\r\n path: path,\r\n componentId: componentId,\r\n meta: undefined,\r\n });\r\n\r\n const stateWithInputProps = new Proxy(baseState, {\r\n get(target, prop) {\r\n if (prop === '$inputProps') {\r\n return {\r\n value: localValue ?? '',\r\n onChange: (e: any) => {\r\n debouncedUpdate(e.target.value);\r\n },\r\n onFocus: handleFocus,\r\n onBlur: handleBlur,\r\n ref: formElementRef,\r\n };\r\n }\r\n\r\n return target[prop];\r\n },\r\n });\r\n\r\n const initialElement = renderFn(stateWithInputProps);\r\n\r\n return (\r\n <ValidationWrapper formOpts={formOpts} path={path} stateKey={stateKey}>\r\n {initialElement}\r\n </ValidationWrapper>\r\n );\r\n}\r\nexport function useRegisterComponent(\r\n stateKey: string,\r\n componentId: string,\r\n forceUpdate: (o: object) => void\r\n) {\r\n const fullComponentId = `${stateKey}////${componentId}`;\r\n\r\n useLayoutEffect(() => {\r\n // Call the safe, centralized function to register\r\n registerComponent(stateKey, fullComponentId, {\r\n forceUpdate: () => forceUpdate({}),\r\n paths: new Set(),\r\n reactiveType: ['component'],\r\n });\r\n\r\n // The cleanup now calls the safe, centralized unregister function\r\n return () => {\r\n unregisterComponent(stateKey, fullComponentId);\r\n };\r\n }, [stateKey, fullComponentId]); // Dependencies are stable and correct\r\n}\r\n\r\nconst useImageLoaded = (ref: RefObject<HTMLElement>): boolean => {\r\n const [loaded, setLoaded] = useState(false);\r\n\r\n useLayoutEffect(() => {\r\n if (!ref.current) {\r\n setLoaded(true);\r\n return;\r\n }\r\n\r\n const images = Array.from(ref.current.querySelectorAll('img'));\r\n\r\n // If there are no images, we are \"loaded\" immediately.\r\n if (images.length === 0) {\r\n setLoaded(true);\r\n return;\r\n }\r\n\r\n let loadedCount = 0;\r\n const handleImageLoad = () => {\r\n loadedCount++;\r\n if (loadedCount === images.length) {\r\n setLoaded(true);\r\n }\r\n };\r\n\r\n images.forEach((image) => {\r\n if (image.complete) {\r\n handleImageLoad();\r\n } else {\r\n image.addEventListener('load', handleImageLoad);\r\n image.addEventListener('error', handleImageLoad);\r\n }\r\n });\r\n\r\n return () => {\r\n images.forEach((image) => {\r\n image.removeEventListener('load', handleImageLoad);\r\n image.removeEventListener('error', handleImageLoad);\r\n });\r\n };\r\n }, [ref.current]);\r\n\r\n return loaded;\r\n};\r\n// Components.tsx\r\n\r\n// Generic isolated component wrapper\r\nexport function IsolatedComponentWrapper({\r\n stateKey,\r\n path,\r\n rebuildStateShape,\r\n renderFn,\r\n}: {\r\n stateKey: string;\r\n path: string[];\r\n rebuildStateShape: (options: {\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n }) => any;\r\n renderFn: (state: any) => React.ReactNode;\r\n}) {\r\n const [componentId] = useState(() => uuidv4());\r\n const [, forceUpdate] = useState({});\r\n\r\n const stateKeyPathKey = [stateKey, ...path].join('.');\r\n useRegisterComponent(stateKey, componentId, forceUpdate);\r\n\r\n useEffect(() => {\r\n const unsubscribe = getGlobalStore\r\n .getState()\r\n .subscribeToPath(stateKeyPathKey, () => {\r\n forceUpdate({});\r\n });\r\n return () => unsubscribe();\r\n }, [stateKeyPathKey]);\r\n\r\n const baseState = rebuildStateShape({\r\n path: path,\r\n componentId: componentId,\r\n meta: undefined,\r\n });\r\n\r\n return <>{renderFn(baseState)}</>;\r\n}\r\n\r\n// 1. Define the MINIMAL props needed.\r\ntype PluginWrapperProps = {\r\n children: React.ReactNode;\r\n stateKey: string;\r\n path: string[];\r\n pluginName: string;\r\n wrapperDepth: number;\r\n};\r\n\r\nconst PluginWrapper = memo(function PluginWrapper({\r\n children,\r\n stateKey,\r\n path,\r\n pluginName,\r\n wrapperDepth,\r\n}: PluginWrapperProps) {\r\n const [, forceUpdate] = useState({});\r\n\r\n useEffect(() => {\r\n const fullPathKey = [stateKey, ...path].join('.');\r\n const unsubscribe = getGlobalStore\r\n .getState()\r\n .subscribeToPath(fullPathKey, () => {\r\n forceUpdate({});\r\n });\r\n return unsubscribe;\r\n }, [stateKey, path]);\r\n\r\n const plugin = pluginStore\r\n .getState()\r\n .registeredPlugins.find((p) => p.name === pluginName);\r\n\r\n const stateHandler: StateObject<any> | undefined = pluginStore\r\n .getState()\r\n .stateHandlers.get(stateKey);\r\n\r\n const typeInfo = getGlobalStore.getState().getShadowNode(stateKey, path)\r\n ?._meta?.typeInfo;\r\n\r\n const options = pluginStore\r\n .getState()\r\n .pluginOptions.get(stateKey)\r\n ?.get(pluginName);\r\n\r\n const hookData = pluginStore.getState().getHookResult(stateKey, pluginName);\r\n\r\n if (!plugin?.formWrapper || !stateHandler) {\r\n return <>{children}</>;\r\n }\r\n\r\n const deconstructed = toDeconstructedMethods(stateHandler);\r\n const scopedMetadataContext = createScopedMetadataContext(\r\n stateKey,\r\n plugin.name,\r\n path\r\n );\r\n return plugin.formWrapper({\r\n element: children,\r\n path,\r\n stateKey,\r\n pluginName: plugin.name,\r\n ...deconstructed,\r\n\r\n ...scopedMetadataContext,\r\n options,\r\n hookData,\r\n fieldType: typeInfo?.type,\r\n wrapperDepth,\r\n });\r\n});\r\n"],"names":["getInitialOptions","getShadowMetadata","setShadowMetadata","getShadowValue","registerComponent","unregisterComponent","notifyPathSubscribers","subscribeToPath","getGlobalStore","stateHandlers","notifyFormUpdate","pluginStore","ValidationWrapper","formOpts","path","stateKey","children","thisStateOpts","validationState","status","errors","err","errorMessages","warningMessages","message","primarySeverity","registeredPlugins","pluginsApi","plugin","pluginName","hookData","scopedMetadata","createScopedMetadataContext","jsx","Fragment","React","MemoizedCogsItemWrapper","memo","ListItemWrapper","prevProps","nextProps","itemComponentId","itemPath","localIndex","arraySetter","rebuildStateShape","renderFn","forceUpdate","useState","inViewRef","inView","useInView","elementRef","useRef","imagesLoaded","useImageLoaded","hasReportedInitialHeight","fullKey","useRegisterComponent","setRefs","useCallback","element","useEffect","unsubscribe","e","newHeight","arrayPath","arrayPathKey","itemValue","itemSetter","FormElementWrapper","setState","componentId","uuidv4","formElementRef","stateKeyPathKey","typeInfo","globalStateValue","localValue","setLocalValue","isCurrentlyDebouncing","debounceTimeoutRef","isDeepEqual","currentMeta","detectElementType","el","tagName","type","newValue","meta","debouncedUpdate","runValidation","debounceTime","handleFocus","handleBlur","focusStartTime","baseState","stateWithInputProps","target","prop","initialElement","fullComponentId","useLayoutEffect","ref","loaded","setLoaded","images","loadedCount","handleImageLoad","image","IsolatedComponentWrapper","wrapperDepth","fullPathKey","p","stateHandler","options","deconstructed","toDeconstructedMethods","scopedMetadataContext"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Components.jsx","sources":["../src/Components.tsx"],"sourcesContent":["import {\r\n FormElementParams,\r\n StateObject,\r\n UpdateTypeDetail,\r\n type FormOptsType,\r\n} from './CogsState';\r\nimport { pluginStore } from './pluginStore';\r\nimport {\r\n createMetadataContext,\r\n createScopedMetadataContext,\r\n toDeconstructedMethods,\r\n} from './plugins';\r\nimport React, {\r\n memo,\r\n RefObject,\r\n useCallback,\r\n useEffect,\r\n useLayoutEffect,\r\n useRef,\r\n useState,\r\n useMemo,\r\n} from 'react';\r\nimport { getGlobalStore, ValidationError, ValidationSeverity } from './store';\r\nimport { useInView } from 'react-intersection-observer';\r\nimport { v4 as uuidv4 } from 'uuid';\r\nimport { isDeepEqual } from './utility';\r\nimport { runValidation } from './validation';\r\n\r\nconst {\r\n getInitialOptions,\r\n\r\n getShadowMetadata,\r\n setShadowMetadata,\r\n getShadowValue,\r\n\r\n registerComponent,\r\n unregisterComponent,\r\n\r\n notifyPathSubscribers,\r\n subscribeToPath,\r\n} = getGlobalStore.getState();\r\nconst { stateHandlers, notifyFormUpdate } = pluginStore.getState();\r\n\r\nexport type ValidationWrapperProps = {\r\n formOpts?: FormOptsType;\r\n path: string[];\r\n stateKey: string;\r\n children: React.ReactNode;\r\n};\r\n\r\nexport function ValidationWrapper({\r\n formOpts,\r\n path,\r\n stateKey,\r\n children,\r\n}: ValidationWrapperProps) {\r\n const { getInitialOptions, getShadowMetadata, getShadowValue } =\r\n getGlobalStore.getState();\r\n const thisStateOpts = getInitialOptions(stateKey!);\r\n\r\n const shadowMeta = getShadowMetadata(stateKey!, path);\r\n const validationState = shadowMeta?.validation;\r\n\r\n const status = validationState?.status || 'NOT_VALIDATED';\r\n\r\n const errors = (validationState?.errors || []).map((err) => ({\r\n ...err,\r\n path: path,\r\n })) as ValidationError[];\r\n const errorMessages = errors\r\n .filter((err) => err.severity === 'error')\r\n .map((err) => err.message);\r\n const warningMessages = errors\r\n .filter((err) => err.severity === 'warning')\r\n .map((err) => err.message);\r\n\r\n // Use first error, or first warning if no errors\r\n const message = errorMessages[0] || warningMessages[0];\r\n const primarySeverity: ValidationSeverity =\r\n errorMessages.length > 0\r\n ? 'error'\r\n : warningMessages.length > 0\r\n ? 'warning'\r\n : undefined;\r\n const { registeredPlugins } = pluginStore.getState();\r\n const pluginsApi: any = {};\r\n\r\n // We iterate over ALL registered plugins in the app.\r\n registeredPlugins.forEach((plugin) => {\r\n // A plugin is considered \"active\" for this state key if its name\r\n // exists as a key in the options (e.g., options.syncPlugin exists).\r\n if (thisStateOpts && thisStateOpts.hasOwnProperty(plugin.name)) {\r\n const pluginName = plugin.name;\r\n\r\n // Now we can safely build the API for this active plugin.\r\n const hookData = pluginStore\r\n .getState()\r\n .getHookResult(stateKey, pluginName);\r\n\r\n const scopedMetadata = createScopedMetadataContext(\r\n stateKey,\r\n pluginName,\r\n path\r\n );\r\n\r\n pluginsApi[pluginName] = {\r\n hookData,\r\n getFieldMetaData: scopedMetadata.getFieldMetaData,\r\n setFieldMetaData: scopedMetadata.setFieldMetaData,\r\n };\r\n }\r\n });\r\n return (\r\n <>\r\n {thisStateOpts?.formElements?.validation &&\r\n !formOpts?.validation?.disable ? (\r\n thisStateOpts.formElements!.validation!({\r\n children: (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n ),\r\n status, // Now passes the new ValidationStatus type\r\n message: formOpts?.validation?.hideMessage\r\n ? ''\r\n : formOpts?.validation?.message || message || '',\r\n severity: primarySeverity,\r\n hasErrors: errorMessages.length > 0,\r\n hasWarnings: warningMessages.length > 0,\r\n allErrors: errors,\r\n path: path,\r\n getData: () => getShadowValue(stateKey!, path),\r\n plugins: pluginsApi,\r\n })\r\n ) : (\r\n <React.Fragment key={path.toString()}>{children}</React.Fragment>\r\n )}\r\n </>\r\n );\r\n}\r\nexport const MemoizedCogsItemWrapper = memo(\r\n ListItemWrapper,\r\n (prevProps, nextProps) => {\r\n // Re-render if any of these change:\r\n return (\r\n prevProps.itemPath.join('.') === nextProps.itemPath.join('.') &&\r\n prevProps.stateKey === nextProps.stateKey &&\r\n prevProps.itemComponentId === nextProps.itemComponentId &&\r\n prevProps.localIndex === nextProps.localIndex\r\n );\r\n }\r\n);\r\nexport function ListItemWrapper({\r\n stateKey,\r\n itemComponentId,\r\n itemPath,\r\n localIndex,\r\n arraySetter,\r\n rebuildStateShape,\r\n renderFn,\r\n}: {\r\n stateKey: string;\r\n itemComponentId: string;\r\n itemPath: string[];\r\n localIndex: number;\r\n arraySetter: any;\r\n\r\n rebuildStateShape: (options: {\r\n currentState: any;\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n }) => any;\r\n renderFn: (\r\n setter: any,\r\n index: number,\r\n\r\n arraySetter: any\r\n ) => React.ReactNode;\r\n}) {\r\n const [, forceUpdate] = useState({});\r\n const { ref: inViewRef, inView } = useInView();\r\n const elementRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const imagesLoaded = useImageLoaded(elementRef);\r\n const hasReportedInitialHeight = useRef(false);\r\n const fullKey = [stateKey, ...itemPath].join('.');\r\n useRegisterComponent(stateKey, itemComponentId, forceUpdate);\r\n\r\n const setRefs = useCallback(\r\n (element: HTMLDivElement | null) => {\r\n elementRef.current = element;\r\n inViewRef(element); // This is the ref from useInView\r\n },\r\n [inViewRef]\r\n );\r\n\r\n useEffect(() => {\r\n const unsubscribe = subscribeToPath(fullKey, (e) => {\r\n forceUpdate({});\r\n });\r\n return () => unsubscribe();\r\n }, [fullKey]);\r\n useEffect(() => {\r\n if (!inView || !imagesLoaded || hasReportedInitialHeight.current) {\r\n return;\r\n }\r\n\r\n const element = elementRef.current;\r\n if (element && element.offsetHeight > 0) {\r\n hasReportedInitialHeight.current = true;\r\n const newHeight = element.offsetHeight;\r\n\r\n setShadowMetadata(stateKey, itemPath, {\r\n virtualizer: {\r\n itemHeight: newHeight,\r\n domRef: element,\r\n },\r\n });\r\n\r\n const arrayPath = itemPath.slice(0, -1);\r\n const arrayPathKey = [stateKey, ...arrayPath].join('.');\r\n notifyPathSubscribers(arrayPathKey, {\r\n type: 'ITEMHEIGHT',\r\n itemKey: itemPath.join('.'),\r\n\r\n ref: elementRef.current,\r\n });\r\n }\r\n }, [inView, imagesLoaded, stateKey, itemPath]);\r\n\r\n const itemValue = getShadowValue(stateKey, itemPath);\r\n\r\n if (itemValue === undefined) {\r\n return null;\r\n }\r\n\r\n const itemSetter = rebuildStateShape({\r\n currentState: itemValue,\r\n path: itemPath,\r\n componentId: itemComponentId,\r\n });\r\n const children = renderFn(itemSetter, localIndex, arraySetter);\r\n\r\n return <div ref={setRefs}>{children}</div>;\r\n}\r\n\r\nexport function FormElementWrapper({\r\n stateKey,\r\n path,\r\n rebuildStateShape,\r\n renderFn,\r\n formOpts,\r\n setState,\r\n}: {\r\n stateKey: string;\r\n path: string[];\r\n rebuildStateShape: (options: {\r\n path: string[];\r\n componentId: string;\r\n meta?: any;\r\n }) => any;\r\n renderFn: (params: FormElementParams<any>) => React.ReactNode;\r\n formOpts?: FormOptsType;\r\n setState: any;\r\n}) {\r\n const componentId = useRef(uuidv4()).current;\r\n\r\n const [, forceUpdate] = useState({});\r\n const formElementRef = useRef<any>(null);\r\n const stateKeyPathKey = [stateKey, ...path].join('.');\r\n useRegisterComponent(stateKey, componentId, forceUpdate);\r\n // Get the shadow node to access typeInfo and schema\r\n const shadowNode = getGlobalStore.getState().getShadowNode(stateKey, path);\r\n const typeInfo = shadowNode?._meta?.typeInfo;\r\n\r\n const globalStateValue = getShadowValue(stateKey, path);\r\n const [localValue, setLocalValue] = useState<any>(globalStateValue);\r\n const isCurrentlyDebouncing = useRef(false);\r\n const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n useEffect(() => {\r\n if (\r\n !isCurrentlyDebouncing.current &&\r\n !isDeepEqual(globalStateValue, localValue)\r\n ) {\r\n setLocalValue(globalStateValue);\r\n }\r\n }, [globalStateValue]);\r\n\r\n useEffect(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Initialize clientActivityState if needed\r\n const currentMeta = getShadowMetadata(stateKey, path) || {};\r\n if (!currentMeta.clientActivityState) {\r\n currentMeta.clientActivityState = { elements: new Map() };\r\n }\r\n\r\n // Detect element type from the ref\r\n const detectElementType = () => {\r\n const el = formElementRef.current;\r\n if (!el) return 'input';\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName === 'textarea') return 'textarea';\r\n if (tagName === 'select') return 'select';\r\n if (tagName === 'input') {\r\n const type = (el as HTMLInputElement).type;\r\n if (type === 'checkbox') return 'checkbox';\r\n if (type === 'radio') return 'radio';\r\n if (type === 'range') return 'range';\r\n if (type === 'file') return 'file';\r\n }\r\n return 'input';\r\n };\r\n\r\n // Add this element to the Map\r\n currentMeta.clientActivityState.elements.set(componentId, {\r\n domRef: formElementRef,\r\n elementType: detectElementType(),\r\n inputType: formElementRef.current?.type,\r\n mountedAt: Date.now(),\r\n });\r\n\r\n setShadowMetadata(stateKey, path, currentMeta);\r\n\r\n // Subscribe to path updates\r\n const unsubscribe = getGlobalStore\r\n .getState()\r\n .subscribeToPath(stateKeyPathKey, (newValue) => {\r\n if (!isCurrentlyDebouncing.current && localValue !== newValue) {\r\n forceUpdate({});\r\n }\r\n });\r\n\r\n // Cleanup\r\n return () => {\r\n unsubscribe();\r\n\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n isCurrentlyDebouncing.current = false;\r\n }\r\n\r\n // Remove element from Map\r\n const meta = getGlobalStore.getState().getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements) {\r\n meta.clientActivityState.elements.delete(componentId);\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n };\r\n }, []);\r\n\r\n const debouncedUpdate = useCallback(\r\n (newValue: any) => {\r\n // Type conversion logic (keep existing)\r\n if (typeInfo) {\r\n if (typeInfo.type === 'number' && typeof newValue === 'string') {\r\n newValue =\r\n newValue === ''\r\n ? typeInfo.nullable\r\n ? null\r\n : (typeInfo.default ?? 0)\r\n : Number(newValue);\r\n } else if (\r\n typeInfo.type === 'boolean' &&\r\n typeof newValue === 'string'\r\n ) {\r\n newValue = newValue === 'true' || newValue === '1';\r\n } else if (typeInfo.type === 'date' && typeof newValue === 'string') {\r\n newValue = new Date(newValue);\r\n }\r\n } else {\r\n const currentType = typeof globalStateValue;\r\n if (currentType === 'number' && typeof newValue === 'string') {\r\n newValue = newValue === '' ? 0 : Number(newValue);\r\n }\r\n }\r\n\r\n setLocalValue(newValue);\r\n\r\n // Update input activity details\r\n const { getShadowMetadata, setShadowMetadata } =\r\n getGlobalStore.getState();\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId);\r\n if (element && element.currentActivity?.type === 'focus') {\r\n element!.currentActivity.details = {\r\n ...element!.currentActivity.details,\r\n value: newValue,\r\n previousValue:\r\n element!.currentActivity.details?.value || globalStateValue,\r\n inputLength:\r\n typeof newValue === 'string' ? newValue.length : undefined,\r\n keystrokeCount:\r\n (element!.currentActivity.details?.keystrokeCount || 0) + 1,\r\n };\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n }\r\n const element = meta?.clientActivityState?.elements?.get(componentId);\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'input', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n details: {\r\n value: newValue,\r\n inputLength:\r\n typeof newValue === 'string' ? newValue.length : undefined,\r\n isComposing: false, // You'd need to track this from the actual input event\r\n isPasting: false, // You'd need to track this from paste events\r\n keystrokeCount:\r\n (element?.currentActivity?.details?.keystrokeCount || 0) + 1,\r\n },\r\n });\r\n // Validation (keep existing)\r\n const virtualOperation: UpdateTypeDetail = {\r\n stateKey,\r\n path,\r\n newValue: newValue,\r\n updateType: 'update',\r\n timeStamp: Date.now(),\r\n status: 'new',\r\n oldValue: globalStateValue,\r\n };\r\n runValidation(virtualOperation, 'onChange');\r\n\r\n // Debounce state update (keep existing)\r\n isCurrentlyDebouncing.current = true;\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n }\r\n\r\n const debounceTime = formOpts?.debounceTime ?? 200;\r\n debounceTimeoutRef.current = setTimeout(() => {\r\n isCurrentlyDebouncing.current = false;\r\n setState(newValue, path, {\r\n updateType: 'update',\r\n validationTrigger: 'onChange',\r\n });\r\n }, debounceTime);\r\n },\r\n [\r\n setState,\r\n path,\r\n formOpts?.debounceTime,\r\n typeInfo,\r\n globalStateValue,\r\n stateKey,\r\n componentId,\r\n ]\r\n );\r\n\r\n const handleFocus = useCallback(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Update element's current activity\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId)!;\r\n element.currentActivity = {\r\n type: 'focus',\r\n startTime: Date.now(),\r\n details: {\r\n value: localValue,\r\n inputLength:\r\n typeof localValue === 'string' ? localValue.length : undefined,\r\n },\r\n };\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'focus', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n details: {\r\n cursorPosition: formElementRef.current?.selectionStart,\r\n },\r\n });\r\n }, [stateKey, path, componentId, localValue]);\r\n const handleBlur = useCallback(() => {\r\n const { getShadowMetadata, setShadowMetadata } = getGlobalStore.getState();\r\n\r\n // Clear debounce if active\r\n if (debounceTimeoutRef.current) {\r\n clearTimeout(debounceTimeoutRef.current);\r\n debounceTimeoutRef.current = null;\r\n isCurrentlyDebouncing.current = false;\r\n setState(localValue, path, {\r\n updateType: 'update',\r\n validationTrigger: 'onBlur',\r\n });\r\n }\r\n\r\n // Clear element's current activity\r\n const meta = getShadowMetadata(stateKey, path);\r\n if (meta?.clientActivityState?.elements?.has(componentId)) {\r\n const element = meta.clientActivityState.elements.get(componentId)!;\r\n element.currentActivity = undefined;\r\n setShadowMetadata(stateKey, path, meta);\r\n }\r\n const focusStartTime =\r\n meta?.clientActivityState?.elements?.get(componentId)?.currentActivity\r\n ?.startTime;\r\n\r\n // Notify plugins\r\n notifyFormUpdate({\r\n stateKey,\r\n activityType: 'blur', // Changed from 'type'\r\n path,\r\n timestamp: Date.now(),\r\n duration: focusStartTime ? Date.now() - focusStartTime : undefined,\r\n details: {\r\n duration: focusStartTime ? Date.now() - focusStartTime : 0,\r\n },\r\n });\r\n\r\n // Run validation if configured\r\n const validationOptions = getInitialOptions(stateKey)?.validation;\r\n if (validationOptions?.onBlur) {\r\n const virtualOperation: UpdateTypeDetail = {\r\n stateKey,\r\n path,\r\n newValue: localValue,\r\n updateType: 'update',\r\n timeStamp: Date.now(),\r\n status: 'new',\r\n oldValue: globalStateValue,\r\n };\r\n runValidation(virtualOperation, 'onBlur');\r\n }\r\n }, [localValue, setState, path, stateKey, componentId, globalStateValue]);\r\n\r\n const baseState = rebuildStateShape({\r\n path: path,\r\n componentId: componentId,\r\n meta: undefined,\r\n });\r\n\r\n const stateWithInputProps = new Proxy(baseState, {\r\n get(target, prop) {\r\n if (prop === '$inputProps') {\r\n return {\r\n value: localValue ?? '',\r\n onChange: (e: any) => {\r\n debouncedUpdate(e.target.value);\r\n },\r\n onFocus: handleFocus,\r\n onBlur: handleBlur,\r\n ref: formElementRef,\r\n };\r\n }\r\n\r\n return target[prop];\r\n },\r\n });\r\n\r\n const initialElement = renderFn(stateWithInputProps);\r\n\r\n return (\r\n <ValidationWrapper formOpts={formOpts} path={path} stateKey={stateKey}>\r\n {initialElement}\r\n </ValidationWrapper>\r\n );\r\n}\r\nexport function useRegisterComponent(\r\n stateKey: string,\r\n componentId: string,\r\n forceUpdate: (o: object) => void\r\n) {\r\n const fullComponentId = `${stateKey}////${componentId}`;\r\n\r\n useLayoutEffect(() => {\r\n registerComponent(stateKey, fullComponentId, {\r\n forceUpdate: () => forceUpdate({}),\r\n paths: new Set(),\r\n reactiveType: ['component'],\r\n });\r\n return () => {\r\n unregisterComponent(stateKey, fullComponentId);\r\n };\r\n }, [stateKey, fullComponentId]);\r\n}\r\n\r\nconst useImageLoaded = (ref: RefObject<HTMLElement>): boolean => {\r\n const [loaded, setLoaded] = useState(false);\r\n\r\n useLayoutEffect(() => {\r\n if (!ref.current) {\r\n setLoaded(true);\r\n return;\r\n }\r\n\r\n const images = Array.from(ref.current.querySelectorAll('img'));\r\n\r\n // If there are no images, we are \"loaded\" immediately.\r\n if (images.length === 0) {\r\n setLoaded(true);\r\n return;\r\n }\r\n\r\n let loadedCount = 0;\r\n const handleImageLoad = () => {\r\n loadedCount++;\r\n if (loadedCount === images.length) {\r\n setLoaded(true);\r\n }\r\n };\r\n\r\n images.forEach((image) => {\r\n if (image.complete) {\r\n handleImageLoad();\r\n } else {\r\n image.addEventListener('load', handleImageLoad);\r\n image.addEventListener('error', handleImageLoad);\r\n }\r\n });\r\n\r\n return () => {\r\n images.forEach((image) => {\r\n image.removeEventListener('load', handleImageLoad);\r\n image.removeEventListener('error', handleImageLoad);\r\n });\r\n };\r\n }, [ref.current]);\r\n\r\n return loaded;\r\n};\r\n// Components.tsx\r\n\r\nexport function IsolatedComponentWrapper({\r\n stateKey,\r\n path, // The path of the parent node (e.g. ['form'])\r\n dependencies, // NEW: Optional array of Proxy objects or path arrays\r\n rebuildStateShape,\r\n renderFn,\r\n}: {\r\n stateKey: string;\r\n path: string[];\r\n dependencies?: any[]; // The explicit list of dependencies\r\n rebuildStateShape: (options: any) => any;\r\n renderFn: (state: any) => React.ReactNode;\r\n}) {\r\n const [componentId] = useState(() => uuidv4());\r\n const [, forceUpdate] = useState({});\r\n\r\n useRegisterComponent(stateKey, componentId, forceUpdate);\r\n\r\n const pathsToSubscribe = useMemo(() => {\r\n if (dependencies && dependencies.length > 0) {\r\n return dependencies.map((dep) => {\r\n console.log(dep, dep.$_path);\r\n return [stateKey, ...dep.$_path].join('.');\r\n });\r\n }\r\n\r\n return [[stateKey, ...path].join('.')];\r\n }, [stateKey, path, dependencies]);\r\n\r\n // 2. Subscribe to ALL calculated paths\r\n useEffect(() => {\r\n const store = getGlobalStore.getState();\r\n\r\n // Create an array of unsubscribe functions\r\n const unsubs = pathsToSubscribe.map((fullPathKey) => {\r\n return store.subscribeToPath(fullPathKey, () => {\r\n forceUpdate({});\r\n });\r\n });\r\n\r\n return () => {\r\n unsubs.forEach((unsub) => unsub());\r\n };\r\n }, [pathsToSubscribe]);\r\n\r\n const baseState = rebuildStateShape({\r\n path: path,\r\n componentId: componentId,\r\n meta: undefined,\r\n });\r\n\r\n return <>{renderFn(baseState)}</>;\r\n}\r\n// 1. Define the MINIMAL props needed.\r\ntype PluginWrapperProps = {\r\n children: React.ReactNode;\r\n stateKey: string;\r\n path: string[];\r\n pluginName: string;\r\n wrapperDepth: number;\r\n};\r\n\r\nconst PluginWrapper = memo(function PluginWrapper({\r\n children,\r\n stateKey,\r\n path,\r\n pluginName,\r\n wrapperDepth,\r\n}: PluginWrapperProps) {\r\n const [, forceUpdate] = useState({});\r\n\r\n useEffect(() => {\r\n const fullPathKey = [stateKey, ...path].join('.');\r\n const unsubscribe = getGlobalStore\r\n .getState()\r\n .subscribeToPath(fullPathKey, () => {\r\n forceUpdate({});\r\n });\r\n return unsubscribe;\r\n }, [stateKey, path]);\r\n\r\n const plugin = pluginStore\r\n .getState()\r\n .registeredPlugins.find((p) => p.name === pluginName);\r\n\r\n const stateHandler: StateObject<any> | undefined = pluginStore\r\n .getState()\r\n .stateHandlers.get(stateKey);\r\n\r\n const typeInfo = getGlobalStore.getState().getShadowNode(stateKey, path)\r\n ?._meta?.typeInfo;\r\n\r\n const options = pluginStore\r\n .getState()\r\n .pluginOptions.get(stateKey)\r\n ?.get(pluginName);\r\n\r\n const hookData = pluginStore.getState().getHookResult(stateKey, pluginName);\r\n\r\n if (!plugin?.formWrapper || !stateHandler) {\r\n return <>{children}</>;\r\n }\r\n\r\n const deconstructed = toDeconstructedMethods(stateHandler);\r\n const scopedMetadataContext = createScopedMetadataContext(\r\n stateKey,\r\n plugin.name,\r\n path\r\n );\r\n return plugin.formWrapper({\r\n element: children,\r\n path,\r\n stateKey,\r\n pluginName: plugin.name,\r\n ...deconstructed,\r\n\r\n ...scopedMetadataContext,\r\n options,\r\n hookData,\r\n fieldType: typeInfo?.type,\r\n wrapperDepth,\r\n });\r\n});\r\n"],"names":["getInitialOptions","getShadowMetadata","setShadowMetadata","getShadowValue","registerComponent","unregisterComponent","notifyPathSubscribers","subscribeToPath","getGlobalStore","stateHandlers","notifyFormUpdate","pluginStore","ValidationWrapper","formOpts","path","stateKey","children","thisStateOpts","validationState","status","errors","err","errorMessages","warningMessages","message","primarySeverity","registeredPlugins","pluginsApi","plugin","pluginName","hookData","scopedMetadata","createScopedMetadataContext","jsx","Fragment","React","MemoizedCogsItemWrapper","memo","ListItemWrapper","prevProps","nextProps","itemComponentId","itemPath","localIndex","arraySetter","rebuildStateShape","renderFn","forceUpdate","useState","inViewRef","inView","useInView","elementRef","useRef","imagesLoaded","useImageLoaded","hasReportedInitialHeight","fullKey","useRegisterComponent","setRefs","useCallback","element","useEffect","unsubscribe","e","newHeight","arrayPath","arrayPathKey","itemValue","itemSetter","FormElementWrapper","setState","componentId","uuidv4","formElementRef","stateKeyPathKey","typeInfo","globalStateValue","localValue","setLocalValue","isCurrentlyDebouncing","debounceTimeoutRef","isDeepEqual","currentMeta","detectElementType","el","tagName","type","newValue","meta","debouncedUpdate","runValidation","debounceTime","handleFocus","handleBlur","focusStartTime","baseState","stateWithInputProps","target","prop","initialElement","fullComponentId","useLayoutEffect","ref","loaded","setLoaded","images","loadedCount","handleImageLoad","image","IsolatedComponentWrapper","dependencies","pathsToSubscribe","useMemo","dep","store","unsubs","fullPathKey","unsub","wrapperDepth","p","stateHandler","options","deconstructed","toDeconstructedMethods","scopedMetadataContext"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogsbox-state",
|
|
3
|
-
"version": "0.5.475-canary.
|
|
3
|
+
"version": "0.5.475-canary.10",
|
|
4
4
|
"description": "React state management library with form controls and server sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@trpc/next": "^10.0.0 || ^11.0.0",
|
|
51
|
-
"@types/react": "^18.0.0",
|
|
51
|
+
"@types/react": "^18.0.0 || ^19.0.0",
|
|
52
52
|
"zod": "^3.25.0 || ^4.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
package/src/CogsState.tsx
CHANGED
|
@@ -221,7 +221,7 @@ export type EndType<
|
|
|
221
221
|
errors: ValidationError[],
|
|
222
222
|
source?: 'client' | 'sync_engine' | 'api'
|
|
223
223
|
) => void;
|
|
224
|
-
$
|
|
224
|
+
$clearValidation: (paths?: string[]) => void;
|
|
225
225
|
$applyOperation: (
|
|
226
226
|
operation: UpdateTypeDetail,
|
|
227
227
|
metaData?: Record<string, any>
|
|
@@ -230,9 +230,18 @@ export type EndType<
|
|
|
230
230
|
$update: UpdateType<T>;
|
|
231
231
|
$_path: string[];
|
|
232
232
|
$_stateKey: string;
|
|
233
|
-
$isolate:
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
$isolate: {
|
|
234
|
+
// Overload 1: Just the render function (Default behavior)
|
|
235
|
+
(
|
|
236
|
+
renderFn: (state: StateObject<T, TPlugins>) => React.ReactNode
|
|
237
|
+
): JSX.Element;
|
|
238
|
+
|
|
239
|
+
// Overload 2: Dependencies array + render function (Optimized behavior)
|
|
240
|
+
(
|
|
241
|
+
dependencies: any[],
|
|
242
|
+
renderFn: (state: StateObject<T, TPlugins>) => React.ReactNode
|
|
243
|
+
): JSX.Element;
|
|
244
|
+
};
|
|
236
245
|
$formElement: (
|
|
237
246
|
control: FormControl<T>,
|
|
238
247
|
opts?: PerPathFormOptsType<T, TPlugins>
|
|
@@ -314,6 +323,7 @@ export type StateObject<
|
|
|
314
323
|
};
|
|
315
324
|
|
|
316
325
|
export type CogsUpdate<T extends unknown> = UpdateType<T>;
|
|
326
|
+
|
|
317
327
|
type EffectiveSetStateArg<
|
|
318
328
|
T,
|
|
319
329
|
UpdateType extends 'update' | 'insert' | 'cut',
|
|
@@ -349,7 +359,6 @@ export type UpdateTypeDetail = {
|
|
|
349
359
|
oldValue: any;
|
|
350
360
|
newValue: any;
|
|
351
361
|
userId?: number;
|
|
352
|
-
|
|
353
362
|
itemId?: string;
|
|
354
363
|
insertAfterId?: string;
|
|
355
364
|
metaData?: Record<string, any>;
|
|
@@ -511,14 +520,12 @@ const {
|
|
|
511
520
|
addPathComponent,
|
|
512
521
|
clearSelectedIndexesForState,
|
|
513
522
|
addStateLog,
|
|
514
|
-
setSyncInfo,
|
|
515
523
|
clearSelectedIndex,
|
|
516
524
|
getSyncInfo,
|
|
517
525
|
notifyPathSubscribers,
|
|
518
526
|
getPluginMetaDataMap,
|
|
519
527
|
setPluginMetaData,
|
|
520
528
|
removePluginMetaData,
|
|
521
|
-
// Note: The old functions are no longer imported under their original names
|
|
522
529
|
} = getGlobalStore.getState();
|
|
523
530
|
|
|
524
531
|
const { notifyUpdate } = pluginStore.getState();
|
|
@@ -1069,9 +1076,7 @@ let isFlushScheduled = false;
|
|
|
1069
1076
|
function scheduleFlush() {
|
|
1070
1077
|
if (!isFlushScheduled) {
|
|
1071
1078
|
isFlushScheduled = true;
|
|
1072
|
-
console.log('Scheduling flush');
|
|
1073
1079
|
queueMicrotask(() => {
|
|
1074
|
-
console.log('Actually flushing');
|
|
1075
1080
|
flushQueue();
|
|
1076
1081
|
});
|
|
1077
1082
|
}
|
|
@@ -1983,6 +1988,7 @@ function createProxyHandler<
|
|
|
1983
1988
|
const viewIds = meta?.arrayViews?.[arrayPathKey];
|
|
1984
1989
|
|
|
1985
1990
|
// Pass viewIds to getShadowValue to get the filtered/sorted data
|
|
1991
|
+
registerComponentDependency(stateKey, componentId, path);
|
|
1986
1992
|
return getShadowValue(stateKey, path, viewIds);
|
|
1987
1993
|
}
|
|
1988
1994
|
|
|
@@ -2129,43 +2135,39 @@ function createProxyHandler<
|
|
|
2129
2135
|
if (prop === '$validate') {
|
|
2130
2136
|
return () => {
|
|
2131
2137
|
const store = getGlobalStore.getState();
|
|
2132
|
-
|
|
2138
|
+
|
|
2139
|
+
// 1. Get Data & Schema
|
|
2133
2140
|
const { value } = getScopedData(stateKey, path, meta);
|
|
2134
2141
|
const opts = store.getInitialOptions(stateKey);
|
|
2135
2142
|
const schema =
|
|
2136
2143
|
opts?.validation?.zodSchemaV4 || opts?.validation?.zodSchemaV3;
|
|
2137
2144
|
|
|
2145
|
+
// If no schema, assume valid
|
|
2138
2146
|
if (!schema) {
|
|
2139
2147
|
return { success: true, data: value };
|
|
2140
2148
|
}
|
|
2141
2149
|
|
|
2142
|
-
// 2. Run Zod
|
|
2150
|
+
// 2. Run Zod Validation
|
|
2143
2151
|
const result = (schema as any).safeParse(value);
|
|
2144
2152
|
|
|
2145
|
-
// 3.
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
const clearPath = (currentPath: string[]) => {
|
|
2150
|
-
const currentMeta =
|
|
2151
|
-
store.getShadowMetadata(stateKey, currentPath) || {};
|
|
2152
|
-
store.setShadowMetadata(stateKey, currentPath, {
|
|
2153
|
+
// 3. Update State Logic
|
|
2154
|
+
if (result.success) {
|
|
2155
|
+
const currentMeta = store.getShadowMetadata(stateKey, path) || {};
|
|
2156
|
+
store.setShadowMetadata(stateKey, path, {
|
|
2153
2157
|
...currentMeta,
|
|
2154
2158
|
validation: {
|
|
2155
|
-
status: '
|
|
2159
|
+
status: 'VALID',
|
|
2156
2160
|
errors: [],
|
|
2157
2161
|
lastValidated: Date.now(),
|
|
2158
2162
|
},
|
|
2159
2163
|
});
|
|
2160
|
-
}
|
|
2161
|
-
|
|
2164
|
+
} else {
|
|
2165
|
+
// Zod v4 uses 'issues', Zod v3 uses 'errors'
|
|
2166
|
+
const zodErrors =
|
|
2167
|
+
result.error?.issues || result.error?.errors || [];
|
|
2162
2168
|
|
|
2163
|
-
|
|
2164
|
-
if (!result.success) {
|
|
2165
|
-
result.error.errors.forEach((error: any) => {
|
|
2166
|
-
// Calculate the exact path to the field with the error
|
|
2169
|
+
zodErrors.forEach((error: any) => {
|
|
2167
2170
|
const errorPath = [...path, ...error.path.map(String)];
|
|
2168
|
-
|
|
2169
2171
|
const currentMeta =
|
|
2170
2172
|
store.getShadowMetadata(stateKey, errorPath) || {};
|
|
2171
2173
|
|
|
@@ -2182,15 +2184,14 @@ function createProxyHandler<
|
|
|
2182
2184
|
},
|
|
2183
2185
|
],
|
|
2184
2186
|
lastValidated: Date.now(),
|
|
2185
|
-
validatedValue: getShadowValue(stateKey, errorPath),
|
|
2187
|
+
validatedValue: store.getShadowValue(stateKey, errorPath),
|
|
2186
2188
|
},
|
|
2187
2189
|
});
|
|
2188
2190
|
});
|
|
2189
|
-
|
|
2190
|
-
// Notify components to re-render and show the errors
|
|
2191
|
-
notifyComponents(stateKey);
|
|
2192
2191
|
}
|
|
2193
2192
|
|
|
2193
|
+
notifyComponents(stateKey);
|
|
2194
|
+
|
|
2194
2195
|
return result;
|
|
2195
2196
|
};
|
|
2196
2197
|
}
|
|
@@ -2769,7 +2770,7 @@ function createProxyHandler<
|
|
|
2769
2770
|
if (prop === '$cut') {
|
|
2770
2771
|
return (index?: number, options?: { waitForSync?: boolean }) => {
|
|
2771
2772
|
const shadowMeta = getShadowMetadata(stateKey, path);
|
|
2772
|
-
|
|
2773
|
+
|
|
2773
2774
|
if (!shadowMeta?.arrayKeys || shadowMeta.arrayKeys.length === 0)
|
|
2774
2775
|
return;
|
|
2775
2776
|
|
|
@@ -2780,12 +2781,8 @@ function createProxyHandler<
|
|
|
2780
2781
|
? index
|
|
2781
2782
|
: shadowMeta.arrayKeys.length - 1;
|
|
2782
2783
|
|
|
2783
|
-
console.log('indexToCut ->>>>>>>>>>>>>>>>', indexToCut);
|
|
2784
|
-
|
|
2785
2784
|
const idToCut = shadowMeta.arrayKeys[indexToCut];
|
|
2786
2785
|
if (!idToCut) return;
|
|
2787
|
-
console.log('idToCut ->>>>>>>>>>>>>>>>', idToCut);
|
|
2788
|
-
|
|
2789
2786
|
effectiveSetState(null, [...path, idToCut], {
|
|
2790
2787
|
updateType: 'cut',
|
|
2791
2788
|
});
|
|
@@ -2988,10 +2985,60 @@ function createProxyHandler<
|
|
|
2988
2985
|
notifySelectionComponents(stateKey, parentPath);
|
|
2989
2986
|
};
|
|
2990
2987
|
}
|
|
2991
|
-
|
|
2992
|
-
|
|
2988
|
+
|
|
2989
|
+
if (prop === '$clearValidation') {
|
|
2990
|
+
return (subPath?: string[]) => {
|
|
2991
|
+
const targetPath = subPath ? [...path, ...subPath] : path;
|
|
2992
|
+
const store = getGlobalStore.getState();
|
|
2993
|
+
|
|
2994
|
+
// 1. Get the node where we want to start clearing
|
|
2995
|
+
const startNode = store.getShadowNode(stateKey, targetPath);
|
|
2996
|
+
console.log('startNode ', startNode);
|
|
2997
|
+
if (!startNode) return;
|
|
2998
|
+
|
|
2999
|
+
// 2. Define a stack for iterative traversal (avoids recursion depth issues)
|
|
3000
|
+
// Stack items: [currentNode, currentPathArray]
|
|
3001
|
+
const stack: [any, string[]][] = [[startNode, targetPath]];
|
|
3002
|
+
console.log('stack ', stack);
|
|
3003
|
+
while (stack.length > 0) {
|
|
3004
|
+
const [node, currPath] = stack.pop()!;
|
|
3005
|
+
console.log('while (stack.length ', node, currPath);
|
|
3006
|
+
if (!node || typeof node !== 'object') continue;
|
|
3007
|
+
|
|
3008
|
+
// 3. Clear validation on the current node if it exists
|
|
3009
|
+
if (node._meta?.validation) {
|
|
3010
|
+
// Reset the validation object
|
|
3011
|
+
node._meta.validation = {
|
|
3012
|
+
status: 'NOT_VALIDATED',
|
|
3013
|
+
errors: [],
|
|
3014
|
+
lastValidated: Date.now(),
|
|
3015
|
+
validatedValue: undefined,
|
|
3016
|
+
};
|
|
3017
|
+
|
|
3018
|
+
// 4. Notify specific path subscribers so isolated fields update
|
|
3019
|
+
const fullPathKey = [stateKey, ...currPath].join('.');
|
|
3020
|
+
store.notifyPathSubscribers(fullPathKey, {
|
|
3021
|
+
type: 'VALIDATION_CLEAR',
|
|
3022
|
+
});
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
// 5. Add children to stack to continue traversal
|
|
3026
|
+
const keys = Object.keys(node);
|
|
3027
|
+
for (const key of keys) {
|
|
3028
|
+
if (key !== '_meta') {
|
|
3029
|
+
stack.push([node[key], [...currPath, key]]);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// 6. Notify root components
|
|
3035
|
+
notifyComponents(stateKey);
|
|
3036
|
+
};
|
|
2993
3037
|
}
|
|
2994
3038
|
if (path.length == 0) {
|
|
3039
|
+
if (prop === '$_componentId') {
|
|
3040
|
+
return componentId;
|
|
3041
|
+
}
|
|
2995
3042
|
if (prop === '$setOptions') {
|
|
2996
3043
|
return (options: OptionsType<T>) => {
|
|
2997
3044
|
setOptions({ stateKey, options, initialOptionsPart: {} });
|
|
@@ -3016,7 +3063,6 @@ function createProxyHandler<
|
|
|
3016
3063
|
getPluginMetaDataMap(stateKey, path)?.get(pluginName);
|
|
3017
3064
|
}
|
|
3018
3065
|
if (prop === '$addPluginMetaData') {
|
|
3019
|
-
console.log('$addPluginMetaDat');
|
|
3020
3066
|
return (pluginName: string, data: Record<string, any>) =>
|
|
3021
3067
|
setPluginMetaData(stateKey, path, pluginName, data);
|
|
3022
3068
|
}
|
|
@@ -3056,24 +3102,6 @@ function createProxyHandler<
|
|
|
3056
3102
|
});
|
|
3057
3103
|
};
|
|
3058
3104
|
}
|
|
3059
|
-
if (prop === '$clearZodValidation') {
|
|
3060
|
-
return (path?: string[]) => {
|
|
3061
|
-
if (!path) {
|
|
3062
|
-
throw new Error('clearZodValidation requires a path');
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3065
|
-
const currentMeta = getShadowMetadata(stateKey, path) || {};
|
|
3066
|
-
|
|
3067
|
-
setShadowMetadata(stateKey, path, {
|
|
3068
|
-
...currentMeta,
|
|
3069
|
-
validation: {
|
|
3070
|
-
status: 'NOT_VALIDATED',
|
|
3071
|
-
errors: [],
|
|
3072
|
-
lastValidated: Date.now(),
|
|
3073
|
-
},
|
|
3074
|
-
});
|
|
3075
|
-
};
|
|
3076
|
-
}
|
|
3077
3105
|
|
|
3078
3106
|
if (prop === '$applyOperation') {
|
|
3079
3107
|
return (
|
|
@@ -3083,12 +3111,6 @@ function createProxyHandler<
|
|
|
3083
3111
|
},
|
|
3084
3112
|
metaData?: Record<string, any>
|
|
3085
3113
|
) => {
|
|
3086
|
-
console.log(
|
|
3087
|
-
'getGlobalStore',
|
|
3088
|
-
getGlobalStore
|
|
3089
|
-
.getState()
|
|
3090
|
-
.getShadowMetadata(stateKey, operation.path)
|
|
3091
|
-
);
|
|
3092
3114
|
let index: number | undefined;
|
|
3093
3115
|
if (
|
|
3094
3116
|
operation.insertAfterId &&
|
|
@@ -3274,11 +3296,29 @@ function createProxyHandler<
|
|
|
3274
3296
|
};
|
|
3275
3297
|
}
|
|
3276
3298
|
if (prop === '$isolate') {
|
|
3277
|
-
|
|
3299
|
+
// We accept (renderFn) OR (deps, renderFn)
|
|
3300
|
+
return (
|
|
3301
|
+
arg1: any[] | ((state: any) => React.ReactNode),
|
|
3302
|
+
arg2?: (state: any) => React.ReactNode
|
|
3303
|
+
) => {
|
|
3304
|
+
// Check if the first argument is the dependency array
|
|
3305
|
+
const hasDependencies = Array.isArray(arg1);
|
|
3306
|
+
|
|
3307
|
+
// Normalize arguments
|
|
3308
|
+
const dependencies = hasDependencies ? arg1 : undefined;
|
|
3309
|
+
const renderFn = hasDependencies ? arg2 : arg1;
|
|
3310
|
+
|
|
3311
|
+
if (!renderFn || typeof renderFn !== 'function') {
|
|
3312
|
+
throw new Error(
|
|
3313
|
+
'CogsState: $isolate requires a render function.'
|
|
3314
|
+
);
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3278
3317
|
return (
|
|
3279
3318
|
<IsolatedComponentWrapper
|
|
3280
3319
|
stateKey={stateKey}
|
|
3281
|
-
path={path}
|
|
3320
|
+
path={path} // The path of the node calling $isolate (e.g. "form")
|
|
3321
|
+
dependencies={dependencies} // Pass the specific parts to watch
|
|
3282
3322
|
rebuildStateShape={rebuildStateShape}
|
|
3283
3323
|
renderFn={renderFn}
|
|
3284
3324
|
/>
|
package/src/Components.tsx
CHANGED
|
@@ -633,36 +633,50 @@ const useImageLoaded = (ref: RefObject<HTMLElement>): boolean => {
|
|
|
633
633
|
};
|
|
634
634
|
// Components.tsx
|
|
635
635
|
|
|
636
|
-
// Generic isolated component wrapper
|
|
637
636
|
export function IsolatedComponentWrapper({
|
|
638
637
|
stateKey,
|
|
639
|
-
path,
|
|
638
|
+
path, // The path of the parent node (e.g. ['form'])
|
|
639
|
+
dependencies, // NEW: Optional array of Proxy objects or path arrays
|
|
640
640
|
rebuildStateShape,
|
|
641
641
|
renderFn,
|
|
642
642
|
}: {
|
|
643
643
|
stateKey: string;
|
|
644
644
|
path: string[];
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
componentId: string;
|
|
648
|
-
meta?: any;
|
|
649
|
-
}) => any;
|
|
645
|
+
dependencies?: any[]; // The explicit list of dependencies
|
|
646
|
+
rebuildStateShape: (options: any) => any;
|
|
650
647
|
renderFn: (state: any) => React.ReactNode;
|
|
651
648
|
}) {
|
|
652
649
|
const [componentId] = useState(() => uuidv4());
|
|
653
650
|
const [, forceUpdate] = useState({});
|
|
654
651
|
|
|
655
|
-
const stateKeyPathKey = [stateKey, ...path].join('.');
|
|
656
652
|
useRegisterComponent(stateKey, componentId, forceUpdate);
|
|
657
653
|
|
|
654
|
+
const pathsToSubscribe = useMemo(() => {
|
|
655
|
+
if (dependencies && dependencies.length > 0) {
|
|
656
|
+
return dependencies.map((dep) => {
|
|
657
|
+
console.log(dep, dep.$_path);
|
|
658
|
+
return [stateKey, ...dep.$_path].join('.');
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return [[stateKey, ...path].join('.')];
|
|
663
|
+
}, [stateKey, path, dependencies]);
|
|
664
|
+
|
|
665
|
+
// 2. Subscribe to ALL calculated paths
|
|
658
666
|
useEffect(() => {
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
667
|
+
const store = getGlobalStore.getState();
|
|
668
|
+
|
|
669
|
+
// Create an array of unsubscribe functions
|
|
670
|
+
const unsubs = pathsToSubscribe.map((fullPathKey) => {
|
|
671
|
+
return store.subscribeToPath(fullPathKey, () => {
|
|
662
672
|
forceUpdate({});
|
|
663
673
|
});
|
|
664
|
-
|
|
665
|
-
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
return () => {
|
|
677
|
+
unsubs.forEach((unsub) => unsub());
|
|
678
|
+
};
|
|
679
|
+
}, [pathsToSubscribe]);
|
|
666
680
|
|
|
667
681
|
const baseState = rebuildStateShape({
|
|
668
682
|
path: path,
|
|
@@ -672,7 +686,6 @@ export function IsolatedComponentWrapper({
|
|
|
672
686
|
|
|
673
687
|
return <>{renderFn(baseState)}</>;
|
|
674
688
|
}
|
|
675
|
-
|
|
676
689
|
// 1. Define the MINIMAL props needed.
|
|
677
690
|
type PluginWrapperProps = {
|
|
678
691
|
children: React.ReactNode;
|