@flamingo-stack/openframe-frontend-core 0.0.503 → 0.0.504-snapshot.20260801181709

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.
Files changed (191) hide show
  1. package/dist/{chunk-SGWPW2AO.cjs → chunk-2A74VRAF.cjs} +18 -18
  2. package/dist/{chunk-SGWPW2AO.cjs.map → chunk-2A74VRAF.cjs.map} +1 -1
  3. package/dist/{chunk-LILQJ3UZ.cjs → chunk-3ENGUBJP.cjs} +1 -1
  4. package/dist/chunk-3ENGUBJP.cjs.map +1 -0
  5. package/dist/{chunk-AWDHRIL3.cjs → chunk-4ST2BOWJ.cjs} +75 -75
  6. package/dist/{chunk-AWDHRIL3.cjs.map → chunk-4ST2BOWJ.cjs.map} +1 -1
  7. package/dist/{chunk-SFJRMBJC.js → chunk-5SVNA7IU.js} +2 -2
  8. package/dist/{chunk-OAWFYZZT.js → chunk-7DOSAJDK.js} +3 -3
  9. package/dist/{chunk-J4T5ZBWG.cjs → chunk-BZRP54IO.cjs} +19 -19
  10. package/dist/{chunk-J4T5ZBWG.cjs.map → chunk-BZRP54IO.cjs.map} +1 -1
  11. package/dist/{chunk-BZF63JXP.js → chunk-CRJVO4KO.js} +6 -6
  12. package/dist/{chunk-5RIHLXEP.cjs → chunk-DDVQ5NKK.cjs} +33 -33
  13. package/dist/{chunk-5RIHLXEP.cjs.map → chunk-DDVQ5NKK.cjs.map} +1 -1
  14. package/dist/{chunk-HR6F6IP4.js → chunk-DIKJLAMY.js} +78 -43
  15. package/dist/chunk-DIKJLAMY.js.map +1 -0
  16. package/dist/{chunk-VO2ZONMR.js → chunk-FNTFWP2A.js} +3 -3
  17. package/dist/{chunk-2OXJ6NHI.cjs → chunk-GJZ42TTG.cjs} +7 -7
  18. package/dist/{chunk-2OXJ6NHI.cjs.map → chunk-GJZ42TTG.cjs.map} +1 -1
  19. package/dist/{chunk-JIZJDAXI.cjs → chunk-GXRVBKYX.cjs} +12 -12
  20. package/dist/{chunk-JIZJDAXI.cjs.map → chunk-GXRVBKYX.cjs.map} +1 -1
  21. package/dist/{chunk-F7AD5CUU.js → chunk-H3N4P3CG.js} +3 -3
  22. package/dist/chunk-H3N4P3CG.js.map +1 -0
  23. package/dist/{chunk-VCPTU4IW.js → chunk-HWER6KGU.js} +7 -7
  24. package/dist/{chunk-4SR2QHMB.js → chunk-ITVWX5HX.js} +3 -3
  25. package/dist/{chunk-FFXNRJ5S.cjs → chunk-LOBR7IC6.cjs} +6 -6
  26. package/dist/chunk-LOBR7IC6.cjs.map +1 -0
  27. package/dist/{chunk-72DF3QTA.cjs → chunk-MJQ263KS.cjs} +14 -14
  28. package/dist/{chunk-72DF3QTA.cjs.map → chunk-MJQ263KS.cjs.map} +1 -1
  29. package/dist/{chunk-FTOVZ7O2.js → chunk-NPO6CHCR.js} +7 -7
  30. package/dist/{chunk-XV5SXALY.js → chunk-NT5FX7GZ.js} +3 -3
  31. package/dist/{chunk-UCV4LFUG.cjs → chunk-NY75FKN6.cjs} +40 -40
  32. package/dist/{chunk-UCV4LFUG.cjs.map → chunk-NY75FKN6.cjs.map} +1 -1
  33. package/dist/{chunk-4UNQMYP7.cjs → chunk-O32Y4E4R.cjs} +3 -3
  34. package/dist/{chunk-4UNQMYP7.cjs.map → chunk-O32Y4E4R.cjs.map} +1 -1
  35. package/dist/{chunk-CLQEBWV7.js → chunk-QE55ROZW.js} +4 -4
  36. package/dist/{chunk-WHJGRRK2.js → chunk-QW7SW5HY.js} +52 -43
  37. package/dist/chunk-QW7SW5HY.js.map +1 -0
  38. package/dist/{chunk-JGXAVNZQ.js → chunk-R6CKL7IR.js} +2464 -1886
  39. package/dist/chunk-R6CKL7IR.js.map +1 -0
  40. package/dist/{chunk-L5CI57RM.cjs → chunk-T3BF6JTQ.cjs} +52 -43
  41. package/dist/chunk-T3BF6JTQ.cjs.map +1 -0
  42. package/dist/{chunk-G43CEISB.js → chunk-TA3VJ2QO.js} +4 -4
  43. package/dist/{chunk-7L2RVINX.cjs → chunk-TRS4CIAS.cjs} +35 -35
  44. package/dist/{chunk-7L2RVINX.cjs.map → chunk-TRS4CIAS.cjs.map} +1 -1
  45. package/dist/{chunk-DMXB3VE2.cjs → chunk-U3YLML53.cjs} +1837 -1259
  46. package/dist/chunk-U3YLML53.cjs.map +1 -0
  47. package/dist/{chunk-3T4SMJM5.cjs → chunk-VDKNUC3N.cjs} +181 -146
  48. package/dist/chunk-VDKNUC3N.cjs.map +1 -0
  49. package/dist/{chunk-RR3Z52X5.cjs → chunk-W3QCFQ56.cjs} +42 -42
  50. package/dist/{chunk-RR3Z52X5.cjs.map → chunk-W3QCFQ56.cjs.map} +1 -1
  51. package/dist/{chunk-VYEDTVIZ.js → chunk-XJPMTJAR.js} +4 -4
  52. package/dist/{chunk-6GT557KN.js → chunk-XKIA4XVE.js} +1 -1
  53. package/dist/chunk-XKIA4XVE.js.map +1 -0
  54. package/dist/components/case-studies/index.cjs +11 -11
  55. package/dist/components/case-studies/index.js +5 -5
  56. package/dist/components/chat/index.cjs +5 -5
  57. package/dist/components/chat/index.js +4 -4
  58. package/dist/components/contact/index.cjs +6 -6
  59. package/dist/components/contact/index.js +5 -5
  60. package/dist/components/docs/index.cjs +8 -8
  61. package/dist/components/docs/index.js +7 -7
  62. package/dist/components/embeds/index.cjs +6 -6
  63. package/dist/components/embeds/index.js +5 -5
  64. package/dist/components/faq/index.cjs +7 -7
  65. package/dist/components/faq/index.js +6 -6
  66. package/dist/components/features/index.cjs +5 -5
  67. package/dist/components/features/index.js +4 -4
  68. package/dist/components/help-center-pages/index.cjs +24 -24
  69. package/dist/components/help-center-pages/index.js +15 -15
  70. package/dist/components/index.cjs +169 -165
  71. package/dist/components/index.cjs.map +1 -1
  72. package/dist/components/index.js +17 -13
  73. package/dist/components/index.js.map +1 -1
  74. package/dist/components/navigation/app-header.d.ts +8 -0
  75. package/dist/components/navigation/app-header.d.ts.map +1 -1
  76. package/dist/components/navigation/header-button.d.ts +5 -1
  77. package/dist/components/navigation/header-button.d.ts.map +1 -1
  78. package/dist/components/navigation/header.d.ts.map +1 -1
  79. package/dist/components/navigation/index.cjs +9 -5
  80. package/dist/components/navigation/index.cjs.map +1 -1
  81. package/dist/components/navigation/index.d.ts +4 -0
  82. package/dist/components/navigation/index.d.ts.map +1 -1
  83. package/dist/components/navigation/index.js +8 -4
  84. package/dist/components/navigation/mingo-ai-button.d.ts.map +1 -1
  85. package/dist/components/navigation/navigation-sidebar-item.d.ts.map +1 -1
  86. package/dist/components/navigation/ticket-alerts-button.d.ts +29 -0
  87. package/dist/components/navigation/ticket-alerts-button.d.ts.map +1 -0
  88. package/dist/components/navigation/top-navigation.d.ts +5 -1
  89. package/dist/components/navigation/top-navigation.d.ts.map +1 -1
  90. package/dist/components/navigation/unread-dot.d.ts +19 -0
  91. package/dist/components/navigation/unread-dot.d.ts.map +1 -0
  92. package/dist/components/onboarding-guides/index.cjs +9 -9
  93. package/dist/components/onboarding-guides/index.js +8 -8
  94. package/dist/components/related-content/index.cjs +7 -7
  95. package/dist/components/related-content/index.js +6 -6
  96. package/dist/components/tickets/help-center-card.d.ts.map +1 -1
  97. package/dist/components/tickets/hooks/use-ticket-actions.d.ts.map +1 -1
  98. package/dist/components/tickets/hooks/use-ticket-engagements.d.ts +1 -9
  99. package/dist/components/tickets/hooks/use-ticket-engagements.d.ts.map +1 -1
  100. package/dist/components/tickets/hooks/use-tickets-list.d.ts +0 -7
  101. package/dist/components/tickets/hooks/use-tickets-list.d.ts.map +1 -1
  102. package/dist/components/tickets/index.cjs +15 -8
  103. package/dist/components/tickets/index.cjs.map +1 -1
  104. package/dist/components/tickets/index.d.ts +2 -1
  105. package/dist/components/tickets/index.d.ts.map +1 -1
  106. package/dist/components/tickets/index.js +14 -7
  107. package/dist/components/tickets/ticket-detail-drawer.d.ts.map +1 -1
  108. package/dist/components/tickets/ticket-live-provider.d.ts +58 -0
  109. package/dist/components/tickets/ticket-live-provider.d.ts.map +1 -0
  110. package/dist/components/tickets/types.d.ts +58 -11
  111. package/dist/components/tickets/types.d.ts.map +1 -1
  112. package/dist/components/ui/button/button.d.ts +6 -5
  113. package/dist/components/ui/button/button.d.ts.map +1 -1
  114. package/dist/components/ui/file-manager/index.cjs +50 -50
  115. package/dist/components/ui/file-manager/index.js +1 -1
  116. package/dist/components/ui/index.cjs +5 -5
  117. package/dist/components/ui/index.js +4 -4
  118. package/dist/contexts/chat-runtime-context.d.ts +8 -0
  119. package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
  120. package/dist/contexts/index.cjs +2 -2
  121. package/dist/contexts/index.js +1 -1
  122. package/dist/hooks/index.cjs +3 -3
  123. package/dist/hooks/index.js +2 -2
  124. package/dist/hooks/ui/use-header-height.d.ts.map +1 -1
  125. package/dist/index.cjs +11 -5
  126. package/dist/index.cjs.map +1 -1
  127. package/dist/index.js +10 -4
  128. package/dist/types/navigation.d.ts +10 -0
  129. package/dist/types/navigation.d.ts.map +1 -1
  130. package/dist/utils/index.cjs +171 -0
  131. package/dist/utils/index.cjs.map +1 -1
  132. package/dist/utils/index.d.ts +1 -0
  133. package/dist/utils/index.d.ts.map +1 -1
  134. package/dist/utils/index.js +171 -1
  135. package/dist/utils/index.js.map +1 -1
  136. package/dist/utils/sse-subscription.d.ts +60 -0
  137. package/dist/utils/sse-subscription.d.ts.map +1 -0
  138. package/package.json +1 -1
  139. package/src/components/features/time-tracker/time-tracker-header-button.tsx +1 -1
  140. package/src/components/navigation/app-header.tsx +36 -20
  141. package/src/components/navigation/header-button.tsx +18 -2
  142. package/src/components/navigation/header-mingo-button.tsx +2 -2
  143. package/src/components/navigation/header-skeleton.tsx +4 -4
  144. package/src/components/navigation/header.tsx +41 -21
  145. package/src/components/navigation/index.ts +4 -0
  146. package/src/components/navigation/mingo-ai-button.tsx +23 -22
  147. package/src/components/navigation/mobile-burger-menu.tsx +3 -3
  148. package/src/components/navigation/navigation-sidebar-item.tsx +2 -3
  149. package/src/components/navigation/ticket-alerts-button.tsx +61 -0
  150. package/src/components/navigation/top-navigation.tsx +17 -1
  151. package/src/components/navigation/unread-dot.tsx +34 -0
  152. package/src/components/tickets/.types.md +1 -2
  153. package/src/components/tickets/help-center-card.tsx +16 -0
  154. package/src/components/tickets/help-center-list.tsx +6 -6
  155. package/src/components/tickets/hooks/.use-ticket-engagements.md +3 -12
  156. package/src/components/tickets/hooks/.use-tickets-list.md +0 -2
  157. package/src/components/tickets/hooks/use-ticket-actions.ts +9 -0
  158. package/src/components/tickets/hooks/use-ticket-engagements.ts +4 -13
  159. package/src/components/tickets/hooks/use-tickets-list.ts +2 -13
  160. package/src/components/tickets/index.ts +10 -0
  161. package/src/components/tickets/ticket-detail-drawer.tsx +45 -13
  162. package/src/components/tickets/ticket-live-provider.tsx +474 -0
  163. package/src/components/tickets/types.ts +62 -11
  164. package/src/components/ui/button/button.tsx +165 -133
  165. package/src/contexts/chat-runtime-context.tsx +8 -0
  166. package/src/hooks/ui/use-header-height.ts +3 -1
  167. package/src/stories/TopNavigation.stories.tsx +20 -1
  168. package/src/types/navigation.ts +10 -0
  169. package/src/utils/index.ts +12 -0
  170. package/src/utils/sse-subscription.ts +276 -0
  171. package/dist/chunk-3T4SMJM5.cjs.map +0 -1
  172. package/dist/chunk-6GT557KN.js.map +0 -1
  173. package/dist/chunk-DMXB3VE2.cjs.map +0 -1
  174. package/dist/chunk-F7AD5CUU.js.map +0 -1
  175. package/dist/chunk-FFXNRJ5S.cjs.map +0 -1
  176. package/dist/chunk-HR6F6IP4.js.map +0 -1
  177. package/dist/chunk-JGXAVNZQ.js.map +0 -1
  178. package/dist/chunk-L5CI57RM.cjs.map +0 -1
  179. package/dist/chunk-LILQJ3UZ.cjs.map +0 -1
  180. package/dist/chunk-WHJGRRK2.js.map +0 -1
  181. /package/dist/{chunk-SFJRMBJC.js.map → chunk-5SVNA7IU.js.map} +0 -0
  182. /package/dist/{chunk-OAWFYZZT.js.map → chunk-7DOSAJDK.js.map} +0 -0
  183. /package/dist/{chunk-BZF63JXP.js.map → chunk-CRJVO4KO.js.map} +0 -0
  184. /package/dist/{chunk-VO2ZONMR.js.map → chunk-FNTFWP2A.js.map} +0 -0
  185. /package/dist/{chunk-VCPTU4IW.js.map → chunk-HWER6KGU.js.map} +0 -0
  186. /package/dist/{chunk-4SR2QHMB.js.map → chunk-ITVWX5HX.js.map} +0 -0
  187. /package/dist/{chunk-FTOVZ7O2.js.map → chunk-NPO6CHCR.js.map} +0 -0
  188. /package/dist/{chunk-XV5SXALY.js.map → chunk-NT5FX7GZ.js.map} +0 -0
  189. /package/dist/{chunk-CLQEBWV7.js.map → chunk-QE55ROZW.js.map} +0 -0
  190. /package/dist/{chunk-G43CEISB.js.map → chunk-TA3VJ2QO.js.map} +0 -0
  191. /package/dist/{chunk-VYEDTVIZ.js.map → chunk-XJPMTJAR.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  ContactForm
4
- } from "./chunk-CLQEBWV7.js";
4
+ } from "./chunk-QE55ROZW.js";
5
5
  import {
6
6
  DeliveryRow,
7
7
  DevCardRowContent,
@@ -10,7 +10,7 @@ import {
10
10
  EmptyState,
11
11
  UnifiedPagination,
12
12
  init_unified_pagination
13
- } from "./chunk-OAWFYZZT.js";
13
+ } from "./chunk-7DOSAJDK.js";
14
14
  import {
15
15
  AlertDialog,
16
16
  AlertDialogAction,
@@ -36,18 +36,19 @@ import {
36
36
  formatRelativeTime,
37
37
  getStatusColorScheme,
38
38
  useChatAttachments,
39
- useChatIdentity
40
- } from "./chunk-JGXAVNZQ.js";
39
+ useChatIdentity,
40
+ useOptionalTicketLive
41
+ } from "./chunk-R6CKL7IR.js";
41
42
  import {
42
43
  STICKY_HEADER_OFFSET_PX,
43
44
  embedAuthedFetch,
44
45
  scrollElementIntoView,
45
46
  toast,
46
47
  useScrollToHash
47
- } from "./chunk-F7AD5CUU.js";
48
+ } from "./chunk-H3N4P3CG.js";
48
49
  import {
49
50
  useRequiredChatRuntime
50
- } from "./chunk-6GT557KN.js";
51
+ } from "./chunk-XKIA4XVE.js";
51
52
  import {
52
53
  usePathname,
53
54
  useRouter,
@@ -58,7 +59,7 @@ import {
58
59
  Input,
59
60
  Skeleton,
60
61
  init_button2 as init_button
61
- } from "./chunk-WHJGRRK2.js";
62
+ } from "./chunk-QW7SW5HY.js";
62
63
 
