@gigabuddy/gadgets 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/react.js +12 -4
  3. package/react.js.map +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gigabuddy/gadgets",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Gigabuddy Gadgets SDK — render interactive gadgets with breakout, state, and hot-swap",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/react.js CHANGED
@@ -901,7 +901,10 @@ function GadgetFrame({
901
901
  return;
902
902
  const cached = getCachedFileUrl(fileId);
903
903
  if (cached) {
904
- iframeRef.current?.contentWindow?.postMessage({ type: "gadget-file-url-response", requestId, url: cached }, "*");
904
+ iframeRef.current?.contentWindow?.postMessage(
905
+ { type: "gadget-file-url-response", requestId, url: cached },
906
+ "*"
907
+ );
905
908
  return;
906
909
  }
907
910
  void (async () => {
@@ -1010,7 +1013,11 @@ function GadgetFrame({
1010
1013
  );
1011
1014
  } catch (err) {
1012
1015
  iframeRef.current?.contentWindow?.postMessage(
1013
- { type: "gadget-context-response", id: requestId, error: err instanceof Error ? err.message : "Context request failed" },
1016
+ {
1017
+ type: "gadget-context-response",
1018
+ id: requestId,
1019
+ error: err instanceof Error ? err.message : "Context request failed"
1020
+ },
1014
1021
  "*"
1015
1022
  );
1016
1023
  }
@@ -1080,7 +1087,7 @@ function GadgetFrame({
1080
1087
  maxHeight: "none",
1081
1088
  margin: 0,
1082
1089
  transform: "none",
1083
- pointerEvents: "none",
1090
+ pointerEvents: breakoutRevealed ? "auto" : "none",
1084
1091
  overflow: "visible",
1085
1092
  visibility: breakoutRevealed ? "visible" : "hidden"
1086
1093
  } : {
@@ -1102,7 +1109,8 @@ function GadgetFrame({
1102
1109
  srcDoc: html,
1103
1110
  style: isCompact ? compactStyle : fullStyle,
1104
1111
  scrolling: isCompact && !breakoutActive && !isCapped ? "no" : void 0,
1105
- sandbox: "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",
1112
+ sandbox: "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-downloads allow-forms allow-modals",
1113
+ allow: "clipboard-write; fullscreen; autoplay",
1106
1114
  title: "Gadget",
1107
1115
  onLoad: () => setIframeLoaded(true)
1108
1116
  }
package/react.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../libs/gadgets/src/lib/react/GadgetContext.tsx", "../../../libs/gadgets/src/lib/react/GadgetFrame.tsx", "../../../libs/gadgets/src/lib/createGadgetRenderer.ts"],
4
- "sourcesContent": ["import { createContext, useContext, useMemo, type ReactNode } from 'react';\n\nexport interface GadgetConfig {\n /** Base API URL (e.g. \"https://api.gigabuddy.com\") */\n apiUrl: string;\n /** Organization ID */\n orgId: string;\n /** Project ID */\n projectId: string;\n /** Returns a fresh auth token */\n getToken: () => Promise<string>;\n /** Optional SSE stream base URL (falls back to apiUrl) */\n streamBaseUrl?: string;\n}\n\ninterface GadgetContextValue {\n config: GadgetConfig;\n /** Resolves a file ID to a fresh signed URL */\n resolveFileUrl: (fileId: string) => Promise<string>;\n}\n\nconst GadgetCtx = createContext<GadgetContextValue | null>(null);\n\nexport function GadgetProvider({ config, children }: { config: GadgetConfig; children: ReactNode }) {\n const value = useMemo<GadgetContextValue>(() => {\n const base = `${config.apiUrl}/${config.orgId}/${config.projectId}`;\n\n return {\n config,\n resolveFileUrl: async (fileId: string) => {\n const token = await config.getToken();\n const res = await fetch(`${base}/context/get-file-url`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ fileId }),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as { url: string };\n return data.url;\n },\n };\n }, [config.apiUrl, config.orgId, config.projectId, config.getToken, config.streamBaseUrl]);\n\n return <GadgetCtx.Provider value={value}>{children}</GadgetCtx.Provider>;\n}\n\nexport function useGadgetConfig(): GadgetContextValue {\n const ctx = useContext(GadgetCtx);\n if (!ctx) throw new Error('GadgetFrame must be wrapped in a <GadgetProvider>');\n return ctx;\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { createGadgetRenderer } from '../createGadgetRenderer.js';\nimport { useGadgetConfig } from './GadgetContext.js';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface GadgetFrameProps {\n /** The gadget entity ID to load */\n gadgetId: string;\n /** Data props to pass to the gadget */\n props?: Record<string, unknown>;\n /** Display mode \u2014 compact (inline, resizable) or full (fills container) */\n mode?: 'compact' | 'full';\n /** Whether breakout is enabled (default: true in compact mode) */\n breakout?: boolean;\n /** Max height in compact mode before scrolling (default: 300) */\n maxHeight?: number;\n /** Deployment ID for mission-backed gadgets (auto-generated if not provided) */\n deploymentId?: string;\n /** Conversation ID \u2014 used when updating message content after action */\n conversationId?: string;\n /** Message ID \u2014 used when updating message content after action */\n messageId?: string;\n /** Additional className for the wrapper div */\n className?: string;\n /** Called when breakout state changes */\n onBreakoutChange?: (active: boolean) => void;\n /** Called on load error */\n onError?: (error: string) => void;\n /** Whether to lazy-load (only render when near viewport). Default: true in compact mode. */\n lazy?: boolean;\n}\n\ninterface GadgetEntity {\n data: {\n type: string;\n componentCode: string;\n actionRef?: { type: string; id: string };\n missionRef?: { type: string; id: string };\n stateBindings?: {\n shared?: { contextFields: string[] };\n user?: { contextFields: string[] };\n };\n assets?: Record<string, { fileId: string; url: string; name: string; contentType: string }>;\n contextBinding?: { contextTypes?: string[] };\n contextEnabled?: boolean;\n contextTypes?: string[];\n };\n}\n\n// =============================================================================\n// Entity cache \u2014 survives across mounts/navigations, keyed by gadgetId\n// =============================================================================\n\n/** Entity cache \u2014 stale-while-revalidate. Serve cached instantly, refresh in background. */\nconst entityCache = new Map<string, { entity: GadgetEntity; fetchedAt: number }>();\nconst ENTITY_STALE_MS = 5 * 60 * 1000; // revalidate after 5 min\n\n/** File URL cache \u2014 signed URLs with TTL (default 50 min, signed URLs typically last 60 min) */\nconst fileUrlCache = new Map<string, { url: string; expiresAt: number }>();\nconst FILE_URL_TTL_MS = 50 * 60 * 1000;\n\nfunction getCachedFileUrl(fileId: string): string | null {\n const entry = fileUrlCache.get(fileId);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n fileUrlCache.delete(fileId);\n return null;\n }\n return entry.url;\n}\n\nfunction setCachedFileUrl(fileId: string, url: string): void {\n fileUrlCache.set(fileId, { url, expiresAt: Date.now() + FILE_URL_TTL_MS });\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function GadgetFrame({\n gadgetId,\n props,\n mode = 'compact',\n breakout: breakoutEnabled = true,\n maxHeight = 300,\n deploymentId: externalDeploymentId,\n conversationId,\n messageId,\n className,\n onBreakoutChange,\n onError,\n lazy,\n}: GadgetFrameProps) {\n const { config, resolveFileUrl } = useGadgetConfig();\n const base = `${config.apiUrl}/${config.orgId}/${config.projectId}`;\n\n // \u2500\u2500 State (all hooks must be called unconditionally \u2014 no early returns before hooks) \u2500\u2500\n const lazyEnabled = lazy ?? mode === 'compact';\n const [visible, setVisible] = useState(!lazyEnabled);\n const [html, setHtml] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [naturalHeight, setNaturalHeight] = useState(60);\n const [iframeLoaded, setIframeLoaded] = useState(false);\n const [breakoutActive, setBreakoutActive] = useState(false);\n const [breakoutRevealed, setBreakoutRevealed] = useState(false);\n\n // \u2500\u2500 Refs \u2500\u2500\n const sentinelRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const entityRef = useRef<GadgetEntity | null>(null);\n const initialPropsRef = useRef(props);\n const deploymentIdRef = useRef<string | null>(externalDeploymentId ?? null);\n const sseRef = useRef<EventSource | null>(null);\n const userIdRef = useRef<string | null>(null);\n const latestStateRef = useRef<{ shared: Record<string, unknown>; user: Record<string, unknown> } | null>(null);\n const placeholderRef = useRef<HTMLDivElement | null>(null);\n const ancestorOverridesRef = useRef<{ el: HTMLElement; key: string; original: string }[]>([]);\n const breakoutActiveRef = useRef(false);\n breakoutActiveRef.current = breakoutActive;\n\n // \u2500\u2500 Derived \u2500\u2500\n const isCompact = mode === 'compact';\n const isCapped = isCompact && naturalHeight > maxHeight;\n const iframeHeight = isCapped ? maxHeight : naturalHeight;\n\n // \u2500\u2500 Lazy loading: defer everything until the gadget is near the viewport \u2500\u2500\n useEffect(() => {\n if (!lazyEnabled || visible) return;\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setVisible(true);\n observer.disconnect();\n }\n },\n { rootMargin: '200px' }, // start loading 200px before entering viewport\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [lazyEnabled, visible]);\n\n // \u2500\u2500 Fetch entity (stale-while-revalidate) + build HTML + deploy \u2500\u2500\n useEffect(() => {\n if (!visible) return;\n let cancelled = false;\n\n async function fetchEntityFromServer(token: string): Promise<GadgetEntity> {\n const res = await fetch(`${base}/chat/get-gadget`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId }),\n });\n if (!res.ok) throw new Error(`Failed to load gadget: ${res.status}`);\n const entity = (await res.json()) as GadgetEntity;\n entityCache.set(gadgetId, { entity, fetchedAt: Date.now() });\n return entity;\n }\n\n function buildHtml(entity: GadgetEntity): string {\n const hasMission = entity.data.missionRef?.id != null;\n const hasContext =\n entity.data.contextEnabled === true ||\n (entity.data.contextBinding?.contextTypes?.length ?? 0) > 0 ||\n (entity.data.contextTypes?.length ?? 0) > 0;\n const assetMap = entity.data.assets\n ? Object.fromEntries(Object.entries(entity.data.assets).map(([k, v]) => [k, { url: v.url, name: v.name }]))\n : undefined;\n return createGadgetRenderer(entity.data.componentCode, initialPropsRef.current ?? {}, {\n viewport: mode,\n stateEnabled: hasMission,\n contextEnabled: hasContext,\n assets: assetMap,\n });\n }\n\n async function deploy(entity: GadgetEntity, token: string) {\n if (!entity.data.missionRef?.id) return;\n\n const depId = externalDeploymentId ?? messageId ?? `gadget_${gadgetId}_${Date.now()}`;\n deploymentIdRef.current = depId;\n\n const deployRes = await fetch(`${base}/gadget-deploy`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId, deploymentId: depId, initialData: initialPropsRef.current, conversationId }),\n });\n if (!deployRes.ok) throw new Error(`Failed to deploy gadget: ${deployRes.status}`);\n\n const deployData = (await deployRes.json()) as {\n deploymentId: string;\n missionInstanceId: string;\n initialState: { shared: Record<string, unknown>; user: Record<string, unknown> };\n userId?: string;\n };\n if (cancelled) return;\n\n if (deployData.userId) userIdRef.current = deployData.userId;\n latestStateRef.current = deployData.initialState;\n\n // Connect SSE\n const streamBase = config.streamBaseUrl ?? config.apiUrl;\n const sseUrl = `${streamBase}/${config.orgId}/${config.projectId}/gadget-state/${depId}/stream?token=${encodeURIComponent(token)}`;\n const sse = new EventSource(sseUrl);\n sseRef.current = sse;\n\n sse.addEventListener('state-update', (event) => {\n if (cancelled) return;\n try {\n const state = JSON.parse(event.data) as {\n shared: Record<string, unknown>;\n user: Record<string, unknown>;\n userId?: string;\n };\n if (state.userId && !userIdRef.current) userIdRef.current = state.userId;\n latestStateRef.current = state;\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-state-update', shared: state.shared, user: state.user, userId: userIdRef.current },\n '*',\n );\n } catch {\n // Ignore malformed SSE\n }\n });\n }\n\n (async () => {\n try {\n const token = await config.getToken();\n const cached = entityCache.get(gadgetId);\n let entity: GadgetEntity;\n\n if (cached) {\n // Serve from cache immediately \u2014 no loading spinner\n entity = cached.entity;\n entityRef.current = entity;\n if (!cancelled) {\n setHtml(buildHtml(entity));\n setLoading(false);\n }\n\n // Revalidate in background if stale\n if (Date.now() - cached.fetchedAt > ENTITY_STALE_MS) {\n fetchEntityFromServer(token).then((fresh) => {\n if (cancelled) return;\n // Only re-render if component code actually changed\n if (fresh.data.componentCode !== cached.entity.data.componentCode) {\n entityRef.current = fresh;\n setHtml(buildHtml(fresh));\n } else {\n entityRef.current = fresh;\n }\n }).catch(() => { /* background revalidation failure is silent */ });\n }\n } else {\n // First load \u2014 fetch from server\n entity = await fetchEntityFromServer(token);\n if (cancelled) return;\n entityRef.current = entity;\n setHtml(buildHtml(entity));\n }\n\n if (cancelled) return;\n await deploy(entity, token);\n } catch (err) {\n if (!cancelled) {\n const msg = err instanceof Error ? err.message : 'Failed to load gadget';\n setError(msg);\n onError?.(msg);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n\n return () => {\n cancelled = true;\n if (sseRef.current) {\n sseRef.current.close();\n sseRef.current = null;\n }\n };\n }, [visible, gadgetId, base, config.getToken, config.streamBaseUrl, config.orgId, config.projectId, mode]);\n\n // \u2500\u2500 Push initial state on iframe load \u2500\u2500\n useEffect(() => {\n if (!iframeLoaded || !latestStateRef.current) return;\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: 'gadget-state-init',\n shared: latestStateRef.current.shared,\n user: latestStateRef.current.user,\n userId: userIdRef.current,\n },\n '*',\n );\n }, [iframeLoaded]);\n\n // \u2500\u2500 Push props changes \u2500\u2500\n useEffect(() => {\n if (!iframeLoaded || !props) return;\n iframeRef.current?.contentWindow?.postMessage({ type: 'gadget-set-data', data: props }, '*');\n }, [props, iframeLoaded]);\n\n // \u2500\u2500 Breakout handler \u2500\u2500\n useEffect(() => {\n if (!visible || !iframeRef.current || !html || !breakoutEnabled) return;\n const iframe = iframeRef.current;\n\n function clearAncestorClipping() {\n let el = iframe.parentElement;\n while (el && el !== document.body && el !== document.documentElement) {\n const cs = getComputedStyle(el);\n const overflow = cs.overflow + cs.overflowX + cs.overflowY;\n const hasClip = /hidden|auto|scroll|clip/.test(overflow);\n const hasContain =\n cs.transform !== 'none' || cs.willChange === 'transform' || cs.contain !== 'none' || cs.filter !== 'none';\n\n if (hasClip || hasContain) {\n if (hasClip) {\n ancestorOverridesRef.current.push({ el, key: 'overflow', original: el.style.overflow });\n ancestorOverridesRef.current.push({ el, key: 'overflowX', original: el.style.overflowX });\n ancestorOverridesRef.current.push({ el, key: 'overflowY', original: el.style.overflowY });\n el.style.overflow = 'visible';\n el.style.overflowX = 'visible';\n el.style.overflowY = 'visible';\n }\n if (hasContain && cs.transform !== 'none') {\n ancestorOverridesRef.current.push({ el, key: 'transform', original: el.style.transform });\n el.style.transform = 'none';\n }\n if (hasContain && cs.contain !== 'none') {\n ancestorOverridesRef.current.push({ el, key: 'contain', original: el.style.contain });\n el.style.contain = 'none';\n }\n }\n el = el.parentElement;\n }\n }\n\n function restoreAncestorClipping() {\n for (const { el, key, original } of ancestorOverridesRef.current) {\n (el.style as unknown as Record<string, string>)[key] = original;\n }\n ancestorOverridesRef.current.length = 0;\n }\n\n function onMessage(event: MessageEvent) {\n if (event.source !== iframe.contentWindow) return;\n const d = event.data;\n if (!d || typeof d !== 'object') return;\n\n if (d.type === 'gadget-request-breakout') {\n const rect = iframe.getBoundingClientRect();\n\n // Placeholder to preserve layout\n const ph = document.createElement('div');\n ph.style.width = `${rect.width}px`;\n ph.style.height = `${rect.height}px`;\n ph.style.flexShrink = '0';\n iframe.parentElement?.insertBefore(ph, iframe);\n placeholderRef.current = ph;\n\n clearAncestorClipping();\n setBreakoutActive(true);\n setBreakoutRevealed(false);\n onBreakoutChange?.(true);\n\n iframe.contentWindow?.postMessage(\n {\n type: 'gadget-breakout-started',\n originalRect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n },\n '*',\n );\n\n // Reveal after repositioning\n requestAnimationFrame(() => requestAnimationFrame(() => setBreakoutRevealed(true)));\n }\n\n if (d.type === 'gadget-exit-breakout') {\n if (placeholderRef.current) {\n placeholderRef.current.remove();\n placeholderRef.current = null;\n }\n restoreAncestorClipping();\n setBreakoutActive(false);\n setBreakoutRevealed(false);\n onBreakoutChange?.(false);\n }\n }\n\n window.addEventListener('message', onMessage);\n return () => {\n window.removeEventListener('message', onMessage);\n if (placeholderRef.current) {\n placeholderRef.current.remove();\n placeholderRef.current = null;\n }\n restoreAncestorClipping();\n setBreakoutActive(false);\n setBreakoutRevealed(false);\n };\n }, [visible, html, breakoutEnabled, onBreakoutChange]);\n\n // \u2500\u2500 Bridge handler (actions, interactions, file URL, resize) \u2500\u2500\n const handleMessage = useCallback(\n async (event: MessageEvent<unknown>) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = event.data as any;\n if (!data || typeof data !== 'object') return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n\n const type = data.type as string;\n\n // Resize (compact only)\n if (type === 'gadget-resize') {\n if (breakoutActiveRef.current || !isCompact) return;\n const h = data.height as number;\n if (h > 0) setNaturalHeight(h);\n return;\n }\n\n // Interaction dispatch\n if (type === 'gadget-interaction' && deploymentIdRef.current) {\n void (async () => {\n try {\n const token = await config.getToken();\n await fetch(`${base}/gadget-interact`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n deploymentId: deploymentIdRef.current,\n action: data.action as string,\n data: (data.data as Record<string, unknown>) ?? {},\n }),\n });\n } catch {\n // Fire-and-forget\n }\n })();\n return;\n }\n\n // File URL resolution (with cache)\n if (type === 'gadget-file-url-request') {\n const requestId = data.requestId as string;\n const fileId = data.fileId as string;\n if (!requestId || !fileId) return;\n\n const cached = getCachedFileUrl(fileId);\n if (cached) {\n iframeRef.current?.contentWindow?.postMessage({ type: 'gadget-file-url-response', requestId, url: cached }, '*');\n return;\n }\n\n void (async () => {\n try {\n const url = await resolveFileUrl(fileId);\n setCachedFileUrl(fileId, url);\n iframeRef.current?.contentWindow?.postMessage({ type: 'gadget-file-url-response', requestId, url }, '*');\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: 'gadget-file-url-response',\n requestId,\n error: err instanceof Error ? err.message : 'Failed to resolve file URL',\n },\n '*',\n );\n }\n })();\n return;\n }\n\n // Action execution\n if (type === 'gadget-action-request') {\n const requestId = data.requestId as string;\n const input = (data.input as Record<string, unknown>) || {};\n const entity = entityRef.current;\n\n if (!entity?.data.actionRef?.id) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: 'No action configured' },\n '*',\n );\n return;\n }\n\n try {\n const token = await config.getToken();\n const res = await fetch(`${base}/chat/execute-gadget`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId, input }),\n });\n\n const result = (await res.json()) as {\n status?: string;\n error?: string;\n errorMessage?: string;\n output?: unknown;\n };\n\n if (!res.ok) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: result.error || `HTTP ${res.status}` },\n '*',\n );\n } else if (result.status === 'failure') {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: result.errorMessage || 'Action failed' },\n '*',\n );\n } else {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, result: result.output },\n '*',\n );\n }\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: err instanceof Error ? err.message : 'Unknown error' },\n '*',\n );\n }\n }\n\n // Context bridge \u2014 proxy context SDK calls to backend API\n if (type === 'gadget-context-request') {\n const requestId = data.id as string;\n const method = data.method as string;\n const params = (data.params as Record<string, unknown>) ?? {};\n\n void (async () => {\n try {\n const token = await config.getToken();\n const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' };\n let result: unknown;\n\n // Map bridge methods to context API endpoints\n const methodEndpointMap: Record<string, string> = {\n listTypes: 'context/list-types',\n getType: 'context/get-type',\n listInstances: 'context/list-instances',\n getInstance: 'context/get-instance',\n createInstance: 'context/create-instance',\n updateInstance: 'context/update-instance',\n deleteInstance: 'context/delete-instance',\n searchKnowledge: 'context/search-knowledge',\n };\n\n // Methods that need id\u2192instanceId remapping\n const idRemapMethods = new Set(['getInstance', 'updateInstance', 'deleteInstance']);\n\n if (method === 'getEnriched' || method === 'getRelated') {\n // Legacy REST endpoints\n const id = params['id'] as string;\n const endpoint = method === 'getEnriched' ? 'enriched' : 'related';\n const res = await fetch(`${base}/context-instances/${id}/${endpoint}`, { headers });\n if (!res.ok) throw new Error(`Context ${method} failed: ${res.status}`);\n result = await res.json();\n } else if (methodEndpointMap[method]) {\n // Remap { id } \u2192 { instanceId } where needed\n const body = idRemapMethods.has(method) && params['id']\n ? { ...params, instanceId: params['id'], id: undefined }\n : params;\n const res = await fetch(`${base}/${methodEndpointMap[method]}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`Context ${method} failed: ${res.status}`);\n result = await res.json();\n } else {\n throw new Error(`Unknown context method: ${method}`);\n }\n\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-context-response', id: requestId, result },\n '*',\n );\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-context-response', id: requestId, error: err instanceof Error ? err.message : 'Context request failed' },\n '*',\n );\n }\n })();\n return;\n }\n },\n [base, config.getToken, resolveFileUrl, gadgetId, isCompact],\n );\n\n useEffect(() => {\n if (!visible) return;\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [visible, handleMessage]);\n\n // \u2500\u2500 Skeleton placeholder (shared by lazy + loading states) \u2500\u2500\n const skeleton = (\n <div\n ref={!visible ? sentinelRef : undefined}\n className={className}\n style={{\n width: '100%',\n height: maxHeight,\n minHeight: 60,\n borderRadius: 8,\n background: 'linear-gradient(90deg, rgba(128,128,128,0.06) 25%, rgba(128,128,128,0.12) 50%, rgba(128,128,128,0.06) 75%)',\n backgroundSize: '200% 100%',\n animation: 'gadget-skeleton 1.5s ease-in-out infinite',\n }}\n >\n <style>{`@keyframes gadget-skeleton { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }`}</style>\n </div>\n );\n\n if (!visible) return skeleton;\n\n // \u2500\u2500 Render \u2500\u2500\n\n if (error) {\n return (\n <div\n className={className}\n style={{\n padding: '8px 12px',\n fontSize: 12,\n color: '#b91c1c',\n background: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: 8,\n }}\n >\n {error}\n </div>\n );\n }\n\n if (loading) return skeleton;\n\n if (!html) return null;\n\n const compactStyle = breakoutActive\n ? {\n position: 'fixed' as const,\n top: 0,\n left: 0,\n width: '100vw',\n height: '100vh',\n zIndex: 99999,\n background: 'transparent',\n border: 'none',\n borderRadius: 0,\n maxWidth: 'none',\n maxHeight: 'none',\n margin: 0,\n transform: 'none',\n pointerEvents: 'none' as const,\n overflow: 'visible',\n visibility: breakoutRevealed ? ('visible' as const) : ('hidden' as const),\n }\n : {\n width: '100%',\n height: iframeHeight,\n border: 'none',\n borderRadius: 8,\n overflow: isCapped ? undefined : ('hidden' as const),\n };\n\n const fullStyle = {\n width: '100%',\n height: '100%',\n border: 'none',\n };\n\n return (\n <div className={className} style={isCompact ? { position: 'relative' } : { width: '100%', height: '100%' }}>\n <iframe\n ref={iframeRef}\n srcDoc={html}\n style={isCompact ? compactStyle : fullStyle}\n scrolling={isCompact && !breakoutActive && !isCapped ? 'no' : undefined}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n title=\"Gadget\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n );\n}\n", "/**\n * Creates a self-contained HTML string for rendering a gadget component in an iframe.\n *\n * Loads React 18, ReactDOM, Babel (for JSX transpilation), and Tailwind CSS from CDNs.\n * Sets up the full gadget bridge: state, breakout, actions, chat, context, and hot-swap.\n *\n * Usage:\n * import { createGadgetRenderer, setupGadgetBreakout } from '@gigabuddy/chat';\n *\n * const html = createGadgetRenderer(componentCode, data, { viewport: 'compact', stateEnabled: true });\n * iframe.srcdoc = html;\n * setupGadgetBreakout(iframe);\n *\n * The gadget component receives these props:\n * function Gadget({ data, viewport, state, userId, breakout, chat, context })\n *\n * Bridge protocol (postMessage):\n * - Host \u2192 iframe: `gadget-set-data` \u2014 push new props\n * - Host \u2192 iframe: `gadget-state-init` / `gadget-state-update` \u2014 state changes\n * - Host \u2192 iframe: `gadget-update-component` \u2014 hot-swap component code\n * - Host \u2192 iframe: `gadget-breakout-started` \u2014 breakout activated with originalRect\n * - iframe \u2192 Host: `gadget-interaction` \u2014 user dispatched an action\n * - iframe \u2192 Host: `gadget-resize` \u2014 auto-height\n * - iframe \u2192 Host: `gadget-request-breakout` / `gadget-exit-breakout` \u2014 breakout lifecycle\n * - iframe \u2192 Host: `gadget-action-request` / `gadget-chat-request` / `gadget-context-request` \u2014 API calls\n */\nexport function createGadgetRenderer(\n componentCode: string,\n data: unknown = {},\n options?: {\n viewport?: 'compact' | 'full' | 'mobile';\n stateEnabled?: boolean;\n chatEnabled?: boolean;\n contextEnabled?: boolean;\n roomEnabled?: boolean;\n assets?: Record<string, { url: string; name: string }>;\n /** Additional script URLs to inject before gadget code (e.g. GadgetKit, Three.js) */\n libraries?: string[];\n },\n): string {\n const serializedData = JSON.stringify(data);\n const viewport = options?.viewport ?? 'full';\n const stateEnabled = options?.stateEnabled ?? false;\n const chatEnabled = options?.chatEnabled ?? false;\n const contextEnabled = options?.contextEnabled ?? false;\n const roomEnabled = options?.roomEnabled ?? false;\n const libraries = options?.libraries ?? [];\n const escapedCode = componentCode.replace(/<\\/script>/g, '<\\\\/script>');\n const serializedAssets = JSON.stringify(options?.assets ?? {});\n const libraryScripts = libraries.map((url) => ` <script src=\"${url}\"></script>`).join('\\n');\n\n const stateBridgeScript = stateEnabled\n ? `\n window.gadget.state = {\n shared: {},\n user: {},\n userId: null,\n _sharedCallbacks: [],\n _userCallbacks: [],\n\n dispatch: function(action, data) {\n window.parent.postMessage({ type: 'gadget-interaction', action: action, data: data || {} }, '*');\n },\n\n onSharedChange: function(callback) {\n window.gadget.state._sharedCallbacks.push(callback);\n callback(window.gadget.state.shared);\n return function() {\n var i = window.gadget.state._sharedCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.state._sharedCallbacks.splice(i, 1);\n };\n },\n\n onUserChange: function(callback) {\n window.gadget.state._userCallbacks.push(callback);\n callback(window.gadget.state.user);\n return function() {\n var i = window.gadget.state._userCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.state._userCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && (d.type === 'gadget-state-init' || d.type === 'gadget-state-update')) {\n if (d.userId !== undefined) {\n window.gadget.state.userId = d.userId;\n }\n if (d.shared !== undefined) {\n window.gadget.state.shared = d.shared;\n window.gadget.state._sharedCallbacks.forEach(function(cb) { try { cb(d.shared); } catch(e) {} });\n }\n if (d.user !== undefined) {\n window.gadget.state.user = d.user;\n window.gadget.state._userCallbacks.forEach(function(cb) { try { cb(d.user); } catch(e) {} });\n }\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const chatBridgeScript = chatEnabled\n ? `\n window.gadget.chat = {\n _request: function(method, params) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-chat-response' && d.requestId === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() { window.removeEventListener('message', handler); reject(new Error('Timed out')); }, 30000);\n window.parent.postMessage({ type: 'gadget-chat-request', requestId: requestId, method: method, params: params || {} }, '*');\n });\n },\n\n _eventCallbacks: [],\n\n createChannel: function(opts) { return window.gadget.chat._request('createChannel', opts); },\n findOrCreateChannel: function(name, opts) { return window.gadget.chat._request('findOrCreateChannel', { name: name, description: opts && opts.description }); },\n listChannels: function() { return window.gadget.chat._request('listChannels'); },\n joinChannel: function(conversationId) { return window.gadget.chat._request('joinChannel', { conversationId: conversationId }); },\n sendMessage: function(conversationId, text) { return window.gadget.chat._request('sendMessage', { conversationId: conversationId, text: text }); },\n getMessages: function(conversationId, opts) { return window.gadget.chat._request('getMessages', { conversationId: conversationId, limit: opts && opts.limit, before: opts && opts.before }); },\n updateChannel: function(conversationId, updates) { return window.gadget.chat._request('updateChannel', { conversationId: conversationId, description: updates && updates.description }); },\n createInvite: function(conversationId) { return window.gadget.chat._request('createInvite', { conversationId: conversationId }); },\n redeemInvite: function(token) { return window.gadget.chat._request('redeemInvite', { token: token }); },\n\n onEvent: function(callback) {\n window.gadget.chat._eventCallbacks.push(callback);\n return function() {\n var i = window.gadget.chat._eventCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.chat._eventCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-chat-event') {\n window.gadget.chat._eventCallbacks.forEach(function(cb) { try { cb(d.event); } catch(e) {} });\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const contextBridgeScript = contextEnabled\n ? `\n window.gadget.context = {\n _request: function(method, params) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-context-response' && d.id === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() { window.removeEventListener('message', handler); reject(new Error('Timed out')); }, 30000);\n window.parent.postMessage({ type: 'gadget-context-request', id: requestId, method: method, params: params || {} }, '*');\n });\n },\n\n _eventCallbacks: [],\n\n listTypes: function() { return window.gadget.context._request('listTypes', {}); },\n getType: function(contextType) { return window.gadget.context._request('getType', { contextType: contextType }); },\n listInstances: function(params) { return window.gadget.context._request('listInstances', params || {}); },\n getInstance: function(id) { return window.gadget.context._request('getInstance', { id: id }); },\n createInstance: function(params) { return window.gadget.context._request('createInstance', params); },\n updateInstance: function(id, data) { return window.gadget.context._request('updateInstance', { id: id, data: data }); },\n deleteInstance: function(id) { return window.gadget.context._request('deleteInstance', { id: id }); },\n searchKnowledge: function(params) { return window.gadget.context._request('searchKnowledge', params); },\n getEnriched: function(id) { return window.gadget.context._request('getEnriched', { id: id }); },\n getRelated: function(id) { return window.gadget.context._request('getRelated', { id: id }); },\n\n onEvent: function(callback) {\n window.gadget.context._eventCallbacks.push(callback);\n return function() {\n var i = window.gadget.context._eventCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.context._eventCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-context-event') {\n window.gadget.context._eventCallbacks.forEach(function(cb) { try { cb(d.event); } catch(e) {} });\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const roomBridgeScript = roomEnabled\n ? `\n // \u2500\u2500 Room presence \u2500\u2500\n window.gadget.room = {\n peers: [],\n userId: null,\n displayName: null,\n _peersCallbacks: [],\n _playerJoinedCallbacks: [],\n _playerLeftCallbacks: [],\n\n setCursor: function(pos) {\n window.parent.postMessage({ type: 'gadget-presence', cursor: pos }, '*');\n },\n setSelection: function(sel) {\n window.parent.postMessage({ type: 'gadget-presence', selection: sel }, '*');\n },\n onPeersChange: function(cb) {\n window.gadget.room._peersCallbacks.push(cb);\n cb(window.gadget.room.peers);\n return function() {\n var i = window.gadget.room._peersCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._peersCallbacks.splice(i, 1);\n };\n },\n onPlayerJoined: function(cb) {\n window.gadget.room._playerJoinedCallbacks.push(cb);\n return function() {\n var i = window.gadget.room._playerJoinedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._playerJoinedCallbacks.splice(i, 1);\n };\n },\n onPlayerLeft: function(cb) {\n window.gadget.room._playerLeftCallbacks.push(cb);\n return function() {\n var i = window.gadget.room._playerLeftCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._playerLeftCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Room chat \u2500\u2500\n window.gadget.roomChat = {\n messages: [],\n _messageCallbacks: [],\n\n send: function(text) {\n window.parent.postMessage({ type: 'gadget-chat-send', text: text }, '*');\n },\n onMessage: function(cb) {\n window.gadget.roomChat._messageCallbacks.push(cb);\n return function() {\n var i = window.gadget.roomChat._messageCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.roomChat._messageCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Gestures \u2500\u2500\n window.gadget.gestures = {\n active: [],\n _spawnedCallbacks: [],\n _dismissedCallbacks: [],\n\n spawn: function(gadgetId, anchor, opts) {\n opts = opts || {};\n window.parent.postMessage({\n type: 'gadget-gesture-send',\n gadgetId: gadgetId,\n anchor: anchor,\n ttl: opts.ttl,\n size: opts.size,\n rotation: opts.rotation,\n }, '*');\n },\n dismiss: function(gestureId) {\n window.parent.postMessage({ type: 'gadget-gesture-dismiss', gestureId: gestureId }, '*');\n },\n reportAnchorRect: function(selector, rect) {\n window.parent.postMessage({ type: 'gadget-anchor-rect', selector: selector, rect: rect }, '*');\n },\n onSpawned: function(cb) {\n window.gadget.gestures._spawnedCallbacks.push(cb);\n return function() {\n var i = window.gadget.gestures._spawnedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.gestures._spawnedCallbacks.splice(i, 1);\n };\n },\n onDismissed: function(cb) {\n window.gadget.gestures._dismissedCallbacks.push(cb);\n return function() {\n var i = window.gadget.gestures._dismissedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.gestures._dismissedCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Buddy attraction \u2500\u2500\n window.gadget.buddy = {\n attract: function(anchor, interest) {\n window.parent.postMessage({\n type: 'gadget-buddy-attract',\n anchor: anchor,\n interest: interest || 'medium',\n }, '*');\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (!d) return;\n\n // Presence updates\n if (d.type === 'gadget-presence-update') {\n window.gadget.room.peers = d.peers || [];\n window.gadget.room._peersCallbacks.forEach(function(cb) { try { cb(d.peers || []); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Player join/leave\n if (d.type === 'gadget-player-joined') {\n window.gadget.room._playerJoinedCallbacks.forEach(function(cb) { try { cb(d); } catch(e) {} });\n }\n if (d.type === 'gadget-player-left') {\n window.gadget.room.peers = window.gadget.room.peers.filter(function(p) { return p.userId !== d.userId; });\n window.gadget.room._playerLeftCallbacks.forEach(function(cb) { try { cb(d.userId); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Chat\n if (d.type === 'gadget-chat-message') {\n var msg = d.message || d;\n window.gadget.roomChat.messages.push(msg);\n if (window.gadget.roomChat.messages.length > 100) window.gadget.roomChat.messages.shift();\n window.gadget.roomChat._messageCallbacks.forEach(function(cb) { try { cb(msg); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-chat-history') {\n window.gadget.roomChat.messages = d.messages || [];\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Gestures\n if (d.type === 'gadget-gesture-spawned') {\n window.gadget.gestures.active.push(d.gesture);\n window.gadget.gestures._spawnedCallbacks.forEach(function(cb) { try { cb(d.gesture); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-gesture-dismissed') {\n window.gadget.gestures.active = window.gadget.gestures.active.filter(function(g) { return g.id !== d.gestureId; });\n window.gadget.gestures._dismissedCallbacks.forEach(function(cb) { try { cb(d.gestureId); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-gesture-sync') {\n window.gadget.gestures.active = d.gestures || [];\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Anchor rect request from host\n if (d.type === 'gadget-request-anchor-rect' && d.selector) {\n try {\n var el = document.querySelector(d.selector);\n if (el) {\n var rect = el.getBoundingClientRect();\n window.parent.postMessage({\n type: 'gadget-anchor-rect',\n selector: d.selector,\n rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n }, '*');\n }\n } catch(e) {}\n }\n });`\n : '';\n\n // When state is enabled, pass state prop alongside data and viewport\n const chatPropFragment = chatEnabled ? ', chat: window.gadget.chat' : '';\n const contextPropFragment = contextEnabled ? ', context: window.gadget.context' : '';\n const roomPropFragment = roomEnabled\n ? ', room: window.gadget.room, roomChat: window.gadget.roomChat, gestures: window.gadget.gestures'\n : '';\n const breakoutPropFragment =\n ', breakout: { active: window.gadget.breakout._active, originalRect: window.gadget.breakout._originalRect, request: window.gadget.breakout.request, exit: window.gadget.breakout.exit }';\n const componentProps = stateEnabled\n ? `{ data: window.__GADGET_DATA__, viewport: window.__GADGET_VIEWPORT__, state: window.gadget.state ? { shared: window.gadget.state.shared, user: window.gadget.state.user } : undefined, userId: window.gadget.state ? window.gadget.state.userId : undefined${chatPropFragment}${contextPropFragment}${breakoutPropFragment}${roomPropFragment} }`\n : `{ data: window.__GADGET_DATA__, viewport: window.__GADGET_VIEWPORT__${chatPropFragment}${contextPropFragment}${breakoutPropFragment}${roomPropFragment} }`;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <script src=\"https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js\"></script>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n${libraryScripts}\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n html, body { background: transparent; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; min-height: 100%; }\n #root { min-height: 100vh; }\n .gadget-error {\n padding: 16px;\n background: #fef2f2;\n border: 1px solid #fecaca;\n border-radius: 8px;\n color: #991b1b;\n font-family: monospace;\n font-size: 13px;\n white-space: pre-wrap;\n word-break: break-word;\n }\n .gadget-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n </style>\n</head>\n<body>\n <div id=\"root\"></div>\n <script>\n window.__GADGET_DATA__ = ${serializedData};\n window.__GADGET_VIEWPORT__ = '${viewport}';\n\n window.gadget = {\n data: window.__GADGET_DATA__,\n assets: ${serializedAssets},\n\n breakout: {\n _active: false,\n _originalRect: null,\n request: function() {\n if (window.gadget.breakout._active) return;\n window.gadget.breakout._active = true;\n window.parent.postMessage({ type: 'gadget-request-breakout' }, '*');\n window.__rerenderGadget && window.__rerenderGadget();\n },\n exit: function() {\n if (!window.gadget.breakout._active) return;\n window.gadget.breakout._active = false;\n window.gadget.breakout._originalRect = null;\n window.parent.postMessage({ type: 'gadget-exit-breakout' }, '*');\n window.__rerenderGadget();\n },\n },\n\n callAction: function(input) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-action-response' && d.requestId === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() {\n window.removeEventListener('message', handler);\n reject(new Error('Action timed out'));\n }, 30000);\n window.parent.postMessage({ type: 'gadget-action-request', requestId: requestId, input: input }, '*');\n });\n },\n };\n${stateBridgeScript}\n${chatBridgeScript}\n${contextBridgeScript}\n${roomBridgeScript}\n\n window.__gadgetRoot = null;\n window.__gadgetComponent = null;\n\n window.__rerenderGadget = function() {\n if (window.__gadgetRoot && window.__gadgetComponent) {\n var C = window.__gadgetComponent;\n var EB = window.__gadgetErrorBoundary;\n window.__gadgetRoot.render(\n React.createElement(EB, null, React.createElement(C, ${componentProps}))\n );\n }\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-set-data') {\n window.__GADGET_DATA__ = d.data;\n window.gadget.data = d.data;\n window.__rerenderGadget();\n }\n if (d && d.type === 'gadget-breakout-started') {\n var wasActive = window.gadget.breakout._active;\n window.gadget.breakout._active = true;\n window.gadget.breakout._originalRect = d.originalRect || null;\n if (!wasActive) window.__rerenderGadget();\n }\n if (d && d.type === 'gadget-update-component' && d.code) {\n try {\n var compiled = Babel.transform(d.code, { presets: ['react'] }).code;\n var fn = new Function('React', 'useState', 'useEffect', 'useCallback', 'useMemo', 'useRef',\n compiled + '\\\\nreturn typeof Gadget !== \"undefined\" ? Gadget : null;');\n var NewComponent = fn(React, React.useState, React.useEffect, React.useCallback, React.useMemo, React.useRef);\n if (NewComponent) {\n window.__gadgetComponent = NewComponent;\n if (window.__gadgetErrorBoundaryInstance) {\n window.__gadgetErrorBoundaryInstance.setState({ error: null });\n }\n window.__rerenderGadget();\n }\n } catch (err) {\n console.error('[gadget-hmr] Component update failed:', err);\n }\n }\n });\n </script>\n <script type=\"text/babel\" data-type=\"module\">\n const { useState, useEffect, useCallback, useMemo, useRef } = React;\n\n class ErrorBoundary extends React.Component {\n constructor(props) {\n super(props);\n this.state = { error: null };\n window.__gadgetErrorBoundaryInstance = this;\n }\n static getDerivedStateFromError(error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return React.createElement('div', { className: 'gadget-error' },\n React.createElement('div', { className: 'gadget-error-title' }, 'Runtime Error'),\n this.state.error.message\n );\n }\n return this.props.children;\n }\n }\n window.__gadgetErrorBoundary = ErrorBoundary;\n\n try {\n ${escapedCode}\n\n const ComponentToRender = typeof Gadget !== 'undefined' ? Gadget : null;\n\n if (ComponentToRender) {\n window.__gadgetComponent = ComponentToRender;\n const root = ReactDOM.createRoot(document.getElementById('root'));\n window.__gadgetRoot = root;\n root.render(\n <ErrorBoundary>\n <ComponentToRender data={window.__GADGET_DATA__} viewport={window.__GADGET_VIEWPORT__}${stateEnabled ? ' state={window.gadget.state ? { shared: window.gadget.state.shared, user: window.gadget.state.user } : undefined} userId={window.gadget.state ? window.gadget.state.userId : undefined}' : ''}${chatEnabled ? ' chat={window.gadget.chat}' : ''}${contextEnabled ? ' context={window.gadget.context}' : ''}${roomEnabled ? ' room={window.gadget.room} roomChat={window.gadget.roomChat} gestures={window.gadget.gestures}' : ''} breakout={{ active: window.gadget.breakout._active, originalRect: window.gadget.breakout._originalRect, request: window.gadget.breakout.request, exit: window.gadget.breakout.exit }} />\n </ErrorBoundary>\n );\n } else {\n document.getElementById('root').innerHTML =\n '<div class=\"gadget-error\"><div class=\"gadget-error-title\">No component found</div>Define a function called Gadget.</div>';\n }\n } catch (err) {\n document.getElementById('root').innerHTML =\n '<div class=\"gadget-error\"><div class=\"gadget-error-title\">Error</div>' +\n err.message.replace(/</g, '&lt;').replace(/>/g, '&gt;') +\n '</div>';\n }\n\n const rootEl = document.getElementById('root');\n const observer = new ResizeObserver(() => {\n window.parent.postMessage({\n type: 'gadget-resize',\n height: rootEl.scrollHeight,\n }, '*');\n });\n observer.observe(rootEl);\n </script>\n</body>\n</html>`;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createContext, useContext, useMemo, type ReactNode } from 'react';\n\nexport interface GadgetConfig {\n /** Base API URL (e.g. \"https://api.gigabuddy.com\") */\n apiUrl: string;\n /** Organization ID */\n orgId: string;\n /** Project ID */\n projectId: string;\n /** Returns a fresh auth token */\n getToken: () => Promise<string>;\n /** Optional SSE stream base URL (falls back to apiUrl) */\n streamBaseUrl?: string;\n}\n\ninterface GadgetContextValue {\n config: GadgetConfig;\n /** Resolves a file ID to a fresh signed URL */\n resolveFileUrl: (fileId: string) => Promise<string>;\n}\n\nconst GadgetCtx = createContext<GadgetContextValue | null>(null);\n\nexport function GadgetProvider({ config, children }: { config: GadgetConfig; children: ReactNode }) {\n const value = useMemo<GadgetContextValue>(() => {\n const base = `${config.apiUrl}/${config.orgId}/${config.projectId}`;\n\n return {\n config,\n resolveFileUrl: async (fileId: string) => {\n const token = await config.getToken();\n const res = await fetch(`${base}/context/get-file-url`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ fileId }),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as { url: string };\n return data.url;\n },\n };\n }, [config.apiUrl, config.orgId, config.projectId, config.getToken, config.streamBaseUrl]);\n\n return <GadgetCtx.Provider value={value}>{children}</GadgetCtx.Provider>;\n}\n\nexport function useGadgetConfig(): GadgetContextValue {\n const ctx = useContext(GadgetCtx);\n if (!ctx) throw new Error('GadgetFrame must be wrapped in a <GadgetProvider>');\n return ctx;\n}\n", "import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { createGadgetRenderer } from '../createGadgetRenderer.js';\nimport { useGadgetConfig } from './GadgetContext.js';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface GadgetFrameProps {\n /** The gadget entity ID to load */\n gadgetId: string;\n /** Data props to pass to the gadget */\n props?: Record<string, unknown>;\n /** Display mode \u2014 compact (inline, resizable) or full (fills container) */\n mode?: 'compact' | 'full';\n /** Whether breakout is enabled (default: true in compact mode) */\n breakout?: boolean;\n /** Max height in compact mode before scrolling (default: 300) */\n maxHeight?: number;\n /** Deployment ID for mission-backed gadgets (auto-generated if not provided) */\n deploymentId?: string;\n /** Conversation ID \u2014 used when updating message content after action */\n conversationId?: string;\n /** Message ID \u2014 used when updating message content after action */\n messageId?: string;\n /** Additional className for the wrapper div */\n className?: string;\n /** Called when breakout state changes */\n onBreakoutChange?: (active: boolean) => void;\n /** Called on load error */\n onError?: (error: string) => void;\n /** Whether to lazy-load (only render when near viewport). Default: true in compact mode. */\n lazy?: boolean;\n}\n\ninterface GadgetEntity {\n data: {\n type: string;\n componentCode: string;\n actionRef?: { type: string; id: string };\n missionRef?: { type: string; id: string };\n stateBindings?: {\n shared?: { contextFields: string[] };\n user?: { contextFields: string[] };\n };\n assets?: Record<string, { fileId: string; url: string; name: string; contentType: string }>;\n contextBinding?: { contextTypes?: string[] };\n contextEnabled?: boolean;\n contextTypes?: string[];\n };\n}\n\n// =============================================================================\n// Entity cache \u2014 survives across mounts/navigations, keyed by gadgetId\n// =============================================================================\n\n/** Entity cache \u2014 stale-while-revalidate. Serve cached instantly, refresh in background. */\nconst entityCache = new Map<string, { entity: GadgetEntity; fetchedAt: number }>();\nconst ENTITY_STALE_MS = 5 * 60 * 1000; // revalidate after 5 min\n\n/** File URL cache \u2014 signed URLs with TTL (default 50 min, signed URLs typically last 60 min) */\nconst fileUrlCache = new Map<string, { url: string; expiresAt: number }>();\nconst FILE_URL_TTL_MS = 50 * 60 * 1000;\n\nfunction getCachedFileUrl(fileId: string): string | null {\n const entry = fileUrlCache.get(fileId);\n if (!entry) return null;\n if (Date.now() > entry.expiresAt) {\n fileUrlCache.delete(fileId);\n return null;\n }\n return entry.url;\n}\n\nfunction setCachedFileUrl(fileId: string, url: string): void {\n fileUrlCache.set(fileId, { url, expiresAt: Date.now() + FILE_URL_TTL_MS });\n}\n\n// =============================================================================\n// Component\n// =============================================================================\n\nexport function GadgetFrame({\n gadgetId,\n props,\n mode = 'compact',\n breakout: breakoutEnabled = true,\n maxHeight = 300,\n deploymentId: externalDeploymentId,\n conversationId,\n messageId,\n className,\n onBreakoutChange,\n onError,\n lazy,\n}: GadgetFrameProps) {\n const { config, resolveFileUrl } = useGadgetConfig();\n const base = `${config.apiUrl}/${config.orgId}/${config.projectId}`;\n\n // \u2500\u2500 State (all hooks must be called unconditionally \u2014 no early returns before hooks) \u2500\u2500\n const lazyEnabled = lazy ?? mode === 'compact';\n const [visible, setVisible] = useState(!lazyEnabled);\n const [html, setHtml] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [naturalHeight, setNaturalHeight] = useState(60);\n const [iframeLoaded, setIframeLoaded] = useState(false);\n const [breakoutActive, setBreakoutActive] = useState(false);\n const [breakoutRevealed, setBreakoutRevealed] = useState(false);\n\n // \u2500\u2500 Refs \u2500\u2500\n const sentinelRef = useRef<HTMLDivElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const entityRef = useRef<GadgetEntity | null>(null);\n const initialPropsRef = useRef(props);\n const deploymentIdRef = useRef<string | null>(externalDeploymentId ?? null);\n const sseRef = useRef<EventSource | null>(null);\n const userIdRef = useRef<string | null>(null);\n const latestStateRef = useRef<{ shared: Record<string, unknown>; user: Record<string, unknown> } | null>(null);\n const placeholderRef = useRef<HTMLDivElement | null>(null);\n const ancestorOverridesRef = useRef<{ el: HTMLElement; key: string; original: string }[]>([]);\n const breakoutActiveRef = useRef(false);\n breakoutActiveRef.current = breakoutActive;\n\n // \u2500\u2500 Derived \u2500\u2500\n const isCompact = mode === 'compact';\n const isCapped = isCompact && naturalHeight > maxHeight;\n const iframeHeight = isCapped ? maxHeight : naturalHeight;\n\n // \u2500\u2500 Lazy loading: defer everything until the gadget is near the viewport \u2500\u2500\n useEffect(() => {\n if (!lazyEnabled || visible) return;\n const el = sentinelRef.current;\n if (!el) return;\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setVisible(true);\n observer.disconnect();\n }\n },\n { rootMargin: '200px' }, // start loading 200px before entering viewport\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [lazyEnabled, visible]);\n\n // \u2500\u2500 Fetch entity (stale-while-revalidate) + build HTML + deploy \u2500\u2500\n useEffect(() => {\n if (!visible) return;\n let cancelled = false;\n\n async function fetchEntityFromServer(token: string): Promise<GadgetEntity> {\n const res = await fetch(`${base}/chat/get-gadget`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId }),\n });\n if (!res.ok) throw new Error(`Failed to load gadget: ${res.status}`);\n const entity = (await res.json()) as GadgetEntity;\n entityCache.set(gadgetId, { entity, fetchedAt: Date.now() });\n return entity;\n }\n\n function buildHtml(entity: GadgetEntity): string {\n const hasMission = entity.data.missionRef?.id != null;\n const hasContext =\n entity.data.contextEnabled === true ||\n (entity.data.contextBinding?.contextTypes?.length ?? 0) > 0 ||\n (entity.data.contextTypes?.length ?? 0) > 0;\n const assetMap = entity.data.assets\n ? Object.fromEntries(Object.entries(entity.data.assets).map(([k, v]) => [k, { url: v.url, name: v.name }]))\n : undefined;\n return createGadgetRenderer(entity.data.componentCode, initialPropsRef.current ?? {}, {\n viewport: mode,\n stateEnabled: hasMission,\n contextEnabled: hasContext,\n assets: assetMap,\n });\n }\n\n async function deploy(entity: GadgetEntity, token: string) {\n if (!entity.data.missionRef?.id) return;\n\n const depId = externalDeploymentId ?? messageId ?? `gadget_${gadgetId}_${Date.now()}`;\n deploymentIdRef.current = depId;\n\n const deployRes = await fetch(`${base}/gadget-deploy`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId, deploymentId: depId, initialData: initialPropsRef.current, conversationId }),\n });\n if (!deployRes.ok) throw new Error(`Failed to deploy gadget: ${deployRes.status}`);\n\n const deployData = (await deployRes.json()) as {\n deploymentId: string;\n missionInstanceId: string;\n initialState: { shared: Record<string, unknown>; user: Record<string, unknown> };\n userId?: string;\n };\n if (cancelled) return;\n\n if (deployData.userId) userIdRef.current = deployData.userId;\n latestStateRef.current = deployData.initialState;\n\n // Connect SSE\n const streamBase = config.streamBaseUrl ?? config.apiUrl;\n const sseUrl = `${streamBase}/${config.orgId}/${config.projectId}/gadget-state/${depId}/stream?token=${encodeURIComponent(token)}`;\n const sse = new EventSource(sseUrl);\n sseRef.current = sse;\n\n sse.addEventListener('state-update', (event) => {\n if (cancelled) return;\n try {\n const state = JSON.parse(event.data) as {\n shared: Record<string, unknown>;\n user: Record<string, unknown>;\n userId?: string;\n };\n if (state.userId && !userIdRef.current) userIdRef.current = state.userId;\n latestStateRef.current = state;\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-state-update', shared: state.shared, user: state.user, userId: userIdRef.current },\n '*',\n );\n } catch {\n // Ignore malformed SSE\n }\n });\n }\n\n (async () => {\n try {\n const token = await config.getToken();\n const cached = entityCache.get(gadgetId);\n let entity: GadgetEntity;\n\n if (cached) {\n // Serve from cache immediately \u2014 no loading spinner\n entity = cached.entity;\n entityRef.current = entity;\n if (!cancelled) {\n setHtml(buildHtml(entity));\n setLoading(false);\n }\n\n // Revalidate in background if stale\n if (Date.now() - cached.fetchedAt > ENTITY_STALE_MS) {\n fetchEntityFromServer(token)\n .then((fresh) => {\n if (cancelled) return;\n // Only re-render if component code actually changed\n if (fresh.data.componentCode !== cached.entity.data.componentCode) {\n entityRef.current = fresh;\n setHtml(buildHtml(fresh));\n } else {\n entityRef.current = fresh;\n }\n })\n .catch(() => {\n /* background revalidation failure is silent */\n });\n }\n } else {\n // First load \u2014 fetch from server\n entity = await fetchEntityFromServer(token);\n if (cancelled) return;\n entityRef.current = entity;\n setHtml(buildHtml(entity));\n }\n\n if (cancelled) return;\n await deploy(entity, token);\n } catch (err) {\n if (!cancelled) {\n const msg = err instanceof Error ? err.message : 'Failed to load gadget';\n setError(msg);\n onError?.(msg);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n\n return () => {\n cancelled = true;\n if (sseRef.current) {\n sseRef.current.close();\n sseRef.current = null;\n }\n };\n }, [visible, gadgetId, base, config.getToken, config.streamBaseUrl, config.orgId, config.projectId, mode]);\n\n // \u2500\u2500 Push initial state on iframe load \u2500\u2500\n useEffect(() => {\n if (!iframeLoaded || !latestStateRef.current) return;\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: 'gadget-state-init',\n shared: latestStateRef.current.shared,\n user: latestStateRef.current.user,\n userId: userIdRef.current,\n },\n '*',\n );\n }, [iframeLoaded]);\n\n // \u2500\u2500 Push props changes \u2500\u2500\n useEffect(() => {\n if (!iframeLoaded || !props) return;\n iframeRef.current?.contentWindow?.postMessage({ type: 'gadget-set-data', data: props }, '*');\n }, [props, iframeLoaded]);\n\n // \u2500\u2500 Breakout handler \u2500\u2500\n useEffect(() => {\n if (!visible || !iframeRef.current || !html || !breakoutEnabled) return;\n const iframe = iframeRef.current;\n\n function clearAncestorClipping() {\n let el = iframe.parentElement;\n while (el && el !== document.body && el !== document.documentElement) {\n const cs = getComputedStyle(el);\n const overflow = cs.overflow + cs.overflowX + cs.overflowY;\n const hasClip = /hidden|auto|scroll|clip/.test(overflow);\n const hasContain =\n cs.transform !== 'none' || cs.willChange === 'transform' || cs.contain !== 'none' || cs.filter !== 'none';\n\n if (hasClip || hasContain) {\n if (hasClip) {\n ancestorOverridesRef.current.push({ el, key: 'overflow', original: el.style.overflow });\n ancestorOverridesRef.current.push({ el, key: 'overflowX', original: el.style.overflowX });\n ancestorOverridesRef.current.push({ el, key: 'overflowY', original: el.style.overflowY });\n el.style.overflow = 'visible';\n el.style.overflowX = 'visible';\n el.style.overflowY = 'visible';\n }\n if (hasContain && cs.transform !== 'none') {\n ancestorOverridesRef.current.push({ el, key: 'transform', original: el.style.transform });\n el.style.transform = 'none';\n }\n if (hasContain && cs.contain !== 'none') {\n ancestorOverridesRef.current.push({ el, key: 'contain', original: el.style.contain });\n el.style.contain = 'none';\n }\n }\n el = el.parentElement;\n }\n }\n\n function restoreAncestorClipping() {\n for (const { el, key, original } of ancestorOverridesRef.current) {\n (el.style as unknown as Record<string, string>)[key] = original;\n }\n ancestorOverridesRef.current.length = 0;\n }\n\n function onMessage(event: MessageEvent) {\n if (event.source !== iframe.contentWindow) return;\n const d = event.data;\n if (!d || typeof d !== 'object') return;\n\n if (d.type === 'gadget-request-breakout') {\n const rect = iframe.getBoundingClientRect();\n\n // Placeholder to preserve layout\n const ph = document.createElement('div');\n ph.style.width = `${rect.width}px`;\n ph.style.height = `${rect.height}px`;\n ph.style.flexShrink = '0';\n iframe.parentElement?.insertBefore(ph, iframe);\n placeholderRef.current = ph;\n\n clearAncestorClipping();\n setBreakoutActive(true);\n setBreakoutRevealed(false);\n onBreakoutChange?.(true);\n\n iframe.contentWindow?.postMessage(\n {\n type: 'gadget-breakout-started',\n originalRect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n },\n '*',\n );\n\n // Reveal after repositioning\n requestAnimationFrame(() => requestAnimationFrame(() => setBreakoutRevealed(true)));\n }\n\n if (d.type === 'gadget-exit-breakout') {\n if (placeholderRef.current) {\n placeholderRef.current.remove();\n placeholderRef.current = null;\n }\n restoreAncestorClipping();\n setBreakoutActive(false);\n setBreakoutRevealed(false);\n onBreakoutChange?.(false);\n }\n }\n\n window.addEventListener('message', onMessage);\n return () => {\n window.removeEventListener('message', onMessage);\n if (placeholderRef.current) {\n placeholderRef.current.remove();\n placeholderRef.current = null;\n }\n restoreAncestorClipping();\n setBreakoutActive(false);\n setBreakoutRevealed(false);\n };\n }, [visible, html, breakoutEnabled, onBreakoutChange]);\n\n // \u2500\u2500 Bridge handler (actions, interactions, file URL, resize) \u2500\u2500\n const handleMessage = useCallback(\n async (event: MessageEvent<unknown>) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = event.data as any;\n if (!data || typeof data !== 'object') return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n\n const type = data.type as string;\n\n // Resize (compact only)\n if (type === 'gadget-resize') {\n if (breakoutActiveRef.current || !isCompact) return;\n const h = data.height as number;\n if (h > 0) setNaturalHeight(h);\n return;\n }\n\n // Interaction dispatch\n if (type === 'gadget-interaction' && deploymentIdRef.current) {\n void (async () => {\n try {\n const token = await config.getToken();\n await fetch(`${base}/gadget-interact`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n deploymentId: deploymentIdRef.current,\n action: data.action as string,\n data: (data.data as Record<string, unknown>) ?? {},\n }),\n });\n } catch {\n // Fire-and-forget\n }\n })();\n return;\n }\n\n // File URL resolution (with cache)\n if (type === 'gadget-file-url-request') {\n const requestId = data.requestId as string;\n const fileId = data.fileId as string;\n if (!requestId || !fileId) return;\n\n const cached = getCachedFileUrl(fileId);\n if (cached) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-file-url-response', requestId, url: cached },\n '*',\n );\n return;\n }\n\n void (async () => {\n try {\n const url = await resolveFileUrl(fileId);\n setCachedFileUrl(fileId, url);\n iframeRef.current?.contentWindow?.postMessage({ type: 'gadget-file-url-response', requestId, url }, '*');\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: 'gadget-file-url-response',\n requestId,\n error: err instanceof Error ? err.message : 'Failed to resolve file URL',\n },\n '*',\n );\n }\n })();\n return;\n }\n\n // Action execution\n if (type === 'gadget-action-request') {\n const requestId = data.requestId as string;\n const input = (data.input as Record<string, unknown>) || {};\n const entity = entityRef.current;\n\n if (!entity?.data.actionRef?.id) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: 'No action configured' },\n '*',\n );\n return;\n }\n\n try {\n const token = await config.getToken();\n const res = await fetch(`${base}/chat/execute-gadget`, {\n method: 'POST',\n headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ gadgetId, input }),\n });\n\n const result = (await res.json()) as {\n status?: string;\n error?: string;\n errorMessage?: string;\n output?: unknown;\n };\n\n if (!res.ok) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: result.error || `HTTP ${res.status}` },\n '*',\n );\n } else if (result.status === 'failure') {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: result.errorMessage || 'Action failed' },\n '*',\n );\n } else {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, result: result.output },\n '*',\n );\n }\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-action-response', requestId, error: err instanceof Error ? err.message : 'Unknown error' },\n '*',\n );\n }\n }\n\n // Context bridge \u2014 proxy context SDK calls to backend API\n if (type === 'gadget-context-request') {\n const requestId = data.id as string;\n const method = data.method as string;\n const params = (data.params as Record<string, unknown>) ?? {};\n\n void (async () => {\n try {\n const token = await config.getToken();\n const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' };\n let result: unknown;\n\n // Map bridge methods to context API endpoints\n const methodEndpointMap: Record<string, string> = {\n listTypes: 'context/list-types',\n getType: 'context/get-type',\n listInstances: 'context/list-instances',\n getInstance: 'context/get-instance',\n createInstance: 'context/create-instance',\n updateInstance: 'context/update-instance',\n deleteInstance: 'context/delete-instance',\n searchKnowledge: 'context/search-knowledge',\n };\n\n // Methods that need id\u2192instanceId remapping\n const idRemapMethods = new Set(['getInstance', 'updateInstance', 'deleteInstance']);\n\n if (method === 'getEnriched' || method === 'getRelated') {\n // Legacy REST endpoints\n const id = params['id'] as string;\n const endpoint = method === 'getEnriched' ? 'enriched' : 'related';\n const res = await fetch(`${base}/context-instances/${id}/${endpoint}`, { headers });\n if (!res.ok) throw new Error(`Context ${method} failed: ${res.status}`);\n result = await res.json();\n } else if (methodEndpointMap[method]) {\n // Remap { id } \u2192 { instanceId } where needed\n const body =\n idRemapMethods.has(method) && params['id']\n ? { ...params, instanceId: params['id'], id: undefined }\n : params;\n const res = await fetch(`${base}/${methodEndpointMap[method]}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`Context ${method} failed: ${res.status}`);\n result = await res.json();\n } else {\n throw new Error(`Unknown context method: ${method}`);\n }\n\n iframeRef.current?.contentWindow?.postMessage(\n { type: 'gadget-context-response', id: requestId, result },\n '*',\n );\n } catch (err) {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: 'gadget-context-response',\n id: requestId,\n error: err instanceof Error ? err.message : 'Context request failed',\n },\n '*',\n );\n }\n })();\n return;\n }\n },\n [base, config.getToken, resolveFileUrl, gadgetId, isCompact],\n );\n\n useEffect(() => {\n if (!visible) return;\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [visible, handleMessage]);\n\n // \u2500\u2500 Skeleton placeholder (shared by lazy + loading states) \u2500\u2500\n const skeleton = (\n <div\n ref={!visible ? sentinelRef : undefined}\n className={className}\n style={{\n width: '100%',\n height: maxHeight,\n minHeight: 60,\n borderRadius: 8,\n background:\n 'linear-gradient(90deg, rgba(128,128,128,0.06) 25%, rgba(128,128,128,0.12) 50%, rgba(128,128,128,0.06) 75%)',\n backgroundSize: '200% 100%',\n animation: 'gadget-skeleton 1.5s ease-in-out infinite',\n }}\n >\n <style>{`@keyframes gadget-skeleton { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }`}</style>\n </div>\n );\n\n if (!visible) return skeleton;\n\n // \u2500\u2500 Render \u2500\u2500\n\n if (error) {\n return (\n <div\n className={className}\n style={{\n padding: '8px 12px',\n fontSize: 12,\n color: '#b91c1c',\n background: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: 8,\n }}\n >\n {error}\n </div>\n );\n }\n\n if (loading) return skeleton;\n\n if (!html) return null;\n\n const compactStyle = breakoutActive\n ? {\n position: 'fixed' as const,\n top: 0,\n left: 0,\n width: '100vw',\n height: '100vh',\n zIndex: 99999,\n background: 'transparent',\n border: 'none',\n borderRadius: 0,\n maxWidth: 'none',\n maxHeight: 'none',\n margin: 0,\n transform: 'none',\n pointerEvents: breakoutRevealed ? ('auto' as const) : ('none' as const),\n overflow: 'visible',\n visibility: breakoutRevealed ? ('visible' as const) : ('hidden' as const),\n }\n : {\n width: '100%',\n height: iframeHeight,\n border: 'none',\n borderRadius: 8,\n overflow: isCapped ? undefined : ('hidden' as const),\n };\n\n const fullStyle = {\n width: '100%',\n height: '100%',\n border: 'none',\n };\n\n return (\n <div className={className} style={isCompact ? { position: 'relative' } : { width: '100%', height: '100%' }}>\n <iframe\n ref={iframeRef}\n srcDoc={html}\n style={isCompact ? compactStyle : fullStyle}\n scrolling={isCompact && !breakoutActive && !isCapped ? 'no' : undefined}\n sandbox=\"allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-downloads allow-forms allow-modals\"\n allow=\"clipboard-write; fullscreen; autoplay\"\n title=\"Gadget\"\n onLoad={() => setIframeLoaded(true)}\n />\n </div>\n );\n}\n", "/**\n * Creates a self-contained HTML string for rendering a gadget component in an iframe.\n *\n * Loads React 18, ReactDOM, Babel (for JSX transpilation), and Tailwind CSS from CDNs.\n * Sets up the full gadget bridge: state, breakout, actions, chat, context, and hot-swap.\n *\n * Usage:\n * import { createGadgetRenderer, setupGadgetBreakout } from '@gigabuddy/chat';\n *\n * const html = createGadgetRenderer(componentCode, data, { viewport: 'compact', stateEnabled: true });\n * iframe.srcdoc = html;\n * setupGadgetBreakout(iframe);\n *\n * The gadget component receives these props:\n * function Gadget({ data, viewport, state, userId, breakout, chat, context })\n *\n * Bridge protocol (postMessage):\n * - Host \u2192 iframe: `gadget-set-data` \u2014 push new props\n * - Host \u2192 iframe: `gadget-state-init` / `gadget-state-update` \u2014 state changes\n * - Host \u2192 iframe: `gadget-update-component` \u2014 hot-swap component code\n * - Host \u2192 iframe: `gadget-breakout-started` \u2014 breakout activated with originalRect\n * - iframe \u2192 Host: `gadget-interaction` \u2014 user dispatched an action\n * - iframe \u2192 Host: `gadget-resize` \u2014 auto-height\n * - iframe \u2192 Host: `gadget-request-breakout` / `gadget-exit-breakout` \u2014 breakout lifecycle\n * - iframe \u2192 Host: `gadget-action-request` / `gadget-chat-request` / `gadget-context-request` \u2014 API calls\n */\nexport function createGadgetRenderer(\n componentCode: string,\n data: unknown = {},\n options?: {\n viewport?: 'compact' | 'full' | 'mobile';\n stateEnabled?: boolean;\n chatEnabled?: boolean;\n contextEnabled?: boolean;\n roomEnabled?: boolean;\n assets?: Record<string, { url: string; name: string }>;\n /** Additional script URLs to inject before gadget code (e.g. GadgetKit, Three.js) */\n libraries?: string[];\n },\n): string {\n const serializedData = JSON.stringify(data);\n const viewport = options?.viewport ?? 'full';\n const stateEnabled = options?.stateEnabled ?? false;\n const chatEnabled = options?.chatEnabled ?? false;\n const contextEnabled = options?.contextEnabled ?? false;\n const roomEnabled = options?.roomEnabled ?? false;\n const libraries = options?.libraries ?? [];\n const escapedCode = componentCode.replace(/<\\/script>/g, '<\\\\/script>');\n const serializedAssets = JSON.stringify(options?.assets ?? {});\n const libraryScripts = libraries.map((url) => ` <script src=\"${url}\"></script>`).join('\\n');\n\n const stateBridgeScript = stateEnabled\n ? `\n window.gadget.state = {\n shared: {},\n user: {},\n userId: null,\n _sharedCallbacks: [],\n _userCallbacks: [],\n\n dispatch: function(action, data) {\n window.parent.postMessage({ type: 'gadget-interaction', action: action, data: data || {} }, '*');\n },\n\n onSharedChange: function(callback) {\n window.gadget.state._sharedCallbacks.push(callback);\n callback(window.gadget.state.shared);\n return function() {\n var i = window.gadget.state._sharedCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.state._sharedCallbacks.splice(i, 1);\n };\n },\n\n onUserChange: function(callback) {\n window.gadget.state._userCallbacks.push(callback);\n callback(window.gadget.state.user);\n return function() {\n var i = window.gadget.state._userCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.state._userCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && (d.type === 'gadget-state-init' || d.type === 'gadget-state-update')) {\n if (d.userId !== undefined) {\n window.gadget.state.userId = d.userId;\n }\n if (d.shared !== undefined) {\n window.gadget.state.shared = d.shared;\n window.gadget.state._sharedCallbacks.forEach(function(cb) { try { cb(d.shared); } catch(e) {} });\n }\n if (d.user !== undefined) {\n window.gadget.state.user = d.user;\n window.gadget.state._userCallbacks.forEach(function(cb) { try { cb(d.user); } catch(e) {} });\n }\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const chatBridgeScript = chatEnabled\n ? `\n window.gadget.chat = {\n _request: function(method, params) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-chat-response' && d.requestId === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() { window.removeEventListener('message', handler); reject(new Error('Timed out')); }, 30000);\n window.parent.postMessage({ type: 'gadget-chat-request', requestId: requestId, method: method, params: params || {} }, '*');\n });\n },\n\n _eventCallbacks: [],\n\n createChannel: function(opts) { return window.gadget.chat._request('createChannel', opts); },\n findOrCreateChannel: function(name, opts) { return window.gadget.chat._request('findOrCreateChannel', { name: name, description: opts && opts.description }); },\n listChannels: function() { return window.gadget.chat._request('listChannels'); },\n joinChannel: function(conversationId) { return window.gadget.chat._request('joinChannel', { conversationId: conversationId }); },\n sendMessage: function(conversationId, text) { return window.gadget.chat._request('sendMessage', { conversationId: conversationId, text: text }); },\n getMessages: function(conversationId, opts) { return window.gadget.chat._request('getMessages', { conversationId: conversationId, limit: opts && opts.limit, before: opts && opts.before }); },\n updateChannel: function(conversationId, updates) { return window.gadget.chat._request('updateChannel', { conversationId: conversationId, description: updates && updates.description }); },\n createInvite: function(conversationId) { return window.gadget.chat._request('createInvite', { conversationId: conversationId }); },\n redeemInvite: function(token) { return window.gadget.chat._request('redeemInvite', { token: token }); },\n\n onEvent: function(callback) {\n window.gadget.chat._eventCallbacks.push(callback);\n return function() {\n var i = window.gadget.chat._eventCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.chat._eventCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-chat-event') {\n window.gadget.chat._eventCallbacks.forEach(function(cb) { try { cb(d.event); } catch(e) {} });\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const contextBridgeScript = contextEnabled\n ? `\n window.gadget.context = {\n _request: function(method, params) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-context-response' && d.id === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() { window.removeEventListener('message', handler); reject(new Error('Timed out')); }, 30000);\n window.parent.postMessage({ type: 'gadget-context-request', id: requestId, method: method, params: params || {} }, '*');\n });\n },\n\n _eventCallbacks: [],\n\n listTypes: function() { return window.gadget.context._request('listTypes', {}); },\n getType: function(contextType) { return window.gadget.context._request('getType', { contextType: contextType }); },\n listInstances: function(params) { return window.gadget.context._request('listInstances', params || {}); },\n getInstance: function(id) { return window.gadget.context._request('getInstance', { id: id }); },\n createInstance: function(params) { return window.gadget.context._request('createInstance', params); },\n updateInstance: function(id, data) { return window.gadget.context._request('updateInstance', { id: id, data: data }); },\n deleteInstance: function(id) { return window.gadget.context._request('deleteInstance', { id: id }); },\n searchKnowledge: function(params) { return window.gadget.context._request('searchKnowledge', params); },\n getEnriched: function(id) { return window.gadget.context._request('getEnriched', { id: id }); },\n getRelated: function(id) { return window.gadget.context._request('getRelated', { id: id }); },\n\n onEvent: function(callback) {\n window.gadget.context._eventCallbacks.push(callback);\n return function() {\n var i = window.gadget.context._eventCallbacks.indexOf(callback);\n if (i !== -1) window.gadget.context._eventCallbacks.splice(i, 1);\n };\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-context-event') {\n window.gadget.context._eventCallbacks.forEach(function(cb) { try { cb(d.event); } catch(e) {} });\n window.__rerenderGadget();\n }\n });`\n : '';\n\n const roomBridgeScript = roomEnabled\n ? `\n // \u2500\u2500 Room presence \u2500\u2500\n window.gadget.room = {\n peers: [],\n userId: null,\n displayName: null,\n _peersCallbacks: [],\n _playerJoinedCallbacks: [],\n _playerLeftCallbacks: [],\n\n setCursor: function(pos) {\n window.parent.postMessage({ type: 'gadget-presence', cursor: pos }, '*');\n },\n setSelection: function(sel) {\n window.parent.postMessage({ type: 'gadget-presence', selection: sel }, '*');\n },\n onPeersChange: function(cb) {\n window.gadget.room._peersCallbacks.push(cb);\n cb(window.gadget.room.peers);\n return function() {\n var i = window.gadget.room._peersCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._peersCallbacks.splice(i, 1);\n };\n },\n onPlayerJoined: function(cb) {\n window.gadget.room._playerJoinedCallbacks.push(cb);\n return function() {\n var i = window.gadget.room._playerJoinedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._playerJoinedCallbacks.splice(i, 1);\n };\n },\n onPlayerLeft: function(cb) {\n window.gadget.room._playerLeftCallbacks.push(cb);\n return function() {\n var i = window.gadget.room._playerLeftCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.room._playerLeftCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Room chat \u2500\u2500\n window.gadget.roomChat = {\n messages: [],\n _messageCallbacks: [],\n\n send: function(text) {\n window.parent.postMessage({ type: 'gadget-chat-send', text: text }, '*');\n },\n onMessage: function(cb) {\n window.gadget.roomChat._messageCallbacks.push(cb);\n return function() {\n var i = window.gadget.roomChat._messageCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.roomChat._messageCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Gestures \u2500\u2500\n window.gadget.gestures = {\n active: [],\n _spawnedCallbacks: [],\n _dismissedCallbacks: [],\n\n spawn: function(gadgetId, anchor, opts) {\n opts = opts || {};\n window.parent.postMessage({\n type: 'gadget-gesture-send',\n gadgetId: gadgetId,\n anchor: anchor,\n ttl: opts.ttl,\n size: opts.size,\n rotation: opts.rotation,\n }, '*');\n },\n dismiss: function(gestureId) {\n window.parent.postMessage({ type: 'gadget-gesture-dismiss', gestureId: gestureId }, '*');\n },\n reportAnchorRect: function(selector, rect) {\n window.parent.postMessage({ type: 'gadget-anchor-rect', selector: selector, rect: rect }, '*');\n },\n onSpawned: function(cb) {\n window.gadget.gestures._spawnedCallbacks.push(cb);\n return function() {\n var i = window.gadget.gestures._spawnedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.gestures._spawnedCallbacks.splice(i, 1);\n };\n },\n onDismissed: function(cb) {\n window.gadget.gestures._dismissedCallbacks.push(cb);\n return function() {\n var i = window.gadget.gestures._dismissedCallbacks.indexOf(cb);\n if (i !== -1) window.gadget.gestures._dismissedCallbacks.splice(i, 1);\n };\n },\n };\n\n // \u2500\u2500 Buddy attraction \u2500\u2500\n window.gadget.buddy = {\n attract: function(anchor, interest) {\n window.parent.postMessage({\n type: 'gadget-buddy-attract',\n anchor: anchor,\n interest: interest || 'medium',\n }, '*');\n },\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (!d) return;\n\n // Presence updates\n if (d.type === 'gadget-presence-update') {\n window.gadget.room.peers = d.peers || [];\n window.gadget.room._peersCallbacks.forEach(function(cb) { try { cb(d.peers || []); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Player join/leave\n if (d.type === 'gadget-player-joined') {\n window.gadget.room._playerJoinedCallbacks.forEach(function(cb) { try { cb(d); } catch(e) {} });\n }\n if (d.type === 'gadget-player-left') {\n window.gadget.room.peers = window.gadget.room.peers.filter(function(p) { return p.userId !== d.userId; });\n window.gadget.room._playerLeftCallbacks.forEach(function(cb) { try { cb(d.userId); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Chat\n if (d.type === 'gadget-chat-message') {\n var msg = d.message || d;\n window.gadget.roomChat.messages.push(msg);\n if (window.gadget.roomChat.messages.length > 100) window.gadget.roomChat.messages.shift();\n window.gadget.roomChat._messageCallbacks.forEach(function(cb) { try { cb(msg); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-chat-history') {\n window.gadget.roomChat.messages = d.messages || [];\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Gestures\n if (d.type === 'gadget-gesture-spawned') {\n window.gadget.gestures.active.push(d.gesture);\n window.gadget.gestures._spawnedCallbacks.forEach(function(cb) { try { cb(d.gesture); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-gesture-dismissed') {\n window.gadget.gestures.active = window.gadget.gestures.active.filter(function(g) { return g.id !== d.gestureId; });\n window.gadget.gestures._dismissedCallbacks.forEach(function(cb) { try { cb(d.gestureId); } catch(e) {} });\n window.__rerenderGadget && window.__rerenderGadget();\n }\n if (d.type === 'gadget-gesture-sync') {\n window.gadget.gestures.active = d.gestures || [];\n window.__rerenderGadget && window.__rerenderGadget();\n }\n\n // Anchor rect request from host\n if (d.type === 'gadget-request-anchor-rect' && d.selector) {\n try {\n var el = document.querySelector(d.selector);\n if (el) {\n var rect = el.getBoundingClientRect();\n window.parent.postMessage({\n type: 'gadget-anchor-rect',\n selector: d.selector,\n rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n }, '*');\n }\n } catch(e) {}\n }\n });`\n : '';\n\n // When state is enabled, pass state prop alongside data and viewport\n const chatPropFragment = chatEnabled ? ', chat: window.gadget.chat' : '';\n const contextPropFragment = contextEnabled ? ', context: window.gadget.context' : '';\n const roomPropFragment = roomEnabled\n ? ', room: window.gadget.room, roomChat: window.gadget.roomChat, gestures: window.gadget.gestures'\n : '';\n const breakoutPropFragment =\n ', breakout: { active: window.gadget.breakout._active, originalRect: window.gadget.breakout._originalRect, request: window.gadget.breakout.request, exit: window.gadget.breakout.exit }';\n const componentProps = stateEnabled\n ? `{ data: window.__GADGET_DATA__, viewport: window.__GADGET_VIEWPORT__, state: window.gadget.state ? { shared: window.gadget.state.shared, user: window.gadget.state.user } : undefined, userId: window.gadget.state ? window.gadget.state.userId : undefined${chatPropFragment}${contextPropFragment}${breakoutPropFragment}${roomPropFragment} }`\n : `{ data: window.__GADGET_DATA__, viewport: window.__GADGET_VIEWPORT__${chatPropFragment}${contextPropFragment}${breakoutPropFragment}${roomPropFragment} }`;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <script src=\"https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js\"></script>\n <script src=\"https://cdn.tailwindcss.com\"></script>\n${libraryScripts}\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n html, body { background: transparent; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; min-height: 100%; }\n #root { min-height: 100vh; }\n .gadget-error {\n padding: 16px;\n background: #fef2f2;\n border: 1px solid #fecaca;\n border-radius: 8px;\n color: #991b1b;\n font-family: monospace;\n font-size: 13px;\n white-space: pre-wrap;\n word-break: break-word;\n }\n .gadget-error-title {\n font-weight: 600;\n margin-bottom: 8px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n </style>\n</head>\n<body>\n <div id=\"root\"></div>\n <script>\n window.__GADGET_DATA__ = ${serializedData};\n window.__GADGET_VIEWPORT__ = '${viewport}';\n\n window.gadget = {\n data: window.__GADGET_DATA__,\n assets: ${serializedAssets},\n\n breakout: {\n _active: false,\n _originalRect: null,\n request: function() {\n if (window.gadget.breakout._active) return;\n window.gadget.breakout._active = true;\n window.parent.postMessage({ type: 'gadget-request-breakout' }, '*');\n window.__rerenderGadget && window.__rerenderGadget();\n },\n exit: function() {\n if (!window.gadget.breakout._active) return;\n window.gadget.breakout._active = false;\n window.gadget.breakout._originalRect = null;\n window.parent.postMessage({ type: 'gadget-exit-breakout' }, '*');\n window.__rerenderGadget();\n },\n },\n\n callAction: function(input) {\n var requestId = Math.random().toString(36).slice(2) + Date.now().toString(36);\n return new Promise(function(resolve, reject) {\n var handler = function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-action-response' && d.requestId === requestId) {\n window.removeEventListener('message', handler);\n if (d.error) reject(new Error(d.error));\n else resolve(d.result);\n }\n };\n window.addEventListener('message', handler);\n setTimeout(function() {\n window.removeEventListener('message', handler);\n reject(new Error('Action timed out'));\n }, 30000);\n window.parent.postMessage({ type: 'gadget-action-request', requestId: requestId, input: input }, '*');\n });\n },\n };\n${stateBridgeScript}\n${chatBridgeScript}\n${contextBridgeScript}\n${roomBridgeScript}\n\n window.__gadgetRoot = null;\n window.__gadgetComponent = null;\n\n window.__rerenderGadget = function() {\n if (window.__gadgetRoot && window.__gadgetComponent) {\n var C = window.__gadgetComponent;\n var EB = window.__gadgetErrorBoundary;\n window.__gadgetRoot.render(\n React.createElement(EB, null, React.createElement(C, ${componentProps}))\n );\n }\n };\n\n window.addEventListener('message', function(event) {\n var d = event.data;\n if (d && d.type === 'gadget-set-data') {\n window.__GADGET_DATA__ = d.data;\n window.gadget.data = d.data;\n window.__rerenderGadget();\n }\n if (d && d.type === 'gadget-breakout-started') {\n var wasActive = window.gadget.breakout._active;\n window.gadget.breakout._active = true;\n window.gadget.breakout._originalRect = d.originalRect || null;\n if (!wasActive) window.__rerenderGadget();\n }\n if (d && d.type === 'gadget-update-component' && d.code) {\n try {\n var compiled = Babel.transform(d.code, { presets: ['react'] }).code;\n var fn = new Function('React', 'useState', 'useEffect', 'useCallback', 'useMemo', 'useRef',\n compiled + '\\\\nreturn typeof Gadget !== \"undefined\" ? Gadget : null;');\n var NewComponent = fn(React, React.useState, React.useEffect, React.useCallback, React.useMemo, React.useRef);\n if (NewComponent) {\n window.__gadgetComponent = NewComponent;\n if (window.__gadgetErrorBoundaryInstance) {\n window.__gadgetErrorBoundaryInstance.setState({ error: null });\n }\n window.__rerenderGadget();\n }\n } catch (err) {\n console.error('[gadget-hmr] Component update failed:', err);\n }\n }\n });\n </script>\n <script type=\"text/babel\" data-type=\"module\">\n const { useState, useEffect, useCallback, useMemo, useRef } = React;\n\n class ErrorBoundary extends React.Component {\n constructor(props) {\n super(props);\n this.state = { error: null };\n window.__gadgetErrorBoundaryInstance = this;\n }\n static getDerivedStateFromError(error) {\n return { error };\n }\n render() {\n if (this.state.error) {\n return React.createElement('div', { className: 'gadget-error' },\n React.createElement('div', { className: 'gadget-error-title' }, 'Runtime Error'),\n this.state.error.message\n );\n }\n return this.props.children;\n }\n }\n window.__gadgetErrorBoundary = ErrorBoundary;\n\n try {\n ${escapedCode}\n\n const ComponentToRender = typeof Gadget !== 'undefined' ? Gadget : null;\n\n if (ComponentToRender) {\n window.__gadgetComponent = ComponentToRender;\n const root = ReactDOM.createRoot(document.getElementById('root'));\n window.__gadgetRoot = root;\n root.render(\n <ErrorBoundary>\n <ComponentToRender data={window.__GADGET_DATA__} viewport={window.__GADGET_VIEWPORT__}${stateEnabled ? ' state={window.gadget.state ? { shared: window.gadget.state.shared, user: window.gadget.state.user } : undefined} userId={window.gadget.state ? window.gadget.state.userId : undefined}' : ''}${chatEnabled ? ' chat={window.gadget.chat}' : ''}${contextEnabled ? ' context={window.gadget.context}' : ''}${roomEnabled ? ' room={window.gadget.room} roomChat={window.gadget.roomChat} gestures={window.gadget.gestures}' : ''} breakout={{ active: window.gadget.breakout._active, originalRect: window.gadget.breakout._originalRect, request: window.gadget.breakout.request, exit: window.gadget.breakout.exit }} />\n </ErrorBoundary>\n );\n } else {\n document.getElementById('root').innerHTML =\n '<div class=\"gadget-error\"><div class=\"gadget-error-title\">No component found</div>Define a function called Gadget.</div>';\n }\n } catch (err) {\n document.getElementById('root').innerHTML =\n '<div class=\"gadget-error\"><div class=\"gadget-error-title\">Error</div>' +\n err.message.replace(/</g, '&lt;').replace(/>/g, '&gt;') +\n '</div>';\n }\n\n const rootEl = document.getElementById('root');\n const observer = new ResizeObserver(() => {\n window.parent.postMessage({\n type: 'gadget-resize',\n height: rootEl.scrollHeight,\n }, '*');\n });\n observer.observe(rootEl);\n </script>\n</body>\n</html>`;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["jsx"]
7
7
  }