1 line
9.4 KiB
Plaintext
1 line
9.4 KiB
Plaintext
{"version":3,"file":"useA2UIComponent.cjs","names":["useA2UIActions","useTheme"],"sources":["../../../src/react-renderer/hooks/useA2UIComponent.ts"],"sourcesContent":["import { useCallback, useId, useMemo } from \"react\";\nimport type { Types, Primitives } from \"@a2ui/lit/0.8\";\nimport { useA2UIActions, useA2UIState } from \"../core/A2UIProvider\";\nimport { useTheme } from \"../theme/ThemeContext\";\n\n/**\n * Result returned by the useA2UIComponent hook.\n */\nexport interface UseA2UIComponentResult {\n /** The current theme */\n theme: Types.Theme;\n\n /** Resolve a StringValue to its actual string value */\n resolveString: (\n value: Primitives.StringValue | null | undefined,\n ) => string | null;\n\n /** Resolve a NumberValue to its actual number value */\n resolveNumber: (\n value: Primitives.NumberValue | null | undefined,\n ) => number | null;\n\n /** Resolve a BooleanValue to its actual boolean value */\n resolveBoolean: (\n value: Primitives.BooleanValue | null | undefined,\n ) => boolean | null;\n\n /** Set a value in the data model (for two-way binding) */\n setValue: (path: string, value: Types.DataValue) => void;\n\n /** Get a value from the data model */\n getValue: (path: string) => Types.DataValue | null;\n\n /** Dispatch a user action */\n sendAction: (action: Types.Action) => void;\n\n /** Generate a unique ID for accessibility */\n getUniqueId: (prefix: string) => string;\n}\n\n/**\n * Base hook for A2UI components. Provides data binding, theme access,\n * and action dispatching.\n *\n * @param node - The component node from the A2UI message processor\n * @param surfaceId - The surface ID this component belongs to\n * @returns Object with theme, data binding helpers, and action dispatcher\n *\n * @example\n * ```tsx\n * function TextField({ node, surfaceId }: A2UIComponentProps<Types.TextFieldNode>) {\n * const { theme, resolveString, setValue } = useA2UIComponent(node, surfaceId);\n *\n * const label = resolveString(node.properties.label);\n * const value = resolveString(node.properties.text) ?? '';\n *\n * return (\n * <div className={classMapToString(theme.components.TextField.container)}>\n * <label>{label}</label>\n * <input\n * value={value}\n * onChange={(e) => setValue(node.properties.text?.path!, e.target.value)}\n * />\n * </div>\n * );\n * }\n * ```\n */\nexport function useA2UIComponent<T extends Types.AnyComponentNode>(\n node: T,\n surfaceId: string,\n): UseA2UIComponentResult {\n // Use stable actions - won't cause re-renders when version changes\n const actions = useA2UIActions();\n const theme = useTheme();\n const baseId = useId();\n\n // Subscribe to data model version - triggers re-render when data changes via setData.\n // This ensures components with path bindings see updated values.\n // memo() doesn't block context-triggered re-renders.\n useA2UIState();\n\n /**\n * Resolve a StringValue to its actual string value.\n * Checks literalString, literal, then path in that order.\n * Note: This reads from data model via stable actions reference.\n */\n const resolveString = useCallback(\n (value: Primitives.StringValue | null | undefined): string | null => {\n if (!value) return null;\n if (typeof value !== \"object\") return null;\n\n if (value.literalString !== undefined) {\n return value.literalString;\n }\n if (value.literal !== undefined) {\n return String(value.literal);\n }\n if (value.path) {\n const data = actions.getData(node, value.path, surfaceId);\n return data !== null ? String(data) : null;\n }\n return null;\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Resolve a NumberValue to its actual number value.\n */\n const resolveNumber = useCallback(\n (value: Primitives.NumberValue | null | undefined): number | null => {\n if (!value) return null;\n if (typeof value !== \"object\") return null;\n\n if (value.literalNumber !== undefined) {\n return value.literalNumber;\n }\n if (value.literal !== undefined) {\n return Number(value.literal);\n }\n if (value.path) {\n const data = actions.getData(node, value.path, surfaceId);\n return data !== null ? Number(data) : null;\n }\n return null;\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Resolve a BooleanValue to its actual boolean value.\n */\n const resolveBoolean = useCallback(\n (value: Primitives.BooleanValue | null | undefined): boolean | null => {\n if (!value) return null;\n if (typeof value !== \"object\") return null;\n\n if (value.literalBoolean !== undefined) {\n return value.literalBoolean;\n }\n if (value.literal !== undefined) {\n return Boolean(value.literal);\n }\n if (value.path) {\n const data = actions.getData(node, value.path, surfaceId);\n return data !== null ? Boolean(data) : null;\n }\n return null;\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Set a value in the data model for two-way binding.\n */\n const setValue = useCallback(\n (path: string, value: Types.DataValue) => {\n actions.setData(node, path, value, surfaceId);\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Get a value from the data model.\n */\n const getValue = useCallback(\n (path: string): Types.DataValue | null => {\n return actions.getData(node, path, surfaceId);\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Dispatch a user action to the server.\n * Resolves all context bindings before dispatching.\n */\n const sendAction = useCallback(\n (action: Types.Action) => {\n const actionContext: Record<string, unknown> = {};\n\n if (action.context) {\n for (const item of action.context) {\n if (item.value.literalString !== undefined) {\n actionContext[item.key] = item.value.literalString;\n } else if (item.value.literalNumber !== undefined) {\n actionContext[item.key] = item.value.literalNumber;\n } else if (item.value.literalBoolean !== undefined) {\n actionContext[item.key] = item.value.literalBoolean;\n } else if (item.value.path) {\n const resolvedPath = actions.resolvePath(\n item.value.path,\n node.dataContextPath,\n );\n actionContext[item.key] = actions.getData(\n node,\n resolvedPath,\n surfaceId,\n );\n }\n }\n }\n\n actions.dispatch({\n userAction: {\n name: action.name,\n sourceComponentId: node.id,\n surfaceId,\n timestamp: new Date().toISOString(),\n context: actionContext,\n },\n });\n },\n [actions, node, surfaceId],\n );\n\n /**\n * Generate a unique ID for accessibility purposes.\n * Uses React's useId() for SSR and Concurrent Mode compatibility.\n */\n const getUniqueId = useCallback(\n (prefix: string) => {\n return `${prefix}${baseId}`;\n },\n [baseId],\n );\n\n return useMemo(\n () => ({\n theme,\n resolveString,\n resolveNumber,\n resolveBoolean,\n setValue,\n getValue,\n sendAction,\n getUniqueId,\n }),\n [\n theme,\n resolveString,\n resolveNumber,\n resolveBoolean,\n setValue,\n getValue,\n sendAction,\n getUniqueId,\n ],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,SAAgB,iBACd,MACA,WACwB;CAExB,MAAM,UAAUA,qCAAgB;CAChC,MAAM,QAAQC,+BAAU;CACxB,MAAM,2BAAgB;AAKtB,oCAAc;;;;;;CAOd,MAAM,wCACH,UAAoE;AACnE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,MAAI,MAAM,kBAAkB,OAC1B,QAAO,MAAM;AAEf,MAAI,MAAM,YAAY,OACpB,QAAO,OAAO,MAAM,QAAQ;AAE9B,MAAI,MAAM,MAAM;GACd,MAAM,OAAO,QAAQ,QAAQ,MAAM,MAAM,MAAM,UAAU;AACzD,UAAO,SAAS,OAAO,OAAO,KAAK,GAAG;;AAExC,SAAO;IAET;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;CAKD,MAAM,wCACH,UAAoE;AACnE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,MAAI,MAAM,kBAAkB,OAC1B,QAAO,MAAM;AAEf,MAAI,MAAM,YAAY,OACpB,QAAO,OAAO,MAAM,QAAQ;AAE9B,MAAI,MAAM,MAAM;GACd,MAAM,OAAO,QAAQ,QAAQ,MAAM,MAAM,MAAM,UAAU;AACzD,UAAO,SAAS,OAAO,OAAO,KAAK,GAAG;;AAExC,SAAO;IAET;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;CAKD,MAAM,yCACH,UAAsE;AACrE,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO;AAEtC,MAAI,MAAM,mBAAmB,OAC3B,QAAO,MAAM;AAEf,MAAI,MAAM,YAAY,OACpB,QAAO,QAAQ,MAAM,QAAQ;AAE/B,MAAI,MAAM,MAAM;GACd,MAAM,OAAO,QAAQ,QAAQ,MAAM,MAAM,MAAM,UAAU;AACzD,UAAO,SAAS,OAAO,QAAQ,KAAK,GAAG;;AAEzC,SAAO;IAET;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;CAKD,MAAM,mCACH,MAAc,UAA2B;AACxC,UAAQ,QAAQ,MAAM,MAAM,OAAO,UAAU;IAE/C;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;CAKD,MAAM,mCACH,SAAyC;AACxC,SAAO,QAAQ,QAAQ,MAAM,MAAM,UAAU;IAE/C;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;;CAMD,MAAM,qCACH,WAAyB;EACxB,MAAM,gBAAyC,EAAE;AAEjD,MAAI,OAAO,SACT;QAAK,MAAM,QAAQ,OAAO,QACxB,KAAI,KAAK,MAAM,kBAAkB,OAC/B,eAAc,KAAK,OAAO,KAAK,MAAM;YAC5B,KAAK,MAAM,kBAAkB,OACtC,eAAc,KAAK,OAAO,KAAK,MAAM;YAC5B,KAAK,MAAM,mBAAmB,OACvC,eAAc,KAAK,OAAO,KAAK,MAAM;YAC5B,KAAK,MAAM,MAAM;IAC1B,MAAM,eAAe,QAAQ,YAC3B,KAAK,MAAM,MACX,KAAK,gBACN;AACD,kBAAc,KAAK,OAAO,QAAQ,QAChC,MACA,cACA,UACD;;;AAKP,UAAQ,SAAS,EACf,YAAY;GACV,MAAM,OAAO;GACb,mBAAmB,KAAK;GACxB;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,SAAS;GACV,EACF,CAAC;IAEJ;EAAC;EAAS;EAAM;EAAU,CAC3B;;;;;CAMD,MAAM,sCACH,WAAmB;AAClB,SAAO,GAAG,SAAS;IAErB,CAAC,OAAO,CACT;AAED,kCACS;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"} |