@djangocfg/ui-tools 2.1.381 → 2.1.382

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 (183) hide show
  1. package/README.md +132 -899
  2. package/dist/ChatRoot-6IZFM5HM.mjs +5 -0
  3. package/dist/{ChatRoot-EJC5Y2YM.cjs.map → ChatRoot-6IZFM5HM.mjs.map} +1 -1
  4. package/dist/ChatRoot-LW4XNIKP.cjs +14 -0
  5. package/dist/{ChatRoot-QOSKJPM6.mjs.map → ChatRoot-LW4XNIKP.cjs.map} +1 -1
  6. package/dist/DictationField-2ZLQWLYV.mjs +4 -0
  7. package/dist/DictationField-2ZLQWLYV.mjs.map +1 -0
  8. package/dist/DictationField-IPPJ54CU.cjs +13 -0
  9. package/dist/DictationField-IPPJ54CU.cjs.map +1 -0
  10. package/dist/{DocsLayout-2YKPXZYO.mjs → DocsLayout-2P3ONDWJ.mjs} +3 -3
  11. package/dist/{DocsLayout-2YKPXZYO.mjs.map → DocsLayout-2P3ONDWJ.mjs.map} +1 -1
  12. package/dist/{DocsLayout-Q4KS3QWW.cjs → DocsLayout-2YZNS5VK.cjs} +8 -8
  13. package/dist/{DocsLayout-Q4KS3QWW.cjs.map → DocsLayout-2YZNS5VK.cjs.map} +1 -1
  14. package/dist/chunk-4LXG3NBV.mjs +833 -0
  15. package/dist/chunk-4LXG3NBV.mjs.map +1 -0
  16. package/dist/{chunk-XACCHZH2.cjs → chunk-FIRK5CEH.cjs} +42 -4
  17. package/dist/chunk-FIRK5CEH.cjs.map +1 -0
  18. package/dist/{chunk-NWUT327A.mjs → chunk-HIK6BPL7.mjs} +38 -5
  19. package/dist/chunk-HIK6BPL7.mjs.map +1 -0
  20. package/dist/chunk-KMSBGNVC.cjs +835 -0
  21. package/dist/chunk-KMSBGNVC.cjs.map +1 -0
  22. package/dist/chunk-OZAU3QWD.cjs +2493 -0
  23. package/dist/chunk-OZAU3QWD.cjs.map +1 -0
  24. package/dist/chunk-UWVP6LCW.mjs +2447 -0
  25. package/dist/chunk-UWVP6LCW.mjs.map +1 -0
  26. package/dist/index.cjs +1532 -100
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +1148 -107
  29. package/dist/index.d.ts +1148 -107
  30. package/dist/index.mjs +1421 -51
  31. package/dist/index.mjs.map +1 -1
  32. package/package.json +16 -8
  33. package/src/audio-assets.d.ts +8 -0
  34. package/src/components/markdown/MarkdownMessage/CollapseToggle.tsx +3 -1
  35. package/src/components/markdown/MarkdownMessage/components.tsx +2 -5
  36. package/src/stories/index.ts +32 -2
  37. package/src/tools/Chat/README.md +347 -530
  38. package/src/tools/Chat/components/Attachments.tsx +6 -1
  39. package/src/tools/Chat/components/ChatRoot.tsx +30 -2
  40. package/src/tools/Chat/components/Composer.tsx +20 -3
  41. package/src/tools/Chat/components/ErrorBanner.tsx +7 -3
  42. package/src/tools/Chat/components/MessageActions.tsx +3 -1
  43. package/src/tools/Chat/components/MessageBubble.tsx +6 -5
  44. package/src/tools/Chat/components/MessageList.tsx +87 -1
  45. package/src/tools/Chat/components/ToolCalls.tsx +21 -3
  46. package/src/tools/Chat/context/ChatProvider.tsx +21 -3
  47. package/src/tools/Chat/core/audio/audioBus.ts +10 -163
  48. package/src/tools/Chat/core/audio/defaults.ts +43 -0
  49. package/src/tools/Chat/core/audio/index.ts +1 -0
  50. package/src/tools/Chat/core/audio/preferences.ts +5 -59
  51. package/src/tools/Chat/core/audio/sounds/error.mp3 +0 -0
  52. package/src/tools/Chat/core/audio/sounds/mention.mp3 +0 -0
  53. package/src/tools/Chat/core/audio/sounds/notification.mp3 +0 -0
  54. package/src/tools/Chat/core/audio/sounds/received.mp3 +0 -0
  55. package/src/tools/Chat/core/audio/sounds/sent.mp3 +0 -0
  56. package/src/tools/Chat/core/audio/sounds/start.mp3 +0 -0
  57. package/src/tools/Chat/core/audio/types.ts +28 -0
  58. package/src/tools/Chat/core/reducer.ts +33 -0
  59. package/src/tools/Chat/core/transport/index.ts +13 -0
  60. package/src/tools/Chat/core/transport/mappers/index.ts +6 -0
  61. package/src/tools/Chat/core/transport/mappers/pydantic-ai.ts +142 -0
  62. package/src/tools/Chat/core/transport/pydantic-ai-transport.ts +208 -0
  63. package/src/tools/Chat/core/transport/sse.ts +18 -5
  64. package/src/tools/Chat/hooks/index.ts +25 -0
  65. package/src/tools/Chat/hooks/useAutoFocusOnStreamEnd.ts +5 -3
  66. package/src/tools/Chat/hooks/useChat.ts +28 -0
  67. package/src/tools/Chat/hooks/useChatAudio.ts +59 -180
  68. package/src/tools/Chat/hooks/useChatDockPrefs.ts +74 -0
  69. package/src/tools/Chat/hooks/useChatReset.ts +70 -0
  70. package/src/tools/Chat/hooks/useChatUnread.ts +87 -0
  71. package/src/tools/Chat/hooks/useFocusOnEmptyClick.ts +111 -0
  72. package/src/tools/Chat/hooks/useVisitorFingerprint.ts +48 -0
  73. package/src/tools/Chat/index.ts +69 -1
  74. package/src/tools/Chat/launcher/ChatDock.tsx +263 -0
  75. package/src/tools/Chat/launcher/ChatFAB.tsx +349 -0
  76. package/src/tools/Chat/launcher/ChatGreeting.tsx +200 -0
  77. package/src/tools/Chat/launcher/ChatHeader.tsx +76 -0
  78. package/src/tools/Chat/launcher/ChatHeaderActionButton.tsx +87 -0
  79. package/src/tools/Chat/launcher/ChatHeaderAudioToggle.tsx +47 -0
  80. package/src/tools/Chat/launcher/ChatHeaderLanguageButton.tsx +179 -0
  81. package/src/tools/Chat/launcher/ChatHeaderModeToggle.tsx +57 -0
  82. package/src/tools/Chat/launcher/ChatHeaderResetButton.tsx +93 -0
  83. package/src/tools/Chat/launcher/ChatLauncher.tsx +321 -0
  84. package/src/tools/Chat/launcher/ChatUnreadPreview.tsx +197 -0
  85. package/src/tools/Chat/launcher/index.ts +46 -0
  86. package/src/tools/Chat/launcher/useChatPresence.ts +44 -0
  87. package/src/tools/Chat/stories/01-basic.story.tsx +64 -0
  88. package/src/tools/Chat/stories/02-bubbles.story.tsx +21 -0
  89. package/src/tools/Chat/stories/03-tool-calls.story.tsx +59 -0
  90. package/src/tools/Chat/stories/04-personas.story.tsx +78 -0
  91. package/src/tools/Chat/stories/05-launcher.story.tsx +321 -0
  92. package/src/tools/Chat/stories/06-header.story.tsx +147 -0
  93. package/src/tools/Chat/stories/07-audio-actions.story.tsx +112 -0
  94. package/src/tools/Chat/stories/shared/Frame.tsx +21 -0
  95. package/src/tools/Chat/stories/shared/index.ts +5 -0
  96. package/src/tools/Chat/stories/shared/messages.ts +39 -0
  97. package/src/tools/Chat/stories/shared/personas.ts +13 -0
  98. package/src/tools/Chat/stories/shared/seeds.ts +92 -0
  99. package/src/tools/Chat/stories/shared/transports.ts +36 -0
  100. package/src/tools/Chat/styles/bubbleTokens.ts +71 -0
  101. package/src/tools/Chat/styles/index.ts +16 -0
  102. package/src/tools/Chat/styles/useChatStyles.ts +101 -0
  103. package/src/tools/Chat/types/attachment.ts +25 -0
  104. package/src/tools/Chat/types/config.ts +48 -0
  105. package/src/tools/Chat/types/events.ts +35 -0
  106. package/src/tools/Chat/types/index.ts +34 -0
  107. package/src/tools/Chat/types/labels.ts +38 -0
  108. package/src/tools/Chat/types/message.ts +32 -0
  109. package/src/tools/Chat/types/persona.ts +31 -0
  110. package/src/tools/Chat/types/session.ts +43 -0
  111. package/src/tools/Chat/types/tool-call.ts +17 -0
  112. package/src/tools/Chat/types/transport.ts +28 -0
  113. package/src/tools/Chat/types.ts +5 -240
  114. package/src/tools/MarkdownEditor/MarkdownEditor.tsx +50 -14
  115. package/src/tools/MarkdownEditor/index.ts +1 -1
  116. package/src/tools/SpeechRecognition/README.md +336 -0
  117. package/src/tools/SpeechRecognition/__tests__/ids.test.ts +15 -0
  118. package/src/tools/SpeechRecognition/__tests__/language.test.ts +59 -0
  119. package/src/tools/SpeechRecognition/__tests__/reducer.test.ts +71 -0
  120. package/src/tools/SpeechRecognition/__tests__/transcript.test.ts +52 -0
  121. package/src/tools/SpeechRecognition/components/DevicePicker.tsx +49 -0
  122. package/src/tools/SpeechRecognition/components/DictationButton.tsx +93 -0
  123. package/src/tools/SpeechRecognition/components/EngineBadge.tsx +30 -0
  124. package/src/tools/SpeechRecognition/components/ErrorBanner.tsx +52 -0
  125. package/src/tools/SpeechRecognition/components/LanguagePicker.tsx +63 -0
  126. package/src/tools/SpeechRecognition/components/MicMeter.tsx +63 -0
  127. package/src/tools/SpeechRecognition/components/PushToTalkHint.tsx +51 -0
  128. package/src/tools/SpeechRecognition/components/TranscriptView.tsx +55 -0
  129. package/src/tools/SpeechRecognition/components/index.ts +16 -0
  130. package/src/tools/SpeechRecognition/context/SpeechRecognitionProvider.tsx +47 -0
  131. package/src/tools/SpeechRecognition/context/index.ts +6 -0
  132. package/src/tools/SpeechRecognition/core/audio/defaults.ts +24 -0
  133. package/src/tools/SpeechRecognition/core/engine/external.ts +222 -0
  134. package/src/tools/SpeechRecognition/core/engine/http.ts +147 -0
  135. package/src/tools/SpeechRecognition/core/engine/index.ts +52 -0
  136. package/src/tools/SpeechRecognition/core/engine/mediarecorder.ts +105 -0
  137. package/src/tools/SpeechRecognition/core/engine/websocket.ts +211 -0
  138. package/src/tools/SpeechRecognition/core/engine/webspeech.ts +188 -0
  139. package/src/tools/SpeechRecognition/core/ids.ts +11 -0
  140. package/src/tools/SpeechRecognition/core/index.ts +14 -0
  141. package/src/tools/SpeechRecognition/core/language.ts +78 -0
  142. package/src/tools/SpeechRecognition/core/languages-catalog.ts +229 -0
  143. package/src/tools/SpeechRecognition/core/logger.ts +3 -0
  144. package/src/tools/SpeechRecognition/core/reducer.ts +105 -0
  145. package/src/tools/SpeechRecognition/core/transcript.ts +36 -0
  146. package/src/tools/SpeechRecognition/hooks/index.ts +14 -0
  147. package/src/tools/SpeechRecognition/hooks/useDictation.ts +59 -0
  148. package/src/tools/SpeechRecognition/hooks/useEnginePrefs.ts +15 -0
  149. package/src/tools/SpeechRecognition/hooks/useMicDevices.ts +57 -0
  150. package/src/tools/SpeechRecognition/hooks/useMicLevel.ts +52 -0
  151. package/src/tools/SpeechRecognition/hooks/usePushToTalk.ts +85 -0
  152. package/src/tools/SpeechRecognition/hooks/useResolvedLanguage.ts +28 -0
  153. package/src/tools/SpeechRecognition/hooks/useSpeechLanguageInfo.ts +108 -0
  154. package/src/tools/SpeechRecognition/hooks/useSpeechRecognition.ts +188 -0
  155. package/src/tools/SpeechRecognition/hooks/useVoiceSupport.ts +78 -0
  156. package/src/tools/SpeechRecognition/index.ts +82 -0
  157. package/src/tools/SpeechRecognition/lazy.tsx +19 -0
  158. package/src/tools/SpeechRecognition/store/index.ts +2 -0
  159. package/src/tools/SpeechRecognition/store/prefsStore.ts +54 -0
  160. package/src/tools/SpeechRecognition/stories/01-basic.story.tsx +32 -0
  161. package/src/tools/SpeechRecognition/stories/02-dictation-field.story.tsx +32 -0
  162. package/src/tools/SpeechRecognition/stories/03-push-to-talk.story.tsx +27 -0
  163. package/src/tools/SpeechRecognition/stories/04-mic-meter.story.tsx +35 -0
  164. package/src/tools/SpeechRecognition/stories/05-custom-engine-http.story.tsx +40 -0
  165. package/src/tools/SpeechRecognition/stories/06-custom-engine-ws.story.tsx +48 -0
  166. package/src/tools/SpeechRecognition/stories/07-language-device.story.tsx +57 -0
  167. package/src/tools/SpeechRecognition/stories/08-errors-permissions.story.tsx +25 -0
  168. package/src/tools/SpeechRecognition/stories/09-chat-voice.story.tsx +90 -0
  169. package/src/tools/SpeechRecognition/stories/shared.tsx +123 -0
  170. package/src/tools/SpeechRecognition/types.ts +133 -0
  171. package/src/tools/SpeechRecognition/widgets/DictationField.tsx +105 -0
  172. package/src/tools/SpeechRecognition/widgets/VoiceComposerSlot.tsx +305 -0
  173. package/src/tools/SpeechRecognition/widgets/VoiceMessageRecorder.tsx +88 -0
  174. package/src/tools/SpeechRecognition/widgets/index.ts +6 -0
  175. package/dist/ChatRoot-EJC5Y2YM.cjs +0 -14
  176. package/dist/ChatRoot-QOSKJPM6.mjs +0 -5
  177. package/dist/chunk-NWUT327A.mjs.map +0 -1
  178. package/dist/chunk-QLMKCSR6.mjs +0 -2420
  179. package/dist/chunk-QLMKCSR6.mjs.map +0 -1
  180. package/dist/chunk-SI5RD2GD.cjs +0 -2460
  181. package/dist/chunk-SI5RD2GD.cjs.map +0 -1
  182. package/dist/chunk-XACCHZH2.cjs.map +0 -1
  183. package/src/tools/Chat/Chat.story.tsx +0 -1457
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import react__default, { ReactNode, ComponentType, RefObject, ChangeEvent, KeyboardEvent, ClipboardEvent } from 'react';
3
+ import react__default, { ReactNode, ComponentType, RefObject, ChangeEvent, KeyboardEvent, ClipboardEvent, CSSProperties, ButtonHTMLAttributes, MouseEvent } from 'react';
4
4
  import { Components } from 'react-markdown';
