@yak-io/react 0.7.1 → 0.8.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 ADDED
@@ -0,0 +1,186 @@
1
+ # @yak-io/react
2
+
3
+ React integration for the Yak embeddable chat widget. Provides `YakProvider`, `YakWidget`, `useYak`, and `useYakToolEvent`.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @yak-io/react
9
+ ```
10
+
11
+ For Next.js, use [`@yak-io/nextjs`](../nextjs) instead — it adds route scanning and server handler factories on top of this package.
12
+
13
+ ## Quickstart
14
+
15
+ ### 1. Wrap your app with `YakProvider`
16
+
17
+ ```tsx
18
+ // src/App.tsx (or your root layout)
19
+ import { YakProvider, YakWidget } from "@yak-io/react";
20
+
21
+ export default function App({ children }: { children: React.ReactNode }) {
22
+ return (
23
+ <YakProvider
24
+ appId={import.meta.env.VITE_YAK_APP_ID}
25
+ theme={{ position: "bottom-right", colorMode: "system" }}
26
+ getConfig={async () => {
27
+ const res = await fetch("/api/yak");
28
+ return res.json();
29
+ }}
30
+ onToolCall={async (name, args) => {
31
+ const res = await fetch("/api/yak", {
32
+ method: "POST",
33
+ headers: { "Content-Type": "application/json" },
34
+ body: JSON.stringify({ name, args }),
35
+ });
36
+ const data = await res.json();
37
+ if (!data.ok) throw new Error(data.error);
38
+ return data.result;
39
+ }}
40
+ >
41
+ {children}
42
+ <YakWidget />
43
+ </YakProvider>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ### 2. Control the widget programmatically
49
+
50
+ ```tsx
51
+ import { useYak } from "@yak-io/react";
52
+
53
+ export function HelpButton() {
54
+ const { open, openWithPrompt, isOpen } = useYak();
55
+
56
+ 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>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### 3. Invalidate data after tool calls
69
+
70
+ ```tsx
71
+ import { useYakToolEvent } from "@yak-io/react";
72
+
73
+ function TasksPage() {
74
+ const [tasks, setTasks] = useState([]);
75
+
76
+ // Re-fetch when the chatbot modifies tasks
77
+ useYakToolEvent((event) => {
78
+ if (event.ok && event.name.startsWith("tasks.")) {
79
+ fetchTasks().then(setTasks);
80
+ }
81
+ });
82
+
83
+ // ...
84
+ }
85
+ ```
86
+
87
+ ## API Reference
88
+
89
+ ### `YakProvider`
90
+
91
+ Sets up context, initializes the widget, and delegates DOM rendering to `@yak-io/javascript`.
92
+
93
+ **Props:**
94
+
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) |
107
+
108
+ ### `YakWidget`
109
+
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 |
121
+
122
+ ### `useYak()`
123
+
124
+ Access the widget API from any component inside `YakProvider`.
125
+
126
+ ```ts
127
+ 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
133
+ subscribeToToolEvents, // (handler) => () => void
134
+ } = useYak();
135
+ ```
136
+
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
+ ## Logging
154
+
155
+ ```ts
156
+ import { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-io/react";
157
+
158
+ enableYakLogging(); // Enable verbose SDK logs
159
+ disableYakLogging(); // Disable SDK logs
160
+ isYakLoggingEnabled(); // → boolean
161
+ ```
162
+
163
+ ## Types
164
+
165
+ All key types are re-exported for convenience:
166
+
167
+ ```ts
168
+ import type {
169
+ ChatConfigProvider,
170
+ ToolCallHandler,
171
+ ToolCallEvent,
172
+ GraphQLSchemaHandler,
173
+ RESTSchemaHandler,
174
+ Theme,
175
+ ThemeColors,
176
+ TriggerButtonConfig,
177
+ WidgetPosition,
178
+ SchemaSource,
179
+ GraphQLSchemaSource,
180
+ OpenAPISchemaSource,
181
+ } from "@yak-io/react";
182
+ ```
183
+
184
+ ## License
185
+
186
+ Proprietary — see LICENSE file.
@@ -11,7 +11,7 @@ import { logger } from "@yak-io/javascript";
11
11
  */
12
12
  export function YakProvider({ appId, getConfig, onToolCall, onGraphQLSchemaCall, onRESTSchemaCall, theme, onRedirect, disableRestartButton, trigger = false, children, }) {
13
13
  const [isOpen, setIsOpen] = useState(false);
14
- const [isIframeReady, setIsIframeReady] = useState(false);
14
+ const [isReady, setIsReady] = useState(false);
15
15
  // Store event subscribers for tool call events
16
16
  const toolEventSubscribersRef = useRef(new Set());
17
17
  // Handler that notifies all subscribers when a tool call completes
@@ -61,7 +61,7 @@ export function YakProvider({ appId, getConfig, onToolCall, onGraphQLSchemaCall,
61
61
  embed.mount();
62
62
  const unsubscribe = embed.onStateChange((state) => {
63
63
  setIsOpen(state.isOpen);
64
- setIsIframeReady(state.isReady);
64
+ setIsReady(state.isReady);
65
65
  });
66
66
  return () => {
67
67
  unsubscribe();
@@ -130,12 +130,12 @@ export function YakProvider({ appId, getConfig, onToolCall, onGraphQLSchemaCall,
130
130
  const getIframeOrigin = useCallback(() => embed.getClient().getIframeOrigin(), [embed]);
131
131
  const contextValue = useMemo(() => ({
132
132
  isOpen,
133
- isIframeReady,
133
+ isReady,
134
134
  open,
135
135
  close,
136
136
  openWithPrompt,
137
137
  subscribeToToolEvents,
138
138
  getIframeOrigin,
139
- }), [isOpen, isIframeReady, open, close, openWithPrompt, subscribeToToolEvents, getIframeOrigin]);
139
+ }), [isOpen, isReady, open, close, openWithPrompt, subscribeToToolEvents, getIframeOrigin]);
140
140
  return _jsx(YakContext.Provider, { value: contextValue, children: children });
141
141
  }
package/dist/YakWidget.js CHANGED
@@ -41,10 +41,10 @@ function buildButtonClasses(colorMode, hasLightCustom, hasDarkCustom) {
41
41
  * only provides the React button element using those shared class names.
42
42
  */
43
43
  export function YakWidget({ triggerLabel = "Ask with AI", position = "bottom-right", colorMode, lightButton, darkButton, } = {}) {
44
- const { open, isOpen, isIframeReady } = useYak();
44
+ const { open, isOpen, isReady } = useYak();
45
45
  const internal = useContext(YakContext);
46
46
  const logoUrl = internal ? `${internal.getIframeOrigin()}/logo.svg` : "";
47
- const isLoading = isOpen && !isIframeReady;
47
+ const isLoading = isOpen && !isReady;
48
48
  const hasLightCustom = lightButton?.background || lightButton?.color || lightButton?.border;
49
49
  const hasDarkCustom = darkButton?.background || darkButton?.color || darkButton?.border;
50
50
  const buttonStyle = buildButtonStyle(lightButton, darkButton);
package/dist/context.d.ts CHANGED
@@ -20,7 +20,7 @@ export type YakContextValue = {
20
20
  /** Whether the chat widget is currently open */
21
21
  isOpen: boolean;
22
22
  /** Whether the iframe is ready to receive messages */
23
- isIframeReady: boolean;
23
+ isReady: boolean;
24
24
  /** Open the chat widget */
25
25
  open: () => void;
26
26
  /** Close the chat widget */
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAE3E;;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,gDAAgD;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,aAAa,EAAE,OAAO,CAAC;IACvB,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;CACtE,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IACtD,4DAA4D;IAC5D,eAAe,EAAE,MAAM,MAAM,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,UAAU,yDAAsD,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAcxC;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":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAE3E;;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,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;CACtE,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IACtD,4DAA4D;IAC5D,eAAe,EAAE,MAAM,MAAM,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,UAAU,yDAAsD,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAcxC;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
@@ -29,7 +29,7 @@ export function useYak() {
29
29
  // Return only the public API
30
30
  return {
31
31
  isOpen: context.isOpen,
32
- isIframeReady: context.isIframeReady,
32
+ isReady: context.isReady,
33
33
  open: context.open,
34
34
  close: context.close,
35
35
  openWithPrompt: context.openWithPrompt,
package/dist/index.d.ts CHANGED
@@ -4,5 +4,6 @@ export { YakProvider } from "./YakProvider.js";
4
4
  export type { YakProviderProps } from "./YakProvider.js";
5
5
  export { YakWidget } from "./YakWidget.js";
6
6
  export type { YakWidgetProps } from "./YakWidget.js";
7
- export type { GraphQLSchemaHandler, RESTSchemaHandler, GraphQLRequest, RESTRequest, ToolCallHandler, ToolCallEvent, SchemaSource, GraphQLSchemaSource, OpenAPISchemaSource, Theme, ThemeColors, TriggerButtonConfig, WidgetPosition, } from "@yak-io/javascript";
7
+ export { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-io/javascript";
8
+ export type { GraphQLSchemaHandler, RESTSchemaHandler, GraphQLRequest, RESTRequest, ToolCallHandler, ToolCallEvent, SchemaSource, GraphQLSchemaSource, OpenAPISchemaSource, Theme, ThemeColors, TriggerButtonConfig, WidgetPosition, ChatConfigProvider, } from "@yak-io/javascript";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,EACf,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,EACf,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -3,3 +3,5 @@
3
3
  export { useYak, useYakToolEvent } from "./context.js";
4
4
  export { YakProvider } from "./YakProvider.js";
5
5
  export { YakWidget } from "./YakWidget.js";
6
+ // Re-export useful types and constants from @yak-io/javascript for consumers
7
+ export { enableYakLogging, disableYakLogging, isYakLoggingEnabled } from "@yak-io/javascript";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yak-io/react",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "React SDK for embedding yak chatbot",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -41,7 +41,7 @@
41
41
  "./package.json": "./package.json"
42
42
  },
43
43
  "dependencies": {
44
- "@yak-io/javascript": "0.6.0"
44
+ "@yak-io/javascript": "0.7.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "react": "^18.0.0 || ^19.0.0",