@cstar.help/react 0.10.2 → 0.10.3

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
@@ -117,6 +117,7 @@ Wrap in `<CStarLibraryProvider>` for public knowledge base access. No auth requi
117
117
  import { CStarLibraryProvider } from '@cstar.help/react';
118
118
 
119
119
  function App() {
120
+ // Seeded with a test key (cstar seed)? Add publishableKey="pk_test_..." to read test articles.
120
121
  return (
121
122
  <CStarLibraryProvider teamSlug="acme">
122
123
  <HelpCenter />
package/dist/index.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  "use strict";
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -81,32 +82,51 @@ function useCommunityClient() {
81
82
  }
82
83
 
83
84
  // src/chat/CStarChatProvider.tsx
84
- var import_react2 = require("react");
85
+ var import_react3 = require("react");
85
86
  var import_chat = require("@cstar.help/js/chat");
87
+
88
+ // src/useDisconnectOnUnmount.ts
89
+ var import_react2 = require("react");
90
+ function useDisconnectOnUnmount(target, disconnect) {
91
+ const pending = (0, import_react2.useRef)(null);
92
+ const disconnectRef = (0, import_react2.useRef)(disconnect);
93
+ disconnectRef.current = disconnect;
94
+ (0, import_react2.useEffect)(() => {
95
+ if (target === null) return;
96
+ if (pending.current?.target === target) {
97
+ clearTimeout(pending.current.timer);
98
+ pending.current = null;
99
+ }
100
+ return () => {
101
+ const timer = setTimeout(() => {
102
+ if (pending.current?.target === target) pending.current = null;
103
+ disconnectRef.current(target);
104
+ }, 0);
105
+ pending.current = { target, timer };
106
+ };
107
+ }, [target]);
108
+ }
109
+
110
+ // src/chat/CStarChatProvider.tsx
86
111
  var import_jsx_runtime = require("react/jsx-runtime");
87
112
  function CStarChatProvider({ children, ...config }) {
88
- const clientRef = (0, import_react2.useRef)(null);
113
+ const clientRef = (0, import_react3.useRef)(null);
89
114
  if (!clientRef.current) {
90
115
  clientRef.current = new import_chat.ChatClient(config);
91
116
  }
92
- (0, import_react2.useEffect)(() => {
93
- return () => {
94
- clientRef.current?.disconnect();
95
- clientRef.current = null;
96
- };
97
- }, []);
117
+ useDisconnectOnUnmount(clientRef.current, (client) => client.disconnect());
98
118
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CStarChatContext.Provider, { value: clientRef.current, children });
99
119
  }
100
120
 
101
121
  // src/chat/useChat.ts
102
- var import_react3 = require("react");
122
+ var import_react4 = require("react");
103
123
  function useChat() {
104
124
  const client = useChatClient();
105
- const [isAuthenticated, setIsAuthenticated] = (0, import_react3.useState)(false);
106
- const [authMode, setAuthMode] = (0, import_react3.useState)(() => client.getAuthMode());
107
- const [isRealtimeReady, setIsRealtimeReady] = (0, import_react3.useState)(false);
108
- const [error, setError] = (0, import_react3.useState)(null);
109
- (0, import_react3.useEffect)(() => {
125
+ const [isAuthenticated, setIsAuthenticated] = (0, import_react4.useState)(false);
126
+ const [authMode, setAuthMode] = (0, import_react4.useState)(() => client.getAuthMode());
127
+ const [isRealtimeReady, setIsRealtimeReady] = (0, import_react4.useState)(false);
128
+ const [error, setError] = (0, import_react4.useState)(null);
129
+ (0, import_react4.useEffect)(() => {
110
130
  const subscribe = client.subscribe?.bind(client);
111
131
  if (!subscribe) return;
112
132
  return subscribe(() => {
@@ -115,11 +135,11 @@ function useChat() {
115
135
  setIsAuthenticated(mode !== null);
116
136
  });
117
137
  }, [client]);
118
- const wireRealtime = (0, import_react3.useCallback)(() => {
138
+ const wireRealtime = (0, import_react4.useCallback)(() => {
119
139
  client.waitForRealtime().then(() => setIsRealtimeReady(true)).catch(() => {
120
140
  });
121
141
  }, [client]);
122
- const identify = (0, import_react3.useCallback)(
142
+ const identify = (0, import_react4.useCallback)(
123
143
  async (customer, signature) => {
124
144
  setError(null);
125
145
  try {
@@ -136,7 +156,7 @@ function useChat() {
136
156
  },
137
157
  [client, wireRealtime]
138
158
  );
139
- const loginWithCredentials = (0, import_react3.useCallback)(
159
+ const loginWithCredentials = (0, import_react4.useCallback)(
140
160
  async (params) => {
141
161
  setError(null);
142
162
  try {
@@ -153,7 +173,7 @@ function useChat() {
153
173
  },
154
174
  [client, wireRealtime]
155
175
  );
156
- const loginWithSession = (0, import_react3.useCallback)(
176
+ const loginWithSession = (0, import_react4.useCallback)(
157
177
  async (params) => {
158
178
  setError(null);
159
179
  try {
@@ -169,7 +189,7 @@ function useChat() {
169
189
  },
170
190
  [client, wireRealtime]
171
191
  );
172
- const disconnect = (0, import_react3.useCallback)(() => {
192
+ const disconnect = (0, import_react4.useCallback)(() => {
173
193
  client.disconnect();
174
194
  setIsAuthenticated(false);
175
195
  setAuthMode(null);
@@ -190,15 +210,15 @@ function useChat() {
190
210
  }
191
211
 
192
212
  // src/chat/useTickets.ts
193
- var import_react4 = require("react");
213
+ var import_react5 = require("react");
194
214
  function useTickets() {
195
215
  const client = useChatClient();
196
- const [tickets, setTickets] = (0, import_react4.useState)([]);
197
- const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
198
- const [error, setError] = (0, import_react4.useState)(null);
199
- const [hasMore, setHasMore] = (0, import_react4.useState)(false);
200
- const mountedRef = (0, import_react4.useRef)(true);
201
- const refresh = (0, import_react4.useCallback)(async () => {
216
+ const [tickets, setTickets] = (0, import_react5.useState)([]);
217
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
218
+ const [error, setError] = (0, import_react5.useState)(null);
219
+ const [hasMore, setHasMore] = (0, import_react5.useState)(false);
220
+ const mountedRef = (0, import_react5.useRef)(true);
221
+ const refresh = (0, import_react5.useCallback)(async () => {
202
222
  setIsLoading(true);
203
223
  setError(null);
204
224
  try {
@@ -217,14 +237,14 @@ function useTickets() {
217
237
  }
218
238
  }
219
239
  }, [client]);
220
- (0, import_react4.useEffect)(() => {
240
+ (0, import_react5.useEffect)(() => {
221
241
  mountedRef.current = true;
222
242
  refresh();
223
243
  return () => {
224
244
  mountedRef.current = false;
225
245
  };
226
246
  }, [refresh]);
227
- const create = (0, import_react4.useCallback)(
247
+ const create = (0, import_react5.useCallback)(
228
248
  async (params) => {
229
249
  const ticket = await client.tickets.create(params);
230
250
  if (mountedRef.current) {
@@ -238,18 +258,18 @@ function useTickets() {
238
258
  }
239
259
 
240
260
  // src/chat/useMessages.ts
241
- var import_react5 = require("react");
261
+ var import_react6 = require("react");
242
262
  function useMessages(ticketId) {
243
263
  const client = useChatClient();
244
- const [messages, setMessages] = (0, import_react5.useState)([]);
245
- const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
246
- const [error, setError] = (0, import_react5.useState)(null);
247
- const mountedRef = (0, import_react5.useRef)(true);
248
- const seenIdsRef = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
249
- const requestRef = (0, import_react5.useRef)(0);
250
- const scopeRef = (0, import_react5.useRef)(0);
251
- const optimisticRef = (0, import_react5.useRef)(0);
252
- const refresh = (0, import_react5.useCallback)(async () => {
264
+ const [messages, setMessages] = (0, import_react6.useState)([]);
265
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
266
+ const [error, setError] = (0, import_react6.useState)(null);
267
+ const mountedRef = (0, import_react6.useRef)(true);
268
+ const seenIdsRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
269
+ const requestRef = (0, import_react6.useRef)(0);
270
+ const scopeRef = (0, import_react6.useRef)(0);
271
+ const optimisticRef = (0, import_react6.useRef)(0);
272
+ const refresh = (0, import_react6.useCallback)(async () => {
253
273
  if (!ticketId) return;
254
274
  const request = ++requestRef.current;
255
275
  setIsLoading(true);
@@ -270,7 +290,7 @@ function useMessages(ticketId) {
270
290
  }
271
291
  }
272
292
  }, [client, ticketId]);
273
- (0, import_react5.useEffect)(() => {
293
+ (0, import_react6.useEffect)(() => {
274
294
  mountedRef.current = true;
275
295
  const scope = ++scopeRef.current;
276
296
  seenIdsRef.current = /* @__PURE__ */ new Set();
@@ -309,7 +329,7 @@ function useMessages(ticketId) {
309
329
  unsubscribe();
310
330
  };
311
331
  }, [client, ticketId, refresh]);
312
- const send = (0, import_react5.useCallback)(
332
+ const send = (0, import_react6.useCallback)(
313
333
  async (content) => {
314
334
  if (!ticketId) throw new Error("No ticket selected");
315
335
  const scope = scopeRef.current;
@@ -342,14 +362,14 @@ function useMessages(ticketId) {
342
362
  }
343
363
 
344
364
  // src/chat/useTyping.ts
345
- var import_react6 = require("react");
365
+ var import_react7 = require("react");
346
366
  var TYPING_TIMEOUT = 4e3;
347
367
  function useTyping(ticketId) {
348
368
  const client = useChatClient();
349
- const [typingAgents, setTypingAgents] = (0, import_react6.useState)([]);
350
- const timersRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
351
- const mountedRef = (0, import_react6.useRef)(true);
352
- (0, import_react6.useEffect)(() => {
369
+ const [typingAgents, setTypingAgents] = (0, import_react7.useState)([]);
370
+ const timersRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
371
+ const mountedRef = (0, import_react7.useRef)(true);
372
+ (0, import_react7.useEffect)(() => {
353
373
  mountedRef.current = true;
354
374
  if (!ticketId) {
355
375
  setTypingAgents([]);
@@ -386,7 +406,7 @@ function useTyping(ticketId) {
386
406
  timersRef.current.clear();
387
407
  };
388
408
  }, [client, ticketId]);
389
- const sendTyping = (0, import_react6.useCallback)(
409
+ const sendTyping = (0, import_react7.useCallback)(
390
410
  async (isTyping) => {
391
411
  if (!ticketId) return;
392
412
  await client.sendTyping(ticketId, isTyping);
@@ -397,11 +417,11 @@ function useTyping(ticketId) {
397
417
  }
398
418
 
399
419
  // src/library/CStarLibraryProvider.tsx
400
- var import_react7 = require("react");
420
+ var import_react8 = require("react");
401
421
  var import_library = require("@cstar.help/js/library");
402
422
  var import_jsx_runtime2 = require("react/jsx-runtime");
403
423
  function CStarLibraryProvider({ children, ...config }) {
404
- const clientRef = (0, import_react7.useRef)(null);
424
+ const clientRef = (0, import_react8.useRef)(null);
405
425
  if (!clientRef.current) {
406
426
  clientRef.current = new import_library.LibraryClient(config);
407
427
  }
@@ -409,14 +429,14 @@ function CStarLibraryProvider({ children, ...config }) {
409
429
  }
410
430
 
411
431
  // src/library/useCategories.ts
412
- var import_react8 = require("react");
432
+ var import_react9 = require("react");
413
433
  function useCategories() {
414
434
  const client = useLibraryClient();
415
- const [categories, setCategories] = (0, import_react8.useState)([]);
416
- const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
417
- const [error, setError] = (0, import_react8.useState)(null);
418
- const mountedRef = (0, import_react8.useRef)(true);
419
- const refresh = (0, import_react8.useCallback)(async () => {
435
+ const [categories, setCategories] = (0, import_react9.useState)([]);
436
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(true);
437
+ const [error, setError] = (0, import_react9.useState)(null);
438
+ const mountedRef = (0, import_react9.useRef)(true);
439
+ const refresh = (0, import_react9.useCallback)(async () => {
420
440
  setIsLoading(true);
421
441
  setError(null);
422
442
  try {
@@ -434,7 +454,7 @@ function useCategories() {
434
454
  }
435
455
  }
436
456
  }, [client]);
437
- (0, import_react8.useEffect)(() => {
457
+ (0, import_react9.useEffect)(() => {
438
458
  mountedRef.current = true;
439
459
  refresh();
440
460
  return () => {
@@ -445,17 +465,17 @@ function useCategories() {
445
465
  }
446
466
 
447
467
  // src/library/useArticles.ts
448
- var import_react9 = require("react");
468
+ var import_react10 = require("react");
449
469
  function useArticles(params) {
450
470
  const client = useLibraryClient();
451
- const [articles, setArticles] = (0, import_react9.useState)([]);
452
- const [isLoading, setIsLoading] = (0, import_react9.useState)(true);
453
- const [error, setError] = (0, import_react9.useState)(null);
454
- const mountedRef = (0, import_react9.useRef)(true);
471
+ const [articles, setArticles] = (0, import_react10.useState)([]);
472
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
473
+ const [error, setError] = (0, import_react10.useState)(null);
474
+ const mountedRef = (0, import_react10.useRef)(true);
455
475
  const categorySlug = params?.categorySlug;
456
476
  const limit = params?.limit;
457
477
  const offset = params?.offset;
458
- const refresh = (0, import_react9.useCallback)(async () => {
478
+ const refresh = (0, import_react10.useCallback)(async () => {
459
479
  setIsLoading(true);
460
480
  setError(null);
461
481
  try {
@@ -473,7 +493,7 @@ function useArticles(params) {
473
493
  }
474
494
  }
475
495
  }, [client, categorySlug, limit, offset]);
476
- (0, import_react9.useEffect)(() => {
496
+ (0, import_react10.useEffect)(() => {
477
497
  mountedRef.current = true;
478
498
  refresh();
479
499
  return () => {
@@ -484,14 +504,14 @@ function useArticles(params) {
484
504
  }
485
505
 
486
506
  // src/library/useArticle.ts
487
- var import_react10 = require("react");
507
+ var import_react11 = require("react");
488
508
  function useArticle(slug) {
489
509
  const client = useLibraryClient();
490
- const [article, setArticle] = (0, import_react10.useState)(null);
491
- const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
492
- const [error, setError] = (0, import_react10.useState)(null);
493
- const mountedRef = (0, import_react10.useRef)(true);
494
- const refresh = (0, import_react10.useCallback)(async () => {
510
+ const [article, setArticle] = (0, import_react11.useState)(null);
511
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
512
+ const [error, setError] = (0, import_react11.useState)(null);
513
+ const mountedRef = (0, import_react11.useRef)(true);
514
+ const refresh = (0, import_react11.useCallback)(async () => {
495
515
  if (!slug) return;
496
516
  setIsLoading(true);
497
517
  setError(null);
@@ -510,14 +530,14 @@ function useArticle(slug) {
510
530
  }
511
531
  }
512
532
  }, [client, slug]);
513
- const recordView = (0, import_react10.useCallback)(async () => {
533
+ const recordView = (0, import_react11.useCallback)(async () => {
514
534
  if (!slug) return;
515
535
  try {
516
536
  await client.recordView(slug);
517
537
  } catch {
518
538
  }
519
539
  }, [client, slug]);
520
- (0, import_react10.useEffect)(() => {
540
+ (0, import_react11.useEffect)(() => {
521
541
  mountedRef.current = true;
522
542
  if (!slug) {
523
543
  setArticle(null);
@@ -533,16 +553,16 @@ function useArticle(slug) {
533
553
  }
534
554
 
535
555
  // src/library/useArticleSearch.ts
536
- var import_react11 = require("react");
556
+ var import_react12 = require("react");
537
557
  var DEBOUNCE_MS = 300;
538
558
  function useArticleSearch(query) {
539
559
  const client = useLibraryClient();
540
- const [results, setResults] = (0, import_react11.useState)([]);
541
- const [totalCount, setTotalCount] = (0, import_react11.useState)(0);
542
- const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
543
- const [error, setError] = (0, import_react11.useState)(null);
544
- const mountedRef = (0, import_react11.useRef)(true);
545
- (0, import_react11.useEffect)(() => {
560
+ const [results, setResults] = (0, import_react12.useState)([]);
561
+ const [totalCount, setTotalCount] = (0, import_react12.useState)(0);
562
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
563
+ const [error, setError] = (0, import_react12.useState)(null);
564
+ const mountedRef = (0, import_react12.useRef)(true);
565
+ (0, import_react12.useEffect)(() => {
546
566
  mountedRef.current = true;
547
567
  const trimmed = query.trim();
548
568
  if (!trimmed) {
@@ -580,11 +600,11 @@ function useArticleSearch(query) {
580
600
  }
581
601
 
582
602
  // src/community/CStarCommunityProvider.tsx
583
- var import_react12 = require("react");
603
+ var import_react13 = require("react");
584
604
  var import_community = require("@cstar.help/js/community");
585
605
  var import_jsx_runtime3 = require("react/jsx-runtime");
586
606
  function CStarCommunityProvider({ children, ...config }) {
587
- const clientRef = (0, import_react12.useRef)(null);
607
+ const clientRef = (0, import_react13.useRef)(null);
588
608
  if (!clientRef.current) {
589
609
  clientRef.current = new import_community.CommunityClient(config);
590
610
  }
@@ -592,14 +612,14 @@ function CStarCommunityProvider({ children, ...config }) {
592
612
  }
593
613
 
594
614
  // src/community/useTopics.ts
595
- var import_react13 = require("react");
615
+ var import_react14 = require("react");
596
616
  function useTopics() {
597
617
  const client = useCommunityClient();
598
- const [topics, setTopics] = (0, import_react13.useState)([]);
599
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
600
- const [error, setError] = (0, import_react13.useState)(null);
601
- const mountedRef = (0, import_react13.useRef)(true);
602
- const refresh = (0, import_react13.useCallback)(async () => {
618
+ const [topics, setTopics] = (0, import_react14.useState)([]);
619
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
620
+ const [error, setError] = (0, import_react14.useState)(null);
621
+ const mountedRef = (0, import_react14.useRef)(true);
622
+ const refresh = (0, import_react14.useCallback)(async () => {
603
623
  setIsLoading(true);
604
624
  setError(null);
605
625
  try {
@@ -617,7 +637,7 @@ function useTopics() {
617
637
  }
618
638
  }
619
639
  }, [client]);
620
- (0, import_react13.useEffect)(() => {
640
+ (0, import_react14.useEffect)(() => {
621
641
  mountedRef.current = true;
622
642
  refresh();
623
643
  return () => {
@@ -628,20 +648,20 @@ function useTopics() {
628
648
  }
629
649
 
630
650
  // src/community/usePosts.ts
631
- var import_react14 = require("react");
651
+ var import_react15 = require("react");
632
652
  function usePosts(params) {
633
653
  const client = useCommunityClient();
634
- const [posts, setPosts] = (0, import_react14.useState)([]);
635
- const [count, setCount] = (0, import_react14.useState)(0);
636
- const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
637
- const [error, setError] = (0, import_react14.useState)(null);
638
- const mountedRef = (0, import_react14.useRef)(true);
654
+ const [posts, setPosts] = (0, import_react15.useState)([]);
655
+ const [count, setCount] = (0, import_react15.useState)(0);
656
+ const [isLoading, setIsLoading] = (0, import_react15.useState)(true);
657
+ const [error, setError] = (0, import_react15.useState)(null);
658
+ const mountedRef = (0, import_react15.useRef)(true);
639
659
  const topicSlug = params?.topicSlug;
640
660
  const status = params?.status;
641
661
  const sort = params?.sort;
642
662
  const limit = params?.limit;
643
663
  const offset = params?.offset;
644
- const refresh = (0, import_react14.useCallback)(async () => {
664
+ const refresh = (0, import_react15.useCallback)(async () => {
645
665
  setIsLoading(true);
646
666
  setError(null);
647
667
  try {
@@ -660,7 +680,7 @@ function usePosts(params) {
660
680
  }
661
681
  }
662
682
  }, [client, topicSlug, status, sort, limit, offset]);
663
- (0, import_react14.useEffect)(() => {
683
+ (0, import_react15.useEffect)(() => {
664
684
  mountedRef.current = true;
665
685
  refresh();
666
686
  return () => {
@@ -671,14 +691,14 @@ function usePosts(params) {
671
691
  }
672
692
 
673
693
  // src/community/usePost.ts
674
- var import_react15 = require("react");
694
+ var import_react16 = require("react");
675
695
  function usePost(slug) {
676
696
  const client = useCommunityClient();
677
- const [data, setData] = (0, import_react15.useState)(null);
678
- const [isLoading, setIsLoading] = (0, import_react15.useState)(true);
679
- const [error, setError] = (0, import_react15.useState)(null);
680
- const mountedRef = (0, import_react15.useRef)(true);
681
- const refresh = (0, import_react15.useCallback)(async () => {
697
+ const [data, setData] = (0, import_react16.useState)(null);
698
+ const [isLoading, setIsLoading] = (0, import_react16.useState)(true);
699
+ const [error, setError] = (0, import_react16.useState)(null);
700
+ const mountedRef = (0, import_react16.useRef)(true);
701
+ const refresh = (0, import_react16.useCallback)(async () => {
682
702
  setIsLoading(true);
683
703
  setError(null);
684
704
  try {
@@ -696,7 +716,7 @@ function usePost(slug) {
696
716
  }
697
717
  }
698
718
  }, [client, slug]);
699
- (0, import_react15.useEffect)(() => {
719
+ (0, import_react16.useEffect)(() => {
700
720
  mountedRef.current = true;
701
721
  refresh();
702
722
  return () => {
@@ -707,20 +727,20 @@ function usePost(slug) {
707
727
  }
708
728
 
709
729
  // src/community/useCommunitySearch.ts
710
- var import_react16 = require("react");
730
+ var import_react17 = require("react");
711
731
  function useCommunitySearch() {
712
732
  const client = useCommunityClient();
713
- const [results, setResults] = (0, import_react16.useState)(null);
714
- const [isLoading, setIsLoading] = (0, import_react16.useState)(false);
715
- const [error, setError] = (0, import_react16.useState)(null);
716
- const mountedRef = (0, import_react16.useRef)(true);
717
- (0, import_react16.useEffect)(() => {
733
+ const [results, setResults] = (0, import_react17.useState)(null);
734
+ const [isLoading, setIsLoading] = (0, import_react17.useState)(false);
735
+ const [error, setError] = (0, import_react17.useState)(null);
736
+ const mountedRef = (0, import_react17.useRef)(true);
737
+ (0, import_react17.useEffect)(() => {
718
738
  mountedRef.current = true;
719
739
  return () => {
720
740
  mountedRef.current = false;
721
741
  };
722
742
  }, []);
723
- const search = (0, import_react16.useCallback)(
743
+ const search = (0, import_react17.useCallback)(
724
744
  async (query) => {
725
745
  if (!query.trim()) {
726
746
  setResults(null);
@@ -749,10 +769,10 @@ function useCommunitySearch() {
749
769
  }
750
770
 
751
771
  // src/dashboard/CStarDashboardProvider.tsx
752
- var import_react17 = require("react");
772
+ var import_react18 = require("react");
753
773
  var import_js = require("@cstar.help/js");
754
774
  var import_jsx_runtime4 = require("react/jsx-runtime");
755
- var CStarDashboardContext = (0, import_react17.createContext)(null);
775
+ var CStarDashboardContext = (0, import_react18.createContext)(null);
756
776
  function CStarDashboardProvider({
757
777
  config,
758
778
  client: providedClient,
@@ -760,10 +780,10 @@ function CStarDashboardProvider({
760
780
  }) {
761
781
  if (!config && !providedClient) {
762
782
  throw new Error(
763
- "CStarDashboardProvider requires either a `config` prop (`{ apiKey, teamId }`, recommended) or a `client` prop (a pre-built CStarClient instance, deprecated). See https://cstar.help/developers/sdk/react#dashboard"
783
+ "CStarDashboardProvider requires either a `config` prop (`{ apiKey, teamId }`, recommended) or a `client` prop (a pre-built CStarClient instance, deprecated). See https://www.cstar.help/developers/sdk/react#dashboard"
764
784
  );
765
785
  }
766
- const client = (0, import_react17.useMemo)(() => {
786
+ const client = (0, import_react18.useMemo)(() => {
767
787
  if (providedClient) return providedClient;
768
788
  return new import_js.CStarClient(config);
769
789
  }, [
@@ -775,17 +795,12 @@ function CStarDashboardProvider({
775
795
  config?.maxRetries,
776
796
  config?.timeout
777
797
  ]);
778
- const contextValue = (0, import_react17.useMemo)(() => ({ client }), [client]);
779
- (0, import_react17.useEffect)(() => {
780
- if (providedClient) return;
781
- return () => {
782
- client?.realtime?.disconnect?.();
783
- };
784
- }, [client, providedClient]);
798
+ const contextValue = (0, import_react18.useMemo)(() => ({ client }), [client]);
799
+ useDisconnectOnUnmount(providedClient ? null : client, (owned) => owned.realtime?.disconnect?.());
785
800
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CStarDashboardContext.Provider, { value: contextValue, children });
786
801
  }
787
802
  function useDashboardClient() {
788
- const ctx = (0, import_react17.useContext)(CStarDashboardContext);
803
+ const ctx = (0, import_react18.useContext)(CStarDashboardContext);
789
804
  if (!ctx) {
790
805
  throw new Error("useDashboardClient must be used within a <CStarDashboardProvider>");
791
806
  }
@@ -793,7 +808,7 @@ function useDashboardClient() {
793
808
  }
794
809
 
795
810
  // src/dashboard/useCStarQuery.ts
796
- var import_react18 = require("react");
811
+ var import_react19 = require("react");
797
812
  var import_js2 = require("@cstar.help/js");
798
813
  function resolveResource(client, path) {
799
814
  const parts = path.split(".");
@@ -812,12 +827,12 @@ function useCStarQuery(resource, params) {
812
827
  );
813
828
  }
814
829
  const client = useDashboardClient();
815
- const [data, setData] = (0, import_react18.useState)(null);
816
- const [loading, setLoading] = (0, import_react18.useState)(true);
817
- const [error, setError] = (0, import_react18.useState)(null);
818
- const subscriptionRef = (0, import_react18.useRef)(null);
830
+ const [data, setData] = (0, import_react19.useState)(null);
831
+ const [loading, setLoading] = (0, import_react19.useState)(true);
832
+ const [error, setError] = (0, import_react19.useState)(null);
833
+ const subscriptionRef = (0, import_react19.useRef)(null);
819
834
  const paramsKey = params ? JSON.stringify(params) : "";
820
- (0, import_react18.useEffect)(() => {
835
+ (0, import_react19.useEffect)(() => {
821
836
  const resolved = resolveResource(client, resource);
822
837
  if (!resolved) {
823
838
  setError(new Error(`Invalid resource path: ${resource}. Expected format: 'tickets.list'`));
@@ -840,7 +855,7 @@ function useCStarQuery(resource, params) {
840
855
  subscriptionRef.current = null;
841
856
  };
842
857
  }, [client, resource, paramsKey]);
843
- const refresh = (0, import_react18.useCallback)(async () => {
858
+ const refresh = (0, import_react19.useCallback)(async () => {
844
859
  if (subscriptionRef.current) {
845
860
  await subscriptionRef.current.refresh();
846
861
  }
@@ -849,7 +864,7 @@ function useCStarQuery(resource, params) {
849
864
  }
850
865
 
851
866
  // src/dashboard/useCStarMutation.ts
852
- var import_react19 = require("react");
867
+ var import_react20 = require("react");
853
868
  function resolveMutation(client, path) {
854
869
  const parts = path.split(".");
855
870
  if (parts.length < 2) return null;
@@ -877,9 +892,9 @@ function resolveMutation(client, path) {
877
892
  }
878
893
  function useCStarMutation(resource) {
879
894
  const client = useDashboardClient();
880
- const [loading, setLoading] = (0, import_react19.useState)(false);
881
- const [error, setError] = (0, import_react19.useState)(null);
882
- const mutate = (0, import_react19.useCallback)(
895
+ const [loading, setLoading] = (0, import_react20.useState)(false);
896
+ const [error, setError] = (0, import_react20.useState)(null);
897
+ const mutate = (0, import_react20.useCallback)(
883
898
  async (params) => {
884
899
  const fn = resolveMutation(client, resource);
885
900
  if (!fn) {
@@ -904,14 +919,14 @@ function useCStarMutation(resource) {
904
919
  }
905
920
 
906
921
  // src/dashboard/useCStarEvents.ts
907
- var import_react20 = require("react");
922
+ var import_react21 = require("react");
908
923
  var MAX_EVENTS = 100;
909
924
  function useCStarEvents(types) {
910
925
  const client = useDashboardClient();
911
- const [events, setEvents] = (0, import_react20.useState)([]);
912
- const [connected, setConnected] = (0, import_react20.useState)(false);
926
+ const [events, setEvents] = (0, import_react21.useState)([]);
927
+ const [connected, setConnected] = (0, import_react21.useState)(false);
913
928
  const typesKey = types ? types.join(",") : "";
914
- (0, import_react20.useEffect)(() => {
929
+ (0, import_react21.useEffect)(() => {
915
930
  const realtime = client.realtime;
916
931
  const handler = (event) => {
917
932
  if (types && types.length > 0) {
@@ -943,14 +958,14 @@ function useCStarEvents(types) {
943
958
  }
944
959
 
945
960
  // src/dashboard/useBossBattle.ts
946
- var import_react21 = require("react");
961
+ var import_react22 = require("react");
947
962
  function useBossBattle() {
948
963
  const client = useDashboardClient();
949
- const [boss, setBoss] = (0, import_react21.useState)(null);
950
- const [loading, setLoading] = (0, import_react21.useState)(true);
951
- const [error, setError] = (0, import_react21.useState)(null);
952
- const subRef = (0, import_react21.useRef)(null);
953
- (0, import_react21.useEffect)(() => {
964
+ const [boss, setBoss] = (0, import_react22.useState)(null);
965
+ const [loading, setLoading] = (0, import_react22.useState)(true);
966
+ const [error, setError] = (0, import_react22.useState)(null);
967
+ const subRef = (0, import_react22.useRef)(null);
968
+ (0, import_react22.useEffect)(() => {
954
969
  const sub = client.game.subscribeBoss(client.realtime);
955
970
  subRef.current = sub;
956
971
  sub.on("change", (data) => {
@@ -967,21 +982,21 @@ function useBossBattle() {
967
982
  subRef.current = null;
968
983
  };
969
984
  }, [client]);
970
- const refresh = (0, import_react21.useCallback)(async () => {
985
+ const refresh = (0, import_react22.useCallback)(async () => {
971
986
  if (subRef.current) await subRef.current.refresh();
972
987
  }, []);
973
988
  return { boss, active: boss?.active ?? false, loading, error, refresh };
974
989
  }
975
990
 
976
991
  // src/dashboard/usePlayerStats.ts
977
- var import_react22 = require("react");
992
+ var import_react23 = require("react");
978
993
  function usePlayerStats(memberId) {
979
994
  const client = useDashboardClient();
980
- const [player, setPlayer] = (0, import_react22.useState)(null);
981
- const [loading, setLoading] = (0, import_react22.useState)(true);
982
- const [error, setError] = (0, import_react22.useState)(null);
983
- const subRef = (0, import_react22.useRef)(null);
984
- (0, import_react22.useEffect)(() => {
995
+ const [player, setPlayer] = (0, import_react23.useState)(null);
996
+ const [loading, setLoading] = (0, import_react23.useState)(true);
997
+ const [error, setError] = (0, import_react23.useState)(null);
998
+ const subRef = (0, import_react23.useRef)(null);
999
+ (0, import_react23.useEffect)(() => {
985
1000
  const sub = client.game.subscribePlayer(client.realtime, memberId);
986
1001
  subRef.current = sub;
987
1002
  sub.on("change", (data) => {
@@ -998,21 +1013,21 @@ function usePlayerStats(memberId) {
998
1013
  subRef.current = null;
999
1014
  };
1000
1015
  }, [client, memberId]);
1001
- const refresh = (0, import_react22.useCallback)(async () => {
1016
+ const refresh = (0, import_react23.useCallback)(async () => {
1002
1017
  if (subRef.current) await subRef.current.refresh();
1003
1018
  }, []);
1004
1019
  return { player, loading, error, refresh };
1005
1020
  }
1006
1021
 
1007
1022
  // src/dashboard/useLeaderboard.ts
1008
- var import_react23 = require("react");
1023
+ var import_react24 = require("react");
1009
1024
  function useLeaderboard(period) {
1010
1025
  const client = useDashboardClient();
1011
- const [entries, setEntries] = (0, import_react23.useState)([]);
1012
- const [loading, setLoading] = (0, import_react23.useState)(true);
1013
- const [error, setError] = (0, import_react23.useState)(null);
1014
- const subRef = (0, import_react23.useRef)(null);
1015
- (0, import_react23.useEffect)(() => {
1026
+ const [entries, setEntries] = (0, import_react24.useState)([]);
1027
+ const [loading, setLoading] = (0, import_react24.useState)(true);
1028
+ const [error, setError] = (0, import_react24.useState)(null);
1029
+ const subRef = (0, import_react24.useRef)(null);
1030
+ (0, import_react24.useEffect)(() => {
1016
1031
  const sub = client.game.subscribeLeaderboard(client.realtime, period ? { period } : void 0);
1017
1032
  subRef.current = sub;
1018
1033
  sub.on("change", (data) => {
@@ -1029,21 +1044,21 @@ function useLeaderboard(period) {
1029
1044
  subRef.current = null;
1030
1045
  };
1031
1046
  }, [client, period]);
1032
- const refresh = (0, import_react23.useCallback)(async () => {
1047
+ const refresh = (0, import_react24.useCallback)(async () => {
1033
1048
  if (subRef.current) await subRef.current.refresh();
1034
1049
  }, []);
1035
1050
  return { entries, loading, error, refresh };
1036
1051
  }
1037
1052
 
1038
1053
  // src/dashboard/useGameActivity.ts
1039
- var import_react24 = require("react");
1054
+ var import_react25 = require("react");
1040
1055
  function useGameActivity() {
1041
1056
  const client = useDashboardClient();
1042
- const [events, setEvents] = (0, import_react24.useState)([]);
1043
- const [loading, setLoading] = (0, import_react24.useState)(true);
1044
- const [error, setError] = (0, import_react24.useState)(null);
1045
- const subRef = (0, import_react24.useRef)(null);
1046
- (0, import_react24.useEffect)(() => {
1057
+ const [events, setEvents] = (0, import_react25.useState)([]);
1058
+ const [loading, setLoading] = (0, import_react25.useState)(true);
1059
+ const [error, setError] = (0, import_react25.useState)(null);
1060
+ const subRef = (0, import_react25.useRef)(null);
1061
+ (0, import_react25.useEffect)(() => {
1047
1062
  const sub = client.game.subscribeActivity(client.realtime);
1048
1063
  subRef.current = sub;
1049
1064
  sub.on("change", (data) => {
@@ -1060,7 +1075,7 @@ function useGameActivity() {
1060
1075
  subRef.current = null;
1061
1076
  };
1062
1077
  }, [client]);
1063
- const refresh = (0, import_react24.useCallback)(async () => {
1078
+ const refresh = (0, import_react25.useCallback)(async () => {
1064
1079
  if (subRef.current) await subRef.current.refresh();
1065
1080
  }, []);
1066
1081
  return { events, loading, error, refresh };
package/dist/index.d.cts CHANGED
@@ -32,7 +32,9 @@ interface CStarChatProviderProps extends ChatConfig {
32
32
  }
33
33
  /**
34
34
  * Provides a ChatClient instance to all child components.
35
- * Creates the client on mount and disconnects on unmount.
35
+ * Creates the client once and disconnects it on a real unmount. The client
36
+ * survives StrictMode's simulated unmount, so an identified customer stays
37
+ * identified.
36
38
  *
37
39
  * ```tsx
38
40
  * <CStarChatProvider teamSlug="acme">
@@ -88,7 +90,7 @@ interface UseChatReturn {
88
90
  * const { identify, loginWithCredentials, isAuthenticated, authMode } = useChat();
89
91
  *
90
92
  * await identify(
91
- * { externalId: 'usr_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
93
+ * { externalId: 'user_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
92
94
  * hmacSignature
93
95
  * );
94
96
  * // OR
@@ -498,7 +500,7 @@ interface UsePlayerStatsReturn {
498
500
  * Subscribe to player stats (XP, level, streaks).
499
501
  *
500
502
  * ```tsx
501
- * const { player, loading, error } = usePlayerStats('user_123');
503
+ * const { player, loading, error } = usePlayerStats('550e8400-e29b-41d4-a716-446655440001');
502
504
  * ```
503
505
  */
504
506
  declare function usePlayerStats(memberId?: string): UsePlayerStatsReturn;
package/dist/index.d.ts CHANGED
@@ -32,7 +32,9 @@ interface CStarChatProviderProps extends ChatConfig {
32
32
  }
33
33
  /**
34
34
  * Provides a ChatClient instance to all child components.
35
- * Creates the client on mount and disconnects on unmount.
35
+ * Creates the client once and disconnects it on a real unmount. The client
36
+ * survives StrictMode's simulated unmount, so an identified customer stays
37
+ * identified.
36
38
  *
37
39
  * ```tsx
38
40
  * <CStarChatProvider teamSlug="acme">
@@ -88,7 +90,7 @@ interface UseChatReturn {
88
90
  * const { identify, loginWithCredentials, isAuthenticated, authMode } = useChat();
89
91
  *
90
92
  * await identify(
91
- * { externalId: 'usr_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
93
+ * { externalId: 'user_123', email: 'jane@co.com', timestamp: Date.now() / 1000 },
92
94
  * hmacSignature
93
95
  * );
94
96
  * // OR
@@ -498,7 +500,7 @@ interface UsePlayerStatsReturn {
498
500
  * Subscribe to player stats (XP, level, streaks).
499
501
  *
500
502
  * ```tsx
501
- * const { player, loading, error } = usePlayerStats('user_123');
503
+ * const { player, loading, error } = usePlayerStats('550e8400-e29b-41d4-a716-446655440001');
502
504
  * ```
503
505
  */
504
506
  declare function usePlayerStats(memberId?: string): UsePlayerStatsReturn;
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  // src/context.tsx
2
4
  import { createContext, useContext } from "react";
3
5
  var CStarChatContext = createContext(null);
@@ -26,20 +28,39 @@ function useCommunityClient() {
26
28
  }
27
29
 
28
30
  // src/chat/CStarChatProvider.tsx
29
- import { useEffect, useRef } from "react";
31
+ import { useRef as useRef2 } from "react";
30
32
  import { ChatClient } from "@cstar.help/js/chat";
33
+
34
+ // src/useDisconnectOnUnmount.ts
35
+ import { useEffect, useRef } from "react";
36
+ function useDisconnectOnUnmount(target, disconnect) {
37
+ const pending = useRef(null);
38
+ const disconnectRef = useRef(disconnect);
39
+ disconnectRef.current = disconnect;
40
+ useEffect(() => {
41
+ if (target === null) return;
42
+ if (pending.current?.target === target) {
43
+ clearTimeout(pending.current.timer);
44
+ pending.current = null;
45
+ }
46
+ return () => {
47
+ const timer = setTimeout(() => {
48
+ if (pending.current?.target === target) pending.current = null;
49
+ disconnectRef.current(target);
50
+ }, 0);
51
+ pending.current = { target, timer };
52
+ };
53
+ }, [target]);
54
+ }
55
+
56
+ // src/chat/CStarChatProvider.tsx
31
57
  import { jsx } from "react/jsx-runtime";
32
58
  function CStarChatProvider({ children, ...config }) {
33
- const clientRef = useRef(null);
59
+ const clientRef = useRef2(null);
34
60
  if (!clientRef.current) {
35
61
  clientRef.current = new ChatClient(config);
36
62
  }
37
- useEffect(() => {
38
- return () => {
39
- clientRef.current?.disconnect();
40
- clientRef.current = null;
41
- };
42
- }, []);
63
+ useDisconnectOnUnmount(clientRef.current, (client) => client.disconnect());
43
64
  return /* @__PURE__ */ jsx(CStarChatContext.Provider, { value: clientRef.current, children });
44
65
  }
45
66
 
@@ -135,14 +156,14 @@ function useChat() {
135
156
  }
136
157
 
137
158
  // src/chat/useTickets.ts
138
- import { useState as useState2, useEffect as useEffect3, useCallback as useCallback2, useRef as useRef2 } from "react";
159
+ import { useState as useState2, useEffect as useEffect3, useCallback as useCallback2, useRef as useRef3 } from "react";
139
160
  function useTickets() {
140
161
  const client = useChatClient();
141
162
  const [tickets, setTickets] = useState2([]);
142
163
  const [isLoading, setIsLoading] = useState2(true);
143
164
  const [error, setError] = useState2(null);
144
165
  const [hasMore, setHasMore] = useState2(false);
145
- const mountedRef = useRef2(true);
166
+ const mountedRef = useRef3(true);
146
167
  const refresh = useCallback2(async () => {
147
168
  setIsLoading(true);
148
169
  setError(null);
@@ -183,17 +204,17 @@ function useTickets() {
183
204
  }
184
205
 
185
206
  // src/chat/useMessages.ts
186
- import { useState as useState3, useEffect as useEffect4, useCallback as useCallback3, useRef as useRef3 } from "react";
207
+ import { useState as useState3, useEffect as useEffect4, useCallback as useCallback3, useRef as useRef4 } from "react";
187
208
  function useMessages(ticketId) {
188
209
  const client = useChatClient();
189
210
  const [messages, setMessages] = useState3([]);
190
211
  const [isLoading, setIsLoading] = useState3(true);
191
212
  const [error, setError] = useState3(null);
192
- const mountedRef = useRef3(true);
193
- const seenIdsRef = useRef3(/* @__PURE__ */ new Set());
194
- const requestRef = useRef3(0);
195
- const scopeRef = useRef3(0);
196
- const optimisticRef = useRef3(0);
213
+ const mountedRef = useRef4(true);
214
+ const seenIdsRef = useRef4(/* @__PURE__ */ new Set());
215
+ const requestRef = useRef4(0);
216
+ const scopeRef = useRef4(0);
217
+ const optimisticRef = useRef4(0);
197
218
  const refresh = useCallback3(async () => {
198
219
  if (!ticketId) return;
199
220
  const request = ++requestRef.current;
@@ -287,13 +308,13 @@ function useMessages(ticketId) {
287
308
  }
288
309
 
289
310
  // src/chat/useTyping.ts
290
- import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4, useRef as useRef4 } from "react";
311
+ import { useState as useState4, useEffect as useEffect5, useCallback as useCallback4, useRef as useRef5 } from "react";
291
312
  var TYPING_TIMEOUT = 4e3;
292
313
  function useTyping(ticketId) {
293
314
  const client = useChatClient();
294
315
  const [typingAgents, setTypingAgents] = useState4([]);
295
- const timersRef = useRef4(/* @__PURE__ */ new Map());
296
- const mountedRef = useRef4(true);
316
+ const timersRef = useRef5(/* @__PURE__ */ new Map());
317
+ const mountedRef = useRef5(true);
297
318
  useEffect5(() => {
298
319
  mountedRef.current = true;
299
320
  if (!ticketId) {
@@ -342,11 +363,11 @@ function useTyping(ticketId) {
342
363
  }
343
364
 
344
365
  // src/library/CStarLibraryProvider.tsx
345
- import { useRef as useRef5 } from "react";
366
+ import { useRef as useRef6 } from "react";
346
367
  import { LibraryClient } from "@cstar.help/js/library";
347
368
  import { jsx as jsx2 } from "react/jsx-runtime";
348
369
  function CStarLibraryProvider({ children, ...config }) {
349
- const clientRef = useRef5(null);
370
+ const clientRef = useRef6(null);
350
371
  if (!clientRef.current) {
351
372
  clientRef.current = new LibraryClient(config);
352
373
  }
@@ -354,13 +375,13 @@ function CStarLibraryProvider({ children, ...config }) {
354
375
  }
355
376
 
356
377
  // src/library/useCategories.ts
357
- import { useState as useState5, useEffect as useEffect6, useCallback as useCallback5, useRef as useRef6 } from "react";
378
+ import { useState as useState5, useEffect as useEffect6, useCallback as useCallback5, useRef as useRef7 } from "react";
358
379
  function useCategories() {
359
380
  const client = useLibraryClient();
360
381
  const [categories, setCategories] = useState5([]);
361
382
  const [isLoading, setIsLoading] = useState5(true);
362
383
  const [error, setError] = useState5(null);
363
- const mountedRef = useRef6(true);
384
+ const mountedRef = useRef7(true);
364
385
  const refresh = useCallback5(async () => {
365
386
  setIsLoading(true);
366
387
  setError(null);
@@ -390,13 +411,13 @@ function useCategories() {
390
411
  }
391
412
 
392
413
  // src/library/useArticles.ts
393
- import { useState as useState6, useEffect as useEffect7, useCallback as useCallback6, useRef as useRef7 } from "react";
414
+ import { useState as useState6, useEffect as useEffect7, useCallback as useCallback6, useRef as useRef8 } from "react";
394
415
  function useArticles(params) {
395
416
  const client = useLibraryClient();
396
417
  const [articles, setArticles] = useState6([]);
397
418
  const [isLoading, setIsLoading] = useState6(true);
398
419
  const [error, setError] = useState6(null);
399
- const mountedRef = useRef7(true);
420
+ const mountedRef = useRef8(true);
400
421
  const categorySlug = params?.categorySlug;
401
422
  const limit = params?.limit;
402
423
  const offset = params?.offset;
@@ -429,13 +450,13 @@ function useArticles(params) {
429
450
  }
430
451
 
431
452
  // src/library/useArticle.ts
432
- import { useState as useState7, useEffect as useEffect8, useCallback as useCallback7, useRef as useRef8 } from "react";
453
+ import { useState as useState7, useEffect as useEffect8, useCallback as useCallback7, useRef as useRef9 } from "react";
433
454
  function useArticle(slug) {
434
455
  const client = useLibraryClient();
435
456
  const [article, setArticle] = useState7(null);
436
457
  const [isLoading, setIsLoading] = useState7(true);
437
458
  const [error, setError] = useState7(null);
438
- const mountedRef = useRef8(true);
459
+ const mountedRef = useRef9(true);
439
460
  const refresh = useCallback7(async () => {
440
461
  if (!slug) return;
441
462
  setIsLoading(true);
@@ -478,7 +499,7 @@ function useArticle(slug) {
478
499
  }
479
500
 
480
501
  // src/library/useArticleSearch.ts
481
- import { useState as useState8, useEffect as useEffect9, useRef as useRef9 } from "react";
502
+ import { useState as useState8, useEffect as useEffect9, useRef as useRef10 } from "react";
482
503
  var DEBOUNCE_MS = 300;
483
504
  function useArticleSearch(query) {
484
505
  const client = useLibraryClient();
@@ -486,7 +507,7 @@ function useArticleSearch(query) {
486
507
  const [totalCount, setTotalCount] = useState8(0);
487
508
  const [isLoading, setIsLoading] = useState8(false);
488
509
  const [error, setError] = useState8(null);
489
- const mountedRef = useRef9(true);
510
+ const mountedRef = useRef10(true);
490
511
  useEffect9(() => {
491
512
  mountedRef.current = true;
492
513
  const trimmed = query.trim();
@@ -525,11 +546,11 @@ function useArticleSearch(query) {
525
546
  }
526
547
 
527
548
  // src/community/CStarCommunityProvider.tsx
528
- import { useRef as useRef10 } from "react";
549
+ import { useRef as useRef11 } from "react";
529
550
  import { CommunityClient } from "@cstar.help/js/community";
530
551
  import { jsx as jsx3 } from "react/jsx-runtime";
531
552
  function CStarCommunityProvider({ children, ...config }) {
532
- const clientRef = useRef10(null);
553
+ const clientRef = useRef11(null);
533
554
  if (!clientRef.current) {
534
555
  clientRef.current = new CommunityClient(config);
535
556
  }
@@ -537,13 +558,13 @@ function CStarCommunityProvider({ children, ...config }) {
537
558
  }
538
559
 
539
560
  // src/community/useTopics.ts
540
- import { useState as useState9, useEffect as useEffect10, useCallback as useCallback8, useRef as useRef11 } from "react";
561
+ import { useState as useState9, useEffect as useEffect10, useCallback as useCallback8, useRef as useRef12 } from "react";
541
562
  function useTopics() {
542
563
  const client = useCommunityClient();
543
564
  const [topics, setTopics] = useState9([]);
544
565
  const [isLoading, setIsLoading] = useState9(true);
545
566
  const [error, setError] = useState9(null);
546
- const mountedRef = useRef11(true);
567
+ const mountedRef = useRef12(true);
547
568
  const refresh = useCallback8(async () => {
548
569
  setIsLoading(true);
549
570
  setError(null);
@@ -573,14 +594,14 @@ function useTopics() {
573
594
  }
574
595
 
575
596
  // src/community/usePosts.ts
576
- import { useState as useState10, useEffect as useEffect11, useCallback as useCallback9, useRef as useRef12 } from "react";
597
+ import { useState as useState10, useEffect as useEffect11, useCallback as useCallback9, useRef as useRef13 } from "react";
577
598
  function usePosts(params) {
578
599
  const client = useCommunityClient();
579
600
  const [posts, setPosts] = useState10([]);
580
601
  const [count, setCount] = useState10(0);
581
602
  const [isLoading, setIsLoading] = useState10(true);
582
603
  const [error, setError] = useState10(null);
583
- const mountedRef = useRef12(true);
604
+ const mountedRef = useRef13(true);
584
605
  const topicSlug = params?.topicSlug;
585
606
  const status = params?.status;
586
607
  const sort = params?.sort;
@@ -616,13 +637,13 @@ function usePosts(params) {
616
637
  }
617
638
 
618
639
  // src/community/usePost.ts
619
- import { useState as useState11, useEffect as useEffect12, useCallback as useCallback10, useRef as useRef13 } from "react";
640
+ import { useState as useState11, useEffect as useEffect12, useCallback as useCallback10, useRef as useRef14 } from "react";
620
641
  function usePost(slug) {
621
642
  const client = useCommunityClient();
622
643
  const [data, setData] = useState11(null);
623
644
  const [isLoading, setIsLoading] = useState11(true);
624
645
  const [error, setError] = useState11(null);
625
- const mountedRef = useRef13(true);
646
+ const mountedRef = useRef14(true);
626
647
  const refresh = useCallback10(async () => {
627
648
  setIsLoading(true);
628
649
  setError(null);
@@ -652,13 +673,13 @@ function usePost(slug) {
652
673
  }
653
674
 
654
675
  // src/community/useCommunitySearch.ts
655
- import { useState as useState12, useEffect as useEffect13, useCallback as useCallback11, useRef as useRef14 } from "react";
676
+ import { useState as useState12, useEffect as useEffect13, useCallback as useCallback11, useRef as useRef15 } from "react";
656
677
  function useCommunitySearch() {
657
678
  const client = useCommunityClient();
658
679
  const [results, setResults] = useState12(null);
659
680
  const [isLoading, setIsLoading] = useState12(false);
660
681
  const [error, setError] = useState12(null);
661
- const mountedRef = useRef14(true);
682
+ const mountedRef = useRef15(true);
662
683
  useEffect13(() => {
663
684
  mountedRef.current = true;
664
685
  return () => {
@@ -694,7 +715,7 @@ function useCommunitySearch() {
694
715
  }
695
716
 
696
717
  // src/dashboard/CStarDashboardProvider.tsx
697
- import { createContext as createContext2, useContext as useContext2, useEffect as useEffect14, useMemo } from "react";
718
+ import { createContext as createContext2, useContext as useContext2, useMemo } from "react";
698
719
  import { CStarClient } from "@cstar.help/js";
699
720
  import { jsx as jsx4 } from "react/jsx-runtime";
700
721
  var CStarDashboardContext = createContext2(null);
@@ -705,7 +726,7 @@ function CStarDashboardProvider({
705
726
  }) {
706
727
  if (!config && !providedClient) {
707
728
  throw new Error(
708
- "CStarDashboardProvider requires either a `config` prop (`{ apiKey, teamId }`, recommended) or a `client` prop (a pre-built CStarClient instance, deprecated). See https://cstar.help/developers/sdk/react#dashboard"
729
+ "CStarDashboardProvider requires either a `config` prop (`{ apiKey, teamId }`, recommended) or a `client` prop (a pre-built CStarClient instance, deprecated). See https://www.cstar.help/developers/sdk/react#dashboard"
709
730
  );
710
731
  }
711
732
  const client = useMemo(() => {
@@ -721,12 +742,7 @@ function CStarDashboardProvider({
721
742
  config?.timeout
722
743
  ]);
723
744
  const contextValue = useMemo(() => ({ client }), [client]);
724
- useEffect14(() => {
725
- if (providedClient) return;
726
- return () => {
727
- client?.realtime?.disconnect?.();
728
- };
729
- }, [client, providedClient]);
745
+ useDisconnectOnUnmount(providedClient ? null : client, (owned) => owned.realtime?.disconnect?.());
730
746
  return /* @__PURE__ */ jsx4(CStarDashboardContext.Provider, { value: contextValue, children });
731
747
  }
732
748
  function useDashboardClient() {
@@ -738,7 +754,7 @@ function useDashboardClient() {
738
754
  }
739
755
 
740
756
  // src/dashboard/useCStarQuery.ts
741
- import { useState as useState13, useEffect as useEffect15, useRef as useRef15, useCallback as useCallback12 } from "react";
757
+ import { useState as useState13, useEffect as useEffect14, useRef as useRef16, useCallback as useCallback12 } from "react";
742
758
  import { CStarValidationError } from "@cstar.help/js";
743
759
  function resolveResource(client, path) {
744
760
  const parts = path.split(".");
@@ -760,9 +776,9 @@ function useCStarQuery(resource, params) {
760
776
  const [data, setData] = useState13(null);
761
777
  const [loading, setLoading] = useState13(true);
762
778
  const [error, setError] = useState13(null);
763
- const subscriptionRef = useRef15(null);
779
+ const subscriptionRef = useRef16(null);
764
780
  const paramsKey = params ? JSON.stringify(params) : "";
765
- useEffect15(() => {
781
+ useEffect14(() => {
766
782
  const resolved = resolveResource(client, resource);
767
783
  if (!resolved) {
768
784
  setError(new Error(`Invalid resource path: ${resource}. Expected format: 'tickets.list'`));
@@ -849,14 +865,14 @@ function useCStarMutation(resource) {
849
865
  }
850
866
 
851
867
  // src/dashboard/useCStarEvents.ts
852
- import { useState as useState15, useEffect as useEffect16 } from "react";
868
+ import { useState as useState15, useEffect as useEffect15 } from "react";
853
869
  var MAX_EVENTS = 100;
854
870
  function useCStarEvents(types) {
855
871
  const client = useDashboardClient();
856
872
  const [events, setEvents] = useState15([]);
857
873
  const [connected, setConnected] = useState15(false);
858
874
  const typesKey = types ? types.join(",") : "";
859
- useEffect16(() => {
875
+ useEffect15(() => {
860
876
  const realtime = client.realtime;
861
877
  const handler = (event) => {
862
878
  if (types && types.length > 0) {
@@ -888,14 +904,14 @@ function useCStarEvents(types) {
888
904
  }
889
905
 
890
906
  // src/dashboard/useBossBattle.ts
891
- import { useState as useState16, useEffect as useEffect17, useRef as useRef16, useCallback as useCallback14 } from "react";
907
+ import { useState as useState16, useEffect as useEffect16, useRef as useRef17, useCallback as useCallback14 } from "react";
892
908
  function useBossBattle() {
893
909
  const client = useDashboardClient();
894
910
  const [boss, setBoss] = useState16(null);
895
911
  const [loading, setLoading] = useState16(true);
896
912
  const [error, setError] = useState16(null);
897
- const subRef = useRef16(null);
898
- useEffect17(() => {
913
+ const subRef = useRef17(null);
914
+ useEffect16(() => {
899
915
  const sub = client.game.subscribeBoss(client.realtime);
900
916
  subRef.current = sub;
901
917
  sub.on("change", (data) => {
@@ -919,14 +935,14 @@ function useBossBattle() {
919
935
  }
920
936
 
921
937
  // src/dashboard/usePlayerStats.ts
922
- import { useState as useState17, useEffect as useEffect18, useRef as useRef17, useCallback as useCallback15 } from "react";
938
+ import { useState as useState17, useEffect as useEffect17, useRef as useRef18, useCallback as useCallback15 } from "react";
923
939
  function usePlayerStats(memberId) {
924
940
  const client = useDashboardClient();
925
941
  const [player, setPlayer] = useState17(null);
926
942
  const [loading, setLoading] = useState17(true);
927
943
  const [error, setError] = useState17(null);
928
- const subRef = useRef17(null);
929
- useEffect18(() => {
944
+ const subRef = useRef18(null);
945
+ useEffect17(() => {
930
946
  const sub = client.game.subscribePlayer(client.realtime, memberId);
931
947
  subRef.current = sub;
932
948
  sub.on("change", (data) => {
@@ -950,14 +966,14 @@ function usePlayerStats(memberId) {
950
966
  }
951
967
 
952
968
  // src/dashboard/useLeaderboard.ts
953
- import { useState as useState18, useEffect as useEffect19, useRef as useRef18, useCallback as useCallback16 } from "react";
969
+ import { useState as useState18, useEffect as useEffect18, useRef as useRef19, useCallback as useCallback16 } from "react";
954
970
  function useLeaderboard(period) {
955
971
  const client = useDashboardClient();
956
972
  const [entries, setEntries] = useState18([]);
957
973
  const [loading, setLoading] = useState18(true);
958
974
  const [error, setError] = useState18(null);
959
- const subRef = useRef18(null);
960
- useEffect19(() => {
975
+ const subRef = useRef19(null);
976
+ useEffect18(() => {
961
977
  const sub = client.game.subscribeLeaderboard(client.realtime, period ? { period } : void 0);
962
978
  subRef.current = sub;
963
979
  sub.on("change", (data) => {
@@ -981,14 +997,14 @@ function useLeaderboard(period) {
981
997
  }
982
998
 
983
999
  // src/dashboard/useGameActivity.ts
984
- import { useState as useState19, useEffect as useEffect20, useRef as useRef19, useCallback as useCallback17 } from "react";
1000
+ import { useState as useState19, useEffect as useEffect19, useRef as useRef20, useCallback as useCallback17 } from "react";
985
1001
  function useGameActivity() {
986
1002
  const client = useDashboardClient();
987
1003
  const [events, setEvents] = useState19([]);
988
1004
  const [loading, setLoading] = useState19(true);
989
1005
  const [error, setError] = useState19(null);
990
- const subRef = useRef19(null);
991
- useEffect20(() => {
1006
+ const subRef = useRef20(null);
1007
+ useEffect19(() => {
992
1008
  const sub = client.game.subscribeActivity(client.realtime);
993
1009
  subRef.current = sub;
994
1010
  sub.on("change", (data) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cstar.help/react",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "React hooks for the cStar customer support platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",