@yak-io/react 0.9.0 → 0.11.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.
package/README.md CHANGED
@@ -1,18 +1,30 @@
1
1
  # @yak-io/react
2
2
 
3
- React integration for the Yak embeddable chat widget. Provides `YakProvider`, `YakWidget`, `useYak`, and `useYakToolEvent`.
3
+ > 📚 **Full documentation:** https://docs.yak.io/docs/sdks/react
4
+ >
5
+ > 🤖 **For LLMs / AI agents:** https://docs.yak.io/llms.txt
4
6
 
5
- ## Installation
7
+ React SDK for [Yak](https://docs.yak.io) — an embeddable AI assistant (text chat **and** push-to-talk voice) for web apps. Wrap your app in `YakProvider`, render `YakWidget` (or build your own trigger), and control everything with the `useYak()` hook.
8
+
9
+ **On Next.js, use [`@yak-io/nextjs`](https://docs.yak.io/docs/sdks/nextjs) instead** — it adds route scanning and server handler factories on top of this package.
6
10
 
7
11
  ```bash
8
12
  pnpm add @yak-io/react
9
13
  ```
10
14
 
11
- For Next.js, use [`@yak-io/nextjs`](../nextjs) instead — it adds route scanning and server handler factories on top of this package.
15
+ ## Exports
12
16
 
13
- ## Quickstart
17
+ | Export | Kind | Purpose |
18
+ | --- | --- | --- |
19
+ | `YakProvider` | component | Sets up the chat + voice runtime. Wrap your app once. |
20
+ | `YakWidget` | component | The floating launcher pill. Render it inside `YakProvider`, or omit it and build your own trigger. |
21
+ | `useYak()` | hook | Imperative control of chat + voice, plus reactive state. |
22
+ | `useYakToolEvent(handler)` | hook | Run a callback after each tool call (e.g. cache invalidation). |
23
+ | `createYakToolset` / `createYakServerAdapter` | fn | Compose GraphQL/REST/tRPC/custom tool adapters into one `onToolCall` (re-exported from `@yak-io/javascript`). |
24
+ | `enableYakLogging` / `disableYakLogging` / `isYakLoggingEnabled` | fn | Toggle verbose SDK logging. |
25
+ | Types | — | `YakProviderProps`, `YakWidgetProps`, `YakContextValue`, plus core types re-exported from `@yak-io/javascript`. |
14
26
 
15
- ### 1. Wrap your app with `YakProvider`
27
+ ## Quickstart
16
28
 
17
29
  ```tsx
18
30
  // src/App.tsx (or your root layout)
@@ -22,11 +34,14 @@ export default function App({ children }: { children: React.ReactNode }) {
22
34
  return (
23
35
  <YakProvider
24
36
  appId={import.meta.env.VITE_YAK_APP_ID}
37
+ mode="both" // "chat" | "voice" | "both" — default "chat"
25
38
  theme={{ position: "bottom-right", colorMode: "system" }}
39
+ // Routes + tools the assistant may use (usually your server endpoint).
26
40
  getConfig={async () => {
27
41
  const res = await fetch("/api/yak");
28
42
  return res.json();
29
43
  }}
44
+ // Execute a tool the assistant decides to call.
30
45
  onToolCall={async (name, args) => {
31
46
  const res = await fetch("/api/yak", {
32
47
  method: "POST",
@@ -45,142 +60,143 @@ export default function App({ children }: { children: React.ReactNode }) {
45
60
  }
46
61
  ```
47
62
 
48
- ### 2. Control the widget programmatically
63
+ ## Programmatic control
64
+
65
+ `useYak()` works from any component inside `YakProvider`. To skip the floating pill entirely, just don't render `<YakWidget>` and wire your own buttons:
49
66
 
50
67
  ```tsx
51
68
  import { useYak } from "@yak-io/react";
52
69
 
53
- export function HelpButton() {
70
+ function HelpButton() {
54
71
  const { open, openWithPrompt, isOpen } = useYak();
72
+ return (
73
+ <>
74
+ <button onClick={open}>Open chat</button>
75
+ <button onClick={() => openWithPrompt("How do I get started?")}>Get help</button>
76
+ {isOpen && <span>Chat is open</span>}
77
+ </>
78
+ );
79
+ }
80
+ ```
81
+
82
+ ## Voice
83
+
84
+ Set `mode="voice"` or `mode="both"` on the provider, then drive the session with the voice methods. `voiceStart()` must run from a user gesture (browser mic requirement).
85
+
86
+ ```tsx
87
+ import { useYak } from "@yak-io/react";
55
88
 
89
+ function VoiceButton() {
90
+ const { voiceToggle, voiceState, voiceIsActive, voiceLoading } = useYak();
56
91
  return (
57
- <div>
58
- <button onClick={open}>Open Chat</button>
59
- <button onClick={() => openWithPrompt("How do I get started?")}>
60
- Get Help
61
- </button>
62
- {isOpen && <p>Chat is open</p>}
63
- </div>
92
+ <button onClick={voiceToggle} disabled={voiceLoading}>
93
+ {voiceIsActive ? `Stop (${voiceState})` : "Start voice"}
94
+ </button>
64
95
  );
65
96
  }
66
97
  ```
67
98
 
68
- ### 3. Invalidate data after tool calls
99
+ ## Tool events
100
+
101
+ Re-sync your UI when the assistant changes data:
69
102
 
70
103
  ```tsx
71
104
  import { useYakToolEvent } from "@yak-io/react";
72
105
 
73
106
  function TasksPage() {
74
- const [tasks, setTasks] = useState([]);
75
-
76
- // Re-fetch when the chatbot modifies tasks
77
107
  useYakToolEvent((event) => {
78
- if (event.ok && event.name.startsWith("tasks.")) {
79
- fetchTasks().then(setTasks);
80
- }
108
+ // { name, args, ok, result?, error? }
109
+ if (event.ok && event.name.startsWith("tasks.")) refetchTasks();
81
110
  });
82
-
83
111
  // ...
84
112
  }
85
113
  ```
86
114
 
87
- ## API Reference
115
+ ## API reference
88
116
 
89
- ### `YakProvider`
117
+ ### `<YakProvider>`
90
118
 
91
- Sets up context, initializes the widget, and delegates DOM rendering to `@yak-io/javascript`.
119
+ | Prop | Type | Default | Description |
120
+ | --- | --- | --- | --- |
121
+ | `appId` | `string` | — | Your Yak app ID (required). |
122
+ | `children` | `ReactNode` | — | Your app (required). |
123
+ | `mode` | `"chat" \| "voice" \| "both"` | `"chat"` | Which surfaces are exposed. |
124
+ | `getConfig` | `ChatConfigProvider` | — | Async provider of routes + tools. Called on open / voice start. |
125
+ | `onToolCall` | `ToolCallHandler` | — | Executes a tool the assistant calls. || `theme` | `Theme` | — | Position, color mode, and colors. |
126
+ | `onRedirect` | `(path: string) => void` | `window.location.assign` | Navigation handler. |
127
+ | `disableRestartButton` | `boolean` | `false` | Hide the restart-session button. |
128
+ | `trigger` | `boolean \| TriggerButtonConfig` | `false` | Render the provider's built-in pill. Leave `false` and use `<YakWidget>` instead. |
129
+ | `user` | `UserIdentity` | — | Signed end-user identity for conversation persistence. See [end-user identity](https://docs.yak.io/docs/customization/end-user-identity). |
92
130
 
93
- **Props:**
131
+ ### `<YakWidget>`
94
132
 
95
- | Prop | Type | Required | Description |
96
- |------|------|----------|-------------|
97
- | `appId` | `string` | ✅ | Your Yak app ID |
98
- | `children` | `ReactNode` | ✅ | Your app content |
99
- | `getConfig` | `ChatConfigProvider` | — | Async function returning routes + tools config. Called when the widget opens. |
100
- | `onToolCall` | `ToolCallHandler` | — | Handle tool calls from the assistant |
101
- | `onGraphQLSchemaCall` | `GraphQLSchemaHandler` | — | Handle GraphQL schema tool calls |
102
- | `onRESTSchemaCall` | `RESTSchemaHandler` | — | Handle REST/OpenAPI schema tool calls |
103
- | `theme` | `Theme` | — | Widget theme (position, colorMode, colors) |
104
- | `onRedirect` | `(path: string) => void` | — | Custom navigation handler (defaults to `window.location.assign`) |
105
- | `disableRestartButton` | `boolean` | — | Hide the restart session button |
106
- | `trigger` | `boolean \| TriggerButtonConfig` | — | Built-in trigger button config (`false` by default — use `<YakWidget>` instead) |
133
+ The floating launcher pill. Shows a chat icon, a voice icon, or both, based on `mode`.
107
134
 
108
- ### `YakWidget`
135
+ | Prop | Type | Default | Description |
136
+ | --- | --- | --- | --- |
137
+ | `mode` | `"chat" \| "voice" \| "both"` | inherits provider | Override which icons appear. |
138
+ | `lightButton` | `{ background?, color?, border? }` | — | Pill colors in light mode. |
139
+ | `darkButton` | `{ background?, color?, border? }` | — | Pill colors in dark mode. |
109
140
 
110
- Renders a fixed-position launcher button. Place it anywhere inside `YakProvider`.
111
-
112
- **Props:**
113
-
114
- | Prop | Type | Description |
115
- |------|------|-------------|
116
- | `triggerLabel` | `string` | Button label (default: `"Ask with AI"`) |
117
- | `position` | `WidgetPosition` | Button position (default: `"bottom-right"`) |
118
- | `colorMode` | `"light" \| "dark" \| "system"` | Color mode override |
119
- | `lightButton` | `{ background?, color?, border? }` | Custom light mode button colors |
120
- | `darkButton` | `{ background?, color?, border? }` | Custom dark mode button colors |
141
+ > Position and color mode come from the provider's `theme` (`theme.position`, `theme.colorMode`) not from `YakWidget` props.
121
142
 
122
143
  ### `useYak()`
123
144
 
124
- Access the widget API from any component inside `YakProvider`.
145
+ Returns `YakContextValue`. Throws if used outside `YakProvider`.
125
146
 
126
147
  ```ts
127
148
  const {
128
- isOpen, // boolean — whether the widget is open
129
- isReady, // boolean — whether the iframe is ready
130
- open, // () => void
131
- close, // () => void
132
- openWithPrompt, // (prompt: string) => void
149
+ // chat
150
+ isOpen, // boolean
151
+ isReady, // boolean iframe ready to receive messages
152
+ chatLoading, // boolean — isOpen && !isReady (show a loading spinner)
153
+ open, // () => void
154
+ close, // () => void
155
+ openWithPrompt, // (prompt: string) => void
156
+ // voice
157
+ voiceState, // "idle" | "connecting" | "listening" | "thinking" | "speaking" | "error"
158
+ voiceMachine, // { state, errorMessage? }
159
+ voiceIsActive, // boolean — connecting/listening/thinking/speaking
160
+ voiceLoading, // boolean — voiceState === "connecting"
161
+ voiceErrorMessage, // string | undefined
162
+ voiceStart, // () => Promise<void>
163
+ voiceStop, // () => Promise<void>
164
+ voiceToggle, // () => Promise<void>
165
+ // misc
166
+ mode, // "chat" | "voice" | "both"
133
167
  subscribeToToolEvents, // (handler) => () => void
134
168
  } = useYak();
135
169
  ```
136
170
 
137
- Throws if called outside `YakProvider`.
138
-
139
- ### `useYakToolEvent(handler)`
140
-
141
- Subscribe to tool call completion events. Automatically unsubscribes on unmount. Useful for cache invalidation when the chatbot modifies data.
142
-
143
- ```ts
144
- useYakToolEvent((event) => {
145
- // event.name — the tool name called ("tasks.list")
146
- // event.args — arguments passed to the tool
147
- // event.ok — whether the call succeeded
148
- // event.result — the result (if ok)
149
- // event.error — error message (if not ok)
150
- });
151
- ```
152
-
153
171
  ## Logging
154
172
 
155
173
  ```ts
156
174
  import { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-io/react";
157
175
 
158
- enableYakLogging(); // Enable verbose SDK logs
159
- disableYakLogging(); // Disable SDK logs
160
- isYakLoggingEnabled(); // → boolean
176
+ enableYakLogging(); // verbose SDK logs
161
177
  ```
162
178
 
163
179
  ## Types
164
180
 
165
- All key types are re-exported for convenience:
166
-
167
181
  ```ts
168
182
  import type {
183
+ YakProviderProps,
184
+ YakWidgetProps,
185
+ YakContextValue,
169
186
  ChatConfigProvider,
170
187
  ToolCallHandler,
171
188
  ToolCallEvent,
172
- GraphQLSchemaHandler,
173
- RESTSchemaHandler,
189
+ ToolAdapter,
190
+ YakToolset,
191
+ YakServerAdapterConfig,
174
192
  Theme,
175
- ThemeColors,
176
- TriggerButtonConfig,
193
+ WidgetMode,
177
194
  WidgetPosition,
178
- SchemaSource,
179
- GraphQLSchemaSource,
180
- OpenAPISchemaSource,
195
+ VoiceState,
196
+ VoiceMachine,
181
197
  } from "@yak-io/react";
182
198
  ```
183
199
 
184
200
  ## License
185
201
 
186
- Proprietary — see LICENSE file.
202
+ Proprietary — see [LICENSE](./LICENSE).
@@ -1,4 +1,4 @@
1
- import { type ChatConfigProvider, type GraphQLSchemaHandler, type RESTSchemaHandler, type Theme, type ToolCallHandler, type TriggerButtonConfig, type UserIdentity, type WidgetMode } from "@yak-io/javascript";
1
+ import { type ChatConfigProvider, type Theme, type ToolCallHandler, type TriggerButtonConfig, type UserIdentity, type WidgetMode } from "@yak-io/javascript";
2
2
  import type React from "react";
3
3
  /**
4
4
  * Props for YakProvider
@@ -6,6 +6,12 @@ import type React from "react";
6
6
  export type YakProviderProps = {
7
7
  /** App identifier in the yak SaaS */
8
8
  appId: string;
9
+ /**
10
+ * Override the origin the chat/voice runtime connects to. Defaults to
11
+ * `https://chat.yak.io`. Read once when the provider mounts; most integrators
12
+ * never set this.
13
+ */
14
+ origin?: string;
9
15
  /**
10
16
  * Which experiences this widget exposes.
11
17
  * "chat" — chat only (iframe).
@@ -25,14 +31,6 @@ export type YakProviderProps = {
25
31
  * The consuming platform decides how to execute (browser, server fetch, etc.)
26
32
  */
27
33
  onToolCall?: ToolCallHandler;
28
- /**
29
- * Handler for GraphQL schema tool calls.
30
- */
31
- onGraphQLSchemaCall?: GraphQLSchemaHandler;
32
- /**
33
- * Handler for REST/OpenAPI schema tool calls.
34
- */
35
- onRESTSchemaCall?: RESTSchemaHandler;
36
34
  /** Optional theme configuration */
37
35
  theme?: Theme;
38
36
  /** Optional redirect handler (defaults to window.location.assign) */
@@ -62,5 +60,5 @@ export type YakProviderProps = {
62
60
  * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers
63
61
  * access both surfaces via `useYak()`.
64
62
  */
65
- export declare function YakProvider({ appId, mode, getConfig, onToolCall, onGraphQLSchemaCall, onRESTSchemaCall, theme, onRedirect, disableRestartButton, trigger, user, children, }: YakProviderProps): React.JSX.Element;
63
+ export declare function YakProvider({ appId, origin, mode, getConfig, onToolCall, theme, onRedirect, disableRestartButton, trigger, user, children, }: YakProviderProps): React.JSX.Element;
66
64
  //# 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,EACvB,KAAK,oBAAoB,EAGzB,KAAK,iBAAiB,EACtB,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;;;;;;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;;OAEG;IACH,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;IAC3C;;OAEG;IACH,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,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,IAAa,EACb,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,EACL,UAAU,EACV,oBAAoB,EACpB,OAAe,EACf,IAAI,EACJ,QAAQ,GACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA6MtC"}
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,GAAG,CAAC,OAAO,CA4MtC"}
@@ -8,7 +8,7 @@ import { YakContext } from "./context.js";
8
8
  * (panel, iframe, optional trigger) is delegated to YakEmbed. Consumers
9
9
  * access both surfaces via `useYak()`.
10
10
  */
11
- export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGraphQLSchemaCall, onRESTSchemaCall, theme, onRedirect, disableRestartButton, trigger = false, user, children, }) {
11
+ export function YakProvider({ appId, origin, mode = "chat", getConfig, onToolCall, theme, onRedirect, disableRestartButton, trigger = false, user, children, }) {
12
12
  const [isOpen, setIsOpen] = useState(false);
13
13
  const [isReady, setIsReady] = useState(false);
14
14
  const [voiceMachine, setVoiceMachine] = useState(INITIAL_VOICE_MACHINE);
@@ -45,13 +45,12 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
45
45
  if (!embedRef.current) {
46
46
  embedRef.current = new YakEmbed({
47
47
  appId,
48
+ origin,
48
49
  mode,
49
50
  theme,
50
51
  trigger,
51
52
  getConfig,
52
53
  onToolCall,
53
- onGraphQLSchemaCall,
54
- onRESTSchemaCall,
55
54
  onRedirect: resolvedRedirect,
56
55
  options: { disableRestartButton },
57
56
  onToolCallComplete: handleToolCallComplete,
@@ -79,8 +78,6 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
79
78
  embed.getClient().updateConfig({
80
79
  appId,
81
80
  onToolCall,
82
- onGraphQLSchemaCall,
83
- onRESTSchemaCall,
84
81
  theme,
85
82
  onRedirect: resolvedRedirect,
86
83
  options: { disableRestartButton },
@@ -91,16 +88,12 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
91
88
  appId,
92
89
  getConfig,
93
90
  onToolCall,
94
- onGraphQLSchemaCall,
95
- onRESTSchemaCall,
96
91
  onRedirect: resolvedRedirect,
97
92
  });
98
93
  }, [
99
94
  appId,
100
95
  getConfig,
101
96
  onToolCall,
102
- onGraphQLSchemaCall,
103
- onRESTSchemaCall,
104
97
  theme,
105
98
  resolvedRedirect,
106
99
  disableRestartButton,
@@ -158,10 +151,13 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
158
151
  const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);
159
152
  const voiceState = voiceMachine.state;
160
153
  const voiceIsActive = voiceState !== "idle" && voiceState !== "error";
154
+ const chatLoading = isOpen && !isReady;
155
+ const voiceLoading = voiceState === "connecting";
161
156
  const contextValue = useMemo(() => ({
162
157
  mode,
163
158
  isOpen,
164
159
  isReady,
160
+ chatLoading,
165
161
  open,
166
162
  close,
167
163
  openWithPrompt,
@@ -170,6 +166,7 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
170
166
  voiceState,
171
167
  voiceErrorMessage: voiceMachine.errorMessage,
172
168
  voiceIsActive,
169
+ voiceLoading,
173
170
  voiceStart,
174
171
  voiceStop,
175
172
  voiceToggle,
@@ -179,6 +176,7 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
179
176
  mode,
180
177
  isOpen,
181
178
  isReady,
179
+ chatLoading,
182
180
  open,
183
181
  close,
184
182
  openWithPrompt,
@@ -186,6 +184,7 @@ export function YakProvider({ appId, mode = "chat", getConfig, onToolCall, onGra
186
184
  voiceMachine,
187
185
  voiceState,
188
186
  voiceIsActive,
187
+ voiceLoading,
189
188
  voiceStart,
190
189
  voiceStop,
191
190
  voiceToggle,
@@ -1 +1 @@
1
- {"version":3,"file":"YakWidget.d.ts","sourceRoot":"","sources":["../src/YakWidget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,yCAAyC;IACzC,UAAU,CAAC,EAAE;QACX,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAsGF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,WAAW,EACX,UAAU,GACX,GAAE,cAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkEzC"}
1
+ {"version":3,"file":"YakWidget.d.ts","sourceRoot":"","sources":["../src/YakWidget.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE;QACZ,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,yCAAyC;IACzC,UAAU,CAAC,EAAE;QACX,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAsGF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,WAAW,EACX,UAAU,GACX,GAAE,cAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAmEzC"}
package/dist/YakWidget.js CHANGED
@@ -68,8 +68,9 @@ export function YakWidget({ mode, lightButton, darkButton, } = {}) {
68
68
  const logoUrl = `${ctx.getIframeOrigin()}/logo.svg`;
69
69
  const showChat = resolvedMode === "chat" || resolvedMode === "both";
70
70
  const showVoice = resolvedMode === "voice" || resolvedMode === "both";
71
- const chatLoading = ctx.isOpen && !ctx.isReady;
72
- const voiceConnecting = ctx.voiceState === "connecting";
71
+ // Consume the shipped loading flags rather than re-deriving them here.
72
+ const chatLoading = ctx.chatLoading;
73
+ const voiceConnecting = ctx.voiceLoading;
73
74
  const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;
74
75
  const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;
75
76
  const buttonStyle = buildButtonStyle(lightButton, darkButton);
package/dist/context.d.ts CHANGED
@@ -23,6 +23,11 @@ export type YakContextValue = {
23
23
  isOpen: boolean;
24
24
  /** Whether the iframe is ready to receive messages */
25
25
  isReady: boolean;
26
+ /**
27
+ * Whether the chat is opening but not yet interactive (`isOpen && !isReady`).
28
+ * Drive a custom loading state off this instead of re-deriving it.
29
+ */
30
+ chatLoading: boolean;
26
31
  /** Open the chat widget */
27
32
  open: () => void;
28
33
  /** Close the chat widget */
@@ -39,6 +44,8 @@ export type YakContextValue = {
39
44
  voiceErrorMessage: string | undefined;
40
45
  /** Whether a voice session is currently live (connecting/listening/thinking/speaking). */
41
46
  voiceIsActive: boolean;
47
+ /** Whether the voice session is still connecting (`voiceState === "connecting"`). */
48
+ voiceLoading: boolean;
42
49
  /** Start a voice session. Must be invoked from a user gesture. */
43
50
  voiceStart: () => Promise<void>;
44
51
  /** Stop the current voice session. */
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,KAAK,EACL,aAAa,EACb,YAAY,EACZ,UAAU,EACV,UAAU,EACX,MAAM,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,UAAU,CAAC;IAGjB,gDAAgD;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yDAAyD;IACzD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,+CAA+C;IAC/C,qBAAqB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAC;IAGrE,yEAAyE;IACzE,YAAY,EAAE,YAAY,CAAC;IAC3B,yCAAyC;IACzC,UAAU,EAAE,UAAU,CAAC;IACvB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,0FAA0F;IAC1F,aAAa,EAAE,OAAO,CAAC;IACvB,kEAAkE;IAClE,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,sCAAsC;IACtC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,mDAAmD;IACnD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IACtD,4DAA4D;IAC5D,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,iFAAiF;IACjF,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,UAAU,yDAAsD,CAAC;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAqBxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,uBAAuB,CAMxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAkBnE"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,KAAK,EACL,aAAa,EACb,YAAY,EACZ,UAAU,EACV,UAAU,EACX,MAAM,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAElE;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,UAAU,CAAC;IAGjB,gDAAgD;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yDAAyD;IACzD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,+CAA+C;IAC/C,qBAAqB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAC;IAGrE,yEAAyE;IACzE,YAAY,EAAE,YAAY,CAAC;IAC3B,yCAAyC;IACzC,UAAU,EAAE,UAAU,CAAC;IACvB,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,0FAA0F;IAC1F,aAAa,EAAE,OAAO,CAAC;IACvB,qFAAqF;IACrF,YAAY,EAAE,OAAO,CAAC;IACtB,kEAAkE;IAClE,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,sCAAsC;IACtC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,mDAAmD;IACnD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IACtD,4DAA4D;IAC5D,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,iFAAiF;IACjF,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,UAAU,yDAAsD,CAAC;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAuBxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,uBAAuB,CAMxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAkBnE"}
package/dist/context.js CHANGED
@@ -28,6 +28,7 @@ export function useYak() {
28
28
  mode: context.mode,
29
29
  isOpen: context.isOpen,
30
30
  isReady: context.isReady,
31
+ chatLoading: context.chatLoading,
31
32
  open: context.open,
32
33
  close: context.close,
33
34
  openWithPrompt: context.openWithPrompt,
@@ -36,6 +37,7 @@ export function useYak() {
36
37
  voiceState: context.voiceState,
37
38
  voiceErrorMessage: context.voiceErrorMessage,
38
39
  voiceIsActive: context.voiceIsActive,
40
+ voiceLoading: context.voiceLoading,
39
41
  voiceStart: context.voiceStart,
40
42
  voiceStop: context.voiceStop,
41
43
  voiceToggle: context.voiceToggle,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export type { ChatConfigProvider, GraphQLRequest, GraphQLSchemaHandler, GraphQLSchemaSource, OpenAPISchemaSource, RESTRequest, RESTSchemaHandler, SchemaSource, Theme, ThemeColors, ToolCallEvent, ToolCallHandler, TriggerButtonConfig, VoiceMachine, VoiceState, WidgetMode, WidgetPosition, } from "@yak-io/javascript";
2
- export { disableYakLogging, enableYakLogging, isYakLoggingEnabled } from "@yak-io/javascript";
1
+ export type { ChatConfigProvider, GraphQLRequest, RESTRequest, Theme, ThemeColors, ToolAdapter, ToolCallEvent, ToolCallHandler, TriggerButtonConfig, VoiceMachine, VoiceState, WidgetMode, WidgetPosition, YakServerAdapterConfig, YakToolset, } from "@yak-io/javascript";
2
+ export { createYakServerAdapter, createYakToolset, disableYakLogging, enableYakLogging, isYakLoggingEnabled, } from "@yak-io/javascript";
3
3
  export type { ToolCallEventHandler, YakConfig, YakContextValue } from "./context.js";
4
4
  export { useYak, useYakToolEvent } from "./context.js";
5
5
  export type { YakProviderProps } from "./YakProvider.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,KAAK,EACL,WAAW,EACX,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,KAAK,EACL,WAAW,EACX,WAAW,EACX,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,UAAU,GACX,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,oBAAoB,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  // Re-export useful types and constants from @yak-io/javascript for consumers
3
- export { disableYakLogging, enableYakLogging, isYakLoggingEnabled } from "@yak-io/javascript";
3
+ export { createYakServerAdapter, createYakToolset, disableYakLogging, enableYakLogging, isYakLoggingEnabled, } from "@yak-io/javascript";
4
4
  // Public API - only export what consumers need
5
5
  export { useYak, useYakToolEvent } from "./context.js";
6
6
  export { YakProvider } from "./YakProvider.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/react",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "React SDK for embedding yak chatbot",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -25,6 +25,7 @@
25
25
  "node": ">=18"
26
26
  },
27
27
  "files": [
28
+ "README.md",
28
29
  "dist",
29
30
  "LICENSE"
30
31
  ],
@@ -41,7 +42,7 @@
41
42
  "./package.json": "./package.json"
42
43
  },
43
44
  "dependencies": {
44
- "@yak-io/javascript": "0.8.0"
45
+ "@yak-io/javascript": "0.10.0"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "react": "^18.0.0 || ^19.0.0",
@@ -59,6 +60,7 @@
59
60
  "typescript": "^5.3.0",
60
61
  "@repo/typescript-config": "0.0.0"
61
62
  },
63
+ "homepage": "https://docs.yak.io/docs/sdks/react",
62
64
  "scripts": {
63
65
  "build": "tsc",
64
66
  "check-types": "tsc --noEmit",