@judo/core 0.1.0

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.
Files changed (59) hide show
  1. package/LICENSE +277 -0
  2. package/README.md +213 -0
  3. package/dist/contexts/application-context.d.ts +46 -0
  4. package/dist/contexts/application-context.d.ts.map +1 -0
  5. package/dist/contexts/customizations-context.d.ts +227 -0
  6. package/dist/contexts/customizations-context.d.ts.map +1 -0
  7. package/dist/contexts/data-context.d.ts +30 -0
  8. package/dist/contexts/data-context.d.ts.map +1 -0
  9. package/dist/contexts/dispatch-context.d.ts +39 -0
  10. package/dist/contexts/dispatch-context.d.ts.map +1 -0
  11. package/dist/contexts/index.d.ts +12 -0
  12. package/dist/contexts/index.d.ts.map +1 -0
  13. package/dist/contexts/mui-pro-context.d.ts +52 -0
  14. package/dist/contexts/mui-pro-context.d.ts.map +1 -0
  15. package/dist/contexts/navigation-context.d.ts +113 -0
  16. package/dist/contexts/navigation-context.d.ts.map +1 -0
  17. package/dist/contexts/page-context.d.ts +43 -0
  18. package/dist/contexts/page-context.d.ts.map +1 -0
  19. package/dist/contexts/refresh-signal-context.d.ts +18 -0
  20. package/dist/contexts/refresh-signal-context.d.ts.map +1 -0
  21. package/dist/contexts/runtime-config-context.d.ts +70 -0
  22. package/dist/contexts/runtime-config-context.d.ts.map +1 -0
  23. package/dist/contexts/selector-selection-context.d.ts +44 -0
  24. package/dist/contexts/selector-selection-context.d.ts.map +1 -0
  25. package/dist/contexts/validation-context.d.ts +57 -0
  26. package/dist/contexts/validation-context.d.ts.map +1 -0
  27. package/dist/hooks/index.d.ts +9 -0
  28. package/dist/hooks/index.d.ts.map +1 -0
  29. package/dist/hooks/use-data-selector.d.ts +51 -0
  30. package/dist/hooks/use-data-selector.d.ts.map +1 -0
  31. package/dist/hooks/use-debounced-callback.d.ts +36 -0
  32. package/dist/hooks/use-debounced-callback.d.ts.map +1 -0
  33. package/dist/hooks/use-edit-mode.d.ts +23 -0
  34. package/dist/hooks/use-edit-mode.d.ts.map +1 -0
  35. package/dist/hooks/use-element-disabled.d.ts +16 -0
  36. package/dist/hooks/use-element-disabled.d.ts.map +1 -0
  37. package/dist/hooks/use-element-visibility.d.ts +16 -0
  38. package/dist/hooks/use-element-visibility.d.ts.map +1 -0
  39. package/dist/hooks/use-validation.d.ts +32 -0
  40. package/dist/hooks/use-validation.d.ts.map +1 -0
  41. package/dist/hooks/use-visual-binding.d.ts +38 -0
  42. package/dist/hooks/use-visual-binding.d.ts.map +1 -0
  43. package/dist/hooks/use-visual-element.d.ts +13 -0
  44. package/dist/hooks/use-visual-element.d.ts.map +1 -0
  45. package/dist/index.d.ts +11 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +764 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/store/data-store.d.ts +168 -0
  50. package/dist/store/data-store.d.ts.map +1 -0
  51. package/dist/store/index.d.ts +3 -0
  52. package/dist/store/index.d.ts.map +1 -0
  53. package/dist/store/selectors.d.ts +58 -0
  54. package/dist/store/selectors.d.ts.map +1 -0
  55. package/dist/utils/deep-equal.d.ts +10 -0
  56. package/dist/utils/deep-equal.d.ts.map +1 -0
  57. package/dist/utils/index.d.ts +2 -0
  58. package/dist/utils/index.d.ts.map +1 -0
  59. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["value: ApplicationContextType","value: NavigationContextType","value: ValidationContextType","value: PageContextType","value: DispatchContextType","value: SelectorSelectionContextType","newResult: SelectorResult"],"sources":["../src/contexts/application-context.tsx","../src/contexts/navigation-context.tsx","../src/utils/deep-equal.ts","../src/store/data-store.ts","../src/store/selectors.ts","../src/contexts/data-context.tsx","../src/contexts/validation-context.tsx","../src/contexts/page-context.tsx","../src/contexts/runtime-config-context.tsx","../src/contexts/dispatch-context.tsx","../src/contexts/customizations-context.tsx","../src/contexts/selector-selection-context.tsx","../src/contexts/mui-pro-context.tsx","../src/contexts/refresh-signal-context.tsx","../src/hooks/use-validation.ts","../src/hooks/use-visual-binding.ts","../src/hooks/use-data-selector.ts","../src/hooks/use-edit-mode.ts","../src/hooks/use-visual-element.ts","../src/hooks/use-element-visibility.ts","../src/hooks/use-element-disabled.ts","../src/hooks/use-debounced-callback.ts"],"sourcesContent":["import type { Application } from \"@judo/model-api\";\nimport type { ModelRegistry, RegistrySnapshot } from \"@judo/model-loader\";\nimport { type ReactNode, createContext, useCallback, useContext, useSyncExternalStore } from \"react\";\n\n/**\n * Application context type.\n */\nexport interface ApplicationContextType {\n\t/** Current active application (model required) */\n\tapplication: Application;\n\t/** All available applications (multi-actor) */\n\tapplications: Application[];\n\t/** Switch to different actor */\n\tswitchActor: (actorName: string) => void;\n\t/** Switch to different actor with navigation callback */\n\tswitchActorWithNavigation: (actorName: string, onSwitch?: (app: Application) => void) => void;\n\t/** Current actor name */\n\tactorName: string;\n}\n\nconst ApplicationContext = createContext<ApplicationContextType | null>(null);\n\n/**\n * Hook to access application context.\n * Throws if used outside provider or without model.\n *\n * @returns ApplicationContextType\n * @throws Error if used outside ApplicationProvider\n */\nexport function useApplication(): ApplicationContextType {\n\tconst context = useContext(ApplicationContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useApplication must be used within ApplicationProvider. \" +\n\t\t\t\t\"Ensure model is loaded before rendering application.\"\n\t\t);\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access application context (optional).\n * Returns null if not within provider instead of throwing.\n *\n * @returns ApplicationContextType | null\n */\nexport function useApplicationOptional(): ApplicationContextType | null {\n\treturn useContext(ApplicationContext);\n}\n\n/**\n * Props for ApplicationProvider.\n */\nexport interface ApplicationProviderProps {\n\tchildren: ReactNode;\n\tregistry: ModelRegistry;\n}\n\n/**\n * Provider requiring loaded model.\n * Uses useSyncExternalStore for proper subscription to registry changes.\n */\nexport function ApplicationProvider({ children, registry }: ApplicationProviderProps) {\n\tconst subscribe = useCallback((onStoreChange: () => void) => registry.subscribe(onStoreChange), [registry]);\n\n\tconst getSnapshot = useCallback((): RegistrySnapshot => registry.getSnapshot(), [registry]);\n\n\tconst snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n\tif (!snapshot.activeApplication) {\n\t\tthrow new Error(\"No active application. Model must be loaded first.\");\n\t}\n\n\tconst value: ApplicationContextType = {\n\t\tapplication: snapshot.activeApplication,\n\t\tapplications: snapshot.applications,\n\t\tactorName: snapshot.activeActorName!,\n\t\tswitchActor: (actorName: string) => registry.setActiveApplication(actorName),\n\t\tswitchActorWithNavigation: (actorName: string, onSwitch?: (app: Application) => void) => {\n\t\t\tregistry.setActiveApplication(actorName);\n\t\t\tif (onSwitch) {\n\t\t\t\tconst newSnapshot = registry.getSnapshot();\n\t\t\t\tif (newSnapshot.activeApplication) {\n\t\t\t\t\tonSwitch(newSnapshot.activeApplication);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n\n\treturn <ApplicationContext.Provider value={value}>{children}</ApplicationContext.Provider>;\n}\n","import type { PageDefinition } from \"@judo/model-api\";\nimport { DialogSize } from \"@judo/model-api\";\nimport { type ReactNode, createContext, useCallback, useContext, useRef, useState } from \"react\";\n\n/**\n * Page stack entry.\n */\nexport interface PageStackEntry {\n\tpageDefinition: PageDefinition;\n\tparams?: Record<string, unknown>;\n\tscrollPosition?: number;\n}\n\n/**\n * Dialog close result types.\n */\nexport type DialogCloseResultType = \"cancelled\" | \"created\" | \"updated\" | \"deleted\" | \"selected\" | \"submitted\";\n\n/**\n * Result returned when dialog closes.\n * Uses discriminated union for type-safe handling of different outcomes.\n */\nexport type DialogCloseResult =\n\t| { type: \"cancelled\" }\n\t| { type: \"created\"; isEager: boolean; data?: unknown }\n\t| { type: \"updated\"; data?: unknown }\n\t| { type: \"deleted\"; data?: unknown }\n\t| { type: \"selected\"; data?: unknown }\n\t| { type: \"submitted\"; data?: unknown };\n\n/**\n * Dialog state.\n */\nexport interface DialogState {\n\tpageDefinition: PageDefinition;\n\tsize: DialogSize;\n\tparams?: Record<string, unknown>;\n}\n\n/**\n * Navigation state.\n */\nexport interface NavigationState {\n\t/** Current page stack (for back navigation) */\n\tpageStack: PageStackEntry[];\n\t/** Current page definition */\n\tcurrentPage: PageDefinition | null;\n\t/** Dialog stack — supports nested dialogs. Top of stack is the active dialog. */\n\tdialogStack: DialogState[];\n}\n\n/**\n * Callback invoked when dialog closes.\n */\nexport type DialogCloseCallback = (result?: DialogCloseResult) => void;\n\n/**\n * Navigation context type.\n */\nexport interface NavigationContextType extends NavigationState {\n\t/** Top dialog (convenience — same as dialogStack[dialogStack.length - 1] or null) */\n\tdialog: DialogState | null;\n\t/** Navigate to page */\n\tnavigateTo: (page: PageDefinition, params?: Record<string, unknown>) => void;\n\t/** Navigate back */\n\tgoBack: () => void;\n\t/** Open page in dialog with optional onClose callback */\n\topenDialog: (page: PageDefinition, params?: Record<string, unknown>, onClose?: DialogCloseCallback) => void;\n\t/** Close current dialog with optional result */\n\tcloseDialog: (result?: DialogCloseResult) => void;\n\t/** Replace current page (no stack) */\n\treplacePage: (page: PageDefinition, params?: Record<string, unknown>) => void;\n\t/** Clear navigation stack */\n\tclearStack: () => void;\n\t/** Check if can go back */\n\tcanGoBack: boolean;\n}\n\nconst NavigationContext = createContext<NavigationContextType | null>(null);\n\n/**\n * Hook to access navigation context.\n *\n * @returns NavigationContextType\n * @throws Error if used outside NavigationProvider\n */\nexport function useNavigation(): NavigationContextType {\n\tconst context = useContext(NavigationContext);\n\tif (!context) {\n\t\tthrow new Error(\"useNavigation must be used within NavigationProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access navigation context (optional).\n *\n * @returns NavigationContextType | null\n */\nexport function useNavigationOptional(): NavigationContextType | null {\n\treturn useContext(NavigationContext);\n}\n\n/**\n * Props for NavigationProvider.\n */\nexport interface NavigationProviderProps {\n\tchildren: ReactNode;\n\t/** Initial page (optional) */\n\tinitialPage?: PageDefinition;\n\t/** Optional navigate function for React Router integration */\n\tnavigate?: (path: string, options?: { state?: unknown }) => void;\n\t/** Optional function to get route path for a page */\n\tgetRouteForPage?: (page: PageDefinition) => string;\n}\n\n/**\n * Provider for navigation context.\n */\nexport function NavigationProvider({ children, initialPage, navigate, getRouteForPage }: NavigationProviderProps) {\n\tconst [state, setState] = useState<NavigationState>({\n\t\tpageStack: [],\n\t\tcurrentPage: initialPage ?? null,\n\t\tdialogStack: [],\n\t});\n\n\tconst navigateTo = useCallback(\n\t\t(page: PageDefinition, params?: Record<string, unknown>) => {\n\t\t\tsetState((prev) => {\n\t\t\t\t// Check if page should open in dialog\n\t\t\t\tif (page.openInDialog) {\n\t\t\t\t\t// Push to dialog stack (supports nested dialogs)\n\t\t\t\t\tdialogCloseCallbackStackRef.current.push(null);\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\tdialogStack: [\n\t\t\t\t\t\t\t...prev.dialogStack,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tpageDefinition: page,\n\t\t\t\t\t\t\t\tsize: page.dialogSize || DialogSize.MD,\n\t\t\t\t\t\t\t\tparams,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Regular navigation - push to stack, clear all dialogs\n\t\t\t\tdialogCloseCallbackStackRef.current = [];\n\t\t\t\tconst newStack = prev.currentPage ? [...prev.pageStack, { pageDefinition: prev.currentPage }] : prev.pageStack;\n\n\t\t\t\treturn {\n\t\t\t\t\t...prev,\n\t\t\t\t\tpageStack: newStack,\n\t\t\t\t\tcurrentPage: page,\n\t\t\t\t\tdialogStack: [],\n\t\t\t\t};\n\t\t\t});\n\n\t\t\t// Integrate with React Router if navigate function is provided\n\t\t\tif (!page.openInDialog && navigate && getRouteForPage) {\n\t\t\t\tconst route = getRouteForPage(page);\n\n\t\t\t\t// For pages that need transfer context (e.g., VIEW pages), append signed identifier to URL\n\t\t\t\tconst transfer = params?.transfer as { __signedIdentifier?: string } | undefined;\n\t\t\t\tconst finalRoute = transfer?.__signedIdentifier\n\t\t\t\t\t? `${route}/${encodeURIComponent(transfer.__signedIdentifier)}`\n\t\t\t\t\t: route;\n\n\t\t\t\tnavigate(finalRoute, { state: params });\n\t\t\t}\n\t\t},\n\t\t[navigate, getRouteForPage]\n\t);\n\n\tconst goBack = useCallback(() => {\n\t\tsetState((prev) => {\n\t\t\t// If dialog stack is non-empty, pop the top dialog\n\t\t\tif (prev.dialogStack.length > 0) {\n\t\t\t\t// Invoke onClose callback for the top dialog\n\t\t\t\tconst callback = dialogCloseCallbackStackRef.current.pop() ?? null;\n\t\t\t\tif (callback) {\n\t\t\t\t\tcallback(undefined); // No result means cancelled\n\t\t\t\t}\n\t\t\t\treturn { ...prev, dialogStack: prev.dialogStack.slice(0, -1) };\n\t\t\t}\n\n\t\t\t// Pop from stack\n\t\t\tif (prev.pageStack.length === 0) {\n\t\t\t\t// No internal stack - use browser back if navigate available\n\t\t\t\tif (navigate) {\n\t\t\t\t\t// Navigate(-1) triggers browser back\n\t\t\t\t\tnavigate(-1 as unknown as string);\n\t\t\t\t}\n\t\t\t\treturn prev;\n\t\t\t}\n\n\t\t\tconst newStack = [...prev.pageStack];\n\t\t\tconst previousEntry = newStack.pop()!;\n\n\t\t\t// Navigate to previous page's route if router integration available\n\t\t\tif (navigate && getRouteForPage) {\n\t\t\t\tconst route = getRouteForPage(previousEntry.pageDefinition);\n\t\t\t\tnavigate(route, { state: previousEntry.params });\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...prev,\n\t\t\t\tpageStack: newStack,\n\t\t\t\tcurrentPage: previousEntry.pageDefinition,\n\t\t\t};\n\t\t});\n\t}, [navigate, getRouteForPage]);\n\n\t// Store dialog close callbacks in a stack (one per dialog in the stack)\n\tconst dialogCloseCallbackStackRef = useRef<(DialogCloseCallback | null)[]>([]);\n\n\tconst openDialog = useCallback(\n\t\t(page: PageDefinition, params?: Record<string, unknown>, onClose?: DialogCloseCallback) => {\n\t\t\t// Push the callback for this dialog\n\t\t\tdialogCloseCallbackStackRef.current.push(onClose ?? null);\n\n\t\t\tsetState((prev) => ({\n\t\t\t\t...prev,\n\t\t\t\tdialogStack: [\n\t\t\t\t\t...prev.dialogStack,\n\t\t\t\t\t{\n\t\t\t\t\t\tpageDefinition: page,\n\t\t\t\t\t\tsize: page.dialogSize || DialogSize.MD,\n\t\t\t\t\t\tparams,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}));\n\t\t},\n\t\t[]\n\t);\n\n\tconst closeDialog = useCallback((result?: DialogCloseResult) => {\n\t\t// Pop and invoke the top dialog's callback\n\t\tconst callback = dialogCloseCallbackStackRef.current.pop() ?? null;\n\t\tif (callback) {\n\t\t\tcallback(result);\n\t\t}\n\n\t\tsetState((prev) => ({ ...prev, dialogStack: prev.dialogStack.slice(0, -1) }));\n\t}, []);\n\n\tconst replacePage = useCallback((page: PageDefinition, _params?: Record<string, unknown>) => {\n\t\tdialogCloseCallbackStackRef.current = [];\n\t\tsetState((prev) => ({\n\t\t\t...prev,\n\t\t\tcurrentPage: page,\n\t\t\tdialogStack: [],\n\t\t}));\n\t}, []);\n\n\tconst clearStack = useCallback(() => {\n\t\tsetState((prev) => ({\n\t\t\t...prev,\n\t\t\tpageStack: [],\n\t\t}));\n\t}, []);\n\n\tconst dialog = state.dialogStack.length > 0 ? state.dialogStack[state.dialogStack.length - 1] : null;\n\n\tconst value: NavigationContextType = {\n\t\t...state,\n\t\tdialog,\n\t\tnavigateTo,\n\t\tgoBack,\n\t\topenDialog,\n\t\tcloseDialog,\n\t\treplacePage,\n\t\tclearStack,\n\t\tcanGoBack: state.pageStack.length > 0 || state.dialogStack.length > 0,\n\t};\n\n\treturn <NavigationContext.Provider value={value}>{children}</NavigationContext.Provider>;\n}\n","/**\n * Deep equality comparison for objects and arrays.\n * Used for dirty state tracking in DataStore.\n *\n * @param a - First value\n * @param b - Second value\n * @returns true if values are deeply equal\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\t// Reference equality\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\t// Null/undefined checks\n\tif (a === null || b === null || a === undefined || b === undefined) {\n\t\treturn a === b;\n\t}\n\n\t// Type checks\n\tif (typeof a !== typeof b) {\n\t\treturn false;\n\t}\n\n\t// Primitive types\n\tif (typeof a !== \"object\") {\n\t\treturn a === b;\n\t}\n\n\t// Array comparison\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tif (a.length !== b.length) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let i = 0; i < a.length; i++) {\n\t\t\tif (!deepEqual(a[i], b[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t// One is array, other is not\n\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\treturn false;\n\t}\n\n\t// Date comparison\n\tif (a instanceof Date && b instanceof Date) {\n\t\treturn a.getTime() === b.getTime();\n\t}\n\n\t// Object comparison\n\tconst objA = a as Record<string, unknown>;\n\tconst objB = b as Record<string, unknown>;\n\n\tconst keysA = Object.keys(objA);\n\tconst keysB = Object.keys(objB);\n\n\tif (keysA.length !== keysB.length) {\n\t\treturn false;\n\t}\n\n\tfor (const key of keysA) {\n\t\tif (!Object.prototype.hasOwnProperty.call(objB, key)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!deepEqual(objA[key], objB[key])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n","import { deepEqual } from \"../utils\";\n\n/**\n * Transfer data structure.\n *\n * Generic parameter `T` allows strict-typing when the transfer shape is known\n * (e.g. via codegen-generated interfaces). Falls back to an open index signature\n * when omitted so existing untyped code keeps compiling.\n *\n */\nexport interface TransferData {\n\t__identifier?: string;\n\t__signedIdentifier?: string;\n\t__typename?: string;\n\t/** Index signature preserved for backwards-compatibility when T = Record<string, unknown> */\n\t[key: string]: unknown;\n}\n\n/**\n * Strict transfer data — a TransferData whose *own* properties conform to `T`.\n *\n * Use this alias in generated code and userland APIs where the exact field set is\n * known at compile time. The intersection keeps the internal `__*` fields from\n * `TransferData` while adding compile-time keys from `T`.\n *\n * @typeParam T - Strict field definitions (e.g. `{ name: string; age: number }`)\n */\nexport type StrictTransferData<T extends Record<string, unknown> = Record<string, unknown>> = TransferData & T;\n\n/**\n * Data store state per transfer type.\n */\nexport interface TransferState {\n\tdata: TransferData | null;\n\toriginalData: TransferData | null;\n\tisDirty: boolean;\n\tisLoading: boolean;\n\terror: Error | null;\n}\n\n/**\n * Full store state.\n */\nexport interface DataStoreState {\n\ttransfers: Map<string, TransferState>;\n\tversion: number;\n}\n\n/**\n * Selector for fine-grained subscriptions.\n */\nexport type DataSelector<T> = (state: DataStoreState) => T;\n\n/**\n * Create empty transfer state.\n */\nexport function createEmptyTransferState(): TransferState {\n\treturn {\n\t\tdata: null,\n\t\toriginalData: null,\n\t\tisDirty: false,\n\t\tisLoading: false,\n\t\terror: null,\n\t};\n}\n\n/**\n * Data store with selector-based subscriptions.\n * Provides fine-grained reactivity by only notifying subscribers\n * when their selected value actually changes.\n */\nexport class DataStore {\n\tprivate state: DataStoreState = {\n\t\ttransfers: new Map(),\n\t\tversion: 0,\n\t};\n\n\tprivate subscribers = new Map<DataSelector<unknown>, Set<() => void>>();\n\tprivate selectorCache = new Map<DataSelector<unknown>, unknown>();\n\n\t/**\n\t * Subscribe to specific data slice.\n\t * Only notifies when selected value changes.\n\t *\n\t * @param selector - Function to select data from state\n\t * @param callback - Callback to invoke when selected data changes\n\t * @returns Unsubscribe function\n\t */\n\tsubscribe<T>(selector: DataSelector<T>, callback: () => void): () => void {\n\t\tif (!this.subscribers.has(selector)) {\n\t\t\tthis.subscribers.set(selector, new Set());\n\t\t\t// Initialize cache with current value\n\t\t\tthis.selectorCache.set(selector, selector(this.state));\n\t\t}\n\t\tthis.subscribers.get(selector)!.add(callback);\n\n\t\treturn () => {\n\t\t\tconst subs = this.subscribers.get(selector);\n\t\t\tif (subs) {\n\t\t\t\tsubs.delete(callback);\n\t\t\t\tif (subs.size === 0) {\n\t\t\t\t\tthis.subscribers.delete(selector);\n\t\t\t\t\tthis.selectorCache.delete(selector);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Get current snapshot for selector.\n\t *\n\t * @param selector - Function to select data from state\n\t * @returns Selected value\n\t */\n\tgetSnapshot<T>(selector: DataSelector<T>): T {\n\t\treturn selector(this.state);\n\t}\n\n\t/**\n\t * Get the full state snapshot.\n\t * Used for debugging and testing.\n\t *\n\t * @returns Current state\n\t */\n\tgetState(): DataStoreState {\n\t\treturn this.state;\n\t}\n\n\t/**\n\t * Get transfer state by ID.\n\t *\n\t * When called with an explicit type parameter the returned `data` / `originalData`\n\t * fields are narrowed to `StrictTransferData<T> | null`.\n\t *\n\t * @typeParam T - Optional strict transfer shape\n\t * @param transferId - Transfer identifier\n\t * @returns Transfer state (optionally narrowed) or undefined\n\t */\n\tgetTransfer<T extends Record<string, unknown> = Record<string, unknown>>(\n\t\ttransferId: string\n\t): (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null }) | undefined {\n\t\treturn this.state.transfers.get(transferId) as\n\t\t\t| (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null })\n\t\t\t| undefined;\n\t}\n\n\t/**\n\t * Set transfer data.\n\t * Resets dirty state and error.\n\t *\n\t * @typeParam T - Optional strict transfer shape\n\t * @param transferId - Transfer identifier\n\t * @param data - Transfer data (typed when T is provided)\n\t */\n\tsetTransferData<T extends Record<string, unknown> = Record<string, unknown>>(\n\t\ttransferId: string,\n\t\tdata: StrictTransferData<T>\n\t): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId) || createEmptyTransferState();\n\t\t\ttransfers.set(transferId, {\n\t\t\t\t...current,\n\t\t\t\tdata,\n\t\t\t\toriginalData: data,\n\t\t\t\tisDirty: false,\n\t\t\t\tisLoading: false,\n\t\t\t\terror: null,\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Update a single field on a transfer.\n\t * If the transfer doesn't exist, creates it with just this field.\n\t *\n\t * When `T` is provided the `field` parameter is restricted to `keyof T`\n\t * and `value` is narrowed to the matching property type.\n\t *\n\t * @typeParam T - Optional strict transfer shape\n\t * @param transferId - Transfer identifier\n\t * @param field - Field name (restricted to `keyof T` when strict)\n\t * @param value - New value (typed to `T[K]` when strict)\n\t */\n\tupdateTransferField<\n\t\tT extends Record<string, unknown> = Record<string, unknown>,\n\t\tK extends string & keyof T = string & keyof T,\n\t>(transferId: string, field: K, value: T[K]): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId);\n\t\t\tif (current?.data) {\n\t\t\t\t// Transfer exists - update the field\n\t\t\t\tconst newData = { ...current.data, [field]: value };\n\t\t\t\tconst isDirty = !deepEqual(newData, current.originalData);\n\t\t\t\ttransfers.set(transferId, {\n\t\t\t\t\t...current,\n\t\t\t\t\tdata: newData,\n\t\t\t\t\tisDirty,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Transfer doesn't exist yet - create it with this field\n\t\t\t\t// This happens when typing into a form before data is loaded\n\t\t\t\tconst newData = { [field]: value };\n\t\t\t\ttransfers.set(transferId, {\n\t\t\t\t\t...(current || createEmptyTransferState()),\n\t\t\t\t\tdata: newData,\n\t\t\t\t\toriginalData: null, // No original yet - created locally\n\t\t\t\t\tisDirty: true, // New transfer is dirty by definition\n\t\t\t\t\tisLoading: false,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Set transfer loading state.\n\t *\n\t * @param transferId - Transfer identifier\n\t * @param isLoading - Loading state\n\t */\n\tsetTransferLoading(transferId: string, isLoading: boolean): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId) || createEmptyTransferState();\n\t\t\ttransfers.set(transferId, {\n\t\t\t\t...current,\n\t\t\t\tisLoading,\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Set transfer error state.\n\t *\n\t * @param transferId - Transfer identifier\n\t * @param error - Error or null to clear\n\t */\n\tsetTransferError(transferId: string, error: Error | null): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId) || createEmptyTransferState();\n\t\t\ttransfers.set(transferId, {\n\t\t\t\t...current,\n\t\t\t\terror,\n\t\t\t\tisLoading: false,\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Reset transfer to original data.\n\t *\n\t * @param transferId - Transfer identifier\n\t */\n\tresetTransfer(transferId: string): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId);\n\t\t\tif (current) {\n\t\t\t\ttransfers.set(transferId, {\n\t\t\t\t\t...current,\n\t\t\t\t\tdata: current.originalData,\n\t\t\t\t\tisDirty: false,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Clear transfer from store.\n\t *\n\t * @param transferId - Transfer identifier\n\t */\n\tclearTransfer(transferId: string): void {\n\t\tthis.updateState((transfers) => {\n\t\t\ttransfers.delete(transferId);\n\t\t});\n\t}\n\n\t/**\n\t * Clear all transfers from store.\n\t */\n\tclearAll(): void {\n\t\tthis.updateState((transfers) => {\n\t\t\ttransfers.clear();\n\t\t});\n\t}\n\n\t/**\n\t * Update multiple fields at once.\n\t *\n\t * When `T` is provided the `updates` object is restricted to partial keys of `T`.\n\t *\n\t * @typeParam T - Optional strict transfer shape\n\t * @param transferId - Transfer identifier\n\t * @param updates - Object with field updates (typed to `Partial<T>` when strict)\n\t */\n\tupdateTransferFields<T extends Record<string, unknown> = Record<string, unknown>>(\n\t\ttransferId: string,\n\t\tupdates: Partial<T>\n\t): void {\n\t\tthis.updateState((transfers) => {\n\t\t\tconst current = transfers.get(transferId);\n\t\t\tif (current?.data) {\n\t\t\t\tconst newData = { ...current.data, ...updates };\n\t\t\t\tconst isDirty = !deepEqual(newData, current.originalData);\n\t\t\t\ttransfers.set(transferId, {\n\t\t\t\t\t...current,\n\t\t\t\t\tdata: newData,\n\t\t\t\t\tisDirty,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Internal method to update state and notify subscribers.\n\t */\n\tprivate updateState(updater: (transfers: Map<string, TransferState>) => void): void {\n\t\tconst prevState = this.state;\n\t\tconst newEntities = new Map(this.state.transfers);\n\t\tupdater(newEntities);\n\n\t\tthis.state = {\n\t\t\ttransfers: newEntities,\n\t\t\tversion: this.state.version + 1,\n\t\t};\n\n\t\t// Notify only affected subscribers\n\t\tif (this.state !== prevState) {\n\t\t\tthis.notifySubscribers();\n\t\t}\n\t}\n\n\t/**\n\t * Notify subscribers whose selected values have changed.\n\t */\n\tprivate notifySubscribers(): void {\n\t\tfor (const [selector, callbacks] of this.subscribers) {\n\t\t\tconst prevValue = this.selectorCache.get(selector);\n\t\t\tconst newValue = selector(this.state);\n\n\t\t\t// Only notify if value changed (reference equality)\n\t\t\tif (prevValue !== newValue) {\n\t\t\t\tthis.selectorCache.set(selector, newValue);\n\t\t\t\tfor (const cb of callbacks) {\n\t\t\t\t\tcb();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { DataStoreState, StrictTransferData, TransferState } from \"./data-store\";\n\n/**\n * Create a selector for transfer data by ID.\n *\n * @typeParam T - Optional strict transfer shape for narrowing data fields\n * @param transferId - Transfer identifier\n * @returns Selector function\n */\nexport function selectTransfer<T extends Record<string, unknown> = Record<string, unknown>>(transferId: string) {\n\treturn (\n\t\tstate: DataStoreState\n\t): (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null }) | undefined =>\n\t\tstate.transfers.get(transferId) as\n\t\t\t| (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null })\n\t\t\t| undefined;\n}\n\n/**\n * Create a selector for a typed transfer field value.\n *\n * @typeParam T - Optional strict transfer shape\n * @typeParam K - Field key (inferred from `field` when T is provided)\n * @param transferId - Transfer identifier\n * @param field - Field name (restricted to `keyof T` when strict)\n * @returns Selector function returning `T[K]` (or `unknown` when untyped)\n */\nexport function selectTransferField<\n\tT extends Record<string, unknown> = Record<string, unknown>,\n\tK extends string & keyof T = string & keyof T,\n>(transferId: string, field: K) {\n\treturn (state: DataStoreState): T[K] | undefined =>\n\t\tstate.transfers.get(transferId)?.data?.[field] as T[K] | undefined;\n}\n\n/**\n * Create a selector for transfer loading state.\n *\n * @param transferId - Transfer identifier\n * @returns Selector function\n */\nexport function selectTransferLoading(transferId: string) {\n\treturn (state: DataStoreState): boolean => state.transfers.get(transferId)?.isLoading ?? false;\n}\n\n/**\n * Create a selector for transfer error state.\n *\n * @param transferId - Transfer identifier\n * @returns Selector function\n */\nexport function selectTransferError(transferId: string) {\n\treturn (state: DataStoreState): Error | null => state.transfers.get(transferId)?.error ?? null;\n}\n\n/**\n * Create a selector for transfer dirty state.\n *\n * @param transferId - Transfer identifier\n * @returns Selector function\n */\nexport function selectTransferDirty(transferId: string) {\n\treturn (state: DataStoreState): boolean => state.transfers.get(transferId)?.isDirty ?? false;\n}\n\n/**\n * Selector for all transfer IDs.\n *\n * @param state - Store state\n * @returns Array of transfer IDs\n */\nexport function selectTransferIds(state: DataStoreState): string[] {\n\treturn Array.from(state.transfers.keys());\n}\n\n/**\n * Selector for store version (useful for detecting any change).\n *\n * @param state - Store state\n * @returns Store version number\n */\nexport function selectVersion(state: DataStoreState): number {\n\treturn state.version;\n}\n","import { type ReactNode, createContext, useContext, useState } from \"react\";\nimport { DataStore } from \"../store\";\n\n/**\n * Data context.\n */\nconst DataContext = createContext<DataStore | null>(null);\n\n/**\n * Hook to access the data store.\n *\n * @returns DataStore instance\n * @throws Error if used outside DataProvider\n */\nexport function useDataStore(): DataStore {\n\tconst store = useContext(DataContext);\n\tif (!store) {\n\t\tthrow new Error(\"useDataStore must be used within DataProvider\");\n\t}\n\treturn store;\n}\n\n/**\n * Hook to access the data store (optional).\n * Returns null if not within provider instead of throwing.\n *\n * @returns DataStore instance or null\n */\nexport function useDataStoreOptional(): DataStore | null {\n\treturn useContext(DataContext);\n}\n\n/**\n * Props for DataProvider.\n */\nexport interface DataProviderProps {\n\tchildren: ReactNode;\n\t/** Optional initial store (for testing) */\n\tstore?: DataStore;\n}\n\n/**\n * Provider for data context.\n * Creates a DataStore instance that persists for the lifetime of the provider.\n */\nexport function DataProvider({ children, store: initialStore }: DataProviderProps) {\n\tconst [store] = useState(() => initialStore ?? new DataStore());\n\n\treturn <DataContext.Provider value={store}>{children}</DataContext.Provider>;\n}\n","import { type ReactNode, createContext, useCallback, useContext, useState } from \"react\";\n\n/**\n * Validation state.\n */\nexport interface ValidationState {\n\terrors: Map<string, string>;\n\ttouched: Set<string>;\n}\n\n/**\n * Validation context type.\n */\nexport interface ValidationContextType {\n\t/** Get error for field */\n\tgetError: (fieldId: string) => string | null;\n\t/** Set error for field */\n\tsetError: (fieldId: string, error: string | null) => void;\n\t/** Mark field as touched */\n\ttouch: (fieldId: string) => void;\n\t/** Check if field is touched */\n\tisTouched: (fieldId: string) => boolean;\n\t/** Clear all errors */\n\tclearErrors: () => void;\n\t/** Clear error for specific field */\n\tclearError: (fieldId: string) => void;\n\t/** Validate all fields */\n\tvalidateAll: () => boolean;\n\t/** Check if form is valid */\n\tisValid: boolean;\n\t/** Get all errors */\n\tgetAllErrors: () => Map<string, string>;\n\t/** Set multiple errors at once */\n\tsetErrors: (errors: Record<string, string>) => void;\n}\n\nconst ValidationContext = createContext<ValidationContextType | null>(null);\n\n/**\n * Hook to access validation context.\n *\n * @returns ValidationContextType\n * @throws Error if used outside ValidationProvider\n */\nexport function useValidationContext(): ValidationContextType {\n\tconst context = useContext(ValidationContext);\n\tif (!context) {\n\t\tthrow new Error(\"useValidationContext must be used within ValidationProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access validation context (optional).\n *\n * @returns ValidationContextType | null\n */\nexport function useValidationContextOptional(): ValidationContextType | null {\n\treturn useContext(ValidationContext);\n}\n\n/**\n * Props for ValidationProvider.\n */\nexport interface ValidationProviderProps {\n\tchildren: ReactNode;\n}\n\n/**\n * Provider for validation context.\n */\nexport function ValidationProvider({ children }: ValidationProviderProps) {\n\tconst [state, setState] = useState<ValidationState>({\n\t\terrors: new Map(),\n\t\ttouched: new Set(),\n\t});\n\n\tconst getError = useCallback((fieldId: string) => state.errors.get(fieldId) || null, [state.errors]);\n\n\tconst setError = useCallback((fieldId: string, error: string | null) => {\n\t\tsetState((prev) => {\n\t\t\tconst errors = new Map(prev.errors);\n\t\t\tif (error) {\n\t\t\t\terrors.set(fieldId, error);\n\t\t\t} else {\n\t\t\t\terrors.delete(fieldId);\n\t\t\t}\n\t\t\treturn { ...prev, errors };\n\t\t});\n\t}, []);\n\n\tconst setErrors = useCallback((errors: Record<string, string>) => {\n\t\tsetState((prev) => {\n\t\t\tconst newErrors = new Map(prev.errors);\n\t\t\tfor (const [fieldId, error] of Object.entries(errors)) {\n\t\t\t\tif (error) {\n\t\t\t\t\tnewErrors.set(fieldId, error);\n\t\t\t\t} else {\n\t\t\t\t\tnewErrors.delete(fieldId);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { ...prev, errors: newErrors };\n\t\t});\n\t}, []);\n\n\tconst touch = useCallback((fieldId: string) => {\n\t\tsetState((prev) => {\n\t\t\tconst touched = new Set(prev.touched);\n\t\t\ttouched.add(fieldId);\n\t\t\treturn { ...prev, touched };\n\t\t});\n\t}, []);\n\n\tconst isTouched = useCallback((fieldId: string) => state.touched.has(fieldId), [state.touched]);\n\n\tconst clearErrors = useCallback(() => {\n\t\tsetState({ errors: new Map(), touched: new Set() });\n\t}, []);\n\n\tconst clearError = useCallback((fieldId: string) => {\n\t\tsetState((prev) => {\n\t\t\tconst errors = new Map(prev.errors);\n\t\t\terrors.delete(fieldId);\n\t\t\treturn { ...prev, errors };\n\t\t});\n\t}, []);\n\n\tconst validateAll = useCallback(() => {\n\t\t// Trigger validation for all fields\n\t\t// Return true if valid\n\t\treturn state.errors.size === 0;\n\t}, [state.errors]);\n\n\tconst getAllErrors = useCallback(() => {\n\t\treturn new Map(state.errors);\n\t}, [state.errors]);\n\n\tconst value: ValidationContextType = {\n\t\tgetError,\n\t\tsetError,\n\t\tsetErrors,\n\t\ttouch,\n\t\tisTouched,\n\t\tclearErrors,\n\t\tclearError,\n\t\tvalidateAll,\n\t\tgetAllErrors,\n\t\tisValid: state.errors.size === 0,\n\t};\n\n\treturn <ValidationContext.Provider value={value}>{children}</ValidationContext.Provider>;\n}\n","import type { PageDefinition } from \"@judo/model-api\";\nimport { type ReactNode, createContext, useContext } from \"react\";\n\n/**\n * Page context type.\n */\nexport interface PageContextType {\n\t/** Current page definition */\n\tpageDefinition: PageDefinition;\n\t/** Transfer ID for this page (if applicable) */\n\ttransferId: string | null;\n\t/** Page parameters */\n\tparams: Record<string, unknown>;\n\t/** Whether page is in a dialog */\n\tisDialog: boolean;\n}\n\nconst PageContext = createContext<PageContextType | null>(null);\n\n/**\n * Hook to access page context.\n *\n * @returns PageContextType\n * @throws Error if used outside PageProvider\n */\nexport function usePageContext(): PageContextType {\n\tconst context = useContext(PageContext);\n\tif (!context) {\n\t\tthrow new Error(\"usePageContext must be used within PageProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access page context (optional).\n *\n * @returns PageContextType | null\n */\nexport function usePageContextOptional(): PageContextType | null {\n\treturn useContext(PageContext);\n}\n\n/**\n * Props for PageProvider.\n */\nexport interface PageProviderProps {\n\tchildren: ReactNode;\n\tpageDefinition: PageDefinition;\n\ttransferId?: string | null;\n\tparams?: Record<string, unknown>;\n\tisDialog?: boolean;\n}\n\n/**\n * Provider for page context.\n */\nexport function PageProvider({\n\tchildren,\n\tpageDefinition,\n\ttransferId = null,\n\tparams = {},\n\tisDialog = false,\n}: PageProviderProps) {\n\tconst value: PageContextType = {\n\t\tpageDefinition,\n\t\ttransferId,\n\t\tparams,\n\t\tisDialog,\n\t};\n\n\treturn <PageContext.Provider value={value}>{children}</PageContext.Provider>;\n}\n","import { type ReactNode, createContext, useContext } from \"react\";\n\n/**\n * Feature toggles configuration.\n */\nexport interface FeaturesConfig {\n\t/**\n\t * Enable navigation guards (unsaved changes, session timeout).\n\t * @default true\n\t */\n\tguards?: boolean;\n\n\t/**\n\t * Force showTotalCount for all lazy (non-eager) tables.\n\t * When enabled, all lazy tables will request total row count from backend,\n\t * overriding individual table's showTotalCount setting.\n\t * @default false\n\t */\n\tforceShowTotalCountForLazyTables?: boolean;\n\n\t/**\n\t * Enable inline header filters in DataGrid tables.\n\t * Requires MUI X Pro license (`muiProLicenseKey` must be set).\n\t * When enabled, each column header shows an inline filter input,\n\t * replacing the standalone filter panel for a more streamlined UX.\n\t * @default false\n\t */\n\theaderFilters?: boolean;\n}\n\n/**\n * Runtime configuration available to components.\n */\nexport interface RuntimeConfig {\n\tfeatures?: FeaturesConfig;\n\t/**\n\t * UI density level from theme configuration.\n\t * @default 'compact'\n\t */\n\tdensity?: \"compact\" | \"comfortable\" | \"standard\";\n\t/**\n\t * MUI X Pro license key.\n\t * When set, the runtime will activate MUI Pro and automatically wire in\n\t * Pro variants of MUI X components (DataGridPro, DatePickerPro, etc.).\n\t * Requires `@mui/x-data-grid-pro` (and/or other Pro packages) to be installed.\n\t */\n\tmuiProLicenseKey?: string;\n}\n\n/**\n * RuntimeConfig context provides access to runtime feature flags.\n */\nexport interface RuntimeConfigContextType {\n\tconfig: RuntimeConfig;\n}\n\nconst RuntimeConfigContext = createContext<RuntimeConfigContextType | null>(null);\n\nexport interface RuntimeConfigProviderProps {\n\tconfig?: RuntimeConfig;\n\tchildren: ReactNode;\n}\n\n/**\n * Provider for runtime configuration.\n * Typically wraps the app at a high level (e.g., in JudoRuntime).\n */\nexport function RuntimeConfigProvider({ config = {}, children }: RuntimeConfigProviderProps) {\n\treturn <RuntimeConfigContext.Provider value={{ config }}>{children}</RuntimeConfigContext.Provider>;\n}\n\n/**\n * Hook to access runtime configuration.\n * Throws if used outside RuntimeConfigProvider.\n */\nexport function useRuntimeConfig(): RuntimeConfigContextType {\n\tconst context = useContext(RuntimeConfigContext);\n\tif (!context) {\n\t\tthrow new Error(\"useRuntimeConfig must be used within RuntimeConfigProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access runtime configuration (optional).\n * Returns null if used outside RuntimeConfigProvider.\n */\nexport function useRuntimeConfigOptional(): RuntimeConfigContextType | null {\n\treturn useContext(RuntimeConfigContext);\n}\n","import type { Action } from \"@judo/actions\";\nimport { type ReactNode, createContext, useContext } from \"react\";\n\n/**\n * Dispatch function type for actions.\n */\nexport type DispatchFn = (action: Action) => Promise<unknown>;\n\n/**\n * Dispatch context type.\n */\nexport interface DispatchContextType {\n\t/** Dispatch an action */\n\tdispatch: DispatchFn;\n}\n\nconst DispatchContext = createContext<DispatchContextType | null>(null);\n\n/**\n * Hook to access dispatch context.\n *\n * @returns DispatchContextType\n * @throws Error if used outside DispatchProvider\n */\nexport function useDispatch(): DispatchContextType {\n\tconst context = useContext(DispatchContext);\n\tif (!context) {\n\t\tthrow new Error(\"useDispatch must be used within DispatchProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access dispatch context (optional).\n *\n * @returns DispatchContextType | null\n */\nexport function useDispatchOptional(): DispatchContextType | null {\n\treturn useContext(DispatchContext);\n}\n\n/**\n * Props for DispatchProvider.\n */\nexport interface DispatchProviderProps {\n\tchildren: ReactNode;\n\tdispatch: DispatchFn;\n}\n\n/**\n * Provider for dispatch context.\n * Provides the dispatch function to all child components.\n */\nexport function DispatchProvider({ children, dispatch }: DispatchProviderProps) {\n\tconst value: DispatchContextType = { dispatch };\n\n\treturn <DispatchContext.Provider value={value}>{children}</DispatchContext.Provider>;\n}\n","import type { ComponentType, ReactElement } from \"react\";\nimport type {\n\tActionLifecycle,\n\tAnyComponentInterceptor,\n\tItemContainerConfig,\n\tColumnCustomizerFn,\n\tCustomComponent,\n\tCustomizationsConfig,\n\tDateValidationProps,\n\tGuestPageProps,\n\tHeroComponentProps,\n\tNavigationItem,\n\tPageCustomization,\n\tSubThemeHook,\n\tTableRowHighlightConfig,\n\tVisualPropertyOverrides,\n\tVisualPropertySet,\n} from \"@judo/model-api\";\nimport type { PageDefinition, VisualElement } from \"@judo/model-api\";\nimport {\n\ttype ReactNode,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\nimport type { DataStoreState } from \"../store\";\nimport { useDataStoreOptional } from \"./data-context\";\nimport { usePageContextOptional } from \"./page-context\";\n\n// ============================================\n// CONTEXT VALUE TYPE\n// ============================================\n\n/**\n * @internal Context value for the customizations system.\n *\n * This is a framework-internal contract. Developers access customizations\n * through the generated `createCustomizations()` factory, not this context directly.\n */\nexport interface CustomizationsContextType {\n\t/** Internal version counter for HMR / change detection */\n\tversion: number;\n\t/** @internal Get the page customization bundle (keyed by page's xmi:id, resolved from the model element) */\n\tgetPageCustomization(pageSourceId: string): PageCustomization | undefined;\n\t/** @internal Get the custom component (keyed by element's xmi:id, resolved from the model element) */\n\tgetComponent(elementSourceId: string): CustomComponent | undefined;\n\t/** Get the component interceptor for an element @type */\n\tgetComponentInterceptor(elementType: string): AnyComponentInterceptor | undefined;\n\t/** Get the sub-theme provider for a named sub-theme */\n\tgetSubThemeProvider(subThemeName: string): SubThemeHook | undefined;\n\t/** Get the redirect handler component for the /_redirect route */\n\tgetRedirectHandler(): ComponentType | undefined;\n\t/** Get custom routes to inject into the router */\n\tgetCustomRoutes(): Array<{ path: string; element: ReactElement }> | undefined;\n\t/** Get the menu customizer function */\n\tgetMenuCustomizer(): ((items: NavigationItem[]) => NavigationItem[]) | undefined;\n\t/** Get the footer text (static or dynamic) */\n\tgetFooterText(): string | (() => string) | undefined;\n\t/** Get the custom hero component for the AppBar */\n\tgetHeroComponent(): ComponentType<HeroComponentProps> | undefined;\n\t/** Get the settings page component */\n\tgetSettingsPage(): ComponentType | undefined;\n\t/** Get the custom guest page component (for supportGuestAccess mode) */\n\tgetGuestComponent(): ComponentType<GuestPageProps> | undefined;\n}\n\nconst CustomizationsContext = createContext<CustomizationsContextType | null>(null);\n\n// ============================================\n// HOOKS\n// ============================================\n\n/**\n * Hook to access customizations context.\n * @throws Error if used outside CustomizationsProvider\n */\nexport function useCustomizations(): CustomizationsContextType {\n\tconst context = useContext(CustomizationsContext);\n\tif (!context) {\n\t\tthrow new Error(\"useCustomizations must be used within CustomizationsProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access customizations context (optional).\n * Returns null if no CustomizationsProvider is in the tree.\n */\nexport function useCustomizationsOptional(): CustomizationsContextType | null {\n\treturn useContext(CustomizationsContext);\n}\n\n/**\n * Returns the custom component for a visual element, if registered.\n *\n * @internal This is a framework-internal hook used by `VisualElementRenderer`.\n * Developers register component overrides via the type-safe `createCustomizations()`\n * factory using human-readable names — never raw sourceIds.\n *\n * @param element - The VisualElement model object (identity resolved from element[\"xmi:id\"])\n * @returns The custom component or null\n */\nexport function useComponentOverride(element: VisualElement): CustomComponent | null {\n\tconst customizations = useCustomizationsOptional();\n\tif (!customizations) return null;\n\n\tconst sourceId = element[\"xmi:id\"];\n\tif (!sourceId) return null;\n\n\treturn customizations.getComponent(sourceId) ?? null;\n}\n\n/**\n * Returns an intercepted component for a visual element based on its @type.\n *\n * @internal This is a framework-internal hook used by `VisualElementRenderer`.\n * Developers register interceptors via the type-safe `createCustomizations()`\n * factory using the `componentInterceptors` property with human-readable @type keys\n * (e.g., 'TextInput', 'Table').\n *\n * Called after `useComponentOverride` (per-element override takes priority over type interceptor).\n *\n * @param element - The VisualElement model object\n * @returns The intercepted custom component or null\n */\nexport function useComponentInterceptor(element: VisualElement): CustomComponent | null {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tif (!customizations || !pageContext) return null;\n\n\tconst elementType = element[\"@type\"];\n\tif (!elementType) return null;\n\n\tconst interceptor = customizations.getComponentInterceptor(elementType);\n\tif (!interceptor) return null;\n\n\treturn interceptor(element, pageContext.pageDefinition) ?? null;\n}\n\n/**\n * Returns the sub-theme provider hook for an element's `subTheme` property.\n *\n * @internal This is a framework-internal hook used by `SubThemeWrapper`.\n * Developers register sub-theme providers via the type-safe `createCustomizations()`\n * factory using the `subThemeProviders` property with human-readable sub-theme names.\n *\n * @param element - The VisualElement model object (must have `subTheme` property)\n * @returns The SubThemeHook or null if not registered\n */\nexport function useSubThemeProvider(element: VisualElement): SubThemeHook | null {\n\tconst customizations = useCustomizationsOptional();\n\tif (!customizations) return null;\n\n\tconst subThemeName = element.subTheme;\n\tif (!subThemeName) return null;\n\n\treturn customizations.getSubThemeProvider(subThemeName) ?? null;\n}\n\n/**\n * Returns the action lifecycle overrides for a specific action on a page.\n * Used by the action dispatch system to compose overrides with built-in handlers.\n *\n * @param page - The PageDefinition\n * @param action - The Action to check\n * @returns Partial ActionLifecycle or null\n */\nexport function usePageActionOverrides(\n\tpage: PageDefinition | undefined,\n\taction: { \"xmi:id\"?: string } | undefined\n): Partial<ActionLifecycle> | null {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\n\t// Use provided page or fall back to current page context\n\tconst effectivePage = page ?? pageContext?.pageDefinition;\n\n\tif (!customizations || !effectivePage || !action) return null;\n\n\tconst pageSourceId = effectivePage[\"xmi:id\"];\n\tif (!pageSourceId) return null;\n\n\tconst pageCustomization = customizations.getPageCustomization(pageSourceId);\n\tif (!pageCustomization?.actions) return null;\n\n\t// Note: the hook is called at the provider level (PageActionOverridesProvider),\n\t// not here. This function is called with the already-resolved overrides.\n\t// However, for direct usage we can resolve inline.\n\tconst actionSourceId = action[\"xmi:id\"];\n\tif (!actionSourceId) return null;\n\n\treturn null; // Resolved at provider level, not here\n}\n\n/**\n * Returns visual property overrides for an element on the current page.\n *\n * @internal This is a framework-internal hook used by `useVisualBinding` and component renderers.\n * Developers provide visual property overrides via the type-safe `createCustomizations()`\n * factory using human-readable element names within page scopes.\n *\n * @param element - The VisualElement model object\n * @returns Partial VisualPropertySet or null\n */\nexport function useVisualPropertyOverrides(element: VisualElement): Partial<VisualPropertySet> | null {\n\tconst ctx = useContext(VisualPropertiesContext);\n\tif (!ctx) return null;\n\n\tconst sourceId = element[\"xmi:id\"];\n\tif (!sourceId) return null;\n\n\treturn ctx[sourceId] ?? null;\n}\n\n/**\n * Returns the typeahead provider for a text input element on the current page.\n *\n * @internal This is a framework-internal hook called by input renderers.\n * Developers register typeahead providers via the type-safe `createCustomizations()`\n * factory using human-readable element names.\n *\n * @param elementSourceId - The element's xmi:id (resolved from the model object, not developer-supplied)\n * @returns The typeahead provider function, or undefined if not registered\n */\nexport function useTypeaheadProvider(\n\telementSourceId: string | undefined\n): ((text: string) => Promise<string[]>) | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tif (!customizations || !pageContext || !elementSourceId) return undefined;\n\n\tconst pageSourceId = pageContext.pageDefinition?.[\"xmi:id\"];\n\tif (!pageSourceId) return undefined;\n\n\treturn customizations.getPageCustomization(pageSourceId)?.typeaheadProviders?.[elementSourceId];\n}\n\n/**\n * Returns the row highlighting configuration for a table element on the current page.\n *\n * @internal This is a framework-internal hook called by `TableRenderer`.\n * Developers register row highlighting via the type-safe `createCustomizations()`\n * factory using human-readable table element names.\n *\n * @param elementSourceId - The element's xmi:id (resolved from the model object, not developer-supplied)\n * @returns Array of highlight configs, or undefined if not registered\n */\nexport function useTableRowHighlighting(elementSourceId: string | undefined): TableRowHighlightConfig[] | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tif (!customizations || !pageContext || !elementSourceId) return undefined;\n\n\tconst pageSourceId = pageContext.pageDefinition?.[\"xmi:id\"];\n\tif (!pageSourceId) return undefined;\n\n\treturn customizations.getPageCustomization(pageSourceId)?.tableRowHighlighting?.[elementSourceId];\n}\n\n/**\n * Returns a wrapped enumeration option filter for an enum input element on the current page.\n *\n * @internal This is a framework-internal hook called by `InputRenderer`.\n * Developers register enum filters via the type-safe `createCustomizations()`\n * factory using human-readable element names.\n *\n * @param elementSourceId - The element's xmi:id (resolved from the model object, not developer-supplied)\n * @returns A function that takes options and returns filtered options, or undefined if not registered\n */\nexport function useEnumOptionFilter(\n\telementSourceId: string | undefined\n): ((options: Array<{ value: string; label: string }>) => Array<{ value: string; label: string }>) | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tconst store = useDataStoreOptional();\n\n\tconst pageSourceId =\n\t\tcustomizations && pageContext && elementSourceId ? pageContext.pageDefinition?.[\"xmi:id\"] : undefined;\n\tconst filterFn = pageSourceId\n\t\t? customizations?.getPageCustomization(pageSourceId)?.enumOptionFilter?.[elementSourceId!]\n\t\t: undefined;\n\n\t// Subscribe to transfer data changes when a filter is configured.\n\t// When no filter, selector always returns undefined (no extra re-renders).\n\tconst transferId = pageContext?.transferId ?? \"\";\n\tconst hasFilter = !!filterFn;\n\n\tconst selector = useCallback(\n\t\t(state: DataStoreState) => {\n\t\t\tif (!hasFilter) return undefined;\n\t\t\treturn (state.transfers.get(transferId)?.data as Record<string, unknown> | undefined) ?? undefined;\n\t\t},\n\t\t[transferId, hasFilter]\n\t);\n\n\tconst subscribe = useCallback(\n\t\t(cb: () => void) => (store ? store.subscribe(selector, cb) : () => {}),\n\t\t[store, selector]\n\t);\n\n\tconst getSnapshot = useCallback(() => (store ? store.getSnapshot(selector) : undefined), [store, selector]);\n\n\tconst entityData = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n\t// Memoize wrapper to avoid re-creating on every render when filter + data haven't changed\n\treturn useMemo(() => {\n\t\tif (!filterFn) return undefined;\n\t\treturn (options: Array<{ value: string; label: string }>) => filterFn(entityData, options);\n\t}, [filterFn, entityData]);\n}\n\n/**\n * Returns resolved date validation props for a date/datetime input element on the current page.\n *\n * @internal This is a framework-internal hook called by date input renderers.\n * Developers register date validation via the type-safe `createCustomizations()`\n * factory using human-readable element names.\n *\n * @param elementSourceId - The element's xmi:id (resolved from the model object, not developer-supplied)\n * @returns Resolved date validation props, or undefined if not registered\n */\nexport function useDateValidationProps(elementSourceId: string | undefined): DateValidationProps | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tconst store = useDataStoreOptional();\n\n\tconst pageSourceId =\n\t\tcustomizations && pageContext && elementSourceId ? pageContext.pageDefinition?.[\"xmi:id\"] : undefined;\n\tconst validationFn = pageSourceId\n\t\t? customizations?.getPageCustomization(pageSourceId)?.dateValidationProps?.[elementSourceId!]\n\t\t: undefined;\n\n\t// Subscribe to transfer data changes when a validation fn is configured.\n\tconst transferId = pageContext?.transferId ?? \"\";\n\tconst hasValidation = !!validationFn;\n\n\tconst selector = useCallback(\n\t\t(state: DataStoreState) => {\n\t\t\tif (!hasValidation) return undefined;\n\t\t\treturn (state.transfers.get(transferId)?.data as Record<string, unknown> | undefined) ?? undefined;\n\t\t},\n\t\t[transferId, hasValidation]\n\t);\n\n\tconst subscribe = useCallback(\n\t\t(cb: () => void) => (store ? store.subscribe(selector, cb) : () => {}),\n\t\t[store, selector]\n\t);\n\n\tconst getSnapshot = useCallback(() => (store ? store.getSnapshot(selector) : undefined), [store, selector]);\n\n\tconst entityData = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n\treturn useMemo(() => {\n\t\tif (!validationFn) return undefined;\n\t\treturn validationFn(entityData);\n\t}, [validationFn, entityData]);\n}\n\n/**\n * Returns all column customizer functions for the current page.\n *\n * @internal This is a framework-internal hook called by `TableRenderer`.\n * Developers register column customizers via the type-safe `createCustomizations()`\n * factory using human-readable column element names.\n *\n * @returns Record of column xmi:id → customizer function, or undefined if not registered\n */\nexport function useColumnCustomizers(): Record<string, ColumnCustomizerFn> | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tif (!customizations || !pageContext) return undefined;\n\n\tconst pageSourceId = pageContext.pageDefinition?.[\"xmi:id\"];\n\tif (!pageSourceId) return undefined;\n\n\treturn customizations.getPageCustomization(pageSourceId)?.columnCustomizers;\n}\n\n/**\n * Returns the item container configuration for a specific table element.\n *\n * @internal This is a framework-internal hook called by `TableRenderer`.\n * Developers register item container configs via the type-safe `createCustomizations()`\n * factory using human-readable table element names.\n *\n * @param elementSourceId - The element's xmi:id (resolved from the model object, not developer-supplied)\n * @returns Item container config or undefined if not registered\n */\nexport function useItemContainerConfig(elementSourceId: string | undefined): ItemContainerConfig | undefined {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\tif (!customizations || !pageContext || !elementSourceId) return undefined;\n\n\tconst pageSourceId = pageContext.pageDefinition?.[\"xmi:id\"];\n\tif (!pageSourceId) return undefined;\n\n\treturn customizations.getPageCustomization(pageSourceId)?.itemContainerConfigs?.[elementSourceId];\n}\n\n// ============================================\n// PAGE ACTION OVERRIDES CONTEXT\n// ============================================\n\n/**\n * @internal Resolved action overrides for the current page.\n * Key: action xmi:id (resolved internally), Value: lifecycle overrides\n */\nconst PageActionOverridesContext = createContext<Record<string, Partial<ActionLifecycle>> | null>(null);\n\n/**\n * @internal Hook to get the resolved action overrides for the current page.\n * Returns all action overrides keyed by action xmi:id.\n */\nexport function useResolvedPageActionOverrides(): Record<string, Partial<ActionLifecycle>> | null {\n\treturn useContext(PageActionOverridesContext);\n}\n\n/**\n * @internal Get lifecycle overrides for a specific action.\n * The actionSourceId is the action's xmi:id, resolved from the Action model object\n * (not developer-supplied).\n */\nexport function useActionLifecycleOverrides(actionSourceId: string | undefined): Partial<ActionLifecycle> | null {\n\tconst overrides = useContext(PageActionOverridesContext);\n\tif (!overrides || !actionSourceId) return null;\n\treturn overrides[actionSourceId] ?? null;\n}\n\n/**\n * Provider that calls the registered page action hook and provides\n * the resolved overrides to descendants.\n * Must be rendered inside PageProvider.\n */\nexport function PageActionOverridesProvider({ children }: { children: ReactNode }) {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\n\tconst pageSourceId = pageContext?.pageDefinition?.[\"xmi:id\"];\n\tconst actionsHook = pageSourceId ? customizations?.getPageCustomization(pageSourceId)?.actions : undefined;\n\n\t// Call the hook (always, to respect rules of hooks)\n\t// If no hook registered, use a no-op that returns empty\n\tconst overrides = actionsHook ? actionsHook() : null;\n\n\treturn <PageActionOverridesContext.Provider value={overrides}>{children}</PageActionOverridesContext.Provider>;\n}\n\n// ============================================\n// VISUAL PROPERTIES CONTEXT\n// ============================================\n\nconst VisualPropertiesContext = createContext<VisualPropertyOverrides | null>(null);\n\n/**\n * Provider that calls the registered visual properties hook and provides\n * the resolved overrides to descendants.\n * Must be rendered inside PageProvider.\n */\nexport function VisualPropertiesProvider({ children }: { children: ReactNode }) {\n\tconst customizations = useCustomizationsOptional();\n\tconst pageContext = usePageContextOptional();\n\n\tconst pageSourceId = pageContext?.pageDefinition?.[\"xmi:id\"];\n\tconst visualHook = pageSourceId ? customizations?.getPageCustomization(pageSourceId)?.visualProperties : undefined;\n\n\t// Call the hook (always, to respect rules of hooks)\n\tconst overrides = visualHook ? visualHook() : null;\n\n\treturn <VisualPropertiesContext.Provider value={overrides}>{children}</VisualPropertiesContext.Provider>;\n}\n\n// ============================================\n// CUSTOMIZATIONS PROVIDER\n// ============================================\n\n/**\n * Props for CustomizationsProvider.\n */\nexport interface CustomizationsProviderProps {\n\tchildren: ReactNode;\n\t/** The customizations config (from createCustomizations() or manually built) */\n\tcustomizations?: CustomizationsConfig | null;\n}\n\n/**\n * Provider for the customizations system.\n *\n * Stores the config in a ref and uses a version counter for HMR support.\n * When the customizations object identity changes (e.g., during HMR),\n * the version bumps and all consumers re-render with new values.\n *\n * @example\n * ```tsx\n * <CustomizationsProvider customizations={myCustomizations}>\n * <JudoRuntime modelSource=\"/models/app.model\" />\n * </CustomizationsProvider>\n * ```\n */\nexport function CustomizationsProvider({ children, customizations }: CustomizationsProviderProps) {\n\tconst configRef = useRef(customizations ?? null);\n\tconst [version, setVersion] = useState(0);\n\n\t// Update ref + bump version when customizations object identity changes (HMR support)\n\tuseEffect(() => {\n\t\tconfigRef.current = customizations ?? null;\n\t\tsetVersion((v) => v + 1);\n\t}, [customizations]);\n\n\tconst value = useMemo<CustomizationsContextType>(\n\t\t() => ({\n\t\t\tversion,\n\t\t\tgetPageCustomization: (id: string) => configRef.current?.pages?.[id],\n\t\t\tgetComponent: (id: string) => configRef.current?.components?.[id],\n\t\t\tgetComponentInterceptor: (elementType: string) =>\n\t\t\t\t(configRef.current?.componentInterceptors as Record<string, AnyComponentInterceptor> | undefined)?.[\n\t\t\t\t\telementType\n\t\t\t\t],\n\t\t\tgetSubThemeProvider: (name: string) => configRef.current?.subThemeProviders?.[name],\n\t\t\tgetRedirectHandler: () => configRef.current?.redirectHandler,\n\t\t\tgetCustomRoutes: () => configRef.current?.customRoutes,\n\t\t\tgetMenuCustomizer: () => configRef.current?.menuCustomizer,\n\t\t\tgetFooterText: () => configRef.current?.footerText,\n\t\t\tgetHeroComponent: () => configRef.current?.heroComponent,\n\t\t\tgetSettingsPage: () => configRef.current?.settingsPage,\n\t\t\tgetGuestComponent: () => configRef.current?.guestComponent,\n\t\t}),\n\t\t[version]\n\t);\n\n\treturn <CustomizationsContext.Provider value={value}>{children}</CustomizationsContext.Provider>;\n}\n","import { type MutableRefObject, type ReactNode, createContext, useContext, useRef } from \"react\";\n\n/**\n * Selector selection context type.\n * Provides a mutable ref that TableRenderer writes selected transfers to,\n * and dialog footer buttons read from when dispatching Add/Set actions.\n *\n * Uses a ref instead of state to avoid re-renders when selection changes -\n * the value is only read at dispatch time.\n */\nexport interface SelectorSelectionContextType {\n\t/** Mutable ref holding the currently selected transfers */\n\tselectedTransfersRef: MutableRefObject<unknown[]>;\n\t/** The owner transfer for the selector (who owns the relation) */\n\townerTransfer?: unknown;\n}\n\nconst SelectorSelectionContext = createContext<SelectorSelectionContextType | null>(null);\n\n/**\n * Hook to access selector selection context.\n *\n * @returns SelectorSelectionContextType\n * @throws Error if used outside SelectorSelectionProvider\n */\nexport function useSelectorSelection(): SelectorSelectionContextType {\n\tconst context = useContext(SelectorSelectionContext);\n\tif (!context) {\n\t\tthrow new Error(\"useSelectorSelection must be used within SelectorSelectionProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access selector selection context (optional).\n * Returns null when not inside a selector dialog.\n *\n * @returns SelectorSelectionContextType | null\n */\nexport function useSelectorSelectionOptional(): SelectorSelectionContextType | null {\n\treturn useContext(SelectorSelectionContext);\n}\n\n/**\n * Props for SelectorSelectionProvider.\n */\nexport interface SelectorSelectionProviderProps {\n\tchildren: ReactNode;\n\t/** The owner transfer for the selector relation */\n\townerTransfer?: unknown;\n}\n\n/**\n * Provider for selector selection state.\n * Wraps selector dialog content to enable sharing selection state\n * between TableRenderer (writer) and dialog footer buttons (reader).\n */\nexport function SelectorSelectionProvider({ children, ownerTransfer }: SelectorSelectionProviderProps) {\n\tconst selectedTransfersRef = useRef<unknown[]>([]);\n\n\tconst value: SelectorSelectionContextType = { selectedTransfersRef, ownerTransfer };\n\n\treturn <SelectorSelectionContext.Provider value={value}>{children}</SelectorSelectionContext.Provider>;\n}\n","import { type ComponentType, type ReactNode, createContext, useCallback, useContext, useMemo } from \"react\";\n\n/**\n * MUI Pro components context.\n *\n * When MUI X Pro is available (license key set + pro packages installed),\n * components can retrieve upgraded Pro variants (e.g., DataGridPro instead of DataGrid)\n * via the `getComponent` helper.\n */\nexport interface MuiProContextType {\n\t/** Whether MUI Pro features are enabled (license key present and activated). */\n\tisProEnabled: boolean;\n\t/**\n\t * Retrieve a MUI Pro component by name.\n\t * Returns `null` if Pro is not enabled or the component was not registered.\n\t *\n\t * Known component names:\n\t * - `\"DataGrid\"` → `DataGridPro` from `@mui/x-data-grid-pro`\n\t */\n\tgetComponent: (name: string) => ComponentType<any> | null;\n}\n\nconst MuiProContext = createContext<MuiProContextType | null>(null);\n\nexport interface MuiProProviderProps {\n\t/** Whether MUI Pro is enabled. */\n\tisProEnabled: boolean;\n\t/**\n\t * Map of Pro component names to actual component references.\n\t * Populated during app initialization via dynamic import.\n\t *\n\t * Example: `{ DataGrid: DataGridPro }`\n\t */\n\tcomponents?: Record<string, ComponentType<any>>;\n\tchildren: ReactNode;\n}\n\n/**\n * Provider for MUI Pro components.\n *\n * Typically wrapped around the application by JudoRuntime when a `muiProLicenseKey`\n * is configured. Components use `useMuiPro()` / `useMuiProOptional()` to access\n * Pro-upgraded components.\n */\nexport function MuiProProvider({ isProEnabled, components = {}, children }: MuiProProviderProps) {\n\tconst getComponent = useCallback(\n\t\t(name: string): ComponentType<any> | null => {\n\t\t\tif (!isProEnabled) return null;\n\t\t\treturn components[name] ?? null;\n\t\t},\n\t\t[isProEnabled, components]\n\t);\n\n\tconst value = useMemo<MuiProContextType>(() => ({ isProEnabled, getComponent }), [isProEnabled, getComponent]);\n\n\treturn <MuiProContext.Provider value={value}>{children}</MuiProContext.Provider>;\n}\n\n/**\n * Hook to access MUI Pro context.\n * Throws if used outside MuiProProvider.\n */\nexport function useMuiPro(): MuiProContextType {\n\tconst context = useContext(MuiProContext);\n\tif (!context) {\n\t\tthrow new Error(\"useMuiPro must be used within MuiProProvider\");\n\t}\n\treturn context;\n}\n\n/**\n * Hook to access MUI Pro context (optional).\n * Returns `null` if used outside MuiProProvider.\n * Preferred in library components that should work with or without Pro.\n */\nexport function useMuiProOptional(): MuiProContextType | null {\n\treturn useContext(MuiProContext);\n}\n","import { type ReactNode, createContext, useContext } from \"react\";\n\n/**\n * Context that carries a page-level refresh signal.\n *\n * ViewContainerRenderer increments the signal after successful operations;\n * embedded components (TableRenderer, LinkRenderer, etc.) watch it and\n * re-dispatch their own onInit / refresh logic when it changes.\n *\n * The initial value is 0 (no refresh requested). A value > 0 means a\n * refresh has been requested that many times since mount.\n */\nconst RefreshSignalContext = createContext<number>(0);\n\n/**\n * Read the current refresh signal value.\n * Returns 0 when used outside a RefreshSignalProvider.\n */\nexport function useRefreshSignal(): number {\n\treturn useContext(RefreshSignalContext);\n}\n\nexport interface RefreshSignalProviderProps {\n\tchildren: ReactNode;\n\t/** Current refresh signal value (managed by parent container). */\n\tsignal: number;\n}\n\n/**\n * Provides a refresh signal to descendant components.\n * The parent container owns the state and increments `signal` when a\n * page-wide refresh is needed.\n */\nexport function RefreshSignalProvider({ children, signal }: RefreshSignalProviderProps) {\n\treturn <RefreshSignalContext.Provider value={signal}>{children}</RefreshSignalContext.Provider>;\n}\n","import type { VisualElement } from \"@judo/model-api\";\nimport { useValidationContext, useValidationContextOptional } from \"../contexts\";\n\n/**\n * Result from useValidation hook.\n */\nexport interface ValidationResult {\n\t/** Error message or null */\n\terror: string | null;\n\t/** Whether field has been touched */\n\tisTouched: boolean;\n\t/** Mark field as touched */\n\ttouch: () => void;\n\t/** Set error for this field */\n\tsetError: (error: string | null) => void;\n\t/** Clear error for this field */\n\tclearError: () => void;\n}\n\n/**\n * Get field ID from visual element.\n * Uses the element's `name` property as the primary identifier since this matches\n * the `location` field returned by JUDO REST API validation errors.\n *\n * @param element - Visual element\n * @returns Field identifier (element name, or sourceId/xmi:id as fallback)\n */\nfunction getFieldId(element: VisualElement): string {\n\t// Prefer element.name as it matches API validation error locations\n\tif (element.name) {\n\t\treturn element.name;\n\t}\n\t// Fallback to sourceId or xmi:id\n\tconst sourceId = (element as unknown as { sourceId?: string }).sourceId;\n\treturn sourceId || element[\"xmi:id\"];\n}\n\n/**\n * Hook for single element validation.\n *\n * @param element - Visual element\n * @returns ValidationResult\n */\nexport function useValidation(element: VisualElement): ValidationResult {\n\tconst validation = useValidationContextOptional();\n\tconst fieldId = getFieldId(element);\n\n\tif (!validation) {\n\t\t// Return stub when no validation context\n\t\treturn {\n\t\t\terror: null,\n\t\t\tisTouched: false,\n\t\t\ttouch: () => {},\n\t\t\tsetError: () => {},\n\t\t\tclearError: () => {},\n\t\t};\n\t}\n\n\tconst isTouched = validation.isTouched(fieldId);\n\tconst error = isTouched ? validation.getError(fieldId) : null;\n\n\treturn {\n\t\terror,\n\t\tisTouched,\n\t\ttouch: () => validation.touch(fieldId),\n\t\tsetError: (newError: string | null) => validation.setError(fieldId, newError),\n\t\tclearError: () => validation.clearError(fieldId),\n\t};\n}\n\n/**\n * Hook for form validation.\n * Requires ValidationProvider.\n *\n * @returns Full validation context\n * @throws Error if used outside ValidationProvider\n */\nexport function useFormValidation() {\n\treturn useValidationContext();\n}\n","import type { AttributeType, Input, VisualElement } from \"@judo/model-api\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { useDataStore } from \"../contexts\";\nimport { usePageContext } from \"../contexts\";\nimport { useVisualPropertyOverrides } from \"../contexts\";\nimport type { DataStoreState } from \"../store\";\nimport { deepEqual } from \"../utils\";\nimport { useValidation } from \"./use-validation\";\n\n/**\n * Result from useVisualBinding hook.\n */\nexport interface VisualBindingResult {\n\t/** Current value from data store */\n\tvalue: unknown;\n\t/** Change handler */\n\tonChange: (newValue: unknown) => void;\n\t/** Validation error if any */\n\terror: string | null;\n\t/** Whether element is hidden (via hiddenBy or static hidden) */\n\thidden: boolean;\n\t/** Whether field is disabled */\n\tdisabled: boolean;\n\t/** Whether field is required */\n\trequired: boolean;\n\t/** Display label */\n\tlabel: string;\n\t/** Whether field is read-only */\n\treadOnly: boolean;\n\t/** Whether data is loading */\n\tisLoading: boolean;\n\t/** Whether value has changed from original */\n\tisDirty: boolean;\n}\n\n/**\n * Check if element is an Input type.\n */\nfunction isInput(element: VisualElement): element is Input & VisualElement {\n\treturn \"attributeType\" in element;\n}\n\n/**\n * Dedicated hook for visual element to data binding.\n *\n * IMPORTANT: No memoization of values that could corrupt data consistency.\n * Always reads fresh from DataContext via selector subscription.\n *\n * @param element - Visual element to bind\n * @param attributeType - Optional pre-resolved AttributeType\n * @returns VisualBindingResult\n */\nexport function useVisualBinding(element: VisualElement, attributeType?: AttributeType): VisualBindingResult {\n\tconst store = useDataStore();\n\tconst pageContext = usePageContext();\n\tconst transferId = pageContext.transferId ?? \"\";\n\n\t// Resolve attribute name from element or provided attributeType\n\t// element.attributeType is now a resolved AttributeType object, so access .name\n\tconst resolvedAttrType = attributeType ?? (isInput(element) ? element.attributeType : undefined);\n\tconst attributeName = resolvedAttrType?.name;\n\n\t// Warn in development if an Input element has an unresolved attributeType\n\tif (import.meta.env?.DEV && isInput(element) && element.attributeType) {\n\t\tif (typeof element.attributeType === \"string\") {\n\t\t\tconsole.warn(\n\t\t\t\t`[useVisualBinding] element.attributeType is a string reference \"${element.attributeType}\" for element \"${element.name}\". This means model resolution failed. Expected an AttributeType object with 'name' property.`\n\t\t\t);\n\t\t} else if (!element.attributeType.name) {\n\t\t\tconsole.warn(\n\t\t\t\t`[useVisualBinding] element.attributeType is missing 'name' property for element \"${element.name}\". Data binding will not work.`\n\t\t\t);\n\t\t}\n\t}\n\n\t// Resolve *By attribute names for dynamic behavior\n\tconst hiddenByAttr = element.hiddenBy?.name;\n\tconst enabledByAttr = element.enabledBy?.name;\n\tconst requiredByAttr = element.requiredBy?.name;\n\n\t// Cache for selector result to ensure referential stability\n\ttype SelectorResult = {\n\t\tvalue: unknown;\n\t\tisDirty: boolean;\n\t\tisLoading: boolean;\n\t\thiddenByValue: unknown;\n\t\tenabledByValue: unknown;\n\t\trequiredByValue: unknown;\n\t};\n\tconst cacheRef = useRef<SelectorResult>({\n\t\tvalue: undefined,\n\t\tisDirty: false,\n\t\tisLoading: false,\n\t\thiddenByValue: undefined,\n\t\tenabledByValue: undefined,\n\t\trequiredByValue: undefined,\n\t});\n\n\t// Create selector for this specific attribute and *By fields\n\tconst selector = useCallback(\n\t\t(state: DataStoreState): SelectorResult => {\n\t\t\tconst transferState = state.transfers.get(transferId);\n\t\t\tconst data = transferState?.data;\n\n\t\t\tlet newResult: SelectorResult;\n\n\t\t\tif (!attributeName && !hiddenByAttr && !enabledByAttr && !requiredByAttr) {\n\t\t\t\tnewResult = {\n\t\t\t\t\tvalue: undefined,\n\t\t\t\t\tisDirty: false,\n\t\t\t\t\tisLoading: transferState?.isLoading ?? false,\n\t\t\t\t\thiddenByValue: undefined,\n\t\t\t\t\tenabledByValue: undefined,\n\t\t\t\t\trequiredByValue: undefined,\n\t\t\t\t};\n\t\t\t} else if (!data) {\n\t\t\t\tnewResult = {\n\t\t\t\t\tvalue: undefined,\n\t\t\t\t\tisDirty: false,\n\t\t\t\t\tisLoading: transferState?.isLoading ?? false,\n\t\t\t\t\thiddenByValue: undefined,\n\t\t\t\t\tenabledByValue: undefined,\n\t\t\t\t\trequiredByValue: undefined,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tnewResult = {\n\t\t\t\t\tvalue: attributeName ? data[attributeName] : undefined,\n\t\t\t\t\tisDirty: transferState.isDirty,\n\t\t\t\t\tisLoading: transferState.isLoading,\n\t\t\t\t\thiddenByValue: hiddenByAttr ? data[hiddenByAttr] : undefined,\n\t\t\t\t\tenabledByValue: enabledByAttr ? data[enabledByAttr] : undefined,\n\t\t\t\t\trequiredByValue: requiredByAttr ? data[requiredByAttr] : undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Return cached result if values are equal (referential stability for useSyncExternalStore)\n\t\t\tif (deepEqual(cacheRef.current, newResult)) {\n\t\t\t\treturn cacheRef.current;\n\t\t\t}\n\t\t\tcacheRef.current = newResult;\n\t\t\treturn newResult;\n\t\t},\n\t\t[transferId, attributeName, hiddenByAttr, enabledByAttr, requiredByAttr]\n\t);\n\n\t// Subscribe to data changes for this selector\n\tconst subscribe = useCallback((cb: () => void) => store.subscribe(selector, cb), [store, selector]);\n\n\tconst getSnapshot = useCallback(() => store.getSnapshot(selector), [store, selector]);\n\n\tconst { value, isDirty, isLoading, hiddenByValue, enabledByValue, requiredByValue } = useSyncExternalStore(\n\t\tsubscribe,\n\t\tgetSnapshot,\n\t\tgetSnapshot\n\t);\n\n\t// Change handler - no debounce, immediate update\n\tconst onChange = useCallback(\n\t\t(newValue: unknown) => {\n\t\t\tif (!attributeName) return;\n\t\t\tstore.updateTransferField(transferId, attributeName, newValue);\n\t\t},\n\t\t[store, transferId, attributeName]\n\t);\n\n\t// Resolve validation state\n\tconst { error } = useValidation(element);\n\n\t// Helper to convert value to boolean (handles string \"true\"/\"false\" from XML)\n\tconst toBoolean = (val: unknown, defaultValue: boolean): boolean => {\n\t\tif (typeof val === \"boolean\") return val;\n\t\tif (val === \"true\") return true;\n\t\tif (val === \"false\") return false;\n\t\treturn defaultValue;\n\t};\n\n\t// Get element properties with fallbacks\n\tlet disabled = toBoolean((element as unknown as Record<string, unknown>).disabled, false);\n\tlet required = isInput(element)\n\t\t? toBoolean((element as Input).required, false) || toBoolean(resolvedAttrType?.isRequired, false)\n\t\t: false;\n\tconst label = ((element as unknown as Record<string, unknown>).label as string) ?? resolvedAttrType?.name ?? \"\";\n\tconst elementReadOnly = (element as unknown as Record<string, unknown>).readOnly;\n\tconst attrReadOnly = resolvedAttrType?.isReadOnly;\n\tconst readOnly = toBoolean(elementReadOnly ?? attrReadOnly, false);\n\n\t// Apply *By dynamic overrides (data-driven, between static and customization overrides)\n\t// hiddenBy: if referenced boolean field is true → element is hidden\n\tlet hidden = toBoolean((element as unknown as Record<string, unknown>).hidden, false);\n\tif (hiddenByAttr && toBoolean(hiddenByValue, false)) {\n\t\thidden = true;\n\t}\n\t// enabledBy: when present, fully controls disabled state\n\t// referenced boolean true → enabled (disabled=false), false → disabled (disabled=true)\n\tif (enabledByAttr) {\n\t\tdisabled = !toBoolean(enabledByValue, false);\n\t}\n\t// requiredBy: if referenced boolean field is true → element is required\n\tif (requiredByAttr && toBoolean(requiredByValue, false)) {\n\t\trequired = true;\n\t}\n\n\t// Visual property overrides (from CustomizationsProvider) - highest priority\n\tconst propertyOverrides = useVisualPropertyOverrides(element);\n\n\treturn {\n\t\tvalue,\n\t\tonChange,\n\t\terror,\n\t\thidden: propertyOverrides?.hidden ?? hidden,\n\t\tdisabled: propertyOverrides?.disabled ?? disabled,\n\t\trequired: propertyOverrides?.required ?? required,\n\t\tlabel: propertyOverrides?.label ?? label,\n\t\treadOnly: propertyOverrides?.readOnly ?? readOnly,\n\t\tisLoading,\n\t\tisDirty,\n\t};\n}\n","import { useCallback, useSyncExternalStore } from \"react\";\nimport { useDataStore } from \"../contexts\";\nimport type { DataSelector, StrictTransferData, TransferState } from \"../store\";\n\n/**\n * Hook for selector-based data subscriptions.\n * Only re-renders when selected value changes.\n *\n * @param selector - Function to select data from state\n * @returns Selected value\n */\nexport function useDataSelector<T>(selector: DataSelector<T>): T {\n\tconst store = useDataStore();\n\n\tconst subscribe = useCallback((cb: () => void) => store.subscribe(selector, cb), [store, selector]);\n\n\tconst getSnapshot = useCallback(() => store.getSnapshot(selector), [store, selector]);\n\n\treturn useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Hook for transfer state by ID.\n *\n * When called with an explicit type parameter the returned `data` / `originalData`\n * fields are narrowed to `StrictTransferData<T> | null`.\n *\n * @typeParam T - Optional strict transfer shape\n * @param transferId - Transfer identifier\n * @returns TransferState (optionally narrowed) or undefined\n */\nexport function useTransferState<T extends Record<string, unknown> = Record<string, unknown>>(\n\ttransferId: string\n): (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null }) | undefined {\n\tconst selector = useCallback(\n\t\t(state: { transfers: Map<string, TransferState> }) => state.transfers.get(transferId),\n\t\t[transferId]\n\t);\n\n\treturn useDataSelector(selector) as\n\t\t| (TransferState & { data: StrictTransferData<T> | null; originalData: StrictTransferData<T> | null })\n\t\t| undefined;\n}\n\n/**\n * Hook for transfer field value.\n *\n * When called with an explicit type parameter `T` and field `K`, the return type\n * is narrowed to `T[K] | undefined`.\n *\n * @typeParam T - Optional strict transfer shape\n * @typeParam K - Field key (restricted to `keyof T` when strict)\n * @param transferId - Transfer identifier\n * @param field - Field name\n * @returns Field value (typed to `T[K]` when strict)\n */\nexport function useTransferField<\n\tT extends Record<string, unknown> = Record<string, unknown>,\n\tK extends string & keyof T = string & keyof T,\n>(transferId: string, field: K): T[K] | undefined {\n\tconst selector = useCallback(\n\t\t(state: { transfers: Map<string, TransferState> }) => state.transfers.get(transferId)?.data?.[field],\n\t\t[transferId, field]\n\t);\n\n\treturn useDataSelector(selector) as T[K] | undefined;\n}\n\n/**\n * Hook for transfer loading state.\n *\n * @param transferId - Transfer identifier\n * @returns Loading state\n */\nexport function useTransferLoading(transferId: string): boolean {\n\tconst selector = useCallback(\n\t\t(state: { transfers: Map<string, TransferState> }) => state.transfers.get(transferId)?.isLoading ?? false,\n\t\t[transferId]\n\t);\n\n\treturn useDataSelector(selector);\n}\n\n/**\n * Hook for transfer dirty state.\n *\n * @param transferId - Transfer identifier\n * @returns Dirty state\n */\nexport function useTransferDirty(transferId: string): boolean {\n\tconst selector = useCallback(\n\t\t(state: { transfers: Map<string, TransferState> }) => state.transfers.get(transferId)?.isDirty ?? false,\n\t\t[transferId]\n\t);\n\n\treturn useDataSelector(selector);\n}\n","import { usePageContextOptional } from \"../contexts\";\nimport { useTransferDirty } from \"./use-data-selector\";\n\n/**\n * Result from useEditMode hook.\n */\nexport interface EditModeResult {\n\t/** Whether the current page is in edit mode (has unsaved changes) */\n\tisEditMode: boolean;\n\t/** The transfer ID being tracked */\n\ttransferId: string | null;\n}\n\n/**\n * Hook to determine if the current page is in edit mode.\n *\n * Edit mode is derived from the DataStore's isDirty state for the current transfer.\n * When a user modifies any field on a VIEW page, the transfer becomes dirty and\n * the page enters edit mode. This affects:\n * - Visibility of Cancel/Save buttons (only shown in edit mode)\n * - Whether navigation away should prompt for unsaved changes\n * - Whether Create actions can navigate to new pages\n *\n * @returns EditModeResult with isEditMode and transferId\n */\nexport function useEditMode(): EditModeResult {\n\tconst pageContext = usePageContextOptional();\n\tconst transferId = pageContext?.transferId ?? null;\n\n\t// Use the existing useTransferDirty hook, but handle null transferId gracefully\n\t// When transferId is null or empty, we're not tracking any transfer\n\tconst isDirty = useTransferDirty(transferId ?? \"\");\n\n\treturn {\n\t\tisEditMode: transferId !== null && isDirty,\n\t\ttransferId,\n\t};\n}\n","import type { VisualElement } from \"@judo/model-api\";\nimport type { ModelRegistry } from \"@judo/model-loader\";\n\n/**\n * Retrieve visual element by sourceId.\n * Note: This is a utility function, not a hook.\n * For reactive updates, use a context-based approach.\n *\n * @param registry - Model registry\n * @param sourceId - Source ID to find\n * @returns VisualElement or undefined\n */\nexport function getVisualElement(registry: ModelRegistry, sourceId: string): VisualElement | undefined {\n\treturn registry.resolveVisualElement(sourceId);\n}\n","import type { VisualElement } from \"@judo/model-api\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { useDataStoreOptional, useVisualPropertyOverrides } from \"../contexts\";\nimport { usePageContextOptional } from \"../contexts\";\nimport type { DataStoreState } from \"../store\";\nimport { deepEqual } from \"../utils\";\n\n// No-op store for when DataProvider is not available\nconst EMPTY_SNAPSHOT = { hiddenByValue: undefined };\n\n/**\n * Hook for evaluating the runtime visibility of any VisualElement.\n *\n * Resolution priority (highest to lowest):\n * 1. VisualPropertyOverrides (customization) — `hidden` field\n * 2. hiddenBy dynamic data — resolved AttributeType boolean field from DataStore\n * 3. Static model property — element.hidden\n *\n * Safe to use outside DataProvider/PageProvider — returns static hidden value when context is unavailable.\n *\n * @param element - The VisualElement to evaluate visibility for\n * @returns `true` if the element should be hidden, `false` otherwise\n */\nexport function useElementVisibility(element: VisualElement): boolean {\n\tconst store = useDataStoreOptional();\n\tconst pageContext = usePageContextOptional();\n\tconst transferId = pageContext?.transferId ?? \"\";\n\n\tconst hiddenByAttr = element.hiddenBy?.name;\n\n\t// Cache for selector result to ensure referential stability\n\tconst cacheRef = useRef<{ hiddenByValue: unknown }>({ hiddenByValue: undefined });\n\n\tconst selector = useCallback(\n\t\t(state: DataStoreState): { hiddenByValue: unknown } => {\n\t\t\tif (!hiddenByAttr) {\n\t\t\t\treturn cacheRef.current;\n\t\t\t}\n\t\t\tconst data = state.transfers.get(transferId)?.data;\n\t\t\tconst newResult = { hiddenByValue: data ? data[hiddenByAttr] : undefined };\n\n\t\t\tif (deepEqual(cacheRef.current, newResult)) {\n\t\t\t\treturn cacheRef.current;\n\t\t\t}\n\t\t\tcacheRef.current = newResult;\n\t\t\treturn newResult;\n\t\t},\n\t\t[transferId, hiddenByAttr]\n\t);\n\n\tconst subscribe = useCallback(\n\t\t(cb: () => void) => (store ? store.subscribe(selector, cb) : () => {}),\n\t\t[store, selector]\n\t);\n\tconst getSnapshot = useCallback(() => (store ? store.getSnapshot(selector) : EMPTY_SNAPSHOT), [store, selector]);\n\n\tconst { hiddenByValue } = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n\t// Resolve hidden: static → *By dynamic → customization override\n\tconst toBoolean = (value: unknown, defaultValue: boolean): boolean => {\n\t\tif (typeof value === \"boolean\") return value;\n\t\tif (value === \"true\") return true;\n\t\tif (value === \"false\") return false;\n\t\treturn defaultValue;\n\t};\n\n\tlet hidden = toBoolean((element as unknown as Record<string, unknown>).hidden, false);\n\n\t// hiddenBy: if referenced boolean field is true → override to hidden\n\tif (hiddenByAttr && toBoolean(hiddenByValue, false)) {\n\t\thidden = true;\n\t}\n\n\t// Customization override wins over everything\n\tconst propertyOverrides = useVisualPropertyOverrides(element);\n\tif (propertyOverrides?.hidden != null) {\n\t\treturn propertyOverrides.hidden;\n\t}\n\n\treturn hidden;\n}\n","import type { VisualElement } from \"@judo/model-api\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { useDataStoreOptional, useVisualPropertyOverrides } from \"../contexts\";\nimport { usePageContextOptional } from \"../contexts\";\nimport type { DataStoreState } from \"../store\";\nimport { deepEqual } from \"../utils\";\n\n// No-op store for when DataProvider is not available\nconst EMPTY_SNAPSHOT = { enabledByValue: undefined };\n\n/**\n * Hook for evaluating the runtime disabled state of any VisualElement.\n *\n * Resolution priority (highest to lowest):\n * 1. VisualPropertyOverrides (customization) — `disabled` field\n * 2. enabledBy dynamic data — if referenced boolean attribute is true, element is **enabled** (not disabled)\n * 3. Static model property — element.disabled\n *\n * Safe to use outside DataProvider/PageProvider — returns static disabled value when context is unavailable.\n *\n * @param element - The VisualElement to evaluate disabled state for\n * @returns `true` if the element should be disabled, `false` otherwise\n */\nexport function useElementDisabled(element: VisualElement): boolean {\n\tconst store = useDataStoreOptional();\n\tconst pageContext = usePageContextOptional();\n\tconst transferId = pageContext?.transferId ?? \"\";\n\n\tconst enabledByAttr = element.enabledBy?.name;\n\n\t// Cache for selector result to ensure referential stability\n\tconst cacheRef = useRef<{ enabledByValue: unknown }>({ enabledByValue: undefined });\n\n\tconst selector = useCallback(\n\t\t(state: DataStoreState): { enabledByValue: unknown } => {\n\t\t\tif (!enabledByAttr) {\n\t\t\t\treturn cacheRef.current;\n\t\t\t}\n\t\t\tconst data = state.transfers.get(transferId)?.data;\n\t\t\tconst newResult = { enabledByValue: data ? data[enabledByAttr] : undefined };\n\n\t\t\tif (deepEqual(cacheRef.current, newResult)) {\n\t\t\t\treturn cacheRef.current;\n\t\t\t}\n\t\t\tcacheRef.current = newResult;\n\t\t\treturn newResult;\n\t\t},\n\t\t[transferId, enabledByAttr]\n\t);\n\n\tconst subscribe = useCallback(\n\t\t(cb: () => void) => (store ? store.subscribe(selector, cb) : () => {}),\n\t\t[store, selector]\n\t);\n\tconst getSnapshot = useCallback(() => (store ? store.getSnapshot(selector) : EMPTY_SNAPSHOT), [store, selector]);\n\n\tconst { enabledByValue } = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n\t// Resolve disabled: static → enabledBy dynamic → customization override\n\tconst toBoolean = (value: unknown, defaultValue: boolean): boolean => {\n\t\tif (typeof value === \"boolean\") return value;\n\t\tif (value === \"true\") return true;\n\t\tif (value === \"false\") return false;\n\t\treturn defaultValue;\n\t};\n\n\tlet disabled = toBoolean((element as unknown as Record<string, unknown>).disabled, false);\n\n\t// enabledBy: when present, fully controls disabled state\n\t// referenced boolean true → enabled (disabled=false), false → disabled (disabled=true)\n\tif (enabledByAttr) {\n\t\tdisabled = !toBoolean(enabledByValue, false);\n\t}\n\n\t// Customization override wins over everything\n\tconst propertyOverrides = useVisualPropertyOverrides(element);\n\tif (propertyOverrides?.disabled != null) {\n\t\treturn propertyOverrides.disabled;\n\t}\n\n\treturn disabled;\n}\n","import { useCallback, useEffect, useRef } from \"react\";\n\n/**\n * Default debounce delay in milliseconds.\n * Used for autocomplete/typeahead fetch operations to avoid\n * excessive backend calls during rapid user input.\n */\nexport const DEFAULT_DEBOUNCE_MS = 300;\n\n/**\n * Returns a debounced version of the given callback.\n *\n * The returned function delays invoking `callback` until after `delay` ms\n * have elapsed since the last invocation. Useful for search/autocomplete\n * inputs that trigger backend fetches.\n *\n * - Automatically cleans up pending timers on unmount.\n * - Provides a `cancel()` method on the returned function to manually\n * discard any pending invocation.\n * - The callback reference is always kept up-to-date (no stale closures).\n *\n * @param callback - The function to debounce\n * @param delay - Debounce delay in ms (default: {@link DEFAULT_DEBOUNCE_MS})\n * @returns A debounced function with an additional `cancel` method\n *\n * @example\n * ```tsx\n * const fetchSuggestions = useDebouncedCallback(async (text: string) => {\n * const results = await api.search(text);\n * setOptions(results);\n * });\n *\n * <input onChange={(e) => fetchSuggestions(e.target.value)} />\n * ```\n */\nexport function useDebouncedCallback<Args extends unknown[]>(\n\tcallback: (...args: Args) => void,\n\tdelay: number = DEFAULT_DEBOUNCE_MS\n): ((...args: Args) => void) & { cancel: () => void } {\n\tconst timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\tconst callbackRef = useRef(callback);\n\n\t// Always keep the latest callback reference\n\tcallbackRef.current = callback;\n\n\tconst cancel = useCallback(() => {\n\t\tif (timerRef.current !== null) {\n\t\t\tclearTimeout(timerRef.current);\n\t\t\ttimerRef.current = null;\n\t\t}\n\t}, []);\n\n\tconst debounced = useCallback(\n\t\t(...args: Args) => {\n\t\t\tcancel();\n\t\t\ttimerRef.current = setTimeout(() => {\n\t\t\t\ttimerRef.current = null;\n\t\t\t\tcallbackRef.current(...args);\n\t\t\t}, delay);\n\t\t},\n\t\t[delay, cancel]\n\t);\n\n\t// Clean up on unmount\n\tuseEffect(() => cancel, [cancel]);\n\n\treturn Object.assign(debounced, { cancel });\n}\n"],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Transfer data structure.
