@helpway/react 0.15.3 → 0.17.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.d.ts CHANGED
@@ -67,6 +67,12 @@ interface HelpwayWidgetProps {
67
67
  * Only used when `placement="docked"`.
68
68
  */
69
69
  dockSuggestions?: readonly DockSuggestion[];
70
+ /**
71
+ * Render your own agent avatar (e.g. an animated mascot) wherever the
72
+ * widget shows the AI agent. Wins over the dashboard avatar image; an
73
+ * assigned human's photo still wins over it.
74
+ */
75
+ agentAvatar?: ReactNode;
70
76
  /**
71
77
  * CSS selector for a custom trigger element (e.g. `"#support-btn"`).
72
78
  * Clicking the matched element calls `Helpway.open()`. Combine with
@@ -103,7 +109,7 @@ type HelpwayPublicAPI = HelpwayMethods;
103
109
  * `layout.tsx`, or `main.tsx`). Unmounting cleanly tears down the
104
110
  * widget and its WebSocket connection — useful for route-scoped mounts.
105
111
  */
106
- declare function HelpwayWidget({ apiKey, apiUrl, locale, initialConversationId, deepLinkToken, onReady, hideLauncher, placement, colorScheme, dockSuggestions, customLauncherSelector, onOpen, onClose, onUnreadChange, theme, src, }: HelpwayWidgetProps): react_jsx_runtime.JSX.Element;
112
+ declare function HelpwayWidget({ apiKey, apiUrl, locale, initialConversationId, deepLinkToken, onReady, hideLauncher, placement, colorScheme, dockSuggestions, agentAvatar, customLauncherSelector, onOpen, onClose, onUnreadChange, theme, src, }: HelpwayWidgetProps): react_jsx_runtime.JSX.Element;
107
113
 
108
114
  interface IdentifyData {
109
115
  externalId: string;
@@ -111,6 +117,13 @@ interface IdentifyData {
111
117
  name?: string;
112
118
  image?: string;
113
119
  metadata?: Record<string, unknown>;
120
+ /**
121
+ * Move this browser's visitor to the contact above even if it already
122
+ * belongs to a different contact. Dangerous: it merges whatever history
123
+ * this browser has into that contact. Off by default; without it the
124
+ * server keeps the existing link and returns that contact (#193).
125
+ */
126
+ reassign?: boolean;
114
127
  }
115
128
  /** Use a slice of the widget store with auto re-render */
116
129
  declare function useWidgetStore<T>(selector: (state: WidgetStore) => T): T;
@@ -174,6 +187,13 @@ declare function useWidget(): {
174
187
  name?: string;
175
188
  image?: string;
176
189
  metadata?: Record<string, unknown>;
190
+ /**
191
+ * Move this browser's visitor to the contact above even if it already
192
+ * belongs to a different contact. Dangerous: it merges whatever history
193
+ * this browser has into that contact. Off by default; without it the
194
+ * server keeps the existing link and returns that contact (#193).
195
+ */
196
+ reassign?: boolean;
177
197
  }) => Promise<any>;
178
198
  };
179
199
 
@@ -261,6 +281,30 @@ declare function useUnread(): {
261
281
  totalUnread: number;
262
282
  };
263
283
 
284
+ /**
285
+ * How many conversations are waiting on the visitor to reply.
286
+ *
287
+ * Exists because `useUnread()` answers a question consumers usually do not have.
288
+ * A thread we answered two minutes ago and a thread the visitor closed
289
+ * themselves look identical in the widget — same row, same weight, no marker —
290
+ * and that is the moment a support thread dies: we reply, the visitor never
291
+ * registers it, the conversation is abandoned with an unanswered message in it.
292
+ *
293
+ * Counts human replies, not AI ones. An auto-reply follows nearly every visitor
294
+ * message, so including them leaves the indicator permanently lit for anyone who
295
+ * has ever opened the widget, which teaches people to ignore it.
296
+ *
297
+ * Written by hand in a downstream dashboard before it existed here; a
298
+ * `hideLauncher` integration badging its own trigger should not have to
299
+ * reimplement the rule.
300
+ *
301
+ * ```tsx
302
+ * const awaiting = useAwaitingReply();
303
+ * // "3 awaiting reply" — label it, do not just show the number
304
+ * ```
305
+ */
306
+ declare function useAwaitingReply(): number;
307
+
264
308
  /**
265
309
  * Subscribe to raw WebSocket events.
266
310
  * For advanced usage — most apps should use useTimeline/usePresence instead.
@@ -271,19 +315,28 @@ declare function useUnread(): {
271
315
  * if (event.type === 'timelineItemCreated') { ... }
272
316
  * })
273
317
  * ```
318
+ *
319
+ * The subscription lives as long as the socket instance, not as long as the
320
+ * handler's identity (#146). Callers pass inline arrows, which are new on every
321
+ * render; with `handler` in the effect deps that meant `handlers.delete` and
322
+ * `handlers.add` on every render above the caller, and any event that arrived
323
+ * between the two was dropped. The latest handler is kept in a ref and one
324
+ * stable wrapper is subscribed per socket.
274
325
  */