5
5
  import { ViewState } from 'react-map-gl/maplibre';
6
6
  import { Language } from 'prism-react-renderer';
@@ -13,12 +13,14 @@ export { CustomJsonSchema7, CustomJsonSchema7Type, CustomJsonUiDisabledWhenRule,
13
13
  import { CommonExternalProps } from 'react-json-tree';
14
14
  import { b as TreeRootProps } from './types-CevSbyfD.js';
15
15
  export { c as DEFAULT_TREE_APPEARANCE, D as DEFAULT_TREE_LABELS, F as FlatRow, R as ResolvedAppearance, m as TreeAccentIntensity, k as TreeAppearance, e as TreeContextMenuSlot, l as TreeDensity, f as TreeItemId, g as TreeLabels, j as TreeLoadChildren, T as TreeNode, n as TreeRadius, i as TreeRowRenderProps, a as TreeRowSlot, h as TreeSelectionMode, d as appearanceToStyle, r as resolveAppearance } from './types-CevSbyfD.js';
16
- import * as zustand_middleware from 'zustand/middleware';
17
16
  import * as zustand from 'zustand';
17
+ import { AudioPrefsState } from '@djangocfg/ui-core/hooks';
18
18
  import { ConsolaInstance } from 'consola';
19
19
  import { MediaPlayerInstance } from '@vidstack/react';
20
20
  import * as monaco from 'monaco-editor';
21
+ import { Editor as Editor$1 } from '@tiptap/react';
21
22
  export { ChildCache, ChildEntry, ChildEntryStatus, DemoNode, FlattenInput, PersistedTreeState, TreeRoot as Tree, TreeChevron, TreeChevronProps, TreeContent, TreeContentProps, TreeContextValue, TreeEmpty, TreeEmptyProps, TreeError, TreeErrorProps, TreeIcon, TreeIconProps, TreeIndentGuides, TreeIndentGuidesProps, TreeLabel, TreeLabelProps, TreeProvider, TreeProviderProps, TreeRoot, TreeRow, TreeRowProps, TreeSearchInput, TreeSearchInputProps, TreeSkeleton, TreeSkeletonProps, UseTreeKeyboardOptions, UseTreeTypeAheadOptions, clearTreeState, createChildCache, createDemoTree, flattenTree, loadTreeState, resolveChildren, saveTreeState, useTreeActions, useTreeContext, useTreeExpansion, useTreeFocus, useTreeKeyboard, useTreeLabels, useTreeRows, useTreeSearch, useTreeSelection, useTreeTypeAhead } from './tree/index.js';
23
+ import * as zustand_middleware from 'zustand/middleware';
22
24
 
23
25
  interface LoadingFallbackProps {
24
26
  /** Minimum height of the loading container */
@@ -1418,12 +1420,36 @@ declare const LazyCronScheduler: react.ComponentType<CronSchedulerProps>;
1418
1420
  declare const LazyTree: react.ComponentType<TreeRootProps<unknown>>;
1419
1421
 
1420
1422
  /**
1421
- * Public types for the Chat tool.
1423
+ * Persona display identity attached to messages and config.
1422
1424
  *
1423
- * Shapes here are the contract between transport adapters, the reducer,
1424
- * the hooks layer and the components. Keep serializable (no Date, no Map).
1425
+ * Used by `ChatMessage.sender`, `ChatConfig.user`, `ChatConfig.assistant`.
1425
1426
  */
1426
1427
  type ChatRole = 'user' | 'assistant' | 'system';
1428
+ interface ChatPersona {
1429
+ /** Display name. */
1430
+ name?: string;
1431
+ /** Avatar image URL. */
1432
+ avatarUrl?: string;
1433
+ /** Initials fallback when no avatar. Auto-derived from `name` if absent. */
1434
+ initials?: string;
1435
+ /** Tooltip / aria description. */
1436
+ description?: string;
1437
+ }
1438
+ interface ChatUserContext extends ChatPersona {
1439
+ email?: string;
1440
+ language?: string;
1441
+ role?: string;
1442
+ /** Free-form custom data forwarded to transport metadata. */
1443
+ custom?: Record<string, unknown>;
1444
+ }
1445
+ interface ChatAssistantContext extends ChatPersona {
1446
+ /** Model identifier (gpt-4o, claude-opus, …). */
1447
+ model?: string;
1448
+ }
1449
+
1450
+ /**
1451
+ * Tool calls — assistant-initiated function/tool invocations during a turn.
1452
+ */
1427
1453
  interface ChatToolCall {
1428
1454
  id: string;
1429
1455
  name: string;
@@ -1437,6 +1463,10 @@ interface ChatToolCall {
1437
1463
  /** Optional grouping label for parallel/fan-out execution. */
1438
1464
  sourceHostname?: string;
1439
1465
  }
1466
+
1467
+ /**
1468
+ * Attachments + sources attached to a chat message.
1469
+ */
1440
1470
  interface ChatAttachment {
1441
1471
  id: string;
1442
1472
  type: 'image' | 'file' | 'audio' | 'video';
@@ -1457,16 +1487,14 @@ interface ChatSource {
1457
1487
  snippet?: string;
1458
1488
  chunkIndex?: number;
1459
1489
  }
1460
- interface ChatPersona {
1461
- /** Display name. */
1462
- name?: string;
1463
- /** Avatar image URL. */
1464
- avatarUrl?: string;
1465
- /** Initials fallback when no avatar. Auto-derived from `name` if absent. */
1466
- initials?: string;
1467
- /** Tooltip / aria description. */
1468
- description?: string;
1469
- }
1490
+
1491
+ /**
1492
+ * The atomic unit — a single message in a chat session.
1493
+ *
1494
+ * Composed of role + content + optional rich-data slots (attachments,
1495
+ * sources, tool calls). Serializable: no Date, no Map.
1496
+ */
1497
+
1470
1498
  interface ChatMessage {
1471
1499
  id: string;
1472
1500
  role: ChatRole;
@@ -1488,18 +1516,34 @@ interface ChatMessage {
1488
1516
  tokensIn?: number;
1489
1517
  tokensOut?: number;
1490
1518
  }
1491
- type ChatDisplayMode = 'closed' | 'embedded' | 'floating' | 'sidebar' | 'fullscreen';
1492
- interface ChatUserContext extends ChatPersona {
1493
- email?: string;
1494
- language?: string;
1495
- role?: string;
1496
- /** Free-form custom data forwarded to transport metadata. */
1497
- custom?: Record<string, unknown>;
1498
- }
1499
- interface ChatAssistantContext extends ChatPersona {
1500
- /** Model identifier (gpt-4o, claude-opus, …). */
1501
- model?: string;
1519
+
1520
+ /**
1521
+ * UI label strings — i18n is the host's job. Pass overrides via
1522
+ * `ChatConfig.labels` and merge with `DEFAULT_LABELS`.
1523
+ */
1524
+ interface ChatLabels {
1525
+ send: string;
1526
+ cancel: string;
1527
+ copy: string;
1528
+ regenerate: string;
1529
+ edit: string;
1530
+ delete: string;
1531
+ retry: string;
1532
+ newChat: string;
1533
+ loadMore: string;
1534
+ jumpToLatest: string;
1535
+ attach: string;
1536
+ voice: string;
1537
+ errorGeneric: string;
1538
+ cancelledSuffix: string;
1502
1539
  }
1540
+ declare const DEFAULT_LABELS: ChatLabels;
1541
+
1542
+ /**
1543
+ * Top-level chat configuration — placeholder, suggestions, identities, prefs.
1544
+ */
1545
+
1546
+ type ChatDisplayMode = 'closed' | 'embedded' | 'floating' | 'sidebar' | 'fullscreen';
1503
1547
  interface ChatPrefs {
1504
1548
  /** Submit hotkey for the composer. */
1505
1549
  submitOn?: 'enter' | 'cmd+enter';
@@ -1541,55 +1585,14 @@ interface ChatConfig {
1541
1585
  /** Visual labels (i18n is the host's job). */
1542
1586
  labels?: Partial<ChatLabels>;
1543
1587
  }
1544
- interface ChatLabels {
1545
- send: string;
1546
- cancel: string;
1547
- copy: string;
1548
- regenerate: string;
1549
- edit: string;
1550
- delete: string;
1551
- retry: string;
1552
- newChat: string;
1553
- loadMore: string;
1554
- jumpToLatest: string;
1555
- attach: string;
1556
- voice: string;
1557
- errorGeneric: string;
1558
- cancelledSuffix: string;
1559
- }
1560
- declare const DEFAULT_LABELS: ChatLabels;
1561
- interface CreateSessionOptions {
1562
- metadata?: Record<string, unknown>;
1563
- }
1564
- interface SessionInfo {
1565
- sessionId: string;
1566
- /** If the server resumed an existing session, it may return prior messages. */
1567
- messages?: ChatMessage[];
1568
- hasMore?: boolean;
1569
- cursor?: string | null;
1570
- resumed?: boolean;
1571
- /**
1572
- * Optional human-readable title (typically derived from the first
1573
- * user message). Hosts that render a session-list sidebar can read
1574
- * this directly instead of crawling messages. Plan64.
1575
- */
1576
- title?: string;
1577
- }
1578
- interface HistoryPage {
1579
- messages: ChatMessage[];
1580
- hasMore: boolean;
1581
- nextCursor: string | null;
1582
- }
1583
- interface StreamOptions {
1584
- signal: AbortSignal;
1585
- attachments?: ChatAttachment[];
1586
- metadata?: Record<string, unknown>;
1587
- }
1588
- interface SendOptions {
1589
- signal?: AbortSignal;
1590
- attachments?: ChatAttachment[];
1591
- metadata?: Record<string, unknown>;
1592
- }
1588
+
1589
+ /**
1590
+ * SSE stream events — the canonical wire shape consumed by the reducer.
1591
+ *
1592
+ * Backend-specific shapes (e.g. pydantic-AI's `text_delta`) get normalized
1593
+ * into this union by `mapPydanticAIEvent` and friends.
1594
+ */
1595
+
1593
1596
  type ChatStreamEvent = {
1594
1597
  type: 'message_start';
1595
1598
  messageId: string;
@@ -1628,6 +1631,51 @@ type ChatStreamEvent = {
1628
1631
  code: string;
1629
1632
  message: string;
1630
1633
  };
1634
+
1635
+ /**
1636
+ * Session info + history page shapes returned by transports.
1637
+ */
1638
+
1639
+ interface CreateSessionOptions {
1640
+ metadata?: Record<string, unknown>;
1641
+ }
1642
+ interface SessionInfo {
1643
+ sessionId: string;
1644
+ /** If the server resumed an existing session, it may return prior messages. */
1645
+ messages?: ChatMessage[];
1646
+ hasMore?: boolean;
1647
+ cursor?: string | null;
1648
+ resumed?: boolean;
1649
+ /**
1650
+ * Optional human-readable title (typically derived from the first
1651
+ * user message). Hosts that render a session-list sidebar can read
1652
+ * this directly instead of crawling messages. Plan64.
1653
+ */
1654
+ title?: string;
1655
+ }
1656
+ interface HistoryPage {
1657
+ messages: ChatMessage[];
1658
+ hasMore: boolean;
1659
+ nextCursor: string | null;
1660
+ }
1661
+ interface StreamOptions {
1662
+ signal: AbortSignal;
1663
+ attachments?: ChatAttachment[];
1664
+ metadata?: Record<string, unknown>;
1665
+ }
1666
+ interface SendOptions {
1667
+ signal?: AbortSignal;
1668
+ attachments?: ChatAttachment[];
1669
+ metadata?: Record<string, unknown>;
1670
+ }
1671
+
1672
+ /**
1673
+ * Transport interface — what every chat backend adapter implements.
1674
+ *
1675
+ * Default web implementation lives in `core/transport/http.ts`.
1676
+ * Pydantic-AI adapter lives in `core/transport/pydantic-ai-transport.ts`.
1677
+ */
1678
+
1631
1679
  interface ChatTransport {
1632
1680
  createSession(opts?: CreateSessionOptions): Promise<SessionInfo>;
1633
1681
  loadHistory(sessionId: string, cursor?: string | null, limit?: number): Promise<HistoryPage>;
@@ -1644,6 +1692,19 @@ interface ChatAudioConfig {
1644
1692
  sounds?: ChatAudioSounds;
1645
1693
  /** Master volume 0..1. Persisted via the global prefs store. */
1646
1694
  volume?: number;
1695
+ /**
1696
+ * Per-event volume multipliers (0..1). Applied on top of `volume`.
1697
+ * Defaults applied by `useChatAudio` if not provided:
1698
+ * - error: 0.25 (gentle — error UI is the loud signal, not the sound)
1699
+ * - mention: 1.0 (louder than baseline received)
1700
+ * - messageSent: 0.5 (subtle self-confirmation)
1701
+ * - messageReceived: 0.7
1702
+ * - streamStart: 0.3 (very subtle, fires often)
1703
+ * - notification: 0.9
1704
+ *
1705
+ * Pass `{}` to disable defaults; pass overrides to tweak.
1706
+ */
1707
+ eventVolumes?: Partial<Record<ChatAudioEvent, number>>;
1647
1708
  /** Master mute. */
1648
1709
  muted?: boolean;
1649
1710
  /** Custom predicate — return `false` to suppress a play call. */
@@ -1654,6 +1715,17 @@ interface ChatAudioConfig {
1654
1715
  respectReducedData?: boolean;
1655
1716
  /** Mute when host page is hidden (`visibilityState === 'hidden'`). Default: true. */
1656
1717
  muteWhenHidden?: boolean;
1718
+ /**
1719
+ * Skip web playback entirely — `play()` becomes a no-op. Pair with
1720
+ * `onSoundEvent` for native hosts (cmdop_go / Tauri) that play sounds
1721
+ * outside the browser.
1722
+ */
1723
+ silenced?: boolean;
1724
+ /**
1725
+ * Side-channel fired whenever `play(event)` is called. Stays active
1726
+ * even when `silenced=true`. Use to bridge into a native audio backend.
1727
+ */
1728
+ onSoundEvent?: (event: ChatAudioEvent) => void;
1657
1729
  }
1658
1730
  interface UseChatAudioReturn {
1659
1731
  /** Play a sound for an event. No-ops if the event has no URL or is muted. */
@@ -1667,12 +1739,16 @@ interface UseChatAudioReturn {
1667
1739
  /** Master mute (persistent). */
1668
1740
  muted: boolean;
1669
1741
  setMuted: (m: boolean) => void;
1742
+ /** Flip mute state — convenience. */
1743
+ toggleMute: () => void;
1670
1744
  /** Master volume 0..1 (persistent). */
1671
1745
  volume: number;
1672
1746
  setVolume: (v: number) => void;
1673
1747
  /** Per-event opt-out (persistent). */
1674
1748
  isEventEnabled: (event: ChatAudioEvent) => boolean;
1675
1749
  setEventEnabled: (event: ChatAudioEvent, enabled: boolean) => void;
1750
+ /** True when no sounds are configured (or `silenced`). */
1751
+ isSilent: boolean;
1676
1752
  }
1677
1753
 
1678
1754
  /**
@@ -1774,6 +1850,14 @@ type ChatAction = {
1774
1850
  } | {
1775
1851
  type: 'MESSAGE_DELETE';
1776
1852
  id: string;
1853
+ } | {
1854
+ type: 'MESSAGE_INJECT';
1855
+ message: ChatMessage;
1856
+ position?: 'append' | 'prepend';
1857
+ } | {
1858
+ type: 'MESSAGE_PATCH';
1859
+ id: string;
1860
+ patch: Partial<ChatMessage>;
1777
1861
  } | {
1778
1862
  type: 'MESSAGES_CLEAR';
1779
1863
  } | {
@@ -1831,6 +1915,18 @@ interface UseChatReturn extends ChatState {
1831
1915
  loadMore: () => Promise<void>;
1832
1916
  newSession: () => Promise<void>;
1833
1917
  lastError: Error | null;
1918
+ /**
1919
+ * Inject a complete message from outside (push notification, admin
1920
+ * takeover, system notice). De-duped by id. Position defaults to
1921
+ * `append` — pass `prepend` for retroactive inserts.
1922
+ */
1923
+ injectMessage: (message: ChatMessage, position?: 'append' | 'prepend') => void;
1924
+ /**
1925
+ * Patch fields of an existing message in place (e.g. live-edit the
1926
+ * admin's last reply, mark a message as resolved). No-op if the id
1927
+ * doesn't exist.
1928
+ */
1929
+ updateMessage: (id: string, patch: Partial<ChatMessage>) => void;
1834
1930
  }
1835
1931
  declare function useChat(config: UseChatConfig): UseChatReturn;
1836
1932
 
@@ -1859,11 +1955,29 @@ interface UseChatLayoutReturn {
1859
1955
  }
1860
1956
  declare function useChatLayout(config?: UseChatLayoutConfig): UseChatLayoutReturn;
1861
1957
 
1862
- /** Minimal handle a composer (built-in or custom) registers so other
1863
- * parts of the chat tree can drive it imperatively `.focus()` is
1864
- * enough today; expand the surface as new needs arise. */
1958
+ /** Imperative handle a composer (built-in or custom) registers so
1959
+ * other parts of the chat tree can drive it without prop-drilling a
1960
+ * ref. `focus()` is the baseline; the rest is optional so non-textarea
1961
+ * hosts can keep returning `{ focus }` only.
1962
+ *
1963
+ * Implemented by:
1964
+ * - built-in `<Composer>` — backed by `useChatComposer.textareaRef`.
1965
+ * - `@djangocfg/ui-tools/markdown-editor` — backed by the TipTap
1966
+ * editor (`editor.commands.focus('end')`).
1967
+ * Consumed by `VoiceComposerSlot` for the focus / move-caret behaviour
1968
+ * during live dictation.
1969
+ */
1865
1970
  interface ComposerHandle {
1866
1971
  focus: () => void;
1972
+ /** Move the caret to the very end of the input. */
1973
+ moveCursorToEnd?: () => void;
1974
+ /** Read the current draft text. Needed by voice dictation to anchor
1975
+ * partial transcripts onto the user's already-typed prefix. */
1976
+ getValue?: () => string;
1977
+ /** Replace the current draft text. Voice dictation uses this to push
1978
+ * interim + final transcripts into the composer without owning a
1979
+ * controlled binding. */
1980
+ setValue?: (value: string) => void;
1867
1981
  }
1868
1982
  interface ChatContextValue extends UseChatReturn {
1869
1983
  layout: UseChatLayoutReturn;
@@ -2126,6 +2240,12 @@ interface ChatRootProps {
2126
2240
  listClassName?: string;
2127
2241
  /** Extra className forwarded to the `<Composer>` wrapper div. */
2128
2242
  composerClassName?: string;
2243
+ /**
2244
+ * Click in the message area → focus the composer (Slack / ChatGPT / Linear).
2245
+ * Honours selection drag, interactive elements, and touch input.
2246
+ * @default true
2247
+ */
2248
+ focusOnEmptyClick?: boolean;
2129
2249
  }
2130
2250
  declare function ChatRoot(props: ChatRootProps): react_jsx_runtime.JSX.Element;
2131
2251
 
@@ -2259,9 +2379,10 @@ interface RawEvent {
2259
2379
  }
2260
2380
  interface ParseSSEOptions {
2261
2381
  signal?: AbortSignal;
2262
- /** Map a raw SSE event to a ChatStreamEvent. Default: parse `data` as JSON
2263
- * and assume the JSON shape already matches `ChatStreamEvent`. */
2264
- map?: (raw: RawEvent) => ChatStreamEvent | null;
2382
+ /** Map a raw SSE event to zero, one, or many `ChatStreamEvent`s.
2383
+ * Default: parse `data` as JSON and assume the JSON shape already
2384
+ * matches `ChatStreamEvent`. */
2385
+ map?: (raw: RawEvent) => ChatStreamEvent | ChatStreamEvent[] | null;
2265
2386
  idleTimeoutMs?: number;
2266
2387
  }
2267
2388
  declare function parseSSE(response: Response, options?: ParseSSEOptions): AsyncGenerator<ChatStreamEvent, void, void>;
@@ -2276,6 +2397,643 @@ declare class TransportError extends Error {
2276
2397
  constructor(message: string, code?: string);
2277
2398
  }
2278
2399
 
2400
+ /**
2401
+ * Pydantic-AI SSE event mapper.
2402
+ *
2403
+ * Translates the event shape emitted by pydantic-AI–style Django backends
2404
+ * (text_delta / tool_call / tool_result / done / error / approval_required)
2405
+ * into the canonical `ChatStreamEvent` stream consumed by the Chat reducer.
2406
+ *
2407
+ * Backends that don't expose a stable `tool_call_id` are supported via a
2408
+ * per-stream FIFO queue keyed by tool name. The earlier "Map<name, toolId>"
2409
+ * approach lost the first toolId when a tool was invoked twice in one turn
2410
+ * (e.g. `list_tasks` for search and again for confirmation) — using a queue
2411
+ * keeps each call/result pair correctly matched.
2412
+ */
2413
+
2414
+ interface PydanticAIEvent {
2415
+ type: 'text_delta' | 'tool_call' | 'tool_result' | 'done' | 'error' | 'approval_required';
2416
+ delta?: string;
2417
+ tool?: string;
2418
+ args?: unknown;
2419
+ result?: unknown;
2420
+ /**
2421
+ * Structured frontend payload — present on `tool_result` when the tool has
2422
+ * a `result_schema`. The LLM sees only `result` (compact text); the
2423
+ * frontend uses `data` to render rich UI (e.g. vehicle cards).
2424
+ */
2425
+ data?: unknown;
2426
+ total_tokens?: number;
2427
+ error?: string;
2428
+ tool_call_id?: string;
2429
+ session_id?: string;
2430
+ }
2431
+ /** Per-stream FIFO queue keyed by tool name. Created via `createToolIdQueue`. */
2432
+ interface ToolIdQueue {
2433
+ /** Allocate a new toolId for a `tool_call` event and enqueue it under `name`. */
2434
+ push(name: string): string;
2435
+ /** Pop the oldest toolId for `name` (or return an orphan marker if none). */
2436
+ shift(name: string): string;
2437
+ /** Reset all queues (e.g. on stream close). */
2438
+ clear(): void;
2439
+ }
2440
+ declare function createToolIdQueue(): ToolIdQueue;
2441
+ /**
2442
+ * Translate a single pydantic-AI event into zero or more `ChatStreamEvent`s.
2443
+ * Pass a `ToolIdQueue` shared across the lifetime of one stream so that
2444
+ * `tool_call` / `tool_result` pairs match correctly.
2445
+ */
2446
+ declare function mapPydanticAIEvent(ev: PydanticAIEvent, toolIds: ToolIdQueue): Generator<ChatStreamEvent>;
2447
+ /**
2448
+ * Convenience factory: returns a `ParseSSEOptions['map']` callback that
2449
+ * decodes raw SSE frames as `PydanticAIEvent` JSON and yields zero or
2450
+ * more `ChatStreamEvent`s through `mapPydanticAIEvent`.
2451
+ *
2452
+ * Allocates an internal `ToolIdQueue` — call this once per stream.
2453
+ */
2454
+ declare function createPydanticAISSEMap(): NonNullable<ParseSSEOptions['map']>;
2455
+
2456
+ /**
2457
+ * High-level transport factory for pydantic-AI–style backends.
2458
+ *
2459
+ * Composes:
2460
+ * - `parseSSE` for spec-compliant SSE framing (multi-line `data:`, comments, idle timeout).
2461
+ * - `createPydanticAISSEMap` for normalizing pydantic-AI events into `ChatStreamEvent`.
2462
+ *
2463
+ * Use when your backend speaks the canonical pydantic-AI stream shape
2464
+ * (`text_delta` / `tool_call` / `tool_result` / `done` / `error`).
2465
+ * URL building, auth headers, history loading, and optional session
2466
+ * bootstrapping are caller responsibilities — pass them in.
2467
+ */
2468
+
2469
+ interface PydanticAIChatTransportOpts {
2470
+ /**
2471
+ * Build the SSE stream URL for a user message turn.
2472
+ * @example (sessionId, message) => `${base}/stream?session_id=${sessionId}&message=${encodeURIComponent(message)}`
2473
+ */
2474
+ buildStreamUrl: (sessionId: string, message: string) => string | URL;
2475
+ /** Optional history loader. If omitted, `loadHistory` returns an empty page. */
2476
+ loadHistory?: (sessionId: string, cursor?: string | null) => Promise<HistoryPage>;
2477
+ /**
2478
+ * Optional session bootstrap. Called from `createSession`. Useful for
2479
+ * backends that need a `POST /sessions` round-trip or want to pre-seed
2480
+ * history.
2481
+ */
2482
+ bootstrapSession?: (opts?: CreateSessionOptions) => Promise<SessionInfo>;
2483
+ /** Optional session teardown. */
2484
+ closeSession?: (sessionId: string) => Promise<void>;
2485
+ /**
2486
+ * Optional non-streaming send (for hosts that need a buffered fallback,
2487
+ * e.g. when the user disables streaming). Defaults to throwing — most
2488
+ * hosts only use streaming.
2489
+ */
2490
+ send?: (sessionId: string, content: string, options?: SendOptions) => Promise<ChatMessage>;
2491
+ /** Request headers (Authorization, content-type, etc.). */
2492
+ buildHeaders?: () => HeadersInit | Promise<HeadersInit>;
2493
+ /** Override fetch (tests, retry layers). */
2494
+ fetchImpl?: typeof fetch;
2495
+ /**
2496
+ * HTTP method for the stream request. Defaults to `'POST'` with
2497
+ * `{ content, attachments, metadata }` JSON body. Set to `'GET'` if
2498
+ * your backend embeds the message in the URL via `buildStreamUrl`.
2499
+ */
2500
+ streamMethod?: 'GET' | 'POST';
2501
+ /** Idle timeout for the SSE connection, in ms. Forwarded to `parseSSE`. */
2502
+ idleTimeoutMs?: number;
2503
+ /**
2504
+ * Side-channel for events that don't translate to `ChatStreamEvent`
2505
+ * (e.g. `approval_required` — surfaces interactive prompts outside the
2506
+ * normal message stream). Called synchronously while parsing the SSE
2507
+ * frame; mutate caller-owned state, don't `await` long work here.
2508
+ */
2509
+ onPydanticEvent?: (event: PydanticAIEvent) => void;
2510
+ }
2511
+ declare function createPydanticAIChatTransport(opts: PydanticAIChatTransportOpts): ChatTransport;
2512
+
2513
+ type ChatFABPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
2514
+ type ChatFABVariant = 'simple' | 'animated' | 'glass';
2515
+ type ChatFABSize = 'sm' | 'md' | 'lg' | 'responsive';
2516
+ interface ChatFABProps {
2517
+ /** Click handler — typically toggles a `ChatDock`. */
2518
+ onClick: () => void;
2519
+ /** Accessible label. */
2520
+ ariaLabel?: string;
2521
+ /** Icon inside the FAB. Defaults to a bot glyph. */
2522
+ icon?: ReactNode;
2523
+ /** Visual style. @default 'simple' */
2524
+ variant?: ChatFABVariant;
2525
+ /** Button size. @default 'md' */
2526
+ size?: ChatFABSize;
2527
+ /** Fixed-screen position. @default 'bottom-right' */
2528
+ position?: ChatFABPosition;
2529
+ /** Pixel offset from screen edges. @default 24 */
2530
+ offset?: number;
2531
+ /** z-index for the button. @default 9999 */
2532
+ zIndex?: number;
2533
+ /** Show a small attention dot (unread / new). */
2534
+ pulse?: boolean;
2535
+ /**
2536
+ * Numeric badge — unread count. Numbers > 9 render as "9+".
2537
+ * Overrides `pulse` when both set.
2538
+ */
2539
+ badge?: number;
2540
+ /** Hover tooltip text. Shows next to the FAB on hover/focus. */
2541
+ tooltip?: string;
2542
+ /**
2543
+ * Render in-place (no fixed positioning) so the FAB sits inline in the
2544
+ * normal document flow. Useful for stories, screenshots, and previews
2545
+ * inside a contained playground panel. @default false
2546
+ */
2547
+ inline?: boolean;
2548
+ /** Override classes on the button itself. */
2549
+ className?: string;
2550
+ /** Extra style on the button (caller-controlled overrides). */
2551
+ style?: CSSProperties;
2552
+ }
2553
+ /**
2554
+ * Floating action button for opening a chat dock. Pure presentation — owns
2555
+ * no state. Wire it to whatever toggles your dock open.
2556
+ *
2557
+ * For the common "FAB + dock + hotkey" composition, use `<ChatLauncher>` —
2558
+ * this primitive is only useful when you need custom triggering.
2559
+ */
2560
+ declare function ChatFAB({ onClick, ariaLabel, icon, variant, size, position, offset, zIndex, pulse, badge, tooltip, inline, className, style, }: ChatFABProps): react_jsx_runtime.JSX.Element;
2561
+
2562
+ type ChatDockMode = 'popover' | 'side';
2563
+ type ChatDockSide = 'left' | 'right';
2564
+ interface ChatDockProps {
2565
+ /** Controlled open state. */
2566
+ open: boolean;
2567
+ /** Called when the user clicks the close button. */
2568
+ onClose: () => void;
2569
+ /** Dock contents (typically a `<Chat>` component). */
2570
+ children: ReactNode;
2571
+ /**
2572
+ * Visual mode.
2573
+ * - `popover` (default): floating card anchored to a corner, fixed size, FAB-style.
2574
+ * - `side`: docked panel pinned to the left/right edge, full viewport height.
2575
+ */
2576
+ mode?: ChatDockMode;
2577
+ /** Side for `mode='side'`. @default 'right' */
2578
+ side?: ChatDockSide;
2579
+ /** Header title text. */
2580
+ title?: ReactNode;
2581
+ /** Header icon. Defaults to a bot glyph. */
2582
+ icon?: ReactNode;
2583
+ /**
2584
+ * Header actions slot (right side, before the close button).
2585
+ * Use `ChatHeaderActionButton` to keep visual consistency.
2586
+ */
2587
+ headerActions?: ReactNode;
2588
+ /** Hide the header entirely (you render your own inside `children`). */
2589
+ hideHeader?: boolean;
2590
+ /** ARIA label for the close button. @default 'Close' */
2591
+ closeLabel?: string;
2592
+ /** Dock width in px. Clamped to viewport. @default 480 (popover) / 420 (side) */
2593
+ width?: number;
2594
+ /** Dock height in px. Only used in `popover` mode. @default 720 */
2595
+ height?: number;
2596
+ /** Which screen corner to dock to in `popover` mode. @default 'bottom-right' */
2597
+ position?: ChatFABPosition;
2598
+ /** Offset from screen edges in px (popover only). @default 24 / 96 */
2599
+ offset?: {
2600
+ horizontal?: number;
2601
+ vertical?: number;
2602
+ };
2603
+ /** Transition duration in ms — should match CSS animation. @default 200 */
2604
+ exitDurationMs?: number;
2605
+ /** z-index. @default 10000 */
2606
+ zIndex?: number;
2607
+ /** Accessible dialog label. */
2608
+ ariaLabel?: string;
2609
+ /** Extra classes on the dock container. */
2610
+ className?: string;
2611
+ /**
2612
+ * Take over the full viewport on mobile (< 768px). Applies to both modes.
2613
+ * @default true
2614
+ */
2615
+ mobileFullscreen?: boolean;
2616
+ /**
2617
+ * Render in-place (not in `document.body` via a portal). Useful for stories,
2618
+ * screenshots, or wrapping the dock inside a custom container. @default false
2619
+ */
2620
+ disablePortal?: boolean;
2621
+ /**
2622
+ * Drop fixed positioning entirely — the dock renders as a normal flow
2623
+ * element sized by `width`/`height`. Combine with `disablePortal` for
2624
+ * stories/previews where the dock should sit inside the panel instead
2625
+ * of attaching to the viewport. @default false
2626
+ */
2627
+ inline?: boolean;
2628
+ /**
2629
+ * In `mode='side'`, reserve space on the document body so page content
2630
+ * isn't covered by the dock. Sets `padding-{side}` on `<body>` while
2631
+ * the dock is open and exposes the width via the `--chat-dock-reserve`
2632
+ * CSS variable for custom layouts. @default true (when mode='side')
2633
+ */
2634
+ reserveBodySpace?: boolean;
2635
+ }
2636
+ /**
2637
+ * Fixed-position chat surface. Two modes:
2638
+ *
2639
+ * - `popover` — floating card anchored to a corner. Companion to `<ChatFAB>`.
2640
+ * - `side` — full-height panel pinned to the left/right edge. App-shell style.
2641
+ *
2642
+ * Renders only when `open` is true (plus the leave-transition tail). Uses
2643
+ * `useChatPresence` for the four-phase mount/animate/unmount cycle.
2644
+ */
2645
+ declare function ChatDock({ open, onClose, children, mode, side, title, icon, headerActions, hideHeader, closeLabel, width, height, position, offset, exitDurationMs, zIndex, ariaLabel, className, mobileFullscreen, disablePortal, inline, reserveBodySpace, }: ChatDockProps): react_jsx_runtime.JSX.Element;
2646
+
2647
+ interface ChatHeaderProps {
2648
+ /** Window title text. */
2649
+ title?: ReactNode;
2650
+ /** Icon next to the title. Defaults to a bot glyph. */
2651
+ icon?: ReactNode;
2652
+ /**
2653
+ * Action slot — appears to the right of the title, before the close button.
2654
+ * Use for reset / settings / minimize / etc. Compose with `ChatHeaderActionButton`.
2655
+ */
2656
+ actions?: ReactNode;
2657
+ /** Show the close (×) button. @default true */
2658
+ showClose?: boolean;
2659
+ /** Close click handler. */
2660
+ onClose?: () => void;
2661
+ /** ARIA label for the close button. @default 'Close' */
2662
+ closeLabel?: string;
2663
+ /** Replace the close button entirely (rare — most hosts want the default). */
2664
+ closeSlot?: ReactNode;
2665
+ /** Extra classes on the `<header>` element. */
2666
+ className?: string;
2667
+ }
2668
+ /**
2669
+ * Standalone chat header — title + icon + action slot + close button.
2670
+ *
2671
+ * Used by `<ChatDock>` automatically, but can be rendered standalone when
2672
+ * the host owns the chat container (e.g. embedded inline in a page).
2673
+ */
2674
+ declare function ChatHeader({ title, icon, actions, showClose, onClose, closeLabel, closeSlot, className, }: ChatHeaderProps): react_jsx_runtime.JSX.Element;
2675
+
2676
+ interface ChatHeaderActionButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
2677
+ /** Icon (required). */
2678
+ icon: ReactNode;
2679
+ /** Accessible label + native tooltip. */
2680
+ ariaLabel: string;
2681
+ /** Optional unread / status badge — small number on top-right. */
2682
+ badge?: number;
2683
+ /** Mark as destructive — uses destructive hover tokens. */
2684
+ destructive?: boolean;
2685
+ /** Optional visual loading state (e.g. while reset is in flight). */
2686
+ loading?: boolean;
2687
+ }
2688
+ /**
2689
+ * Compact icon button for the chat header actions slot.
2690
+ *
2691
+ * Standard chrome: 28×28 ghost button, hover bg-accent, focus ring, optional
2692
+ * destructive variant, optional numeric badge for unread / pending.
2693
+ *
2694
+ * @example
2695
+ * ```tsx
2696
+ * <ChatHeader
2697
+ * title="Assistant"
2698
+ * onClose={close}
2699
+ * actions={
2700
+ * <>
2701
+ * <ChatHeaderActionButton
2702
+ * icon={<RotateCcw className="h-3.5 w-3.5" />}
2703
+ * ariaLabel="Clear context"
2704
+ * onClick={handleReset}
2705
+ * loading={isResetting}
2706
+ * />
2707
+ * <ChatHeaderActionButton
2708
+ * icon={<Settings className="h-3.5 w-3.5" />}
2709
+ * ariaLabel="Settings"
2710
+ * onClick={openSettings}
2711
+ * />
2712
+ * </>
2713
+ * }
2714
+ * />
2715
+ * ```
2716
+ */
2717
+ declare const ChatHeaderActionButton: react.ForwardRefExoticComponent<ChatHeaderActionButtonProps & react.RefAttributes<HTMLButtonElement>>;
2718
+
2719
+ interface ChatHeaderModeToggleProps {
2720
+ /** Current dock mode. */
2721
+ mode: ChatDockMode;
2722
+ /** Toggle handler. Wire to `useChatDockPrefs().toggleMode`. */
2723
+ onToggle: () => void;
2724
+ /** Override aria/tooltip label for popover→side. */
2725
+ expandLabel?: string;
2726
+ /** Override aria/tooltip label for side→popover. */
2727
+ collapseLabel?: string;
2728
+ /**
2729
+ * Always render — useful for stories. By default the toggle hides itself on
2730
+ * viewports below `lg` (1024px) since side mode falls back to popover there.
2731
+ */
2732
+ forceVisible?: boolean;
2733
+ }
2734
+ /**
2735
+ * "Dock to side" / "back to popover" toggle.
2736
+ *
2737
+ * Side mode is desktop-only — on viewports below `lg` (1024px) `<ChatDock>`
2738
+ * silently falls back to popover anyway, so the toggle has nothing to do
2739
+ * and auto-hides. Pass `forceVisible` to override (e.g. in stories).
2740
+ */
2741
+ declare function ChatHeaderModeToggle({ mode, onToggle, expandLabel, collapseLabel, forceVisible, }: ChatHeaderModeToggleProps): react_jsx_runtime.JSX.Element;
2742
+
2743
+ interface ChatHeaderAudioToggleProps {
2744
+ /** Current muted state. */
2745
+ muted: boolean;
2746
+ /** Toggle handler. Wire to `useChatAudio().setMuted` or `toggleMute`. */
2747
+ onToggle: () => void;
2748
+ /** Override tooltip label for muted → unmuted. */
2749
+ unmuteLabel?: string;
2750
+ /** Override tooltip label for unmuted → muted. */
2751
+ muteLabel?: string;
2752
+ }
2753
+ /**
2754
+ * Mute / unmute notification sounds. Drop into a `<ChatHeader>` actions
2755
+ * slot or into `<ChatDock headerActions>`.
2756
+ *
2757
+ * @example
2758
+ * ```tsx
2759
+ * const audio = useChatAudio({ sounds: {...} });
2760
+ * <ChatHeaderAudioToggle muted={audio.muted} onToggle={() => audio.setMuted(!audio.muted)} />
2761
+ * ```
2762
+ */
2763
+ declare function ChatHeaderAudioToggle({ muted, onToggle, unmuteLabel, muteLabel, }: ChatHeaderAudioToggleProps): react_jsx_runtime.JSX.Element;
2764
+
2765
+ interface ChatHeaderResetButtonProps {
2766
+ /**
2767
+ * Backend reset call. Should resolve to `true` on success.
2768
+ * Plugged into `useChatReset` for in-flight state.
2769
+ */
2770
+ onReset: () => Promise<boolean>;
2771
+ /** Called after a successful reset (e.g. clear local messages, refetch). */
2772
+ onSuccess?: () => void;
2773
+ /** Called when reset fails (returned `false` or threw). */
2774
+ onError?: (error?: unknown) => void;
2775
+ /**
2776
+ * Show a `window.dialog.confirm` before calling `onReset`. @default true
2777
+ *
2778
+ * Requires the host to mount `<DialogProvider>` from `@djangocfg/ui-core`
2779
+ * — it installs the `window.dialog` API used here.
2780
+ */
2781
+ confirm?: boolean;
2782
+ /** Confirm dialog title. */
2783
+ confirmTitle?: string;
2784
+ /** Confirm dialog message. */
2785
+ confirmMessage?: string;
2786
+ /** Override tooltip / aria label. */
2787
+ ariaLabel?: string;
2788
+ }
2789
+ /**
2790
+ * Standard chat-reset action: prompts the user via `window.dialog.confirm`,
2791
+ * then runs the backend reset call through `useChatReset` so the button
2792
+ * spins while it's in flight.
2793
+ *
2794
+ * @example
2795
+ * ```tsx
2796
+ * <ChatHeaderResetButton
2797
+ * onReset={api.clearChat}
2798
+ * onSuccess={() => chat.clearMessages()}
2799
+ * />
2800
+ * ```
2801
+ */
2802
+ declare function ChatHeaderResetButton({ onReset, onSuccess, onError, confirm, confirmTitle, confirmMessage, ariaLabel, }: ChatHeaderResetButtonProps): react_jsx_runtime.JSX.Element;
2803
+
2804
+ interface ChatGreetingProps {
2805
+ /** Controlled visibility — usually `!chatOpen && !userDismissed`. */
2806
+ open: boolean;
2807
+ /** Greeting text. Pass a string for the default bubble, or any ReactNode. */
2808
+ children: ReactNode;
2809
+ /** Click handler — typically opens the chat. Bubble is clickable when set. */
2810
+ onClick?: () => void;
2811
+ /** Close (×) button handler — typically marks the greeting as dismissed. */
2812
+ onDismiss?: () => void;
2813
+ /** Anchor relative to a FAB on the same side. @default 'bottom-right' */
2814
+ position?: ChatFABPosition;
2815
+ /**
2816
+ * Horizontal pixel offset matching the FAB's `offset` prop, so the greeting
2817
+ * lines up under the FAB. @default 24
2818
+ */
2819
+ fabOffset?: number;
2820
+ /**
2821
+ * Vertical pixel offset above/below the FAB centerline. @default 96
2822
+ * (room for an `md` FAB plus a small gap).
2823
+ */
2824
+ fabClearance?: number;
2825
+ /** Delay before the greeting appears, in ms. @default 1500 */
2826
+ delayMs?: number;
2827
+ /** z-index. @default 9998 (just below the default FAB at 9999). */
2828
+ zIndex?: number;
2829
+ /** Override classes on the bubble. */
2830
+ className?: string;
2831
+ /** Override styles on the bubble. */
2832
+ style?: CSSProperties;
2833
+ /** Optional sender avatar / icon shown on the left. */
2834
+ avatar?: ReactNode;
2835
+ /** Optional sender label rendered above the text. */
2836
+ senderName?: string;
2837
+ /** ARIA label for the dismiss button. @default 'Dismiss' */
2838
+ dismissLabel?: string;
2839
+ /**
2840
+ * Render in-place (no fixed positioning). Useful for stories and inline previews.
2841
+ * @default false
2842
+ */
2843
+ inline?: boolean;
2844
+ }
2845
+ /**
2846
+ * Greeting bubble shown next to a `ChatFAB` to invite the user to start a
2847
+ * conversation (LiveChat / Intercom-style proactive prompt).
2848
+ *
2849
+ * Renders fixed-position, anchored to the same corner as the FAB. Owns its
2850
+ * own delayed-mount + presence animation. Hide on chat open and/or after
2851
+ * user dismissal.
2852
+ *
2853
+ * @example
2854
+ * ```tsx
2855
+ * const [open, setOpen] = useState(false);
2856
+ * const [dismissed, setDismissed] = useState(false);
2857
+ *
2858
+ * <ChatLauncher
2859
+ * open={open}
2860
+ * onOpenChange={setOpen}
2861
+ * fab={{ variant: 'animated' }}
2862
+ * dock={{ title: 'Support' }}
2863
+ * >
2864
+ * <SupportChat />
2865
+ * </ChatLauncher>
2866
+ *
2867
+ * <ChatGreeting
2868
+ * open={!open && !dismissed}
2869
+ * onClick={() => setOpen(true)}
2870
+ * onDismiss={() => setDismissed(true)}
2871
+ * senderName="Anna from Support"
2872
+ * delayMs={2000}
2873
+ * >
2874
+ * Hi! 👋 Got a question? I'm here to help.
2875
+ * </ChatGreeting>
2876
+ * ```
2877
+ */
2878
+ declare function ChatGreeting({ open, children, onClick, onDismiss, position, fabOffset, fabClearance, delayMs, zIndex, className, style, avatar, senderName, dismissLabel, inline, }: ChatGreetingProps): react_jsx_runtime.JSX.Element;
2879
+
2880
+ interface ChatUnreadPreviewProps {
2881
+ /** Controlled — usually `!dockOpen && !!message`. */
2882
+ open: boolean;
2883
+ /** Inbound message to preview. `null` hides the bubble. */
2884
+ message: ChatMessage | null;
2885
+ /** Tap → open chat + mark read. */
2886
+ onClick?: () => void;
2887
+ /** × → mark read without opening. */
2888
+ onDismiss?: () => void;
2889
+ /** Anchor corner — match the FAB so the bubble sits above it. @default 'bottom-right' */
2890
+ position?: ChatFABPosition;
2891
+ /** Horizontal offset from screen edge, matches the FAB. @default 24 */
2892
+ fabOffset?: number;
2893
+ /** Vertical clearance above/below the FAB. @default 96 */
2894
+ fabClearance?: number;
2895
+ /** Lines of body text before ellipsis. @default 2 */
2896
+ truncate?: number;
2897
+ /** z-index. @default 9998 */
2898
+ zIndex?: number;
2899
+ /** Render in-place (stories / previews). @default false */
2900
+ inline?: boolean;
2901
+ /** Override classes on the bubble. */
2902
+ className?: string;
2903
+ /** Override styles on the bubble. */
2904
+ style?: CSSProperties;
2905
+ /** ARIA label for the dismiss button. @default 'Mark as read' */
2906
+ dismissLabel?: string;
2907
+ /** Override the avatar — defaults to derived from `message.sender`. */
2908
+ avatar?: ReactNode;
2909
+ /** Override the sender label — defaults to `message.sender?.name`. */
2910
+ senderName?: string;
2911
+ }
2912
+ /**
2913
+ * Push-notification bubble next to the chat FAB.
2914
+ *
2915
+ * Shows the last inbound message while the chat is closed —
2916
+ * Intercom / LiveChat-style. Tap → open chat (host wires `onClick`).
2917
+ * Dismiss × → keep chat closed but stop nagging.
2918
+ *
2919
+ * Pair with `useChatUnread()` (inside `<ChatProvider>`) for state.
2920
+ */
2921
+ declare function ChatUnreadPreview({ open, message, onClick, onDismiss, position, fabOffset, fabClearance, truncate, zIndex, inline, className, style, dismissLabel, avatar, senderName, }: ChatUnreadPreviewProps): react_jsx_runtime.JSX.Element;
2922
+
2923
+ interface ChatLauncherHotkey {
2924
+ /** Key (case-sensitive single char or named like 'Escape'). */
2925
+ key: string;
2926
+ /** Require Cmd (mac) or Ctrl (other). */
2927
+ meta?: boolean;
2928
+ /** Require Shift. */
2929
+ shift?: boolean;
2930
+ /** Require Alt. */
2931
+ alt?: boolean;
2932
+ }
2933
+ interface ChatLauncherGreeting extends Omit<ChatGreetingProps, 'open' | 'onClick' | 'onDismiss' | 'position' | 'fabOffset' | 'children'> {
2934
+ /** Greeting body — string for the default style, or any ReactNode. */
2935
+ content: ReactNode;
2936
+ /** Persistence key for "user dismissed this greeting" in `localStorage`. Pass `null` to disable persistence. @default null */
2937
+ dismissStorageKey?: string | null;
2938
+ /** Hide the greeting once the user opens the chat. @default true */
2939
+ hideOnOpen?: boolean;
2940
+ }
2941
+ interface ChatLauncherProps {
2942
+ /** Dock contents — typically a `<Chat>` instance. */
2943
+ children: ReactNode;
2944
+ /** FAB customization (icon, position, label, pulse, badge, tooltip, variant, size). */
2945
+ fab?: Omit<ChatFABProps, 'onClick'>;
2946
+ /** Dock customization (size, title, position, transition, mobileFullscreen). */
2947
+ dock?: Omit<ChatDockProps, 'open' | 'onClose' | 'children'>;
2948
+ /**
2949
+ * Proactive greeting bubble shown next to the FAB before the user opens the chat.
2950
+ * Set to a string or full config object. Omit to disable.
2951
+ */
2952
+ greeting?: string | ChatLauncherGreeting;
2953
+ /** Open/close via a keyboard shortcut. */
2954
+ hotkey?: ChatLauncherHotkey;
2955
+ /** Initial open state for uncontrolled mode. @default false */
2956
+ defaultOpen?: boolean;
2957
+ /** Controlled open state (pair with `onOpenChange`). */
2958
+ open?: boolean;
2959
+ /** Controlled open state setter. */
2960
+ onOpenChange?: (open: boolean) => void;
2961
+ /**
2962
+ * Focus the composer textarea when the dock opens. Saves a click for
2963
+ * every "FAB → start typing" interaction. @default true
2964
+ */
2965
+ autoFocusComposerOnOpen?: boolean;
2966
+ /**
2967
+ * Close the dock on `Escape`. Mirrors standard popover / drawer UX.
2968
+ * Set to `false` to disable (e.g. if you want Escape to do something
2969
+ * else inside the chat). @default true
2970
+ */
2971
+ closeOnEscape?: boolean;
2972
+ /**
2973
+ * Last inbound message (admin reply / system notice / agent push) the
2974
+ * user hasn't seen yet. Drives the `<ChatUnreadPreview>` bubble next
2975
+ * to the FAB and (by default) the FAB badge.
2976
+ *
2977
+ * Source it from `useChatUnread()` inside your `<ChatProvider>`.
2978
+ */
2979
+ unreadMessage?: ChatMessage | null;
2980
+ /**
2981
+ * Called when the user opens the chat via FAB/preview/hotkey or
2982
+ * dismisses the preview with ×. Wire to `useChatUnread().markRead`.
2983
+ */
2984
+ onMarkRead?: () => void;
2985
+ /**
2986
+ * Customize the unread bubble (`truncate`, `dismissLabel`, …).
2987
+ * `open`/`message`/`onClick`/`onDismiss`/`position`/`fabOffset` are
2988
+ * wired automatically.
2989
+ */
2990
+ unreadPreview?: Omit<ChatUnreadPreviewProps, 'open' | 'message' | 'onClick' | 'onDismiss' | 'position' | 'fabOffset'>;
2991
+ /**
2992
+ * Auto-inject a mute / unmute button into the header. Pass the
2993
+ * `useChatAudio()` (or any compatible `{ muted, toggleMute }`)
2994
+ * instance — the launcher renders `<ChatHeaderAudioToggle>` in the
2995
+ * header's actions slot when audio is actually configured (not silent).
2996
+ *
2997
+ * Hosts that manage their own header can ignore this prop and render
2998
+ * `<ChatHeaderAudioToggle>` directly.
2999
+ */
3000
+ audio?: {
3001
+ muted: boolean;
3002
+ toggleMute: () => void;
3003
+ isSilent?: boolean;
3004
+ } | null;
3005
+ /**
3006
+ * Suppress the auto-injected audio toggle even when `audio` is passed.
3007
+ * @default false
3008
+ */
3009
+ hideAudioToggle?: boolean;
3010
+ }
3011
+ /**
3012
+ * Floating chat launcher = FAB + Dock + presence + optional greeting + hotkey.
3013
+ *
3014
+ * 99% of hosts use this directly. For non-FAB triggers (e.g. an inline
3015
+ * link in the page) compose `<ChatDock>` with your own button.
3016
+ */
3017
+ declare function ChatLauncher({ children, fab, dock, greeting, hotkey, defaultOpen, open: controlledOpen, onOpenChange, autoFocusComposerOnOpen, closeOnEscape, unreadMessage, onMarkRead, unreadPreview, audio, hideAudioToggle, }: ChatLauncherProps): react_jsx_runtime.JSX.Element;
3018
+
3019
+ type ChatPresencePhase = 'hidden' | 'entering' | 'visible' | 'leaving';
3020
+ /**
3021
+ * Presence state machine for floating popovers.
3022
+ *
3023
+ * Drives a four-phase lifecycle so enter/leave CSS transitions actually fire:
3024
+ *
3025
+ * hidden → entering (mount, transition class starts) → visible
3026
+ * visible → leaving (transition runs) → hidden (unmount)
3027
+ *
3028
+ * Mounting in `entering` and ticking to `visible` on the next paint is what
3029
+ * lets transition classes animate. Without it the element appears already
3030
+ * at its final state and CSS transitions never observe a change.
3031
+ *
3032
+ * @param open - controlled open state
3033
+ * @param exitDurationMs - how long the leave transition runs; should match CSS
3034
+ */
3035
+ declare function useChatPresence(open: boolean, exitDurationMs?: number): ChatPresencePhase;
3036
+
2279
3037
  /**
2280
3038
  * @deprecated Plan64. As of ui-tools 2.1.369, `<MessageList>` is
2281
3039
  * virtualized via react-virtuoso and owns its own scroll viewport.
@@ -2319,6 +3077,11 @@ interface UseChatHistoryOptions {
2319
3077
  * bump scrollTop by the delta so the previously-visible message stays put. */
2320
3078
  declare function useChatHistory(options: UseChatHistoryOptions): void;
2321
3079
 
3080
+ /**
3081
+ * Chat-specific audio facade. Thin wrapper over `useNotificationSounds`
3082
+ * from `@djangocfg/ui-core` — keeps the `ChatAudioEvent` typing while
3083
+ * the underlying bus / prefs / Safari-unlock logic lives in ui-core.
3084
+ */
2322
3085
  declare function useChatAudio(config?: ChatAudioConfig): UseChatAudioReturn;
2323
3086
 
2324
3087
  interface ChatLightboxState {
@@ -2404,32 +3167,167 @@ declare function useAutoFocusOnStreamEnd(options?: UseAutoFocusOnStreamEndOption
2404
3167
  *
2405
3168
  * No-op when called outside a `<ChatProvider>`.
2406
3169
  */
2407
- declare function useRegisterComposer(focus: () => void): void;
3170
+ declare function useRegisterComposer(handle: ComposerHandle): void;
2408
3171
 
2409
- interface ChatAudioPrefsState {
2410
- /** 0..1 master volume. */
2411
- volume: number;
2412
- /** Master mute (overrides per-event toggles). */
2413
- muted: boolean;
2414
- /** Per-event opt-out — `false` silences a single trigger. */
2415
- enabled: Partial<Record<ChatAudioEvent, boolean>>;
2416
- setVolume: (v: number) => void;
2417
- setMuted: (m: boolean) => void;
2418
- setEventEnabled: (event: ChatAudioEvent, enabled: boolean) => void;
3172
+ interface UseChatResetOptions {
3173
+ /**
3174
+ * Backend call that performs the actual reset (e.g. POST /chat/reset).
3175
+ * Should resolve to `true` on success, `false` on failure.
3176
+ * Throwing also counts as failure — caught and logged.
3177
+ */
3178
+ onReset: () => Promise<boolean>;
3179
+ /**
3180
+ * Called after a successful reset (status === true). Use to clear the
3181
+ * local message list, navigate, or fire analytics.
3182
+ */
3183
+ onSuccess?: () => void;
3184
+ /**
3185
+ * Called when reset fails (returned `false` or threw). Defaults to no-op
3186
+ * — wire to a toast/banner if you want to surface it.
3187
+ */
3188
+ onError?: (error?: unknown) => void;
2419
3189
  }
2420
- declare const useChatAudioPrefs: zustand.UseBoundStore<Omit<zustand.StoreApi<ChatAudioPrefsState>, "setState" | "persist"> & {
2421
- setState(partial: ChatAudioPrefsState | Partial<ChatAudioPrefsState> | ((state: ChatAudioPrefsState) => ChatAudioPrefsState | Partial<ChatAudioPrefsState>), replace?: false): unknown;
2422
- setState(state: ChatAudioPrefsState | ((state: ChatAudioPrefsState) => ChatAudioPrefsState), replace: true): unknown;
2423
- persist: {
2424
- setOptions: (options: Partial<zustand_middleware.PersistOptions<ChatAudioPrefsState, unknown, unknown>>) => void;
2425
- clearStorage: () => void;
2426
- rehydrate: () => Promise<void> | void;
2427
- hasHydrated: () => boolean;
2428
- onHydrate: (fn: (state: ChatAudioPrefsState) => void) => () => void;
2429
- onFinishHydration: (fn: (state: ChatAudioPrefsState) => void) => () => void;
2430
- getOptions: () => Partial<zustand_middleware.PersistOptions<ChatAudioPrefsState, unknown, unknown>>;
2431
- };
2432
- }>;
3190
+ interface UseChatResetReturn {
3191
+ /** Trigger the reset. Safe to call multiple times re-entrant guard. */
3192
+ reset: () => Promise<boolean>;
3193
+ /** True while the reset is in flight. */
3194
+ isResetting: boolean;
3195
+ }
3196
+ /**
3197
+ * Generic "clear chat context" hook.
3198
+ *
3199
+ * Stays generic the backend call lives in the host (it knows the URL,
3200
+ * auth, project slug). Provides the in-flight state and success/error
3201
+ * callbacks every consumer wires up the same way.
3202
+ *
3203
+ * @example
3204
+ * ```tsx
3205
+ * const { reset, isResetting } = useChatReset({
3206
+ * onReset: async () => {
3207
+ * const res = await fetch('/api/chat/reset', { method: 'POST', credentials: 'include' });
3208
+ * return res.ok;
3209
+ * },
3210
+ * onSuccess: () => chat.clearMessages(),
3211
+ * });
3212
+ * ```
3213
+ */
3214
+ declare function useChatReset(opts: UseChatResetOptions): UseChatResetReturn;
3215
+
3216
+ interface UseVisitorFingerprintOptions {
3217
+ /** localStorage key. @default 'chat.visitor.fingerprint' */
3218
+ storageKey?: string;
3219
+ }
3220
+ /**
3221
+ * Persistent anonymous visitor id, kept in `localStorage`.
3222
+ *
3223
+ * Returns `null` on the first render (SSR-safe) and the stable id from
3224
+ * the second render onwards. Use as `fingerprint` for public chat
3225
+ * transports that need to dedupe sessions per visitor without auth.
3226
+ */
3227
+ declare function useVisitorFingerprint(opts?: UseVisitorFingerprintOptions): string | null;
3228
+
3229
+ interface ChatDockPrefs {
3230
+ /** Popover (FAB-style) or side-docked panel. */
3231
+ mode: ChatDockMode;
3232
+ /** Which edge the side dock attaches to. */
3233
+ side: ChatDockSide;
3234
+ /** Width in px when side-docked (resizable in the future). */
3235
+ sideWidth: number;
3236
+ }
3237
+ declare const DEFAULT_DOCK_PREFS: ChatDockPrefs;
3238
+ interface UseChatDockPrefsOptions {
3239
+ /** localStorage key. @default 'chat.dock.prefs' */
3240
+ storageKey?: string;
3241
+ /** Override the baseline defaults (per-product branding, etc.). */
3242
+ defaults?: Partial<ChatDockPrefs>;
3243
+ }
3244
+ interface UseChatDockPrefsReturn extends ChatDockPrefs {
3245
+ /** Merge-update — pass only the fields that changed. */
3246
+ setPrefs: (patch: Partial<ChatDockPrefs>) => void;
3247
+ /** Convenience toggle: popover ⇆ side. */
3248
+ toggleMode: () => void;
3249
+ /** Convenience toggle: right ⇆ left (only affects side mode). */
3250
+ toggleSide: () => void;
3251
+ /** Reset to defaults. */
3252
+ reset: () => void;
3253
+ }
3254
+ /**
3255
+ * Persistent dock preferences (mode / side / width) via ui-core localStorage.
3256
+ *
3257
+ * SSR-safe: returns defaults on the server, hydrates on mount.
3258
+ * Survives reloads — power users keep their preferred chat layout.
3259
+ */
3260
+ declare function useChatDockPrefs(opts?: UseChatDockPrefsOptions): UseChatDockPrefsReturn;
3261
+
3262
+ interface UseFocusOnEmptyClickOptions {
3263
+ /**
3264
+ * Custom focus target. Defaults to the composer registered in the chat
3265
+ * context.
3266
+ */
3267
+ targetRef?: RefObject<Focusable | HTMLElement | null>;
3268
+ /** Opt-out without unmounting the hook. @default true */
3269
+ enabled?: boolean;
3270
+ /**
3271
+ * Don't focus if currently streaming (user is reading the reply).
3272
+ * @default true
3273
+ */
3274
+ skipWhileStreaming?: boolean;
3275
+ }
3276
+ /**
3277
+ * "Click anywhere in the chat → focus the composer" — Slack / Linear /
3278
+ * ChatGPT behaviour.
3279
+ *
3280
+ * Returns a single `onMouseUp` handler to attach to the scrollable
3281
+ * messages container. Heuristics that mirror the popular chat apps:
3282
+ *
3283
+ * 1. Ignore clicks on interactive elements (`button`, `a`, `input`,
3284
+ * `textarea`, `[role="button"]`, `[contenteditable]`, …) — they
3285
+ * have their own behaviour.
3286
+ * 2. Ignore clicks that produced a text selection (drag-to-select).
3287
+ * Stealing focus would break copy-paste flow.
3288
+ * 3. Ignore touch input — on mobile the system focuses the textarea
3289
+ * via tap on the composer itself; touching messages should never
3290
+ * open the keyboard.
3291
+ * 4. Optionally skip while the assistant is streaming so the user
3292
+ * can keep reading without the keyboard popping up.
3293
+ *
3294
+ * @example
3295
+ * ```tsx
3296
+ * const onMouseUp = useFocusOnEmptyClick();
3297
+ * <div ref={scrollRef} onMouseUp={onMouseUp}>{messages}</div>
3298
+ * ```
3299
+ */
3300
+ declare function useFocusOnEmptyClick(options?: UseFocusOnEmptyClickOptions): (event: MouseEvent<HTMLElement>) => void;
3301
+
3302
+ declare const useChatAudioPrefs: zustand.UseBoundStore<zustand.StoreApi<AudioPrefsState<ChatAudioEvent>>>;
3303
+
3304
+ /**
3305
+ * Built-in chat notification sounds.
3306
+ *
3307
+ * Bundled into the JS at build time as base64 data URLs (`tsup.config.ts`
3308
+ * loader: `.mp3 → dataurl`). Total ≈ 136KB, gzipped ≈ 130KB — added to
3309
+ * the lazy Chat tool so hosts get notification sounds with zero setup.
3310
+ *
3311
+ * Source files live in `./sounds/`. Re-encode via ffmpeg if you tweak:
3312
+ *
3313
+ * ffmpeg -i in.mp3 -ac 2 -ar 44100 -b:a 128k -af 'atrim=0:1.4,afade=t=out:st=1.22:d=0.18' out.mp3
3314
+ */
3315
+
3316
+ /**
3317
+ * Default chat notification sounds. Pass to `useChatAudio` (or spread
3318
+ * into a custom map) so hosts don't have to ship assets themselves.
3319
+ *
3320
+ * @example
3321
+ * ```tsx
3322
+ * const audio = useChatAudio({ sounds: DEFAULT_CHAT_SOUNDS });
3323
+ *
3324
+ * // Override one event:
3325
+ * const audio = useChatAudio({
3326
+ * sounds: { ...DEFAULT_CHAT_SOUNDS, mention: '/custom-mention.mp3' },
3327
+ * });
3328
+ * ```
3329
+ */
3330
+ declare const DEFAULT_CHAT_SOUNDS: ChatAudioSounds;
2433
3331
 
2434
3332
  interface ToolPayloadMatcher {
2435
3333
  /** Cheap predicate. First match wins. */
@@ -2449,6 +3347,120 @@ declare function isGeoJSONFeatureCollection(v: unknown): v is {
2449
3347
  };
2450
3348
  declare function isStringValue(v: unknown): v is string;
2451
3349
 
3350
+ /**
3351
+ * Chat color tokens — single source of truth.
3352
+ *
3353
+ * Every role-conditional class for chat surfaces lives here.
3354
+ * Components consume via `useChatBubbleStyles` / `useChatRoleStyles`,
3355
+ * never via raw Tailwind literals.
3356
+ *
3357
+ * Why centralize:
3358
+ * 1. One file to edit when the design system changes (e.g. light-theme
3359
+ * contrast tweaks, palette swap).
3360
+ * 2. Eliminates the "first-token-on-bg-primary-was-text-white" class
3361
+ * of bugs where each call site picks its own foreground.
3362
+ * 3. Lets us snapshot-test color decisions later.
3363
+ */
3364
+ /** Bubble surface classes (background + text), keyed by message state. */
3365
+ declare const BUBBLE_SURFACE: {
3366
+ /** User-authored bubble — solid brand color. */
3367
+ readonly user: "bg-primary text-primary-foreground rounded-tr-md";
3368
+ /** Assistant bubble in normal state — neutral muted surface. */
3369
+ readonly assistant: "bg-muted text-foreground rounded-tl-md";
3370
+ /** Assistant bubble when the turn failed — destructive tint. */
3371
+ readonly error: "bg-destructive/10 text-destructive rounded-tl-md border border-destructive/30";
3372
+ };
3373
+ /**
3374
+ * Anchor (link) classes for markdown content rendered inside a bubble.
3375
+ *
3376
+ * On `bg-primary` the link MUST stay legible against the cyan/brand fill —
3377
+ * `text-primary-foreground` matches the bubble's foreground token, so
3378
+ * contrast tracks the design system automatically.
3379
+ *
3380
+ * On the neutral assistant bubble we keep the brand-primary color so links
3381
+ * still pop without competing with the body text.
3382
+ */
3383
+ declare const ANCHOR: {
3384
+ readonly user: string;
3385
+ readonly assistant: "text-primary underline hover:text-primary/80 transition-colors break-all";
3386
+ };
3387
+ /** Inline secondary action (e.g. "Show more / less"). Same logic as anchors. */
3388
+ declare const TOGGLE: {
3389
+ readonly user: "text-primary-foreground/80 hover:text-primary-foreground";
3390
+ readonly assistant: "text-primary hover:text-primary/80";
3391
+ };
3392
+ /** Destructive surface — used by ErrorBanner and the delete action. */
3393
+ declare const DESTRUCTIVE_SURFACE: {
3394
+ /** Banner / card variant: border + tint + text. */
3395
+ readonly banner: "border border-destructive/40 bg-destructive/10 text-destructive";
3396
+ /** Subtle hover for destructive buttons inside the banner / menu. */
3397
+ readonly hover: "hover:bg-destructive/15";
3398
+ /** Strong-hover variant (e.g. trash overlay on attachments). */
3399
+ readonly hoverStrong: "hover:bg-destructive hover:text-destructive-foreground";
3400
+ /** Inline destructive text utility. */
3401
+ readonly text: "text-destructive";
3402
+ /** Hover style for menu items that delete data. */
3403
+ readonly menuItem: "text-destructive focus:text-destructive hover:bg-destructive/15 hover:text-destructive";
3404
+ };
3405
+ /** Tool-call result text. */
3406
+ declare const TOOL_CALL: {
3407
+ readonly errorText: "text-destructive";
3408
+ };
3409
+ type ChatBubbleSurface = keyof typeof BUBBLE_SURFACE;
3410
+
3411
+ /**
3412
+ * Role-aware style hooks for chat surfaces.
3413
+ *
3414
+ * Pure utility hooks — no React state, no side effects, just memoized
3415
+ * className strings derived from `bubbleTokens`. They exist so:
3416
+ * - components don't import token constants directly (single facade)
3417
+ * - "the user-bubble link color" can be changed in one file
3418
+ * - tests can mock the hook to assert intent without parsing classNames
3419
+ */
3420
+ interface ChatBubbleStyles {
3421
+ /** className for the bubble container (background + text + border). */
3422
+ surface: string;
3423
+ /** className for an inline anchor inside markdown. */
3424
+ anchor: string;
3425
+ /** className for a secondary inline action (e.g. show more). */
3426
+ toggle: string;
3427
+ }
3428
+ /**
3429
+ * Resolve bubble + content styles for a single message.
3430
+ *
3431
+ * @param role 'user' | 'assistant' | 'system' (system defaults to assistant styling)
3432
+ * @param isError marks the bubble as a failed turn (overrides surface)
3433
+ *
3434
+ * @example
3435
+ * ```tsx
3436
+ * const { surface, anchor } = useChatBubbleStyles(message.role, !!message.isError);
3437
+ * <div className={cn('rounded-2xl px-3.5 py-2', surface)}>…</div>
3438
+ * ```
3439
+ */
3440
+ declare function useChatBubbleStyles(role: 'user' | 'assistant' | 'system', isError: boolean): ChatBubbleStyles;
3441
+ interface ChatRoleStyles {
3442
+ anchor: string;
3443
+ toggle: string;
3444
+ }
3445
+ /**
3446
+ * Lightweight variant when only role matters (no error state, no surface).
3447
+ * Use in shared markdown renderers that don't know about bubble background.
3448
+ */
3449
+ declare function useChatRoleStyles(isUser: boolean): ChatRoleStyles;
3450
+ interface ChatDestructiveStyles {
3451
+ banner: string;
3452
+ hover: string;
3453
+ hoverStrong: string;
3454
+ text: string;
3455
+ menuItem: string;
3456
+ toolErrorText: string;
3457
+ }
3458
+ /**
3459
+ * Destructive (delete / error) class facade. Hook form keeps the API
3460
+ * symmetric with the others; under the hood it returns a frozen object.
3461
+ */
3462
+ declare function useChatDestructiveStyles(): ChatDestructiveStyles;
3463
+
2452
3464
  /** Walk the conversation and collect image attachments in chronological order. */
2453
3465
  declare function collectImageAttachments(messages: ChatMessage[]): ChatAttachment[];
2454
3466
 
@@ -2595,6 +3607,20 @@ interface MessageListProps {
2595
3607
  * `!isAtBottom`. Plan64.
2596
3608
  */
2597
3609
  onAtBottomChange?: (isAtBottom: boolean) => void;
3610
+ /**
3611
+ * Pixel distance from the bottom that still counts as "at bottom".
3612
+ * Default 120 — generous enough that mid-message users keep getting
3613
+ * sticky-followed (matches ChatGPT / Slack feel) while still letting
3614
+ * a deliberate scroll-up break the lock. Plan11.
3615
+ */
3616
+ atBottomThreshold?: number;
3617
+ /**
3618
+ * Force-scroll to the bottom when this id changes. Wire to the id of
3619
+ * the most-recently-sent user message: every send re-anchors the
3620
+ * viewport so users always see their own bubble + the incoming
3621
+ * reply, even if they were scrolled up. Plan11.
3622
+ */
3623
+ scrollAnchorId?: string | number | null;
2598
3624
  }
2599
3625
  interface MessageListHandle {
2600
3626
  scrollToBottom: (smooth?: boolean) => void;
@@ -3567,7 +4593,22 @@ interface MarkdownEditorProps {
3567
4593
  */
3568
4594
  onSubmit?: () => boolean | void;
3569
4595
  }
3570
- declare function MarkdownEditor({ value, onChange, placeholder, minHeight, className, disabled, showToolbar, mentions, onMentionIdsChange, onSubmit, }: MarkdownEditorProps): react_jsx_runtime.JSX.Element;
4596
+ /**
4597
+ * Imperative handle exposed via `ref`. Matches `ComposerHandle` from
4598
+ * `@djangocfg/ui-tools/chat` so consumers can forward it straight into
4599
+ * `useRegisterComposer({ focus, moveCursorToEnd })` — that's what makes
4600
+ * voice dictation (`VoiceComposerSlot`) push live text into a TipTap
4601
+ * composer.
4602
+ */
4603
+ interface MarkdownEditorHandle {
4604
+ /** Move keyboard focus into the editor. */
4605
+ focus: () => void;
4606
+ /** Place the caret at the end of the document (and focus). */
4607
+ moveCursorToEnd: () => void;
4608
+ /** Escape hatch — the underlying TipTap `Editor` instance. */
4609
+ getEditor: () => Editor$1 | null;
4610
+ }
4611
+ declare const MarkdownEditor: react.ForwardRefExoticComponent<MarkdownEditorProps & react.RefAttributes<MarkdownEditorHandle>>;
3571
4612
 
3572
4613
  /**
3573
4614
  * Built-in serializers for the `MentionConfig.renderMarkdown` callback.
@@ -3776,4 +4817,4 @@ declare function useBlobUrlCleanup(key: string | null): void;
3776
4817
  */
3777
4818
  declare function generateContentKey(content: ArrayBuffer): string;
3778
4819
 
3779
- export { type ApiKey, ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AttachmentRenderer, type AttachmentRendererArgs, type AttachmentRendererMap, Attachments, AttachmentsGrid, type AttachmentsGridProps, AttachmentsList, type AttachmentsListProps, type AttachmentsProps, Player as AudioPlayer, type PlayerProps as AudioPlayerProps, AudioToggle, type AudioToggleProps, BaseInputTemplate, type BlobSource, CHAT_EVENT_NAME, CSS_VARS, CardLoadingFallback, type ChatAction, type ChatAssistantContext, type ChatAttachment, type ChatAudioConfig, type ChatAudioEvent, type ChatAudioSounds, type ChatConfig, type ChatContextValue, type ChatDisplayMode, type ChatEventDetail, type ChatLabels, type ChatLightboxState, type ChatLogScope, type ChatLogger, type ChatMessage, type ChatPersona, type ChatPrefs, ChatProvider, type ChatProviderProps, type ChatRole, ChatRoot, type ChatRootProps, type ChatSource, type ChatState, type ChatStreamEvent, type ChatToolCall, type ChatTransport, type ChatUserContext, CheckboxWidget, ColorWidget, Composer, type ComposerProps, type CreateLazyComponentOptions, type CreateSessionOptions, type CreateVideoErrorFallbackOptions, CronScheduler, type CronSchedulerContextValue, type CronSchedulerProps, CronSchedulerProvider, type CronSchedulerState, CustomInput, type DASHSource, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, type DataUrlSource, DayChips, DiffEditor, type DiffEditorProps, type DisabledWhenRule, Editor, type EditorContextValue, type EditorFile, type EditorOptions, type EditorProps, EditorProvider, type EditorRef, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, type Focusable, type HLSSource, HOTKEYS, type HistoryPage, type HttpTransportConfig, type ImageFile, ImageViewer, type ImageViewerProps, type JsonFormContext, type JsonFormDensity, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type JsonTreeProps, JumpToLatest, type JumpToLatestProps, LIMITS, LazyPlayer as LazyAudioPlayer, LazyChat, type ChatRootProps as LazyChatProps, LazyCronScheduler, LazyImageViewer, LazyJsonSchemaForm, LazyJsonTree, LazyLottiePlayer, LazyMapContainer, LazyMapView, LazyMermaid, LazyOpenapiViewer, LazyPrettyCode, LazyTree, TreeRootProps as LazyTreeProps, LazyVideoPlayer, LazyWrapper, type LazyWrapperProps, type LinkRule, LoadingFallback, type LoadingFallbackProps, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, type MapContainerProps, MapLoadingFallback, type MapStyleKey, type MapViewport, MarkdownEditor, type MarkdownEditorProps, MarkdownMessage, type MarkdownMessageProps, type MarkerData, type MentionAttrs, type MentionConfig, type MentionItem, type MentionMarkdownRenderer, Mermaid, type MermaidProps, MessageActions, type MessageActionsProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListHandle, type MessageListProps, type MockTransportOptions, type MonthDay, MonthDayGrid, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, type ParseSSEOptions, type PlayerMode, type PlaygroundConfig, type PlaygroundProps$1 as PlaygroundProps, PrettyCode, type PrettyCodeProps$1 as PrettyCodeProps, type ResolveFileSourceOptions, STORAGE_KEYS, SchedulePreview, type ScheduleType, ScheduleTypeSelector, type SchemaSource, SelectWidget, type SendOptions, type SessionInfo, type SimpleStreamSource, SliderWidget, Sources, type SourcesProps, Spinner, type StreamOptions, StreamProvider, type StreamSource, StreamingIndicator, type StreamingIndicatorProps, SwitchWidget, TextWidget, TimeSelector, type TokenBuffer, ToolCalls, type ToolCallsProps, type ToolPayloadFallback, type ToolPayloadKind, type ToolPayloadMatcher, TransportError, TreeRootProps, type UiGroup, type UrlSource, type UseAutoFocusOnStreamEndOptions, type UseChatAudioReturn, type UseChatComposerOptions, type UseChatComposerReturn, type UseChatConfig, type UseChatHistoryOptions, type UseChatLayoutConfig, type UseChatLayoutReturn, type UseChatLightboxReturn, type UseChatReturn, type UseChatScrollOptions, type UseChatScrollReturn, type UseCollapsibleContentOptions, type UseCollapsibleContentResult, type UseEditorReturn, type UseLottieOptions, type UseLottieReturn, type UseMonacoReturn, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type WeekDay, type YouTubeSource, buildCron, collectImageAttachments, createHttpTransport, createId, createLazyComponent, createMockTransport, createTokenBuffer, createVideoErrorFallback, deriveInitials, dispatchToolPayload, evaluateDisabledWhen, extractTextFromChildren, generateContentKey, getChatLogger, getRequiredFields, hasRequiredFields, humanizeCron, initialState, isGeoJSONFeatureCollection, isLatLng, isPlainObject, isSimpleStreamSource, isStringValue, isSubmittableDraft, isValidCron, mentionPresets, mergeDefaults, normalizeFormData, parseCron, parseSSE, reducer, resolveFileSource, resolvePersona, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, sanitizeDraft, useAudioCache, useAutoFocusOnStreamEnd, useBlobUrlCleanup, useChat, useChatAudio, useChatAudioPrefs, useChatComposer, useChatContext, useChatContextOptional, useChatHistory, useChatLayout, useChatLightbox, useChatScroll, useCollapsibleContent, useCronCustom, useCronMonthDays, useCronPreview, useCronScheduler, useCronSchedulerContext, useCronTime, useCronType, useCronWeekDays, useEditor, useEditorContext, useImageCache, useLanguage, useLottie, useMediaCacheStore, useMonaco, useRegisterComposer, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, validateRequiredFields, validateSchema };
4820
+ export { ANCHOR, type ApiKey, ArrayFieldItemTemplate, ArrayFieldTemplate, type AspectRatioValue, type AttachmentRenderer, type AttachmentRendererArgs, type AttachmentRendererMap, Attachments, AttachmentsGrid, type AttachmentsGridProps, AttachmentsList, type AttachmentsListProps, type AttachmentsProps, Player as AudioPlayer, type PlayerProps as AudioPlayerProps, AudioToggle, type AudioToggleProps, BUBBLE_SURFACE, BaseInputTemplate, type BlobSource, CHAT_EVENT_NAME, CSS_VARS, CardLoadingFallback, type ChatAction, type ChatAssistantContext, type ChatAttachment, type ChatAudioConfig, type ChatAudioEvent, type ChatAudioSounds, type ChatBubbleStyles, type ChatBubbleSurface, type ChatConfig, type ChatContextValue, type ChatDestructiveStyles, type ChatDisplayMode, ChatDock, type ChatDockMode, type ChatDockPrefs, type ChatDockProps, type ChatDockSide, type ChatEventDetail, ChatFAB, type ChatFABPosition, type ChatFABProps, type ChatFABSize, type ChatFABVariant, ChatGreeting, type ChatGreetingProps, ChatHeader, ChatHeaderActionButton, type ChatHeaderActionButtonProps, ChatHeaderAudioToggle, type ChatHeaderAudioToggleProps, ChatHeaderModeToggle, type ChatHeaderModeToggleProps, type ChatHeaderProps, ChatHeaderResetButton, type ChatHeaderResetButtonProps, type ChatLabels, ChatLauncher, type ChatLauncherGreeting, type ChatLauncherHotkey, type ChatLauncherProps, type ChatLightboxState, type ChatLogScope, type ChatLogger, type ChatMessage, type ChatPersona, type ChatPrefs, type ChatPresencePhase, ChatProvider, type ChatProviderProps, type ChatRole, type ChatRoleStyles, ChatRoot, type ChatRootProps, type ChatSource, type ChatState, type ChatStreamEvent, type ChatToolCall, type ChatTransport, ChatUnreadPreview, type ChatUnreadPreviewProps, type ChatUserContext, CheckboxWidget, ColorWidget, Composer, type ComposerProps, type CreateLazyComponentOptions, type CreateSessionOptions, type CreateVideoErrorFallbackOptions, CronScheduler, type CronSchedulerContextValue, type CronSchedulerProps, CronSchedulerProvider, type CronSchedulerState, CustomInput, type DASHSource, DEFAULT_CHAT_SOUNDS, DEFAULT_DOCK_PREFS, DEFAULT_LABELS, DEFAULT_SIDEBAR, DEFAULT_Z_INDEX, DESTRUCTIVE_SURFACE, type DataUrlSource, DayChips, DiffEditor, type DiffEditorProps, type DisabledWhenRule, Editor, type EditorContextValue, type EditorFile, type EditorOptions, type EditorProps, EditorProvider, type EditorRef, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, type ErrorFallbackProps, ErrorListTemplate, FieldTemplate, type Focusable, type HLSSource, HOTKEYS, type HistoryPage, type HttpTransportConfig, type ImageFile, ImageViewer, type ImageViewerProps, type JsonFormContext, type JsonFormDensity, JsonSchemaForm, type JsonSchemaFormProps, JsonTreeComponent as JsonTree, type JsonTreeConfig, type JsonTreeProps, JumpToLatest, type JumpToLatestProps, LIMITS, LazyPlayer as LazyAudioPlayer, LazyChat, type ChatRootProps as LazyChatProps, LazyCronScheduler, LazyImageViewer, LazyJsonSchemaForm, LazyJsonTree, LazyLottiePlayer, LazyMapContainer, LazyMapView, LazyMermaid, LazyOpenapiViewer, LazyPrettyCode, LazyTree, TreeRootProps as LazyTreeProps, LazyVideoPlayer, LazyWrapper, type LazyWrapperProps, type LinkRule, LoadingFallback, type LoadingFallbackProps, type LottieDirection, LottiePlayer, type LottiePlayerProps, type LottieSize, type LottieSpeed, type MapContainerProps, MapLoadingFallback, type MapStyleKey, type MapViewport, MarkdownEditor, type MarkdownEditorProps, MarkdownMessage, type MarkdownMessageProps, type MarkerData, type MentionAttrs, type MentionConfig, type MentionItem, type MentionMarkdownRenderer, Mermaid, type MermaidProps, MessageActions, type MessageActionsProps, MessageBubble, type MessageBubbleProps, MessageList, type MessageListHandle, type MessageListProps, type MockTransportOptions, type MonthDay, MonthDayGrid, NativeProvider, NumberWidget, ObjectFieldTemplate, Playground as OpenapiViewer, type ParseSSEOptions, type PlayerMode, type PlaygroundConfig, type PlaygroundProps$1 as PlaygroundProps, PrettyCode, type PrettyCodeProps$1 as PrettyCodeProps, type PydanticAIChatTransportOpts, type PydanticAIEvent, type ResolveFileSourceOptions, STORAGE_KEYS, SchedulePreview, type ScheduleType, ScheduleTypeSelector, type SchemaSource, SelectWidget, type SendOptions, type SessionInfo, type SimpleStreamSource, SliderWidget, Sources, type SourcesProps, Spinner, type StreamOptions, StreamProvider, type StreamSource, StreamingIndicator, type StreamingIndicatorProps, SwitchWidget, TOGGLE, TOOL_CALL, TextWidget, TimeSelector, type TokenBuffer, ToolCalls, type ToolCallsProps, type ToolIdQueue, type ToolPayloadFallback, type ToolPayloadKind, type ToolPayloadMatcher, TransportError, TreeRootProps, type UiGroup, type UrlSource, type UseAutoFocusOnStreamEndOptions, type UseChatAudioReturn, type UseChatComposerOptions, type UseChatComposerReturn, type UseChatConfig, type UseChatDockPrefsOptions, type UseChatDockPrefsReturn, type UseChatHistoryOptions, type UseChatLayoutConfig, type UseChatLayoutReturn, type UseChatLightboxReturn, type UseChatResetOptions, type UseChatResetReturn, type UseChatReturn, type UseChatScrollOptions, type UseChatScrollReturn, type UseCollapsibleContentOptions, type UseCollapsibleContentResult, type UseEditorReturn, type UseFocusOnEmptyClickOptions, type UseLottieOptions, type UseLottieReturn, type UseMonacoReturn, type UseVisitorFingerprintOptions, VideoControls, VideoErrorFallback, type VideoErrorFallbackProps, VideoPlayer, type VideoPlayerContextValue, type VideoPlayerProps, VideoPlayerProvider, type VideoPlayerProviderProps, type VideoPlayerRef, type VideoSourceUnion, VidstackProvider, type VimeoSource, type WeekDay, type YouTubeSource, buildCron, collectImageAttachments, createHttpTransport, createId, createLazyComponent, createMockTransport, createPydanticAIChatTransport, createPydanticAISSEMap, createTokenBuffer, createToolIdQueue, createVideoErrorFallback, deriveInitials, dispatchToolPayload, evaluateDisabledWhen, extractTextFromChildren, generateContentKey, getChatLogger, getRequiredFields, hasRequiredFields, humanizeCron, initialState, isGeoJSONFeatureCollection, isLatLng, isPlainObject, isSimpleStreamSource, isStringValue, isSubmittableDraft, isValidCron, mapPydanticAIEvent, mentionPresets, mergeDefaults, normalizeFormData, parseCron, parseSSE, reducer, resolveFileSource, resolvePersona, resolvePlayerMode, resolveStreamSource, safeJsonParse, safeJsonStringify, sanitizeDraft, useAudioCache, useAutoFocusOnStreamEnd, useBlobUrlCleanup, useChat, useChatAudio, useChatAudioPrefs, useChatBubbleStyles, useChatComposer, useChatContext, useChatContextOptional, useChatDestructiveStyles, useChatDockPrefs, useChatHistory, useChatLayout, useChatLightbox, useChatPresence, useChatReset, useChatRoleStyles, useChatScroll, useCollapsibleContent, useCronCustom, useCronMonthDays, useCronPreview, useCronScheduler, useCronSchedulerContext, useCronTime, useCronType, useCronWeekDays, useEditor, useEditorContext, useFocusOnEmptyClick, useImageCache, useLanguage, useLottie, useMediaCacheStore, useMonaco, useRegisterComposer, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisitorFingerprint, validateRequiredFields, validateSchema };