3
+ *
4
+ * Generic parameter `T` allows strict-typing when the transfer shape is known
5
+ * (e.g. via codegen-generated interfaces). Falls back to an open index signature
6
+ * when omitted so existing untyped code keeps compiling.
7
+ *
8
+ */
9
+ export interface TransferData {
10
+ __identifier?: string;
11
+ __signedIdentifier?: string;
12
+ __typename?: string;
13
+ /** Index signature preserved for backwards-compatibility when T = Record<string, unknown> */
14
+ [key: string]: unknown;
15
+ }
16
+ /**
17
+ * Strict transfer data — a TransferData whose *own* properties conform to `T`.
18
+ *
19
+ * Use this alias in generated code and userland APIs where the exact field set is
20
+ * known at compile time. The intersection keeps the internal `__*` fields from
21
+ * `TransferData` while adding compile-time keys from `T`.
22
+ *
23
+ * @typeParam T - Strict field definitions (e.g. `{ name: string; age: number }`)
24
+ */
25
+ export type StrictTransferData<T extends Record<string, unknown> = Record<string, unknown>> = TransferData & T;
26
+ /**
27
+ * Data store state per transfer type.
28
+ */
29
+ export interface TransferState {
30
+ data: TransferData | null;
31
+ originalData: TransferData | null;
32
+ isDirty: boolean;
33
+ isLoading: boolean;
34
+ error: Error | null;
35
+ }
36
+ /**
37
+ * Full store state.
38
+ */
39
+ export interface DataStoreState {
40
+ transfers: Map<string, TransferState>;
41
+ version: number;
42
+ }
43
+ /**
44
+ * Selector for fine-grained subscriptions.
45
+ */
46
+ export type DataSelector<T> = (state: DataStoreState) => T;
47
+ /**
48
+ * Create empty transfer state.
49
+ */
50
+ export declare function createEmptyTransferState(): TransferState;
51
+ /**
52
+ * Data store with selector-based subscriptions.
53
+ * Provides fine-grained reactivity by only notifying subscribers
54
+ * when their selected value actually changes.
55
+ */
56
+ export declare class DataStore {
57
+ private state;
58
+ private subscribers;
59
+ private selectorCache;
60
+ /**
61
+ * Subscribe to specific data slice.
62
+ * Only notifies when selected value changes.
63
+ *
64
+ * @param selector - Function to select data from state
65
+ * @param callback - Callback to invoke when selected data changes
66
+ * @returns Unsubscribe function
67
+ */
68
+ subscribe<T>(selector: DataSelector<T>, callback: () => void): () => void;
69
+ /**
70
+ * Get current snapshot for selector.
71
+ *
72
+ * @param selector - Function to select data from state
73
+ * @returns Selected value
74
+ */
75
+ getSnapshot<T>(selector: DataSelector<T>): T;
76
+ /**
77
+ * Get the full state snapshot.
78
+ * Used for debugging and testing.
79
+ *
80
+ * @returns Current state
81
+ */
82
+ getState(): DataStoreState;
83
+ /**
84
+ * Get transfer state by ID.
85
+ *
86
+ * When called with an explicit type parameter the returned `data` / `originalData`
87
+ * fields are narrowed to `StrictTransferData<T> | null`.
88
+ *
89
+ * @typeParam T - Optional strict transfer shape
90
+ * @param transferId - Transfer identifier
91
+ * @returns Transfer state (optionally narrowed) or undefined
92
+ */
93
+ getTransfer<T extends Record<string, unknown> = Record<string, unknown>>(transferId: string): (TransferState & {
94
+ data: StrictTransferData<T> | null;
95
+ originalData: StrictTransferData<T> | null;
96
+ }) | undefined;
97
+ /**
98
+ * Set transfer data.
99
+ * Resets dirty state and error.
100
+ *
101
+ * @typeParam T - Optional strict transfer shape
102
+ * @param transferId - Transfer identifier
103
+ * @param data - Transfer data (typed when T is provided)
104
+ */
105
+ setTransferData<T extends Record<string, unknown> = Record<string, unknown>>(transferId: string, data: StrictTransferData<T>): void;
106
+ /**
107
+ * Update a single field on a transfer.
108
+ * If the transfer doesn't exist, creates it with just this field.
109
+ *
110
+ * When `T` is provided the `field` parameter is restricted to `keyof T`
111
+ * and `value` is narrowed to the matching property type.
112
+ *
113
+ * @typeParam T - Optional strict transfer shape
114
+ * @param transferId - Transfer identifier
115
+ * @param field - Field name (restricted to `keyof T` when strict)
116
+ * @param value - New value (typed to `T[K]` when strict)
117
+ */
118
+ updateTransferField<T extends Record<string, unknown> = Record<string, unknown>, K extends string & keyof T = string & keyof T>(transferId: string, field: K, value: T[K]): void;
119
+ /**
120
+ * Set transfer loading state.
121
+ *
122
+ * @param transferId - Transfer identifier
123
+ * @param isLoading - Loading state
124
+ */
125
+ setTransferLoading(transferId: string, isLoading: boolean): void;
126
+ /**
127
+ * Set transfer error state.
128
+ *
129
+ * @param transferId - Transfer identifier
130
+ * @param error - Error or null to clear
131
+ */
132
+ setTransferError(transferId: string, error: Error | null): void;
133
+ /**
134
+ * Reset transfer to original data.
135
+ *
136
+ * @param transferId - Transfer identifier
137
+ */
138
+ resetTransfer(transferId: string): void;
139
+ /**
140
+ * Clear transfer from store.
141
+ *
142
+ * @param transferId - Transfer identifier
143
+ */
144
+ clearTransfer(transferId: string): void;
145
+ /**
146
+ * Clear all transfers from store.
147
+ */
148
+ clearAll(): void;
149
+ /**
150
+ * Update multiple fields at once.
151
+ *
152
+ * When `T` is provided the `updates` object is restricted to partial keys of `T`.
153
+ *
154
+ * @typeParam T - Optional strict transfer shape
155
+ * @param transferId - Transfer identifier
156
+ * @param updates - Object with field updates (typed to `Partial<T>` when strict)
157
+ */
158
+ updateTransferFields<T extends Record<string, unknown> = Record<string, unknown>>(transferId: string, updates: Partial<T>): void;
159
+ /**
160
+ * Internal method to update state and notify subscribers.
161
+ */
162
+ private updateState;
163
+ /**
164
+ * Notify subscribers whose selected values have changed.
165
+ */
166
+ private notifySubscribers;
167
+ }
168
+ //# sourceMappingURL=data-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../../src/store/data-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { DataStore, createEmptyTransferState, type TransferData, type StrictTransferData, type TransferState, type DataStoreState, type DataSelector, } from './data-store';
2
+ export { selectTransfer, selectTransferField, selectTransferLoading, selectTransferError, selectTransferDirty, selectTransferIds, selectVersion, } from './selectors';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,SAAS,EACT,wBAAwB,EACxB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,GACb,MAAM,aAAa,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { DataStoreState, StrictTransferData, TransferState } from './data-store';
2
+ /**
3
+ * Create a selector for transfer data by ID.
4
+ *
5
+ * @typeParam T - Optional strict transfer shape for narrowing data fields
6
+ * @param transferId - Transfer identifier
7
+ * @returns Selector function
8
+ */
9
+ export declare function selectTransfer<T extends Record<string, unknown> = Record<string, unknown>>(transferId: string): (state: DataStoreState) => (TransferState & {
10
+ data: StrictTransferData<T> | null;
11
+ originalData: StrictTransferData<T> | null;
12
+ }) | undefined;
13
+ /**
14
+ * Create a selector for a typed transfer field value.
15
+ *
16
+ * @typeParam T - Optional strict transfer shape
17
+ * @typeParam K - Field key (inferred from `field` when T is provided)
18
+ * @param transferId - Transfer identifier
19
+ * @param field - Field name (restricted to `keyof T` when strict)
20
+ * @returns Selector function returning `T[K]` (or `unknown` when untyped)
21
+ */
22
+ export declare function selectTransferField<T extends Record<string, unknown> = Record<string, unknown>, K extends string & keyof T = string & keyof T>(transferId: string, field: K): (state: DataStoreState) => T[K] | undefined;
23
+ /**
24
+ * Create a selector for transfer loading state.
25
+ *
26
+ * @param transferId - Transfer identifier
27
+ * @returns Selector function
28
+ */
29
+ export declare function selectTransferLoading(transferId: string): (state: DataStoreState) => boolean;
30
+ /**
31
+ * Create a selector for transfer error state.
32
+ *
33
+ * @param transferId - Transfer identifier
34
+ * @returns Selector function
35
+ */
36
+ export declare function selectTransferError(transferId: string): (state: DataStoreState) => Error | null;
37
+ /**
38
+ * Create a selector for transfer dirty state.
39
+ *
40
+ * @param transferId - Transfer identifier
41
+ * @returns Selector function
42
+ */
43
+ export declare function selectTransferDirty(transferId: string): (state: DataStoreState) => boolean;
44
+ /**
45
+ * Selector for all transfer IDs.
46
+ *
47
+ * @param state - Store state
48
+ * @returns Array of transfer IDs
49
+ */
50
+ export declare function selectTransferIds(state: DataStoreState): string[];
51
+ /**
52
+ * Selector for store version (useful for detecting any change).
53
+ *
54
+ * @param state - Store state
55
+ * @returns Store version number
56
+ */
57
+ export declare function selectVersion(state: DataStoreState): number;
58
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/store/selectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEtF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,IAE5G,OAAO,cAAc,KACnB,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,SAAS,CAInH;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAClC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,EAC5C,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,IACrB,OAAO,cAAc,KAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,IAC/C,OAAO,cAAc,KAAG,OAAO,CACvC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,IAC7C,OAAO,cAAc,KAAG,KAAK,GAAG,IAAI,CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,IAC7C,OAAO,cAAc,KAAG,OAAO,CACvC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CAEjE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAE3D"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Deep equality comparison for objects and arrays.
3
+ * Used for dirty state tracking in DataStore.
4
+ *
5
+ * @param a - First value
6
+ * @param b - Second value
7
+ * @returns true if values are deeply equal
8
+ */
9
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
10
+ //# sourceMappingURL=deep-equal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-equal.d.ts","sourceRoot":"","sources":["../../src/utils/deep-equal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAiEzD"}
@@ -0,0 +1,2 @@
1
+ export { deepEqual } from './deep-equal';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@judo/core",
3
+ "version": "0.1.0",
4
+ "description": "Core React contexts and hooks for JUDO UI Runtime",
5
+ "license": "EPL-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/BlackBeltTechnology/judo-frontend-runtime.git",
9
+ "directory": "packages/core"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "LICENSE",
14
+ "README.md"
15
+ ],
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "main": "./dist/index.js",
19
+ "module": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ }
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "dependencies": {
31
+ "@judo/actions": "0.1.0",
32
+ "@judo/model-api": "0.1.0",
33
+ "@judo/model-loader": "0.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "@testing-library/react": "^16.3.2",
37
+ "@types/react": "^19.2.14",
38
+ "typescript": "^5.9.3",
39
+ "vitest": "^4.0.18",
40
+ "@judo/actions": "0.1.0",
41
+ "@judo/model-api": "0.1.0",
42
+ "@judo/model-loader": "0.1.0",
43
+ "@judo/testing": "0.1.0"
44
+ },
45
+ "peerDependencies": {
46
+ "react": "^19.0.0",
47
+ "@judo/model-api": "0.1.0",
48
+ "@judo/actions": "0.1.0",
49
+ "@judo/model-loader": "0.1.0"
50
+ },
51
+ "scripts": {
52
+ "build": "vite build",
53
+ "test": "vitest run",
54
+ "test:watch": "vitest",
55
+ "test:coverage": "vitest run --coverage",
56
+ "type-check": "tsgo --noEmit"
57
+ }
58
+ }