275
326
  declare function useRealtime(handler: (event: RealtimeEvent) => void): void;
276
327
 
328
+ declare const AgentAvatarProvider: react.Provider<ReactNode>;
277
329
  /**
278
330
  * WidgetLogo — chat-header avatar. Renders WHO is talking to the
279
331
  * visitor right now. Resolution chain:
280
332
  * 1. Active conversation's assigned support user (assigneeName +
281
333
  * assigneeImage from the widget API). When a human takes over a
282
334
  * conversation the visitor sees that human, not the AI agent.
283
- * 2. Agent uploaded image (agentConfig.avatarUrl)
284
- * 3. Agent icon preset (avatarPreset + brandColor)
285
- * 4. Website logo (website.logoUrl)
286
- * 5. Helpway brand mark (octagonal) as the true last-resort fallback
335
+ * 2. Host-rendered avatar (`agentAvatar` prop, via AgentAvatarContext)
336
+ * 3. Agent uploaded image (agentConfig.avatarUrl)
337
+ * 4. Agent icon preset (avatarPreset + brandColor)
338
+ * 5. Website logo (website.logoUrl)
339
+ * 6. Helpway brand mark (octagonal) as the true last-resort fallback
287
340
  *
288
341
  * The `forceAgent` escape hatch skips the assignee lookup — used by
289
342
  * surfaces that mean "the agent" specifically (welcome card, conversation
@@ -474,6 +527,19 @@ interface AnnouncementPreviewsProps {
474
527
  * so its visual stays byte-identical to the original.
475
528
  */
476
529
  footer?: ReactNode;
530
+ /**
531
+ * How many cards to render before collapsing the rest into a single
532
+ * "+N more updates" row.
533
+ *
534
+ * Unlimited by default, which is what every existing consumer already gets.
535
+ * The launcher passes a real number because the strip above it is shared with
536
+ * the incoming-reply card and the two together ran off the top of the screen:
537
+ * four cards need more than 600px of viewport, and the topmost ones were
538
+ * simply gone. Clipping is a priority statement, not a size fix — a reply is a
539
+ * conversation waiting on the visitor, an announcement is content that can
540
+ * wait, so the announcements are what gets collapsed.
541
+ */
542
+ maxVisible?: number;
477
543
  }
478
544
  /**
479
545
  * `<AnnouncementPreviews>` — proactive "new content" cards shown when
@@ -490,7 +556,7 @@ interface AnnouncementPreviewsProps {
490
556
  *
491
557
  * Must be rendered inside `<SupportProvider>`.
492
558
  */
493
- declare function AnnouncementPreviews({ onOpen, avatar, placement, footer, }: AnnouncementPreviewsProps): react_jsx_runtime.JSX.Element | null;
559
+ declare function AnnouncementPreviews({ onOpen, avatar, placement, footer, maxVisible, }: AnnouncementPreviewsProps): react_jsx_runtime.JSX.Element | null;
494
560
 
495
561
  /**
496
562
  * Lightweight Markdown → HTML renderer.
@@ -520,4 +586,4 @@ declare function MarkdownContent({ bodyHtml, bodyMarkdown, className, }: {
520
586
  className?: string;
521
587
  }): react_jsx_runtime.JSX.Element | null;
522
588
 
523
- export { type AnnouncementPreviewEntry, AnnouncementPreviews, type AnnouncementPreviewsPlacement, type AnnouncementPreviewsProps, Composer, DefaultWidget, type HelpwayPublicAPI, HelpwayWidget, type HelpwayWidgetProps, type IdentifyData, MarkdownContent, MessageBubble, MessageList, MessagePreview, type MessagePreviewPlacement, type MessagePreviewProps, SupportProvider, WidgetLogo, linkifyText, renderMarkdown, useComposer, useConversations, useIdentify, usePresence, useRealtime, useTimeline, useUnread, useWidget, useWidgetStore };
589
+ export { AgentAvatarProvider, type AnnouncementPreviewEntry, AnnouncementPreviews, type AnnouncementPreviewsPlacement, type AnnouncementPreviewsProps, Composer, DefaultWidget, type HelpwayPublicAPI, HelpwayWidget, type HelpwayWidgetProps, type IdentifyData, MarkdownContent, MessageBubble, MessageList, MessagePreview, type MessagePreviewPlacement, type MessagePreviewProps, SupportProvider, WidgetLogo, linkifyText, renderMarkdown, useAwaitingReply, useComposer, useConversations, useIdentify, usePresence, useRealtime, useTimeline, useUnread, useWidget, useWidgetStore };