@freesail/react
Advanced tools
+2
-2
| { | ||
| "name": "@freesail/react", | ||
| "version": "0.4.3", | ||
| "version": "0.4.5", | ||
| "description": "React implementation for Freesail - Agent-driven UI SDK", | ||
@@ -36,3 +36,3 @@ "type": "module", | ||
| "dependencies": { | ||
| "@freesail/core": "^0.4.3", | ||
| "@freesail/core": "^0.4.5", | ||
| "vite": "7.3.1" | ||
@@ -39,0 +39,0 @@ }, |
| /** | ||
| * @fileoverview Freesail React Context | ||
| * | ||
| * Provides React context for Freesail state management. | ||
| */ | ||
| import type { SurfaceManager, A2UITransport, Surface, SurfaceId, ComponentId } from '@freesail/core'; | ||
| /** | ||
| * Freesail context value. | ||
| */ | ||
| export interface FreesailContextValue { | ||
| /** Surface manager instance */ | ||
| surfaceManager: SurfaceManager; | ||
| /** Transport instance (may be null if not connected) */ | ||
| transport: A2UITransport | null; | ||
| /** Send an action (v0.9 format) */ | ||
| sendAction: (surfaceId: SurfaceId, name: string, sourceComponentId: ComponentId, context: Record<string, unknown>) => Promise<void>; | ||
| /** Get a surface by ID */ | ||
| getSurface: (surfaceId: SurfaceId) => Surface | undefined; | ||
| /** Connection state */ | ||
| isConnected: boolean; | ||
| } | ||
| /** | ||
| * React context for Freesail. | ||
| */ | ||
| export declare const FreesailContext: import("react").Context<FreesailContextValue | null>; | ||
| /** | ||
| * Hook to access the Freesail context. | ||
| * Throws if used outside of a FreesailProvider. | ||
| */ | ||
| export declare function useFreesailContext(): FreesailContextValue; | ||
| //# sourceMappingURL=context.d.ts.map |
| {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,OAAO,EACP,SAAS,EACT,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,wDAAwD;IACxD,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,mCAAmC;IACnC,UAAU,EAAE,CACV,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,WAAW,EAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,0BAA0B;IAC1B,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,GAAG,SAAS,CAAC;IAC1D,uBAAuB;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,sDAAmD,CAAC;AAEhF;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,oBAAoB,CAMzD"} |
| /** | ||
| * @fileoverview Freesail React Context | ||
| * | ||
| * Provides React context for Freesail state management. | ||
| */ | ||
| import { createContext, useContext } from 'react'; | ||
| /** | ||
| * React context for Freesail. | ||
| */ | ||
| export const FreesailContext = createContext(null); | ||
| /** | ||
| * Hook to access the Freesail context. | ||
| * Throws if used outside of a FreesailProvider. | ||
| */ | ||
| export function useFreesailContext() { | ||
| const context = useContext(FreesailContext); | ||
| if (!context) { | ||
| throw new Error('useFreesailContext must be used within a FreesailProvider'); | ||
| } | ||
| return context; | ||
| } | ||
| //# sourceMappingURL=context.js.map |
| {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AA+BlD;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAA8B,IAAI,CAAC,CAAC;AAEhF;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["/**\n * @fileoverview Freesail React Context\n *\n * Provides React context for Freesail state management.\n */\n\nimport { createContext, useContext } from 'react';\nimport type {\n SurfaceManager,\n A2UITransport,\n Surface,\n SurfaceId,\n ComponentId,\n A2UIClientDataModel,\n} from '@freesail/core';\n\n/**\n * Freesail context value.\n */\nexport interface FreesailContextValue {\n /** Surface manager instance */\n surfaceManager: SurfaceManager;\n /** Transport instance (may be null if not connected) */\n transport: A2UITransport | null;\n /** Send an action (v0.9 format) */\n sendAction: (\n surfaceId: SurfaceId,\n name: string,\n sourceComponentId: ComponentId,\n context: Record<string, unknown>\n ) => Promise<void>;\n /** Get a surface by ID */\n getSurface: (surfaceId: SurfaceId) => Surface | undefined;\n /** Connection state */\n isConnected: boolean;\n}\n\n/**\n * React context for Freesail.\n */\nexport const FreesailContext = createContext<FreesailContextValue | null>(null);\n\n/**\n * Hook to access the Freesail context.\n * Throws if used outside of a FreesailProvider.\n */\nexport function useFreesailContext(): FreesailContextValue {\n const context = useContext(FreesailContext);\n if (!context) {\n throw new Error('useFreesailContext must be used within a FreesailProvider');\n }\n return context;\n}\n"]} |
| /** | ||
| * @fileoverview FreesailProvider Component | ||
| * | ||
| * The root provider component that manages Freesail connections | ||
| * and state for the React application. | ||
| */ | ||
| import { type ReactNode } from 'react'; | ||
| import { type TransportOptions, type CatalogId } from '@freesail/core'; | ||
| import type { CatalogDefinition } from './types.js'; | ||
| /** | ||
| * Props for FreesailProvider. | ||
| */ | ||
| export interface FreesailProviderProps { | ||
| /** Child components */ | ||
| children: ReactNode; | ||
| /** SSE endpoint URL */ | ||
| sseUrl: string; | ||
| /** HTTP POST endpoint URL */ | ||
| postUrl: string; | ||
| /** List of supported catalog IDs */ | ||
| catalogs?: CatalogId[]; | ||
| /** | ||
| * Array of custom catalog definitions to register. | ||
| * Each definition bundles a namespace, schema, and component map. | ||
| * Components are auto-registered on mount. | ||
| */ | ||
| catalogDefinitions?: CatalogDefinition[]; | ||
| /** Additional transport options */ | ||
| transportOptions?: Partial<Omit<TransportOptions, 'sseUrl' | 'postUrl' | 'capabilities'>>; | ||
| /** Auto-connect on mount (default: true) */ | ||
| autoConnect?: boolean; | ||
| /** Callback when connection state changes */ | ||
| onConnectionChange?: (connected: boolean) => void; | ||
| /** Callback when an error occurs */ | ||
| onError?: (error: Error) => void; | ||
| } | ||
| /** | ||
| * Root provider component for Freesail. | ||
| * | ||
| * Manages the transport connection and surface state, | ||
| * making them available to all child components. | ||
| */ | ||
| export declare function FreesailProvider({ children, sseUrl, postUrl, catalogs, catalogDefinitions, transportOptions, autoConnect, onConnectionChange, onError, }: FreesailProviderProps): import("react/jsx-runtime").JSX.Element; | ||
| //# sourceMappingURL=FreesailProvider.d.ts.map |
| {"version":3,"file":"FreesailProvider.d.ts","sourceRoot":"","sources":["../src/FreesailProvider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAc,EAKZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EASL,KAAK,gBAAgB,EAGrB,KAAK,SAAS,EAGf,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,uBAAuB;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC;IAC1F,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,MAAM,EACN,OAAO,EACP,QAAa,EACb,kBAAuB,EACvB,gBAAgB,EAChB,WAAkB,EAClB,kBAAkB,EAClB,OAAO,GACR,EAAE,qBAAqB,2CA0IvB"} |
| import { jsx as _jsx } from "react/jsx-runtime"; | ||
| /** | ||
| * @fileoverview FreesailProvider Component | ||
| * | ||
| * The root provider component that manages Freesail connections | ||
| * and state for the React application. | ||
| */ | ||
| import { useState, useEffect, useCallback, useMemo, } from 'react'; | ||
| import { createSurfaceManager, createTransport, isCreateSurfaceMessage, isUpdateComponentsMessage, isUpdateDataModelMessage, isDeleteSurfaceMessage, } from '@freesail/core'; | ||
| import { FreesailContext } from './context.js'; | ||
| import { registerCatalog } from './registry.js'; | ||
| /** | ||
| * Root provider component for Freesail. | ||
| * | ||
| * Manages the transport connection and surface state, | ||
| * making them available to all child components. | ||
| */ | ||
| export function FreesailProvider({ children, sseUrl, postUrl, catalogs = [], catalogDefinitions = [], transportOptions, autoConnect = true, onConnectionChange, onError, }) { | ||
| const [surfaceManager] = useState(() => createSurfaceManager()); | ||
| const [transport, setTransport] = useState(null); | ||
| const [isConnected, setIsConnected] = useState(false); | ||
| // Register custom catalog definitions | ||
| useEffect(() => { | ||
| for (const def of catalogDefinitions) { | ||
| registerCatalog(def.namespace, def.components, def.functions); | ||
| } | ||
| }, [catalogDefinitions]); | ||
| // Merge explicit catalog IDs with catalog definition namespaces | ||
| const mergedCatalogs = useMemo(() => { | ||
| const definitionIds = catalogDefinitions.map((d) => d.namespace); | ||
| const combined = [...catalogs, ...definitionIds]; | ||
| return Array.from(new Set(combined)); | ||
| }, [catalogs, catalogDefinitions]); | ||
| // Build capabilities from catalogs | ||
| const capabilities = useMemo(() => { | ||
| if (mergedCatalogs.length === 0) | ||
| return undefined; | ||
| return { catalogs: mergedCatalogs }; | ||
| }, [mergedCatalogs]); | ||
| // Initialize transport | ||
| useEffect(() => { | ||
| const newTransport = createTransport({ | ||
| sseUrl, | ||
| postUrl, | ||
| capabilities, | ||
| ...transportOptions, | ||
| }); | ||
| // Handle incoming messages | ||
| newTransport.on('message', (message) => { | ||
| handleMessage(message, surfaceManager); | ||
| }); | ||
| // Handle connection state changes | ||
| newTransport.on('stateChange', (state) => { | ||
| const connected = state === 'connected'; | ||
| setIsConnected(connected); | ||
| onConnectionChange?.(connected); | ||
| }); | ||
| // When session starts, register catalog schemas with the gateway | ||
| newTransport.on('sessionStart', (_sessionId) => { | ||
| if (catalogDefinitions.length > 0) { | ||
| const schemas = catalogDefinitions | ||
| .map((def) => def.schema) | ||
| .filter((s) => s && Object.keys(s).length > 0); | ||
| if (schemas.length > 0) { | ||
| newTransport.registerCatalogs(schemas).then((ok) => { | ||
| if (ok) { | ||
| console.log('[Freesail] Catalogs registered with gateway'); | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| // Handle errors | ||
| newTransport.on('error', (error) => { | ||
| console.error('[Freesail] Transport error:', error); | ||
| onError?.(error); | ||
| }); | ||
| setTransport(newTransport); | ||
| // Auto-connect if enabled | ||
| if (autoConnect) { | ||
| newTransport.connect(); | ||
| } | ||
| // Cleanup | ||
| return () => { | ||
| newTransport.disconnect(); | ||
| surfaceManager.dispose(); | ||
| }; | ||
| }, [sseUrl, postUrl]); // Only recreate if URLs change | ||
| // Send action callback (v0.9 format) | ||
| const sendAction = useCallback(async (surfaceId, name, sourceComponentId, context) => { | ||
| if (!transport) { | ||
| console.warn('[Freesail] Cannot send action: transport not initialized'); | ||
| return; | ||
| } | ||
| // Always send all surface data models that have sendDataModel enabled. | ||
| // This ensures the agent can see all form/input state across all surfaces, | ||
| // not just the one that triggered this action. | ||
| const allDataModels = surfaceManager.getAllSendableDataModels(); | ||
| const dataModel = Object.keys(allDataModels).length > 0 | ||
| ? { surfaceId, dataModel: allDataModels } | ||
| : undefined; | ||
| await transport.sendAction(surfaceId, name, sourceComponentId, context, dataModel); | ||
| }, [transport, surfaceManager]); | ||
| // Get surface callback | ||
| const getSurface = useCallback((surfaceId) => surfaceManager.getSurface(surfaceId), [surfaceManager]); | ||
| // Context value | ||
| const contextValue = useMemo(() => ({ | ||
| surfaceManager, | ||
| transport, | ||
| sendAction, | ||
| getSurface, | ||
| isConnected, | ||
| }), [surfaceManager, transport, sendAction, getSurface, isConnected]); | ||
| return (_jsx(FreesailContext.Provider, { value: contextValue, children: children })); | ||
| } | ||
| // ============================================================================= | ||
| // Message Handler | ||
| // ============================================================================= | ||
| function handleMessage(message, manager) { | ||
| if (isCreateSurfaceMessage(message)) { | ||
| const { surfaceId, catalogId, sendDataModel } = message.createSurface; | ||
| manager.createSurface({ surfaceId, catalogId, sendDataModel }); | ||
| } | ||
| else if (isUpdateComponentsMessage(message)) { | ||
| const { surfaceId, components } = message.updateComponents; | ||
| manager.updateComponents(surfaceId, components); | ||
| } | ||
| else if (isUpdateDataModelMessage(message)) { | ||
| const { surfaceId, path, value } = message.updateDataModel; | ||
| manager.updateDataModel(surfaceId, path, value); | ||
| } | ||
| else if (isDeleteSurfaceMessage(message)) { | ||
| const { surfaceId } = message.deleteSurface; | ||
| manager.deleteSurface(surfaceId); | ||
| } | ||
| } | ||
| //# sourceMappingURL=FreesailProvider.js.map |
| {"version":3,"file":"FreesailProvider.js","sourceRoot":"","sources":["../src/FreesailProvider.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview FreesailProvider Component\n *\n * The root provider component that manages Freesail connections\n * and state for the React application.\n */\n\nimport React, {\n useState,\n useEffect,\n useCallback,\n useMemo,\n type ReactNode,\n} from 'react';\nimport {\n createSurfaceManager,\n createTransport,\n isCreateSurfaceMessage,\n isUpdateComponentsMessage,\n isUpdateDataModelMessage,\n isDeleteSurfaceMessage,\n type SurfaceManager,\n type A2UITransport,\n type TransportOptions,\n type SurfaceId,\n type ComponentId,\n type CatalogId,\n type DownstreamMessage,\n type A2UIClientCapabilities,\n} from '@freesail/core';\nimport { FreesailContext, type FreesailContextValue } from './context.js';\nimport { registerCatalog, type FreesailComponent } from './registry.js';\nimport type { CatalogDefinition } from './types.js';\n\n/**\n * Props for FreesailProvider.\n */\nexport interface FreesailProviderProps {\n /** Child components */\n children: ReactNode;\n /** SSE endpoint URL */\n sseUrl: string;\n /** HTTP POST endpoint URL */\n postUrl: string;\n /** List of supported catalog IDs */\n catalogs?: CatalogId[];\n /**\n * Array of custom catalog definitions to register.\n * Each definition bundles a namespace, schema, and component map.\n * Components are auto-registered on mount.\n */\n catalogDefinitions?: CatalogDefinition[];\n /** Additional transport options */\n transportOptions?: Partial<Omit<TransportOptions, 'sseUrl' | 'postUrl' | 'capabilities'>>;\n /** Auto-connect on mount (default: true) */\n autoConnect?: boolean;\n /** Callback when connection state changes */\n onConnectionChange?: (connected: boolean) => void;\n /** Callback when an error occurs */\n onError?: (error: Error) => void;\n}\n\n/**\n * Root provider component for Freesail.\n *\n * Manages the transport connection and surface state,\n * making them available to all child components.\n */\nexport function FreesailProvider({\n children,\n sseUrl,\n postUrl,\n catalogs = [],\n catalogDefinitions = [],\n transportOptions,\n autoConnect = true,\n onConnectionChange,\n onError,\n}: FreesailProviderProps) {\n const [surfaceManager] = useState<SurfaceManager>(() => createSurfaceManager());\n const [transport, setTransport] = useState<A2UITransport | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n // Register custom catalog definitions\n useEffect(() => {\n for (const def of catalogDefinitions) {\n registerCatalog(\n def.namespace as CatalogId,\n def.components as Record<string, FreesailComponent>,\n def.functions\n );\n }\n }, [catalogDefinitions]);\n\n // Merge explicit catalog IDs with catalog definition namespaces\n const mergedCatalogs = useMemo(() => {\n const definitionIds = catalogDefinitions.map((d) => d.namespace as CatalogId);\n const combined = [...catalogs, ...definitionIds];\n return Array.from(new Set(combined));\n }, [catalogs, catalogDefinitions]);\n\n // Build capabilities from catalogs\n const capabilities: A2UIClientCapabilities | undefined = useMemo(() => {\n if (mergedCatalogs.length === 0) return undefined;\n return { catalogs: mergedCatalogs };\n }, [mergedCatalogs]);\n\n // Initialize transport\n useEffect(() => {\n const newTransport = createTransport({\n sseUrl,\n postUrl,\n capabilities,\n ...transportOptions,\n });\n\n // Handle incoming messages\n newTransport.on('message', (message: DownstreamMessage) => {\n handleMessage(message, surfaceManager);\n });\n\n\n\n // Handle connection state changes\n newTransport.on('stateChange', (state) => {\n const connected = state === 'connected';\n setIsConnected(connected);\n onConnectionChange?.(connected);\n });\n\n // When session starts, register catalog schemas with the gateway\n newTransport.on('sessionStart', (_sessionId) => {\n if (catalogDefinitions.length > 0) {\n const schemas = catalogDefinitions\n .map((def) => def.schema)\n .filter((s) => s && Object.keys(s).length > 0);\n\n if (schemas.length > 0) {\n newTransport.registerCatalogs(schemas).then((ok) => {\n if (ok) {\n console.log('[Freesail] Catalogs registered with gateway');\n }\n });\n }\n }\n });\n\n // Handle errors\n newTransport.on('error', (error) => {\n console.error('[Freesail] Transport error:', error);\n onError?.(error);\n });\n\n setTransport(newTransport);\n\n // Auto-connect if enabled\n if (autoConnect) {\n newTransport.connect();\n }\n\n // Cleanup\n return () => {\n newTransport.disconnect();\n surfaceManager.dispose();\n };\n }, [sseUrl, postUrl]); // Only recreate if URLs change\n\n // Send action callback (v0.9 format)\n const sendAction = useCallback(\n async (\n surfaceId: SurfaceId,\n name: string,\n sourceComponentId: ComponentId,\n context: Record<string, unknown>\n ) => {\n if (!transport) {\n console.warn('[Freesail] Cannot send action: transport not initialized');\n return;\n }\n\n // Always send all surface data models that have sendDataModel enabled.\n // This ensures the agent can see all form/input state across all surfaces,\n // not just the one that triggered this action.\n const allDataModels = surfaceManager.getAllSendableDataModels();\n const dataModel = Object.keys(allDataModels).length > 0\n ? { surfaceId, dataModel: allDataModels }\n : undefined;\n\n await transport.sendAction(surfaceId, name, sourceComponentId, context, dataModel);\n },\n [transport, surfaceManager]\n );\n\n // Get surface callback\n const getSurface = useCallback(\n (surfaceId: SurfaceId) => surfaceManager.getSurface(surfaceId),\n [surfaceManager]\n );\n\n // Context value\n const contextValue: FreesailContextValue = useMemo(\n () => ({\n surfaceManager,\n transport,\n sendAction,\n getSurface,\n isConnected,\n }),\n [surfaceManager, transport, sendAction, getSurface, isConnected]\n );\n\n return (\n <FreesailContext.Provider value={contextValue}>\n {children}\n </FreesailContext.Provider>\n );\n}\n\n// =============================================================================\n// Message Handler\n// =============================================================================\n\nfunction handleMessage(message: DownstreamMessage, manager: SurfaceManager): void {\n if (isCreateSurfaceMessage(message)) {\n const { surfaceId, catalogId, sendDataModel } = message.createSurface;\n manager.createSurface({ surfaceId, catalogId, sendDataModel });\n } else if (isUpdateComponentsMessage(message)) {\n const { surfaceId, components } = message.updateComponents;\n manager.updateComponents(surfaceId, components);\n } else if (isUpdateDataModelMessage(message)) {\n const { surfaceId, path, value } = message.updateDataModel;\n manager.updateDataModel(surfaceId, path, value);\n } else if (isDeleteSurfaceMessage(message)) {\n const { surfaceId } = message.deleteSurface;\n manager.deleteSurface(surfaceId);\n }\n}\n"]} |
| /** | ||
| * @fileoverview FreesailSurface Component | ||
| * | ||
| * The main container component that renders a single A2UI surface. | ||
| * Users drop this into their app to display agent-driven UI. | ||
| */ | ||
| import { type ReactNode } from 'react'; | ||
| import type { SurfaceId, FunctionCall } from '@freesail/core'; | ||
| /** | ||
| * Props for FreesailSurface. | ||
| */ | ||
| export interface FreesailSurfaceProps { | ||
| /** The surface ID to render */ | ||
| surfaceId: SurfaceId; | ||
| /** Optional className for the container */ | ||
| className?: string; | ||
| /** Loading state component */ | ||
| loading?: ReactNode; | ||
| /** Error state component */ | ||
| error?: ReactNode; | ||
| /** Empty state component (when surface exists but has no components) */ | ||
| empty?: ReactNode; | ||
| } | ||
| /** | ||
| * Renders a single A2UI surface. | ||
| * | ||
| * This component subscribes to surface updates and automatically | ||
| * re-renders when the component tree or data model changes. | ||
| */ | ||
| export declare function FreesailSurface({ surfaceId, className, loading, error, empty, }: FreesailSurfaceProps): import("react/jsx-runtime").JSX.Element; | ||
| /** | ||
| * Evaluate a function call. | ||
| */ | ||
| export declare function evaluateFunction(call: FunctionCall, dataModel: Record<string, unknown>, catalogId: string, scopeData?: unknown): unknown; | ||
| //# sourceMappingURL=FreesailSurface.d.ts.map |
| {"version":3,"file":"FreesailSurface.d.ts","sourceRoot":"","sources":["../src/FreesailSurface.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAc,EAAwB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMpE,OAAO,KAAK,EACV,SAAS,EAIT,YAAY,EACb,MAAM,gBAAgB,CAAC;AAMxB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+BAA+B;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAgBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,SAAS,EACT,SAAS,EACT,OAA4B,EAC5B,KAAwB,EACxB,KAA0B,GAC3B,EAAE,oBAAoB,2CAqDtB;AAmQD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAwDT"} |
| import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; | ||
| /** | ||
| * @fileoverview FreesailSurface Component | ||
| * | ||
| * The main container component that renders a single A2UI surface. | ||
| * Users drop this into their app to display agent-driven UI. | ||
| */ | ||
| import { useMemo, useCallback } from 'react'; | ||
| import { FREESAIL_LOGO_DATA_URI } from './logo.js'; | ||
| import { isFunctionCall, } from '@freesail/core'; | ||
| import { useSurface, useAction } from './hooks.js'; | ||
| import { registry } from './registry.js'; | ||
| import { useFreesailContext } from './context.js'; | ||
| /** | ||
| * Renders a single A2UI surface. | ||
| * | ||
| * This component subscribes to surface updates and automatically | ||
| * re-renders when the component tree or data model changes. | ||
| */ | ||
| export function FreesailSurface({ surfaceId, className, loading = _jsx(DefaultLoading, {}), error = _jsx(DefaultError, {}), empty = _jsx(DefaultLoading, {}), }) { | ||
| const surface = useSurface(surfaceId); | ||
| const dispatch = useAction(surfaceId); | ||
| const { surfaceManager } = useFreesailContext(); | ||
| // Two-way binding: input components write to the local data model. | ||
| // This is local only — no network request. The updated data model | ||
| // reaches the server via resolved data bindings in action context | ||
| // or via the sendDataModel metadata mechanism. | ||
| const onDataChange = useCallback((path, value) => { | ||
| console.log(`[Freesail] onDataChange: surface=${surfaceId} path=${path} value=`, value); | ||
| surfaceManager.updateDataModel(surfaceId, path, value); | ||
| }, [surfaceManager, surfaceId]); | ||
| // Build the component tree | ||
| const renderedTree = useMemo(() => { | ||
| if (!surface) | ||
| return null; | ||
| if (surface.components.size === 0) | ||
| return null; | ||
| if (!surface.rootId) | ||
| return null; | ||
| return renderComponent(surface.rootId, surface.components, surface.catalogId, surface.dataModel, dispatch, onDataChange, undefined, undefined, undefined); | ||
| }, [surface, dispatch, onDataChange]); | ||
| // Loading state - surface doesn't exist yet | ||
| if (!surface) { | ||
| return _jsx("div", { className: className, style: { flex: 1, minHeight: 0 }, children: loading }); | ||
| } | ||
| // Empty state - surface exists but no components | ||
| if (surface.components.size === 0 || !surface.rootId) { | ||
| return _jsx("div", { className: className, style: { flex: 1, minHeight: 0 }, children: empty }); | ||
| } | ||
| // Check if catalog is registered | ||
| if (!registry.hasCatalog(surface.catalogId)) { | ||
| console.error(`[Freesail] Catalog not registered: ${surface.catalogId}`); | ||
| return _jsx("div", { className: className, style: { flex: 1, minHeight: 0 }, children: error }); | ||
| } | ||
| return _jsx("div", { className: className, "data-freesail-surface": surfaceId, style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: renderedTree }); | ||
| } | ||
| // ============================================================================= | ||
| // Component Renderer | ||
| // ============================================================================= | ||
| function renderComponent(componentId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, keyOverride, scopeBasePath) { | ||
| const componentDef = components.get(componentId); | ||
| if (!componentDef) { | ||
| // Component may arrive in a subsequent update_components batch — render nothing for now | ||
| return null; | ||
| } | ||
| // Get the React component from registry | ||
| const Component = registry.getComponent(catalogId, componentDef.component); | ||
| if (!Component) { | ||
| return _jsx(UnknownComponent, { component: componentDef }); | ||
| } | ||
| // Render children recursively | ||
| let children = null; | ||
| // 1. Handle single child (for Card, etc.) | ||
| if (componentDef.child) { | ||
| children = renderComponent(componentDef.child, components, catalogId, dataModel, dispatch, onDataChange, scopeData, undefined, scopeBasePath); | ||
| } | ||
| // 2. Handle multiple standard children (Column, Row, List, etc.) | ||
| else if (componentDef.children) { | ||
| const childList = componentDef.children; | ||
| if (Array.isArray(childList)) { | ||
| // Static array of child IDs | ||
| children = childList.map((childId) => renderComponent(childId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, undefined, scopeBasePath)); | ||
| } | ||
| else if (typeof childList === 'object' && 'componentId' in childList) { | ||
| // Template for dynamic children | ||
| const template = childList; | ||
| const listData = getDataAtPath(dataModel, template.path); | ||
| if (Array.isArray(listData)) { | ||
| children = listData.map((itemData, index) => { | ||
| // Build the absolute path for this item in the data model | ||
| const itemBasePath = `${template.path}/${index}`; | ||
| return renderComponent(template.componentId, components, catalogId, dataModel, dispatch, onDataChange, itemData, // Pass item data as scope | ||
| `${template.componentId}_${itemData?.id ?? index}`, // Unique key per item | ||
| itemBasePath // Absolute path for two-way binding | ||
| ); | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| // 3. Handle named slots for specific components (Tabs, Modal) | ||
| else if (componentDef.component === 'Tabs' && Array.isArray(componentDef.tabs)) { | ||
| // Render each tab's child component | ||
| children = componentDef.tabs.map((tab, index) => renderComponent(tab.child, components, catalogId, dataModel, dispatch, onDataChange, scopeData, `${componentId}_tab_${index}`, scopeBasePath)); | ||
| } | ||
| else if (componentDef.component === 'Modal') { | ||
| // Render trigger and content slots | ||
| const triggerId = componentDef.trigger; | ||
| const contentId = componentDef.content; | ||
| const trigger = triggerId | ||
| ? renderComponent(triggerId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, `${componentId}_trigger`, scopeBasePath) | ||
| : null; | ||
| const content = contentId | ||
| ? renderComponent(contentId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, `${componentId}_content`, scopeBasePath) | ||
| : null; | ||
| children = [trigger, content]; | ||
| } | ||
| // Resolve data bindings in component properties | ||
| const resolvedProps = resolveDataBindings(componentDef, dataModel, catalogId, scopeData, scopeBasePath); | ||
| // Build props | ||
| const props = { | ||
| component: { ...componentDef, ...resolvedProps }, | ||
| children, | ||
| dataModel, | ||
| scopeData, | ||
| onAction: (name, context) => { | ||
| // Resolve data bindings in action context at dispatch time. | ||
| const resolvedContext = resolveActionContext(context, dataModel, catalogId, scopeData); | ||
| return dispatch(name, componentDef.id, resolvedContext); | ||
| }, | ||
| onDataChange, | ||
| onFunctionCall: (call) => { | ||
| evaluateFunction(call, dataModel, catalogId, scopeData); | ||
| }, | ||
| }; | ||
| return _jsx(Component, { ...props }, keyOverride ?? componentId); | ||
| } | ||
| /** | ||
| * Resolve data bindings in component properties. | ||
| */ | ||
| function resolveDataBindings(component, dataModel, catalogId, scopeData, scopeBasePath) { | ||
| const resolved = {}; | ||
| for (const [key, value] of Object.entries(component)) { | ||
| if (key === 'id' || key === 'component' || key === 'children' || key === 'child') { | ||
| continue; | ||
| } | ||
| // Robustness: Handle double-encoded bindings | ||
| let effectiveValue = value; | ||
| if (typeof value === 'string' && value.trim().startsWith('{') && value.includes('"path"')) { | ||
| try { | ||
| const parsed = JSON.parse(value); | ||
| if (isDataBindingObject(parsed)) { | ||
| effectiveValue = parsed; | ||
| } | ||
| } | ||
| catch { | ||
| // Ignore parse errors | ||
| } | ||
| } | ||
| if (isFunctionCall(effectiveValue)) { | ||
| resolved[key] = evaluateFunction(effectiveValue, dataModel, catalogId, scopeData); | ||
| } | ||
| else if (isDataBindingObject(effectiveValue)) { | ||
| // Preserve the raw binding so components can find the path for two-way binding. | ||
| // If inside a scoped template, convert relative paths to absolute paths | ||
| // so onDataChange writes to the correct location in the data model. | ||
| const rawBinding = { ...effectiveValue }; | ||
| if (scopeBasePath && !rawBinding.path.startsWith('/')) { | ||
| rawBinding.path = `${scopeBasePath}/${rawBinding.path}`; | ||
| } | ||
| resolved[`__raw${key.charAt(0).toUpperCase()}${key.slice(1)}`] = rawBinding; | ||
| // Resolve data binding | ||
| resolved[key] = resolveSingleBinding(effectiveValue, dataModel, scopeData); | ||
| } | ||
| else if (typeof value === 'object' && value !== null) { | ||
| // Prevent recursion into LocalAction definitions (which contain FunctionCalls that should NOT be evaluated yet) | ||
| if ('functionCall' in value && isFunctionCall(value.functionCall)) { | ||
| resolved[key] = value; | ||
| continue; | ||
| } | ||
| // Recursively resolve bindings inside objects and arrays | ||
| if (Array.isArray(value)) { | ||
| resolved[key] = value.map(item => { | ||
| if (typeof item === 'object' && item !== null) { | ||
| // Check for LocalAction in array items too | ||
| if ('functionCall' in item && isFunctionCall(item.functionCall)) { | ||
| return item; | ||
| } | ||
| if (isFunctionCall(item)) { | ||
| return evaluateFunction(item, dataModel, catalogId, scopeData); | ||
| } | ||
| if (isDataBindingObject(item)) { | ||
| return resolveSingleBinding(item, dataModel, scopeData); | ||
| } | ||
| return resolveDataBindings(item, dataModel, catalogId, scopeData); | ||
| } | ||
| return item; | ||
| }); | ||
| } | ||
| else { | ||
| resolved[key] = resolveDataBindings(value, dataModel, catalogId, scopeData); | ||
| } | ||
| } | ||
| else { | ||
| resolved[key] = value; | ||
| } | ||
| } | ||
| return resolved; | ||
| } | ||
| /** | ||
| * Helper to resolve a single binding object, following chains. | ||
| */ | ||
| function resolveSingleBinding(binding, dataModel, scopeData) { | ||
| const path = binding.path; | ||
| let resolvedValue; | ||
| // "." or "" means "the current scoped item" — used when iterating scalar arrays | ||
| if (path === '.' || path === '') { | ||
| return scopeData !== undefined ? scopeData : getDataAtPath(dataModel, '/'); | ||
| } | ||
| if (path.startsWith('/')) { | ||
| resolvedValue = getDataAtPath(dataModel, path); | ||
| } | ||
| else if (scopeData !== undefined) { | ||
| resolvedValue = getDataAtPath(scopeData, '/' + path); | ||
| } | ||
| else { | ||
| resolvedValue = getDataAtPath(dataModel, '/' + path); | ||
| } | ||
| // Chained bindings (max depth 5) | ||
| let depth = 0; | ||
| while (isDataBindingObject(resolvedValue) && depth < 5) { | ||
| const chainedPath = resolvedValue.path; | ||
| resolvedValue = chainedPath.startsWith('/') | ||
| ? getDataAtPath(dataModel, chainedPath) | ||
| : getDataAtPath(dataModel, '/' + chainedPath); | ||
| depth++; | ||
| } | ||
| return resolvedValue; | ||
| } | ||
| function isDataBindingObject(value) { | ||
| if (typeof value !== 'object' || value === null || !('path' in value)) | ||
| return false; | ||
| if (typeof value['path'] !== 'string') | ||
| return false; | ||
| if ('componentId' in value) | ||
| return false; // ChildListTemplate | ||
| if ('event' in value) | ||
| return false; // ServerAction | ||
| if ('call' in value) | ||
| return false; // FunctionCall | ||
| return true; | ||
| } | ||
| /** | ||
| * Evaluate a function call. | ||
| */ | ||
| export function evaluateFunction(call, dataModel, catalogId, scopeData) { | ||
| const functionName = call.call; | ||
| const funcImpl = registry.getFunction(catalogId, functionName); | ||
| if (!funcImpl) { | ||
| console.warn(`[Freesail] Function not found: ${functionName} in catalog ${catalogId}`); | ||
| return undefined; | ||
| } | ||
| // Resolve arguments | ||
| let rawArgs = []; | ||
| if (Array.isArray(call.args)) { | ||
| rawArgs = call.args; | ||
| } | ||
| else if (call.args && typeof call.args === 'object') { | ||
| // If it's an object, we need to extract the values in the correct order. | ||
| // Agents often generate object keys like "'0'", "'1'" out of numerical order, | ||
| // so we parse the keys as numbers and sort them. | ||
| const entries = Object.entries(call.args); | ||
| entries.sort(([keyA], [keyB]) => { | ||
| // Remove surrounding quotes if present to cleanly parse as number | ||
| const numA = parseInt(keyA.replace(/^'|'$/g, ''), 10); | ||
| const numB = parseInt(keyB.replace(/^'|'$/g, ''), 10); | ||
| if (!isNaN(numA) && !isNaN(numB)) { | ||
| return numA - numB; | ||
| } | ||
| return 0; // fallback to stable sort for non-numeric keys | ||
| }); | ||
| rawArgs = entries.map(([, value]) => value); | ||
| } | ||
| const args = rawArgs.map(arg => { | ||
| if (isFunctionCall(arg)) { | ||
| return evaluateFunction(arg, dataModel, catalogId, scopeData); | ||
| } | ||
| if (isDataBindingObject(arg)) { | ||
| return resolveSingleBinding(arg, dataModel, scopeData); | ||
| } | ||
| // Handle nested arrays/objects in args | ||
| if (typeof arg === 'object' && arg !== null) { | ||
| if (Array.isArray(arg)) { | ||
| return arg.map(item => { | ||
| if (isFunctionCall(item)) | ||
| return evaluateFunction(item, dataModel, catalogId, scopeData); | ||
| if (isDataBindingObject(item)) | ||
| return resolveSingleBinding(item, dataModel, scopeData); | ||
| return item; | ||
| }); | ||
| } | ||
| } | ||
| return arg; | ||
| }); | ||
| try { | ||
| return funcImpl(...args); | ||
| } | ||
| catch (error) { | ||
| console.error(`[Freesail] Error evaluating function ${functionName}:`, error); | ||
| return undefined; | ||
| } | ||
| } | ||
| /** | ||
| * Resolve data bindings in an action's context object. | ||
| */ | ||
| function resolveActionContext(context, dataModel, catalogId, scopeData) { | ||
| const resolved = {}; | ||
| for (const [key, value] of Object.entries(context)) { | ||
| if (isFunctionCall(value)) { | ||
| resolved[key] = evaluateFunction(value, dataModel, catalogId, scopeData); | ||
| } | ||
| else if (isDataBindingObject(value)) { | ||
| const path = value.path; | ||
| if (path.startsWith('/')) { | ||
| resolved[key] = getDataAtPath(dataModel, path); | ||
| } | ||
| else if (scopeData !== undefined) { | ||
| resolved[key] = getDataAtPath(scopeData, '/' + path); | ||
| } | ||
| else { | ||
| // Relative path but no scope — normalize to absolute | ||
| resolved[key] = getDataAtPath(dataModel, '/' + path); | ||
| } | ||
| } | ||
| else { | ||
| resolved[key] = value; | ||
| } | ||
| } | ||
| return resolved; | ||
| } | ||
| function getDataAtPath(data, path) { | ||
| if (data === null || data === undefined) | ||
| return undefined; | ||
| const parts = path.split('/').filter((p) => p !== ''); | ||
| let current = data; | ||
| for (const part of parts) { | ||
| if (current === null || typeof current !== 'object') { | ||
| return undefined; | ||
| } | ||
| current = current[part]; | ||
| } | ||
| return current; | ||
| } | ||
| // ============================================================================= | ||
| // Default UI States | ||
| // ============================================================================= | ||
| function DefaultLoading() { | ||
| return (_jsxs("div", { style: { | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| padding: '40px 16px', | ||
| gap: '16px', | ||
| }, children: [_jsx("style", { children: ` | ||
| @keyframes freesail-pulse { | ||
| 0%, 100% { opacity: 0.4; transform: scale(0.95); } | ||
| 50% { opacity: 1; transform: scale(1); } | ||
| } | ||
| @keyframes freesail-spin { | ||
| 0% { transform: rotate(0deg); } | ||
| 100% { transform: rotate(360deg); } | ||
| } | ||
| ` }), FREESAIL_LOGO_DATA_URI ? (_jsx("img", { src: FREESAIL_LOGO_DATA_URI, alt: "Loading", style: { | ||
| width: '48px', | ||
| height: '48px', | ||
| animation: 'freesail-pulse 1.5s ease-in-out infinite', | ||
| } })) : (_jsx("div", { style: { | ||
| width: '32px', | ||
| height: '32px', | ||
| border: '3px solid var(--freesail-border, #e2e8f0)', | ||
| borderTopColor: 'var(--freesail-primary, #2563eb)', | ||
| borderRadius: '50%', | ||
| animation: 'freesail-spin 0.8s linear infinite', | ||
| } })), _jsx("span", { style: { | ||
| fontSize: '13px', | ||
| color: 'var(--freesail-text-muted, #64748b)', | ||
| letterSpacing: '0.05em', | ||
| }, children: "Preparing\u2026" })] })); | ||
| } | ||
| function DefaultError() { | ||
| return (_jsx("div", { style: { padding: '16px', color: '#c00' }, children: "Error: Unable to render surface" })); | ||
| } | ||
| function UnknownComponent({ component }) { | ||
| return (_jsxs("div", { style: { | ||
| padding: '8px', | ||
| border: '1px dashed #f00', | ||
| background: '#fee', | ||
| margin: '4px', | ||
| }, children: [_jsx("strong", { children: "Unknown Component:" }), " ", component.component, _jsx("pre", { style: { fontSize: '10px' }, children: JSON.stringify(component, null, 2) })] })); | ||
| } | ||
| //# sourceMappingURL=FreesailSurface.js.map |
| {"version":3,"file":"FreesailSurface.js","sourceRoot":"","sources":["../src/FreesailSurface.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview FreesailSurface Component\n *\n * The main container component that renders a single A2UI surface.\n * Users drop this into their app to display agent-driven UI.\n */\n\nimport React, { useMemo, useCallback, type ReactNode } from 'react';\nimport { FREESAIL_LOGO_DATA_URI } from './logo.js';\nimport {\n isChildListTemplate,\n isFunctionCall,\n} from '@freesail/core';\nimport type {\n SurfaceId,\n A2UIComponent,\n ComponentId,\n ChildList,\n FunctionCall,\n} from '@freesail/core';\nimport { useSurface, useAction } from './hooks.js';\nimport { registry, type FreesailComponentProps } from './registry.js';\nimport { useFreesailContext } from './context.js';\nimport type { FunctionImplementation } from './types.js';\n\n/**\n * Props for FreesailSurface.\n */\nexport interface FreesailSurfaceProps {\n /** The surface ID to render */\n surfaceId: SurfaceId;\n /** Optional className for the container */\n className?: string;\n /** Loading state component */\n loading?: ReactNode;\n /** Error state component */\n error?: ReactNode;\n /** Empty state component (when surface exists but has no components) */\n empty?: ReactNode;\n}\n\n/**\n * Dispatch function type for actions.\n */\ntype ActionDispatch = (\n name: string,\n sourceComponentId: ComponentId,\n context: Record<string, unknown>\n) => Promise<void>;\n\n/**\n * Callback for two-way binding: components write values to the local data model.\n */\ntype DataChangeDispatch = (path: string, value: unknown) => void;\n\n/**\n * Renders a single A2UI surface.\n *\n * This component subscribes to surface updates and automatically\n * re-renders when the component tree or data model changes.\n */\nexport function FreesailSurface({\n surfaceId,\n className,\n loading = <DefaultLoading />,\n error = <DefaultError />,\n empty = <DefaultLoading />,\n}: FreesailSurfaceProps) {\n const surface = useSurface(surfaceId);\n const dispatch = useAction(surfaceId);\n const { surfaceManager } = useFreesailContext();\n\n // Two-way binding: input components write to the local data model.\n // This is local only — no network request. The updated data model\n // reaches the server via resolved data bindings in action context\n // or via the sendDataModel metadata mechanism.\n const onDataChange: DataChangeDispatch = useCallback(\n (path: string, value: unknown) => {\n console.log(`[Freesail] onDataChange: surface=${surfaceId} path=${path} value=`, value);\n surfaceManager.updateDataModel(surfaceId, path, value);\n },\n [surfaceManager, surfaceId]\n );\n\n // Build the component tree\n const renderedTree = useMemo(() => {\n if (!surface) return null;\n if (surface.components.size === 0) return null;\n if (!surface.rootId) return null;\n\n return renderComponent(\n surface.rootId,\n surface.components,\n surface.catalogId,\n surface.dataModel,\n dispatch,\n onDataChange,\n undefined,\n undefined,\n undefined\n );\n }, [surface, dispatch, onDataChange]);\n\n // Loading state - surface doesn't exist yet\n if (!surface) {\n return <div className={className} style={{ flex: 1, minHeight: 0 }}>{loading}</div>;\n }\n\n // Empty state - surface exists but no components\n if (surface.components.size === 0 || !surface.rootId) {\n return <div className={className} style={{ flex: 1, minHeight: 0 }}>{empty}</div>;\n }\n\n // Check if catalog is registered\n if (!registry.hasCatalog(surface.catalogId)) {\n console.error(`[Freesail] Catalog not registered: ${surface.catalogId}`);\n return <div className={className} style={{ flex: 1, minHeight: 0 }}>{error}</div>;\n }\n\n return <div className={className} data-freesail-surface={surfaceId} style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>{renderedTree}</div>;\n}\n\n// =============================================================================\n// Component Renderer\n// =============================================================================\n\nfunction renderComponent(\n componentId: ComponentId,\n components: Map<ComponentId, A2UIComponent>,\n catalogId: string,\n dataModel: Record<string, unknown>,\n dispatch: ActionDispatch,\n onDataChange: DataChangeDispatch,\n scopeData?: unknown,\n keyOverride?: string,\n scopeBasePath?: string\n): ReactNode {\n const componentDef = components.get(componentId);\n if (!componentDef) {\n // Component may arrive in a subsequent update_components batch — render nothing for now\n return null;\n }\n\n // Get the React component from registry\n const Component = registry.getComponent(catalogId, componentDef.component);\n if (!Component) {\n return <UnknownComponent component={componentDef} />;\n }\n\n // Render children recursively\n let children: ReactNode = null;\n\n // 1. Handle single child (for Card, etc.)\n if (componentDef.child) {\n children = renderComponent(\n componentDef.child,\n components,\n catalogId,\n dataModel,\n dispatch,\n onDataChange,\n scopeData,\n undefined,\n scopeBasePath\n );\n }\n // 2. Handle multiple standard children (Column, Row, List, etc.)\n else if (componentDef.children) {\n const childList = componentDef.children as ChildList;\n\n if (Array.isArray(childList)) {\n // Static array of child IDs\n children = childList.map((childId) =>\n renderComponent(childId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, undefined, scopeBasePath)\n );\n } else if (typeof childList === 'object' && 'componentId' in childList) {\n // Template for dynamic children\n const template = childList;\n const listData = getDataAtPath(dataModel, template.path);\n\n if (Array.isArray(listData)) {\n children = listData.map((itemData, index) => {\n // Build the absolute path for this item in the data model\n const itemBasePath = `${template.path}/${index}`;\n return renderComponent(\n template.componentId,\n components,\n catalogId,\n dataModel,\n dispatch,\n onDataChange,\n itemData, // Pass item data as scope\n `${template.componentId}_${(itemData as any)?.id ?? index}`, // Unique key per item\n itemBasePath // Absolute path for two-way binding\n );\n });\n }\n }\n }\n // 3. Handle named slots for specific components (Tabs, Modal)\n else if (componentDef.component === 'Tabs' && Array.isArray((componentDef as any).tabs)) {\n // Render each tab's child component\n children = (componentDef as any).tabs.map((tab: any, index: number) =>\n renderComponent(\n tab.child as ComponentId,\n components,\n catalogId,\n dataModel,\n dispatch,\n onDataChange,\n scopeData,\n `${componentId}_tab_${index}`,\n scopeBasePath\n )\n );\n } else if (componentDef.component === 'Modal') {\n // Render trigger and content slots\n const triggerId = (componentDef as any).trigger as ComponentId | undefined;\n const contentId = (componentDef as any).content as ComponentId | undefined;\n\n const trigger = triggerId\n ? renderComponent(triggerId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, `${componentId}_trigger`, scopeBasePath)\n : null;\n const content = contentId\n ? renderComponent(contentId, components, catalogId, dataModel, dispatch, onDataChange, scopeData, `${componentId}_content`, scopeBasePath)\n : null;\n\n children = [trigger, content];\n }\n\n // Resolve data bindings in component properties\n const resolvedProps = resolveDataBindings(componentDef, dataModel, catalogId, scopeData, scopeBasePath);\n\n // Build props\n const props: FreesailComponentProps = {\n component: { ...componentDef, ...resolvedProps },\n children,\n dataModel,\n scopeData,\n onAction: (name, context) => {\n // Resolve data bindings in action context at dispatch time.\n const resolvedContext = resolveActionContext(context, dataModel, catalogId, scopeData);\n return dispatch(name, componentDef.id, resolvedContext);\n },\n onDataChange,\n onFunctionCall: (call) => {\n evaluateFunction(call, dataModel, catalogId, scopeData);\n },\n };\n\n return <Component key={keyOverride ?? componentId} {...props} />;\n}\n\n/**\n * Resolve data bindings in component properties.\n */\nfunction resolveDataBindings(\n component: A2UIComponent,\n dataModel: Record<string, unknown>,\n catalogId: string,\n scopeData?: unknown,\n scopeBasePath?: string\n): Record<string, unknown> {\n const resolved: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(component)) {\n if (key === 'id' || key === 'component' || key === 'children' || key === 'child') {\n continue;\n }\n\n // Robustness: Handle double-encoded bindings\n let effectiveValue = value;\n if (typeof value === 'string' && value.trim().startsWith('{') && value.includes('\"path\"')) {\n try {\n const parsed = JSON.parse(value);\n if (isDataBindingObject(parsed)) {\n effectiveValue = parsed;\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n if (isFunctionCall(effectiveValue)) {\n resolved[key] = evaluateFunction(effectiveValue, dataModel, catalogId, scopeData);\n } else if (isDataBindingObject(effectiveValue)) {\n // Preserve the raw binding so components can find the path for two-way binding.\n // If inside a scoped template, convert relative paths to absolute paths\n // so onDataChange writes to the correct location in the data model.\n const rawBinding = { ...effectiveValue };\n if (scopeBasePath && !rawBinding.path.startsWith('/')) {\n rawBinding.path = `${scopeBasePath}/${rawBinding.path}`;\n }\n resolved[`__raw${key.charAt(0).toUpperCase()}${key.slice(1)}`] = rawBinding;\n // Resolve data binding\n resolved[key] = resolveSingleBinding(effectiveValue, dataModel, scopeData);\n\n } else if (typeof value === 'object' && value !== null) {\n // Prevent recursion into LocalAction definitions (which contain FunctionCalls that should NOT be evaluated yet)\n if ('functionCall' in value && isFunctionCall((value as any).functionCall)) {\n resolved[key] = value;\n continue;\n }\n\n // Recursively resolve bindings inside objects and arrays\n if (Array.isArray(value)) {\n resolved[key] = value.map(item => {\n if (typeof item === 'object' && item !== null) {\n // Check for LocalAction in array items too\n if ('functionCall' in item && isFunctionCall((item as any).functionCall)) {\n return item;\n }\n if (isFunctionCall(item)) {\n return evaluateFunction(item, dataModel, catalogId, scopeData);\n }\n if (isDataBindingObject(item)) {\n return resolveSingleBinding(item, dataModel, scopeData);\n }\n return resolveDataBindings(item as any, dataModel, catalogId, scopeData);\n }\n return item;\n });\n } else {\n resolved[key] = resolveDataBindings(value as any, dataModel, catalogId, scopeData);\n }\n } else {\n resolved[key] = value;\n }\n }\n\n return resolved;\n}\n\n/**\n * Helper to resolve a single binding object, following chains.\n */\nfunction resolveSingleBinding(\n binding: { path: string },\n dataModel: Record<string, unknown>,\n scopeData?: unknown\n): unknown {\n const path = binding.path;\n let resolvedValue: unknown;\n\n // \".\" or \"\" means \"the current scoped item\" — used when iterating scalar arrays\n if (path === '.' || path === '') {\n return scopeData !== undefined ? scopeData : getDataAtPath(dataModel, '/');\n }\n\n if (path.startsWith('/')) {\n resolvedValue = getDataAtPath(dataModel, path);\n } else if (scopeData !== undefined) {\n resolvedValue = getDataAtPath(scopeData as Record<string, unknown>, '/' + path);\n } else {\n resolvedValue = getDataAtPath(dataModel, '/' + path);\n }\n\n // Chained bindings (max depth 5)\n let depth = 0;\n while (isDataBindingObject(resolvedValue) && depth < 5) {\n const chainedPath = resolvedValue.path;\n resolvedValue = chainedPath.startsWith('/')\n ? getDataAtPath(dataModel, chainedPath)\n : getDataAtPath(dataModel, '/' + chainedPath);\n depth++;\n }\n\n return resolvedValue;\n}\n\nfunction isDataBindingObject(value: unknown): value is { path: string } {\n if (typeof value !== 'object' || value === null || !('path' in value)) return false;\n if (typeof (value as Record<string, unknown>)['path'] !== 'string') return false;\n if ('componentId' in value) return false; // ChildListTemplate\n if ('event' in value) return false; // ServerAction\n if ('call' in value) return false; // FunctionCall\n return true;\n}\n\n/**\n * Evaluate a function call.\n */\nexport function evaluateFunction(\n call: FunctionCall,\n dataModel: Record<string, unknown>,\n catalogId: string,\n scopeData?: unknown\n): unknown {\n const functionName = call.call;\n const funcImpl = registry.getFunction(catalogId, functionName);\n\n if (!funcImpl) {\n console.warn(`[Freesail] Function not found: ${functionName} in catalog ${catalogId}`);\n return undefined;\n }\n\n // Resolve arguments\n let rawArgs: unknown[] = [];\n if (Array.isArray(call.args)) {\n rawArgs = call.args;\n } else if (call.args && typeof call.args === 'object') {\n // If it's an object, we need to extract the values in the correct order.\n // Agents often generate object keys like \"'0'\", \"'1'\" out of numerical order,\n // so we parse the keys as numbers and sort them.\n const entries = Object.entries(call.args);\n entries.sort(([keyA], [keyB]) => {\n // Remove surrounding quotes if present to cleanly parse as number\n const numA = parseInt(keyA.replace(/^'|'$/g, ''), 10);\n const numB = parseInt(keyB.replace(/^'|'$/g, ''), 10);\n if (!isNaN(numA) && !isNaN(numB)) {\n return numA - numB;\n }\n return 0; // fallback to stable sort for non-numeric keys\n });\n rawArgs = entries.map(([, value]) => value);\n }\n\n const args = rawArgs.map(arg => {\n if (isFunctionCall(arg)) {\n return evaluateFunction(arg, dataModel, catalogId, scopeData);\n }\n if (isDataBindingObject(arg)) {\n return resolveSingleBinding(arg, dataModel, scopeData);\n }\n // Handle nested arrays/objects in args\n if (typeof arg === 'object' && arg !== null) {\n if (Array.isArray(arg)) {\n return arg.map(item => {\n if (isFunctionCall(item)) return evaluateFunction(item, dataModel, catalogId, scopeData);\n if (isDataBindingObject(item)) return resolveSingleBinding(item, dataModel, scopeData);\n return item;\n });\n }\n }\n return arg;\n });\n\n try {\n return funcImpl(...args);\n } catch (error) {\n console.error(`[Freesail] Error evaluating function ${functionName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Resolve data bindings in an action's context object.\n */\nfunction resolveActionContext(\n context: Record<string, unknown>,\n dataModel: Record<string, unknown>,\n catalogId: string,\n scopeData?: unknown\n): Record<string, unknown> {\n const resolved: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(context)) {\n if (isFunctionCall(value)) {\n resolved[key] = evaluateFunction(value, dataModel, catalogId, scopeData);\n } else if (isDataBindingObject(value)) {\n const path = value.path;\n if (path.startsWith('/')) {\n resolved[key] = getDataAtPath(dataModel, path);\n } else if (scopeData !== undefined) {\n resolved[key] = getDataAtPath(scopeData as Record<string, unknown>, '/' + path);\n } else {\n // Relative path but no scope — normalize to absolute\n resolved[key] = getDataAtPath(dataModel, '/' + path);\n }\n } else {\n resolved[key] = value;\n }\n }\n\n return resolved;\n}\n\nfunction getDataAtPath(data: unknown, path: string): unknown {\n if (data === null || data === undefined) return undefined;\n\n const parts = path.split('/').filter((p) => p !== '');\n let current: unknown = data;\n\n for (const part of parts) {\n if (current === null || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n// =============================================================================\n// Default UI States\n// =============================================================================\n\nfunction DefaultLoading() {\n return (\n <div style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '40px 16px',\n gap: '16px',\n }}>\n <style>{`\n @keyframes freesail-pulse {\n 0%, 100% { opacity: 0.4; transform: scale(0.95); }\n 50% { opacity: 1; transform: scale(1); }\n }\n @keyframes freesail-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n `}</style>\n {FREESAIL_LOGO_DATA_URI ? (\n <img\n src={FREESAIL_LOGO_DATA_URI}\n alt=\"Loading\"\n style={{\n width: '48px',\n height: '48px',\n animation: 'freesail-pulse 1.5s ease-in-out infinite',\n }}\n />\n ) : (\n <div style={{\n width: '32px',\n height: '32px',\n border: '3px solid var(--freesail-border, #e2e8f0)',\n borderTopColor: 'var(--freesail-primary, #2563eb)',\n borderRadius: '50%',\n animation: 'freesail-spin 0.8s linear infinite',\n }} />\n )}\n <span style={{\n fontSize: '13px',\n color: 'var(--freesail-text-muted, #64748b)',\n letterSpacing: '0.05em',\n }}>Preparing…</span>\n </div>\n );\n}\n\nfunction DefaultError() {\n return (\n <div style={{ padding: '16px', color: '#c00' }}>\n Error: Unable to render surface\n </div>\n );\n}\n\nfunction UnknownComponent({ component }: { component: A2UIComponent }) {\n return (\n <div\n style={{\n padding: '8px',\n border: '1px dashed #f00',\n background: '#fee',\n margin: '4px',\n }}\n >\n <strong>Unknown Component:</strong> {component.component}\n <pre style={{ fontSize: '10px' }}>\n {JSON.stringify(component, null, 2)}\n </pre>\n </div>\n );\n}\n"]} |
| /** | ||
| * @fileoverview Freesail React Hooks | ||
| * | ||
| * Custom hooks for interacting with Freesail surfaces and data. | ||
| */ | ||
| import type { SurfaceId, Surface, JsonPointer, ComponentId } from '@freesail/core'; | ||
| /** | ||
| * Hook to access and subscribe to a specific surface. | ||
| */ | ||
| export declare function useSurface(surfaceId: SurfaceId): Surface | undefined; | ||
| /** | ||
| * Hook to access data from a surface's data model. | ||
| */ | ||
| export declare function useSurfaceData<T = unknown>(surfaceId: SurfaceId, path?: JsonPointer): T | undefined; | ||
| /** | ||
| * Hook to send user actions (v0.9 format). | ||
| */ | ||
| export declare function useAction(surfaceId: SurfaceId): (name: string, sourceComponentId: ComponentId, context?: Record<string, unknown>) => Promise<void>; | ||
| /** | ||
| * Hook to get connection status. | ||
| */ | ||
| export declare function useConnectionStatus(): { | ||
| isConnected: boolean; | ||
| }; | ||
| /** | ||
| * Hook to get all surfaces. | ||
| */ | ||
| export declare function useSurfaces(): Surface[]; | ||
| /** | ||
| * Hook to access the current session ID assigned by the Gateway. | ||
| * This ID is available after the transport successfully connects. | ||
| */ | ||
| export declare function useSessionId(): string | null; | ||
| //# sourceMappingURL=hooks.d.ts.map |
| {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGnF;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CA4CpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,EACxC,SAAS,EAAE,SAAS,EACpB,IAAI,CAAC,EAAE,WAAW,GACjB,CAAC,GAAG,SAAS,CA8Bf;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,SAAS,UAKlC,MAAM,qBACO,WAAW,YACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,mBAQrC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI;IACrC,WAAW,EAAE,OAAO,CAAC;CACtB,CAGA;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,OAAO,EAAE,CAwBvC;AA2BD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAiB5C"} |
-151
| /** | ||
| * @fileoverview Freesail React Hooks | ||
| * | ||
| * Custom hooks for interacting with Freesail surfaces and data. | ||
| */ | ||
| import { useState, useEffect, useCallback, useMemo } from 'react'; | ||
| import { useFreesailContext } from './context.js'; | ||
| /** | ||
| * Hook to access and subscribe to a specific surface. | ||
| */ | ||
| export function useSurface(surfaceId) { | ||
| const { surfaceManager, getSurface } = useFreesailContext(); | ||
| const [surface, setSurface] = useState(() => getSurface(surfaceId)); | ||
| useEffect(() => { | ||
| // Initial state | ||
| setSurface(getSurface(surfaceId)); | ||
| // Subscribe to surface changes | ||
| const unsubCreate = surfaceManager.on('surfaceCreated', (created) => { | ||
| if (created.id === surfaceId) { | ||
| setSurface(created); | ||
| } | ||
| }); | ||
| const unsubDelete = surfaceManager.on('surfaceDeleted', (deletedId) => { | ||
| if (deletedId === surfaceId) { | ||
| setSurface(undefined); | ||
| } | ||
| }); | ||
| const unsubComponents = surfaceManager.on('componentsUpdated', (updatedId) => { | ||
| if (updatedId === surfaceId) { | ||
| setSurface({ ...getSurface(surfaceId) }); | ||
| } | ||
| }); | ||
| const unsubData = surfaceManager.on('dataModelUpdated', (updatedId) => { | ||
| if (updatedId === surfaceId) { | ||
| setSurface({ ...getSurface(surfaceId) }); | ||
| } | ||
| }); | ||
| return () => { | ||
| unsubCreate(); | ||
| unsubDelete(); | ||
| unsubComponents(); | ||
| unsubData(); | ||
| }; | ||
| }, [surfaceId, surfaceManager, getSurface]); | ||
| return surface; | ||
| } | ||
| /** | ||
| * Hook to access data from a surface's data model. | ||
| */ | ||
| export function useSurfaceData(surfaceId, path) { | ||
| const { surfaceManager, getSurface } = useFreesailContext(); | ||
| const [data, setData] = useState(() => { | ||
| const surface = getSurface(surfaceId); | ||
| if (!surface) | ||
| return undefined; | ||
| return getDataAtPath(surface.dataModel, path); | ||
| }); | ||
| useEffect(() => { | ||
| const surface = getSurface(surfaceId); | ||
| if (surface) { | ||
| setData(getDataAtPath(surface.dataModel, path)); | ||
| } | ||
| const unsub = surfaceManager.on('dataModelUpdated', (updatedId, updatedPath) => { | ||
| if (updatedId === surfaceId) { | ||
| // Check if the update affects our path | ||
| if (!path || updatedPath.startsWith(path) || path.startsWith(updatedPath)) { | ||
| const currentSurface = getSurface(surfaceId); | ||
| if (currentSurface) { | ||
| setData(getDataAtPath(currentSurface.dataModel, path)); | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| return unsub; | ||
| }, [surfaceId, path, surfaceManager, getSurface]); | ||
| return data; | ||
| } | ||
| /** | ||
| * Hook to send user actions (v0.9 format). | ||
| */ | ||
| export function useAction(surfaceId) { | ||
| const { sendAction } = useFreesailContext(); | ||
| const dispatch = useCallback(async (name, sourceComponentId, context = {}) => { | ||
| await sendAction(surfaceId, name, sourceComponentId, context); | ||
| }, [surfaceId, sendAction]); | ||
| return dispatch; | ||
| } | ||
| /** | ||
| * Hook to get connection status. | ||
| */ | ||
| export function useConnectionStatus() { | ||
| const { isConnected } = useFreesailContext(); | ||
| return useMemo(() => ({ isConnected }), [isConnected]); | ||
| } | ||
| /** | ||
| * Hook to get all surfaces. | ||
| */ | ||
| export function useSurfaces() { | ||
| const { surfaceManager } = useFreesailContext(); | ||
| const [surfaces, setSurfaces] = useState(() => surfaceManager.getAllSurfaces()); | ||
| useEffect(() => { | ||
| setSurfaces(surfaceManager.getAllSurfaces()); | ||
| const unsubCreate = surfaceManager.on('surfaceCreated', () => { | ||
| setSurfaces(surfaceManager.getAllSurfaces()); | ||
| }); | ||
| const unsubDelete = surfaceManager.on('surfaceDeleted', () => { | ||
| setSurfaces(surfaceManager.getAllSurfaces()); | ||
| }); | ||
| return () => { | ||
| unsubCreate(); | ||
| unsubDelete(); | ||
| }; | ||
| }, [surfaceManager]); | ||
| return surfaces; | ||
| } | ||
| // ============================================================================= | ||
| // Helpers | ||
| // ============================================================================= | ||
| function getDataAtPath(data, path) { | ||
| if (!path || path === '/') { | ||
| return data; | ||
| } | ||
| const parts = path.split('/').filter((p) => p !== ''); | ||
| let current = data; | ||
| for (const part of parts) { | ||
| if (current === null || typeof current !== 'object') { | ||
| return undefined; | ||
| } | ||
| current = current[part]; | ||
| } | ||
| return current; | ||
| } | ||
| /** | ||
| * Hook to access the current session ID assigned by the Gateway. | ||
| * This ID is available after the transport successfully connects. | ||
| */ | ||
| export function useSessionId() { | ||
| const { transport } = useFreesailContext(); | ||
| const [sessionId, setSessionId] = useState(() => transport?.sessionId ?? null); | ||
| useEffect(() => { | ||
| if (!transport) | ||
| return; | ||
| setSessionId(transport.sessionId); | ||
| const unsub = transport.on('sessionStart', (sid) => { | ||
| setSessionId(sid); | ||
| }); | ||
| return unsub; | ||
| }, [transport]); | ||
| return sessionId; | ||
| } | ||
| //# sourceMappingURL=hooks.js.map |
| {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,SAAoB;IAC7C,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC5D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAsB,GAAG,EAAE,CAC/D,UAAU,CAAC,SAAS,CAAC,CACtB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,gBAAgB;QAChB,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAElC,+BAA+B;QAC/B,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,EAAE;YAClE,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC7B,UAAU,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,SAAS,EAAE,EAAE;YACpE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,UAAU,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,cAAc,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,SAAS,EAAE,EAAE;YAC3E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,UAAU,CAAC,EAAE,GAAG,UAAU,CAAC,SAAS,CAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,cAAc,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,SAAS,EAAE,EAAE;YACpE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,UAAU,CAAC,EAAE,GAAG,UAAU,CAAC,SAAS,CAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,CAAC;YACd,eAAe,EAAE,CAAC;YAClB,SAAS,EAAE,CAAC;QACd,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;IAE5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAoB,EACpB,IAAkB;IAElB,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC5D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,GAAG,EAAE;QACnD,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,OAAO,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAM,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAM,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE;YAC7E,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,uCAAuC;gBACvC,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC1E,MAAM,cAAc,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;oBAC7C,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAM,CAAC,CAAC;oBAC9D,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;IAElD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,SAAoB;IAC5C,MAAM,EAAE,UAAU,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAE5C,MAAM,QAAQ,GAAG,WAAW,CAC1B,KAAK,EACH,IAAY,EACZ,iBAA8B,EAC9B,UAAmC,EAAE,EACrC,EAAE;QACF,MAAM,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC,EACD,CAAC,SAAS,EAAE,UAAU,CAAC,CACxB,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IAGjC,MAAM,EAAE,WAAW,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC7C,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,cAAc,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY,GAAG,EAAE,CACvD,cAAc,CAAC,cAAc,EAAE,CAChC,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC;QAE7C,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC3D,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,cAAc,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC3D,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAErB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAEhF,SAAS,aAAa,CACpB,IAA6B,EAC7B,IAAkB;IAElB,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACtD,IAAI,OAAO,GAAY,IAAI,CAAC;IAE5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAI,OAAmC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,EAAE,SAAS,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgB,GAAG,EAAE,CAAC,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,CAAC;IAE9F,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAElC,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;YACjD,YAAY,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;IAEhB,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["/**\n * @fileoverview Freesail React Hooks\n *\n * Custom hooks for interacting with Freesail surfaces and data.\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport type { SurfaceId, Surface, JsonPointer, ComponentId } from '@freesail/core';\nimport { useFreesailContext } from './context.js';\n\n/**\n * Hook to access and subscribe to a specific surface.\n */\nexport function useSurface(surfaceId: SurfaceId): Surface | undefined {\n const { surfaceManager, getSurface } = useFreesailContext();\n const [surface, setSurface] = useState<Surface | undefined>(() =>\n getSurface(surfaceId)\n );\n\n useEffect(() => {\n // Initial state\n setSurface(getSurface(surfaceId));\n\n // Subscribe to surface changes\n const unsubCreate = surfaceManager.on('surfaceCreated', (created) => {\n if (created.id === surfaceId) {\n setSurface(created);\n }\n });\n\n const unsubDelete = surfaceManager.on('surfaceDeleted', (deletedId) => {\n if (deletedId === surfaceId) {\n setSurface(undefined);\n }\n });\n\n const unsubComponents = surfaceManager.on('componentsUpdated', (updatedId) => {\n if (updatedId === surfaceId) {\n setSurface({ ...getSurface(surfaceId)! });\n }\n });\n\n const unsubData = surfaceManager.on('dataModelUpdated', (updatedId) => {\n if (updatedId === surfaceId) {\n setSurface({ ...getSurface(surfaceId)! });\n }\n });\n\n return () => {\n unsubCreate();\n unsubDelete();\n unsubComponents();\n unsubData();\n };\n }, [surfaceId, surfaceManager, getSurface]);\n\n return surface;\n}\n\n/**\n * Hook to access data from a surface's data model.\n */\nexport function useSurfaceData<T = unknown>(\n surfaceId: SurfaceId,\n path?: JsonPointer\n): T | undefined {\n const { surfaceManager, getSurface } = useFreesailContext();\n const [data, setData] = useState<T | undefined>(() => {\n const surface = getSurface(surfaceId);\n if (!surface) return undefined;\n return getDataAtPath(surface.dataModel, path) as T;\n });\n\n useEffect(() => {\n const surface = getSurface(surfaceId);\n if (surface) {\n setData(getDataAtPath(surface.dataModel, path) as T);\n }\n\n const unsub = surfaceManager.on('dataModelUpdated', (updatedId, updatedPath) => {\n if (updatedId === surfaceId) {\n // Check if the update affects our path\n if (!path || updatedPath.startsWith(path) || path.startsWith(updatedPath)) {\n const currentSurface = getSurface(surfaceId);\n if (currentSurface) {\n setData(getDataAtPath(currentSurface.dataModel, path) as T);\n }\n }\n }\n });\n\n return unsub;\n }, [surfaceId, path, surfaceManager, getSurface]);\n\n return data;\n}\n\n/**\n * Hook to send user actions (v0.9 format).\n */\nexport function useAction(surfaceId: SurfaceId) {\n const { sendAction } = useFreesailContext();\n\n const dispatch = useCallback(\n async (\n name: string,\n sourceComponentId: ComponentId,\n context: Record<string, unknown> = {}\n ) => {\n await sendAction(surfaceId, name, sourceComponentId, context);\n },\n [surfaceId, sendAction]\n );\n\n return dispatch;\n}\n\n/**\n * Hook to get connection status.\n */\nexport function useConnectionStatus(): {\n isConnected: boolean;\n} {\n const { isConnected } = useFreesailContext();\n return useMemo(() => ({ isConnected }), [isConnected]);\n}\n\n/**\n * Hook to get all surfaces.\n */\nexport function useSurfaces(): Surface[] {\n const { surfaceManager } = useFreesailContext();\n const [surfaces, setSurfaces] = useState<Surface[]>(() =>\n surfaceManager.getAllSurfaces()\n );\n\n useEffect(() => {\n setSurfaces(surfaceManager.getAllSurfaces());\n\n const unsubCreate = surfaceManager.on('surfaceCreated', () => {\n setSurfaces(surfaceManager.getAllSurfaces());\n });\n\n const unsubDelete = surfaceManager.on('surfaceDeleted', () => {\n setSurfaces(surfaceManager.getAllSurfaces());\n });\n\n return () => {\n unsubCreate();\n unsubDelete();\n };\n }, [surfaceManager]);\n\n return surfaces;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\nfunction getDataAtPath(\n data: Record<string, unknown>,\n path?: JsonPointer\n): unknown {\n if (!path || path === '/') {\n return data;\n }\n\n const parts = path.split('/').filter((p) => p !== '');\n let current: unknown = data;\n\n for (const part of parts) {\n if (current === null || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/**\n * Hook to access the current session ID assigned by the Gateway.\n * This ID is available after the transport successfully connects.\n */\nexport function useSessionId(): string | null {\n const { transport } = useFreesailContext();\n const [sessionId, setSessionId] = useState<string | null>(() => transport?.sessionId ?? null);\n\n useEffect(() => {\n if (!transport) return;\n \n setSessionId(transport.sessionId);\n \n const unsub = transport.on('sessionStart', (sid) => {\n setSessionId(sid);\n });\n \n return unsub;\n }, [transport]);\n\n return sessionId;\n}\n"]} |
| /** | ||
| * @fileoverview Freesail React - Public API | ||
| */ | ||
| export { FreesailProvider, type FreesailProviderProps } from './FreesailProvider.js'; | ||
| export { FreesailSurface, type FreesailSurfaceProps } from './FreesailSurface.js'; | ||
| export { FreesailContext, useFreesailContext, type FreesailContextValue } from './context.js'; | ||
| export { useSurface, useSurfaceData, useAction, useConnectionStatus, useSurfaces, useSessionId, } from './hooks.js'; | ||
| export { registry, withCatalog, registerCatalog, type FreesailComponent, type FreesailComponentProps, } from './registry.js'; | ||
| export { type CatalogDefinition, type FunctionImplementation } from './types.js'; | ||
| export type { SurfaceId, ComponentId, CatalogId, A2UIComponent, Surface, } from '@freesail/core'; | ||
| export * from './theme.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGrF,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGlF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG9F,OAAO,EACL,UAAU,EACV,cAAc,EACd,SAAS,EACT,mBAAmB,EACnB,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGjF,YAAY,EACV,SAAS,EACT,WAAW,EACX,SAAS,EACT,aAAa,EACb,OAAO,GACR,MAAM,gBAAgB,CAAC;AAGxB,cAAc,YAAY,CAAC"} |
| /** | ||
| * @fileoverview Freesail React - Public API | ||
| */ | ||
| // Provider | ||
| export { FreesailProvider } from './FreesailProvider.js'; | ||
| // Surface Component | ||
| export { FreesailSurface } from './FreesailSurface.js'; | ||
| // Context | ||
| export { FreesailContext, useFreesailContext } from './context.js'; | ||
| // Hooks | ||
| export { useSurface, useSurfaceData, useAction, useConnectionStatus, useSurfaces, useSessionId, } from './hooks.js'; | ||
| // Registry | ||
| export { registry, withCatalog, registerCatalog, } from './registry.js'; | ||
| // Theme | ||
| export * from './theme.js'; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,WAAW;AACX,OAAO,EAAE,gBAAgB,EAA8B,MAAM,uBAAuB,CAAC;AAErF,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAA6B,MAAM,sBAAsB,CAAC;AAElF,UAAU;AACV,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAA6B,MAAM,cAAc,CAAC;AAE9F,QAAQ;AACR,OAAO,EACL,UAAU,EACV,cAAc,EACd,SAAS,EACT,mBAAmB,EACnB,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,WAAW;AACX,OAAO,EACL,QAAQ,EACR,WAAW,EACX,eAAe,GAGhB,MAAM,eAAe,CAAC;AAcvB,QAAQ;AACR,cAAc,YAAY,CAAC","sourcesContent":["/**\n * @fileoverview Freesail React - Public API\n */\n\n// Provider\nexport { FreesailProvider, type FreesailProviderProps } from './FreesailProvider.js';\n\n// Surface Component\nexport { FreesailSurface, type FreesailSurfaceProps } from './FreesailSurface.js';\n\n// Context\nexport { FreesailContext, useFreesailContext, type FreesailContextValue } from './context.js';\n\n// Hooks\nexport {\n useSurface,\n useSurfaceData,\n useAction,\n useConnectionStatus,\n useSurfaces,\n useSessionId,\n} from './hooks.js';\n\n// Registry\nexport {\n registry,\n withCatalog,\n registerCatalog,\n type FreesailComponent,\n type FreesailComponentProps,\n} from './registry.js';\n\n// Types\nexport { type CatalogDefinition, type FunctionImplementation } from './types.js';\n\n// Re-export core types for convenience\nexport type {\n SurfaceId,\n ComponentId,\n CatalogId,\n A2UIComponent,\n Surface,\n} from '@freesail/core';\n\n// Theme\nexport * from './theme.js';\n"]} |
| export declare const FREESAIL_LOGO_DATA_URI = "data:image/png;base64,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"; | ||
| //# sourceMappingURL=logo.d.ts.map |
| {"version":3,"file":"logo.d.ts","sourceRoot":"","sources":["../src/logo.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,24nCAA24nC,CAAC"} |
| // Auto-generated by scripts/generate-logo-base64.ts — do not edit manually | ||
| export const FREESAIL_LOGO_DATA_URI = 'data:image/png;base64,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'; | ||
| //# sourceMappingURL=logo.js.map |
| {"version":3,"file":"logo.js","sourceRoot":"","sources":["../src/logo.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,sBAAsB,GAAG,w4nCAAw4nC,CAAC","sourcesContent":["// Auto-generated by scripts/generate-logo-base64.ts — do not edit manually\nexport const FREESAIL_LOGO_DATA_URI = 'data:image/png;base64,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';\n"]} |
| /** | ||
| * @fileoverview Component Registry | ||
| * | ||
| * Maps component names from the catalog to React components. | ||
| * This enables the renderer to dynamically instantiate components | ||
| * based on A2UI messages. | ||
| */ | ||
| import type { ComponentType, ReactNode } from 'react'; | ||
| import type { A2UIComponent, CatalogId, FunctionCall } from '@freesail/core'; | ||
| import type { FunctionImplementation } from './types.js'; | ||
| /** | ||
| * Props passed to all Freesail components. | ||
| */ | ||
| export interface FreesailComponentProps { | ||
| /** The component definition from the A2UI message (with resolved data bindings) */ | ||
| component: A2UIComponent; | ||
| /** Rendered children (for container components) */ | ||
| children?: ReactNode; | ||
| /** Full data model for the surface (server → client, kept in sync by two-way binding) */ | ||
| dataModel?: Record<string, unknown>; | ||
| /** Scope data when inside a template iteration */ | ||
| scopeData?: unknown; | ||
| /** Callback to dispatch user actions (client → server) */ | ||
| onAction?: (name: string, context: Record<string, unknown>) => void; | ||
| /** | ||
| * Write a value to the local data model at the given JSON Pointer path. | ||
| * This is the "Write" half of A2UI two-way binding — input components | ||
| * call this on every user interaction (keystroke, toggle, etc.). | ||
| * The update is LOCAL only; it does NOT send a message to the server. | ||
| * The updated data model reaches the server when an action is dispatched | ||
| * (either via resolved data bindings in the action context, or via | ||
| * the sendDataModel metadata mechanism). | ||
| */ | ||
| onDataChange?: (path: string, value: unknown) => void; | ||
| /** | ||
| * Execute a function call definition. | ||
| * This is for LocalAction handling (client-side logic). | ||
| */ | ||
| onFunctionCall?: (call: FunctionCall) => void; | ||
| } | ||
| /** | ||
| * A React component that can render an A2UX component. | ||
| */ | ||
| export type FreesailComponent = ComponentType<FreesailComponentProps>; | ||
| /** | ||
| * Component map within a catalog. | ||
| */ | ||
| export type ComponentMap = Map<string, FreesailComponent>; | ||
| /** | ||
| * Registry of all catalogs and their components. | ||
| */ | ||
| declare class ComponentRegistry { | ||
| private catalogs; | ||
| private functions; | ||
| private fallbackComponent; | ||
| /** | ||
| * Register a catalog with its components and functions. | ||
| */ | ||
| registerCatalog(catalogId: CatalogId, components: Record<string, FreesailComponent>, functions?: Record<string, FunctionImplementation>): void; | ||
| /** | ||
| * Register a single component in a catalog. | ||
| */ | ||
| registerComponent(catalogId: CatalogId, componentName: string, component: FreesailComponent): void; | ||
| /** | ||
| * Get a component from a catalog. | ||
| */ | ||
| getComponent(catalogId: CatalogId, componentName: string): FreesailComponent | null; | ||
| /** | ||
| * Get a function from a catalog. | ||
| */ | ||
| getFunction(catalogId: CatalogId, functionName: string): FunctionImplementation | null; | ||
| /** | ||
| * Check if a catalog is registered. | ||
| */ | ||
| hasCatalog(catalogId: CatalogId): boolean; | ||
| /** | ||
| * Get all registered catalog IDs. | ||
| */ | ||
| getCatalogIds(): CatalogId[]; | ||
| /** | ||
| * Set a fallback component for unknown components. | ||
| */ | ||
| setFallbackComponent(component: FreesailComponent): void; | ||
| /** | ||
| * Clear all registrations. | ||
| */ | ||
| clear(): void; | ||
| } | ||
| /** | ||
| * Global component registry instance. | ||
| */ | ||
| export declare const registry: ComponentRegistry; | ||
| /** | ||
| * Higher-order function to create a component with catalog binding. | ||
| * This ensures the component is registered when imported. | ||
| */ | ||
| export declare function withCatalog<P extends FreesailComponentProps>(catalogId: CatalogId, componentName: string, Component: ComponentType<P>): ComponentType<P>; | ||
| /** | ||
| * Register multiple components for a catalog at once. | ||
| */ | ||
| export declare function registerCatalog(catalogId: CatalogId, components: Record<string, FreesailComponent>, functions?: Record<string, FunctionImplementation>): void; | ||
| export {}; | ||
| //# sourceMappingURL=registry.d.ts.map |
| {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,SAAS,EAAE,aAAa,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpE;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACtD;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC,sBAAsB,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAE1D;;GAEG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,SAAS,CAAqE;IACtF,OAAO,CAAC,iBAAiB,CAAkC;IAE3D;;OAEG;IACH,eAAe,CACb,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAC7C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,GACjD,IAAI;IAQP;;OAEG;IACH,iBAAiB,CACf,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iBAAiB,GAC3B,IAAI;IAOP;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAgBnF;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI;IAiBtF;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO;IAIzC;;OAEG;IACH,aAAa,IAAI,SAAS,EAAE;IAI5B;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAIxD;;OAEG;IACH,KAAK,IAAI,IAAI;CAKd;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,mBAA0B,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,sBAAsB,EAC1D,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,GAC1B,aAAa,CAAC,CAAC,CAAC,CAGlB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAC7C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,GACjD,IAAI,CAEN"} |
-114
| /** | ||
| * @fileoverview Component Registry | ||
| * | ||
| * Maps component names from the catalog to React components. | ||
| * This enables the renderer to dynamically instantiate components | ||
| * based on A2UI messages. | ||
| */ | ||
| /** | ||
| * Registry of all catalogs and their components. | ||
| */ | ||
| class ComponentRegistry { | ||
| catalogs = new Map(); | ||
| functions = new Map(); | ||
| fallbackComponent = null; | ||
| /** | ||
| * Register a catalog with its components and functions. | ||
| */ | ||
| registerCatalog(catalogId, components, functions) { | ||
| const map = new Map(Object.entries(components)); | ||
| this.catalogs.set(catalogId, map); | ||
| if (functions) { | ||
| this.functions.set(catalogId, functions); | ||
| } | ||
| } | ||
| /** | ||
| * Register a single component in a catalog. | ||
| */ | ||
| registerComponent(catalogId, componentName, component) { | ||
| if (!this.catalogs.has(catalogId)) { | ||
| this.catalogs.set(catalogId, new Map()); | ||
| } | ||
| this.catalogs.get(catalogId).set(componentName, component); | ||
| } | ||
| /** | ||
| * Get a component from a catalog. | ||
| */ | ||
| getComponent(catalogId, componentName) { | ||
| const catalog = this.catalogs.get(catalogId); | ||
| if (!catalog) { | ||
| console.warn(`Catalog not found: ${catalogId}`); | ||
| return this.fallbackComponent; | ||
| } | ||
| const component = catalog.get(componentName); | ||
| if (!component) { | ||
| console.warn(`Component not found: ${componentName} in catalog ${catalogId}`); | ||
| return this.fallbackComponent; | ||
| } | ||
| return component; | ||
| } | ||
| /** | ||
| * Get a function from a catalog. | ||
| */ | ||
| getFunction(catalogId, functionName) { | ||
| const catalogFunctions = this.functions.get(catalogId); | ||
| if (!catalogFunctions) { | ||
| return null; | ||
| } | ||
| // Direct lookup first | ||
| if (catalogFunctions[functionName] != null) { | ||
| return catalogFunctions[functionName]; | ||
| } | ||
| // Fallback: try snake_case -> camelCase conversion (e.g. open_url -> openUrl) | ||
| if (functionName.includes('_')) { | ||
| const camelName = functionName.replace(/_([a-z])/g, (_match, p1) => p1.toUpperCase()); | ||
| return catalogFunctions[camelName] ?? null; | ||
| } | ||
| return null; | ||
| } | ||
| /** | ||
| * Check if a catalog is registered. | ||
| */ | ||
| hasCatalog(catalogId) { | ||
| return this.catalogs.has(catalogId); | ||
| } | ||
| /** | ||
| * Get all registered catalog IDs. | ||
| */ | ||
| getCatalogIds() { | ||
| return Array.from(this.catalogs.keys()); | ||
| } | ||
| /** | ||
| * Set a fallback component for unknown components. | ||
| */ | ||
| setFallbackComponent(component) { | ||
| this.fallbackComponent = component; | ||
| } | ||
| /** | ||
| * Clear all registrations. | ||
| */ | ||
| clear() { | ||
| this.catalogs.clear(); | ||
| this.functions.clear(); | ||
| this.fallbackComponent = null; | ||
| } | ||
| } | ||
| /** | ||
| * Global component registry instance. | ||
| */ | ||
| export const registry = new ComponentRegistry(); | ||
| /** | ||
| * Higher-order function to create a component with catalog binding. | ||
| * This ensures the component is registered when imported. | ||
| */ | ||
| export function withCatalog(catalogId, componentName, Component) { | ||
| registry.registerComponent(catalogId, componentName, Component); | ||
| return Component; | ||
| } | ||
| /** | ||
| * Register multiple components for a catalog at once. | ||
| */ | ||
| export function registerCatalog(catalogId, components, functions) { | ||
| registry.registerCatalog(catalogId, components, functions); | ||
| } | ||
| //# sourceMappingURL=registry.js.map |
| {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Component Registry\n *\n * Maps component names from the catalog to React components.\n * This enables the renderer to dynamically instantiate components\n * based on A2UI messages.\n */\n\nimport type { ComponentType, ReactNode } from 'react';\nimport type { A2UIComponent, CatalogId, FunctionCall } from '@freesail/core';\nimport type { FunctionImplementation } from './types.js';\n\n/**\n * Props passed to all Freesail components.\n */\nexport interface FreesailComponentProps {\n /** The component definition from the A2UI message (with resolved data bindings) */\n component: A2UIComponent;\n /** Rendered children (for container components) */\n children?: ReactNode;\n /** Full data model for the surface (server → client, kept in sync by two-way binding) */\n dataModel?: Record<string, unknown>;\n /** Scope data when inside a template iteration */\n scopeData?: unknown;\n /** Callback to dispatch user actions (client → server) */\n onAction?: (name: string, context: Record<string, unknown>) => void;\n /**\n * Write a value to the local data model at the given JSON Pointer path.\n * This is the \"Write\" half of A2UI two-way binding — input components\n * call this on every user interaction (keystroke, toggle, etc.).\n * The update is LOCAL only; it does NOT send a message to the server.\n * The updated data model reaches the server when an action is dispatched\n * (either via resolved data bindings in the action context, or via\n * the sendDataModel metadata mechanism).\n */\n onDataChange?: (path: string, value: unknown) => void;\n /**\n * Execute a function call definition.\n * This is for LocalAction handling (client-side logic).\n */\n onFunctionCall?: (call: FunctionCall) => void;\n}\n\n/**\n * A React component that can render an A2UX component.\n */\nexport type FreesailComponent = ComponentType<FreesailComponentProps>;\n\n/**\n * Component map within a catalog.\n */\nexport type ComponentMap = Map<string, FreesailComponent>;\n\n/**\n * Registry of all catalogs and their components.\n */\nclass ComponentRegistry {\n private catalogs: Map<CatalogId, ComponentMap> = new Map();\n private functions: Map<CatalogId, Record<string, FunctionImplementation>> = new Map();\n private fallbackComponent: FreesailComponent | null = null;\n\n /**\n * Register a catalog with its components and functions.\n */\n registerCatalog(\n catalogId: CatalogId,\n components: Record<string, FreesailComponent>,\n functions?: Record<string, FunctionImplementation>\n ): void {\n const map: ComponentMap = new Map(Object.entries(components));\n this.catalogs.set(catalogId, map);\n if (functions) {\n this.functions.set(catalogId, functions);\n }\n }\n\n /**\n * Register a single component in a catalog.\n */\n registerComponent(\n catalogId: CatalogId,\n componentName: string,\n component: FreesailComponent\n ): void {\n if (!this.catalogs.has(catalogId)) {\n this.catalogs.set(catalogId, new Map());\n }\n this.catalogs.get(catalogId)!.set(componentName, component);\n }\n\n /**\n * Get a component from a catalog.\n */\n getComponent(catalogId: CatalogId, componentName: string): FreesailComponent | null {\n const catalog = this.catalogs.get(catalogId);\n if (!catalog) {\n console.warn(`Catalog not found: ${catalogId}`);\n return this.fallbackComponent;\n }\n\n const component = catalog.get(componentName);\n if (!component) {\n console.warn(`Component not found: ${componentName} in catalog ${catalogId}`);\n return this.fallbackComponent;\n }\n\n return component;\n }\n\n /**\n * Get a function from a catalog.\n */\n getFunction(catalogId: CatalogId, functionName: string): FunctionImplementation | null {\n const catalogFunctions = this.functions.get(catalogId);\n if (!catalogFunctions) {\n return null;\n }\n // Direct lookup first\n if (catalogFunctions[functionName] != null) {\n return catalogFunctions[functionName];\n }\n // Fallback: try snake_case -> camelCase conversion (e.g. open_url -> openUrl)\n if (functionName.includes('_')) {\n const camelName = functionName.replace(/_([a-z])/g, (_match, p1) => p1.toUpperCase());\n return catalogFunctions[camelName] ?? null;\n }\n return null;\n }\n\n /**\n * Check if a catalog is registered.\n */\n hasCatalog(catalogId: CatalogId): boolean {\n return this.catalogs.has(catalogId);\n }\n\n /**\n * Get all registered catalog IDs.\n */\n getCatalogIds(): CatalogId[] {\n return Array.from(this.catalogs.keys());\n }\n\n /**\n * Set a fallback component for unknown components.\n */\n setFallbackComponent(component: FreesailComponent): void {\n this.fallbackComponent = component;\n }\n\n /**\n * Clear all registrations.\n */\n clear(): void {\n this.catalogs.clear();\n this.functions.clear();\n this.fallbackComponent = null;\n }\n}\n\n/**\n * Global component registry instance.\n */\nexport const registry = new ComponentRegistry();\n\n/**\n * Higher-order function to create a component with catalog binding.\n * This ensures the component is registered when imported.\n */\nexport function withCatalog<P extends FreesailComponentProps>(\n catalogId: CatalogId,\n componentName: string,\n Component: ComponentType<P>\n): ComponentType<P> {\n registry.registerComponent(catalogId, componentName, Component as FreesailComponent);\n return Component;\n}\n\n/**\n * Register multiple components for a catalog at once.\n */\nexport function registerCatalog(\n catalogId: CatalogId,\n components: Record<string, FreesailComponent>,\n functions?: Record<string, FunctionImplementation>\n): void {\n registry.registerCatalog(catalogId, components, functions);\n}\n"]} |
| import React from 'react'; | ||
| export type FreesailThemeMode = 'light' | 'dark'; | ||
| export interface FreesailThemeTokens { | ||
| bgRoot: string; | ||
| bgSurface: string; | ||
| bgMuted: string; | ||
| textMain: string; | ||
| textMuted: string; | ||
| primary: string; | ||
| primaryHover: string; | ||
| primaryText: string; | ||
| border: string; | ||
| radiusSm: string; | ||
| radiusMd: string; | ||
| radiusLg: string; | ||
| shadowSm: string; | ||
| shadowMd: string; | ||
| } | ||
| export interface FreesailTheme { | ||
| mode: FreesailThemeMode; | ||
| tokens: FreesailThemeTokens; | ||
| } | ||
| export declare const defaultLightTheme: FreesailThemeTokens; | ||
| export declare const defaultDarkTheme: FreesailThemeTokens; | ||
| export declare const useFreesailTheme: () => FreesailTheme; | ||
| export interface ThemeProviderProps { | ||
| theme?: FreesailThemeMode | Partial<FreesailThemeTokens>; | ||
| children: React.ReactNode; | ||
| } | ||
| export declare function FreesailThemeProvider({ theme, children }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element; | ||
| //# sourceMappingURL=theme.d.ts.map |
| {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwD,MAAM,OAAO,CAAC;AAE7E,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED,eAAO,MAAM,iBAAiB,EAAE,mBAe/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,mBAe9B,CAAC;AAOF,eAAO,MAAM,gBAAgB,qBAAiC,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,qBAAqB,CAAC,EAAE,KAAe,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAyCtF"} |
| import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; | ||
| import { createContext, useContext, useMemo } from 'react'; | ||
| export const defaultLightTheme = { | ||
| bgRoot: '#f8fafc', | ||
| bgSurface: '#ffffff', | ||
| bgMuted: '#f1f5f9', | ||
| textMain: '#0f172a', | ||
| textMuted: '#64748b', | ||
| primary: '#2563eb', | ||
| primaryHover: '#1d4ed8', | ||
| primaryText: '#ffffff', | ||
| border: '#cbd5e1', | ||
| radiusSm: '0.25rem', | ||
| radiusMd: '0.5rem', | ||
| radiusLg: '0.75rem', | ||
| shadowSm: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)', | ||
| shadowMd: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', | ||
| }; | ||
| export const defaultDarkTheme = { | ||
| bgRoot: '#020617', | ||
| bgSurface: '#0f172a', | ||
| bgMuted: '#1e293b', | ||
| textMain: '#f8fafc', | ||
| textMuted: '#94a3b8', | ||
| primary: '#3b82f6', | ||
| primaryHover: '#2563eb', | ||
| primaryText: '#ffffff', | ||
| border: '#334155', | ||
| radiusSm: '0.25rem', | ||
| radiusMd: '0.5rem', | ||
| radiusLg: '0.75rem', | ||
| shadowSm: '0 1px 2px 0 rgb(0 0 0 / 0.05)', | ||
| shadowMd: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', | ||
| }; | ||
| const ThemeContext = createContext({ | ||
| mode: 'light', | ||
| tokens: defaultLightTheme, | ||
| }); | ||
| export const useFreesailTheme = () => useContext(ThemeContext); | ||
| export function FreesailThemeProvider({ theme = 'light', children }) { | ||
| const currentTheme = useMemo(() => { | ||
| if (theme === 'dark') { | ||
| return { mode: 'dark', tokens: defaultDarkTheme }; | ||
| } | ||
| if (theme === 'light') { | ||
| return { mode: 'light', tokens: defaultLightTheme }; | ||
| } | ||
| // Custom partial theme | ||
| return { | ||
| mode: 'light', // Custom themes default to light baseline unless specified otherwise | ||
| tokens: { ...defaultLightTheme, ...theme }, | ||
| }; | ||
| }, [theme]); | ||
| // Inject CSS variables into the body or a wrapper | ||
| const styleString = ` | ||
| :root { | ||
| --freesail-bg-root: ${currentTheme.tokens.bgRoot}; | ||
| --freesail-bg-surface: ${currentTheme.tokens.bgSurface}; | ||
| --freesail-bg-muted: ${currentTheme.tokens.bgMuted}; | ||
| --freesail-text-main: ${currentTheme.tokens.textMain}; | ||
| --freesail-text-muted: ${currentTheme.tokens.textMuted}; | ||
| --freesail-primary: ${currentTheme.tokens.primary}; | ||
| --freesail-primary-hover: ${currentTheme.tokens.primaryHover}; | ||
| --freesail-primary-text: ${currentTheme.tokens.primaryText}; | ||
| --freesail-border: ${currentTheme.tokens.border}; | ||
| --freesail-radius-sm: ${currentTheme.tokens.radiusSm}; | ||
| --freesail-radius-md: ${currentTheme.tokens.radiusMd}; | ||
| --freesail-radius-lg: ${currentTheme.tokens.radiusLg}; | ||
| --freesail-shadow-sm: ${currentTheme.tokens.shadowSm}; | ||
| --freesail-shadow-md: ${currentTheme.tokens.shadowMd}; | ||
| } | ||
| `.trim(); | ||
| return (_jsxs(ThemeContext.Provider, { value: currentTheme, children: [_jsx("style", { children: styleString }), children] })); | ||
| } | ||
| //# sourceMappingURL=theme.js.map |
| {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { createContext, useContext, useEffect, useMemo } from 'react';\n\nexport type FreesailThemeMode = 'light' | 'dark';\n\nexport interface FreesailThemeTokens {\n bgRoot: string;\n bgSurface: string;\n bgMuted: string;\n textMain: string;\n textMuted: string;\n primary: string;\n primaryHover: string;\n primaryText: string;\n border: string;\n radiusSm: string;\n radiusMd: string;\n radiusLg: string;\n shadowSm: string;\n shadowMd: string;\n}\n\nexport interface FreesailTheme {\n mode: FreesailThemeMode;\n tokens: FreesailThemeTokens;\n}\n\nexport const defaultLightTheme: FreesailThemeTokens = {\n bgRoot: '#f8fafc',\n bgSurface: '#ffffff',\n bgMuted: '#f1f5f9',\n textMain: '#0f172a',\n textMuted: '#64748b',\n primary: '#2563eb',\n primaryHover: '#1d4ed8',\n primaryText: '#ffffff',\n border: '#cbd5e1',\n radiusSm: '0.25rem',\n radiusMd: '0.5rem',\n radiusLg: '0.75rem',\n shadowSm: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',\n shadowMd: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n};\n\nexport const defaultDarkTheme: FreesailThemeTokens = {\n bgRoot: '#020617',\n bgSurface: '#0f172a',\n bgMuted: '#1e293b',\n textMain: '#f8fafc',\n textMuted: '#94a3b8',\n primary: '#3b82f6',\n primaryHover: '#2563eb',\n primaryText: '#ffffff',\n border: '#334155',\n radiusSm: '0.25rem',\n radiusMd: '0.5rem',\n radiusLg: '0.75rem',\n shadowSm: '0 1px 2px 0 rgb(0 0 0 / 0.05)',\n shadowMd: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n};\n\nconst ThemeContext = createContext<FreesailTheme>({\n mode: 'light',\n tokens: defaultLightTheme,\n});\n\nexport const useFreesailTheme = () => useContext(ThemeContext);\n\nexport interface ThemeProviderProps {\n theme?: FreesailThemeMode | Partial<FreesailThemeTokens>;\n children: React.ReactNode;\n}\n\nexport function FreesailThemeProvider({ theme = 'light', children }: ThemeProviderProps) {\n const currentTheme = useMemo<FreesailTheme>(() => {\n if (theme === 'dark') {\n return { mode: 'dark', tokens: defaultDarkTheme };\n }\n if (theme === 'light') {\n return { mode: 'light', tokens: defaultLightTheme };\n }\n // Custom partial theme\n return {\n mode: 'light', // Custom themes default to light baseline unless specified otherwise\n tokens: { ...defaultLightTheme, ...theme },\n };\n }, [theme]);\n\n // Inject CSS variables into the body or a wrapper\n const styleString = `\n :root {\n --freesail-bg-root: ${currentTheme.tokens.bgRoot};\n --freesail-bg-surface: ${currentTheme.tokens.bgSurface};\n --freesail-bg-muted: ${currentTheme.tokens.bgMuted};\n --freesail-text-main: ${currentTheme.tokens.textMain};\n --freesail-text-muted: ${currentTheme.tokens.textMuted};\n --freesail-primary: ${currentTheme.tokens.primary};\n --freesail-primary-hover: ${currentTheme.tokens.primaryHover};\n --freesail-primary-text: ${currentTheme.tokens.primaryText};\n --freesail-border: ${currentTheme.tokens.border};\n --freesail-radius-sm: ${currentTheme.tokens.radiusSm};\n --freesail-radius-md: ${currentTheme.tokens.radiusMd};\n --freesail-radius-lg: ${currentTheme.tokens.radiusLg};\n --freesail-shadow-sm: ${currentTheme.tokens.shadowSm};\n --freesail-shadow-md: ${currentTheme.tokens.shadowMd};\n }\n `.trim();\n\n return (\n <ThemeContext.Provider value={currentTheme}>\n <style>{styleString}</style>\n {children}\n </ThemeContext.Provider>\n );\n}\n"]} |
| /** | ||
| * @fileoverview Freesail React - Type Definitions | ||
| * | ||
| * Public interfaces for custom catalog integration. | ||
| */ | ||
| import type { ComponentType } from 'react'; | ||
| import type { FreesailComponentProps } from './registry.js'; | ||
| /** | ||
| * Definition of a custom catalog that can be registered with Freesail. | ||
| * | ||
| * Developers create a CatalogDefinition to bundle their JSON schema | ||
| * and React component implementations together, then pass them to | ||
| * FreesailProvider for registration. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import catalog from './catalog.json'; | ||
| * import MyCustomCard from './components/MyCustomCard'; | ||
| * | ||
| * export const MyOwnCatalog: CatalogDefinition = { | ||
| * namespace: 'myown', | ||
| * schema: catalog, | ||
| * components: { | ||
| * 'MyCustomCard': MyCustomCard, | ||
| * }, | ||
| * }; | ||
| * ``` | ||
| */ | ||
| export interface CatalogDefinition { | ||
| /** Unique namespace for the catalog (e.g., 'myown' or a full URI) */ | ||
| namespace: string; | ||
| /** The JSON schema object (catalog.json content) describing available components */ | ||
| schema: any; | ||
| /** Map of component names to React components implementing FreesailComponentProps */ | ||
| components: Record<string, ComponentType<FreesailComponentProps>>; | ||
| /** Map of function names to their implementations */ | ||
| functions?: Record<string, FunctionImplementation>; | ||
| } | ||
| /** | ||
| * A function implementation that can be called from the data model. | ||
| */ | ||
| export type FunctionImplementation = (...args: any[]) => any; | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,MAAM,EAAE,GAAG,CAAC;IACZ,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAClE,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC"} |
| /** | ||
| * @fileoverview Freesail React - Type Definitions | ||
| * | ||
| * Public interfaces for custom catalog integration. | ||
| */ | ||
| export {}; | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/**\n * @fileoverview Freesail React - Type Definitions\n *\n * Public interfaces for custom catalog integration.\n */\n\nimport type { ComponentType } from 'react';\nimport type { FreesailComponentProps } from './registry.js';\n\n/**\n * Definition of a custom catalog that can be registered with Freesail.\n *\n * Developers create a CatalogDefinition to bundle their JSON schema\n * and React component implementations together, then pass them to\n * FreesailProvider for registration.\n *\n * @example\n * ```ts\n * import catalog from './catalog.json';\n * import MyCustomCard from './components/MyCustomCard';\n *\n * export const MyOwnCatalog: CatalogDefinition = {\n * namespace: 'myown',\n * schema: catalog,\n * components: {\n * 'MyCustomCard': MyCustomCard,\n * },\n * };\n * ```\n */\nexport interface CatalogDefinition {\n /** Unique namespace for the catalog (e.g., 'myown' or a full URI) */\n namespace: string;\n /** The JSON schema object (catalog.json content) describing available components */\n schema: any;\n /** Map of component names to React components implementing FreesailComponentProps */\n components: Record<string, ComponentType<FreesailComponentProps>>;\n /** Map of function names to their implementations */\n functions?: Record<string, FunctionImplementation>;\n}\n\n/**\n * A function implementation that can be called from the data model.\n */\nexport type FunctionImplementation = (...args: any[]) => any;\n"]} |
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
2
-33.33%1
-66.67%2133
-99.13%2
-94.74%0
-100%2
Infinity%Updated