63
64
  // src/components/tickets/ticket-center.tsx
64
65
  import { useCallback as useCallback4, useState as useState4 } from "react";
@@ -75,7 +76,7 @@ function isOptimistic(t) {
75
76
  return t._optimistic === true;
76
77
  }
77
78
  var TICKET_TEXT_MAX_CHARS = 5e3;
78
- var TICKET_LIVE_POLL_MS = 8e3;
79
+ var TICKET_MARK_READ_DEBOUNCE_MS = 2e3;
79
80
  var TOAST_COPY = {
80
81
  open_success: { title: "Ticket opened", description: "We received your message and will follow up shortly." },
81
82
  open_mirror_pending: { title: "Ticket opened", description: "Syncing \u2014 your ticket will appear momentarily." },
@@ -211,7 +212,7 @@ function TicketOpenForm({
211
212
  }
212
213
 
213
214
  // src/components/tickets/ticket-row.tsx
214
- import { useCallback as useCallback2, useRef } from "react";
215
+ import { useCallback as useCallback2, useRef as useRef2 } from "react";
215
216
 
216
217
  // src/components/collapsible.tsx
217
218
  import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
@@ -220,12 +221,13 @@ var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
220
221
 
221
222
  // src/components/tickets/ticket-detail-drawer.tsx
222
223
  init_button();
224
+ import { useEffect, useRef } from "react";
223
225
  import { useStickToBottom } from "use-stick-to-bottom";
224
226
 
225
227
  // src/components/tickets/hooks/use-ticket-engagements.ts
226
228
  import { useQuery } from "@tanstack/react-query";
227
229
  var LIST_ENGAGEMENTS_ENDPOINT = "/api/chat/agent/list-engagements";
228
- function useTicketEngagements(externalTicketId, enabled = true, refetchInterval = false) {
230
+ function useTicketEngagements(externalTicketId, enabled = true) {
229
231
  const identity = useChatIdentity();
230
232
  const identityKey = identity.user?.email ?? "anon";
231
233
  const listEngagementsEndpoint = useRequiredChatRuntime().endpoints.listEngagementsUrl ?? LIST_ENGAGEMENTS_ENDPOINT;
@@ -241,11 +243,10 @@ function useTicketEngagements(externalTicketId, enabled = true, refetchInterval
241
243
  gcTime: 0,
242
244
  refetchOnMount: "always",
243
245
  refetchOnWindowFocus: true,
244
- // Live conversation: poll while the caller opts in (drawer open). New
245
- // agent replies + attachments appear within one interval without a
246
- // manual refresh. `refetchIntervalInBackground` stays false (default)
247
- // so polling pauses on a hidden tab.
248
- refetchInterval,
246
+ // NO interval polling (deleted 2026-08): new agent replies arrive via
247
+ // `TicketLiveProvider`'s stream-driven invalidation of
248
+ // `['ticket-engagements', id]`; focus/mount refetch is the no-stream
249
+ // fallback.
249
250
  queryFn: async () => {
250
251
  const response = await embedAuthedFetch(listEngagementsEndpoint, {
251
252
  method: "POST",
@@ -504,11 +505,33 @@ var TICKET_FEED_SKELETON_ROWS = 6;
504
505
  function TicketTimelinePanel({ ticket }) {
505
506
  const identity = useChatIdentity();
506
507
  const externalId = isOptimistic(ticket) ? null : ticket.external_id;
507
- const { engagements, isLoading } = useTicketEngagements(
508
- externalId,
509
- !!externalId,
510
- TICKET_LIVE_POLL_MS
511
- );
508
+ const { engagements, isLoading } = useTicketEngagements(externalId, !!externalId);
509
+ const live = useOptionalTicketLive();
510
+ const setOpenTicketId = live?.setOpenTicketId;
511
+ const markRead = live?.markRead;
512
+ const markReadDebounceRef = useRef(null);
513
+ useEffect(() => {
514
+ if (!externalId || !setOpenTicketId || !markRead) return;
515
+ setOpenTicketId(externalId);
516
+ void markRead(externalId);
517
+ return () => {
518
+ if (markReadDebounceRef.current) {
519
+ clearTimeout(markReadDebounceRef.current);
520
+ markReadDebounceRef.current = null;
521
+ void markRead(externalId);
522
+ }
523
+ setOpenTicketId(null);
524
+ };
525
+ }, [externalId, setOpenTicketId, markRead]);
526
+ const engagementsCount = engagements.length;
527
+ useEffect(() => {
528
+ if (!externalId || !markRead || engagementsCount === 0) return;
529
+ if (markReadDebounceRef.current) clearTimeout(markReadDebounceRef.current);
530
+ markReadDebounceRef.current = setTimeout(() => {
531
+ markReadDebounceRef.current = null;
532
+ void markRead(externalId);
533
+ }, TICKET_MARK_READ_DEBOUNCE_MS);
534
+ }, [engagementsCount, externalId, markRead]);
512
535
  const { scrollRef, contentRef } = useStickToBottom({ initial: "instant", resize: "smooth" });
513
536
  const bodyTurns = ticket.body ? ticket.body.split(TURN_SEPARATOR_RE).map((t) => t.trim()).filter(Boolean) : [];
514
537
  const customerEngagementBodies = new Set(
@@ -693,7 +716,7 @@ function TicketRow({
693
716
  id
694
717
  }) {
695
718
  const optimistic = isOptimistic(ticket);
696
- const rowRef = useRef(null);
719
+ const rowRef = useRef2(null);
697
720
  const handleClick = useCallback2(() => {
698
721
  onToggle(ticket.id);
699
722
  scrollElementIntoView(rowRef.current, {
@@ -783,7 +806,6 @@ function useTicketsList(filters) {
783
806
  const pageSize = Math.max(1, Math.min(100, Math.floor(filters.pageSize ?? DEFAULT_PAGE_SIZE) || DEFAULT_PAGE_SIZE));
784
807
  const enabled = !!customerEmail;
785
808
  const identityKey = customerEmail || "anon";
786
- const refetchInterval = filters.refetchInterval ?? false;
787
809
  const query = useQuery2({
788
810
  queryKey: ["tickets", "self", identityKey, search, statusFilter, page, pageSize],
789
811
  enabled,
@@ -796,10 +818,8 @@ function useTicketsList(filters) {
796
818
  gcTime: 0,
797
819
  refetchOnMount: "always",
798
820
  refetchOnWindowFocus: true,
799
- // Live status: poll while the caller opts in (drawer open). Defaults to
800
- // false. `refetchIntervalInBackground` stays false (the default) so polling
801
- // pauses on a hidden tab — no wasted requests when the user tabs away.
802
- refetchInterval,
821
+ // NO interval polling (deleted 2026-08): live freshness is push-driven
822
+ // — `TicketLiveProvider` invalidates `['tickets']` on stream events.
803
823
  queryFn: async () => {
804
824
  const body = {
805
825
  query: search,
@@ -861,7 +881,7 @@ function useTicketsList(filters) {
861
881
  }
862
882
 
863
883
  // src/components/tickets/hooks/use-ticket-actions.ts
864
- import { useCallback as useCallback3, useEffect, useMemo, useRef as useRef2, useState as useState3 } from "react";
884
+ import { useCallback as useCallback3, useEffect as useEffect2, useMemo, useRef as useRef3, useState as useState3 } from "react";
865
885
  import { useQueryClient } from "@tanstack/react-query";
866
886
  var TICKET_ACTION_ENDPOINT = "/api/chat/agent/ticket-action";
867
887
  var REPLY_BANNER_CODES = /* @__PURE__ */ new Set([
@@ -874,10 +894,12 @@ var MIRROR_SYNC_BACKOFF_MS = [3e3, 6e3, 12e3];
874
894
  function useTicketActions(options) {
875
895
  const queryClient = useQueryClient();
876
896
  const ticketActionEndpoint = useRequiredChatRuntime().endpoints.ticketActionUrl ?? TICKET_ACTION_ENDPOINT;
897
+ const ticketLive = useOptionalTicketLive();
898
+ const notifyTicketCreated = ticketLive?.notifyTicketCreated;
877
899
  const { prependOptimistic, removeOptimistic, removeTicketFromCache, toast: toast2, onSupportSystemDown } = options;
878
- const formInFlightRef = useRef2(false);
900
+ const formInFlightRef = useRef3(false);
879
901
  const [isSubmittingForm, setIsSubmittingForm] = useState3(false);
880
- const busyRowsRef = useRef2(/* @__PURE__ */ new Set());
902
+ const busyRowsRef = useRef3(/* @__PURE__ */ new Set());
881
903
  const [busyRows, setBusyRows] = useState3(() => /* @__PURE__ */ new Set());
882
904
  const setRowBusy = useCallback3((id, busy) => {
883
905
  if (busy) busyRowsRef.current.add(id);
@@ -905,8 +927,8 @@ function useTicketActions(options) {
905
927
  (externalId) => setReplyError(externalId, null),
906
928
  [setReplyError]
907
929
  );
908
- const watcherControllersRef = useRef2(/* @__PURE__ */ new Map());
909
- useEffect(() => {
930
+ const watcherControllersRef = useRef3(/* @__PURE__ */ new Map());
931
+ useEffect2(() => {
910
932
  return () => {
911
933
  for (const controller of watcherControllersRef.current.values()) {
912
934
  controller.abort();
@@ -914,7 +936,7 @@ function useTicketActions(options) {
914
936
  watcherControllersRef.current.clear();
915
937
  };
916
938
  }, []);
917
- const queueRef = useRef2(Promise.resolve());
939
+ const queueRef = useRef3(Promise.resolve());
918
940
  const enqueue = useCallback3((work) => {
919
941
  const next = queueRef.current.then(work, work);
920
942
  queueRef.current = next.catch(() => void 0);
@@ -982,7 +1004,7 @@ function useTicketActions(options) {
982
1004
  },
983
1005
  [queryClient, removeOptimistic, toast2]
984
1006
  );
985
- const lastUpdateErrorRef = useRef2(null);
1007
+ const lastUpdateErrorRef = useRef3(null);
986
1008
  const surfaceError = useCallback3(
987
1009
  (err, action) => {
988
1010
  const mapped = mapTicketActionError(err);
@@ -1044,6 +1066,7 @@ function useTicketActions(options) {
1044
1066
  await queryClient.invalidateQueries({ queryKey: ["tickets"] });
1045
1067
  removeOptimistic(placeholderId);
1046
1068
  }
1069
+ notifyTicketCreated?.();
1047
1070
  return true;
1048
1071
  });
1049
1072
  } catch (err) {
@@ -1063,6 +1086,7 @@ function useTicketActions(options) {
1063
1086
  queryClient,
1064
1087
  toast2,
1065
1088
  watchMirrorSync,
1089
+ notifyTicketCreated,
1066
1090
  surfaceError
1067
1091
  ]
1068
1092
  );
@@ -1454,7 +1478,7 @@ import { useQueryClient as useQueryClient3 } from "@tanstack/react-query";
1454
1478
  init_unified_pagination();
1455
1479
 
1456
1480
  // src/components/tickets/help-center-card.tsx
1457
- import { useCallback as useCallback5, useEffect as useEffect2, useRef as useRef3 } from "react";
1481
+ import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef4 } from "react";
1458
1482
  import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1459
1483
  function HelpCenterCard({
1460
1484
  ticket,
@@ -1479,11 +1503,11 @@ function HelpCenterCard({
1479
1503
  const description = ticket.preview ?? ticket.body ?? "";
1480
1504
  const isExpandable = !optimistic;
1481
1505
  const isExpanded = expanded && isExpandable;
1482
- const rowRef = useRef3(null);
1506
+ const rowRef = useRef4(null);
1483
1507
  const handleClick = useCallback5(() => {
1484
1508
  onToggle(ticket.id);
1485
1509
  }, [onToggle, ticket.id]);
1486
- useEffect2(() => {
1510
+ useEffect3(() => {
1487
1511
  if (!isExpanded) return;
1488
1512
  const raf = requestAnimationFrame(() => {
1489
1513
  scrollElementIntoView(rowRef.current, {
@@ -1492,7 +1516,18 @@ function HelpCenterCard({
1492
1516
  });
1493
1517
  return () => cancelAnimationFrame(raf);
1494
1518
  }, [isExpanded]);
1519
+ const live = useOptionalTicketLive();
1520
+ const unreadCount = !optimistic && ticket.external_id && live?.unreadByTicket[ticket.external_id] || 0;
1495
1521
  const rightBadges = /* @__PURE__ */ jsxs6(Fragment, { children: [
1522
+ unreadCount > 0 && /* @__PURE__ */ jsx7(
1523
+ StatusBadge,
1524
+ {
1525
+ text: `${unreadCount} NEW`,
1526
+ colorScheme: "warning",
1527
+ variant: "card",
1528
+ className: "border border-ods-border"
1529
+ }
1530
+ ),
1496
1531
  /* @__PURE__ */ jsx7(
1497
1532
  StatusBadge,
1498
1533
  {
@@ -1768,12 +1803,12 @@ function HelpCenterListAuthed({
1768
1803
  customerEmail: sessionEmail,
1769
1804
  search,
1770
1805
  status,
1771
- page,
1772
- // Live status: while a drawer is open, poll so an out-of-band HubSpot
1773
- // status change (e.g. agent closes the ticket) flips the badge +
1774
- // open/reopen affordance within one interval. Idle (no drawer) → no poll.
1775
- // `ticketParam` (the open ticket's external_id) is the open signal.
1776
- refetchInterval: ticketParam ? TICKET_LIVE_POLL_MS : false
1806
+ page
1807
+ // No interval polling (deleted 2026-08): `TicketLiveProvider`
1808
+ // invalidates `['tickets']` on stream events; focus/mount refetch
1809
+ // covers hosts without a stream. Disclosed trade-off: a bare
1810
+ // status/pipeline change with no accompanying reply has no live
1811
+ // path until the next event/focus/reconnect.
1777
1812
  });
1778
1813
  const expandedTicketId = ticketParam && tickets.find((t) => t.external_id === ticketParam)?.id || null;
1779
1814
  const prependOptimistic = useCallback6((placeholder) => {
@@ -1913,4 +1948,4 @@ export {
1913
1948
  HelpCenterCreateForm,
1914
1949
  HelpCenterList
1915
1950
  };
1916
- //# sourceMappingURL=chunk-HR6F6IP4.js.map
1951
+ //# sourceMappingURL=chunk-DIKJLAMY.js.map