@cstar.help/react 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,494 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ CStarChatContext: () => CStarChatContext,
24
+ CStarChatProvider: () => CStarChatProvider,
25
+ CStarLibraryContext: () => CStarLibraryContext,
26
+ CStarLibraryProvider: () => CStarLibraryProvider,
27
+ useArticle: () => useArticle,
28
+ useArticleSearch: () => useArticleSearch,
29
+ useArticles: () => useArticles,
30
+ useCategories: () => useCategories,
31
+ useChat: () => useChat,
32
+ useChatClient: () => useChatClient,
33
+ useConversations: () => useConversations,
34
+ useLibraryClient: () => useLibraryClient,
35
+ useMessages: () => useMessages,
36
+ useTyping: () => useTyping
37
+ });
38
+ module.exports = __toCommonJS(src_exports);
39
+
40
+ // src/context.tsx
41
+ var import_react = require("react");
42
+ var CStarChatContext = (0, import_react.createContext)(null);
43
+ var CStarLibraryContext = (0, import_react.createContext)(null);
44
+ function useChatClient() {
45
+ const client = (0, import_react.useContext)(CStarChatContext);
46
+ if (!client) {
47
+ throw new Error("useChatClient must be used within a <CStarChatProvider>");
48
+ }
49
+ return client;
50
+ }
51
+ function useLibraryClient() {
52
+ const client = (0, import_react.useContext)(CStarLibraryContext);
53
+ if (!client) {
54
+ throw new Error("useLibraryClient must be used within a <CStarLibraryProvider>");
55
+ }
56
+ return client;
57
+ }
58
+
59
+ // src/chat/CStarChatProvider.tsx
60
+ var import_react2 = require("react");
61
+ var import_chat = require("@cstar.help/js/chat");
62
+ var import_jsx_runtime = require("react/jsx-runtime");
63
+ function CStarChatProvider({ children, ...config }) {
64
+ const clientRef = (0, import_react2.useRef)(null);
65
+ if (!clientRef.current) {
66
+ clientRef.current = new import_chat.ChatClient(config);
67
+ }
68
+ (0, import_react2.useEffect)(() => {
69
+ return () => {
70
+ clientRef.current?.disconnect();
71
+ clientRef.current = null;
72
+ };
73
+ }, []);
74
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CStarChatContext.Provider, { value: clientRef.current, children });
75
+ }
76
+
77
+ // src/chat/useChat.ts
78
+ var import_react3 = require("react");
79
+ function useChat() {
80
+ const client = useChatClient();
81
+ const [isIdentified, setIsIdentified] = (0, import_react3.useState)(false);
82
+ const [isRealtimeReady, setIsRealtimeReady] = (0, import_react3.useState)(false);
83
+ const [error, setError] = (0, import_react3.useState)(null);
84
+ const identify = (0, import_react3.useCallback)(
85
+ async (customer, signature) => {
86
+ setError(null);
87
+ try {
88
+ const result = await client.identify(customer, signature);
89
+ setIsIdentified(true);
90
+ client.waitForRealtime().then(() => {
91
+ setIsRealtimeReady(true);
92
+ }).catch(() => {
93
+ });
94
+ return result;
95
+ } catch (err) {
96
+ const e = err instanceof Error ? err : new Error(String(err));
97
+ setError(e);
98
+ throw e;
99
+ }
100
+ },
101
+ [client]
102
+ );
103
+ const disconnect = (0, import_react3.useCallback)(() => {
104
+ client.disconnect();
105
+ setIsIdentified(false);
106
+ setIsRealtimeReady(false);
107
+ setError(null);
108
+ }, [client]);
109
+ return { identify, disconnect, isIdentified, isRealtimeReady, error };
110
+ }
111
+
112
+ // src/chat/useConversations.ts
113
+ var import_react4 = require("react");
114
+ function useConversations() {
115
+ const client = useChatClient();
116
+ const [conversations, setConversations] = (0, import_react4.useState)([]);
117
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
118
+ const [error, setError] = (0, import_react4.useState)(null);
119
+ const [hasMore, setHasMore] = (0, import_react4.useState)(false);
120
+ const mountedRef = (0, import_react4.useRef)(true);
121
+ const refresh = (0, import_react4.useCallback)(async () => {
122
+ setIsLoading(true);
123
+ setError(null);
124
+ try {
125
+ const result = await client.conversations.list();
126
+ if (mountedRef.current) {
127
+ setConversations(result.conversations);
128
+ setHasMore(result.hasMore);
129
+ }
130
+ } catch (err) {
131
+ if (mountedRef.current) {
132
+ setError(err instanceof Error ? err : new Error(String(err)));
133
+ }
134
+ } finally {
135
+ if (mountedRef.current) {
136
+ setIsLoading(false);
137
+ }
138
+ }
139
+ }, [client]);
140
+ (0, import_react4.useEffect)(() => {
141
+ mountedRef.current = true;
142
+ refresh();
143
+ return () => {
144
+ mountedRef.current = false;
145
+ };
146
+ }, [refresh]);
147
+ const create = (0, import_react4.useCallback)(
148
+ async (params) => {
149
+ const conversation = await client.conversations.create(params);
150
+ if (mountedRef.current) {
151
+ setConversations((prev) => [conversation, ...prev]);
152
+ }
153
+ return conversation;
154
+ },
155
+ [client]
156
+ );
157
+ return { conversations, isLoading, error, hasMore, refresh, create };
158
+ }
159
+
160
+ // src/chat/useMessages.ts
161
+ var import_react5 = require("react");
162
+ function useMessages(ticketId) {
163
+ const client = useChatClient();
164
+ const [messages, setMessages] = (0, import_react5.useState)([]);
165
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
166
+ const [error, setError] = (0, import_react5.useState)(null);
167
+ const mountedRef = (0, import_react5.useRef)(true);
168
+ const seenIdsRef = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
169
+ const refresh = (0, import_react5.useCallback)(async () => {
170
+ if (!ticketId) return;
171
+ setIsLoading(true);
172
+ setError(null);
173
+ try {
174
+ const msgs = await client.messages.list(ticketId);
175
+ if (mountedRef.current) {
176
+ seenIdsRef.current = new Set(msgs.map((m) => m.id));
177
+ setMessages(msgs);
178
+ }
179
+ } catch (err) {
180
+ if (mountedRef.current) {
181
+ setError(err instanceof Error ? err : new Error(String(err)));
182
+ }
183
+ } finally {
184
+ if (mountedRef.current) {
185
+ setIsLoading(false);
186
+ }
187
+ }
188
+ }, [client, ticketId]);
189
+ (0, import_react5.useEffect)(() => {
190
+ mountedRef.current = true;
191
+ if (!ticketId) {
192
+ setMessages([]);
193
+ setIsLoading(false);
194
+ return;
195
+ }
196
+ refresh();
197
+ const unsubscribe = client.onMessage(ticketId, (msg) => {
198
+ if (mountedRef.current && !seenIdsRef.current.has(msg.id)) {
199
+ seenIdsRef.current.add(msg.id);
200
+ setMessages((prev) => {
201
+ const optimisticIdx = prev.findIndex(
202
+ (m) => m.id.startsWith("optimistic-") && m.content === msg.content
203
+ );
204
+ if (optimisticIdx >= 0) {
205
+ const next = [...prev];
206
+ next[optimisticIdx] = msg;
207
+ return next;
208
+ }
209
+ return [...prev, msg];
210
+ });
211
+ }
212
+ });
213
+ return () => {
214
+ mountedRef.current = false;
215
+ unsubscribe();
216
+ };
217
+ }, [client, ticketId, refresh]);
218
+ const send = (0, import_react5.useCallback)(
219
+ async (content) => {
220
+ if (!ticketId) throw new Error("No conversation selected");
221
+ const optimistic = {
222
+ id: `optimistic-${Date.now()}`,
223
+ content,
224
+ sender: "customer",
225
+ sender_name: "",
226
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
227
+ read_at: null,
228
+ attachments: []
229
+ };
230
+ setMessages((prev) => [...prev, optimistic]);
231
+ try {
232
+ const msg = await client.messages.send(ticketId, content);
233
+ seenIdsRef.current.add(msg.id);
234
+ setMessages(
235
+ (prev) => prev.map((m) => m.id === optimistic.id ? msg : m)
236
+ );
237
+ return msg;
238
+ } catch (err) {
239
+ setMessages((prev) => prev.filter((m) => m.id !== optimistic.id));
240
+ throw err;
241
+ }
242
+ },
243
+ [client, ticketId]
244
+ );
245
+ return { messages, isLoading, error, send, refresh };
246
+ }
247
+
248
+ // src/chat/useTyping.ts
249
+ var import_react6 = require("react");
250
+ var TYPING_TIMEOUT = 4e3;
251
+ function useTyping(ticketId) {
252
+ const client = useChatClient();
253
+ const [typingAgents, setTypingAgents] = (0, import_react6.useState)([]);
254
+ const timersRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
255
+ const mountedRef = (0, import_react6.useRef)(true);
256
+ (0, import_react6.useEffect)(() => {
257
+ mountedRef.current = true;
258
+ if (!ticketId) {
259
+ setTypingAgents([]);
260
+ return;
261
+ }
262
+ const unsubscribe = client.onTyping(ticketId, (payload) => {
263
+ if (!mountedRef.current) return;
264
+ const { agent_id, agent_name, is_typing } = payload;
265
+ const existing = timersRef.current.get(agent_id);
266
+ if (existing) clearTimeout(existing);
267
+ if (is_typing) {
268
+ setTypingAgents((prev) => {
269
+ if (prev.some((a) => a.agentId === agent_id)) return prev;
270
+ return [...prev, { agentId: agent_id, agentName: agent_name }];
271
+ });
272
+ const timer = setTimeout(() => {
273
+ if (mountedRef.current) {
274
+ setTypingAgents((prev) => prev.filter((a) => a.agentId !== agent_id));
275
+ timersRef.current.delete(agent_id);
276
+ }
277
+ }, TYPING_TIMEOUT);
278
+ timersRef.current.set(agent_id, timer);
279
+ } else {
280
+ setTypingAgents((prev) => prev.filter((a) => a.agentId !== agent_id));
281
+ timersRef.current.delete(agent_id);
282
+ }
283
+ });
284
+ return () => {
285
+ mountedRef.current = false;
286
+ unsubscribe();
287
+ for (const timer of timersRef.current.values()) {
288
+ clearTimeout(timer);
289
+ }
290
+ timersRef.current.clear();
291
+ };
292
+ }, [client, ticketId]);
293
+ const sendTyping = (0, import_react6.useCallback)(
294
+ async (isTyping) => {
295
+ if (!ticketId) return;
296
+ await client.sendTyping(ticketId, isTyping);
297
+ },
298
+ [client, ticketId]
299
+ );
300
+ return { typingAgents, sendTyping };
301
+ }
302
+
303
+ // src/library/CStarLibraryProvider.tsx
304
+ var import_react7 = require("react");
305
+ var import_library = require("@cstar.help/js/library");
306
+ var import_jsx_runtime2 = require("react/jsx-runtime");
307
+ function CStarLibraryProvider({ children, ...config }) {
308
+ const clientRef = (0, import_react7.useRef)(null);
309
+ if (!clientRef.current) {
310
+ clientRef.current = new import_library.LibraryClient(config);
311
+ }
312
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CStarLibraryContext.Provider, { value: clientRef.current, children });
313
+ }
314
+
315
+ // src/library/useCategories.ts
316
+ var import_react8 = require("react");
317
+ function useCategories() {
318
+ const client = useLibraryClient();
319
+ const [categories, setCategories] = (0, import_react8.useState)([]);
320
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
321
+ const [error, setError] = (0, import_react8.useState)(null);
322
+ const mountedRef = (0, import_react8.useRef)(true);
323
+ const refresh = (0, import_react8.useCallback)(async () => {
324
+ setIsLoading(true);
325
+ setError(null);
326
+ try {
327
+ const data = await client.categories();
328
+ if (mountedRef.current) {
329
+ setCategories(data);
330
+ }
331
+ } catch (err) {
332
+ if (mountedRef.current) {
333
+ setError(err instanceof Error ? err : new Error(String(err)));
334
+ }
335
+ } finally {
336
+ if (mountedRef.current) {
337
+ setIsLoading(false);
338
+ }
339
+ }
340
+ }, [client]);
341
+ (0, import_react8.useEffect)(() => {
342
+ mountedRef.current = true;
343
+ refresh();
344
+ return () => {
345
+ mountedRef.current = false;
346
+ };
347
+ }, [refresh]);
348
+ return { categories, isLoading, error, refresh };
349
+ }
350
+
351
+ // src/library/useArticles.ts
352
+ var import_react9 = require("react");
353
+ function useArticles(params) {
354
+ const client = useLibraryClient();
355
+ const [articles, setArticles] = (0, import_react9.useState)([]);
356
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(true);
357
+ const [error, setError] = (0, import_react9.useState)(null);
358
+ const mountedRef = (0, import_react9.useRef)(true);
359
+ const categorySlug = params?.categorySlug;
360
+ const limit = params?.limit;
361
+ const offset = params?.offset;
362
+ const refresh = (0, import_react9.useCallback)(async () => {
363
+ setIsLoading(true);
364
+ setError(null);
365
+ try {
366
+ const data = await client.articles({ categorySlug, limit, offset });
367
+ if (mountedRef.current) {
368
+ setArticles(data);
369
+ }
370
+ } catch (err) {
371
+ if (mountedRef.current) {
372
+ setError(err instanceof Error ? err : new Error(String(err)));
373
+ }
374
+ } finally {
375
+ if (mountedRef.current) {
376
+ setIsLoading(false);
377
+ }
378
+ }
379
+ }, [client, categorySlug, limit, offset]);
380
+ (0, import_react9.useEffect)(() => {
381
+ mountedRef.current = true;
382
+ refresh();
383
+ return () => {
384
+ mountedRef.current = false;
385
+ };
386
+ }, [refresh]);
387
+ return { articles, isLoading, error, refresh };
388
+ }
389
+
390
+ // src/library/useArticle.ts
391
+ var import_react10 = require("react");
392
+ function useArticle(slug) {
393
+ const client = useLibraryClient();
394
+ const [article, setArticle] = (0, import_react10.useState)(null);
395
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
396
+ const [error, setError] = (0, import_react10.useState)(null);
397
+ const mountedRef = (0, import_react10.useRef)(true);
398
+ const refresh = (0, import_react10.useCallback)(async () => {
399
+ if (!slug) return;
400
+ setIsLoading(true);
401
+ setError(null);
402
+ try {
403
+ const data = await client.article(slug);
404
+ if (mountedRef.current) {
405
+ setArticle(data);
406
+ }
407
+ } catch (err) {
408
+ if (mountedRef.current) {
409
+ setError(err instanceof Error ? err : new Error(String(err)));
410
+ }
411
+ } finally {
412
+ if (mountedRef.current) {
413
+ setIsLoading(false);
414
+ }
415
+ }
416
+ }, [client, slug]);
417
+ (0, import_react10.useEffect)(() => {
418
+ mountedRef.current = true;
419
+ if (!slug) {
420
+ setArticle(null);
421
+ setIsLoading(false);
422
+ return;
423
+ }
424
+ refresh();
425
+ return () => {
426
+ mountedRef.current = false;
427
+ };
428
+ }, [slug, refresh]);
429
+ return { article, isLoading, error, refresh };
430
+ }
431
+
432
+ // src/library/useArticleSearch.ts
433
+ var import_react11 = require("react");
434
+ var DEBOUNCE_MS = 300;
435
+ function useArticleSearch(query) {
436
+ const client = useLibraryClient();
437
+ const [results, setResults] = (0, import_react11.useState)([]);
438
+ const [totalCount, setTotalCount] = (0, import_react11.useState)(0);
439
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
440
+ const [error, setError] = (0, import_react11.useState)(null);
441
+ const mountedRef = (0, import_react11.useRef)(true);
442
+ (0, import_react11.useEffect)(() => {
443
+ mountedRef.current = true;
444
+ const trimmed = query.trim();
445
+ if (!trimmed) {
446
+ setResults([]);
447
+ setTotalCount(0);
448
+ setIsLoading(false);
449
+ setError(null);
450
+ return;
451
+ }
452
+ setIsLoading(true);
453
+ const timer = setTimeout(async () => {
454
+ try {
455
+ const result = await client.search(trimmed);
456
+ if (mountedRef.current) {
457
+ setResults(result.data);
458
+ setTotalCount(result.count);
459
+ setError(null);
460
+ }
461
+ } catch (err) {
462
+ if (mountedRef.current) {
463
+ setError(err instanceof Error ? err : new Error(String(err)));
464
+ }
465
+ } finally {
466
+ if (mountedRef.current) {
467
+ setIsLoading(false);
468
+ }
469
+ }
470
+ }, DEBOUNCE_MS);
471
+ return () => {
472
+ mountedRef.current = false;
473
+ clearTimeout(timer);
474
+ };
475
+ }, [client, query]);
476
+ return { results, totalCount, isLoading, error };
477
+ }
478
+ // Annotate the CommonJS export names for ESM import in node:
479
+ 0 && (module.exports = {
480
+ CStarChatContext,
481
+ CStarChatProvider,
482
+ CStarLibraryContext,
483
+ CStarLibraryProvider,
484
+ useArticle,
485
+ useArticleSearch,
486
+ useArticles,
487
+ useCategories,
488
+ useChat,
489
+ useChatClient,
490
+ useConversations,
491
+ useLibraryClient,
492
+ useMessages,
493
+ useTyping
494
+ });
@@ -0,0 +1,218 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { ChatClient, ChatConfig, IdentifyParams, IdentifyResult, Conversation, ConversationCreateParams, WidgetMessage } from '@cstar.help/js/chat';
4
+ export { ChatConfig, Conversation, ConversationCreateParams, ConversationListResponse, IdentifyParams, IdentifyResult, TypingPayload, WidgetMessage } from '@cstar.help/js/chat';
5
+ import { LibraryClient, LibraryConfig, Category, LibraryArticle, LibraryArticleListParams } from '@cstar.help/js/library';
6
+ export { Category, LibraryArticle, LibraryArticleListParams, LibraryConfig, LibrarySearchParams, LibrarySearchResult } from '@cstar.help/js/library';
7
+ import * as react_jsx_runtime from 'react/jsx-runtime';
8
+
9
+ declare const CStarChatContext: react.Context<ChatClient | null>;
10
+ declare const CStarLibraryContext: react.Context<LibraryClient | null>;
11
+ /**
12
+ * Access the ChatClient from the nearest CStarChatProvider.
13
+ * Throws if used outside a provider.
14
+ */
15
+ declare function useChatClient(): ChatClient;
16
+ /**
17
+ * Access the LibraryClient from the nearest CStarLibraryProvider.
18
+ * Throws if used outside a provider.
19
+ */
20
+ declare function useLibraryClient(): LibraryClient;
21
+
22
+ interface CStarChatProviderProps extends ChatConfig {
23
+ children: ReactNode;
24
+ }
25
+ /**
26
+ * Provides a ChatClient instance to all child components.
27
+ * Creates the client on mount and disconnects on unmount.
28
+ *
29
+ * ```tsx
30
+ * <CStarChatProvider teamSlug="acme" supabaseUrl="..." supabaseAnonKey="...">
31
+ * <ChatWidget />
32
+ * </CStarChatProvider>
33
+ * ```
34
+ */
35
+ declare function CStarChatProvider({ children, ...config }: CStarChatProviderProps): react_jsx_runtime.JSX.Element;
36
+
37
+ interface UseChatReturn {
38
+ /** Identify a customer with HMAC signature. */
39
+ identify: (customer: IdentifyParams, signature: string) => Promise<IdentifyResult>;
40
+ /** Disconnect the client and clean up all subscriptions. */
41
+ disconnect: () => void;
42
+ /** Whether a customer has been successfully identified. */
43
+ isIdentified: boolean;
44
+ /** Whether the Supabase Realtime connection is ready. */
45
+ isRealtimeReady: boolean;
46
+ /** The last error from identify, or null. */
47
+ error: Error | null;
48
+ }
49
+ /**
50
+ * Core chat hook — manages identity verification and realtime readiness.
51
+ *
52
+ * ```tsx
53
+ * const { identify, disconnect, isIdentified, isRealtimeReady, error } = useChat();
54
+ *
55
+ * await identify(
56
+ * { externalId: 'usr_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
57
+ * hmacSignature
58
+ * );
59
+ * ```
60
+ */
61
+ declare function useChat(): UseChatReturn;
62
+
63
+ interface UseConversationsReturn {
64
+ /** List of conversations for the identified customer. */
65
+ conversations: Conversation[];
66
+ /** Whether the initial fetch is in progress. */
67
+ isLoading: boolean;
68
+ /** The last error, or null. */
69
+ error: Error | null;
70
+ /** Whether there are more conversations to load. */
71
+ hasMore: boolean;
72
+ /** Re-fetch the conversation list. */
73
+ refresh: () => Promise<void>;
74
+ /** Create a new conversation. */
75
+ create: (params: ConversationCreateParams) => Promise<Conversation>;
76
+ }
77
+ /**
78
+ * Manage the customer's conversation list.
79
+ *
80
+ * ```tsx
81
+ * const { conversations, isLoading, create, refresh } = useConversations();
82
+ * ```
83
+ */
84
+ declare function useConversations(): UseConversationsReturn;
85
+
86
+ interface UseMessagesReturn {
87
+ /** Messages in the conversation, oldest first. */
88
+ messages: WidgetMessage[];
89
+ /** Whether the initial fetch is in progress. */
90
+ isLoading: boolean;
91
+ /** The last error, or null. */
92
+ error: Error | null;
93
+ /** Send a message. Optimistically appended, replaced with server response. */
94
+ send: (content: string) => Promise<WidgetMessage>;
95
+ /** Re-fetch messages from the API. */
96
+ refresh: () => Promise<void>;
97
+ }
98
+ /**
99
+ * Manage messages for a single conversation with automatic real-time updates.
100
+ *
101
+ * ```tsx
102
+ * const { messages, isLoading, send } = useMessages(ticketId);
103
+ * await send('Hello!');
104
+ * ```
105
+ */
106
+ declare function useMessages(ticketId: string | null): UseMessagesReturn;
107
+
108
+ interface TypingAgent {
109
+ agentId: string;
110
+ agentName: string;
111
+ }
112
+ interface UseTypingReturn {
113
+ /** Agents currently typing. Auto-cleared after 4s of no activity. */
114
+ typingAgents: TypingAgent[];
115
+ /** Send a customer typing indicator. */
116
+ sendTyping: (isTyping: boolean) => Promise<void>;
117
+ }
118
+ /**
119
+ * Track agent typing indicators for a conversation.
120
+ *
121
+ * ```tsx
122
+ * const { typingAgents, sendTyping } = useTyping(ticketId);
123
+ * ```
124
+ */
125
+ declare function useTyping(ticketId: string | null): UseTypingReturn;
126
+
127
+ interface CStarLibraryProviderProps extends LibraryConfig {
128
+ children: ReactNode;
129
+ }
130
+ /**
131
+ * Provides a LibraryClient instance to all child components.
132
+ *
133
+ * ```tsx
134
+ * <CStarLibraryProvider teamSlug="acme">
135
+ * <KnowledgeBase />
136
+ * </CStarLibraryProvider>
137
+ * ```
138
+ */
139
+ declare function CStarLibraryProvider({ children, ...config }: CStarLibraryProviderProps): react_jsx_runtime.JSX.Element;
140
+
141
+ interface UseCategoriesReturn {
142
+ /** All public categories. */
143
+ categories: Category[];
144
+ /** Whether the initial fetch is in progress. */
145
+ isLoading: boolean;
146
+ /** The last error, or null. */
147
+ error: Error | null;
148
+ /** Re-fetch categories. */
149
+ refresh: () => Promise<void>;
150
+ }
151
+ /**
152
+ * Fetch public knowledge base categories.
153
+ *
154
+ * ```tsx
155
+ * const { categories, isLoading, error } = useCategories();
156
+ * ```
157
+ */
158
+ declare function useCategories(): UseCategoriesReturn;
159
+
160
+ interface UseArticlesReturn {
161
+ /** Published articles. */
162
+ articles: LibraryArticle[];
163
+ /** Whether the fetch is in progress. */
164
+ isLoading: boolean;
165
+ /** The last error, or null. */
166
+ error: Error | null;
167
+ /** Re-fetch articles with the current params. */
168
+ refresh: () => Promise<void>;
169
+ }
170
+ /**
171
+ * Fetch published articles, optionally filtered by category.
172
+ *
173
+ * ```tsx
174
+ * const { articles, isLoading } = useArticles({ categorySlug: 'getting-started' });
175
+ * ```
176
+ */
177
+ declare function useArticles(params?: LibraryArticleListParams): UseArticlesReturn;
178
+
179
+ interface UseArticleReturn {
180
+ /** The article, or null if not yet loaded. */
181
+ article: LibraryArticle | null;
182
+ /** Whether the fetch is in progress. */
183
+ isLoading: boolean;
184
+ /** The last error, or null. */
185
+ error: Error | null;
186
+ /** Re-fetch the article. */
187
+ refresh: () => Promise<void>;
188
+ }
189
+ /**
190
+ * Fetch a single article by slug.
191
+ *
192
+ * ```tsx
193
+ * const { article, isLoading, error } = useArticle('getting-started');
194
+ * ```
195
+ */
196
+ declare function useArticle(slug: string | null): UseArticleReturn;
197
+
198
+ interface UseArticleSearchReturn {
199
+ /** Search results. */
200
+ results: LibraryArticle[];
201
+ /** Total number of matching articles. */
202
+ totalCount: number;
203
+ /** Whether a search is in progress. */
204
+ isLoading: boolean;
205
+ /** The last error, or null. */
206
+ error: Error | null;
207
+ }
208
+ /**
209
+ * Search articles with automatic debouncing (300ms).
210
+ * Clears results when query is empty.
211
+ *
212
+ * ```tsx
213
+ * const { results, totalCount, isLoading } = useArticleSearch(searchTerm);
214
+ * ```
215
+ */
216
+ declare function useArticleSearch(query: string): UseArticleSearchReturn;
217
+
218
+ export { CStarChatContext, CStarChatProvider, type CStarChatProviderProps, CStarLibraryContext, CStarLibraryProvider, type CStarLibraryProviderProps, type TypingAgent, type UseArticleReturn, type UseArticleSearchReturn, type UseArticlesReturn, type UseCategoriesReturn, type UseChatReturn, type UseConversationsReturn, type UseMessagesReturn, type UseTypingReturn, useArticle, useArticleSearch, useArticles, useCategories, useChat, useChatClient, useConversations, useLibraryClient, useMessages, useTyping };