@yak-io/react 0.12.2 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,6 +37,12 @@ export type YakProviderProps = {
37
37
  onRedirect?: (path: string) => void;
38
38
  /** Disable the restart session button in the header */
39
39
  disableRestartButton?: boolean;
40
+ /**
41
+ * Privacy opt-out: stop sending any page context (URL, title, visible text)
42
+ * to the assistant. The widget still works; it just won't be aware of the
43
+ * current page, so it can't answer questions like "what is this page?".
44
+ */
45
+ disablePageContent?: boolean;
40
46
  /**
41
47
  * Trigger button configuration. Pass `false` to disable the built-in trigger
42
48
  * (useful when rendering `<YakWidget />` separately). Defaults to `false`.
@@ -60,5 +66,5 @@ export type YakProviderProps = {
60
66
  * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers
61
67
  * access both surfaces via `useYak()`.
62
68
  */
63
- export declare function YakProvider({ appId, origin, mode, getConfig, onToolCall, theme, onRedirect, disableRestartButton, trigger, user, children, }: YakProviderProps): React.ReactElement;
69
+ export declare function YakProvider({ appId, origin, mode, getConfig, onToolCall, theme, onRedirect, disableRestartButton, disablePageContent, trigger, user, children, }: YakProviderProps): React.ReactElement;
64
70
  //# sourceMappingURL=YakProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"YakProvider.d.ts","sourceRoot":"","sources":["../src/YakProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,KAAK,EAEV,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAEjB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,mCAAmC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,qEAAqE;IACrE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IACxC;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,0BAA0B;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,MAAM,EACN,IAAa,EACb,SAAS,EACT,UAAU,EACV,KAAK,EACL,UAAU,EACV,oBAAoB,EACpB,OAAe,EACf,IAAI,EACJ,QAAQ,GACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CA4MvC"}
1
+ {"version":3,"file":"YakProvider.d.ts","sourceRoot":"","sources":["../src/YakProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,KAAK,EAEV,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAEjB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,mCAAmC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,qEAAqE;IACrE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IACxC;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,0BAA0B;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,MAAM,EACN,IAAa,EACb,SAAS,EACT,UAAU,EACV,KAAK,EACL,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,OAAe,EACf,IAAI,EACJ,QAAQ,GACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CA6MvC"}
package/dist/index.cjs CHANGED
@@ -96,6 +96,7 @@ function YakProvider({
96
96
  theme,
97
97
  onRedirect,
98
98
  disableRestartButton,
99
+ disablePageContent,
99
100
  trigger = false,
100
101
  user,
101
102
  children
@@ -136,7 +137,7 @@ function YakProvider({
136
137
  getConfig,
137
138
  onToolCall,
138
139
  onRedirect: resolvedRedirect,
139
- options: { disableRestartButton },
140
+ options: { disableRestartButton, disablePageContent },
140
141
  onToolCallComplete: handleToolCallComplete,
141
142
  user
142
143
  });
@@ -161,7 +162,7 @@ function YakProvider({
161
162
  onToolCall,
162
163
  theme,
163
164
  onRedirect: resolvedRedirect,
164
- options: { disableRestartButton },
165
+ options: { disableRestartButton, disablePageContent },
165
166
  onToolCallComplete: handleToolCallComplete,
166
167
  user
167
168
  });
@@ -178,6 +179,7 @@ function YakProvider({
178
179
  theme,
179
180
  resolvedRedirect,
180
181
  disableRestartButton,
182
+ disablePageContent,
181
183
  embed,
182
184
  handleToolCallComplete,
183
185
  user
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/context.ts", "../src/YakProvider.tsx", "../src/YakWidget.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nexport type {\n ChatConfigProvider,\n GraphQLRequest,\n RESTRequest,\n Theme,\n ThemeColors,\n ToolAdapter,\n ToolCallEvent,\n ToolCallHandler,\n TriggerButtonConfig,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n WidgetPosition,\n YakServerAdapterConfig,\n YakToolset,\n} from \"@yak-io/javascript\";\n// Re-export useful types and constants from @yak-io/javascript for consumers\nexport {\n createYakServerAdapter,\n createYakToolset,\n disableYakLogging,\n enableYakLogging,\n isYakLoggingEnabled,\n} from \"@yak-io/javascript\";\nexport type { ToolCallEventHandler, YakConfig, YakContextValue } from \"./context.js\";\n// Public API - only export what consumers need\nexport { useYak, useYakToolEvent } from \"./context.js\";\nexport type { YakProviderProps } from \"./YakProvider.js\";\nexport { YakProvider } from \"./YakProvider.js\";\nexport type { YakWidgetProps } from \"./YakWidget.js\";\nexport { YakWidget } from \"./YakWidget.js\";\n", "\"use client\";\n\nimport type {\n ChatConfig,\n Theme,\n ToolCallEvent,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n} from \"@yak-io/javascript\";\nimport { createContext, useContext, useEffect, useRef } from \"react\";\n\n/**\n * Configuration for the yak provider\n */\nexport type YakConfig = {\n appId: string;\n theme?: Theme;\n chatConfig?: ChatConfig | null;\n onRedirect?: (path: string) => void;\n};\n\n/**\n * Listener function for tool call events\n */\nexport type ToolCallEventHandler = (event: ToolCallEvent) => void;\n\n/**\n * Public API for controlling the Yak widget \u2014 chat + voice combined.\n * This is what consumers get from useYak().\n */\nexport type YakContextValue = {\n /** Which modes are exposed: \"chat\", \"voice\", or \"both\". */\n mode: WidgetMode;\n\n // \u2500\u2500 Chat \u2500\u2500\n /** Whether the chat widget is currently open */\n isOpen: boolean;\n /** Whether the iframe is ready to receive messages */\n isReady: boolean;\n /**\n * Whether the chat is opening but not yet interactive (`isOpen && !isReady`).\n * Drive a custom loading state off this instead of re-deriving it.\n */\n chatLoading: boolean;\n /** Open the chat widget */\n open: () => void;\n /** Close the chat widget */\n close: () => void;\n /** Open the chat widget and trigger a specific prompt */\n openWithPrompt: (prompt: string) => void;\n /** Subscribe to tool call completion events */\n subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;\n\n // \u2500\u2500 Voice \u2500\u2500\n /** Current voice state machine snapshot. `idle` when mode === \"chat\". */\n voiceMachine: VoiceMachine;\n /** Convenience: `voiceMachine.state`. */\n voiceState: VoiceState;\n /** Convenience: error message when voiceState === \"error\". */\n voiceErrorMessage: string | undefined;\n /** Whether a voice session is currently live (connecting/listening/thinking/speaking). */\n voiceIsActive: boolean;\n /** Whether the voice session is still connecting (`voiceState === \"connecting\"`). */\n voiceLoading: boolean;\n /** Start a voice session. Must be invoked from a user gesture. */\n voiceStart: () => Promise<void>;\n /** Stop the current voice session. */\n voiceStop: () => Promise<void>;\n /** Toggle: start if idle/error, stop if active. */\n voiceToggle: () => Promise<void>;\n};\n\n/**\n * Internal context with additional methods for widget internals.\n * Not exposed to consumers - only used by provider internals.\n */\nexport type YakInternalContextValue = YakContextValue & {\n /** Get the iframe origin URL (determined by environment) */\n getIframeOrigin: () => string;\n /** Theme passed to YakProvider \u2014 used by YakWidget to mirror panel placement. */\n theme: Theme | undefined;\n};\n\nexport const YakContext = createContext<YakInternalContextValue | null>(null);\n\n/**\n * Hook to access the Yak widget API \u2014 chat and voice.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { open, voiceToggle, voiceState } = useYak();\n * return (\n * <div>\n * <button onClick={open}>Open chat</button>\n * <button onClick={voiceToggle}>{voiceState === \"idle\" ? \"Start voice\" : \"Stop voice\"}</button>\n * </div>\n * );\n * }\n * ```\n *\n * @throws {Error} if used outside YakProvider\n */\nexport function useYak(): YakContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYak must be used within YakProvider\");\n }\n return {\n mode: context.mode,\n isOpen: context.isOpen,\n isReady: context.isReady,\n chatLoading: context.chatLoading,\n open: context.open,\n close: context.close,\n openWithPrompt: context.openWithPrompt,\n subscribeToToolEvents: context.subscribeToToolEvents,\n voiceMachine: context.voiceMachine,\n voiceState: context.voiceState,\n voiceErrorMessage: context.voiceErrorMessage,\n voiceIsActive: context.voiceIsActive,\n voiceLoading: context.voiceLoading,\n voiceStart: context.voiceStart,\n voiceStop: context.voiceStop,\n voiceToggle: context.voiceToggle,\n };\n}\n\n/**\n * Internal hook for components that need full context access.\n * Not exported publicly.\n */\nexport function useYakInternal(): YakInternalContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakInternal must be used within YakProvider\");\n }\n return context;\n}\n\n/**\n * Hook to subscribe to tool call completion events.\n * Useful for page-level cache invalidation when chatbot tools modify data.\n *\n * The handler receives an event with:\n * - `name`: The tool name that was called (e.g., \"order.cancel\")\n * - `args`: The arguments passed to the tool\n * - `ok`: Whether the call succeeded\n * - `result`: The result (if ok is true)\n * - `error`: The error message (if ok is false)\n *\n * @example\n * ```tsx\n * function PlanPage({ planId }: { planId: string }) {\n * const utils = trpc.useUtils();\n *\n * useYakToolEvent((event) => {\n * // Only invalidate if this tool touched plans\n * if (event.ok && event.name.startsWith(\"plan.\")) {\n * utils.plan.get.invalidate({ id: planId });\n * utils.planItem.list.invalidate({ planId });\n * }\n * });\n *\n * // ... rest of component\n * }\n * ```\n *\n * @param handler - Function called after each tool call completes\n * @throws {Error} if used outside YakProvider\n */\nexport function useYakToolEvent(handler: ToolCallEventHandler): void {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakToolEvent must be used within YakProvider\");\n }\n\n // Use ref to always have latest handler without re-subscribing\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n // Wrap handler to use ref (stable reference)\n const stableHandler: ToolCallEventHandler = (event) => {\n handlerRef.current(event);\n };\n\n return context.subscribeToToolEvents(stableHandler);\n }, [context]);\n}\n", "\"use client\";\n\nimport {\n type ChatConfigProvider,\n INITIAL_VOICE_MACHINE,\n logger,\n type Theme,\n type ToolCallEvent,\n type ToolCallHandler,\n type TriggerButtonConfig,\n type UserIdentity,\n type VoiceMachine,\n type WidgetMode,\n YakEmbed,\n} from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type ToolCallEventHandler, YakContext } from \"./context.js\";\n\n/**\n * Props for YakProvider\n */\nexport type YakProviderProps = {\n /** App identifier in the yak SaaS */\n appId: string;\n /**\n * Override the origin the chat/voice runtime connects to. Defaults to\n * `https://chat.yak.io`. Read once when the provider mounts; most integrators\n * never set this.\n */\n origin?: string;\n /**\n * Which experiences this widget exposes.\n * \"chat\" \u2014 chat only (iframe).\n * \"voice\" \u2014 voice only (WebRTC).\n * \"both\" \u2014 both, sharing one trigger pill.\n * Default: \"chat\".\n */\n mode?: WidgetMode;\n /**\n * Provider function for chat configuration (routes + tools).\n * The consuming platform decides how to get the config (static, fetch, etc.)\n * Called when the chat is opened or when a voice session starts.\n */\n getConfig?: ChatConfigProvider;\n /**\n * Handler for tool calls from the chat or voice runtime.\n * The consuming platform decides how to execute (browser, server fetch, etc.)\n */\n onToolCall?: ToolCallHandler;\n /** Optional theme configuration */\n theme?: Theme;\n /** Optional redirect handler (defaults to window.location.assign) */\n onRedirect?: (path: string) => void;\n /** Disable the restart session button in the header */\n disableRestartButton?: boolean;\n /**\n * Trigger button configuration. Pass `false` to disable the built-in trigger\n * (useful when rendering `<YakWidget />` separately). Defaults to `false`.\n */\n trigger?: boolean | TriggerButtonConfig;\n /**\n * Signed end-user identity for server-side conversation persistence.\n *\n * Compute the `hash` on your backend with\n * `HMAC-SHA256(application.apiSecret, user.id)` and pass it down to the\n * browser. When supplied, the widget stores conversations server-side and\n * shows a history pane so end-users can resume past chats. When omitted,\n * the widget runs in anonymous mode (no persistence).\n */\n user?: UserIdentity;\n /** Children components */\n children: React.ReactNode;\n};\n\n/**\n * YakProvider sets up the unified chat + voice runtime. All DOM rendering\n * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers\n * access both surfaces via `useYak()`.\n */\nexport function YakProvider({\n appId,\n origin,\n mode = \"chat\",\n getConfig,\n onToolCall,\n theme,\n onRedirect,\n disableRestartButton,\n trigger = false,\n user,\n children,\n}: YakProviderProps): React.ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n const [isReady, setIsReady] = useState(false);\n const [voiceMachine, setVoiceMachine] = useState<VoiceMachine>(INITIAL_VOICE_MACHINE);\n\n // Store event subscribers for tool call events\n const toolEventSubscribersRef = useRef<Set<ToolCallEventHandler>>(new Set());\n\n // Handler that notifies all subscribers when a tool call completes\n const handleToolCallComplete = useCallback((event: ToolCallEvent) => {\n logger.debug(\"Tool call completed, notifying subscribers:\", {\n name: event.name,\n ok: event.ok,\n subscriberCount: toolEventSubscribersRef.current.size,\n });\n for (const handler of toolEventSubscribersRef.current) {\n try {\n handler(event);\n } catch (err) {\n logger.warn(\"Error in tool event subscriber:\", err);\n }\n }\n }, []);\n\n // Resolve redirect handler\n const resolvedRedirect = useMemo(() => {\n if (onRedirect) return onRedirect;\n if (typeof window === \"undefined\") return undefined;\n return (path: string) => {\n window.location.assign(path);\n };\n }, [onRedirect]);\n\n // Initialize YakEmbed \u2014 created once, never recreated\n const embedRef = useRef<YakEmbed | null>(null);\n if (!embedRef.current) {\n embedRef.current = new YakEmbed({\n appId,\n origin,\n mode,\n theme,\n trigger,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n }\n const embed = embedRef.current;\n\n // Mount/unmount embed and subscribe to chat + voice state changes\n useEffect(() => {\n embed.mount();\n\n const unsubscribeChat = embed.onStateChange((state) => {\n setIsOpen(state.isOpen);\n setIsReady(state.isReady);\n });\n const unsubscribeVoice = embed.onVoiceStateChange((m) => setVoiceMachine(m));\n\n return () => {\n unsubscribeChat();\n unsubscribeVoice();\n embed.destroy();\n };\n }, [embed]);\n\n // Update embed config when props change. Chat config goes via the client;\n // voice config goes via the voice session.\n useEffect(() => {\n embed.getClient().updateConfig({\n appId,\n onToolCall,\n theme,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n embed.getVoiceSession()?.updateConfig({\n appId,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n });\n }, [\n appId,\n getConfig,\n onToolCall,\n theme,\n resolvedRedirect,\n disableRestartButton,\n embed,\n handleToolCallComplete,\n user,\n ]);\n\n // Fetch chat config when the chat is opened\n useEffect(() => {\n if (typeof window === \"undefined\" || !isOpen || !getConfig) return;\n\n logger.debug(\"Getting chat config\");\n\n let cancelled = false;\n\n (async () => {\n try {\n const config = await getConfig();\n if (!cancelled) {\n logger.debug(\n `Chat config loaded with ${config.tools?.tools.length ?? 0} tools and ${config.routes?.routes.length ?? 0} routes`\n );\n embed.getClient().updateConfig({ chatConfig: config });\n }\n } catch (err) {\n logger.warn(\"Error getting chat config:\", err);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [getConfig, isOpen, embed]);\n\n // Chat methods\n const open = useCallback(() => embed.open(), [embed]);\n const close = useCallback(() => embed.close(), [embed]);\n const openWithPrompt = useCallback((prompt: string) => embed.openWithPrompt(prompt), [embed]);\n\n // Voice methods\n const voiceStart = useCallback(async () => {\n try {\n await embed.voiceStart();\n } catch (err) {\n logger.warn(\"Voice start failed\", err);\n }\n }, [embed]);\n const voiceStop = useCallback(() => embed.voiceStop(), [embed]);\n const voiceToggle = useCallback(() => embed.voiceToggle(), [embed]);\n\n // Subscribe to tool call completion events\n const subscribeToToolEvents = useCallback((handler: ToolCallEventHandler) => {\n toolEventSubscribersRef.current.add(handler);\n logger.debug(\"Tool event subscriber added, total:\", toolEventSubscribersRef.current.size);\n\n return () => {\n toolEventSubscribersRef.current.delete(handler);\n logger.debug(\"Tool event subscriber removed, total:\", toolEventSubscribersRef.current.size);\n };\n }, []);\n\n // Expose iframe origin for YakWidget\n const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);\n\n const voiceState = voiceMachine.state;\n const voiceIsActive = voiceState !== \"idle\" && voiceState !== \"error\";\n const chatLoading = isOpen && !isReady;\n const voiceLoading = voiceState === \"connecting\";\n\n const contextValue = useMemo(\n () => ({\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceErrorMessage: voiceMachine.errorMessage,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n }),\n [\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n ]\n );\n\n return <YakContext.Provider value={contextValue}>{children}</YakContext.Provider>;\n}\n", "\"use client\";\n\nimport type { VoiceState, WidgetMode } from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useYakInternal } from \"./context.js\";\n\n/**\n * Props for YakWidget\n */\nexport type YakWidgetProps = {\n /** Override the mode from the provider. */\n mode?: WidgetMode;\n /** Custom button colors for light mode */\n lightButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n /** Custom button colors for dark mode */\n darkButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n};\n\nconst VOICE_ARIA: Record<VoiceState, string> = {\n idle: \"Start voice mode\",\n connecting: \"Connecting voice session\",\n listening: \"Voice listening \u2014 tap to stop\",\n thinking: \"Voice thinking \u2014 tap to stop\",\n speaking: \"Voice speaking \u2014 tap to stop\",\n error: \"Voice error \u2014 tap to retry\",\n};\n\nfunction MessageCircleIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n </svg>\n );\n}\n\nfunction AudioLinesIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\nfunction StopIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width={20} height={20} aria-hidden=\"true\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction VoiceIcon({ state }: { state: VoiceState }): React.ReactElement {\n if (state === \"connecting\") {\n return <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />;\n }\n if (state === \"listening\" || state === \"speaking\" || state === \"thinking\") {\n return <StopIcon />;\n }\n return <AudioLinesIcon />;\n}\n\nfunction buildButtonStyle(\n lightButton: YakWidgetProps[\"lightButton\"],\n darkButton: YakWidgetProps[\"darkButton\"]\n): React.CSSProperties & Record<string, string | undefined> {\n const style: React.CSSProperties & Record<string, string | undefined> = {};\n if (lightButton?.background) style[\"--yak-btn-light-bg\"] = lightButton.background;\n if (lightButton?.color) style[\"--yak-btn-light-color\"] = lightButton.color;\n if (lightButton?.border) style[\"--yak-btn-light-border\"] = lightButton.border;\n if (darkButton?.background) style[\"--yak-btn-dark-bg\"] = darkButton.background;\n if (darkButton?.color) style[\"--yak-btn-dark-color\"] = darkButton.color;\n if (darkButton?.border) style[\"--yak-btn-dark-border\"] = darkButton.border;\n return style;\n}\n\nfunction buildButtonClasses(\n colorMode: \"light\" | \"dark\" | \"system\" | undefined,\n hasLightCustom: string | boolean | undefined,\n hasDarkCustom: string | boolean | undefined\n): string {\n const colorModeClass =\n colorMode === \"light\" ? \"yak-widget-light\" : colorMode === \"dark\" ? \"yak-widget-dark\" : \"\";\n\n let customButtonClass = \"\";\n if (colorMode === \"light\" && hasLightCustom) {\n customButtonClass = \"yak-widget-custom-light\";\n } else if (colorMode === \"dark\" && hasDarkCustom) {\n customButtonClass = \"yak-widget-custom-dark\";\n }\n\n return [\"yak-widget-trigger\", colorModeClass, customButtonClass].filter(Boolean).join(\" \");\n}\n\n/**\n * YakWidget renders a fixed-position launcher pill. The logo sits on the\n * left; one or two icon buttons sit on the right based on `mode`. Trigger\n * CSS is injected by YakEmbed (via YakProvider) \u2014 this component only\n * provides the React markup using those shared class names.\n */\nexport function YakWidget({\n mode,\n lightButton,\n darkButton,\n}: YakWidgetProps = {}): React.ReactElement {\n const ctx = useYakInternal();\n const resolvedMode = mode ?? ctx.mode;\n const position = ctx.theme?.position ?? \"bottom-left\";\n const colorMode = ctx.theme?.colorMode;\n const logoUrl = `${ctx.getIframeOrigin()}/logo.svg`;\n\n const showChat = resolvedMode === \"chat\" || resolvedMode === \"both\";\n const showVoice = resolvedMode === \"voice\" || resolvedMode === \"both\";\n\n // Consume the shipped loading flags rather than re-deriving them here.\n const chatLoading = ctx.chatLoading;\n const voiceConnecting = ctx.voiceLoading;\n\n const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;\n const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;\n\n const buttonStyle = buildButtonStyle(lightButton, darkButton);\n const buttonClasses = buildButtonClasses(colorMode, hasLightCustom, hasDarkCustom);\n\n return (\n <div\n className={buttonClasses}\n style={Object.keys(buttonStyle).length > 0 ? buttonStyle : undefined}\n data-position={position}\n data-mode={resolvedMode}\n data-has-light-custom={hasLightCustom || undefined}\n data-has-dark-custom={hasDarkCustom || undefined}\n >\n <div className=\"yak-widget-icon-bg\">\n <img src={logoUrl} alt=\"\" width={24} height={24} className=\"yak-widget-icon\" />\n </div>\n\n {showChat && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"chat\"\n aria-label={chatLoading ? \"Loading chat\" : \"Open chat\"}\n disabled={chatLoading}\n onClick={ctx.open}\n >\n {chatLoading ? (\n <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />\n ) : (\n <MessageCircleIcon />\n )}\n </button>\n )}\n\n {showVoice && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"voice\"\n data-state={ctx.voiceState}\n aria-label={VOICE_ARIA[ctx.voiceState]}\n disabled={voiceConnecting}\n onClick={() => {\n void ctx.voiceToggle();\n }}\n >\n <VoiceIcon state={ctx.voiceState} />\n </button>\n )}\n </div>\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\";\n\nexport type {\n ChatConfigProvider,\n GraphQLRequest,\n RESTRequest,\n Theme,\n ThemeColors,\n ToolAdapter,\n ToolCallEvent,\n ToolCallHandler,\n TriggerButtonConfig,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n WidgetPosition,\n YakServerAdapterConfig,\n YakToolset,\n} from \"@yak-io/javascript\";\n// Re-export useful types and constants from @yak-io/javascript for consumers\nexport {\n createYakServerAdapter,\n createYakToolset,\n disableYakLogging,\n enableYakLogging,\n isYakLoggingEnabled,\n} from \"@yak-io/javascript\";\nexport type { ToolCallEventHandler, YakConfig, YakContextValue } from \"./context.js\";\n// Public API - only export what consumers need\nexport { useYak, useYakToolEvent } from \"./context.js\";\nexport type { YakProviderProps } from \"./YakProvider.js\";\nexport { YakProvider } from \"./YakProvider.js\";\nexport type { YakWidgetProps } from \"./YakWidget.js\";\nexport { YakWidget } from \"./YakWidget.js\";\n", "\"use client\";\n\nimport type {\n ChatConfig,\n Theme,\n ToolCallEvent,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n} from \"@yak-io/javascript\";\nimport { createContext, useContext, useEffect, useRef } from \"react\";\n\n/**\n * Configuration for the yak provider\n */\nexport type YakConfig = {\n appId: string;\n theme?: Theme;\n chatConfig?: ChatConfig | null;\n onRedirect?: (path: string) => void;\n};\n\n/**\n * Listener function for tool call events\n */\nexport type ToolCallEventHandler = (event: ToolCallEvent) => void;\n\n/**\n * Public API for controlling the Yak widget \u2014 chat + voice combined.\n * This is what consumers get from useYak().\n */\nexport type YakContextValue = {\n /** Which modes are exposed: \"chat\", \"voice\", or \"both\". */\n mode: WidgetMode;\n\n // \u2500\u2500 Chat \u2500\u2500\n /** Whether the chat widget is currently open */\n isOpen: boolean;\n /** Whether the iframe is ready to receive messages */\n isReady: boolean;\n /**\n * Whether the chat is opening but not yet interactive (`isOpen && !isReady`).\n * Drive a custom loading state off this instead of re-deriving it.\n */\n chatLoading: boolean;\n /** Open the chat widget */\n open: () => void;\n /** Close the chat widget */\n close: () => void;\n /** Open the chat widget and trigger a specific prompt */\n openWithPrompt: (prompt: string) => void;\n /** Subscribe to tool call completion events */\n subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;\n\n // \u2500\u2500 Voice \u2500\u2500\n /** Current voice state machine snapshot. `idle` when mode === \"chat\". */\n voiceMachine: VoiceMachine;\n /** Convenience: `voiceMachine.state`. */\n voiceState: VoiceState;\n /** Convenience: error message when voiceState === \"error\". */\n voiceErrorMessage: string | undefined;\n /** Whether a voice session is currently live (connecting/listening/thinking/speaking). */\n voiceIsActive: boolean;\n /** Whether the voice session is still connecting (`voiceState === \"connecting\"`). */\n voiceLoading: boolean;\n /** Start a voice session. Must be invoked from a user gesture. */\n voiceStart: () => Promise<void>;\n /** Stop the current voice session. */\n voiceStop: () => Promise<void>;\n /** Toggle: start if idle/error, stop if active. */\n voiceToggle: () => Promise<void>;\n};\n\n/**\n * Internal context with additional methods for widget internals.\n * Not exposed to consumers - only used by provider internals.\n */\nexport type YakInternalContextValue = YakContextValue & {\n /** Get the iframe origin URL (determined by environment) */\n getIframeOrigin: () => string;\n /** Theme passed to YakProvider \u2014 used by YakWidget to mirror panel placement. */\n theme: Theme | undefined;\n};\n\nexport const YakContext = createContext<YakInternalContextValue | null>(null);\n\n/**\n * Hook to access the Yak widget API \u2014 chat and voice.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { open, voiceToggle, voiceState } = useYak();\n * return (\n * <div>\n * <button onClick={open}>Open chat</button>\n * <button onClick={voiceToggle}>{voiceState === \"idle\" ? \"Start voice\" : \"Stop voice\"}</button>\n * </div>\n * );\n * }\n * ```\n *\n * @throws {Error} if used outside YakProvider\n */\nexport function useYak(): YakContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYak must be used within YakProvider\");\n }\n return {\n mode: context.mode,\n isOpen: context.isOpen,\n isReady: context.isReady,\n chatLoading: context.chatLoading,\n open: context.open,\n close: context.close,\n openWithPrompt: context.openWithPrompt,\n subscribeToToolEvents: context.subscribeToToolEvents,\n voiceMachine: context.voiceMachine,\n voiceState: context.voiceState,\n voiceErrorMessage: context.voiceErrorMessage,\n voiceIsActive: context.voiceIsActive,\n voiceLoading: context.voiceLoading,\n voiceStart: context.voiceStart,\n voiceStop: context.voiceStop,\n voiceToggle: context.voiceToggle,\n };\n}\n\n/**\n * Internal hook for components that need full context access.\n * Not exported publicly.\n */\nexport function useYakInternal(): YakInternalContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakInternal must be used within YakProvider\");\n }\n return context;\n}\n\n/**\n * Hook to subscribe to tool call completion events.\n * Useful for page-level cache invalidation when chatbot tools modify data.\n *\n * The handler receives an event with:\n * - `name`: The tool name that was called (e.g., \"order.cancel\")\n * - `args`: The arguments passed to the tool\n * - `ok`: Whether the call succeeded\n * - `result`: The result (if ok is true)\n * - `error`: The error message (if ok is false)\n *\n * @example\n * ```tsx\n * function PlanPage({ planId }: { planId: string }) {\n * const utils = trpc.useUtils();\n *\n * useYakToolEvent((event) => {\n * // Only invalidate if this tool touched plans\n * if (event.ok && event.name.startsWith(\"plan.\")) {\n * utils.plan.get.invalidate({ id: planId });\n * utils.planItem.list.invalidate({ planId });\n * }\n * });\n *\n * // ... rest of component\n * }\n * ```\n *\n * @param handler - Function called after each tool call completes\n * @throws {Error} if used outside YakProvider\n */\nexport function useYakToolEvent(handler: ToolCallEventHandler): void {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakToolEvent must be used within YakProvider\");\n }\n\n // Use ref to always have latest handler without re-subscribing\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n // Wrap handler to use ref (stable reference)\n const stableHandler: ToolCallEventHandler = (event) => {\n handlerRef.current(event);\n };\n\n return context.subscribeToToolEvents(stableHandler);\n }, [context]);\n}\n", "\"use client\";\n\nimport {\n type ChatConfigProvider,\n INITIAL_VOICE_MACHINE,\n logger,\n type Theme,\n type ToolCallEvent,\n type ToolCallHandler,\n type TriggerButtonConfig,\n type UserIdentity,\n type VoiceMachine,\n type WidgetMode,\n YakEmbed,\n} from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type ToolCallEventHandler, YakContext } from \"./context.js\";\n\n/**\n * Props for YakProvider\n */\nexport type YakProviderProps = {\n /** App identifier in the yak SaaS */\n appId: string;\n /**\n * Override the origin the chat/voice runtime connects to. Defaults to\n * `https://chat.yak.io`. Read once when the provider mounts; most integrators\n * never set this.\n */\n origin?: string;\n /**\n * Which experiences this widget exposes.\n * \"chat\" \u2014 chat only (iframe).\n * \"voice\" \u2014 voice only (WebRTC).\n * \"both\" \u2014 both, sharing one trigger pill.\n * Default: \"chat\".\n */\n mode?: WidgetMode;\n /**\n * Provider function for chat configuration (routes + tools).\n * The consuming platform decides how to get the config (static, fetch, etc.)\n * Called when the chat is opened or when a voice session starts.\n */\n getConfig?: ChatConfigProvider;\n /**\n * Handler for tool calls from the chat or voice runtime.\n * The consuming platform decides how to execute (browser, server fetch, etc.)\n */\n onToolCall?: ToolCallHandler;\n /** Optional theme configuration */\n theme?: Theme;\n /** Optional redirect handler (defaults to window.location.assign) */\n onRedirect?: (path: string) => void;\n /** Disable the restart session button in the header */\n disableRestartButton?: boolean;\n /**\n * Privacy opt-out: stop sending any page context (URL, title, visible text)\n * to the assistant. The widget still works; it just won't be aware of the\n * current page, so it can't answer questions like \"what is this page?\".\n */\n disablePageContent?: boolean;\n /**\n * Trigger button configuration. Pass `false` to disable the built-in trigger\n * (useful when rendering `<YakWidget />` separately). Defaults to `false`.\n */\n trigger?: boolean | TriggerButtonConfig;\n /**\n * Signed end-user identity for server-side conversation persistence.\n *\n * Compute the `hash` on your backend with\n * `HMAC-SHA256(application.apiSecret, user.id)` and pass it down to the\n * browser. When supplied, the widget stores conversations server-side and\n * shows a history pane so end-users can resume past chats. When omitted,\n * the widget runs in anonymous mode (no persistence).\n */\n user?: UserIdentity;\n /** Children components */\n children: React.ReactNode;\n};\n\n/**\n * YakProvider sets up the unified chat + voice runtime. All DOM rendering\n * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers\n * access both surfaces via `useYak()`.\n */\nexport function YakProvider({\n appId,\n origin,\n mode = \"chat\",\n getConfig,\n onToolCall,\n theme,\n onRedirect,\n disableRestartButton,\n disablePageContent,\n trigger = false,\n user,\n children,\n}: YakProviderProps): React.ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n const [isReady, setIsReady] = useState(false);\n const [voiceMachine, setVoiceMachine] = useState<VoiceMachine>(INITIAL_VOICE_MACHINE);\n\n // Store event subscribers for tool call events\n const toolEventSubscribersRef = useRef<Set<ToolCallEventHandler>>(new Set());\n\n // Handler that notifies all subscribers when a tool call completes\n const handleToolCallComplete = useCallback((event: ToolCallEvent) => {\n logger.debug(\"Tool call completed, notifying subscribers:\", {\n name: event.name,\n ok: event.ok,\n subscriberCount: toolEventSubscribersRef.current.size,\n });\n for (const handler of toolEventSubscribersRef.current) {\n try {\n handler(event);\n } catch (err) {\n logger.warn(\"Error in tool event subscriber:\", err);\n }\n }\n }, []);\n\n // Resolve redirect handler\n const resolvedRedirect = useMemo(() => {\n if (onRedirect) return onRedirect;\n if (typeof window === \"undefined\") return undefined;\n return (path: string) => {\n window.location.assign(path);\n };\n }, [onRedirect]);\n\n // Initialize YakEmbed \u2014 created once, never recreated\n const embedRef = useRef<YakEmbed | null>(null);\n if (!embedRef.current) {\n embedRef.current = new YakEmbed({\n appId,\n origin,\n mode,\n theme,\n trigger,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton, disablePageContent },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n }\n const embed = embedRef.current;\n\n // Mount/unmount embed and subscribe to chat + voice state changes\n useEffect(() => {\n embed.mount();\n\n const unsubscribeChat = embed.onStateChange((state) => {\n setIsOpen(state.isOpen);\n setIsReady(state.isReady);\n });\n const unsubscribeVoice = embed.onVoiceStateChange((m) => setVoiceMachine(m));\n\n return () => {\n unsubscribeChat();\n unsubscribeVoice();\n embed.destroy();\n };\n }, [embed]);\n\n // Update embed config when props change. Chat config goes via the client;\n // voice config goes via the voice session.\n useEffect(() => {\n embed.getClient().updateConfig({\n appId,\n onToolCall,\n theme,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton, disablePageContent },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n embed.getVoiceSession()?.updateConfig({\n appId,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n });\n }, [\n appId,\n getConfig,\n onToolCall,\n theme,\n resolvedRedirect,\n disableRestartButton,\n disablePageContent,\n embed,\n handleToolCallComplete,\n user,\n ]);\n\n // Fetch chat config when the chat is opened\n useEffect(() => {\n if (typeof window === \"undefined\" || !isOpen || !getConfig) return;\n\n logger.debug(\"Getting chat config\");\n\n let cancelled = false;\n\n (async () => {\n try {\n const config = await getConfig();\n if (!cancelled) {\n logger.debug(\n `Chat config loaded with ${config.tools?.tools.length ?? 0} tools and ${config.routes?.routes.length ?? 0} routes`\n );\n embed.getClient().updateConfig({ chatConfig: config });\n }\n } catch (err) {\n logger.warn(\"Error getting chat config:\", err);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [getConfig, isOpen, embed]);\n\n // Chat methods\n const open = useCallback(() => embed.open(), [embed]);\n const close = useCallback(() => embed.close(), [embed]);\n const openWithPrompt = useCallback((prompt: string) => embed.openWithPrompt(prompt), [embed]);\n\n // Voice methods\n const voiceStart = useCallback(async () => {\n try {\n await embed.voiceStart();\n } catch (err) {\n logger.warn(\"Voice start failed\", err);\n }\n }, [embed]);\n const voiceStop = useCallback(() => embed.voiceStop(), [embed]);\n const voiceToggle = useCallback(() => embed.voiceToggle(), [embed]);\n\n // Subscribe to tool call completion events\n const subscribeToToolEvents = useCallback((handler: ToolCallEventHandler) => {\n toolEventSubscribersRef.current.add(handler);\n logger.debug(\"Tool event subscriber added, total:\", toolEventSubscribersRef.current.size);\n\n return () => {\n toolEventSubscribersRef.current.delete(handler);\n logger.debug(\"Tool event subscriber removed, total:\", toolEventSubscribersRef.current.size);\n };\n }, []);\n\n // Expose iframe origin for YakWidget\n const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);\n\n const voiceState = voiceMachine.state;\n const voiceIsActive = voiceState !== \"idle\" && voiceState !== \"error\";\n const chatLoading = isOpen && !isReady;\n const voiceLoading = voiceState === \"connecting\";\n\n const contextValue = useMemo(\n () => ({\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceErrorMessage: voiceMachine.errorMessage,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n }),\n [\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n ]\n );\n\n return <YakContext.Provider value={contextValue}>{children}</YakContext.Provider>;\n}\n", "\"use client\";\n\nimport type { VoiceState, WidgetMode } from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useYakInternal } from \"./context.js\";\n\n/**\n * Props for YakWidget\n */\nexport type YakWidgetProps = {\n /** Override the mode from the provider. */\n mode?: WidgetMode;\n /** Custom button colors for light mode */\n lightButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n /** Custom button colors for dark mode */\n darkButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n};\n\nconst VOICE_ARIA: Record<VoiceState, string> = {\n idle: \"Start voice mode\",\n connecting: \"Connecting voice session\",\n listening: \"Voice listening \u2014 tap to stop\",\n thinking: \"Voice thinking \u2014 tap to stop\",\n speaking: \"Voice speaking \u2014 tap to stop\",\n error: \"Voice error \u2014 tap to retry\",\n};\n\nfunction MessageCircleIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n </svg>\n );\n}\n\nfunction AudioLinesIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\nfunction StopIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width={20} height={20} aria-hidden=\"true\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction VoiceIcon({ state }: { state: VoiceState }): React.ReactElement {\n if (state === \"connecting\") {\n return <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />;\n }\n if (state === \"listening\" || state === \"speaking\" || state === \"thinking\") {\n return <StopIcon />;\n }\n return <AudioLinesIcon />;\n}\n\nfunction buildButtonStyle(\n lightButton: YakWidgetProps[\"lightButton\"],\n darkButton: YakWidgetProps[\"darkButton\"]\n): React.CSSProperties & Record<string, string | undefined> {\n const style: React.CSSProperties & Record<string, string | undefined> = {};\n if (lightButton?.background) style[\"--yak-btn-light-bg\"] = lightButton.background;\n if (lightButton?.color) style[\"--yak-btn-light-color\"] = lightButton.color;\n if (lightButton?.border) style[\"--yak-btn-light-border\"] = lightButton.border;\n if (darkButton?.background) style[\"--yak-btn-dark-bg\"] = darkButton.background;\n if (darkButton?.color) style[\"--yak-btn-dark-color\"] = darkButton.color;\n if (darkButton?.border) style[\"--yak-btn-dark-border\"] = darkButton.border;\n return style;\n}\n\nfunction buildButtonClasses(\n colorMode: \"light\" | \"dark\" | \"system\" | undefined,\n hasLightCustom: string | boolean | undefined,\n hasDarkCustom: string | boolean | undefined\n): string {\n const colorModeClass =\n colorMode === \"light\" ? \"yak-widget-light\" : colorMode === \"dark\" ? \"yak-widget-dark\" : \"\";\n\n let customButtonClass = \"\";\n if (colorMode === \"light\" && hasLightCustom) {\n customButtonClass = \"yak-widget-custom-light\";\n } else if (colorMode === \"dark\" && hasDarkCustom) {\n customButtonClass = \"yak-widget-custom-dark\";\n }\n\n return [\"yak-widget-trigger\", colorModeClass, customButtonClass].filter(Boolean).join(\" \");\n}\n\n/**\n * YakWidget renders a fixed-position launcher pill. The logo sits on the\n * left; one or two icon buttons sit on the right based on `mode`. Trigger\n * CSS is injected by YakEmbed (via YakProvider) \u2014 this component only\n * provides the React markup using those shared class names.\n */\nexport function YakWidget({\n mode,\n lightButton,\n darkButton,\n}: YakWidgetProps = {}): React.ReactElement {\n const ctx = useYakInternal();\n const resolvedMode = mode ?? ctx.mode;\n const position = ctx.theme?.position ?? \"bottom-left\";\n const colorMode = ctx.theme?.colorMode;\n const logoUrl = `${ctx.getIframeOrigin()}/logo.svg`;\n\n const showChat = resolvedMode === \"chat\" || resolvedMode === \"both\";\n const showVoice = resolvedMode === \"voice\" || resolvedMode === \"both\";\n\n // Consume the shipped loading flags rather than re-deriving them here.\n const chatLoading = ctx.chatLoading;\n const voiceConnecting = ctx.voiceLoading;\n\n const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;\n const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;\n\n const buttonStyle = buildButtonStyle(lightButton, darkButton);\n const buttonClasses = buildButtonClasses(colorMode, hasLightCustom, hasDarkCustom);\n\n return (\n <div\n className={buttonClasses}\n style={Object.keys(buttonStyle).length > 0 ? buttonStyle : undefined}\n data-position={position}\n data-mode={resolvedMode}\n data-has-light-custom={hasLightCustom || undefined}\n data-has-dark-custom={hasDarkCustom || undefined}\n >\n <div className=\"yak-widget-icon-bg\">\n <img src={logoUrl} alt=\"\" width={24} height={24} className=\"yak-widget-icon\" />\n </div>\n\n {showChat && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"chat\"\n aria-label={chatLoading ? \"Loading chat\" : \"Open chat\"}\n disabled={chatLoading}\n onClick={ctx.open}\n >\n {chatLoading ? (\n <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />\n ) : (\n <MessageCircleIcon />\n )}\n </button>\n )}\n\n {showVoice && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"voice\"\n data-state={ctx.voiceState}\n aria-label={VOICE_ARIA[ctx.voiceState]}\n disabled={voiceConnecting}\n onClick={() => {\n void ctx.voiceToggle();\n }}\n >\n <VoiceIcon state={ctx.voiceState} />\n </button>\n )}\n </div>\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_javascript", "import_react", "import_jsx_runtime"]
7
7
  }
package/dist/index.js CHANGED
@@ -75,6 +75,7 @@ function YakProvider({
75
75
  theme,
76
76
  onRedirect,
77
77
  disableRestartButton,
78
+ disablePageContent,
78
79
  trigger = false,
79
80
  user,
80
81
  children
@@ -115,7 +116,7 @@ function YakProvider({
115
116
  getConfig,
116
117
  onToolCall,
117
118
  onRedirect: resolvedRedirect,
118
- options: { disableRestartButton },
119
+ options: { disableRestartButton, disablePageContent },
119
120
  onToolCallComplete: handleToolCallComplete,
120
121
  user
121
122
  });
@@ -140,7 +141,7 @@ function YakProvider({
140
141
  onToolCall,
141
142
  theme,
142
143
  onRedirect: resolvedRedirect,
143
- options: { disableRestartButton },
144
+ options: { disableRestartButton, disablePageContent },
144
145
  onToolCallComplete: handleToolCallComplete,
145
146
  user
146
147
  });
@@ -157,6 +158,7 @@ function YakProvider({
157
158
  theme,
158
159
  resolvedRedirect,
159
160
  disableRestartButton,
161
+ disablePageContent,
160
162
  embed,
161
163
  handleToolCallComplete,
162
164
  user
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/context.ts", "../src/YakProvider.tsx", "../src/YakWidget.tsx"],
4
- "sourcesContent": ["\"use client\";\n\nexport type {\n ChatConfigProvider,\n GraphQLRequest,\n RESTRequest,\n Theme,\n ThemeColors,\n ToolAdapter,\n ToolCallEvent,\n ToolCallHandler,\n TriggerButtonConfig,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n WidgetPosition,\n YakServerAdapterConfig,\n YakToolset,\n} from \"@yak-io/javascript\";\n// Re-export useful types and constants from @yak-io/javascript for consumers\nexport {\n createYakServerAdapter,\n createYakToolset,\n disableYakLogging,\n enableYakLogging,\n isYakLoggingEnabled,\n} from \"@yak-io/javascript\";\nexport type { ToolCallEventHandler, YakConfig, YakContextValue } from \"./context.js\";\n// Public API - only export what consumers need\nexport { useYak, useYakToolEvent } from \"./context.js\";\nexport type { YakProviderProps } from \"./YakProvider.js\";\nexport { YakProvider } from \"./YakProvider.js\";\nexport type { YakWidgetProps } from \"./YakWidget.js\";\nexport { YakWidget } from \"./YakWidget.js\";\n", "\"use client\";\n\nimport type {\n ChatConfig,\n Theme,\n ToolCallEvent,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n} from \"@yak-io/javascript\";\nimport { createContext, useContext, useEffect, useRef } from \"react\";\n\n/**\n * Configuration for the yak provider\n */\nexport type YakConfig = {\n appId: string;\n theme?: Theme;\n chatConfig?: ChatConfig | null;\n onRedirect?: (path: string) => void;\n};\n\n/**\n * Listener function for tool call events\n */\nexport type ToolCallEventHandler = (event: ToolCallEvent) => void;\n\n/**\n * Public API for controlling the Yak widget \u2014 chat + voice combined.\n * This is what consumers get from useYak().\n */\nexport type YakContextValue = {\n /** Which modes are exposed: \"chat\", \"voice\", or \"both\". */\n mode: WidgetMode;\n\n // \u2500\u2500 Chat \u2500\u2500\n /** Whether the chat widget is currently open */\n isOpen: boolean;\n /** Whether the iframe is ready to receive messages */\n isReady: boolean;\n /**\n * Whether the chat is opening but not yet interactive (`isOpen && !isReady`).\n * Drive a custom loading state off this instead of re-deriving it.\n */\n chatLoading: boolean;\n /** Open the chat widget */\n open: () => void;\n /** Close the chat widget */\n close: () => void;\n /** Open the chat widget and trigger a specific prompt */\n openWithPrompt: (prompt: string) => void;\n /** Subscribe to tool call completion events */\n subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;\n\n // \u2500\u2500 Voice \u2500\u2500\n /** Current voice state machine snapshot. `idle` when mode === \"chat\". */\n voiceMachine: VoiceMachine;\n /** Convenience: `voiceMachine.state`. */\n voiceState: VoiceState;\n /** Convenience: error message when voiceState === \"error\". */\n voiceErrorMessage: string | undefined;\n /** Whether a voice session is currently live (connecting/listening/thinking/speaking). */\n voiceIsActive: boolean;\n /** Whether the voice session is still connecting (`voiceState === \"connecting\"`). */\n voiceLoading: boolean;\n /** Start a voice session. Must be invoked from a user gesture. */\n voiceStart: () => Promise<void>;\n /** Stop the current voice session. */\n voiceStop: () => Promise<void>;\n /** Toggle: start if idle/error, stop if active. */\n voiceToggle: () => Promise<void>;\n};\n\n/**\n * Internal context with additional methods for widget internals.\n * Not exposed to consumers - only used by provider internals.\n */\nexport type YakInternalContextValue = YakContextValue & {\n /** Get the iframe origin URL (determined by environment) */\n getIframeOrigin: () => string;\n /** Theme passed to YakProvider \u2014 used by YakWidget to mirror panel placement. */\n theme: Theme | undefined;\n};\n\nexport const YakContext = createContext<YakInternalContextValue | null>(null);\n\n/**\n * Hook to access the Yak widget API \u2014 chat and voice.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { open, voiceToggle, voiceState } = useYak();\n * return (\n * <div>\n * <button onClick={open}>Open chat</button>\n * <button onClick={voiceToggle}>{voiceState === \"idle\" ? \"Start voice\" : \"Stop voice\"}</button>\n * </div>\n * );\n * }\n * ```\n *\n * @throws {Error} if used outside YakProvider\n */\nexport function useYak(): YakContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYak must be used within YakProvider\");\n }\n return {\n mode: context.mode,\n isOpen: context.isOpen,\n isReady: context.isReady,\n chatLoading: context.chatLoading,\n open: context.open,\n close: context.close,\n openWithPrompt: context.openWithPrompt,\n subscribeToToolEvents: context.subscribeToToolEvents,\n voiceMachine: context.voiceMachine,\n voiceState: context.voiceState,\n voiceErrorMessage: context.voiceErrorMessage,\n voiceIsActive: context.voiceIsActive,\n voiceLoading: context.voiceLoading,\n voiceStart: context.voiceStart,\n voiceStop: context.voiceStop,\n voiceToggle: context.voiceToggle,\n };\n}\n\n/**\n * Internal hook for components that need full context access.\n * Not exported publicly.\n */\nexport function useYakInternal(): YakInternalContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakInternal must be used within YakProvider\");\n }\n return context;\n}\n\n/**\n * Hook to subscribe to tool call completion events.\n * Useful for page-level cache invalidation when chatbot tools modify data.\n *\n * The handler receives an event with:\n * - `name`: The tool name that was called (e.g., \"order.cancel\")\n * - `args`: The arguments passed to the tool\n * - `ok`: Whether the call succeeded\n * - `result`: The result (if ok is true)\n * - `error`: The error message (if ok is false)\n *\n * @example\n * ```tsx\n * function PlanPage({ planId }: { planId: string }) {\n * const utils = trpc.useUtils();\n *\n * useYakToolEvent((event) => {\n * // Only invalidate if this tool touched plans\n * if (event.ok && event.name.startsWith(\"plan.\")) {\n * utils.plan.get.invalidate({ id: planId });\n * utils.planItem.list.invalidate({ planId });\n * }\n * });\n *\n * // ... rest of component\n * }\n * ```\n *\n * @param handler - Function called after each tool call completes\n * @throws {Error} if used outside YakProvider\n */\nexport function useYakToolEvent(handler: ToolCallEventHandler): void {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakToolEvent must be used within YakProvider\");\n }\n\n // Use ref to always have latest handler without re-subscribing\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n // Wrap handler to use ref (stable reference)\n const stableHandler: ToolCallEventHandler = (event) => {\n handlerRef.current(event);\n };\n\n return context.subscribeToToolEvents(stableHandler);\n }, [context]);\n}\n", "\"use client\";\n\nimport {\n type ChatConfigProvider,\n INITIAL_VOICE_MACHINE,\n logger,\n type Theme,\n type ToolCallEvent,\n type ToolCallHandler,\n type TriggerButtonConfig,\n type UserIdentity,\n type VoiceMachine,\n type WidgetMode,\n YakEmbed,\n} from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type ToolCallEventHandler, YakContext } from \"./context.js\";\n\n/**\n * Props for YakProvider\n */\nexport type YakProviderProps = {\n /** App identifier in the yak SaaS */\n appId: string;\n /**\n * Override the origin the chat/voice runtime connects to. Defaults to\n * `https://chat.yak.io`. Read once when the provider mounts; most integrators\n * never set this.\n */\n origin?: string;\n /**\n * Which experiences this widget exposes.\n * \"chat\" \u2014 chat only (iframe).\n * \"voice\" \u2014 voice only (WebRTC).\n * \"both\" \u2014 both, sharing one trigger pill.\n * Default: \"chat\".\n */\n mode?: WidgetMode;\n /**\n * Provider function for chat configuration (routes + tools).\n * The consuming platform decides how to get the config (static, fetch, etc.)\n * Called when the chat is opened or when a voice session starts.\n */\n getConfig?: ChatConfigProvider;\n /**\n * Handler for tool calls from the chat or voice runtime.\n * The consuming platform decides how to execute (browser, server fetch, etc.)\n */\n onToolCall?: ToolCallHandler;\n /** Optional theme configuration */\n theme?: Theme;\n /** Optional redirect handler (defaults to window.location.assign) */\n onRedirect?: (path: string) => void;\n /** Disable the restart session button in the header */\n disableRestartButton?: boolean;\n /**\n * Trigger button configuration. Pass `false` to disable the built-in trigger\n * (useful when rendering `<YakWidget />` separately). Defaults to `false`.\n */\n trigger?: boolean | TriggerButtonConfig;\n /**\n * Signed end-user identity for server-side conversation persistence.\n *\n * Compute the `hash` on your backend with\n * `HMAC-SHA256(application.apiSecret, user.id)` and pass it down to the\n * browser. When supplied, the widget stores conversations server-side and\n * shows a history pane so end-users can resume past chats. When omitted,\n * the widget runs in anonymous mode (no persistence).\n */\n user?: UserIdentity;\n /** Children components */\n children: React.ReactNode;\n};\n\n/**\n * YakProvider sets up the unified chat + voice runtime. All DOM rendering\n * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers\n * access both surfaces via `useYak()`.\n */\nexport function YakProvider({\n appId,\n origin,\n mode = \"chat\",\n getConfig,\n onToolCall,\n theme,\n onRedirect,\n disableRestartButton,\n trigger = false,\n user,\n children,\n}: YakProviderProps): React.ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n const [isReady, setIsReady] = useState(false);\n const [voiceMachine, setVoiceMachine] = useState<VoiceMachine>(INITIAL_VOICE_MACHINE);\n\n // Store event subscribers for tool call events\n const toolEventSubscribersRef = useRef<Set<ToolCallEventHandler>>(new Set());\n\n // Handler that notifies all subscribers when a tool call completes\n const handleToolCallComplete = useCallback((event: ToolCallEvent) => {\n logger.debug(\"Tool call completed, notifying subscribers:\", {\n name: event.name,\n ok: event.ok,\n subscriberCount: toolEventSubscribersRef.current.size,\n });\n for (const handler of toolEventSubscribersRef.current) {\n try {\n handler(event);\n } catch (err) {\n logger.warn(\"Error in tool event subscriber:\", err);\n }\n }\n }, []);\n\n // Resolve redirect handler\n const resolvedRedirect = useMemo(() => {\n if (onRedirect) return onRedirect;\n if (typeof window === \"undefined\") return undefined;\n return (path: string) => {\n window.location.assign(path);\n };\n }, [onRedirect]);\n\n // Initialize YakEmbed \u2014 created once, never recreated\n const embedRef = useRef<YakEmbed | null>(null);\n if (!embedRef.current) {\n embedRef.current = new YakEmbed({\n appId,\n origin,\n mode,\n theme,\n trigger,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n }\n const embed = embedRef.current;\n\n // Mount/unmount embed and subscribe to chat + voice state changes\n useEffect(() => {\n embed.mount();\n\n const unsubscribeChat = embed.onStateChange((state) => {\n setIsOpen(state.isOpen);\n setIsReady(state.isReady);\n });\n const unsubscribeVoice = embed.onVoiceStateChange((m) => setVoiceMachine(m));\n\n return () => {\n unsubscribeChat();\n unsubscribeVoice();\n embed.destroy();\n };\n }, [embed]);\n\n // Update embed config when props change. Chat config goes via the client;\n // voice config goes via the voice session.\n useEffect(() => {\n embed.getClient().updateConfig({\n appId,\n onToolCall,\n theme,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n embed.getVoiceSession()?.updateConfig({\n appId,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n });\n }, [\n appId,\n getConfig,\n onToolCall,\n theme,\n resolvedRedirect,\n disableRestartButton,\n embed,\n handleToolCallComplete,\n user,\n ]);\n\n // Fetch chat config when the chat is opened\n useEffect(() => {\n if (typeof window === \"undefined\" || !isOpen || !getConfig) return;\n\n logger.debug(\"Getting chat config\");\n\n let cancelled = false;\n\n (async () => {\n try {\n const config = await getConfig();\n if (!cancelled) {\n logger.debug(\n `Chat config loaded with ${config.tools?.tools.length ?? 0} tools and ${config.routes?.routes.length ?? 0} routes`\n );\n embed.getClient().updateConfig({ chatConfig: config });\n }\n } catch (err) {\n logger.warn(\"Error getting chat config:\", err);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [getConfig, isOpen, embed]);\n\n // Chat methods\n const open = useCallback(() => embed.open(), [embed]);\n const close = useCallback(() => embed.close(), [embed]);\n const openWithPrompt = useCallback((prompt: string) => embed.openWithPrompt(prompt), [embed]);\n\n // Voice methods\n const voiceStart = useCallback(async () => {\n try {\n await embed.voiceStart();\n } catch (err) {\n logger.warn(\"Voice start failed\", err);\n }\n }, [embed]);\n const voiceStop = useCallback(() => embed.voiceStop(), [embed]);\n const voiceToggle = useCallback(() => embed.voiceToggle(), [embed]);\n\n // Subscribe to tool call completion events\n const subscribeToToolEvents = useCallback((handler: ToolCallEventHandler) => {\n toolEventSubscribersRef.current.add(handler);\n logger.debug(\"Tool event subscriber added, total:\", toolEventSubscribersRef.current.size);\n\n return () => {\n toolEventSubscribersRef.current.delete(handler);\n logger.debug(\"Tool event subscriber removed, total:\", toolEventSubscribersRef.current.size);\n };\n }, []);\n\n // Expose iframe origin for YakWidget\n const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);\n\n const voiceState = voiceMachine.state;\n const voiceIsActive = voiceState !== \"idle\" && voiceState !== \"error\";\n const chatLoading = isOpen && !isReady;\n const voiceLoading = voiceState === \"connecting\";\n\n const contextValue = useMemo(\n () => ({\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceErrorMessage: voiceMachine.errorMessage,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n }),\n [\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n ]\n );\n\n return <YakContext.Provider value={contextValue}>{children}</YakContext.Provider>;\n}\n", "\"use client\";\n\nimport type { VoiceState, WidgetMode } from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useYakInternal } from \"./context.js\";\n\n/**\n * Props for YakWidget\n */\nexport type YakWidgetProps = {\n /** Override the mode from the provider. */\n mode?: WidgetMode;\n /** Custom button colors for light mode */\n lightButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n /** Custom button colors for dark mode */\n darkButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n};\n\nconst VOICE_ARIA: Record<VoiceState, string> = {\n idle: \"Start voice mode\",\n connecting: \"Connecting voice session\",\n listening: \"Voice listening \u2014 tap to stop\",\n thinking: \"Voice thinking \u2014 tap to stop\",\n speaking: \"Voice speaking \u2014 tap to stop\",\n error: \"Voice error \u2014 tap to retry\",\n};\n\nfunction MessageCircleIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n </svg>\n );\n}\n\nfunction AudioLinesIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\nfunction StopIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width={20} height={20} aria-hidden=\"true\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction VoiceIcon({ state }: { state: VoiceState }): React.ReactElement {\n if (state === \"connecting\") {\n return <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />;\n }\n if (state === \"listening\" || state === \"speaking\" || state === \"thinking\") {\n return <StopIcon />;\n }\n return <AudioLinesIcon />;\n}\n\nfunction buildButtonStyle(\n lightButton: YakWidgetProps[\"lightButton\"],\n darkButton: YakWidgetProps[\"darkButton\"]\n): React.CSSProperties & Record<string, string | undefined> {\n const style: React.CSSProperties & Record<string, string | undefined> = {};\n if (lightButton?.background) style[\"--yak-btn-light-bg\"] = lightButton.background;\n if (lightButton?.color) style[\"--yak-btn-light-color\"] = lightButton.color;\n if (lightButton?.border) style[\"--yak-btn-light-border\"] = lightButton.border;\n if (darkButton?.background) style[\"--yak-btn-dark-bg\"] = darkButton.background;\n if (darkButton?.color) style[\"--yak-btn-dark-color\"] = darkButton.color;\n if (darkButton?.border) style[\"--yak-btn-dark-border\"] = darkButton.border;\n return style;\n}\n\nfunction buildButtonClasses(\n colorMode: \"light\" | \"dark\" | \"system\" | undefined,\n hasLightCustom: string | boolean | undefined,\n hasDarkCustom: string | boolean | undefined\n): string {\n const colorModeClass =\n colorMode === \"light\" ? \"yak-widget-light\" : colorMode === \"dark\" ? \"yak-widget-dark\" : \"\";\n\n let customButtonClass = \"\";\n if (colorMode === \"light\" && hasLightCustom) {\n customButtonClass = \"yak-widget-custom-light\";\n } else if (colorMode === \"dark\" && hasDarkCustom) {\n customButtonClass = \"yak-widget-custom-dark\";\n }\n\n return [\"yak-widget-trigger\", colorModeClass, customButtonClass].filter(Boolean).join(\" \");\n}\n\n/**\n * YakWidget renders a fixed-position launcher pill. The logo sits on the\n * left; one or two icon buttons sit on the right based on `mode`. Trigger\n * CSS is injected by YakEmbed (via YakProvider) \u2014 this component only\n * provides the React markup using those shared class names.\n */\nexport function YakWidget({\n mode,\n lightButton,\n darkButton,\n}: YakWidgetProps = {}): React.ReactElement {\n const ctx = useYakInternal();\n const resolvedMode = mode ?? ctx.mode;\n const position = ctx.theme?.position ?? \"bottom-left\";\n const colorMode = ctx.theme?.colorMode;\n const logoUrl = `${ctx.getIframeOrigin()}/logo.svg`;\n\n const showChat = resolvedMode === \"chat\" || resolvedMode === \"both\";\n const showVoice = resolvedMode === \"voice\" || resolvedMode === \"both\";\n\n // Consume the shipped loading flags rather than re-deriving them here.\n const chatLoading = ctx.chatLoading;\n const voiceConnecting = ctx.voiceLoading;\n\n const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;\n const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;\n\n const buttonStyle = buildButtonStyle(lightButton, darkButton);\n const buttonClasses = buildButtonClasses(colorMode, hasLightCustom, hasDarkCustom);\n\n return (\n <div\n className={buttonClasses}\n style={Object.keys(buttonStyle).length > 0 ? buttonStyle : undefined}\n data-position={position}\n data-mode={resolvedMode}\n data-has-light-custom={hasLightCustom || undefined}\n data-has-dark-custom={hasDarkCustom || undefined}\n >\n <div className=\"yak-widget-icon-bg\">\n <img src={logoUrl} alt=\"\" width={24} height={24} className=\"yak-widget-icon\" />\n </div>\n\n {showChat && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"chat\"\n aria-label={chatLoading ? \"Loading chat\" : \"Open chat\"}\n disabled={chatLoading}\n onClick={ctx.open}\n >\n {chatLoading ? (\n <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />\n ) : (\n <MessageCircleIcon />\n )}\n </button>\n )}\n\n {showVoice && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"voice\"\n data-state={ctx.voiceState}\n aria-label={VOICE_ARIA[ctx.voiceState]}\n disabled={voiceConnecting}\n onClick={() => {\n void ctx.voiceToggle();\n }}\n >\n <VoiceIcon state={ctx.voiceState} />\n </button>\n )}\n </div>\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\";\n\nexport type {\n ChatConfigProvider,\n GraphQLRequest,\n RESTRequest,\n Theme,\n ThemeColors,\n ToolAdapter,\n ToolCallEvent,\n ToolCallHandler,\n TriggerButtonConfig,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n WidgetPosition,\n YakServerAdapterConfig,\n YakToolset,\n} from \"@yak-io/javascript\";\n// Re-export useful types and constants from @yak-io/javascript for consumers\nexport {\n createYakServerAdapter,\n createYakToolset,\n disableYakLogging,\n enableYakLogging,\n isYakLoggingEnabled,\n} from \"@yak-io/javascript\";\nexport type { ToolCallEventHandler, YakConfig, YakContextValue } from \"./context.js\";\n// Public API - only export what consumers need\nexport { useYak, useYakToolEvent } from \"./context.js\";\nexport type { YakProviderProps } from \"./YakProvider.js\";\nexport { YakProvider } from \"./YakProvider.js\";\nexport type { YakWidgetProps } from \"./YakWidget.js\";\nexport { YakWidget } from \"./YakWidget.js\";\n", "\"use client\";\n\nimport type {\n ChatConfig,\n Theme,\n ToolCallEvent,\n VoiceMachine,\n VoiceState,\n WidgetMode,\n} from \"@yak-io/javascript\";\nimport { createContext, useContext, useEffect, useRef } from \"react\";\n\n/**\n * Configuration for the yak provider\n */\nexport type YakConfig = {\n appId: string;\n theme?: Theme;\n chatConfig?: ChatConfig | null;\n onRedirect?: (path: string) => void;\n};\n\n/**\n * Listener function for tool call events\n */\nexport type ToolCallEventHandler = (event: ToolCallEvent) => void;\n\n/**\n * Public API for controlling the Yak widget \u2014 chat + voice combined.\n * This is what consumers get from useYak().\n */\nexport type YakContextValue = {\n /** Which modes are exposed: \"chat\", \"voice\", or \"both\". */\n mode: WidgetMode;\n\n // \u2500\u2500 Chat \u2500\u2500\n /** Whether the chat widget is currently open */\n isOpen: boolean;\n /** Whether the iframe is ready to receive messages */\n isReady: boolean;\n /**\n * Whether the chat is opening but not yet interactive (`isOpen && !isReady`).\n * Drive a custom loading state off this instead of re-deriving it.\n */\n chatLoading: boolean;\n /** Open the chat widget */\n open: () => void;\n /** Close the chat widget */\n close: () => void;\n /** Open the chat widget and trigger a specific prompt */\n openWithPrompt: (prompt: string) => void;\n /** Subscribe to tool call completion events */\n subscribeToToolEvents: (handler: ToolCallEventHandler) => () => void;\n\n // \u2500\u2500 Voice \u2500\u2500\n /** Current voice state machine snapshot. `idle` when mode === \"chat\". */\n voiceMachine: VoiceMachine;\n /** Convenience: `voiceMachine.state`. */\n voiceState: VoiceState;\n /** Convenience: error message when voiceState === \"error\". */\n voiceErrorMessage: string | undefined;\n /** Whether a voice session is currently live (connecting/listening/thinking/speaking). */\n voiceIsActive: boolean;\n /** Whether the voice session is still connecting (`voiceState === \"connecting\"`). */\n voiceLoading: boolean;\n /** Start a voice session. Must be invoked from a user gesture. */\n voiceStart: () => Promise<void>;\n /** Stop the current voice session. */\n voiceStop: () => Promise<void>;\n /** Toggle: start if idle/error, stop if active. */\n voiceToggle: () => Promise<void>;\n};\n\n/**\n * Internal context with additional methods for widget internals.\n * Not exposed to consumers - only used by provider internals.\n */\nexport type YakInternalContextValue = YakContextValue & {\n /** Get the iframe origin URL (determined by environment) */\n getIframeOrigin: () => string;\n /** Theme passed to YakProvider \u2014 used by YakWidget to mirror panel placement. */\n theme: Theme | undefined;\n};\n\nexport const YakContext = createContext<YakInternalContextValue | null>(null);\n\n/**\n * Hook to access the Yak widget API \u2014 chat and voice.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { open, voiceToggle, voiceState } = useYak();\n * return (\n * <div>\n * <button onClick={open}>Open chat</button>\n * <button onClick={voiceToggle}>{voiceState === \"idle\" ? \"Start voice\" : \"Stop voice\"}</button>\n * </div>\n * );\n * }\n * ```\n *\n * @throws {Error} if used outside YakProvider\n */\nexport function useYak(): YakContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYak must be used within YakProvider\");\n }\n return {\n mode: context.mode,\n isOpen: context.isOpen,\n isReady: context.isReady,\n chatLoading: context.chatLoading,\n open: context.open,\n close: context.close,\n openWithPrompt: context.openWithPrompt,\n subscribeToToolEvents: context.subscribeToToolEvents,\n voiceMachine: context.voiceMachine,\n voiceState: context.voiceState,\n voiceErrorMessage: context.voiceErrorMessage,\n voiceIsActive: context.voiceIsActive,\n voiceLoading: context.voiceLoading,\n voiceStart: context.voiceStart,\n voiceStop: context.voiceStop,\n voiceToggle: context.voiceToggle,\n };\n}\n\n/**\n * Internal hook for components that need full context access.\n * Not exported publicly.\n */\nexport function useYakInternal(): YakInternalContextValue {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakInternal must be used within YakProvider\");\n }\n return context;\n}\n\n/**\n * Hook to subscribe to tool call completion events.\n * Useful for page-level cache invalidation when chatbot tools modify data.\n *\n * The handler receives an event with:\n * - `name`: The tool name that was called (e.g., \"order.cancel\")\n * - `args`: The arguments passed to the tool\n * - `ok`: Whether the call succeeded\n * - `result`: The result (if ok is true)\n * - `error`: The error message (if ok is false)\n *\n * @example\n * ```tsx\n * function PlanPage({ planId }: { planId: string }) {\n * const utils = trpc.useUtils();\n *\n * useYakToolEvent((event) => {\n * // Only invalidate if this tool touched plans\n * if (event.ok && event.name.startsWith(\"plan.\")) {\n * utils.plan.get.invalidate({ id: planId });\n * utils.planItem.list.invalidate({ planId });\n * }\n * });\n *\n * // ... rest of component\n * }\n * ```\n *\n * @param handler - Function called after each tool call completes\n * @throws {Error} if used outside YakProvider\n */\nexport function useYakToolEvent(handler: ToolCallEventHandler): void {\n const context = useContext(YakContext);\n if (!context) {\n throw new Error(\"useYakToolEvent must be used within YakProvider\");\n }\n\n // Use ref to always have latest handler without re-subscribing\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n // Wrap handler to use ref (stable reference)\n const stableHandler: ToolCallEventHandler = (event) => {\n handlerRef.current(event);\n };\n\n return context.subscribeToToolEvents(stableHandler);\n }, [context]);\n}\n", "\"use client\";\n\nimport {\n type ChatConfigProvider,\n INITIAL_VOICE_MACHINE,\n logger,\n type Theme,\n type ToolCallEvent,\n type ToolCallHandler,\n type TriggerButtonConfig,\n type UserIdentity,\n type VoiceMachine,\n type WidgetMode,\n YakEmbed,\n} from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { type ToolCallEventHandler, YakContext } from \"./context.js\";\n\n/**\n * Props for YakProvider\n */\nexport type YakProviderProps = {\n /** App identifier in the yak SaaS */\n appId: string;\n /**\n * Override the origin the chat/voice runtime connects to. Defaults to\n * `https://chat.yak.io`. Read once when the provider mounts; most integrators\n * never set this.\n */\n origin?: string;\n /**\n * Which experiences this widget exposes.\n * \"chat\" \u2014 chat only (iframe).\n * \"voice\" \u2014 voice only (WebRTC).\n * \"both\" \u2014 both, sharing one trigger pill.\n * Default: \"chat\".\n */\n mode?: WidgetMode;\n /**\n * Provider function for chat configuration (routes + tools).\n * The consuming platform decides how to get the config (static, fetch, etc.)\n * Called when the chat is opened or when a voice session starts.\n */\n getConfig?: ChatConfigProvider;\n /**\n * Handler for tool calls from the chat or voice runtime.\n * The consuming platform decides how to execute (browser, server fetch, etc.)\n */\n onToolCall?: ToolCallHandler;\n /** Optional theme configuration */\n theme?: Theme;\n /** Optional redirect handler (defaults to window.location.assign) */\n onRedirect?: (path: string) => void;\n /** Disable the restart session button in the header */\n disableRestartButton?: boolean;\n /**\n * Privacy opt-out: stop sending any page context (URL, title, visible text)\n * to the assistant. The widget still works; it just won't be aware of the\n * current page, so it can't answer questions like \"what is this page?\".\n */\n disablePageContent?: boolean;\n /**\n * Trigger button configuration. Pass `false` to disable the built-in trigger\n * (useful when rendering `<YakWidget />` separately). Defaults to `false`.\n */\n trigger?: boolean | TriggerButtonConfig;\n /**\n * Signed end-user identity for server-side conversation persistence.\n *\n * Compute the `hash` on your backend with\n * `HMAC-SHA256(application.apiSecret, user.id)` and pass it down to the\n * browser. When supplied, the widget stores conversations server-side and\n * shows a history pane so end-users can resume past chats. When omitted,\n * the widget runs in anonymous mode (no persistence).\n */\n user?: UserIdentity;\n /** Children components */\n children: React.ReactNode;\n};\n\n/**\n * YakProvider sets up the unified chat + voice runtime. All DOM rendering\n * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers\n * access both surfaces via `useYak()`.\n */\nexport function YakProvider({\n appId,\n origin,\n mode = \"chat\",\n getConfig,\n onToolCall,\n theme,\n onRedirect,\n disableRestartButton,\n disablePageContent,\n trigger = false,\n user,\n children,\n}: YakProviderProps): React.ReactElement {\n const [isOpen, setIsOpen] = useState(false);\n const [isReady, setIsReady] = useState(false);\n const [voiceMachine, setVoiceMachine] = useState<VoiceMachine>(INITIAL_VOICE_MACHINE);\n\n // Store event subscribers for tool call events\n const toolEventSubscribersRef = useRef<Set<ToolCallEventHandler>>(new Set());\n\n // Handler that notifies all subscribers when a tool call completes\n const handleToolCallComplete = useCallback((event: ToolCallEvent) => {\n logger.debug(\"Tool call completed, notifying subscribers:\", {\n name: event.name,\n ok: event.ok,\n subscriberCount: toolEventSubscribersRef.current.size,\n });\n for (const handler of toolEventSubscribersRef.current) {\n try {\n handler(event);\n } catch (err) {\n logger.warn(\"Error in tool event subscriber:\", err);\n }\n }\n }, []);\n\n // Resolve redirect handler\n const resolvedRedirect = useMemo(() => {\n if (onRedirect) return onRedirect;\n if (typeof window === \"undefined\") return undefined;\n return (path: string) => {\n window.location.assign(path);\n };\n }, [onRedirect]);\n\n // Initialize YakEmbed \u2014 created once, never recreated\n const embedRef = useRef<YakEmbed | null>(null);\n if (!embedRef.current) {\n embedRef.current = new YakEmbed({\n appId,\n origin,\n mode,\n theme,\n trigger,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton, disablePageContent },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n }\n const embed = embedRef.current;\n\n // Mount/unmount embed and subscribe to chat + voice state changes\n useEffect(() => {\n embed.mount();\n\n const unsubscribeChat = embed.onStateChange((state) => {\n setIsOpen(state.isOpen);\n setIsReady(state.isReady);\n });\n const unsubscribeVoice = embed.onVoiceStateChange((m) => setVoiceMachine(m));\n\n return () => {\n unsubscribeChat();\n unsubscribeVoice();\n embed.destroy();\n };\n }, [embed]);\n\n // Update embed config when props change. Chat config goes via the client;\n // voice config goes via the voice session.\n useEffect(() => {\n embed.getClient().updateConfig({\n appId,\n onToolCall,\n theme,\n onRedirect: resolvedRedirect,\n options: { disableRestartButton, disablePageContent },\n onToolCallComplete: handleToolCallComplete,\n user,\n });\n embed.getVoiceSession()?.updateConfig({\n appId,\n getConfig,\n onToolCall,\n onRedirect: resolvedRedirect,\n });\n }, [\n appId,\n getConfig,\n onToolCall,\n theme,\n resolvedRedirect,\n disableRestartButton,\n disablePageContent,\n embed,\n handleToolCallComplete,\n user,\n ]);\n\n // Fetch chat config when the chat is opened\n useEffect(() => {\n if (typeof window === \"undefined\" || !isOpen || !getConfig) return;\n\n logger.debug(\"Getting chat config\");\n\n let cancelled = false;\n\n (async () => {\n try {\n const config = await getConfig();\n if (!cancelled) {\n logger.debug(\n `Chat config loaded with ${config.tools?.tools.length ?? 0} tools and ${config.routes?.routes.length ?? 0} routes`\n );\n embed.getClient().updateConfig({ chatConfig: config });\n }\n } catch (err) {\n logger.warn(\"Error getting chat config:\", err);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [getConfig, isOpen, embed]);\n\n // Chat methods\n const open = useCallback(() => embed.open(), [embed]);\n const close = useCallback(() => embed.close(), [embed]);\n const openWithPrompt = useCallback((prompt: string) => embed.openWithPrompt(prompt), [embed]);\n\n // Voice methods\n const voiceStart = useCallback(async () => {\n try {\n await embed.voiceStart();\n } catch (err) {\n logger.warn(\"Voice start failed\", err);\n }\n }, [embed]);\n const voiceStop = useCallback(() => embed.voiceStop(), [embed]);\n const voiceToggle = useCallback(() => embed.voiceToggle(), [embed]);\n\n // Subscribe to tool call completion events\n const subscribeToToolEvents = useCallback((handler: ToolCallEventHandler) => {\n toolEventSubscribersRef.current.add(handler);\n logger.debug(\"Tool event subscriber added, total:\", toolEventSubscribersRef.current.size);\n\n return () => {\n toolEventSubscribersRef.current.delete(handler);\n logger.debug(\"Tool event subscriber removed, total:\", toolEventSubscribersRef.current.size);\n };\n }, []);\n\n // Expose iframe origin for YakWidget\n const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);\n\n const voiceState = voiceMachine.state;\n const voiceIsActive = voiceState !== \"idle\" && voiceState !== \"error\";\n const chatLoading = isOpen && !isReady;\n const voiceLoading = voiceState === \"connecting\";\n\n const contextValue = useMemo(\n () => ({\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceErrorMessage: voiceMachine.errorMessage,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n }),\n [\n mode,\n isOpen,\n isReady,\n chatLoading,\n open,\n close,\n openWithPrompt,\n subscribeToToolEvents,\n voiceMachine,\n voiceState,\n voiceIsActive,\n voiceLoading,\n voiceStart,\n voiceStop,\n voiceToggle,\n getIframeOrigin,\n theme,\n ]\n );\n\n return <YakContext.Provider value={contextValue}>{children}</YakContext.Provider>;\n}\n", "\"use client\";\n\nimport type { VoiceState, WidgetMode } from \"@yak-io/javascript\";\nimport type React from \"react\";\nimport { useYakInternal } from \"./context.js\";\n\n/**\n * Props for YakWidget\n */\nexport type YakWidgetProps = {\n /** Override the mode from the provider. */\n mode?: WidgetMode;\n /** Custom button colors for light mode */\n lightButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n /** Custom button colors for dark mode */\n darkButton?: {\n background?: string;\n color?: string;\n border?: string;\n };\n};\n\nconst VOICE_ARIA: Record<VoiceState, string> = {\n idle: \"Start voice mode\",\n connecting: \"Connecting voice session\",\n listening: \"Voice listening \u2014 tap to stop\",\n thinking: \"Voice thinking \u2014 tap to stop\",\n speaking: \"Voice speaking \u2014 tap to stop\",\n error: \"Voice error \u2014 tap to retry\",\n};\n\nfunction MessageCircleIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n </svg>\n );\n}\n\nfunction AudioLinesIcon(): React.ReactElement {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={20}\n height={20}\n aria-hidden=\"true\"\n >\n <path d=\"M2 10v3\" />\n <path d=\"M6 6v11\" />\n <path d=\"M10 3v18\" />\n <path d=\"M14 8v7\" />\n <path d=\"M18 5v13\" />\n <path d=\"M22 10v3\" />\n </svg>\n );\n}\n\nfunction StopIcon(): React.ReactElement {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width={20} height={20} aria-hidden=\"true\">\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction VoiceIcon({ state }: { state: VoiceState }): React.ReactElement {\n if (state === \"connecting\") {\n return <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />;\n }\n if (state === \"listening\" || state === \"speaking\" || state === \"thinking\") {\n return <StopIcon />;\n }\n return <AudioLinesIcon />;\n}\n\nfunction buildButtonStyle(\n lightButton: YakWidgetProps[\"lightButton\"],\n darkButton: YakWidgetProps[\"darkButton\"]\n): React.CSSProperties & Record<string, string | undefined> {\n const style: React.CSSProperties & Record<string, string | undefined> = {};\n if (lightButton?.background) style[\"--yak-btn-light-bg\"] = lightButton.background;\n if (lightButton?.color) style[\"--yak-btn-light-color\"] = lightButton.color;\n if (lightButton?.border) style[\"--yak-btn-light-border\"] = lightButton.border;\n if (darkButton?.background) style[\"--yak-btn-dark-bg\"] = darkButton.background;\n if (darkButton?.color) style[\"--yak-btn-dark-color\"] = darkButton.color;\n if (darkButton?.border) style[\"--yak-btn-dark-border\"] = darkButton.border;\n return style;\n}\n\nfunction buildButtonClasses(\n colorMode: \"light\" | \"dark\" | \"system\" | undefined,\n hasLightCustom: string | boolean | undefined,\n hasDarkCustom: string | boolean | undefined\n): string {\n const colorModeClass =\n colorMode === \"light\" ? \"yak-widget-light\" : colorMode === \"dark\" ? \"yak-widget-dark\" : \"\";\n\n let customButtonClass = \"\";\n if (colorMode === \"light\" && hasLightCustom) {\n customButtonClass = \"yak-widget-custom-light\";\n } else if (colorMode === \"dark\" && hasDarkCustom) {\n customButtonClass = \"yak-widget-custom-dark\";\n }\n\n return [\"yak-widget-trigger\", colorModeClass, customButtonClass].filter(Boolean).join(\" \");\n}\n\n/**\n * YakWidget renders a fixed-position launcher pill. The logo sits on the\n * left; one or two icon buttons sit on the right based on `mode`. Trigger\n * CSS is injected by YakEmbed (via YakProvider) \u2014 this component only\n * provides the React markup using those shared class names.\n */\nexport function YakWidget({\n mode,\n lightButton,\n darkButton,\n}: YakWidgetProps = {}): React.ReactElement {\n const ctx = useYakInternal();\n const resolvedMode = mode ?? ctx.mode;\n const position = ctx.theme?.position ?? \"bottom-left\";\n const colorMode = ctx.theme?.colorMode;\n const logoUrl = `${ctx.getIframeOrigin()}/logo.svg`;\n\n const showChat = resolvedMode === \"chat\" || resolvedMode === \"both\";\n const showVoice = resolvedMode === \"voice\" || resolvedMode === \"both\";\n\n // Consume the shipped loading flags rather than re-deriving them here.\n const chatLoading = ctx.chatLoading;\n const voiceConnecting = ctx.voiceLoading;\n\n const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;\n const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;\n\n const buttonStyle = buildButtonStyle(lightButton, darkButton);\n const buttonClasses = buildButtonClasses(colorMode, hasLightCustom, hasDarkCustom);\n\n return (\n <div\n className={buttonClasses}\n style={Object.keys(buttonStyle).length > 0 ? buttonStyle : undefined}\n data-position={position}\n data-mode={resolvedMode}\n data-has-light-custom={hasLightCustom || undefined}\n data-has-dark-custom={hasDarkCustom || undefined}\n >\n <div className=\"yak-widget-icon-bg\">\n <img src={logoUrl} alt=\"\" width={24} height={24} className=\"yak-widget-icon\" />\n </div>\n\n {showChat && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"chat\"\n aria-label={chatLoading ? \"Loading chat\" : \"Open chat\"}\n disabled={chatLoading}\n onClick={ctx.open}\n >\n {chatLoading ? (\n <span className=\"yak-widget-spinner\" aria-hidden=\"true\" />\n ) : (\n <MessageCircleIcon />\n )}\n </button>\n )}\n\n {showVoice && (\n <button\n type=\"button\"\n className=\"yak-widget-trigger-icon-btn\"\n data-action=\"voice\"\n data-state={ctx.voiceState}\n aria-label={VOICE_ARIA[ctx.voiceState]}\n disabled={voiceConnecting}\n onClick={() => {\n void ctx.voiceToggle();\n }}\n >\n <VoiceIcon state={ctx.voiceState} />\n </button>\n )}\n </div>\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["useEffect", "useRef", "useRef", "useEffect", "jsx"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/react",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "description": "React SDK for embedding yak chatbot",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -43,7 +43,7 @@
43
43
  "./package.json": "./package.json"
44
44
  },
45
45
  "dependencies": {
46
- "@yak-io/javascript": "0.11.2"
46
+ "@yak-io/javascript": "0.13.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": "^17.0.0 || ^18.0.0 || ^19.0.0"