@djangocfg/ui-tools 2.1.390 → 2.1.393

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 +7 -10
  2. package/dist/chunk-PAWJFY3S.mjs +6 -0
  3. package/dist/{chunk-N2XQF2OL.mjs.map → chunk-PAWJFY3S.mjs.map} +1 -1
  4. package/dist/chunk-PK6SKIKE.cjs +8 -0
  5. package/dist/{chunk-OLISEQHS.cjs.map → chunk-PK6SKIKE.cjs.map} +1 -1
  6. package/dist/file-icon/index.cjs +6 -6
  7. package/dist/file-icon/index.d.cts +1 -1
  8. package/dist/file-icon/index.d.ts +1 -1
  9. package/dist/file-icon/index.mjs +1 -1
  10. package/dist/tree/index.cjs +1372 -143
  11. package/dist/tree/index.cjs.map +1 -1
  12. package/dist/tree/index.d.cts +2 -2
  13. package/dist/tree/index.d.ts +2 -2
  14. package/dist/tree/index.mjs +1322 -3
  15. package/dist/tree/index.mjs.map +1 -1
  16. package/dist/{types-CevSbyfD.d.cts → types-B_zhyAqR.d.cts} +1 -1
  17. package/dist/{types-CevSbyfD.d.ts → types-B_zhyAqR.d.ts} +1 -1
  18. package/package.json +6 -14
  19. package/src/tools/AudioPlayer/README.md +4 -4
  20. package/src/tools/Chat/README.md +6 -6
  21. package/src/tools/CronScheduler/index.tsx +1 -1
  22. package/src/tools/CronScheduler/lazy.tsx +1 -1
  23. package/src/tools/ImageViewer/README.md +1 -1
  24. package/src/tools/JsonForm/README.md +2 -2
  25. package/src/tools/MarkdownEditor/README.md +3 -3
  26. package/src/tools/MarkdownMessage/README.md +2 -2
  27. package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +5 -1
  28. package/src/tools/SpeechRecognition/README.md +1 -1
  29. package/dist/ChatRoot-EFNXQXXN.cjs +0 -15
  30. package/dist/ChatRoot-EFNXQXXN.cjs.map +0 -1
  31. package/dist/ChatRoot-FITF5RVP.mjs +0 -6
  32. package/dist/ChatRoot-FITF5RVP.mjs.map +0 -1
  33. package/dist/ChatRoot-PNNGQCYF.css +0 -7
  34. package/dist/ChatRoot-PNNGQCYF.css.map +0 -1
  35. package/dist/CronScheduler.client-DLMXCPAJ.mjs +0 -67
  36. package/dist/CronScheduler.client-DLMXCPAJ.mjs.map +0 -1
  37. package/dist/CronScheduler.client-WEJF4PWQ.cjs +0 -72
  38. package/dist/CronScheduler.client-WEJF4PWQ.cjs.map +0 -1
  39. package/dist/DictationField-AS2F33WI.cjs +0 -13
  40. package/dist/DictationField-AS2F33WI.cjs.map +0 -1
  41. package/dist/DictationField-WPONUCYE.mjs +0 -4
  42. package/dist/DictationField-WPONUCYE.mjs.map +0 -1
  43. package/dist/DocsLayout-EKASBSP7.mjs +0 -3448
  44. package/dist/DocsLayout-EKASBSP7.mjs.map +0 -1
  45. package/dist/DocsLayout-MBFIB4NO.css +0 -7
  46. package/dist/DocsLayout-MBFIB4NO.css.map +0 -1
  47. package/dist/DocsLayout-OURFYWQE.cjs +0 -3455
  48. package/dist/DocsLayout-OURFYWQE.cjs.map +0 -1
  49. package/dist/JsonSchemaForm-DD7CLRIG.cjs +0 -13
  50. package/dist/JsonSchemaForm-DD7CLRIG.cjs.map +0 -1
  51. package/dist/JsonSchemaForm-XKUIVELK.mjs +0 -4
  52. package/dist/JsonSchemaForm-XKUIVELK.mjs.map +0 -1
  53. package/dist/JsonTree-43PQAJKY.mjs +0 -5
  54. package/dist/JsonTree-43PQAJKY.mjs.map +0 -1
  55. package/dist/JsonTree-MLET23ZA.css +0 -7
  56. package/dist/JsonTree-MLET23ZA.css.map +0 -1
  57. package/dist/JsonTree-X6W5YEVY.cjs +0 -11
  58. package/dist/JsonTree-X6W5YEVY.cjs.map +0 -1
  59. package/dist/LottiePlayer.client-2S7ISJ2S.cjs +0 -168
  60. package/dist/LottiePlayer.client-2S7ISJ2S.cjs.map +0 -1
  61. package/dist/LottiePlayer.client-5LDSSJWS.mjs +0 -161
  62. package/dist/LottiePlayer.client-5LDSSJWS.mjs.map +0 -1
  63. package/dist/MapContainer-AKIPABJK.mjs +0 -4
  64. package/dist/MapContainer-AKIPABJK.mjs.map +0 -1
  65. package/dist/MapContainer-STVDMC36.cjs +0 -17
  66. package/dist/MapContainer-STVDMC36.cjs.map +0 -1
  67. package/dist/Mermaid.client-DDXWXZXY.css +0 -7
  68. package/dist/Mermaid.client-DDXWXZXY.css.map +0 -1
  69. package/dist/Mermaid.client-NL4SVR7F.mjs +0 -481
  70. package/dist/Mermaid.client-NL4SVR7F.mjs.map +0 -1
  71. package/dist/Mermaid.client-NNTI6DFX.cjs +0 -487
  72. package/dist/Mermaid.client-NNTI6DFX.cjs.map +0 -1
  73. package/dist/Player-BRV7XTWR.mjs +0 -4
  74. package/dist/Player-BRV7XTWR.mjs.map +0 -1
  75. package/dist/Player-PM7F7DD7.cjs +0 -13
  76. package/dist/Player-PM7F7DD7.cjs.map +0 -1
  77. package/dist/Player-ZGQKKOWI.css +0 -66
  78. package/dist/Player-ZGQKKOWI.css.map +0 -1
  79. package/dist/PrettyCode.client-GWFAIVFN.css +0 -7
  80. package/dist/PrettyCode.client-GWFAIVFN.css.map +0 -1
  81. package/dist/PrettyCode.client-KOHDVPPN.cjs +0 -285
  82. package/dist/PrettyCode.client-KOHDVPPN.cjs.map +0 -1
  83. package/dist/PrettyCode.client-ZGYGKE7G.mjs +0 -283
  84. package/dist/PrettyCode.client-ZGYGKE7G.mjs.map +0 -1
  85. package/dist/TreeRoot-5COOOSWG.mjs +0 -4
  86. package/dist/TreeRoot-5COOOSWG.mjs.map +0 -1
  87. package/dist/TreeRoot-AABP2J6Y.cjs +0 -19
  88. package/dist/TreeRoot-AABP2J6Y.cjs.map +0 -1
  89. package/dist/chunk-2NG4SXEP.mjs +0 -743
  90. package/dist/chunk-2NG4SXEP.mjs.map +0 -1
  91. package/dist/chunk-4LFB7I5K.cjs +0 -1387
  92. package/dist/chunk-4LFB7I5K.cjs.map +0 -1
  93. package/dist/chunk-5D2OCOPQ.cjs +0 -222
  94. package/dist/chunk-5D2OCOPQ.cjs.map +0 -1
  95. package/dist/chunk-5I5QNGUG.cjs +0 -611
  96. package/dist/chunk-5I5QNGUG.cjs.map +0 -1
  97. package/dist/chunk-6ZX2G25W.mjs +0 -1361
  98. package/dist/chunk-6ZX2G25W.mjs.map +0 -1
  99. package/dist/chunk-76NNDZH6.cjs +0 -1061
  100. package/dist/chunk-76NNDZH6.cjs.map +0 -1
  101. package/dist/chunk-7CWGZPO3.mjs +0 -214
  102. package/dist/chunk-7CWGZPO3.mjs.map +0 -1
  103. package/dist/chunk-7EYHNP3E.cjs +0 -965
  104. package/dist/chunk-7EYHNP3E.cjs.map +0 -1
  105. package/dist/chunk-7IYXZUJO.cjs +0 -769
  106. package/dist/chunk-7IYXZUJO.cjs.map +0 -1
  107. package/dist/chunk-ADEN3UA4.cjs +0 -892
  108. package/dist/chunk-ADEN3UA4.cjs.map +0 -1
  109. package/dist/chunk-B6IR5KSC.mjs +0 -59
  110. package/dist/chunk-B6IR5KSC.mjs.map +0 -1
  111. package/dist/chunk-C6GXVH5J.mjs +0 -338
  112. package/dist/chunk-C6GXVH5J.mjs.map +0 -1
  113. package/dist/chunk-DMX7W4XZ.mjs +0 -1113
  114. package/dist/chunk-DMX7W4XZ.mjs.map +0 -1
  115. package/dist/chunk-ECONRHIG.mjs +0 -212
  116. package/dist/chunk-ECONRHIG.mjs.map +0 -1
  117. package/dist/chunk-FEN5S772.cjs +0 -1227
  118. package/dist/chunk-FEN5S772.cjs.map +0 -1
  119. package/dist/chunk-FP2RLYQZ.cjs +0 -187
  120. package/dist/chunk-FP2RLYQZ.cjs.map +0 -1
  121. package/dist/chunk-FVVF7VCD.cjs +0 -1325
  122. package/dist/chunk-FVVF7VCD.cjs.map +0 -1
  123. package/dist/chunk-GYIO7W7M.mjs +0 -1197
  124. package/dist/chunk-GYIO7W7M.mjs.map +0 -1
  125. package/dist/chunk-KNDLV4PI.cjs +0 -1356
  126. package/dist/chunk-KNDLV4PI.cjs.map +0 -1
  127. package/dist/chunk-KNEQRUBA.mjs +0 -181
  128. package/dist/chunk-KNEQRUBA.mjs.map +0 -1
  129. package/dist/chunk-N2XQF2OL.mjs +0 -14
  130. package/dist/chunk-N4MZYNR4.mjs +0 -1342
  131. package/dist/chunk-N4MZYNR4.mjs.map +0 -1
  132. package/dist/chunk-NTVBIIUD.mjs +0 -1439
  133. package/dist/chunk-NTVBIIUD.mjs.map +0 -1
  134. package/dist/chunk-OBRSGM64.mjs +0 -607
  135. package/dist/chunk-OBRSGM64.mjs.map +0 -1
  136. package/dist/chunk-ODO4GMW7.mjs +0 -79
  137. package/dist/chunk-ODO4GMW7.mjs.map +0 -1
  138. package/dist/chunk-OLISEQHS.cjs +0 -18
  139. package/dist/chunk-PVAX67JG.mjs +0 -1041
  140. package/dist/chunk-PVAX67JG.mjs.map +0 -1
  141. package/dist/chunk-QJ6GTUCO.cjs +0 -81
  142. package/dist/chunk-QJ6GTUCO.cjs.map +0 -1
  143. package/dist/chunk-T3MWM23F.cjs +0 -214
  144. package/dist/chunk-T3MWM23F.cjs.map +0 -1
  145. package/dist/chunk-TBSHZO5R.cjs +0 -1134
  146. package/dist/chunk-TBSHZO5R.cjs.map +0 -1
  147. package/dist/chunk-UNCS5V5F.mjs +0 -887
  148. package/dist/chunk-UNCS5V5F.mjs.map +0 -1
  149. package/dist/chunk-VWQ5WOIL.mjs +0 -2059
  150. package/dist/chunk-VWQ5WOIL.mjs.map +0 -1
  151. package/dist/chunk-W75B7Y6C.cjs +0 -1478
  152. package/dist/chunk-W75B7Y6C.cjs.map +0 -1
  153. package/dist/chunk-Y6UTOBF6.mjs +0 -938
  154. package/dist/chunk-Y6UTOBF6.mjs.map +0 -1
  155. package/dist/chunk-YDPDTOSP.cjs +0 -2061
  156. package/dist/chunk-YDPDTOSP.cjs.map +0 -1
  157. package/dist/chunk-YW5IVWHQ.cjs +0 -346
  158. package/dist/chunk-YW5IVWHQ.cjs.map +0 -1
  159. package/dist/chunk-YXZ6GU7H.cjs +0 -63
  160. package/dist/chunk-YXZ6GU7H.cjs.map +0 -1
  161. package/dist/chunk-ZL7FH4NW.mjs +0 -1274
  162. package/dist/chunk-ZL7FH4NW.mjs.map +0 -1
  163. package/dist/components-EHOGXATG.cjs +0 -22
  164. package/dist/components-EHOGXATG.cjs.map +0 -1
  165. package/dist/components-MQ6DR7TX.cjs +0 -26
  166. package/dist/components-MQ6DR7TX.cjs.map +0 -1
  167. package/dist/components-XRX7QGLB.mjs +0 -5
  168. package/dist/components-XRX7QGLB.mjs.map +0 -1
  169. package/dist/components-YATKRWLH.mjs +0 -5
  170. package/dist/components-YATKRWLH.mjs.map +0 -1
  171. package/dist/index.cjs +0 -3674
  172. package/dist/index.cjs.map +0 -1
  173. package/dist/index.css +0 -234
  174. package/dist/index.css.map +0 -1
  175. package/dist/index.d.cts +0 -4929
  176. package/dist/index.d.ts +0 -4929
  177. package/dist/index.mjs +0 -2912
  178. package/dist/index.mjs.map +0 -1
  179. package/dist/launcher-5Y42OBSN.mjs +0 -6
  180. package/dist/launcher-5Y42OBSN.mjs.map +0 -1
  181. package/dist/launcher-PMW2YB24.cjs +0 -59
  182. package/dist/launcher-PMW2YB24.cjs.map +0 -1
  183. package/src/index.ts +0 -157
package/dist/index.d.cts DELETED
@@ -1,4929 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as react from 'react';
3
- import react__default, { ReactNode, ComponentType, RefObject, ChangeEvent, KeyboardEvent, ClipboardEvent, CSSProperties, ButtonHTMLAttributes, MouseEvent } from 'react';
4
- import { ViewState } from 'react-map-gl/maplibre';
5
- import { Language } from 'prism-react-renderer';
6
- export { Language } from 'prism-react-renderer';
7
- import { RJSFSchema, UiSchema, WidgetProps, FieldTemplateProps, ObjectFieldTemplateProps, ArrayFieldTemplateProps, ArrayFieldItemTemplateProps, ErrorListProps } from '@rjsf/utils';
8
- export { RJSFSchema, UiSchema } from '@rjsf/utils';
9
- import { FormProps, IChangeEvent } from '@rjsf/core';
10
- import { CustomJsonSchema7, CustomJsonUiSchema7, CustomJsonUiDisabledWhenRule, CustomJsonUiGroup } from '@djangocfg/ui-core/lib';
11
- export { CustomJsonSchema7, CustomJsonSchema7Type, CustomJsonUiDisabledWhenRule, CustomJsonUiGroup, CustomJsonUiSchema7 } from '@djangocfg/ui-core/lib';
12
- import { CommonExternalProps } from 'react-json-tree';
13
- import { b as TreeRootProps } from './types-CevSbyfD.cjs';
14
- 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.cjs';
15
- import * as zustand from 'zustand';
16
- import { AudioPrefsState } from '@djangocfg/ui-core/hooks';
17
- import { ConsolaInstance } from 'consola';
18
- import { Components } from 'react-markdown';
19
- import { MediaPlayerInstance } from '@vidstack/react';
20
- import * as monaco from 'monaco-editor';
21
- import { Editor as Editor$1 } from '@tiptap/react';
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.cjs';
23
- import * as zustand_middleware from 'zustand/middleware';
24
-
25
- interface LoadingFallbackProps {
26
- /** Minimum height of the loading container */
27
- minHeight?: string | number;
28
- /** Show loading text */
29
- showText?: boolean;
30
- /** Custom loading text */
31
- text?: string;
32
- /** Additional CSS classes */
33
- className?: string;
34
- }
35
- /**
36
- * Spinner - Simple spinning loader
37
- */
38
- declare function Spinner({ className }: {
39
- className?: string;
40
- }): react_jsx_runtime.JSX.Element;
41
- /**
42
- * LoadingFallback - Default loading state for lazy components
43
- */
44
- declare function LoadingFallback({ minHeight, showText, text, className, }: LoadingFallbackProps): react_jsx_runtime.JSX.Element;
45
- /**
46
- * CardLoadingFallback - Loading state styled as a card
47
- */
48
- declare function CardLoadingFallback({ title, description, minHeight, className, }: {
49
- title?: string;
50
- description?: string;
51
- minHeight?: string | number;
52
- className?: string;
53
- }): react_jsx_runtime.JSX.Element;
54
- /**
55
- * MapLoadingFallback - Loading state for map components
56
- */
57
- declare function MapLoadingFallback({ minHeight, className, }: {
58
- minHeight?: string | number;
59
- className?: string;
60
- }): react_jsx_runtime.JSX.Element;
61
- interface LazyWrapperProps {
62
- children: ReactNode;
63
- /** Custom fallback component */
64
- fallback?: ReactNode;
65
- /** Use card-style fallback */
66
- card?: boolean;
67
- /** Card title (when card=true) */
68
- cardTitle?: string;
69
- /** Card description (when card=true) */
70
- cardDescription?: string;
71
- /** Minimum height for fallback */
72
- minHeight?: string | number;
73
- /** Additional CSS classes for fallback */
74
- className?: string;
75
- }
76
- /**
77
- * LazyWrapper - Suspense wrapper with configurable fallbacks
78
- *
79
- * @example
80
- * // Basic usage
81
- * <LazyWrapper>
82
- * <LazyComponent />
83
- * </LazyWrapper>
84
- *
85
- * @example
86
- * // Card style fallback
87
- * <LazyWrapper card cardTitle="Diagram" minHeight={300}>
88
- * <Mermaid chart={...} />
89
- * </LazyWrapper>
90
- *
91
- * @example
92
- * // Custom fallback
93
- * <LazyWrapper fallback={<MyCustomLoader />}>
94
- * <HeavyComponent />
95
- * </LazyWrapper>
96
- */
97
- declare function LazyWrapper({ children, fallback, card, cardTitle, cardDescription, minHeight, className, }: LazyWrapperProps): react_jsx_runtime.JSX.Element;
98
- interface CreateLazyComponentOptions<P> {
99
- /** Loading fallback component */
100
- fallback?: ReactNode | ((props: P) => ReactNode);
101
- /** Display name for the component */
102
- displayName?: string;
103
- }
104
- /**
105
- * createLazyComponent - Factory for creating lazy-loaded components
106
- *
107
- * @example
108
- * const LazyMermaid = createLazyComponent(
109
- * () => import('./Mermaid.client'),
110
- * {
111
- * displayName: 'Mermaid',
112
- * fallback: <CardLoadingFallback title="Diagram" />,
113
- * }
114
- * );
115
- */
116
- declare function createLazyComponent<P extends object>(loader: () => Promise<{
117
- default: ComponentType<P>;
118
- }>, options?: CreateLazyComponentOptions<P>): ComponentType<P>;
119
-
120
- interface MarkerData {
121
- id: string;
122
- longitude: number;
123
- latitude: number;
124
- data?: Record<string, unknown>;
125
- }
126
- interface MapViewport extends Partial<ViewState> {
127
- longitude: number;
128
- latitude: number;
129
- zoom: number;
130
- bearing?: number;
131
- pitch?: number;
132
- transitionDuration?: number;
133
- }
134
- type MapStyleKey = 'light' | 'dark' | 'streets' | 'satellite';
135
-
136
- interface MapContainerProps {
137
- children?: ReactNode;
138
- initialViewport?: Partial<MapViewport>;
139
- mapStyle?: MapStyleKey | string;
140
- interactiveLayerIds?: string[];
141
- className?: string;
142
- style?: React.CSSProperties;
143
- cursor?: string;
144
- attributionControl?: boolean;
145
- reuseMaps?: boolean;
146
- /** URL to open in external maps app (shows "Open in Maps" button if provided) */
147
- openInMapsUrl?: string;
148
- /** Label for the open in maps button */
149
- openInMapsLabel?: string;
150
- /** Auto-reset to initial viewport after N ms of inactivity (0 = disabled) */
151
- autoResetDelay?: number;
152
- /** Show reset button */
153
- showResetButton?: boolean;
154
- }
155
-
156
- /**
157
- * LazyMapContainer - Lazy-loaded map container
158
- *
159
- * Automatically shows loading state while MapLibre GL loads (~800KB)
160
- */
161
- declare const LazyMapContainer: react.ComponentType<MapContainerProps>;
162
- /**
163
- * LazyMapView - Lazy-loaded map view (alias for MapContainer)
164
- */
165
- declare const LazyMapView: react.ComponentType<Omit<MapContainerProps, "initialViewport">>;
166
-
167
- /**
168
- * Mermaid Component - Dynamic Import Wrapper
169
- *
170
- * Lazy loads the heavy Mermaid library (~800KB) only when needed.
171
- * This significantly reduces the initial bundle size.
172
- */
173
-
174
- interface MermaidProps {
175
- chart: string;
176
- className?: string;
177
- isCompact?: boolean;
178
- /** Enable click-to-fullscreen functionality (default: true) */
179
- fullscreen?: boolean;
180
- /**
181
- * Enable the FloatingToolbar's "click to scroll" lock overlay.
182
- * Defaults to `false` — Mermaid diagrams don't scroll internally,
183
- * so the lock overlay just steals page wheel events. See the
184
- * Mermaid.client implementation for the full rationale.
185
- */
186
- scrollIsolation?: boolean;
187
- }
188
- declare const Mermaid: react__default.FC<MermaidProps>;
189
-
190
- /**
191
- * LazyMermaid - Lazy-loaded Mermaid diagram renderer
192
- *
193
- * Automatically shows loading state while Mermaid loads (~800KB)
194
- */
195
- declare const LazyMermaid: react.ComponentType<MermaidProps>;
196
-
197
- interface PrettyCodeProps$1 {
198
- data: string | object;
199
- language: Language;
200
- className?: string;
201
- mode?: 'dark' | 'light';
202
- inline?: boolean;
203
- customBg?: string;
204
- isCompact?: boolean;
205
- scrollIsolation?: boolean;
206
- maxLines?: number;
207
- /** ``'card'`` (default) ships the full chrome. ``'plain'`` is
208
- * chrome-less — for embedding inside another scroll container. */
209
- variant?: 'card' | 'plain';
210
- }
211
-
212
- /**
213
- * LazyPrettyCode - Lazy-loaded code syntax highlighter
214
- *
215
- * Automatically shows loading state while Prism loads (~500KB)
216
- */
217
- declare const LazyPrettyCode: react.ComponentType<PrettyCodeProps$1>;
218
-
219
- interface ApiKey {
220
- id: string;
221
- name: string;
222
- /** Raw key value sent in the ``X-API-Key`` request header. */
223
- secret: string;
224
- created_at?: string;
225
- last_used_at?: string | null;
226
- }
227
- interface OpenApiSchema {
228
- openapi: string;
229
- info: {
230
- title: string;
231
- version: string;
232
- description?: string;
233
- };
234
- servers?: Array<{
235
- url: string;
236
- description?: string;
237
- }>;
238
- paths: Record<string, Record<string, any>>;
239
- components?: {
240
- schemas?: Record<string, any>;
241
- };
242
- }
243
- interface SchemaSource {
244
- id: string;
245
- name: string;
246
- /** URL to fetch the OpenAPI schema from. Required when ``data`` is not
247
- * provided; ignored when ``data`` is present. */
248
- url?: string;
249
- /** Pre-loaded OpenAPI schema object. When provided the viewer uses it
250
- * directly and never makes a network request — ideal for statically
251
- * imported JSON files. Either ``url`` or ``data`` must be set. */
252
- data?: OpenApiSchema;
253
- /** Per-schema override for the request base URL. Wins over the
254
- * global ``PlaygroundConfig.baseUrl`` and over ``schema.servers[0].url``
255
- * from the OpenAPI document. Use when a single playground hosts
256
- * several APIs that live on different domains. */
257
- baseUrl?: string;
258
- }
259
- interface PlaygroundConfig {
260
- schemas: SchemaSource[];
261
- defaultSchemaId?: string;
262
- /** Global override for the request base URL. Used when the OpenAPI
263
- * document has no ``servers`` entry, or when docs are hosted on a
264
- * different origin than the API. Resolution order (highest wins):
265
- * ``SchemaSource.baseUrl`` → ``PlaygroundConfig.baseUrl`` →
266
- * ``schema.servers[0].url`` → empty string (relative paths). */
267
- baseUrl?: string;
268
- /** Optional API keys the user can pick from in the request panel.
269
- * When provided, the playground auto-selects the first one and
270
- * syncs the ``X-API-Key`` header from ``ApiKey.secret``. Pass
271
- * the loading flag if your source is async — the picker shows
272
- * a spinner instead of "no keys yet". */
273
- apiKeys?: ApiKey[];
274
- apiKeysLoading?: boolean;
275
- /** How multiple schemas are presented in the sidebar.
276
- * - ``'selector'`` (default): a Combobox switches between schemas, the
277
- * docs column shows endpoints of the active schema only.
278
- * - ``'sections'``: the Combobox is hidden and every schema becomes a
279
- * top-level heading in the sidebar, with endpoints of all schemas
280
- * rendered back-to-back in the docs column. Scrollspy picks the
281
- * active schema based on what's visible. */
282
- schemaGrouping?: 'selector' | 'sections';
283
- /** URL-hash sync. When enabled, the viewer reads/writes
284
- * ``#<schemaId>/<anchor>`` on the browser location so deep-links
285
- * to a specific endpoint work out of the box. Defaults to ``true`` —
286
- * pass ``false`` (or ``{ enabled: false }``) to opt out if the host
287
- * page already manages the hash itself. */
288
- urlSync?: boolean | {
289
- enabled: boolean;
290
- };
291
- }
292
-
293
- /**
294
- * Lazy-loaded OpenapiViewer Component
295
- *
296
- * Heavy OpenAPI viewer (~400KB) is loaded only when component is rendered.
297
- * Use this for automatic code-splitting with Suspense fallback.
298
- *
299
- * For direct imports without lazy loading, use:
300
- * import OpenapiViewer from '@djangocfg/ui-tools/openapi'
301
- */
302
-
303
- interface PlaygroundProps$1 {
304
- config: PlaygroundConfig;
305
- }
306
-
307
- declare const LazyOpenapiViewer: react.FC<PlaygroundProps$1>;
308
-
309
- /** Visual density for form controls. */
310
- type JsonFormDensity = 'comfortable' | 'compact';
311
- /**
312
- * Aliases that point to the portable schema types in `@djangocfg/ui-core/lib`.
313
- * Kept under their old short names for back-compat — new code can import the
314
- * `CustomJson*` originals directly from ui-core.
315
- */
316
- type DisabledWhenRule = CustomJsonUiDisabledWhenRule;
317
- type UiGroup = CustomJsonUiGroup;
318
- /** What we put into RJSF's `formContext` so widgets/templates can react to global form state. */
319
- interface JsonFormContext {
320
- density: JsonFormDensity;
321
- /** Latest form data — used by `evaluateDisabledWhen`. */
322
- formData: unknown;
323
- }
324
- /**
325
- * JSON Schema Form props interface
326
- */
327
- interface JsonSchemaFormProps<T = any> extends Omit<Partial<FormProps<T>>, 'schema' | 'uiSchema'> {
328
- /**
329
- * JSON Schema that defines the form structure. Accepts either RJSF's
330
- * `RJSFSchema` directly or our portable `CustomJsonSchema7` from
331
- * `@djangocfg/ui-core/lib` — both are cast to RJSF internally.
332
- */
333
- schema: RJSFSchema | CustomJsonSchema7;
334
- /** UI Schema for customizing the form appearance. Same dual-shape acceptance as `schema`. */
335
- uiSchema?: UiSchema | CustomJsonUiSchema7;
336
- /** Initial form data */
337
- formData?: T;
338
- /** Callback when form is submitted */
339
- onSubmit?: (data: IChangeEvent<T>) => void;
340
- /** Callback when form data changes */
341
- onChange?: (data: IChangeEvent<T>) => void;
342
- /** Callback when form has validation errors */
343
- onError?: (errors: any[]) => void;
344
- /** Whether to show error list at the top of form */
345
- showErrorList?: false | 'top' | 'bottom';
346
- /** Whether to live validate on change */
347
- liveValidate?: boolean;
348
- /** Whether the form is disabled */
349
- disabled?: boolean;
350
- /** Whether the form is read-only */
351
- readonly?: boolean;
352
- /** Custom CSS class name */
353
- className?: string;
354
- /** Whether to show submit button */
355
- showSubmitButton?: boolean;
356
- /** Submit button text */
357
- submitButtonText?: string;
358
- /** Visual density preset. `'compact'` shrinks rows and hides description text (moves it to label `title=` tooltip). */
359
- density?: JsonFormDensity;
360
- }
361
-
362
- /**
363
- * LazyJsonSchemaForm - Lazy-loaded JSON Schema form generator
364
- *
365
- * Automatically shows loading state while RJSF loads (~300KB)
366
- */
367
- declare const LazyJsonSchemaForm: react.ComponentType<JsonSchemaFormProps<any>>;
368
-
369
- /**
370
- * JSON Schema Form Component
371
- *
372
- * A fully-featured form generator that creates forms from JSON Schema.
373
- * Built on top of react-jsonschema-form with custom widgets and templates
374
- * using @djangocfg/ui components.
375
- *
376
- * @example
377
- * ```tsx
378
- * const schema = {
379
- * type: 'object',
380
- * required: ['name'],
381
- * properties: {
382
- * name: { type: 'string', title: 'Name' },
383
- * age: { type: 'number', title: 'Age' },
384
- * active: { type: 'boolean', title: 'Active' }
385
- * }
386
- * };
387
- *
388
- * <JsonSchemaForm
389
- * schema={schema}
390
- * onSubmit={(data) => console.log(data.formData)}
391
- * />
392
- * ```
393
- */
394
- declare function JsonSchemaForm<T = any>(props: JsonSchemaFormProps<T>): react_jsx_runtime.JSX.Element;
395
-
396
- /**
397
- * Utility functions for JSON Schema Form
398
- */
399
- /**
400
- * Safely validates and normalizes JSON Schema
401
- * Ensures schema is valid before rendering
402
- */
403
- declare function validateSchema(schema: any): RJSFSchema | null;
404
- /**
405
- * Safely normalizes form data
406
- * Removes undefined values and ensures data structure matches schema
407
- */
408
- declare function normalizeFormData<T = any>(formData: any, schema: RJSFSchema): T;
409
- /**
410
- * Merges schema defaults with form data
411
- */
412
- declare function mergeDefaults(formData: any, schema: RJSFSchema): any;
413
- /**
414
- * Safely parses JSON string with error handling
415
- */
416
- declare function safeJsonParse<T = any>(jsonString: string, fallback: T): T;
417
- /**
418
- * Safely stringifies object to JSON
419
- */
420
- declare function safeJsonStringify(obj: any, pretty?: boolean): string;
421
- /**
422
- * Checks if schema has required fields
423
- */
424
- declare function hasRequiredFields(schema: RJSFSchema): boolean;
425
- /**
426
- * Gets all required field paths from schema
427
- */
428
- declare function getRequiredFields(schema: RJSFSchema, prefix?: string): string[];
429
- /**
430
- * Validates form data against required fields
431
- */
432
- declare function validateRequiredFields(formData: any, schema: RJSFSchema): {
433
- valid: boolean;
434
- missing: string[];
435
- };
436
-
437
- /**
438
- * Evaluates a `ui:disabledWhen` rule against form data. Returns `true` when the
439
- * field should be disabled. If `rule` is undefined, returns `false`.
440
- *
441
- * Supported rule shapes:
442
- * { path, eq } | { path, notEq } | { path, in } | { path, notIn }
443
- * | { path, truthy: true } | { path, falsy: true }
444
- */
445
- declare function evaluateDisabledWhen(rule: DisabledWhenRule | undefined, formData: unknown): boolean;
446
-
447
- /**
448
- * Text input widget for JSON Schema Form
449
- * Handles string fields with optional textarea for multiline
450
- */
451
- declare function TextWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
452
-
453
- /**
454
- * Number input widget for JSON Schema Form
455
- * Handles integer and number fields
456
- */
457
- declare function NumberWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
458
-
459
- /**
460
- * Checkbox widget for JSON Schema Form
461
- * Handles boolean fields
462
- */
463
- declare function CheckboxWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
464
-
465
- /**
466
- * Select dropdown widget for JSON Schema Form
467
- * Handles enum fields
468
- */
469
- declare function SelectWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
470
-
471
- /**
472
- * Switch toggle widget for JSON Schema Form
473
- * Alternative boolean input
474
- */
475
- declare function SwitchWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
476
-
477
- /**
478
- * Color input widget for JSON Schema Form
479
- * Supports HSL format (h s% l%) and HEX format
480
- * Click on color box to open native color picker directly
481
- */
482
- declare function ColorWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
483
-
484
- /**
485
- * Slider widget for JSON Schema Form
486
- *
487
- * Supports:
488
- * - number/integer types
489
- * - min/max from schema
490
- * - step from schema or options
491
- * - unit suffix (e.g., "rem", "px", "%")
492
- * - optional text input for precise values
493
- *
494
- * Usage in uiSchema:
495
- * ```json
496
- * {
497
- * "radius": {
498
- * "ui:widget": "slider",
499
- * "ui:options": {
500
- * "unit": "rem",
501
- * "showInput": true,
502
- * "step": 0.125
503
- * }
504
- * }
505
- * }
506
- * ```
507
- */
508
- declare function SliderWidget(props: WidgetProps): react_jsx_runtime.JSX.Element;
509
-
510
- /**
511
- * Field template for JSON Schema Form
512
- * Controls the layout and styling of individual form fields
513
- */
514
- declare function FieldTemplate(props: FieldTemplateProps): react_jsx_runtime.JSX.Element;
515
-
516
- /**
517
- * Object field template for JSON Schema Form
518
- *
519
- * Supports:
520
- * - Collapsible groups via ui:collapsible option
521
- * - Grid layout via ui:grid option
522
- * - Custom styling via ui:className
523
- *
524
- * Usage in uiSchema:
525
- * ```json
526
- * {
527
- * "colors": {
528
- * "ui:collapsible": true,
529
- * "ui:collapsed": false,
530
- * "ui:grid": 2
531
- * }
532
- * }
533
- * ```
534
- */
535
- declare function ObjectFieldTemplate(props: ObjectFieldTemplateProps): react_jsx_runtime.JSX.Element;
536
-
537
- /**
538
- * Array field template for JSON Schema Form
539
- * Renders array items with add/remove controls
540
- *
541
- * NOTE: In RJSF v6, `items` is an array of ReactElement (already rendered),
542
- * NOT an array of objects with {children, hasRemove, etc.}.
543
- * The actual rendering of each item (including remove buttons) is handled
544
- * by ArrayFieldItemTemplate.
545
- */
546
- declare function ArrayFieldTemplate(props: ArrayFieldTemplateProps): react_jsx_runtime.JSX.Element;
547
-
548
- /**
549
- * Array field item template for JSON Schema Form
550
- * Renders individual array items with proper styling and action buttons
551
- *
552
- * In RJSF v6, this template is responsible for rendering each item in an array,
553
- * including the item content (children) and the action buttons (remove, move up/down, copy).
554
- */
555
- declare function ArrayFieldItemTemplate(props: ArrayFieldItemTemplateProps): react_jsx_runtime.JSX.Element;
556
-
557
- /**
558
- * Error list template for JSON Schema Form
559
- * Displays validation errors at the top of the form
560
- */
561
- declare function ErrorListTemplate(props: ErrorListProps): react_jsx_runtime.JSX.Element;
562
-
563
- /**
564
- * Base input template for JSON Schema Form
565
- *
566
- * This template is CRITICAL for rendering primitive types (string, number)
567
- * inside arrays. Without it, array items with primitive types will render
568
- * as empty containers.
569
- *
570
- * RJSF uses this template for:
571
- * - Array items with primitive types (e.g., array of strings)
572
- * - Fields without explicit widget mapping
573
- * - All text-based widgets internally
574
- *
575
- * @see https://rjsf-team.github.io/react-jsonschema-form/docs/advanced-customization/custom-templates/#baseinputtemplate
576
- */
577
- declare function BaseInputTemplate(props: WidgetProps): react_jsx_runtime.JSX.Element;
578
-
579
- /**
580
- * LottiePlayer Types
581
- *
582
- * Type definitions for the Lottie animation player component
583
- */
584
- type LottieSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
585
- type LottieSpeed = 0.5 | 1 | 1.5 | 2;
586
- type LottieDirection = 1 | -1;
587
- interface LottiePlayerProps {
588
- /**
589
- * Animation data (JSON object) or URL to load from
590
- */
591
- src: string | object;
592
- /**
593
- * Size preset for the player
594
- * @default 'md'
595
- */
596
- size?: LottieSize;
597
- /**
598
- * Custom width (overrides size preset)
599
- */
600
- width?: number | string;
601
- /**
602
- * Custom height (overrides size preset)
603
- */
604
- height?: number | string;
605
- /**
606
- * Autoplay animation
607
- * @default true
608
- */
609
- autoplay?: boolean;
610
- /**
611
- * Loop animation
612
- * @default true
613
- */
614
- loop?: boolean | number;
615
- /**
616
- * Playback speed
617
- * @default 1
618
- */
619
- speed?: LottieSpeed;
620
- /**
621
- * Direction (1 = forward, -1 = reverse)
622
- * @default 1
623
- */
624
- direction?: LottieDirection;
625
- /**
626
- * Show playback controls
627
- * @default false
628
- */
629
- controls?: boolean;
630
- /**
631
- * Background color
632
- */
633
- background?: string;
634
- /**
635
- * CSS class name
636
- */
637
- className?: string;
638
- /**
639
- * Show loading state
640
- * @default true
641
- */
642
- showLoading?: boolean;
643
- /**
644
- * Callback when animation completes
645
- */
646
- onComplete?: () => void;
647
- /**
648
- * Callback when animation loads
649
- */
650
- onLoad?: () => void;
651
- /**
652
- * Callback on error
653
- */
654
- onError?: (error: Error) => void;
655
- }
656
-
657
- /**
658
- * LazyLottiePlayer - Lazy-loaded Lottie animation player
659
- *
660
- * Automatically shows loading state while Lottie loads (~200KB)
661
- */
662
- declare const LazyLottiePlayer: react.ComponentType<LottiePlayerProps>;
663
-
664
- type WaveformMode = 'peaks' | 'live' | 'bars' | 'progress' | 'none';
665
- type WaveformConfig = {
666
- mode?: WaveformMode;
667
- peaks?: Float32Array;
668
- height?: number;
669
- barWidth?: number;
670
- barGap?: number;
671
- bgColor?: string;
672
- fgColor?: string;
673
- decodeOnMount?: boolean;
674
- };
675
- type ReactiveCoverMode = false | 'subtle';
676
- type PlayerVariant = 'default' | 'compact' | 'auto';
677
- type PlayerErrorReason = 'network' | 'decode' | 'unsupported' | 'unknown';
678
- type PlayerProps = {
679
- src: string;
680
- peaks?: Float32Array;
681
- title?: string;
682
- artist?: string;
683
- album?: string;
684
- cover?: string;
685
- variant?: PlayerVariant;
686
- className?: string;
687
- waveform?: WaveformConfig;
688
- reactiveCover?: ReactiveCoverMode;
689
- autoplay?: boolean;
690
- loop?: boolean;
691
- initialVolume?: number;
692
- muted?: boolean;
693
- preload?: 'none' | 'metadata' | 'auto';
694
- exclusive?: boolean;
695
- onPrev?: () => void;
696
- onNext?: () => void;
697
- onPlay?: () => void;
698
- onPause?: () => void;
699
- onEnded?: () => void;
700
- onError?: (reason: PlayerErrorReason, e: unknown) => void;
701
- onTimeUpdate?: (currentTime: number, duration: number) => void;
702
- ariaLabel?: string;
703
- enableKeyboardShortcuts?: boolean;
704
- seekStartsPlayback?: boolean;
705
- };
706
- type PlayerHandle = {
707
- audio: HTMLAudioElement;
708
- play: () => Promise<void>;
709
- pause: () => void;
710
- seek: (seconds: number) => void;
711
- getCurrentTime: () => number;
712
- getDuration: () => number;
713
- };
714
-
715
- declare const LazyPlayer: react.ComponentType<PlayerProps>;
716
-
717
- /**
718
- * Video source type definitions
719
- */
720
- /** Simple URL source (mp4, webm, etc.) */
721
- interface UrlSource {
722
- type: 'url';
723
- url: string;
724
- title?: string;
725
- poster?: string;
726
- }
727
- /** YouTube embed source */
728
- interface YouTubeSource {
729
- type: 'youtube';
730
- /** YouTube video ID (11 characters) */
731
- id: string;
732
- title?: string;
733
- poster?: string;
734
- }
735
- /** Vimeo embed source */
736
- interface VimeoSource {
737
- type: 'vimeo';
738
- /** Vimeo video ID */
739
- id: string;
740
- title?: string;
741
- poster?: string;
742
- }
743
- /** HLS streaming source */
744
- interface HLSSource {
745
- type: 'hls';
746
- /** URL to .m3u8 manifest */
747
- url: string;
748
- title?: string;
749
- poster?: string;
750
- }
751
- /** DASH streaming source */
752
- interface DASHSource {
753
- type: 'dash';
754
- /** URL to .mpd manifest */
755
- url: string;
756
- title?: string;
757
- poster?: string;
758
- }
759
- /** HTTP Range streaming source (for large files with auth) */
760
- interface StreamSource {
761
- type: 'stream';
762
- /** Session ID for authorization */
763
- sessionId: string;
764
- /** File path on server */
765
- path: string;
766
- /** Function to generate stream URL */
767
- getStreamUrl: (sessionId: string, path: string) => string;
768
- /** MIME type for the video */
769
- mimeType?: string;
770
- title?: string;
771
- poster?: string;
772
- }
773
- /** Binary data source (ArrayBuffer) */
774
- interface BlobSource {
775
- type: 'blob';
776
- /** Video data as ArrayBuffer */
777
- data: ArrayBuffer;
778
- /** MIME type (default: video/mp4) */
779
- mimeType?: string;
780
- title?: string;
781
- poster?: string;
782
- }
783
- /** Base64 data URL source */
784
- interface DataUrlSource {
785
- type: 'data-url';
786
- /** Base64 encoded data URL */
787
- data: string;
788
- title?: string;
789
- poster?: string;
790
- }
791
- /** Union of all source types */
792
- type VideoSourceUnion = UrlSource | YouTubeSource | VimeoSource | HLSSource | DASHSource | StreamSource | BlobSource | DataUrlSource;
793
-
794
- /**
795
- * Player configuration types
796
- */
797
-
798
- /** Player mode - determines which provider to use */
799
- type PlayerMode = 'auto' | 'vidstack' | 'native' | 'streaming';
800
- /** Aspect ratio options */
801
- type AspectRatioValue = number | 'auto' | 'fill';
802
- /** Common player settings */
803
- interface CommonPlayerSettings {
804
- /** Auto-play video */
805
- autoPlay?: boolean;
806
- /** Mute video by default */
807
- muted?: boolean;
808
- /** Loop video */
809
- loop?: boolean;
810
- /** Play video inline on mobile */
811
- playsInline?: boolean;
812
- /** Show player controls */
813
- controls?: boolean;
814
- /**
815
- * Aspect ratio:
816
- * - number (e.g. 16/9): Fixed aspect ratio
817
- * - 'auto': Natural video aspect ratio
818
- * - 'fill': Fill parent container (100% width & height)
819
- */
820
- aspectRatio?: AspectRatioValue;
821
- /** Preload strategy */
822
- preload?: 'auto' | 'metadata' | 'none';
823
- }
824
- /** Common player events */
825
- interface CommonPlayerEvents {
826
- onPlay?: () => void;
827
- onPause?: () => void;
828
- onEnded?: () => void;
829
- onError?: (error: string) => void;
830
- onLoadStart?: () => void;
831
- onCanPlay?: () => void;
832
- onTimeUpdate?: (currentTime: number, duration: number) => void;
833
- /** Called when buffering progress changes (buffered seconds, total duration) */
834
- onBufferProgress?: (buffered: number, duration: number) => void;
835
- }
836
- /** Error fallback render props */
837
- interface ErrorFallbackProps {
838
- error: string;
839
- retry?: () => void;
840
- }
841
- /** Main VideoPlayer props */
842
- interface VideoPlayerProps extends CommonPlayerSettings, CommonPlayerEvents {
843
- /** Video source configuration */
844
- source: VideoSourceUnion;
845
- /** Player mode (default: 'auto') */
846
- mode?: PlayerMode;
847
- /** Player theme (Vidstack only) */
848
- theme?: 'default' | 'minimal' | 'modern';
849
- /** Show video info below player */
850
- showInfo?: boolean;
851
- /** Container className */
852
- className?: string;
853
- /** Video element className (native/streaming only) */
854
- videoClassName?: string;
855
- /** Disable right-click context menu */
856
- disableContextMenu?: boolean;
857
- /** Show loading spinner */
858
- showPreloader?: boolean;
859
- /** Preloader timeout in ms */
860
- preloaderTimeout?: number;
861
- /** Custom error fallback UI */
862
- errorFallback?: react__default.ReactNode | ((props: ErrorFallbackProps) => react__default.ReactNode);
863
- }
864
- /** VideoPlayer ref methods */
865
- interface VideoPlayerRef {
866
- /** Play video */
867
- play: () => Promise<void> | void;
868
- /** Pause video */
869
- pause: () => void;
870
- /** Toggle play/pause */
871
- togglePlay: () => void;
872
- /** Seek to time in seconds */
873
- seekTo: (time: number) => void;
874
- /** Set volume (0-1) */
875
- setVolume: (volume: number) => void;
876
- /** Toggle mute */
877
- toggleMute: () => void;
878
- /** Enter fullscreen */
879
- enterFullscreen: () => void;
880
- /** Exit fullscreen */
881
- exitFullscreen: () => void;
882
- /** Current playback time in seconds */
883
- readonly currentTime: number;
884
- /** Video duration in seconds */
885
- readonly duration: number;
886
- /** Whether video is paused */
887
- readonly paused: boolean;
888
- }
889
-
890
- /**
891
- * Provider-specific types
892
- */
893
-
894
- /** Props passed to Vidstack provider */
895
- interface VidstackProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
896
- source: UrlSource | YouTubeSource | VimeoSource | HLSSource | DASHSource;
897
- theme?: 'default' | 'minimal' | 'modern';
898
- showInfo?: boolean;
899
- className?: string;
900
- errorFallback?: react__default.ReactNode | ((props: ErrorFallbackProps) => react__default.ReactNode);
901
- }
902
- /** Props passed to Native provider */
903
- interface NativeProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
904
- source: UrlSource | DataUrlSource;
905
- className?: string;
906
- videoClassName?: string;
907
- disableContextMenu?: boolean;
908
- showPreloader?: boolean;
909
- preloaderTimeout?: number;
910
- }
911
- /** Props passed to Stream provider */
912
- interface StreamProviderProps extends CommonPlayerSettings, CommonPlayerEvents {
913
- source: StreamSource | BlobSource | DataUrlSource;
914
- className?: string;
915
- videoClassName?: string;
916
- disableContextMenu?: boolean;
917
- showPreloader?: boolean;
918
- preloaderTimeout?: number;
919
- errorFallback?: react__default.ReactNode | ((props: ErrorFallbackProps) => react__default.ReactNode);
920
- }
921
- /** Options for resolving file source */
922
- interface ResolveFileSourceOptions {
923
- /** File content - can be data URL string or binary ArrayBuffer */
924
- content: string | ArrayBuffer | null | undefined;
925
- /** File path for streaming */
926
- path: string;
927
- /** MIME type of the file */
928
- mimeType?: string;
929
- /** Session ID for authenticated streaming */
930
- sessionId?: string | null;
931
- /** Load method hint - 'http_stream' enables streaming mode */
932
- loadMethod?: 'http_stream' | 'rpc' | 'unspecified' | 'skip' | string;
933
- /** Function to generate stream URL (required for streaming) */
934
- getStreamUrl?: (sessionId: string, path: string) => string;
935
- /** Optional title */
936
- title?: string;
937
- /** Optional poster */
938
- poster?: string;
939
- }
940
- interface VideoPlayerContextValue {
941
- /** Function to generate stream URL (for HTTP Range streaming) */
942
- getStreamUrl?: (sessionId: string, path: string) => string;
943
- /** Current session ID */
944
- sessionId?: string | null;
945
- }
946
- interface VideoPlayerProviderProps extends VideoPlayerContextValue {
947
- children: react__default.ReactNode;
948
- }
949
- /** Simplified stream source (uses context for getStreamUrl) */
950
- interface SimpleStreamSource {
951
- type: 'stream';
952
- /** File path on server */
953
- path: string;
954
- /** Session ID (optional, uses context if not provided) */
955
- sessionId?: string;
956
- /** MIME type for the video */
957
- mimeType?: string;
958
- title?: string;
959
- poster?: string;
960
- }
961
-
962
- /**
963
- * LazyVideoPlayer - Lazy-loaded professional video player
964
- *
965
- * Automatically shows loading state while Vidstack loads (~150KB)
966
- */
967
- declare const LazyVideoPlayer: react.ComponentType<VideoPlayerProps>;
968
-
969
- type JsonTreeMode = 'full' | 'compact' | 'inline';
970
- interface JsonTreeConfig {
971
- /** Maximum depth to expand automatically (default: 2) */
972
- maxAutoExpandDepth?: number;
973
- /** Maximum items in array to auto-expand (default: 10) */
974
- maxAutoExpandArrayItems?: number;
975
- /** Maximum object keys to auto-expand (default: 5) */
976
- maxAutoExpandObjectKeys?: number;
977
- /** Maximum string length before truncation (default: 200) */
978
- maxStringLength?: number;
979
- /** Collection limit for performance (default: 50) */
980
- collectionLimit?: number;
981
- /** Whether to show collection info (array length, object keys count) */
982
- showCollectionInfo?: boolean;
983
- /** Whether to show expand/collapse all buttons */
984
- showExpandControls?: boolean;
985
- /** Whether to show copy/download buttons */
986
- showActionButtons?: boolean;
987
- /** Custom CSS classes for the container */
988
- className?: string;
989
- /** Whether to preserve object key order (default: true) */
990
- preserveKeyOrder?: boolean;
991
- /** Font size for tree nodes (default: '12px' for compact/inline, '13px' for full) */
992
- fontSize?: string;
993
- }
994
- interface JsonTreeComponentProps {
995
- title?: string;
996
- data: unknown;
997
- /**
998
- * Extra top offset in px for the floating toolbar — use when your layout
999
- * has a non-sticky header that useNavbarHeight cannot auto-detect.
1000
- * Adds to the auto-detected navbar height.
1001
- */
1002
- toolbarOffset?: number;
1003
- /**
1004
- * Display mode:
1005
- * - "full" (default): With toolbar and border
1006
- * - "compact": No toolbar, subtle styling
1007
- * - "inline": Minimal, no border
1008
- */
1009
- mode?: JsonTreeMode;
1010
- config?: JsonTreeConfig;
1011
- /** Override for react-json-tree props */
1012
- jsonTreeProps?: Partial<CommonExternalProps>;
1013
- }
1014
-
1015
- /**
1016
- * JsonTreeComponent — JSON viewer with expand/collapse, copy, download.
1017
- *
1018
- * Memoised: re-renders only when `title`, `data`, `mode`, `config` or
1019
- * `jsonTreeProps` change. `data` is compared by reference — the parent
1020
- * should not mutate the object in place.
1021
- */
1022
- declare const JsonTreeComponent: react__default.MemoExoticComponent<({ title, data, mode, config, jsonTreeProps, }: JsonTreeComponentProps) => react_jsx_runtime.JSX.Element>;
1023
-
1024
- interface JsonTreeProps {
1025
- title?: string;
1026
- data: unknown;
1027
- /**
1028
- * Display mode:
1029
- * - "full" (default): With toolbar and border
1030
- * - "compact": No toolbar, subtle styling
1031
- * - "inline": Minimal, no border
1032
- */
1033
- mode?: JsonTreeMode;
1034
- config?: JsonTreeConfig;
1035
- jsonTreeProps?: Partial<CommonExternalProps>;
1036
- }
1037
-
1038
- /**
1039
- * LazyJsonTree - Lazy-loaded JSON visualization tree
1040
- *
1041
- * Automatically shows loading state while JsonTree loads (~100KB)
1042
- *
1043
- * @example
1044
- * // Full mode (with toolbar)
1045
- * <LazyJsonTree data={obj} mode="full" />
1046
- *
1047
- * // Compact mode (no toolbar)
1048
- * <LazyJsonTree data={obj} mode="compact" />
1049
- *
1050
- * // Inline mode (minimal, for embedding)
1051
- * <LazyJsonTree data={obj} mode="inline" />
1052
- */
1053
- declare const LazyJsonTree: react.ComponentType<JsonTreeProps>;
1054
-
1055
- /**
1056
- * ImageViewer type definitions
1057
- */
1058
- interface ImageFile {
1059
- /** Display name for the image */
1060
- name: string;
1061
- /** File path used for change detection and caching */
1062
- path: string;
1063
- /** Optional MIME type */
1064
- mimeType?: string;
1065
- }
1066
- interface ImageItem {
1067
- /** File info for this image */
1068
- file: ImageFile;
1069
- /** Direct image URL (use when serving from CDN/server) */
1070
- src?: string;
1071
- /** Raw image content — ArrayBuffer or base64/binary string (use when serving from memory) */
1072
- content?: string | ArrayBuffer;
1073
- }
1074
- interface ImageViewerProps {
1075
- /**
1076
- * Gallery images array.
1077
- * When provided, enables gallery mode with prev/next navigation.
1078
- * Single-image mode: pass one item.
1079
- * Each item can have `src` (URL) or `content` (ArrayBuffer/base64) or both.
1080
- */
1081
- images: ImageItem[];
1082
- /**
1083
- * Initial index to show (default: 0).
1084
- * Useful when opening a specific image from a grid.
1085
- */
1086
- initialIndex?: number;
1087
- /** Hide expand button when already in dialog */
1088
- inDialog?: boolean;
1089
- }
1090
-
1091
- /**
1092
- * LazyImageViewer - Lazy-loaded image viewer with zoom/pan/rotate
1093
- *
1094
- * Automatically shows loading state while ImageViewer loads (~50KB)
1095
- */
1096
- declare const LazyImageViewer: react.ComponentType<ImageViewerProps>;
1097
-
1098
- /**
1099
- * CronScheduler Types
1100
- *
1101
- * Unix 5-field cron format: minute hour day-of-month month day-of-week
1102
- */
1103
- type ScheduleType = 'daily' | 'weekly' | 'monthly' | 'custom';
1104
- /** Day of week: 0 = Sunday, 1 = Monday, ..., 6 = Saturday */
1105
- type WeekDay = 0 | 1 | 2 | 3 | 4 | 5 | 6;
1106
- /** Day of month: 1-31 */
1107
- type MonthDay = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31;
1108
- interface CronSchedulerState {
1109
- /** Current schedule type */
1110
- type: ScheduleType;
1111
- /** Hour (0-23) */
1112
- hour: number;
1113
- /** Minute (0-59) */
1114
- minute: number;
1115
- /** Selected week days (for weekly type) */
1116
- weekDays: WeekDay[];
1117
- /** Selected month days (for monthly type) */
1118
- monthDays: MonthDay[];
1119
- /** Raw cron expression (for custom type) */
1120
- customCron: string;
1121
- /** Whether current state produces valid cron */
1122
- isValid: boolean;
1123
- }
1124
- interface CronSchedulerComputed {
1125
- /** Generated cron expression */
1126
- cronExpression: string;
1127
- /** Human-readable description */
1128
- humanDescription: string;
1129
- /** Initial value from props (null if not provided) */
1130
- initialValue: string | null;
1131
- }
1132
- interface CronSchedulerActions {
1133
- /** Set schedule type */
1134
- setType: (type: ScheduleType) => void;
1135
- /** Set time (hour and minute) */
1136
- setTime: (hour: number, minute: number) => void;
1137
- /** Toggle a week day selection */
1138
- toggleWeekDay: (day: WeekDay) => void;
1139
- /** Set all week days at once */
1140
- setWeekDays: (days: WeekDay[]) => void;
1141
- /** Toggle a month day selection */
1142
- toggleMonthDay: (day: MonthDay) => void;
1143
- /** Set all month days at once */
1144
- setMonthDays: (days: MonthDay[]) => void;
1145
- /** Set custom cron expression */
1146
- setCustomCron: (cron: string) => void;
1147
- /** Reset to default state */
1148
- reset: () => void;
1149
- }
1150
- interface CronSchedulerContextValue extends CronSchedulerState, CronSchedulerComputed, CronSchedulerActions {
1151
- }
1152
- interface CronSchedulerProps {
1153
- /** Current cron expression (Unix 5-field format) */
1154
- value?: string;
1155
- /** Callback when schedule changes */
1156
- onChange?: (cron: string) => void;
1157
- /** Initial schedule type (default: 'daily') */
1158
- defaultType?: ScheduleType;
1159
- /** Show human-readable preview (default: true) */
1160
- showPreview?: boolean;
1161
- /** Show raw cron expression in preview (default: false) */
1162
- showCronExpression?: boolean;
1163
- /** Allow copying cron expression (default: false) */
1164
- allowCopy?: boolean;
1165
- /** 12h or 24h time format (default: '24h') */
1166
- timeFormat?: '12h' | '24h';
1167
- /** Disable all interactions */
1168
- disabled?: boolean;
1169
- /** Additional CSS classes */
1170
- className?: string;
1171
- }
1172
- interface CronSchedulerProviderProps {
1173
- children: React.ReactNode;
1174
- value?: string;
1175
- onChange?: (cron: string) => void;
1176
- defaultType?: ScheduleType;
1177
- }
1178
-
1179
- /**
1180
- * LazyCronScheduler - Lazy-loaded cron expression builder
1181
- *
1182
- * Automatically shows loading state while CronScheduler loads (~15KB).
1183
- * Uses createLazyComponent factory for optimal code-splitting.
1184
- *
1185
- * @example
1186
- * // Basic usage
1187
- * <LazyCronScheduler
1188
- * value="0 9 * * *"
1189
- * onChange={handleChange}
1190
- * />
1191
- *
1192
- * @example
1193
- * // With all options
1194
- * <LazyCronScheduler
1195
- * value={cron}
1196
- * onChange={setCron}
1197
- * defaultType="weekly"
1198
- * showPreview
1199
- * showCronExpression
1200
- * allowCopy
1201
- * timeFormat="24h"
1202
- * />
1203
- */
1204
- declare const LazyCronScheduler: react.ComponentType<CronSchedulerProps>;
1205
-
1206
- declare const LazyTree: react.ComponentType<TreeRootProps<unknown>>;
1207
-
1208
- /**
1209
- * Persona — display identity attached to messages and config.
1210
- *
1211
- * Used by `ChatMessage.sender`, `ChatConfig.user`, `ChatConfig.assistant`.
1212
- */
1213
- type ChatRole = 'user' | 'assistant' | 'system';
1214
- interface ChatPersona {
1215
- /** Display name. */
1216
- name?: string;
1217
- /** Avatar image URL. */
1218
- avatarUrl?: string;
1219
- /** Initials fallback when no avatar. Auto-derived from `name` if absent. */
1220
- initials?: string;
1221
- /** Tooltip / aria description. */
1222
- description?: string;
1223
- }
1224
- interface ChatUserContext extends ChatPersona {
1225
- email?: string;
1226
- language?: string;
1227
- role?: string;
1228
- /** Free-form custom data forwarded to transport metadata. */
1229
- custom?: Record<string, unknown>;
1230
- }
1231
- interface ChatAssistantContext extends ChatPersona {
1232
- /** Model identifier (gpt-4o, claude-opus, …). */
1233
- model?: string;
1234
- }
1235
-
1236
- /**
1237
- * Tool calls — assistant-initiated function/tool invocations during a turn.
1238
- */
1239
- interface ChatToolCall {
1240
- id: string;
1241
- name: string;
1242
- input: unknown;
1243
- output?: unknown;
1244
- /** Live buffer accumulated during streaming. Replaced by `output` on completion. */
1245
- streamingText?: string;
1246
- status: 'running' | 'success' | 'error' | 'cancelled';
1247
- startedAt: number;
1248
- endedAt?: number;
1249
- /** Optional grouping label for parallel/fan-out execution. */
1250
- sourceHostname?: string;
1251
- }
1252
-
1253
- /**
1254
- * Attachments + sources attached to a chat message.
1255
- */
1256
- interface ChatAttachment {
1257
- id: string;
1258
- type: 'image' | 'file' | 'audio' | 'video';
1259
- url: string;
1260
- thumbnailUrl?: string;
1261
- name?: string;
1262
- mimeType?: string;
1263
- sizeBytes?: number;
1264
- status?: 'uploading' | 'ready' | 'error';
1265
- /** 0..1 while uploading. */
1266
- progress?: number;
1267
- /** Extracted text from images (OCR). */
1268
- ocrText?: string;
1269
- }
1270
- interface ChatSource {
1271
- title: string;
1272
- url: string;
1273
- snippet?: string;
1274
- chunkIndex?: number;
1275
- }
1276
-
1277
- /**
1278
- * The atomic unit — a single message in a chat session.
1279
- *
1280
- * Composed of role + content + optional rich-data slots (attachments,
1281
- * sources, tool calls). Serializable: no Date, no Map.
1282
- */
1283
-
1284
- interface ChatMessage {
1285
- id: string;
1286
- role: ChatRole;
1287
- content: string;
1288
- /** epoch ms — serializable. */
1289
- createdAt: number;
1290
- isStreaming?: boolean;
1291
- isError?: boolean;
1292
- /** Bumps on edit so memo keys invalidate. */
1293
- version?: number;
1294
- /** Per-message persona override (multi-user / multi-bot). Falls back to
1295
- * `ChatConfig.user` / `ChatConfig.assistant` when absent. */
1296
- sender?: ChatPersona;
1297
- /** Simple status indicator above message ("Searching knowledge base..."). */
1298
- toolActivity?: string;
1299
- toolCalls?: ChatToolCall[];
1300
- attachments?: ChatAttachment[];
1301
- sources?: ChatSource[];
1302
- tokensIn?: number;
1303
- tokensOut?: number;
1304
- }
1305
-
1306
- /**
1307
- * UI label strings — i18n is the host's job. Pass overrides via
1308
- * `ChatConfig.labels` and merge with `DEFAULT_LABELS`.
1309
- */
1310
- interface ChatLabels {
1311
- send: string;
1312
- cancel: string;
1313
- copy: string;
1314
- regenerate: string;
1315
- edit: string;
1316
- delete: string;
1317
- retry: string;
1318
- newChat: string;
1319
- loadMore: string;
1320
- jumpToLatest: string;
1321
- attach: string;
1322
- voice: string;
1323
- errorGeneric: string;
1324
- cancelledSuffix: string;
1325
- }
1326
- declare const DEFAULT_LABELS: ChatLabels;
1327
-
1328
- /**
1329
- * Top-level chat configuration — placeholder, suggestions, identities, prefs.
1330
- */
1331
-
1332
- type ChatDisplayMode = 'closed' | 'embedded' | 'floating' | 'sidebar' | 'fullscreen';
1333
- interface ChatPrefs {
1334
- /** Submit hotkey for the composer. */
1335
- submitOn?: 'enter' | 'cmd+enter';
1336
- /** UI density. */
1337
- density?: 'comfortable' | 'compact';
1338
- /** Locale forwarded to transport metadata. */
1339
- locale?: string;
1340
- /** Show timestamps on each bubble. */
1341
- showTimestamps?: boolean;
1342
- }
1343
- interface ChatConfig {
1344
- /** Window title / aria-label. */
1345
- title?: string;
1346
- /** Composer placeholder. */
1347
- placeholder?: string;
1348
- /** Empty-state greeting. */
1349
- greeting?: string;
1350
- /** Empty-state description. */
1351
- description?: string;
1352
- /** Suggested prompts shown on empty conversation. */
1353
- suggestions?: Array<{
1354
- label: string;
1355
- prompt: string;
1356
- }>;
1357
- /** Locale forwarded to the transport via stream metadata. */
1358
- locale?: string;
1359
- /** Project / chat slug forwarded to the transport. */
1360
- slug?: string;
1361
- /** UI density. Use `prefs.density` for the same effect; this stays for
1362
- * backwards compatibility. */
1363
- density?: 'comfortable' | 'compact';
1364
- /** Identity of the human author. Renders avatar / name on user bubbles
1365
- * and gets stamped on outgoing messages as `message.sender`. */
1366
- user?: ChatUserContext;
1367
- /** Identity of the assistant. Renders avatar / name on assistant bubbles. */
1368
- assistant?: ChatAssistantContext;
1369
- /** UI preferences. */
1370
- prefs?: ChatPrefs;
1371
- /** Visual labels (i18n is the host's job). */
1372
- labels?: Partial<ChatLabels>;
1373
- }
1374
-
1375
- /**
1376
- * SSE stream events — the canonical wire shape consumed by the reducer.
1377
- *
1378
- * Backend-specific shapes (e.g. pydantic-AI's `text_delta`) get normalized
1379
- * into this union by `mapPydanticAIEvent` and friends.
1380
- */
1381
-
1382
- type ChatStreamEvent = {
1383
- type: 'message_start';
1384
- messageId: string;
1385
- sessionId: string;
1386
- } | {
1387
- type: 'resume_start';
1388
- } | {
1389
- type: 'chunk';
1390
- delta: string;
1391
- } | {
1392
- type: 'tool_activity';
1393
- tool: string;
1394
- status: string;
1395
- } | {
1396
- type: 'tool_call_start';
1397
- toolId: string;
1398
- name: string;
1399
- input: unknown;
1400
- sourceHostname?: string;
1401
- } | {
1402
- type: 'tool_call_delta';
1403
- toolId: string;
1404
- delta: string;
1405
- } | {
1406
- type: 'tool_call_end';
1407
- toolId: string;
1408
- output: unknown;
1409
- status: 'success' | 'error';
1410
- } | {
1411
- type: 'message_end';
1412
- tokensIn?: number;
1413
- tokensOut?: number;
1414
- sources?: ChatSource[];
1415
- } | {
1416
- type: 'error';
1417
- code: string;
1418
- message: string;
1419
- };
1420
-
1421
- /**
1422
- * Session info + history page shapes returned by transports.
1423
- */
1424
-
1425
- interface CreateSessionOptions {
1426
- metadata?: Record<string, unknown>;
1427
- }
1428
- interface SessionInfo {
1429
- sessionId: string;
1430
- /** If the server resumed an existing session, it may return prior messages. */
1431
- messages?: ChatMessage[];
1432
- hasMore?: boolean;
1433
- cursor?: string | null;
1434
- resumed?: boolean;
1435
- /**
1436
- * Optional human-readable title (typically derived from the first
1437
- * user message). Hosts that render a session-list sidebar can read
1438
- * this directly instead of crawling messages. Plan64.
1439
- */
1440
- title?: string;
1441
- }
1442
- interface HistoryPage {
1443
- messages: ChatMessage[];
1444
- hasMore: boolean;
1445
- nextCursor: string | null;
1446
- }
1447
- interface StreamOptions {
1448
- signal: AbortSignal;
1449
- attachments?: ChatAttachment[];
1450
- metadata?: Record<string, unknown>;
1451
- }
1452
- interface SendOptions {
1453
- signal?: AbortSignal;
1454
- attachments?: ChatAttachment[];
1455
- metadata?: Record<string, unknown>;
1456
- }
1457
-
1458
- /**
1459
- * Transport interface — what every chat backend adapter implements.
1460
- *
1461
- * Default web implementation lives in `core/transport/http.ts`.
1462
- * Pydantic-AI adapter lives in `core/transport/pydantic-ai-transport.ts`.
1463
- */
1464
-
1465
- interface ChatTransport {
1466
- createSession(opts?: CreateSessionOptions): Promise<SessionInfo>;
1467
- loadHistory(sessionId: string, cursor?: string | null, limit?: number): Promise<HistoryPage>;
1468
- stream(sessionId: string, content: string, options: StreamOptions): AsyncGenerator<ChatStreamEvent, void, void>;
1469
- send(sessionId: string, content: string, options?: SendOptions): Promise<ChatMessage>;
1470
- closeSession(sessionId: string): Promise<void>;
1471
- }
1472
-
1473
- type ChatAudioEvent = 'messageSent' | 'messageReceived' | 'streamStart' | 'error' | 'mention' | 'notification';
1474
- /** Map an event to a sound URL. `false` silences the event explicitly. */
1475
- type ChatAudioSounds = Partial<Record<ChatAudioEvent, string | false>>;
1476
- interface ChatAudioConfig {
1477
- /** Map event → asset URL. Omit (or set `false`) to silence one event. */
1478
- sounds?: ChatAudioSounds;
1479
- /** Master volume 0..1. Persisted via the global prefs store. */
1480
- volume?: number;
1481
- /**
1482
- * Per-event volume multipliers (0..1). Applied on top of `volume`.
1483
- * Defaults applied by `useChatAudio` if not provided:
1484
- * - error: 0.25 (gentle — error UI is the loud signal, not the sound)
1485
- * - mention: 1.0 (louder than baseline received)
1486
- * - messageSent: 0.5 (subtle self-confirmation)
1487
- * - messageReceived: 0.7
1488
- * - streamStart: 0.3 (very subtle, fires often)
1489
- * - notification: 0.9
1490
- *
1491
- * Pass `{}` to disable defaults; pass overrides to tweak.
1492
- */
1493
- eventVolumes?: Partial<Record<ChatAudioEvent, number>>;
1494
- /** Master mute. */
1495
- muted?: boolean;
1496
- /** Custom predicate — return `false` to suppress a play call. */
1497
- shouldPlay?: (event: ChatAudioEvent) => boolean;
1498
- /** Default-suppress when user prefers reduced motion. Default: true. */
1499
- respectReducedMotion?: boolean;
1500
- /** Default-suppress when user prefers reduced data. Default: true. */
1501
- respectReducedData?: boolean;
1502
- /** Mute when host page is hidden (`visibilityState === 'hidden'`). Default: true. */
1503
- muteWhenHidden?: boolean;
1504
- /**
1505
- * Skip web playback entirely — `play()` becomes a no-op. Pair with
1506
- * `onSoundEvent` for native hosts (cmdop_go / Tauri) that play sounds
1507
- * outside the browser.
1508
- */
1509
- silenced?: boolean;
1510
- /**
1511
- * Side-channel fired whenever `play(event)` is called. Stays active
1512
- * even when `silenced=true`. Use to bridge into a native audio backend.
1513
- */
1514
- onSoundEvent?: (event: ChatAudioEvent) => void;
1515
- }
1516
- interface UseChatAudioReturn {
1517
- /** Play a sound for an event. No-ops if the event has no URL or is muted. */
1518
- play: (event: ChatAudioEvent) => void;
1519
- /** Eagerly load an event's audio (called automatically on mount). */
1520
- preload: (event: ChatAudioEvent) => void;
1521
- /** Manually unlock — useful in stories/tests. */
1522
- unlock: () => void;
1523
- /** True after the first user gesture inside the chat root. */
1524
- isUnlocked: boolean;
1525
- /** Master mute (persistent). */
1526
- muted: boolean;
1527
- setMuted: (m: boolean) => void;
1528
- /** Flip mute state — convenience. */
1529
- toggleMute: () => void;
1530
- /** Master volume 0..1 (persistent). */
1531
- volume: number;
1532
- setVolume: (v: number) => void;
1533
- /** Per-event opt-out (persistent). */
1534
- isEventEnabled: (event: ChatAudioEvent) => boolean;
1535
- setEventEnabled: (event: ChatAudioEvent, enabled: boolean) => void;
1536
- /** True when no sounds are configured (or `silenced`). */
1537
- isSilent: boolean;
1538
- }
1539
-
1540
- /**
1541
- * Pure chat state machine. Zero React. Zero I/O.
1542
- *
1543
- * Invariants:
1544
- * - At most one message has `isStreaming === true` at any time. It is always
1545
- * the last message in the array.
1546
- * - Messages are immutable; updates produce new objects.
1547
- * - `version` bumps on edit so memo keys invalidate.
1548
- */
1549
-
1550
- interface ChatState {
1551
- sessionId: string | null;
1552
- messages: ChatMessage[];
1553
- /** Initial history load in flight. */
1554
- isLoading: boolean;
1555
- /** Assistant is generating a reply. */
1556
- isStreaming: boolean;
1557
- /** Older history page in flight. */
1558
- isLoadingMore: boolean;
1559
- hasMore: boolean;
1560
- oldestCursor: string | null;
1561
- error: string | null;
1562
- }
1563
- declare const initialState: ChatState;
1564
- type ChatAction = {
1565
- type: 'SESSION_SET';
1566
- sessionId: string;
1567
- messages?: ChatMessage[];
1568
- hasMore?: boolean;
1569
- cursor?: string | null;
1570
- } | {
1571
- type: 'HISTORY_LOAD_START';
1572
- } | {
1573
- type: 'HISTORY_LOAD_DONE';
1574
- messages: ChatMessage[];
1575
- hasMore: boolean;
1576
- cursor: string | null;
1577
- } | {
1578
- type: 'HISTORY_MORE_START';
1579
- } | {
1580
- type: 'HISTORY_MORE_DONE';
1581
- messages: ChatMessage[];
1582
- hasMore: boolean;
1583
- cursor: string | null;
1584
- } | {
1585
- type: 'MESSAGE_USER_ADD';
1586
- message: ChatMessage;
1587
- } | {
1588
- type: 'STREAM_START';
1589
- id: string;
1590
- createdAt?: number;
1591
- } | {
1592
- type: 'STREAM_CHUNK';
1593
- delta: string;
1594
- } | {
1595
- type: 'STREAM_TOOL_ACTIVITY';
1596
- tool: string;
1597
- } | {
1598
- type: 'TOOL_CALL_START';
1599
- messageId: string;
1600
- toolCall: ChatToolCall;
1601
- } | {
1602
- type: 'TOOL_CALL_DELTA';
1603
- messageId: string;
1604
- toolId: string;
1605
- delta: string;
1606
- } | {
1607
- type: 'TOOL_CALL_END';
1608
- messageId: string;
1609
- toolId: string;
1610
- output: unknown;
1611
- status: 'success' | 'error';
1612
- } | {
1613
- type: 'STREAM_DONE';
1614
- id: string;
1615
- tokensIn?: number;
1616
- tokensOut?: number;
1617
- sources?: ChatSource[];
1618
- } | {
1619
- type: 'STREAM_CANCELLED';
1620
- id: string;
1621
- partialText: string;
1622
- label?: string;
1623
- } | {
1624
- type: 'STREAM_ERROR';
1625
- id?: string;
1626
- message: string;
1627
- } | {
1628
- type: 'STREAM_CANCEL_PLACEHOLDER';
1629
- id: string;
1630
- } | {
1631
- type: 'STREAM_RESUME_EXISTING';
1632
- } | {
1633
- type: 'MESSAGE_EDIT';
1634
- id: string;
1635
- content: string;
1636
- } | {
1637
- type: 'MESSAGE_DELETE';
1638
- id: string;
1639
- } | {
1640
- type: 'MESSAGE_INJECT';
1641
- message: ChatMessage;
1642
- position?: 'append' | 'prepend';
1643
- } | {
1644
- type: 'MESSAGE_PATCH';
1645
- id: string;
1646
- patch: Partial<ChatMessage>;
1647
- } | {
1648
- type: 'MESSAGES_CLEAR';
1649
- } | {
1650
- type: 'ERROR_SET';
1651
- error: string | null;
1652
- } | {
1653
- type: 'ATTACHMENT_PROGRESS';
1654
- messageId: string;
1655
- attachmentId: string;
1656
- progress?: number;
1657
- status?: ChatAttachment['status'];
1658
- };
1659
- declare function reducer(state: ChatState, action: ChatAction): ChatState;
1660
-
1661
- interface UseChatConfig {
1662
- transport: ChatTransport;
1663
- initialSessionId?: string;
1664
- autoCreateSession?: boolean;
1665
- streaming?: boolean;
1666
- pageSize?: number;
1667
- onError?: (err: Error) => void;
1668
- /** Fires once an assistant message finishes streaming (or buffered send returns). */
1669
- onMessageEnd?: (msg: ChatMessage) => void;
1670
- /** Fires after a user message is added to the state (right before streaming starts). */
1671
- onMessageSent?: (msg: ChatMessage) => void;
1672
- /** Fires when the assistant placeholder is created (first byte / pre-stream). */
1673
- onStreamStart?: (assistantMessageId: string) => void;
1674
- metadata?: Record<string, unknown>;
1675
- /** Stamped on outgoing user messages as `message.sender`. */
1676
- userPersona?: ChatPersona;
1677
- /**
1678
- * Rewrite the outgoing message content right before it hits the
1679
- * transport — runs after the user bubble is added (so history shows
1680
- * the original) but before `transport.stream/send`. Sync or async.
1681
- * Return the original to opt out for that call.
1682
- *
1683
- * Use case: strip rich-display chips (e.g. mention links) so the LLM
1684
- * sees plain text, while the bubble keeps the chip rendering. Plan64.
1685
- */
1686
- onBeforeSend?: (content: string) => string | Promise<string>;
1687
- /**
1688
- * Enable verbose dev-mode logging (consola, namespace `chat:*`).
1689
- * Defaults to `isDev` from `@djangocfg/ui-core/lib`. Pass `false` to silence
1690
- * even in development; `true` to force on in production.
1691
- */
1692
- debug?: boolean;
1693
- }
1694
- interface UseChatReturn extends ChatState {
1695
- sendMessage: (content: string, attachments?: ChatAttachment[]) => Promise<void>;
1696
- cancelStream: () => void;
1697
- regenerate: (messageId?: string) => Promise<void>;
1698
- editMessage: (id: string, content: string) => Promise<void>;
1699
- deleteMessage: (id: string) => void;
1700
- clearMessages: () => void;
1701
- loadMore: () => Promise<void>;
1702
- newSession: () => Promise<void>;
1703
- lastError: Error | null;
1704
- /**
1705
- * Inject a complete message from outside (push notification, admin
1706
- * takeover, system notice). De-duped by id. Position defaults to
1707
- * `append` — pass `prepend` for retroactive inserts.
1708
- */
1709
- injectMessage: (message: ChatMessage, position?: 'append' | 'prepend') => void;
1710
- /**
1711
- * Patch fields of an existing message in place (e.g. live-edit the
1712
- * admin's last reply, mark a message as resolved). No-op if the id
1713
- * doesn't exist.
1714
- */
1715
- updateMessage: (id: string, patch: Partial<ChatMessage>) => void;
1716
- }
1717
- declare function useChat(config: UseChatConfig): UseChatReturn;
1718
-
1719
- interface UseChatLayoutConfig {
1720
- defaultMode?: ChatDisplayMode;
1721
- storageKey?: string;
1722
- sidebarStorageKey?: string;
1723
- reserveCssVar?: string;
1724
- defaultSidebarWidth?: number;
1725
- minSidebarWidth?: number;
1726
- maxSidebarWidth?: number;
1727
- /** Mobile breakpoint, e.g. '(max-width: 640px)'. */
1728
- mobileQuery?: string;
1729
- }
1730
- interface UseChatLayoutReturn {
1731
- mode: ChatDisplayMode;
1732
- setMode: (m: ChatDisplayMode) => void;
1733
- open: () => void;
1734
- close: () => void;
1735
- toggle: () => void;
1736
- sidebarWidth: number;
1737
- setSidebarWidth: (w: number) => void;
1738
- isMobile: boolean;
1739
- /** Mode after mobile collapse rules — sidebar/floating become fullscreen on mobile. */
1740
- effectiveMode: ChatDisplayMode;
1741
- }
1742
- declare function useChatLayout(config?: UseChatLayoutConfig): UseChatLayoutReturn;
1743
-
1744
- /** Imperative handle a composer (built-in or custom) registers so
1745
- * other parts of the chat tree can drive it without prop-drilling a
1746
- * ref. `focus()` is the baseline; the rest is optional so non-textarea
1747
- * hosts can keep returning `{ focus }` only.
1748
- *
1749
- * Implemented by:
1750
- * - built-in `<Composer>` — backed by `useChatComposer.textareaRef`.
1751
- * - `@djangocfg/ui-tools/markdown-editor` — backed by the TipTap
1752
- * editor (`editor.commands.focus('end')`).
1753
- * Consumed by `VoiceComposerSlot` for the focus / move-caret behaviour
1754
- * during live dictation.
1755
- */
1756
- interface ComposerHandle {
1757
- focus: () => void;
1758
- /** Move the caret to the very end of the input. */
1759
- moveCursorToEnd?: () => void;
1760
- /** Read the current draft text. Needed by voice dictation to anchor
1761
- * partial transcripts onto the user's already-typed prefix. */
1762
- getValue?: () => string;
1763
- /** Replace the current draft text. Voice dictation uses this to push
1764
- * interim + final transcripts into the composer without owning a
1765
- * controlled binding. */
1766
- setValue?: (value: string) => void;
1767
- }
1768
- interface ChatContextValue extends UseChatReturn {
1769
- layout: UseChatLayoutReturn;
1770
- config: ChatConfig;
1771
- labels: ChatLabels;
1772
- audio: UseChatAudioReturn;
1773
- /** True iff the host wired at least one ``audio.sounds[event]`` URL.
1774
- * Components like ``AudioToggle`` use this to auto-hide when there
1775
- * is nothing to mute. */
1776
- hasAudio: boolean;
1777
- /** Composer registry. The built-in `<Composer>` calls
1778
- * `registerComposer({ focus })` on mount; custom composers (e.g.
1779
- * cmdop's MarkdownEditor wrapper) do the same via the
1780
- * `useRegisterComposer` helper. Read it via `composer?.focus()` —
1781
- * null until any composer has mounted. Plan64 follow-up. */
1782
- composer: ComposerHandle | null;
1783
- registerComposer: (handle: ComposerHandle | null) => void;
1784
- }
1785
- interface ChatProviderProps {
1786
- transport: ChatTransport;
1787
- config?: ChatConfig;
1788
- initialSessionId?: string;
1789
- autoCreateSession?: boolean;
1790
- streaming?: boolean;
1791
- /** Audio-trigger configuration. Off by default (no `sounds` map). */
1792
- audio?: ChatAudioConfig;
1793
- /** Enable verbose dev logging via consola. Defaults to `isDev`. */
1794
- debug?: boolean;
1795
- /**
1796
- * Rewrite outgoing message content before it hits the transport.
1797
- * History bubble keeps the original; useful for stripping rich-
1798
- * display chips so the LLM sees plain text. See `useChat`.
1799
- */
1800
- onBeforeSend?: (content: string) => string | Promise<string>;
1801
- children?: ReactNode;
1802
- }
1803
- declare function ChatProvider({ transport, config, initialSessionId, autoCreateSession, streaming, audio, debug, onBeforeSend, children, }: ChatProviderProps): react_jsx_runtime.JSX.Element;
1804
- declare function useChatContext(): ChatContextValue;
1805
- declare function useChatContextOptional(): ChatContextValue | null;
1806
-
1807
- interface UseChatComposerOptions {
1808
- onSubmit: (content: string, attachments: ChatAttachment[]) => void | Promise<void>;
1809
- initialValue?: string;
1810
- maxLength?: number;
1811
- maxAttachments?: number;
1812
- disabled?: boolean;
1813
- /** 'enter' = Enter sends, Shift+Enter newline. 'cmd+enter' = Enter inserts newline, Cmd/Ctrl+Enter sends. */
1814
- submitOn?: 'enter' | 'cmd+enter';
1815
- history?: {
1816
- enabled?: boolean;
1817
- size?: number;
1818
- };
1819
- onPasteFiles?: (files: File[]) => void;
1820
- /**
1821
- * Persist the current draft to `sessionStorage` under this key. The
1822
- * draft is loaded once on mount (overrides `initialValue` if non-
1823
- * empty) and rewritten on every value change. Cleared on `reset()`.
1824
- *
1825
- * Pass a per-conversation id to keep separate drafts per chat. Pass
1826
- * `undefined` (default) to disable persistence — composer behaves
1827
- * exactly as before. Plan64.
1828
- */
1829
- persistKey?: string;
1830
- /**
1831
- * Skip pre-submit draft sanitation (trim + line-ending normalise +
1832
- * zero-width strip). Default `false` — sanitation matches what
1833
- * ChatGPT / Claude / Telegram ship and is what consumers want 99% of
1834
- * the time. Set to `true` for niche flows that need byte-perfect
1835
- * passthrough (clipboard inspector, raw-prompt debug tool).
1836
- */
1837
- preserveExactValue?: boolean;
1838
- }
1839
- interface UseChatComposerReturn {
1840
- value: string;
1841
- setValue: (next: string) => void;
1842
- attachments: ChatAttachment[];
1843
- addAttachment: (a: ChatAttachment) => void;
1844
- removeAttachment: (id: string) => void;
1845
- isSubmitting: boolean;
1846
- canSubmit: boolean;
1847
- submit: () => Promise<void>;
1848
- reset: () => void;
1849
- focus: () => void;
1850
- textareaRef: RefObject<HTMLTextAreaElement | null>;
1851
- textareaProps: {
1852
- ref: RefObject<HTMLTextAreaElement | null>;
1853
- value: string;
1854
- disabled: boolean;
1855
- onChange: (e: ChangeEvent<HTMLTextAreaElement>) => void;
1856
- onKeyDown: (e: KeyboardEvent<HTMLTextAreaElement>) => void;
1857
- onPaste: (e: ClipboardEvent<HTMLTextAreaElement>) => void;
1858
- };
1859
- recallPrevious: () => void;
1860
- recallNext: () => void;
1861
- }
1862
- declare function useChatComposer(options: UseChatComposerOptions): UseChatComposerReturn;
1863
-
1864
- type ComposerSize = 'sm' | 'md' | 'lg';
1865
- interface ComposerProps {
1866
- composer: UseChatComposerReturn;
1867
- placeholder?: string;
1868
- disabled?: boolean;
1869
- showAttachmentButton?: boolean;
1870
- onPickFiles?: () => void;
1871
- toolbarStart?: ReactNode;
1872
- toolbarEnd?: ReactNode;
1873
- attachmentTray?: ReactNode;
1874
- className?: string;
1875
- textareaClassName?: string;
1876
- /** Visual size — controls textarea height + button slot size.
1877
- *
1878
- * - ``sm`` — 32px slot, dense compact composer (admin sidebars, etc).
1879
- * - ``md`` — 36px slot, default. Same as the legacy fixed size.
1880
- * - ``lg`` — 48px slot, generous textarea. Use when the chat is
1881
- * the page's primary surface (onboarding, support).
1882
- */
1883
- size?: ComposerSize;
1884
- /** Show "Stop" button instead of "Send" while streaming. */
1885
- isStreaming?: boolean;
1886
- onCancel?: () => void;
1887
- }
1888
- declare const Composer: react.ForwardRefExoticComponent<ComposerProps & react.RefAttributes<HTMLDivElement>>;
1889
-
1890
- interface AttachmentRendererArgs {
1891
- attachment: ChatAttachment;
1892
- /** True when shown inside the composer's staging tray (denser layout). */
1893
- isInComposer: boolean;
1894
- onClick?: () => void;
1895
- onRemove?: () => void;
1896
- }
1897
- type AttachmentRenderer = (args: AttachmentRendererArgs) => ReactNode;
1898
- interface AttachmentRendererMap {
1899
- image?: AttachmentRenderer;
1900
- audio?: AttachmentRenderer;
1901
- video?: AttachmentRenderer;
1902
- file?: AttachmentRenderer;
1903
- /** Fallback renderer when no per-type entry matched. */
1904
- default?: AttachmentRenderer;
1905
- }
1906
- interface CommonProps {
1907
- attachments: ChatAttachment[];
1908
- maxVisible?: number;
1909
- onClick?: (a: ChatAttachment) => void;
1910
- onRemove?: (a: ChatAttachment) => void;
1911
- isInComposer?: boolean;
1912
- className?: string;
1913
- }
1914
- interface AttachmentsGridProps extends CommonProps {
1915
- layout?: 'wrap' | 'grid';
1916
- }
1917
- declare function AttachmentsGrid({ attachments, maxVisible, onClick, onRemove, isInComposer, layout, className, }: AttachmentsGridProps): react_jsx_runtime.JSX.Element;
1918
- interface AttachmentsListProps extends CommonProps {
1919
- /** Per-type renderer overrides. Falls back to the default tile. */
1920
- renderers?: AttachmentRendererMap;
1921
- }
1922
- declare function AttachmentsList({ attachments, maxVisible, onClick, onRemove, renderers, isInComposer, className, }: AttachmentsListProps): react_jsx_runtime.JSX.Element;
1923
- interface AttachmentsProps extends CommonProps {
1924
- layout?: 'grid' | 'row';
1925
- renderers?: AttachmentRendererMap;
1926
- }
1927
- declare function Attachments(props: AttachmentsProps): react_jsx_runtime.JSX.Element;
1928
-
1929
- type ToolPayloadKind = 'input' | 'output' | 'streaming';
1930
- interface ToolCallsProps {
1931
- calls: ChatToolCall[];
1932
- /** Open every panel up-front. Default: false (panels are closed). */
1933
- defaultExpanded?: boolean;
1934
- /** Auto-open while a tool is running, then auto-close on completion.
1935
- * User toggles after that are remembered. Default: true. */
1936
- expandWhileStreaming?: boolean;
1937
- /** Override how the tool input payload is rendered. Receives the raw value. */
1938
- renderInput?: (input: unknown, call: ChatToolCall) => ReactNode;
1939
- /** Override how the tool output payload is rendered. */
1940
- renderOutput?: (output: unknown, call: ChatToolCall) => ReactNode;
1941
- /** Override how the live `streamingText` is rendered. */
1942
- renderStreaming?: (text: string, call: ChatToolCall) => ReactNode;
1943
- /** Single override for all three; specific renderers above take precedence. */
1944
- renderPayload?: (value: unknown, kind: ToolPayloadKind, call: ChatToolCall) => ReactNode;
1945
- /**
1946
- * Rendered once **after** all tool-call panels — always visible, outside
1947
- * the collapsible panels. Use for rich UI derived from tool outputs (e.g.
1948
- * vehicle cards, map pins, tax breakdowns). Receives the full calls array
1949
- * so the renderer can aggregate across multiple tool calls.
1950
- */
1951
- renderAfterCalls?: (calls: ChatToolCall[]) => ReactNode;
1952
- /**
1953
- * Custom renderer for each individual tool-call panel. When provided,
1954
- * replaces the default collapsible `<ToolCallItem>`. Return `null` to
1955
- * suppress a specific call while still letting others render.
1956
- */
1957
- renderToolCall?: (call: ChatToolCall) => ReactNode;
1958
- /**
1959
- * When `true`, the collapsible tool-call panels are not rendered at all.
1960
- * `renderAfterCalls` still runs — use together to show only rich UI with
1961
- * no raw accordion panels visible.
1962
- */
1963
- hideToolCalls?: boolean;
1964
- className?: string;
1965
- }
1966
- declare function ToolCalls({ calls, defaultExpanded, expandWhileStreaming, renderInput, renderOutput, renderStreaming, renderPayload, renderAfterCalls, renderToolCall, hideToolCalls, className, }: ToolCallsProps): react_jsx_runtime.JSX.Element;
1967
-
1968
- interface ChatRootProps {
1969
- transport: ChatTransport;
1970
- config?: ChatConfig;
1971
- initialSessionId?: string;
1972
- autoCreateSession?: boolean;
1973
- streaming?: boolean;
1974
- /** Audio-trigger configuration. Off by default (no `sounds` map). */
1975
- audio?: ChatAudioConfig;
1976
- /**
1977
- * Verbose dev-mode logging via `consola` (namespace `chat:*`).
1978
- * Defaults to `isDev` from `@djangocfg/ui-core/lib`. Pass `false` to silence
1979
- * even in development, or `true` to force on in production for debugging.
1980
- */
1981
- debug?: boolean;
1982
- className?: string;
1983
- /** Sticky banner above the message list (e.g. quota warning). */
1984
- banner?: ReactNode;
1985
- /** Header row below the banner — title / actions / session switcher. */
1986
- header?: ReactNode;
1987
- /** Footer slot below the composer (disclaimers, model picker). */
1988
- footer?: ReactNode;
1989
- /** Replaces the default `<EmptyState>` rendered when the conversation is empty. */
1990
- empty?: ReactNode;
1991
- /** Slot left of the textarea inside `<Composer>`. */
1992
- composerToolbarStart?: ReactNode;
1993
- /** Slot right of the textarea inside `<Composer>`. */
1994
- composerToolbarEnd?: ReactNode;
1995
- /** Replaces the default attachment tray inside `<Composer>`. */
1996
- composerAttachmentTray?: ReactNode;
1997
- /** Replaces the default `<JumpToLatest>` floating pill. */
1998
- jumpToLatest?: ReactNode;
1999
- /** Replace `<MessageBubble>` per message. */
2000
- renderMessage?: (m: ChatMessage, i: number) => ReactNode;
2001
- /** Render the header lazily — receives the chat context. */
2002
- renderHeader?: (ctx: ChatContextValue) => ReactNode;
2003
- /** Render the empty-state lazily — receives a `setValue` to seed the composer. */
2004
- renderEmpty?: (api: {
2005
- setValue: (v: string) => void;
2006
- focus: () => void;
2007
- }) => ReactNode;
2008
- /** Forwarded into `<MessageBubble toolCallsProps>` so hosts can swap payload renderers. */
2009
- toolCallsProps?: Omit<ToolCallsProps, 'calls'>;
2010
- /** Per-type attachment renderers — `{ image, audio, video, file, default }`. */
2011
- attachmentRenderers?: AttachmentRendererMap;
2012
- /** Called when an attachment tile is clicked (e.g. open lightbox). */
2013
- onAttachmentOpen?: (attachment: ChatAttachment) => void;
2014
- /** Show the paperclip "attach" button in the composer. */
2015
- showAttachmentButton?: boolean;
2016
- /** Called when the user clicks the attach button (host opens its file picker). */
2017
- onPickFiles?: () => void;
2018
- /** Hide the composer input area entirely (e.g. while waiting for human approval). */
2019
- hideComposer?: boolean;
2020
- /** Composer size variant. Default ``md`` (36px slot). Use ``lg`` for primary
2021
- * surfaces (onboarding, full-page chat), ``sm`` for dense sidebars. */
2022
- composerSize?: ComposerSize;
2023
- /** Extra className forwarded to the `<MessageList>` scroll container.
2024
- * Use to add padding inside the scroll area so the scrollbar stays flush
2025
- * with the edge (e.g. `"px-6 pt-6 sm:px-8"`). */
2026
- listClassName?: string;
2027
- /** Extra className forwarded to the `<Composer>` wrapper div. */
2028
- composerClassName?: string;
2029
- /**
2030
- * Click in the message area → focus the composer (Slack / ChatGPT / Linear).
2031
- * Honours selection drag, interactive elements, and touch input.
2032
- * @default true
2033
- */
2034
- focusOnEmptyClick?: boolean;
2035
- }
2036
- declare function ChatRoot(props: ChatRootProps): react_jsx_runtime.JSX.Element;
2037
-
2038
- type ChatFABPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
2039
- type ChatFABVariant = 'simple' | 'animated' | 'glass';
2040
- type ChatFABSize = 'sm' | 'md' | 'lg' | 'responsive';
2041
- interface ChatFABProps {
2042
- /** Click handler — typically toggles a `ChatDock`. */
2043
- onClick: () => void;
2044
- /** Accessible label. */
2045
- ariaLabel?: string;
2046
- /** Icon inside the FAB. Defaults to a bot glyph. */
2047
- icon?: ReactNode;
2048
- /** Visual style. @default 'simple' */
2049
- variant?: ChatFABVariant;
2050
- /** Button size. @default 'md' */
2051
- size?: ChatFABSize;
2052
- /** Fixed-screen position. @default 'bottom-right' */
2053
- position?: ChatFABPosition;
2054
- /** Pixel offset from screen edges. @default 24 */
2055
- offset?: number;
2056
- /** z-index for the button. @default 9999 */
2057
- zIndex?: number;
2058
- /** Show a small attention dot (unread / new). */
2059
- pulse?: boolean;
2060
- /**
2061
- * Numeric badge — unread count. Numbers > 9 render as "9+".
2062
- * Overrides `pulse` when both set.
2063
- */
2064
- badge?: number;
2065
- /** Hover tooltip text. Shows next to the FAB on hover/focus. */
2066
- tooltip?: string;
2067
- /**
2068
- * Render in-place (no fixed positioning) so the FAB sits inline in the
2069
- * normal document flow. Useful for stories, screenshots, and previews
2070
- * inside a contained playground panel. @default false
2071
- */
2072
- inline?: boolean;
2073
- /** Override classes on the button itself. */
2074
- className?: string;
2075
- /** Extra style on the button (caller-controlled overrides). */
2076
- style?: CSSProperties;
2077
- }
2078
- /**
2079
- * Floating action button for opening a chat dock. Pure presentation — owns
2080
- * no state. Wire it to whatever toggles your dock open.
2081
- *
2082
- * For the common "FAB + dock + hotkey" composition, use `<ChatLauncher>` —
2083
- * this primitive is only useful when you need custom triggering.
2084
- */
2085
- declare function ChatFAB({ onClick, ariaLabel, icon, variant, size, position, offset, zIndex, pulse, badge, tooltip, inline, className, style, }: ChatFABProps): react_jsx_runtime.JSX.Element;
2086
-
2087
- type ChatDockMode = 'popover' | 'side';
2088
- type ChatDockSide = 'left' | 'right';
2089
- interface ChatDockProps {
2090
- /** Controlled open state. */
2091
- open: boolean;
2092
- /** Called when the user clicks the close button. */
2093
- onClose: () => void;
2094
- /** Dock contents (typically a `<Chat>` component). */
2095
- children: ReactNode;
2096
- /**
2097
- * Visual mode.
2098
- * - `popover` (default): floating card anchored to a corner, fixed size, FAB-style.
2099
- * - `side`: docked panel pinned to the left/right edge, full viewport height.
2100
- */
2101
- mode?: ChatDockMode;
2102
- /** Side for `mode='side'`. @default 'right' */
2103
- side?: ChatDockSide;
2104
- /** Header title text. */
2105
- title?: ReactNode;
2106
- /** Header icon. Defaults to a bot glyph. */
2107
- icon?: ReactNode;
2108
- /**
2109
- * Header actions slot (right side, before the close button).
2110
- * Use `ChatHeaderActionButton` to keep visual consistency.
2111
- */
2112
- headerActions?: ReactNode;
2113
- /** Hide the header entirely (you render your own inside `children`). */
2114
- hideHeader?: boolean;
2115
- /** ARIA label for the close button. @default 'Close' */
2116
- closeLabel?: string;
2117
- /** Dock width in px. Clamped to viewport. @default 480 (popover) / 420 (side) */
2118
- width?: number;
2119
- /** Dock height in px. Only used in `popover` mode. @default 720 */
2120
- height?: number;
2121
- /** Which screen corner to dock to in `popover` mode. @default 'bottom-right' */
2122
- position?: ChatFABPosition;
2123
- /** Offset from screen edges in px (popover only). @default 24 / 96 */
2124
- offset?: {
2125
- horizontal?: number;
2126
- vertical?: number;
2127
- };
2128
- /** Transition duration in ms — should match CSS animation. @default 200 */
2129
- exitDurationMs?: number;
2130
- /** z-index. @default 10000 */
2131
- zIndex?: number;
2132
- /** Accessible dialog label. */
2133
- ariaLabel?: string;
2134
- /** Extra classes on the dock container. */
2135
- className?: string;
2136
- /**
2137
- * Take over the full viewport on mobile (< 768px). Applies to both modes.
2138
- * @default true
2139
- */
2140
- mobileFullscreen?: boolean;
2141
- /**
2142
- * Render in-place (not in `document.body` via a portal). Useful for stories,
2143
- * screenshots, or wrapping the dock inside a custom container. @default false
2144
- */
2145
- disablePortal?: boolean;
2146
- /**
2147
- * Drop fixed positioning entirely — the dock renders as a normal flow
2148
- * element sized by `width`/`height`. Combine with `disablePortal` for
2149
- * stories/previews where the dock should sit inside the panel instead
2150
- * of attaching to the viewport. @default false
2151
- */
2152
- inline?: boolean;
2153
- /**
2154
- * In `mode='side'`, reserve space on the document body so page content
2155
- * isn't covered by the dock. Sets `padding-{side}` on `<body>` while
2156
- * the dock is open and exposes the width via the `--chat-dock-reserve`
2157
- * CSS variable for custom layouts. @default true (when mode='side')
2158
- */
2159
- reserveBodySpace?: boolean;
2160
- }
2161
- /**
2162
- * Fixed-position chat surface. Two modes:
2163
- *
2164
- * - `popover` — floating card anchored to a corner. Companion to `<ChatFAB>`.
2165
- * - `side` — full-height panel pinned to the left/right edge. App-shell style.
2166
- *
2167
- * Renders only when `open` is true (plus the leave-transition tail). Uses
2168
- * `useChatPresence` for the four-phase mount/animate/unmount cycle.
2169
- */
2170
- 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;
2171
-
2172
- interface ChatHeaderProps {
2173
- /** Window title text. */
2174
- title?: ReactNode;
2175
- /** Icon next to the title. Defaults to a bot glyph. */
2176
- icon?: ReactNode;
2177
- /**
2178
- * Action slot — appears to the right of the title, before the close button.
2179
- * Use for reset / settings / minimize / etc. Compose with `ChatHeaderActionButton`.
2180
- */
2181
- actions?: ReactNode;
2182
- /** Show the close (×) button. @default true */
2183
- showClose?: boolean;
2184
- /** Close click handler. */
2185
- onClose?: () => void;
2186
- /** ARIA label for the close button. @default 'Close' */
2187
- closeLabel?: string;
2188
- /** Replace the close button entirely (rare — most hosts want the default). */
2189
- closeSlot?: ReactNode;
2190
- /** Extra classes on the `<header>` element. */
2191
- className?: string;
2192
- }
2193
- /**
2194
- * Standalone chat header — title + icon + action slot + close button.
2195
- *
2196
- * Used by `<ChatDock>` automatically, but can be rendered standalone when
2197
- * the host owns the chat container (e.g. embedded inline in a page).
2198
- */
2199
- declare function ChatHeader({ title, icon, actions, showClose, onClose, closeLabel, closeSlot, className, }: ChatHeaderProps): react_jsx_runtime.JSX.Element;
2200
-
2201
- interface ChatHeaderActionButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
2202
- /** Icon (required). */
2203
- icon: ReactNode;
2204
- /** Accessible label + native tooltip. */
2205
- ariaLabel: string;
2206
- /** Optional unread / status badge — small number on top-right. */
2207
- badge?: number;
2208
- /** Mark as destructive — uses destructive hover tokens. */
2209
- destructive?: boolean;
2210
- /** Optional visual loading state (e.g. while reset is in flight). */
2211
- loading?: boolean;
2212
- }
2213
- /**
2214
- * Compact icon button for the chat header actions slot.
2215
- *
2216
- * Standard chrome: 28×28 ghost button, hover bg-accent, focus ring, optional
2217
- * destructive variant, optional numeric badge for unread / pending.
2218
- *
2219
- * @example
2220
- * ```tsx
2221
- * <ChatHeader
2222
- * title="Assistant"
2223
- * onClose={close}
2224
- * actions={
2225
- * <>
2226
- * <ChatHeaderActionButton
2227
- * icon={<RotateCcw className="h-3.5 w-3.5" />}
2228
- * ariaLabel="Clear context"
2229
- * onClick={handleReset}
2230
- * loading={isResetting}
2231
- * />
2232
- * <ChatHeaderActionButton
2233
- * icon={<Settings className="h-3.5 w-3.5" />}
2234
- * ariaLabel="Settings"
2235
- * onClick={openSettings}
2236
- * />
2237
- * </>
2238
- * }
2239
- * />
2240
- * ```
2241
- */
2242
- declare const ChatHeaderActionButton: react.ForwardRefExoticComponent<ChatHeaderActionButtonProps & react.RefAttributes<HTMLButtonElement>>;
2243
-
2244
- interface ChatHeaderModeToggleProps {
2245
- /** Current dock mode. */
2246
- mode: ChatDockMode;
2247
- /** Toggle handler. Wire to `useChatDockPrefs().toggleMode`. */
2248
- onToggle: () => void;
2249
- /** Override aria/tooltip label for popover→side. */
2250
- expandLabel?: string;
2251
- /** Override aria/tooltip label for side→popover. */
2252
- collapseLabel?: string;
2253
- /**
2254
- * Always render — useful for stories. By default the toggle hides itself on
2255
- * viewports below `lg` (1024px) since side mode falls back to popover there.
2256
- */
2257
- forceVisible?: boolean;
2258
- }
2259
- /**
2260
- * "Dock to side" / "back to popover" toggle.
2261
- *
2262
- * Side mode is desktop-only — on viewports below `lg` (1024px) `<ChatDock>`
2263
- * silently falls back to popover anyway, so the toggle has nothing to do
2264
- * and auto-hides. Pass `forceVisible` to override (e.g. in stories).
2265
- */
2266
- declare function ChatHeaderModeToggle({ mode, onToggle, expandLabel, collapseLabel, forceVisible, }: ChatHeaderModeToggleProps): react_jsx_runtime.JSX.Element;
2267
-
2268
- interface ChatHeaderAudioToggleProps {
2269
- /** Current muted state. */
2270
- muted: boolean;
2271
- /** Toggle handler. Wire to `useChatAudio().setMuted` or `toggleMute`. */
2272
- onToggle: () => void;
2273
- /** Override tooltip label for muted → unmuted. */
2274
- unmuteLabel?: string;
2275
- /** Override tooltip label for unmuted → muted. */
2276
- muteLabel?: string;
2277
- }
2278
- /**
2279
- * Mute / unmute notification sounds. Drop into a `<ChatHeader>` actions
2280
- * slot or into `<ChatDock headerActions>`.
2281
- *
2282
- * @example
2283
- * ```tsx
2284
- * const audio = useChatAudio({ sounds: {...} });
2285
- * <ChatHeaderAudioToggle muted={audio.muted} onToggle={() => audio.setMuted(!audio.muted)} />
2286
- * ```
2287
- */
2288
- declare function ChatHeaderAudioToggle({ muted, onToggle, unmuteLabel, muteLabel, }: ChatHeaderAudioToggleProps): react_jsx_runtime.JSX.Element;
2289
-
2290
- interface ChatHeaderResetButtonProps {
2291
- /**
2292
- * Backend reset call. Should resolve to `true` on success.
2293
- * Plugged into `useChatReset` for in-flight state.
2294
- */
2295
- onReset: () => Promise<boolean>;
2296
- /** Called after a successful reset (e.g. clear local messages, refetch). */
2297
- onSuccess?: () => void;
2298
- /** Called when reset fails (returned `false` or threw). */
2299
- onError?: (error?: unknown) => void;
2300
- /**
2301
- * Show a `window.dialog.confirm` before calling `onReset`. @default true
2302
- *
2303
- * Requires the host to mount `<DialogProvider>` from `@djangocfg/ui-core`
2304
- * — it installs the `window.dialog` API used here.
2305
- */
2306
- confirm?: boolean;
2307
- /** Confirm dialog title. */
2308
- confirmTitle?: string;
2309
- /** Confirm dialog message. */
2310
- confirmMessage?: string;
2311
- /** Override tooltip / aria label. */
2312
- ariaLabel?: string;
2313
- }
2314
- /**
2315
- * Standard chat-reset action: prompts the user via `window.dialog.confirm`,
2316
- * then runs the backend reset call through `useChatReset` so the button
2317
- * spins while it's in flight.
2318
- *
2319
- * @example
2320
- * ```tsx
2321
- * <ChatHeaderResetButton
2322
- * onReset={api.clearChat}
2323
- * onSuccess={() => chat.clearMessages()}
2324
- * />
2325
- * ```
2326
- */
2327
- declare function ChatHeaderResetButton({ onReset, onSuccess, onError, confirm, confirmTitle, confirmMessage, ariaLabel, }: ChatHeaderResetButtonProps): react_jsx_runtime.JSX.Element;
2328
-
2329
- interface ChatHeaderLanguageButtonProps {
2330
- /** Override aria-label. Default "Speech language". */
2331
- ariaLabel?: string;
2332
- /**
2333
- * Subset of BCP-47 tags to offer. Default: every entry from the
2334
- * Web Speech catalogue (~66 tags incl. regional variants). Pass a
2335
- * tighter list when your backend STT only supports a subset.
2336
- */
2337
- allowedTags?: string[];
2338
- /** Hide the globe-fallback icon when no flag resolves. */
2339
- hideFallbackIcon?: boolean;
2340
- className?: string;
2341
- }
2342
- /**
2343
- * Compact flag-button language picker for the chat header. Built on
2344
- * top of the ui-core `<Combobox>` — searchable autocomplete with
2345
- * flags, ~66 BCP-47 tags from the official Chrome Web Speech demo, and
2346
- * a custom 28×28 trigger via `renderTrigger`.
2347
- *
2348
- * The selection persists into `useSpeechPrefs` (zustand+localStorage)
2349
- * so `useSpeechRecognition` picks it up as the second-priority resolver
2350
- * value (above i18n locale, below an explicit `language` prop).
2351
- */
2352
- declare function ChatHeaderLanguageButton({ ariaLabel, allowedTags, hideFallbackIcon, className, }: ChatHeaderLanguageButtonProps): react.ReactElement;
2353
-
2354
- interface ChatGreetingProps {
2355
- /** Controlled visibility — usually `!chatOpen && !userDismissed`. */
2356
- open: boolean;
2357
- /** Greeting text. Pass a string for the default bubble, or any ReactNode. */
2358
- children: ReactNode;
2359
- /** Click handler — typically opens the chat. Bubble is clickable when set. */
2360
- onClick?: () => void;
2361
- /** Close (×) button handler — typically marks the greeting as dismissed. */
2362
- onDismiss?: () => void;
2363
- /** Anchor relative to a FAB on the same side. @default 'bottom-right' */
2364
- position?: ChatFABPosition;
2365
- /**
2366
- * Horizontal pixel offset matching the FAB's `offset` prop, so the greeting
2367
- * lines up under the FAB. @default 24
2368
- */
2369
- fabOffset?: number;
2370
- /**
2371
- * Vertical pixel offset above/below the FAB centerline. @default 96
2372
- * (room for an `md` FAB plus a small gap).
2373
- */
2374
- fabClearance?: number;
2375
- /** Delay before the greeting appears, in ms. @default 1500 */
2376
- delayMs?: number;
2377
- /** z-index. @default 9998 (just below the default FAB at 9999). */
2378
- zIndex?: number;
2379
- /** Override classes on the bubble. */
2380
- className?: string;
2381
- /** Override styles on the bubble. */
2382
- style?: CSSProperties;
2383
- /** Optional sender avatar / icon shown on the left. */
2384
- avatar?: ReactNode;
2385
- /** Optional sender label rendered above the text. */
2386
- senderName?: string;
2387
- /** ARIA label for the dismiss button. @default 'Dismiss' */
2388
- dismissLabel?: string;
2389
- /**
2390
- * Render in-place (no fixed positioning). Useful for stories and inline previews.
2391
- * @default false
2392
- */
2393
- inline?: boolean;
2394
- }
2395
- /**
2396
- * Greeting bubble shown next to a `ChatFAB` to invite the user to start a
2397
- * conversation (LiveChat / Intercom-style proactive prompt).
2398
- *
2399
- * Renders fixed-position, anchored to the same corner as the FAB. Owns its
2400
- * own delayed-mount + presence animation. Hide on chat open and/or after
2401
- * user dismissal.
2402
- *
2403
- * @example
2404
- * ```tsx
2405
- * const [open, setOpen] = useState(false);
2406
- * const [dismissed, setDismissed] = useState(false);
2407
- *
2408
- * <ChatLauncher
2409
- * open={open}
2410
- * onOpenChange={setOpen}
2411
- * fab={{ variant: 'animated' }}
2412
- * dock={{ title: 'Support' }}
2413
- * >
2414
- * <SupportChat />
2415
- * </ChatLauncher>
2416
- *
2417
- * <ChatGreeting
2418
- * open={!open && !dismissed}
2419
- * onClick={() => setOpen(true)}
2420
- * onDismiss={() => setDismissed(true)}
2421
- * senderName="Anna from Support"
2422
- * delayMs={2000}
2423
- * >
2424
- * Hi! 👋 Got a question? I'm here to help.
2425
- * </ChatGreeting>
2426
- * ```
2427
- */
2428
- declare function ChatGreeting({ open, children, onClick, onDismiss, position, fabOffset, fabClearance, delayMs, zIndex, className, style, avatar, senderName, dismissLabel, inline, }: ChatGreetingProps): react_jsx_runtime.JSX.Element;
2429
-
2430
- interface ChatUnreadPreviewProps {
2431
- /** Controlled — usually `!dockOpen && !!message`. */
2432
- open: boolean;
2433
- /** Inbound message to preview. `null` hides the bubble. */
2434
- message: ChatMessage | null;
2435
- /** Tap → open chat + mark read. */
2436
- onClick?: () => void;
2437
- /** × → mark read without opening. */
2438
- onDismiss?: () => void;
2439
- /** Anchor corner — match the FAB so the bubble sits above it. @default 'bottom-right' */
2440
- position?: ChatFABPosition;
2441
- /** Horizontal offset from screen edge, matches the FAB. @default 24 */
2442
- fabOffset?: number;
2443
- /** Vertical clearance above/below the FAB. @default 96 */
2444
- fabClearance?: number;
2445
- /** Lines of body text before ellipsis. @default 2 */
2446
- truncate?: number;
2447
- /** z-index. @default 9998 */
2448
- zIndex?: number;
2449
- /** Render in-place (stories / previews). @default false */
2450
- inline?: boolean;
2451
- /** Override classes on the bubble. */
2452
- className?: string;
2453
- /** Override styles on the bubble. */
2454
- style?: CSSProperties;
2455
- /** ARIA label for the dismiss button. @default 'Mark as read' */
2456
- dismissLabel?: string;
2457
- /** Override the avatar — defaults to derived from `message.sender`. */
2458
- avatar?: ReactNode;
2459
- /** Override the sender label — defaults to `message.sender?.name`. */
2460
- senderName?: string;
2461
- }
2462
- /**
2463
- * Push-notification bubble next to the chat FAB.
2464
- *
2465
- * Shows the last inbound message while the chat is closed —
2466
- * Intercom / LiveChat-style. Tap → open chat (host wires `onClick`).
2467
- * Dismiss × → keep chat closed but stop nagging.
2468
- *
2469
- * Pair with `useChatUnread()` (inside `<ChatProvider>`) for state.
2470
- */
2471
- declare function ChatUnreadPreview({ open, message, onClick, onDismiss, position, fabOffset, fabClearance, truncate, zIndex, inline, className, style, dismissLabel, avatar, senderName, }: ChatUnreadPreviewProps): react_jsx_runtime.JSX.Element;
2472
-
2473
- interface ChatLauncherHotkey {
2474
- /** Key (case-sensitive single char or named like 'Escape'). */
2475
- key: string;
2476
- /** Require Cmd (mac) or Ctrl (other). */
2477
- meta?: boolean;
2478
- /** Require Shift. */
2479
- shift?: boolean;
2480
- /** Require Alt. */
2481
- alt?: boolean;
2482
- }
2483
- interface ChatLauncherGreeting extends Omit<ChatGreetingProps, 'open' | 'onClick' | 'onDismiss' | 'position' | 'fabOffset' | 'children'> {
2484
- /** Greeting body — string for the default style, or any ReactNode. */
2485
- content: ReactNode;
2486
- /** Persistence key for "user dismissed this greeting" in `localStorage`. Pass `null` to disable persistence. @default null */
2487
- dismissStorageKey?: string | null;
2488
- /** Hide the greeting once the user opens the chat. @default true */
2489
- hideOnOpen?: boolean;
2490
- }
2491
- interface ChatLauncherProps {
2492
- /** Dock contents — typically a `<Chat>` instance. */
2493
- children: ReactNode;
2494
- /** FAB customization (icon, position, label, pulse, badge, tooltip, variant, size). */
2495
- fab?: Omit<ChatFABProps, 'onClick'>;
2496
- /** Dock customization (size, title, position, transition, mobileFullscreen). */
2497
- dock?: Omit<ChatDockProps, 'open' | 'onClose' | 'children'>;
2498
- /**
2499
- * Proactive greeting bubble shown next to the FAB before the user opens the chat.
2500
- * Set to a string or full config object. Omit to disable.
2501
- */
2502
- greeting?: string | ChatLauncherGreeting;
2503
- /** Open/close via a keyboard shortcut. */
2504
- hotkey?: ChatLauncherHotkey;
2505
- /** Initial open state for uncontrolled mode. @default false */
2506
- defaultOpen?: boolean;
2507
- /** Controlled open state (pair with `onOpenChange`). */
2508
- open?: boolean;
2509
- /** Controlled open state setter. */
2510
- onOpenChange?: (open: boolean) => void;
2511
- /**
2512
- * Focus the composer textarea when the dock opens. Saves a click for
2513
- * every "FAB → start typing" interaction. @default true
2514
- */
2515
- autoFocusComposerOnOpen?: boolean;
2516
- /**
2517
- * Close the dock on `Escape`. Mirrors standard popover / drawer UX.
2518
- * Set to `false` to disable (e.g. if you want Escape to do something
2519
- * else inside the chat). @default true
2520
- */
2521
- closeOnEscape?: boolean;
2522
- /**
2523
- * Last inbound message (admin reply / system notice / agent push) the
2524
- * user hasn't seen yet. Drives the `<ChatUnreadPreview>` bubble next
2525
- * to the FAB and (by default) the FAB badge.
2526
- *
2527
- * Source it from `useChatUnread()` inside your `<ChatProvider>`.
2528
- */
2529
- unreadMessage?: ChatMessage | null;
2530
- /**
2531
- * Called when the user opens the chat via FAB/preview/hotkey or
2532
- * dismisses the preview with ×. Wire to `useChatUnread().markRead`.
2533
- */
2534
- onMarkRead?: () => void;
2535
- /**
2536
- * Customize the unread bubble (`truncate`, `dismissLabel`, …).
2537
- * `open`/`message`/`onClick`/`onDismiss`/`position`/`fabOffset` are
2538
- * wired automatically.
2539
- */
2540
- unreadPreview?: Omit<ChatUnreadPreviewProps, 'open' | 'message' | 'onClick' | 'onDismiss' | 'position' | 'fabOffset'>;
2541
- /**
2542
- * Auto-inject a mute / unmute button into the header. Pass the
2543
- * `useChatAudio()` (or any compatible `{ muted, toggleMute }`)
2544
- * instance — the launcher renders `<ChatHeaderAudioToggle>` in the
2545
- * header's actions slot when audio is actually configured (not silent).
2546
- *
2547
- * Hosts that manage their own header can ignore this prop and render
2548
- * `<ChatHeaderAudioToggle>` directly.
2549
- */
2550
- audio?: {
2551
- muted: boolean;
2552
- toggleMute: () => void;
2553
- isSilent?: boolean;
2554
- } | null;
2555
- /**
2556
- * Suppress the auto-injected audio toggle even when `audio` is passed.
2557
- * @default false
2558
- */
2559
- hideAudioToggle?: boolean;
2560
- }
2561
- /**
2562
- * Floating chat launcher = FAB + Dock + presence + optional greeting + hotkey.
2563
- *
2564
- * 99% of hosts use this directly. For non-FAB triggers (e.g. an inline
2565
- * link in the page) compose `<ChatDock>` with your own button.
2566
- */
2567
- 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;
2568
-
2569
- type ChatPresencePhase = 'hidden' | 'entering' | 'visible' | 'leaving';
2570
- /**
2571
- * Presence state machine for floating popovers.
2572
- *
2573
- * Drives a four-phase lifecycle so enter/leave CSS transitions actually fire:
2574
- *
2575
- * hidden → entering (mount, transition class starts) → visible
2576
- * visible → leaving (transition runs) → hidden (unmount)
2577
- *
2578
- * Mounting in `entering` and ticking to `visible` on the next paint is what
2579
- * lets transition classes animate. Without it the element appears already
2580
- * at its final state and CSS transitions never observe a change.
2581
- *
2582
- * @param open - controlled open state
2583
- * @param exitDurationMs - how long the leave transition runs; should match CSS
2584
- */
2585
- declare function useChatPresence(open: boolean, exitDurationMs?: number): ChatPresencePhase;
2586
-
2587
- /**
2588
- * Chat defaults and constants.
2589
- */
2590
- declare const STORAGE_KEYS: {
2591
- readonly mode: "djc-chat-mode";
2592
- readonly sidebarWidth: "djc-chat-sidebar-width";
2593
- readonly composerHistory: "djc-chat-composer-history";
2594
- };
2595
- declare const CSS_VARS: {
2596
- readonly reserve: "--djc-chat-reserve";
2597
- };
2598
- declare const DEFAULT_Z_INDEX = 9000;
2599
- declare const LIMITS: {
2600
- /** Max characters per single message. */
2601
- readonly messageMaxLength: 8000;
2602
- /** Max attachments per message. */
2603
- readonly attachmentsMax: 10;
2604
- /** Composer history slots. */
2605
- readonly composerHistorySize: 50;
2606
- /** Coalesce stream tokens within this window before dispatching. */
2607
- readonly streamCoalesceMs: 16;
2608
- /** Default history page size. */
2609
- readonly pageSize: 50;
2610
- /** Virtualize list when >= this many messages (host-controlled threshold). */
2611
- readonly virtualizeThreshold: 50;
2612
- /** SSE idle timeout. */
2613
- readonly sseIdleMs: 45000;
2614
- };
2615
- declare const DEFAULT_SIDEBAR: {
2616
- readonly width: 420;
2617
- readonly min: 320;
2618
- readonly max: 720;
2619
- };
2620
- declare const HOTKEYS: {
2621
- readonly send: "mod+enter";
2622
- readonly cancel: "esc";
2623
- readonly newChat: "mod+shift+n";
2624
- readonly toggleOpen: "mod+/";
2625
- readonly focusComposer: "mod+l";
2626
- };
2627
- declare const CHAT_EVENT_NAME = "djc:chat:send";
2628
- interface ChatEventDetail {
2629
- content: string;
2630
- sessionId?: string;
2631
- attachments?: unknown[];
2632
- metadata?: Record<string, unknown>;
2633
- }
2634
-
2635
- /**
2636
- * ID generation. Uses crypto.randomUUID when available with a fallback
2637
- * for older environments (and SSR bundles that may not have crypto).
2638
- */
2639
- declare function createId(prefix?: string): string;
2640
-
2641
- /**
2642
- * Token coalescer. Buffers stream tokens within a small time window before
2643
- * dispatching a single aggregated chunk. Prevents 60+ re-renders per second
2644
- * on fast streams.
2645
- */
2646
- interface TokenBuffer {
2647
- /** Append a delta. Returns immediately. */
2648
- push(delta: string): void;
2649
- /** Force flush and resolve any pending timer. */
2650
- flush(): void;
2651
- /** Stop accepting tokens; flush whatever is buffered. */
2652
- close(): void;
2653
- }
2654
- declare function createTokenBuffer(onFlush: (delta: string) => void, windowMs?: 16): TokenBuffer;
2655
-
2656
- declare function resolvePersona(message: Pick<ChatMessage, 'role' | 'sender'>, user?: ChatUserContext, assistant?: ChatAssistantContext): ChatPersona;
2657
- /** Compute initials for an avatar fallback. */
2658
- declare function deriveInitials(persona: ChatPersona, role?: string): string;
2659
-
2660
- /**
2661
- * HTTP + SSE transport. Default implementation for web hosts.
2662
- *
2663
- * Backend contract (see @dev/@refactoring7-chat/06-integration.md):
2664
- * POST /sessions → SessionInfo (JSON)
2665
- * GET /sessions/:id/history?cursor= → HistoryPage (JSON)
2666
- * POST /sessions/:id/messages → SSE stream of ChatStreamEvent
2667
- * POST /sessions/:id/messages/buffered → ChatMessage (JSON, fallback)
2668
- * DELETE /sessions/:id → 204
2669
- */
2670
-
2671
- interface HttpTransportConfig {
2672
- /** Base URL without trailing slash, e.g. '/api/chat' or 'https://api.example.com/v1/chat'. */
2673
- baseUrl: string;
2674
- /** Optional slug appended/forwarded as project identifier. */
2675
- slug?: string;
2676
- /** Returns headers applied to every request — e.g. Authorization. */
2677
- getAuthHeader?: () => Record<string, string> | Promise<Record<string, string>>;
2678
- /** Default fetch timeout (per non-streaming request). */
2679
- timeoutMs?: number;
2680
- /** Override fetch implementation (useful for tests or custom retry layers). */
2681
- fetchImpl?: typeof fetch;
2682
- }
2683
- declare function createHttpTransport(config: HttpTransportConfig): ChatTransport;
2684
-
2685
- /**
2686
- * In-memory chat transport for stories and tests. Replays scripted replies.
2687
- */
2688
-
2689
- interface MockTransportOptions {
2690
- /** Each entry is the assistant's reply for one user turn. Strings are split
2691
- * into chunks; arrays are taken as the exact event sequence (after a
2692
- * prepended `message_start` and before a synthetic `message_end`). */
2693
- replies?: Array<string | ChatStreamEvent[]>;
2694
- latencyMs?: number;
2695
- /** Initial history returned by `createSession`. */
2696
- initialMessages?: ChatMessage[];
2697
- shouldFail?: (attempt: number) => boolean;
2698
- }
2699
- declare function createMockTransport(opts?: MockTransportOptions): ChatTransport;
2700
-
2701
- /**
2702
- * Server-Sent Events parser as an AsyncGenerator.
2703
- *
2704
- * Yields parsed events from a `Response` body. Handles the split-read case
2705
- * where `event:` and `data:` arrive in separate TCP packets. Skips malformed
2706
- * JSON gracefully. Honors AbortSignal (caller passes one to fetch).
2707
- */
2708
-
2709
- interface RawEvent {
2710
- event?: string;
2711
- data?: string;
2712
- }
2713
- interface ParseSSEOptions {
2714
- signal?: AbortSignal;
2715
- /** Map a raw SSE event to zero, one, or many `ChatStreamEvent`s.
2716
- * Default: parse `data` as JSON and assume the JSON shape already
2717
- * matches `ChatStreamEvent`. */
2718
- map?: (raw: RawEvent) => ChatStreamEvent | ChatStreamEvent[] | null;
2719
- idleTimeoutMs?: number;
2720
- }
2721
- declare function parseSSE(response: Response, options?: ParseSSEOptions): AsyncGenerator<ChatStreamEvent, void, void>;
2722
-
2723
- /**
2724
- * Transport surface re-export. Lives in core so transport implementations
2725
- * never need to reach into the public types module.
2726
- */
2727
-
2728
- declare class TransportError extends Error {
2729
- code: string;
2730
- constructor(message: string, code?: string);
2731
- }
2732
-
2733
- /**
2734
- * Pydantic-AI SSE event mapper.
2735
- *
2736
- * Translates the event shape emitted by pydantic-AI–style Django backends
2737
- * (text_delta / tool_call / tool_result / done / error / approval_required)
2738
- * into the canonical `ChatStreamEvent` stream consumed by the Chat reducer.
2739
- *
2740
- * Backends that don't expose a stable `tool_call_id` are supported via a
2741
- * per-stream FIFO queue keyed by tool name. The earlier "Map<name, toolId>"
2742
- * approach lost the first toolId when a tool was invoked twice in one turn
2743
- * (e.g. `list_tasks` for search and again for confirmation) — using a queue
2744
- * keeps each call/result pair correctly matched.
2745
- */
2746
-
2747
- interface PydanticAIEvent {
2748
- type: 'text_delta' | 'tool_call' | 'tool_result' | 'done' | 'error' | 'approval_required';
2749
- delta?: string;
2750
- tool?: string;
2751
- args?: unknown;
2752
- result?: unknown;
2753
- /**
2754
- * Structured frontend payload — present on `tool_result` when the tool has
2755
- * a `result_schema`. The LLM sees only `result` (compact text); the
2756
- * frontend uses `data` to render rich UI (e.g. vehicle cards).
2757
- */
2758
- data?: unknown;
2759
- total_tokens?: number;
2760
- error?: string;
2761
- tool_call_id?: string;
2762
- session_id?: string;
2763
- }
2764
- /** Per-stream FIFO queue keyed by tool name. Created via `createToolIdQueue`. */
2765
- interface ToolIdQueue {
2766
- /** Allocate a new toolId for a `tool_call` event and enqueue it under `name`. */
2767
- push(name: string): string;
2768
- /** Pop the oldest toolId for `name` (or return an orphan marker if none). */
2769
- shift(name: string): string;
2770
- /** Reset all queues (e.g. on stream close). */
2771
- clear(): void;
2772
- }
2773
- declare function createToolIdQueue(): ToolIdQueue;
2774
- /**
2775
- * Translate a single pydantic-AI event into zero or more `ChatStreamEvent`s.
2776
- * Pass a `ToolIdQueue` shared across the lifetime of one stream so that
2777
- * `tool_call` / `tool_result` pairs match correctly.
2778
- */
2779
- declare function mapPydanticAIEvent(ev: PydanticAIEvent, toolIds: ToolIdQueue): Generator<ChatStreamEvent>;
2780
- /**
2781
- * Convenience factory: returns a `ParseSSEOptions['map']` callback that
2782
- * decodes raw SSE frames as `PydanticAIEvent` JSON and yields zero or
2783
- * more `ChatStreamEvent`s through `mapPydanticAIEvent`.
2784
- *
2785
- * Allocates an internal `ToolIdQueue` — call this once per stream.
2786
- */
2787
- declare function createPydanticAISSEMap(): NonNullable<ParseSSEOptions['map']>;
2788
-
2789
- /**
2790
- * High-level transport factory for pydantic-AI–style backends.
2791
- *
2792
- * Composes:
2793
- * - `parseSSE` for spec-compliant SSE framing (multi-line `data:`, comments, idle timeout).
2794
- * - `createPydanticAISSEMap` for normalizing pydantic-AI events into `ChatStreamEvent`.
2795
- *
2796
- * Use when your backend speaks the canonical pydantic-AI stream shape
2797
- * (`text_delta` / `tool_call` / `tool_result` / `done` / `error`).
2798
- * URL building, auth headers, history loading, and optional session
2799
- * bootstrapping are caller responsibilities — pass them in.
2800
- */
2801
-
2802
- interface PydanticAIChatTransportOpts {
2803
- /**
2804
- * Build the SSE stream URL for a user message turn.
2805
- * @example (sessionId, message) => `${base}/stream?session_id=${sessionId}&message=${encodeURIComponent(message)}`
2806
- */
2807
- buildStreamUrl: (sessionId: string, message: string) => string | URL;
2808
- /** Optional history loader. If omitted, `loadHistory` returns an empty page. */
2809
- loadHistory?: (sessionId: string, cursor?: string | null) => Promise<HistoryPage>;
2810
- /**
2811
- * Optional session bootstrap. Called from `createSession`. Useful for
2812
- * backends that need a `POST /sessions` round-trip or want to pre-seed
2813
- * history.
2814
- */
2815
- bootstrapSession?: (opts?: CreateSessionOptions) => Promise<SessionInfo>;
2816
- /** Optional session teardown. */
2817
- closeSession?: (sessionId: string) => Promise<void>;
2818
- /**
2819
- * Optional non-streaming send (for hosts that need a buffered fallback,
2820
- * e.g. when the user disables streaming). Defaults to throwing — most
2821
- * hosts only use streaming.
2822
- */
2823
- send?: (sessionId: string, content: string, options?: SendOptions) => Promise<ChatMessage>;
2824
- /** Request headers (Authorization, content-type, etc.). */
2825
- buildHeaders?: () => HeadersInit | Promise<HeadersInit>;
2826
- /** Override fetch (tests, retry layers). */
2827
- fetchImpl?: typeof fetch;
2828
- /**
2829
- * HTTP method for the stream request. Defaults to `'POST'` with
2830
- * `{ content, attachments, metadata }` JSON body. Set to `'GET'` if
2831
- * your backend embeds the message in the URL via `buildStreamUrl`.
2832
- */
2833
- streamMethod?: 'GET' | 'POST';
2834
- /** Idle timeout for the SSE connection, in ms. Forwarded to `parseSSE`. */
2835
- idleTimeoutMs?: number;
2836
- /**
2837
- * Side-channel for events that don't translate to `ChatStreamEvent`
2838
- * (e.g. `approval_required` — surfaces interactive prompts outside the
2839
- * normal message stream). Called synchronously while parsing the SSE
2840
- * frame; mutate caller-owned state, don't `await` long work here.
2841
- */
2842
- onPydanticEvent?: (event: PydanticAIEvent) => void;
2843
- }
2844
- declare function createPydanticAIChatTransport(opts: PydanticAIChatTransportOpts): ChatTransport;
2845
-
2846
- /**
2847
- * @deprecated Plan64. As of ui-tools 2.1.369, `<MessageList>` is
2848
- * virtualized via react-virtuoso and owns its own scroll viewport.
2849
- * Sticky-bottom + auto-follow on streaming live inside the component;
2850
- * use the new `MessageListProps.onAtBottomChange` prop and the
2851
- * `MessageListHandle.scrollToBottom()` imperative method instead.
2852
- *
2853
- * This hook is kept for hosts that render messages outside
2854
- * `<MessageList>` (e.g. headless story shells, custom non-virtualized
2855
- * scroll containers). It still works against any HTMLElement scroll
2856
- * container, but it does NOT integrate with Virtuoso — passing a
2857
- * Virtuoso-managed element here will read garbage scroll metrics.
2858
- */
2859
- interface UseChatScrollOptions {
2860
- containerRef: RefObject<HTMLElement | null>;
2861
- bottomRef: RefObject<HTMLElement | null>;
2862
- isStreaming?: boolean;
2863
- /** Distance from bottom (px) considered "at bottom". */
2864
- bottomThresholdPx?: number;
2865
- /** Bump key — increment when a new message arrives so the hook re-evaluates auto-scroll. */
2866
- messagesCount?: number;
2867
- }
2868
- interface UseChatScrollReturn {
2869
- isAtBottom: boolean;
2870
- unreadCount: number;
2871
- scrollToBottom: (smooth?: boolean) => void;
2872
- resetUnread: () => void;
2873
- }
2874
- declare function useChatScroll(options: UseChatScrollOptions): UseChatScrollReturn;
2875
-
2876
- interface UseChatHistoryOptions {
2877
- enabled?: boolean;
2878
- containerRef: RefObject<HTMLElement | null>;
2879
- topSentinelRef: RefObject<HTMLElement | null>;
2880
- hasMore: boolean;
2881
- isLoadingMore: boolean;
2882
- loadMore: () => Promise<void>;
2883
- }
2884
- /** Triggers `loadMore` when the top sentinel enters the container's viewport.
2885
- * Preserves scroll anchor: if the container's height grows after load, we
2886
- * bump scrollTop by the delta so the previously-visible message stays put. */
2887
- declare function useChatHistory(options: UseChatHistoryOptions): void;
2888
-
2889
- /**
2890
- * Chat-specific audio facade. Thin wrapper over `useNotificationSounds`
2891
- * from `@djangocfg/ui-core` — keeps the `ChatAudioEvent` typing while
2892
- * the underlying bus / prefs / Safari-unlock logic lives in ui-core.
2893
- */
2894
- declare function useChatAudio(config?: ChatAudioConfig): UseChatAudioReturn;
2895
-
2896
- interface ChatLightboxState {
2897
- gallery: ChatAttachment[];
2898
- index: number;
2899
- }
2900
- interface UseChatLightboxReturn {
2901
- state: ChatLightboxState | null;
2902
- open: (att: ChatAttachment, gallery?: ChatAttachment[]) => void;
2903
- close: () => void;
2904
- }
2905
- /** Tiny state container for an image lightbox. The host owns the modal +
2906
- * `<LazyImageViewer>` mount; we just track which gallery to show. */
2907
- declare function useChatLightbox(): UseChatLightboxReturn;
2908
-
2909
- /** Anything with a `.focus()` method — covers HTMLElement, the
2910
- * composer's textareaRef from `useChatComposer`, and any custom
2911
- * imperative handle exposing the same shape. */
2912
- interface Focusable {
2913
- focus: () => void;
2914
- }
2915
- interface UseAutoFocusOnStreamEndOptions {
2916
- /** True while an assistant reply is streaming. The hook fires the
2917
- * focus() call on the true → false transition.
2918
- *
2919
- * When omitted, the hook reads `isStreaming` from `useChatContext`.
2920
- * Pass it explicitly only if you're driving stream state from your
2921
- * own store (cmdop's Wails event bus, for example). */
2922
- isStreaming?: boolean;
2923
- /** Ref / handle to focus when the reply lands.
2924
- *
2925
- * When omitted, the hook uses the composer handle registered in
2926
- * the chat context — the built-in `<Composer>` registers itself
2927
- * automatically, custom composers can opt in via
2928
- * `useRegisterComposer`. Pass `targetRef` only when you need to
2929
- * focus something other than the composer (e.g. an "approve"
2930
- * button, a quick-reply chip). */
2931
- targetRef?: RefObject<Focusable | HTMLElement | null>;
2932
- /** Opt-out. Default true. Pass false to disable without unmounting
2933
- * the hook (e.g. user preference). */
2934
- enabled?: boolean;
2935
- /** Delay the focus call by this many ms. Default 0 = next animation
2936
- * frame, which lets the streaming bubble's final commit settle
2937
- * before focus pulls scroll. Bump to 50-150ms for layouts that
2938
- * re-mount the composer after the final chunk. */
2939
- delayMs?: number;
2940
- }
2941
- /**
2942
- * Refocus the chat composer the moment the assistant reply finishes
2943
- * streaming. Standard chat UX: the user types → sends → reads the
2944
- * reply → starts typing again without reaching for the mouse.
2945
- *
2946
- * Default (zero-config) usage — works the moment a `<Composer>` is
2947
- * mounted inside a `<ChatProvider>`:
2948
- *
2949
- * useAutoFocusOnStreamEnd();
2950
- *
2951
- * Custom composer / advanced wiring:
2952
- *
2953
- * const ref = useRef<{ focus: () => void } | null>(null);
2954
- * useAutoFocusOnStreamEnd({ targetRef: ref });
2955
- *
2956
- * Driving stream state yourself:
2957
- *
2958
- * useAutoFocusOnStreamEnd({ isStreaming: myExternalStreaming });
2959
- *
2960
- * Only the true → false transition fires focus — toggling `enabled`
2961
- * mid-stream won't steal focus while the user is reading.
2962
- */
2963
- declare function useAutoFocusOnStreamEnd(options?: UseAutoFocusOnStreamEndOptions): void;
2964
- /**
2965
- * Helper for custom composers (anything that's NOT the built-in
2966
- * `<Composer>`) to register their focus() with the chat context so
2967
- * `useAutoFocusOnStreamEnd()` and other consumers work without
2968
- * prop-drilling.
2969
- *
2970
- * Usage inside your custom composer:
2971
- *
2972
- * const focus = useCallback(() => {
2973
- * myEditorRef.current?.commands.focus();
2974
- * }, []);
2975
- * useRegisterComposer(focus);
2976
- *
2977
- * No-op when called outside a `<ChatProvider>`.
2978
- */
2979
- declare function useRegisterComposer(handle: ComposerHandle): void;
2980
-
2981
- interface UseChatResetOptions {
2982
- /**
2983
- * Backend call that performs the actual reset (e.g. POST /chat/reset).
2984
- * Should resolve to `true` on success, `false` on failure.
2985
- * Throwing also counts as failure — caught and logged.
2986
- */
2987
- onReset: () => Promise<boolean>;
2988
- /**
2989
- * Called after a successful reset (status === true). Use to clear the
2990
- * local message list, navigate, or fire analytics.
2991
- */
2992
- onSuccess?: () => void;
2993
- /**
2994
- * Called when reset fails (returned `false` or threw). Defaults to no-op
2995
- * — wire to a toast/banner if you want to surface it.
2996
- */
2997
- onError?: (error?: unknown) => void;
2998
- }
2999
- interface UseChatResetReturn {
3000
- /** Trigger the reset. Safe to call multiple times — re-entrant guard. */
3001
- reset: () => Promise<boolean>;
3002
- /** True while the reset is in flight. */
3003
- isResetting: boolean;
3004
- }
3005
- /**
3006
- * Generic "clear chat context" hook.
3007
- *
3008
- * Stays generic — the backend call lives in the host (it knows the URL,
3009
- * auth, project slug). Provides the in-flight state and success/error
3010
- * callbacks every consumer wires up the same way.
3011
- *
3012
- * @example
3013
- * ```tsx
3014
- * const { reset, isResetting } = useChatReset({
3015
- * onReset: async () => {
3016
- * const res = await fetch('/api/chat/reset', { method: 'POST', credentials: 'include' });
3017
- * return res.ok;
3018
- * },
3019
- * onSuccess: () => chat.clearMessages(),
3020
- * });
3021
- * ```
3022
- */
3023
- declare function useChatReset(opts: UseChatResetOptions): UseChatResetReturn;
3024
-
3025
- interface UseVisitorFingerprintOptions {
3026
- /** localStorage key. @default 'chat.visitor.fingerprint' */
3027
- storageKey?: string;
3028
- }
3029
- /**
3030
- * Persistent anonymous visitor id, kept in `localStorage`.
3031
- *
3032
- * Returns `null` on the first render (SSR-safe) and the stable id from
3033
- * the second render onwards. Use as `fingerprint` for public chat
3034
- * transports that need to dedupe sessions per visitor without auth.
3035
- */
3036
- declare function useVisitorFingerprint(opts?: UseVisitorFingerprintOptions): string | null;
3037
-
3038
- interface ChatDockPrefs {
3039
- /** Popover (FAB-style) or side-docked panel. */
3040
- mode: ChatDockMode;
3041
- /** Which edge the side dock attaches to. */
3042
- side: ChatDockSide;
3043
- /** Width in px when side-docked (resizable in the future). */
3044
- sideWidth: number;
3045
- }
3046
- declare const DEFAULT_DOCK_PREFS: ChatDockPrefs;
3047
- interface UseChatDockPrefsOptions {
3048
- /** localStorage key. @default 'chat.dock.prefs' */
3049
- storageKey?: string;
3050
- /** Override the baseline defaults (per-product branding, etc.). */
3051
- defaults?: Partial<ChatDockPrefs>;
3052
- }
3053
- interface UseChatDockPrefsReturn extends ChatDockPrefs {
3054
- /** Merge-update — pass only the fields that changed. */
3055
- setPrefs: (patch: Partial<ChatDockPrefs>) => void;
3056
- /** Convenience toggle: popover ⇆ side. */
3057
- toggleMode: () => void;
3058
- /** Convenience toggle: right ⇆ left (only affects side mode). */
3059
- toggleSide: () => void;
3060
- /** Reset to defaults. */
3061
- reset: () => void;
3062
- }
3063
- /**
3064
- * Persistent dock preferences (mode / side / width) via ui-core localStorage.
3065
- *
3066
- * SSR-safe: returns defaults on the server, hydrates on mount.
3067
- * Survives reloads — power users keep their preferred chat layout.
3068
- */
3069
- declare function useChatDockPrefs(opts?: UseChatDockPrefsOptions): UseChatDockPrefsReturn;
3070
-
3071
- interface UseFocusOnEmptyClickOptions {
3072
- /**
3073
- * Custom focus target. Defaults to the composer registered in the chat
3074
- * context.
3075
- */
3076
- targetRef?: RefObject<Focusable | HTMLElement | null>;
3077
- /** Opt-out without unmounting the hook. @default true */
3078
- enabled?: boolean;
3079
- /**
3080
- * Don't focus if currently streaming (user is reading the reply).
3081
- * @default true
3082
- */
3083
- skipWhileStreaming?: boolean;
3084
- }
3085
- /**
3086
- * "Click anywhere in the chat → focus the composer" — Slack / Linear /
3087
- * ChatGPT behaviour.
3088
- *
3089
- * Returns a single `onMouseUp` handler to attach to the scrollable
3090
- * messages container. Heuristics that mirror the popular chat apps:
3091
- *
3092
- * 1. Ignore clicks on interactive elements (`button`, `a`, `input`,
3093
- * `textarea`, `[role="button"]`, `[contenteditable]`, …) — they
3094
- * have their own behaviour.
3095
- * 2. Ignore clicks that produced a text selection (drag-to-select).
3096
- * Stealing focus would break copy-paste flow.
3097
- * 3. Ignore touch input — on mobile the system focuses the textarea
3098
- * via tap on the composer itself; touching messages should never
3099
- * open the keyboard.
3100
- * 4. Optionally skip while the assistant is streaming so the user
3101
- * can keep reading without the keyboard popping up.
3102
- *
3103
- * @example
3104
- * ```tsx
3105
- * const onMouseUp = useFocusOnEmptyClick();
3106
- * <div ref={scrollRef} onMouseUp={onMouseUp}>{messages}</div>
3107
- * ```
3108
- */
3109
- declare function useFocusOnEmptyClick(options?: UseFocusOnEmptyClickOptions): (event: MouseEvent<HTMLElement>) => void;
3110
-
3111
- interface UseChatUnreadOptions {
3112
- /**
3113
- * When true, unread state is auto-cleared (treated as "user is reading
3114
- * the chat right now"). Pass your dock-open boolean here so the badge
3115
- * resets the moment the user opens the chat.
3116
- */
3117
- open?: boolean;
3118
- /**
3119
- * Which message roles count as "unread". Defaults to `['assistant']` —
3120
- * we only count inbound replies, not the user's own messages.
3121
- */
3122
- countRoles?: Array<ChatMessage['role']>;
3123
- }
3124
- interface UseChatUnreadReturn {
3125
- /** Most-recent inbound message since the last mark-as-read. */
3126
- unread: ChatMessage | null;
3127
- /** Total inbound messages since the last mark-as-read. */
3128
- count: number;
3129
- /** Manually clear the unread state. */
3130
- markRead: () => void;
3131
- }
3132
- /**
3133
- * Track inbound chat messages while the user isn't watching.
3134
- *
3135
- * Must be called **inside** the chat's `<ChatProvider>` (i.e. inside the
3136
- * `children` of `ChatLauncher`, alongside `ChatRoot`).
3137
- *
3138
- * @example
3139
- * ```tsx
3140
- * function ChatRootWithUnreadBadge({ open, onUnread }: { open: boolean; onUnread: (m: ChatMessage | null) => void }) {
3141
- * const { unread, count, markRead } = useChatUnread({ open });
3142
- * useEffect(() => onUnread(unread), [unread, onUnread]);
3143
- * // pass `count` to your FAB badge via the host's state
3144
- * return <ChatRoot transport={transport} />;
3145
- * }
3146
- * ```
3147
- *
3148
- * For end-to-end wiring with `<ChatLauncher unreadMessage onMarkRead>`,
3149
- * see the `Launcher / WithLivePush` story.
3150
- */
3151
- declare function useChatUnread(opts?: UseChatUnreadOptions): UseChatUnreadReturn;
3152
-
3153
- declare const useChatAudioPrefs: zustand.UseBoundStore<zustand.StoreApi<AudioPrefsState<ChatAudioEvent>>>;
3154
-
3155
- /**
3156
- * Built-in chat notification sounds.
3157
- *
3158
- * Sounds are inlined as base64 data URLs inside each `./sounds/<name>.ts`
3159
- * module — no `.mp3` loader / `*.d.ts` shim required on the consumer
3160
- * side. Total ≈ 136KB bundled into the lazy Chat chunk.
3161
- *
3162
- * To re-encode after a source edit:
3163
- * 1. Drop the new mp3 next to this file (e.g. `./sounds/sent.source.mp3`).
3164
- * 2. `base64 -i sent.source.mp3` and paste into `./sounds/sent.ts`.
3165
- * 3. Delete the temporary source mp3 — only the `.ts` ships.
3166
- *
3167
- * Encoding cheat-sheet:
3168
- * ffmpeg -i in.mp3 -ac 2 -ar 44100 -b:a 128k \
3169
- * -af 'atrim=0:1.4,afade=t=out:st=1.22:d=0.18' out.mp3
3170
- */
3171
-
3172
- /**
3173
- * Default chat notification sounds. Pass to `useChatAudio` (or spread
3174
- * into a custom map) so hosts don't have to ship assets themselves.
3175
- *
3176
- * @example
3177
- * ```tsx
3178
- * const audio = useChatAudio({ sounds: DEFAULT_CHAT_SOUNDS });
3179
- *
3180
- * // Override one event:
3181
- * const audio = useChatAudio({
3182
- * sounds: { ...DEFAULT_CHAT_SOUNDS, mention: '/custom-mention.mp3' },
3183
- * });
3184
- * ```
3185
- */
3186
- declare const DEFAULT_CHAT_SOUNDS: ChatAudioSounds;
3187
-
3188
- interface ToolPayloadMatcher {
3189
- /** Cheap predicate. First match wins. */
3190
- match: (value: unknown, kind: ToolPayloadKind, call: ChatToolCall) => boolean;
3191
- render: (value: unknown, kind: ToolPayloadKind, call: ChatToolCall) => ReactNode;
3192
- }
3193
- type ToolPayloadFallback = (value: unknown, kind: ToolPayloadKind, call: ChatToolCall) => ReactNode;
3194
- declare function dispatchToolPayload(matchers: ToolPayloadMatcher[], fallback: ToolPayloadFallback): ToolPayloadFallback;
3195
- declare function isPlainObject(v: unknown): v is Record<string, unknown>;
3196
- declare function isLatLng(v: unknown): v is {
3197
- lat: number;
3198
- lng: number;
3199
- };
3200
- declare function isGeoJSONFeatureCollection(v: unknown): v is {
3201
- type: 'FeatureCollection';
3202
- features: unknown[];
3203
- };
3204
- declare function isStringValue(v: unknown): v is string;
3205
-
3206
- /**
3207
- * Chat dev logger.
3208
- *
3209
- * A thin namespaced wrapper over `consola` that no-ops in production unless
3210
- * the host app explicitly opts in via `<ChatRoot debug />`. The default
3211
- * detection uses `isDev` from `@djangocfg/ui-core/lib/env` (NODE_ENV).
3212
- *
3213
- * Why a dedicated module: chat is async and event-heavy (bootstrap, transport,
3214
- * SSE chunks, tool calls, regenerate, …). Inline `console.log`s rot fast and
3215
- * leak into prod. A single `getChatLogger()` call gives every layer the same
3216
- * namespaced sub-logger and keeps zero-cost gating in one place.
3217
- *
3218
- * Sub-loggers:
3219
- * bootstrap — initial session bootstrap (createSession / loadHistory)
3220
- * transport — outbound transport calls + responses
3221
- * stream — SSE chunk / tool / message_end events
3222
- * lifecycle — sendMessage, regenerate, newSession, edits
3223
- * tools — tool_call_start / _delta / _end specifics
3224
- * error — caught errors (always emitted as `error` level)
3225
- */
3226
-
3227
- type ChatLogScope = 'bootstrap' | 'transport' | 'stream' | 'lifecycle' | 'tools' | 'error';
3228
- interface ChatLogger {
3229
- bootstrap: ConsolaInstance;
3230
- transport: ConsolaInstance;
3231
- stream: ConsolaInstance;
3232
- lifecycle: ConsolaInstance;
3233
- tools: ConsolaInstance;
3234
- error: ConsolaInstance;
3235
- /** True when this logger is actually emitting (host opted in or NODE_ENV=development). */
3236
- enabled: boolean;
3237
- }
3238
- /**
3239
- * Get the chat logger.
3240
- * @param debug Explicit override from the host. `undefined` falls back to `isDev`.
3241
- */
3242
- declare function getChatLogger(debug?: boolean): ChatLogger;
3243
-
3244
- /**
3245
- * sanitizeDraft — minimal pre-submit cleanup for chat-composer drafts.
3246
- *
3247
- * Mirrors the conservative behaviour ChatGPT / Claude / Telegram
3248
- * actually ship: clean the obvious junk the user didn't intend to
3249
- * send, touch nothing that *could* be intentional.
3250
- *
3251
- * **What we DO touch:**
3252
- *
3253
- * 1. Trim leading/trailing whitespace (spaces, tabs, newlines,
3254
- * NBSP). The user typing `\n\n hello \n` meant `hello`.
3255
- * 2. Normalise line endings — `\r\n` / `\r` → `\n`. Pasted Windows
3256
- * / old-mac text gets the same internal shape, so the LLM
3257
- * tokeniser and markdown renderer see one canonical form.
3258
- * 3. Strip zero-width / invisible characters that web-paste
3259
- * smuggles in: ZWSP (U+200B), ZWNJ (U+200C), ZWJ (U+200D),
3260
- * BOM / ZWNBSP (U+FEFF). They're invisible, break LLM
3261
- * tokenisation, and the user never meant to type them.
3262
- *
3263
- * **What we DO NOT touch (and why):**
3264
- *
3265
- * - **Internal whitespace runs** (3+ spaces, tabs, blank lines).
3266
- * Code indentation depends on these. ChatGPT preserves them as
3267
- * typed — " if (x):\n return" stays four-space-indented.
3268
- * Collapsing them is the path to subtly broken code snippets.
3269
- *
3270
- * - **Bidi override marks** (U+200E LRM, U+200F RLM, U+202A..U+202E).
3271
- * Legitimately used in Arabic / Hebrew / mixed-direction text.
3272
- * Stripping silently breaks RTL users. If a specific deployment
3273
- * wants to block them as a security measure, do it at that layer
3274
- * with explicit user-visible feedback.
3275
- *
3276
- * - **Tabs vs spaces** beyond rule 1. Could be either code or
3277
- * prose; without parsing markdown we can't tell.
3278
- *
3279
- * - **Emoji, mentions, URLs, code spans** — passthrough text.
3280
- *
3281
- * The function is intentionally tiny — every rule earns its keep
3282
- * with a concrete "user pasted X from Y, got nonsense" story.
3283
- *
3284
- * **Idempotent**: `sanitizeDraft(sanitizeDraft(x)) === sanitizeDraft(x)`.
3285
- */
3286
- declare function sanitizeDraft(input: string): string;
3287
- /**
3288
- * Convenience predicate: true when the draft is non-empty AFTER
3289
- * sanitation. Use to gate Send buttons / Enter submits so an empty
3290
- * or whitespace-only draft never produces a real message.
3291
- *
3292
- * Cheaper than sanitizeDraft(input).length > 0 only marginally —
3293
- * we still allocate the cleaned string. Kept as a named helper for
3294
- * call-site clarity.
3295
- */
3296
- declare function isSubmittableDraft(input: string): boolean;
3297
-
3298
- /** Walk the conversation and collect image attachments in chronological order. */
3299
- declare function collectImageAttachments(messages: ChatMessage[]): ChatAttachment[];
3300
-
3301
- /**
3302
- * Chat color tokens — single source of truth.
3303
- *
3304
- * Every role-conditional class for chat surfaces lives here.
3305
- * Components consume via `useChatBubbleStyles` / `useChatRoleStyles`,
3306
- * never via raw Tailwind literals.
3307
- *
3308
- * Why centralize:
3309
- * 1. One file to edit when the design system changes (e.g. light-theme
3310
- * contrast tweaks, palette swap).
3311
- * 2. Eliminates the "first-token-on-bg-primary-was-text-white" class
3312
- * of bugs where each call site picks its own foreground.
3313
- * 3. Lets us snapshot-test color decisions later.
3314
- */
3315
- /** Bubble surface classes (background + text), keyed by message state. */
3316
- declare const BUBBLE_SURFACE: {
3317
- /** User-authored bubble — solid brand color. */
3318
- readonly user: "bg-primary text-primary-foreground rounded-tr-md";
3319
- /** Assistant bubble in normal state — neutral muted surface. */
3320
- readonly assistant: "bg-muted text-foreground rounded-tl-md";
3321
- /** Assistant bubble when the turn failed — destructive tint. */
3322
- readonly error: "bg-destructive/10 text-destructive rounded-tl-md border border-destructive/30";
3323
- };
3324
- /**
3325
- * Anchor (link) classes for markdown content rendered inside a bubble.
3326
- *
3327
- * On `bg-primary` the link MUST stay legible against the cyan/brand fill —
3328
- * `text-primary-foreground` matches the bubble's foreground token, so
3329
- * contrast tracks the design system automatically.
3330
- *
3331
- * On the neutral assistant bubble we keep the brand-primary color so links
3332
- * still pop without competing with the body text.
3333
- */
3334
- declare const ANCHOR: {
3335
- readonly user: string;
3336
- readonly assistant: "text-primary underline hover:text-primary/80 transition-colors break-all";
3337
- };
3338
- /** Inline secondary action (e.g. "Show more / less"). Same logic as anchors. */
3339
- declare const TOGGLE: {
3340
- readonly user: "text-primary-foreground/80 hover:text-primary-foreground";
3341
- readonly assistant: "text-primary hover:text-primary/80";
3342
- };
3343
- /** Destructive surface — used by ErrorBanner and the delete action. */
3344
- declare const DESTRUCTIVE_SURFACE: {
3345
- /** Banner / card variant: border + tint + text. */
3346
- readonly banner: "border border-destructive/40 bg-destructive/10 text-destructive";
3347
- /** Subtle hover for destructive buttons inside the banner / menu. */
3348
- readonly hover: "hover:bg-destructive/15";
3349
- /** Strong-hover variant (e.g. trash overlay on attachments). */
3350
- readonly hoverStrong: "hover:bg-destructive hover:text-destructive-foreground";
3351
- /** Inline destructive text utility. */
3352
- readonly text: "text-destructive";
3353
- /** Hover style for menu items that delete data. */
3354
- readonly menuItem: "text-destructive focus:text-destructive hover:bg-destructive/15 hover:text-destructive";
3355
- };
3356
- /** Tool-call result text. */
3357
- declare const TOOL_CALL: {
3358
- readonly errorText: "text-destructive";
3359
- };
3360
- type ChatBubbleSurface = keyof typeof BUBBLE_SURFACE;
3361
-
3362
- /**
3363
- * Role-aware style hooks for chat surfaces.
3364
- *
3365
- * Pure utility hooks — no React state, no side effects, just memoized
3366
- * className strings derived from `bubbleTokens`. They exist so:
3367
- * - components don't import token constants directly (single facade)
3368
- * - "the user-bubble link color" can be changed in one file
3369
- * - tests can mock the hook to assert intent without parsing classNames
3370
- */
3371
- interface ChatBubbleStyles {
3372
- /** className for the bubble container (background + text + border). */
3373
- surface: string;
3374
- /** className for an inline anchor inside markdown. */
3375
- anchor: string;
3376
- /** className for a secondary inline action (e.g. show more). */
3377
- toggle: string;
3378
- }
3379
- /**
3380
- * Resolve bubble + content styles for a single message.
3381
- *
3382
- * @param role 'user' | 'assistant' | 'system' (system defaults to assistant styling)
3383
- * @param isError marks the bubble as a failed turn (overrides surface)
3384
- *
3385
- * @example
3386
- * ```tsx
3387
- * const { surface, anchor } = useChatBubbleStyles(message.role, !!message.isError);
3388
- * <div className={cn('rounded-2xl px-3.5 py-2', surface)}>…</div>
3389
- * ```
3390
- */
3391
- declare function useChatBubbleStyles(role: 'user' | 'assistant' | 'system', isError: boolean): ChatBubbleStyles;
3392
- interface ChatRoleStyles {
3393
- anchor: string;
3394
- toggle: string;
3395
- }
3396
- /**
3397
- * Lightweight variant when only role matters (no error state, no surface).
3398
- * Use in shared markdown renderers that don't know about bubble background.
3399
- */
3400
- declare function useChatRoleStyles(isUser: boolean): ChatRoleStyles;
3401
- interface ChatDestructiveStyles {
3402
- banner: string;
3403
- hover: string;
3404
- hoverStrong: string;
3405
- text: string;
3406
- menuItem: string;
3407
- toolErrorText: string;
3408
- }
3409
- /**
3410
- * Destructive (delete / error) class facade. Hook form keeps the API
3411
- * symmetric with the others; under the hood it returns a frozen object.
3412
- */
3413
- declare function useChatDestructiveStyles(): ChatDestructiveStyles;
3414
-
3415
- interface MessageListProps {
3416
- messages?: ChatMessage[];
3417
- renderItem?: (m: ChatMessage, i: number) => ReactNode;
3418
- renderEmpty?: () => ReactNode;
3419
- isLoadingMore?: boolean;
3420
- /**
3421
- * Fires when the user scrolls within `topThresholdPx` of the top of
3422
- * the list — wire to your `loadMore()` here. Replaces the previous
3423
- * `topSentinelRef` API. The callback is gated by Virtuoso, so it
3424
- * won't fire repeatedly while a load is in flight (Virtuoso pauses
3425
- * `startReached` until `data` length grows).
3426
- */
3427
- onStartReached?: () => void;
3428
- /**
3429
- * @deprecated Kept as a no-op for backwards compatibility — wire
3430
- * `onStartReached` instead. Virtuoso owns the scroll viewport now,
3431
- * external sentinels never see scroll events.
3432
- */
3433
- topSentinelRef?: RefObject<HTMLDivElement | null>;
3434
- /**
3435
- * @deprecated Kept as a no-op for backwards compatibility — Virtuoso
3436
- * exposes `scrollToIndex` via the imperative handle instead. See
3437
- * `useChatScroll` for the chat-friendly wrapper.
3438
- */
3439
- bottomRef?: RefObject<HTMLDivElement | null>;
3440
- className?: string;
3441
- itemClassName?: string;
3442
- /**
3443
- * Skip virtualization and render through plain `.map()`. Use for
3444
- * stories / debugging where DevTools needs to see every node, or
3445
- * when `messages` is guaranteed-tiny. Default: `false` — virtualize
3446
- * always. Plan64.
3447
- */
3448
- noVirtualize?: boolean;
3449
- /**
3450
- * @deprecated No-op as of 2.1.373. We intentionally let Virtuoso run
3451
- * its first-item probe pass: cmdop bubbles vary from 40px (one-line
3452
- * user message) to 800px (markdown with code blocks), so any single
3453
- * estimate fed here forces a measure/reshape loop on every render.
3454
- * The kept prop avoids a breaking-change bump for hosts that still
3455
- * pass it explicitly.
3456
- */
3457
- defaultItemHeight?: number;
3458
- /**
3459
- * Fires when the viewport sticky state changes — `true` when the
3460
- * user is pinned to the bottom (streaming token deltas keep them
3461
- * there), `false` once they scroll up. Wire to your "Jump to
3462
- * latest" affordance via the inverse: render the pill when
3463
- * `!isAtBottom`. Plan64.
3464
- */
3465
- onAtBottomChange?: (isAtBottom: boolean) => void;
3466
- /**
3467
- * Pixel distance from the bottom that still counts as "at bottom".
3468
- * Default 120 — generous enough that mid-message users keep getting
3469
- * sticky-followed (matches ChatGPT / Slack feel) while still letting
3470
- * a deliberate scroll-up break the lock. Plan11.
3471
- */
3472
- atBottomThreshold?: number;
3473
- /**
3474
- * Force-scroll to the bottom when this id changes. Wire to the id of
3475
- * the most-recently-sent user message: every send re-anchors the
3476
- * viewport so users always see their own bubble + the incoming
3477
- * reply, even if they were scrolled up. Plan11.
3478
- */
3479
- scrollAnchorId?: string | number | null;
3480
- }
3481
- interface MessageListHandle {
3482
- scrollToBottom: (smooth?: boolean) => void;
3483
- scrollToIndex: (index: number, smooth?: boolean) => void;
3484
- }
3485
- declare const MessageList: react.ForwardRefExoticComponent<MessageListProps & react.RefAttributes<MessageListHandle>>;
3486
-
3487
- interface MessageBubbleProps {
3488
- message: ChatMessage;
3489
- isUser?: boolean;
3490
- showAvatar?: boolean;
3491
- /** Override avatar URL (skips persona resolution). */
3492
- avatarSrc?: string;
3493
- /** Override avatar fallback (skips persona resolution). */
3494
- avatarFallback?: ReactNode;
3495
- /** Personas — when provided, take precedence over context. */
3496
- user?: ChatUserContext;
3497
- assistant?: ChatAssistantContext;
3498
- showTimestamp?: boolean;
3499
- showActions?: boolean;
3500
- isCompact?: boolean;
3501
- className?: string;
3502
- beforeContent?: ReactNode;
3503
- afterContent?: ReactNode;
3504
- toolCallsRenderer?: (calls: ChatToolCall[]) => ReactNode;
3505
- /** Forwarded to the default `<ToolCalls>` when `toolCallsRenderer` is not set. */
3506
- toolCallsProps?: Omit<ToolCallsProps, 'calls'>;
3507
- sourcesRenderer?: (sources: ChatSource[]) => ReactNode;
3508
- attachmentsRenderer?: (atts: ChatAttachment[]) => ReactNode;
3509
- /** Per-type attachment renderers forwarded to default `<Attachments>`. */
3510
- attachmentRenderers?: AttachmentRendererMap;
3511
- /** Click handler for attachment tiles (e.g. open lightbox). */
3512
- onAttachmentOpen?: (a: ChatAttachment) => void;
3513
- onCopy?: () => void;
3514
- onRegenerate?: () => void;
3515
- onEdit?: () => void;
3516
- onDelete?: () => void;
3517
- /**
3518
- * Extra content rendered alongside the default copy/regenerate/edit/
3519
- * delete actions (after them, on the same row). Hosts pass app-
3520
- * specific affordances here — e.g. "Send to plan", "Add note",
3521
- * "Open in inspector" — without having to fork `<MessageActions>`.
3522
- * Receives the message so renderers can branch by id / role / etc.
3523
- * Plan64.
3524
- */
3525
- messageActionsExtra?: (m: ChatMessage) => ReactNode;
3526
- /**
3527
- * Override the default streaming indicator (the dots / pulse + tool
3528
- * activity label). Receives the message so the host can read
3529
- * `toolActivity`, the running tool call name, etc., and render a
3530
- * richer affordance ("Running cmd_execute on vps-audi…"). Plan64.
3531
- *
3532
- * Renders in two slots: as the in-bubble pre-token affordance, and
3533
- * as the inline label above the bubble when `toolActivity` is set.
3534
- * The render-prop is called for both — branch on `m.content` if
3535
- * you need different behaviour per slot.
3536
- */
3537
- streamingIndicator?: (m: ChatMessage) => ReactNode;
3538
- }
3539
- declare const MessageBubble: react.MemoExoticComponent<({ message, isUser: isUserProp, showAvatar, avatarSrc, avatarFallback, user, assistant, showTimestamp, showActions, isCompact, className, beforeContent, afterContent, toolCallsRenderer, toolCallsProps, sourcesRenderer, attachmentsRenderer, attachmentRenderers, onAttachmentOpen, onCopy, onRegenerate, onEdit, onDelete, messageActionsExtra, streamingIndicator, }: MessageBubbleProps) => react_jsx_runtime.JSX.Element>;
3540
-
3541
- interface MessageActionsProps {
3542
- role: ChatRole;
3543
- onCopy?: () => void;
3544
- onRegenerate?: () => void;
3545
- onEdit?: () => void;
3546
- onDelete?: () => void;
3547
- hideOn?: Array<ChatRole>;
3548
- className?: string;
3549
- }
3550
- /**
3551
- * MessageActions — copy/regenerate/edit/delete buttons for a chat bubble.
3552
- *
3553
- * Memoised: re-renders only when `role`, `hideOn`, `className` or
3554
- * any handler reference changes. Event handlers are compared by
3555
- * reference — callers should stabilise them with useCallback.
3556
- */
3557
- declare function MessageActionsRaw({ role, onCopy, onRegenerate, onEdit, onDelete, hideOn, className, }: MessageActionsProps): react_jsx_runtime.JSX.Element;
3558
- declare const MessageActions: react.MemoExoticComponent<typeof MessageActionsRaw>;
3559
-
3560
- interface SourcesProps {
3561
- sources: ChatSource[];
3562
- layout?: 'inline' | 'grid';
3563
- maxVisible?: number;
3564
- onClick?: (source: ChatSource) => void;
3565
- className?: string;
3566
- }
3567
- declare function Sources({ sources, layout, maxVisible, onClick, className }: SourcesProps): react_jsx_runtime.JSX.Element;
3568
-
3569
- interface EmptyStateProps {
3570
- greeting?: string;
3571
- description?: string;
3572
- suggestions?: Array<{
3573
- label: string;
3574
- prompt: string;
3575
- }>;
3576
- onPickSuggestion?: (prompt: string) => void;
3577
- className?: string;
3578
- }
3579
- declare function EmptyState({ greeting, description, suggestions, onPickSuggestion, className, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
3580
-
3581
- interface ErrorBannerProps {
3582
- error: string | null;
3583
- onDismiss?: () => void;
3584
- onRetry?: () => void;
3585
- className?: string;
3586
- }
3587
- declare function ErrorBanner({ error, onDismiss, onRetry, className }: ErrorBannerProps): react_jsx_runtime.JSX.Element;
3588
-
3589
- interface JumpToLatestProps {
3590
- visible?: boolean;
3591
- unreadCount?: number;
3592
- onClick?: () => void;
3593
- className?: string;
3594
- }
3595
- declare function JumpToLatest({ visible, unreadCount, onClick, className }: JumpToLatestProps): react_jsx_runtime.JSX.Element;
3596
-
3597
- interface StreamingIndicatorProps {
3598
- variant?: 'dots' | 'pulse';
3599
- label?: string;
3600
- className?: string;
3601
- }
3602
- /**
3603
- * StreamingIndicator — animated dots or pulse for streaming state.
3604
- *
3605
- * Memoised: re-renders only when `variant`, `label` or `className`
3606
- * change. All props are primitives, so default shallow comparison is
3607
- * sufficient.
3608
- */
3609
- declare function StreamingIndicatorRaw({ variant, label, className }: StreamingIndicatorProps): react_jsx_runtime.JSX.Element;
3610
- declare const StreamingIndicator: react.MemoExoticComponent<typeof StreamingIndicatorRaw>;
3611
-
3612
- interface AudioToggleProps {
3613
- /** Visual size — matches Button sizes. Default: ``icon``. */
3614
- size?: 'sm' | 'icon';
3615
- /** Variant passed to the underlying Button. Default: ``ghost``. */
3616
- variant?: 'ghost' | 'outline' | 'secondary';
3617
- /** Force-show even when no audio config is wired (e.g. for stories). */
3618
- alwaysShow?: boolean;
3619
- className?: string;
3620
- }
3621
- declare function AudioToggle({ size, variant, alwaysShow, className, }: AudioToggleProps): react_jsx_runtime.JSX.Element;
3622
-
3623
- declare const LazyChat: react.ComponentType<ChatRootProps>;
3624
-
3625
- /**
3626
- * Declarative rule for handling a custom URL scheme inside markdown.
3627
- *
3628
- * Each rule owns one href shape (e.g. `cmdop://machine/<uuid>`,
3629
- * `obsidian://open?path=…`) and decides:
3630
- *
3631
- * 1. Whether the URL scheme survives sanitize (`protocols`).
3632
- * 2. How to massage the source markdown before render
3633
- * (`preprocess` — optional; useful for stripping decorative
3634
- * prefixes like the `@` in `@[label](href)` so the chip alone
3635
- * reads as the mention indicator).
3636
- * 3. Which links it owns (`match`), and how to render them
3637
- * (`render`, returning JSX).
3638
- *
3639
- * Rules compose: pass an array, and the renderer iterates top-to-bottom
3640
- * picking the first `match` hit per `<a>`. Anything no rule claims
3641
- * falls through to the built-in chat-link styling (or to a custom
3642
- * `customComponents.a` if both are provided).
3643
- *
3644
- * Prefer `linkRules` over `customComponents` + `extraHrefProtocols` —
3645
- * it's the same pieces with the boilerplate removed.
3646
- */
3647
- interface LinkRule {
3648
- /** Pre-process the raw markdown source before any rendering happens.
3649
- * Pure / synchronous; identity-return when no transform applies. */
3650
- preprocess?: (source: string) => string;
3651
- /** Predicate against the resolved href. */
3652
- match: (href: string) => boolean;
3653
- /** Render the link this rule owns. `children` is the link's label
3654
- * (markdown-rendered React content). */
3655
- render: (props: {
3656
- href: string;
3657
- children: react__default.ReactNode;
3658
- isUser: boolean;
3659
- }) => react__default.ReactNode;
3660
- /** URL scheme(s) to whitelist on the sanitize side, e.g. `['cmdop']`.
3661
- * Bare schemes only — no `://`. Optional; omit for `http(s)` rules. */
3662
- protocols?: readonly string[];
3663
- /** Diagnostic label, surfaced in dev warnings. Optional. */
3664
- name?: string;
3665
- }
3666
- interface MarkdownMessageProps {
3667
- /** Markdown content to render */
3668
- content: string;
3669
- /** Additional CSS classes */
3670
- className?: string;
3671
- /** Whether the message is from the user (affects styling) */
3672
- isUser?: boolean;
3673
- /** Use compact size (text-xs instead of text-sm) */
3674
- isCompact?: boolean;
3675
- /**
3676
- * Force the plain-text rendering path (single `<div>` with
3677
- * `white-space: pre-wrap`, no ReactMarkdown). Use this for
3678
- * user-authored content where markdown shouldn't be parsed.
3679
- *
3680
- * When `undefined` (default) we run a small heuristic
3681
- * (`looksLikePlainProse`): short single-paragraph text without
3682
- * markdown markers → plain; everything else → ReactMarkdown.
3683
- *
3684
- * Pass an explicit `true` / `false` to opt out of the heuristic
3685
- * entirely.
3686
- */
3687
- plainText?: boolean;
3688
- /**
3689
- * Per-tag overrides merged on top of the built-in renderers.
3690
- *
3691
- * Use this when you need custom rendering for a specific tag without
3692
- * losing the chat-tuned defaults (links, code blocks with copy, etc).
3693
- *
3694
- * For custom URL-scheme link handling, prefer `linkRules` — it's the
3695
- * same ergonomics with the per-consumer boilerplate removed.
3696
- */
3697
- customComponents?: Partial<Components>;
3698
- /**
3699
- * Extra URL protocols allowed in `<a href>` after sanitize.
3700
- *
3701
- * The default schema strips anything that isn't
3702
- * `http(s)/mailto/xmpp/irc(s)` — your custom renderer would receive
3703
- * `href={undefined}` for `cmdop://…` / `obsidian://…` etc. Listing
3704
- * the bare scheme here (e.g. `'cmdop'`, NOT `'cmdop://'`) opts it in.
3705
- *
3706
- * Use carefully: every protocol you add increases what the rendered
3707
- * HTML can do via clicks. Stick to schemes you control.
3708
- */
3709
- extraHrefProtocols?: readonly string[];
3710
- /**
3711
- * Declarative link rules — preferred over `customComponents` +
3712
- * `extraHrefProtocols` for chat-style apps that want pluggable
3713
- * URL-scheme handling without re-implementing the custom-`a`
3714
- * boilerplate per consumer.
3715
- *
3716
- * If you provide both `linkRules` and `extraHrefProtocols`, the
3717
- * effective protocol list is the union of the two.
3718
- */
3719
- linkRules?: readonly LinkRule[];
3720
- /**
3721
- * Enable collapsible "Read more..." functionality
3722
- * @default false
3723
- */
3724
- collapsible?: boolean;
3725
- /** Maximum character length before showing "Read more...". */
3726
- maxLength?: number;
3727
- /** Maximum number of lines before showing "Read more...". */
3728
- maxLines?: number;
3729
- /** Custom "Read more" button text. @default "Read more..." */
3730
- readMoreLabel?: string;
3731
- /** Custom "Show less" button text. @default "Show less" */
3732
- showLessLabel?: string;
3733
- /** Start expanded (only when `collapsible` is true). @default false */
3734
- defaultExpanded?: boolean;
3735
- /** Callback when collapsed state changes */
3736
- onCollapseChange?: (isCollapsed: boolean) => void;
3737
- }
3738
-
3739
- /**
3740
- * MarkdownMessage — chat-tuned markdown renderer.
3741
- *
3742
- * Features:
3743
- * - GitHub Flavored Markdown (GFM) via remark-gfm
3744
- * - Syntax-highlighted code blocks with Copy button
3745
- * - Mermaid diagram rendering (` ```mermaid ` fence)
3746
- * - Tables, lists, blockquotes scaled for chat density
3747
- * - User vs assistant styling modes (`isUser`)
3748
- * - Plain-text fast path: skips ReactMarkdown when content has no
3749
- * markdown syntax (cheaper render, preserves newlines via CSS)
3750
- * - Optional collapsible "Read more..." for long messages
3751
- *
3752
- * Custom URL schemes (chat mentions, deep-links, custom file viewers)
3753
- * are best handled with the declarative `linkRules` prop — see the
3754
- * type definition in `./types.ts` and the storybook for examples.
3755
- *
3756
- * @example
3757
- * ```tsx
3758
- * <MarkdownMessage content="# Hello\n\nThis is **bold** text." />
3759
- *
3760
- * // User message styling
3761
- * <MarkdownMessage content="Some content" isUser />
3762
- *
3763
- * // Custom URL scheme via linkRules
3764
- * <MarkdownMessage
3765
- * content="Talk to [Vps-audi](cmdop://machine/abc-123)"
3766
- * linkRules={[machineMentionRule]}
3767
- * />
3768
- * ```
3769
- *
3770
- * Memoised: re-renders only when props change. `content` is the main
3771
- * trigger — all other props (className, isUser, isCompact, etc.) are
3772
- * compared by value/reference. `onCollapseChange` is compared by
3773
- * reference — callers should stabilise it with useCallback.
3774
- */
3775
- declare function MarkdownMessageRaw({ content, className, isUser, isCompact, plainText, customComponents, extraHrefProtocols, linkRules, collapsible, maxLength, maxLines, readMoreLabel, showLessLabel, defaultExpanded, onCollapseChange, }: MarkdownMessageProps): react_jsx_runtime.JSX.Element;
3776
- declare const MarkdownMessage: react__default.MemoExoticComponent<typeof MarkdownMessageRaw>;
3777
-
3778
- /** Recursively concatenate the text content of a React.ReactNode tree.
3779
- * Used by the markdown renderers (e.g. `<pre>` extracting code) and
3780
- * by consumers that need a plain-string label out of link children. */
3781
- declare function extractTextFromChildren(children: react__default.ReactNode): string;
3782
-
3783
- interface ActionRowProps {
3784
- /** Raw text to copy — pass the same source string used for render. */
3785
- value: string;
3786
- /** Bubble side. Just controls flex alignment; nothing is mirrored. */
3787
- isUser: boolean;
3788
- /**
3789
- * Whether the row is currently shown. Owner-controlled (typically
3790
- * `<ChatMessageRow>` toggles this on hover with a small close delay).
3791
- * The component is intentionally dumb about visibility — owners
3792
- * have full control over reveal logic (hover, focus, always-on,
3793
- * touch behaviour, etc.).
3794
- */
3795
- visible: boolean;
3796
- }
3797
- declare function ActionRowRaw({ value, isUser, visible }: ActionRowProps): react_jsx_runtime.JSX.Element;
3798
- declare const ActionRow: react__default.MemoExoticComponent<typeof ActionRowRaw>;
3799
-
3800
- interface ChatMessageRowProps {
3801
- /** Side of the conversation — drives flex alignment and `isUser`
3802
- * passed to `actions`. */
3803
- isUser: boolean;
3804
- /** The bubble (your own JSX). Anything goes — `<MarkdownMessage>`,
3805
- * custom card, multi-element composition. */
3806
- children: react__default.ReactNode;
3807
- /** Render-prop for the action row. Receives `visible` so the row
3808
- * knows when to fade in/out. Render `null` to opt out. */
3809
- actions?: (visible: boolean, isUser: boolean) => react__default.ReactNode;
3810
- /** Close delay in ms after the cursor leaves the row. Long enough
3811
- * to bridge cursor travel from bubble → action button without
3812
- * flicker. Default 250ms (Radix Tooltip-ish). */
3813
- closeDelayMs?: number;
3814
- /** Optional class on the column container. */
3815
- className?: string;
3816
- }
3817
- declare function ChatMessageRowRaw({ isUser, children, actions, closeDelayMs, className, }: ChatMessageRowProps): react_jsx_runtime.JSX.Element;
3818
- declare const ChatMessageRow: react__default.MemoExoticComponent<typeof ChatMessageRowRaw>;
3819
-
3820
- /**
3821
- * PrettyCode Component - Dynamic Import Wrapper
3822
- *
3823
- * Lazy loads the heavy Prism library (~500KB) only when needed.
3824
- * This significantly reduces the initial bundle size.
3825
- */
3826
-
3827
- interface PrettyCodeProps {
3828
- data: string | object;
3829
- language: Language;
3830
- className?: string;
3831
- mode?: 'dark' | 'light';
3832
- inline?: boolean;
3833
- customBg?: string;
3834
- isCompact?: boolean;
3835
- /** Block scroll capture until user clicks (default: true) */
3836
- scrollIsolation?: boolean;
3837
- /**
3838
- * Line count above which the block starts scrolling instead of growing.
3839
- * ``undefined`` (default) = no cap, block grows to fit. Set e.g. ``50``
3840
- * to inline short snippets and cap long ones.
3841
- */
3842
- maxLines?: number;
3843
- /**
3844
- * Visual variant:
3845
- * - ``"card"`` (default) — full chrome: border, background, hover
3846
- * toolbar (Copy + language tag), optional internal scroll. Suits
3847
- * a standalone code block in documentation prose where the block
3848
- * is its own surface.
3849
- * - ``"plain"`` — chrome-less: no border, no background, no toolbar,
3850
- * no internal scroll. Grows to fit its content. Use when
3851
- * embedding inside another scroll container (e.g. the Response
3852
- * panel) — avoids double-scroll surfaces and lets the parent
3853
- * manage copy/language affordances.
3854
- */
3855
- variant?: 'card' | 'plain';
3856
- }
3857
- declare const PrettyCode: react__default.FC<PrettyCodeProps>;
3858
-
3859
- /**
3860
- * useLottie Hook
3861
- *
3862
- * Hook for loading and managing Lottie animation data
3863
- */
3864
- interface UseLottieOptions {
3865
- /**
3866
- * Animation data (JSON object) or URL to load from
3867
- */
3868
- src: string | object;
3869
- /**
3870
- * Enable caching of loaded animations
3871
- * @default true
3872
- */
3873
- cache?: boolean;
3874
- }
3875
- interface UseLottieReturn {
3876
- /**
3877
- * Loaded animation data
3878
- */
3879
- animationData: object | null;
3880
- /**
3881
- * Loading state
3882
- */
3883
- isLoading: boolean;
3884
- /**
3885
- * Error state
3886
- */
3887
- error: Error | null;
3888
- /**
3889
- * Retry loading the animation
3890
- */
3891
- retry: () => void;
3892
- }
3893
- /**
3894
- * Hook for loading Lottie animations from URLs or objects
3895
- *
3896
- * Features:
3897
- * - Loads animations from URLs or accepts animation objects directly
3898
- * - Caching support to prevent re-fetching the same animation
3899
- * - Error handling with retry capability
3900
- * - Loading states
3901
- *
3902
- * Usage:
3903
- * ```tsx
3904
- * const { animationData, isLoading, error, retry } = useLottie({
3905
- * src: 'https://example.com/animation.json'
3906
- * });
3907
- *
3908
- * if (isLoading) return <div>Loading...</div>;
3909
- * if (error) return <div>Error: {error.message} <button onClick={retry}>Retry</button></div>;
3910
- * if (!animationData) return null;
3911
- *
3912
- * return <LottiePlayer animationData={animationData} />;
3913
- * ```
3914
- */
3915
- declare function useLottie(options: UseLottieOptions): UseLottieReturn;
3916
-
3917
- /**
3918
- * LottiePlayer component wrapper with dynamic import
3919
- *
3920
- * This component automatically handles code splitting and lazy loading
3921
- * of the Lottie player to optimize bundle size.
3922
- *
3923
- * Usage:
3924
- * ```tsx
3925
- * import { LottiePlayer } from '@djangocfg/ui-core/tools';
3926
- *
3927
- * <LottiePlayer
3928
- * src="https://example.com/animation.json"
3929
- * size="md"
3930
- * autoplay
3931
- * loop
3932
- * />
3933
- * ```
3934
- */
3935
- declare function LottiePlayer(props: LottiePlayerProps): react_jsx_runtime.JSX.Element;
3936
-
3937
- interface PlaygroundProps {
3938
- config: PlaygroundConfig;
3939
- }
3940
- declare const Playground: react__default.FC<PlaygroundProps>;
3941
-
3942
- /**
3943
- * VideoPlayer - Unified Video Player Component
3944
- *
3945
- * Supports multiple modes:
3946
- * - vidstack: Full-featured player (YouTube, Vimeo, HLS, DASH)
3947
- * - native: Lightweight HTML5 player
3948
- * - streaming: HTTP Range streaming with auth / Blob sources
3949
- *
3950
- * @example
3951
- * // YouTube video
3952
- * <VideoPlayer source={{ type: 'youtube', id: 'dQw4w9WgXcQ' }} />
3953
- *
3954
- * @example
3955
- * // HLS stream
3956
- * <VideoPlayer source={{ type: 'hls', url: 'https://example.com/video.m3u8' }} />
3957
- *
3958
- * @example
3959
- * // HTTP Range streaming with auth (full source)
3960
- * <VideoPlayer
3961
- * source={{
3962
- * type: 'stream',
3963
- * sessionId: 'abc123',
3964
- * path: '/videos/movie.mp4',
3965
- * getStreamUrl: (id, path) => `/api/stream/${id}?path=${path}&token=${token}`
3966
- * }}
3967
- * />
3968
- *
3969
- * @example
3970
- * // HTTP Range streaming (simplified, using VideoPlayerProvider context)
3971
- * <VideoPlayerProvider sessionId={sessionId} getStreamUrl={getStreamUrl}>
3972
- * <VideoPlayer source={{ type: 'stream', path: '/videos/movie.mp4' }} />
3973
- * </VideoPlayerProvider>
3974
- *
3975
- * @example
3976
- * // Blob/ArrayBuffer
3977
- * <VideoPlayer source={{ type: 'blob', data: arrayBuffer, mimeType: 'video/mp4' }} />
3978
- */
3979
-
3980
- declare const VideoPlayer: react__default.ForwardRefExoticComponent<VideoPlayerProps & {
3981
- source: VideoSourceUnion | SimpleStreamSource;
3982
- } & react__default.RefAttributes<VideoPlayerRef>>;
3983
-
3984
- interface VideoControlsProps {
3985
- player: react__default.RefObject<MediaPlayerInstance | null>;
3986
- className?: string;
3987
- }
3988
- declare function VideoControls({ player, className }: VideoControlsProps): react_jsx_runtime.JSX.Element;
3989
-
3990
- interface VideoErrorFallbackProps extends ErrorFallbackProps {
3991
- /** URL for download button (if provided, shows download button) */
3992
- downloadUrl?: string;
3993
- /** Filename for download */
3994
- downloadFilename?: string;
3995
- /** File size to display */
3996
- fileSize?: string;
3997
- /** Show retry button */
3998
- showRetry?: boolean;
3999
- /** Custom className */
4000
- className?: string;
4001
- /** Custom icon */
4002
- icon?: react__default.ReactNode;
4003
- /** Custom title (defaults to error message) */
4004
- title?: string;
4005
- /** Custom description */
4006
- description?: string;
4007
- }
4008
- /**
4009
- * Pre-built error fallback component for VideoPlayer
4010
- *
4011
- * @example
4012
- * // Basic usage
4013
- * <VideoPlayer
4014
- * source={source}
4015
- * errorFallback={(props) => (
4016
- * <VideoErrorFallback
4017
- * {...props}
4018
- * downloadUrl={getDownloadUrl()}
4019
- * downloadFilename="video.mp4"
4020
- * />
4021
- * )}
4022
- * />
4023
- *
4024
- * @example
4025
- * // With file size
4026
- * <VideoErrorFallback
4027
- * error="Failed to load video"
4028
- * downloadUrl="/api/download/video.mp4"
4029
- * fileSize="125 MB"
4030
- * showRetry
4031
- * retry={() => reloadVideo()}
4032
- * />
4033
- */
4034
- declare function VideoErrorFallback({ error, retry, downloadUrl, downloadFilename, fileSize, showRetry, className, icon, title, description, }: VideoErrorFallbackProps): react_jsx_runtime.JSX.Element;
4035
- interface CreateVideoErrorFallbackOptions {
4036
- /** Function to get download URL from source */
4037
- getDownloadUrl?: (source: unknown) => string | undefined;
4038
- /** Function to get filename from source */
4039
- getFilename?: (source: unknown) => string | undefined;
4040
- /** Function to get file size from source */
4041
- getFileSize?: (source: unknown) => string | undefined;
4042
- /** Show retry button */
4043
- showRetry?: boolean;
4044
- }
4045
- /**
4046
- * Factory to create error fallback function for VideoPlayer
4047
- *
4048
- * @example
4049
- * const errorFallback = createVideoErrorFallback({
4050
- * getDownloadUrl: (source) => source.downloadUrl,
4051
- * getFilename: (source) => source.filename,
4052
- * showRetry: true,
4053
- * });
4054
- *
4055
- * <VideoPlayer source={source} errorFallback={errorFallback} />
4056
- */
4057
- declare function createVideoErrorFallback(options: CreateVideoErrorFallbackOptions): (props: ErrorFallbackProps, source?: unknown) => react__default.ReactNode;
4058
-
4059
- /**
4060
- * VidstackProvider - Full-featured video player using Vidstack
4061
- * Supports YouTube, Vimeo, HLS, DASH, and direct URLs
4062
- */
4063
-
4064
- declare const VidstackProvider: react__default.ForwardRefExoticComponent<VidstackProviderProps & react__default.RefAttributes<VideoPlayerRef>>;
4065
-
4066
- /**
4067
- * NativeProvider - Lightweight native HTML5 video player
4068
- * For demo videos, background videos, autoplay loop muted scenarios
4069
- */
4070
-
4071
- declare const NativeProvider: react__default.ForwardRefExoticComponent<NativeProviderProps & react__default.RefAttributes<VideoPlayerRef>>;
4072
-
4073
- /**
4074
- * StreamProvider - HTTP Range streaming and Blob video player
4075
- * Supports:
4076
- * - HTTP Range requests with authorization (for large files)
4077
- * - Blob/ArrayBuffer sources
4078
- * - Data URL sources
4079
- * - Fill parent container mode
4080
- * - Custom error fallback
4081
- */
4082
-
4083
- declare const StreamProvider: react__default.ForwardRefExoticComponent<StreamProviderProps & react__default.RefAttributes<VideoPlayerRef>>;
4084
-
4085
- /**
4086
- * Provider for VideoPlayer streaming configuration
4087
- *
4088
- * @example
4089
- * // In your app layout or FileWorkspace
4090
- * <VideoPlayerProvider
4091
- * sessionId={sessionId}
4092
- * getStreamUrl={terminalClient.terminal_media.streamStreamRetrieveUrl}
4093
- * >
4094
- * <VideoPlayer source={{ type: 'stream', path: '/video.mp4' }} />
4095
- * </VideoPlayerProvider>
4096
- */
4097
- declare function VideoPlayerProvider({ children, getStreamUrl, sessionId, }: VideoPlayerProviderProps): react_jsx_runtime.JSX.Element;
4098
- /**
4099
- * Hook to access VideoPlayer context
4100
- */
4101
- declare function useVideoPlayerContext(): VideoPlayerContextValue | null;
4102
-
4103
- /**
4104
- * Video source and player mode resolvers
4105
- */
4106
-
4107
- /**
4108
- * Determine which provider to use based on source type
4109
- */
4110
- declare function resolvePlayerMode(source: VideoSourceUnion, mode?: PlayerMode): 'vidstack' | 'native' | 'streaming';
4111
- /**
4112
- * Check if source is a simplified stream source (without getStreamUrl)
4113
- */
4114
- declare function isSimpleStreamSource(source: VideoSourceUnion | SimpleStreamSource | undefined | null): source is SimpleStreamSource;
4115
- /**
4116
- * Resolve simplified stream source to full stream source using context
4117
- */
4118
- declare function resolveStreamSource(source: SimpleStreamSource, context: VideoPlayerContextValue | null): StreamSource | null;
4119
-
4120
- /**
4121
- * File source resolution utilities
4122
- */
4123
-
4124
- /**
4125
- * Resolve file content to VideoSourceUnion
4126
- * Useful for FileWorkspace/file manager integrations
4127
- *
4128
- * @example
4129
- * const source = resolveFileSource({
4130
- * content: file.content,
4131
- * path: file.path,
4132
- * mimeType: file.mimeType,
4133
- * sessionId: sessionId,
4134
- * loadMethod: file.loadMethod,
4135
- * getStreamUrl: terminalClient.terminal_media.streamStreamRetrieveUrl
4136
- * });
4137
- *
4138
- * <VideoPlayer source={source} />
4139
- */
4140
- declare function resolveFileSource(options: ResolveFileSourceOptions): VideoSourceUnion | null;
4141
-
4142
- declare const Player: react.ForwardRefExoticComponent<PlayerProps & react.RefAttributes<PlayerHandle>>;
4143
-
4144
- declare function ImageViewer({ images, initialIndex, inDialog, }: ImageViewerProps): react_jsx_runtime.JSX.Element;
4145
-
4146
- declare function CronSchedulerProvider({ children, value, onChange, defaultType, }: CronSchedulerProviderProps): react_jsx_runtime.JSX.Element;
4147
- declare function useCronSchedulerContext(): CronSchedulerContextValue;
4148
-
4149
- /**
4150
- * Hook for schedule type selection
4151
- * Re-renders only when type changes
4152
- */
4153
- declare function useCronType(): {
4154
- type: ScheduleType;
4155
- setType: (type: ScheduleType) => void;
4156
- };
4157
- /**
4158
- * Hook for time selection
4159
- * Re-renders only when hour/minute changes
4160
- */
4161
- declare function useCronTime(): {
4162
- hour: number;
4163
- minute: number;
4164
- setTime: (hour: number, minute: number) => void;
4165
- };
4166
- /**
4167
- * Hook for week days selection
4168
- * Re-renders only when weekDays changes
4169
- */
4170
- declare function useCronWeekDays(): {
4171
- weekDays: WeekDay[];
4172
- toggleWeekDay: (day: WeekDay) => void;
4173
- setWeekDays: (days: WeekDay[]) => void;
4174
- };
4175
- /**
4176
- * Hook for month days selection
4177
- * Re-renders only when monthDays changes
4178
- */
4179
- declare function useCronMonthDays(): {
4180
- monthDays: MonthDay[];
4181
- toggleMonthDay: (day: MonthDay) => void;
4182
- setMonthDays: (days: MonthDay[]) => void;
4183
- };
4184
- /**
4185
- * Hook for custom cron input
4186
- * Re-renders only when customCron/isValid changes
4187
- */
4188
- declare function useCronCustom(): {
4189
- customCron: string;
4190
- isValid: boolean;
4191
- setCustomCron: (cron: string) => void;
4192
- };
4193
- /**
4194
- * Hook for preview display
4195
- * Re-renders only when computed values change
4196
- */
4197
- declare function useCronPreview(): {
4198
- cronExpression: string;
4199
- humanDescription: string;
4200
- isValid: boolean;
4201
- initialValue: string;
4202
- };
4203
- /**
4204
- * Full context access
4205
- * Use sparingly - causes re-render on any state change
4206
- */
4207
- declare function useCronScheduler(): CronSchedulerContextValue;
4208
-
4209
- /**
4210
- * Cron Builder
4211
- *
4212
- * Converts CronSchedulerState to Unix 5-field cron expression
4213
- * Format: minute hour day-of-month month day-of-week
4214
- */
4215
-
4216
- /**
4217
- * Builds Unix 5-field cron expression from state
4218
- *
4219
- * @example
4220
- * // Daily at 9:00
4221
- * buildCron({ type: 'daily', hour: 9, minute: 0, ... }) // '0 9 * * *'
4222
- *
4223
- * // Weekly on Mon, Wed, Fri at 14:30
4224
- * buildCron({ type: 'weekly', hour: 14, minute: 30, weekDays: [1, 3, 5], ... }) // '30 14 * * 1,3,5'
4225
- *
4226
- * // Monthly on 1st and 15th at 0:00
4227
- * buildCron({ type: 'monthly', hour: 0, minute: 0, monthDays: [1, 15], ... }) // '0 0 1,15 * *'
4228
- */
4229
- declare function buildCron(state: CronSchedulerState): string;
4230
-
4231
- /**
4232
- * Cron Parser
4233
- *
4234
- * Parses Unix 5-field cron expression into CronSchedulerState
4235
- * Format: minute hour day-of-month month day-of-week
4236
- */
4237
-
4238
- /**
4239
- * Parses Unix 5-field cron expression into state
4240
- *
4241
- * @param cron - Cron expression to parse
4242
- * @returns Parsed state or null if invalid
4243
- *
4244
- * @example
4245
- * parseCron('0 9 * * *')
4246
- * // { type: 'daily', hour: 9, minute: 0, ... }
4247
- *
4248
- * parseCron('30 14 * * 1,3,5')
4249
- * // { type: 'weekly', hour: 14, minute: 30, weekDays: [1, 3, 5], ... }
4250
- */
4251
- declare function parseCron(cron: string): CronSchedulerState | null;
4252
- /**
4253
- * Validates cron expression syntax
4254
- */
4255
- declare function isValidCron(cron: string): boolean;
4256
-
4257
- /**
4258
- * Cron Humanize
4259
- *
4260
- * Converts cron expressions to human-readable descriptions
4261
- */
4262
- /**
4263
- * Converts cron expression to human-readable description
4264
- *
4265
- * Examples:
4266
- * - humanizeCron('0 9 * * *') returns "Every day at 09:00"
4267
- * - humanizeCron('30 14 * * 1,3,5') returns "Mon, Wed, Fri at 14:30"
4268
- * - humanizeCron('0 0 1 * *') returns "1st of every month at 00:00"
4269
- */
4270
- declare function humanizeCron(cron: string): string;
4271
-
4272
- interface ScheduleTypeSelectorProps {
4273
- disabled?: boolean;
4274
- className?: string;
4275
- }
4276
- declare function ScheduleTypeSelector({ disabled, className, }: ScheduleTypeSelectorProps): react_jsx_runtime.JSX.Element;
4277
-
4278
- interface TimeSelectorProps {
4279
- format?: '12h' | '24h';
4280
- disabled?: boolean;
4281
- className?: string;
4282
- }
4283
- declare function TimeSelector({ format, disabled, className, }: TimeSelectorProps): react_jsx_runtime.JSX.Element;
4284
-
4285
- interface DayChipsProps {
4286
- disabled?: boolean;
4287
- showPresets?: boolean;
4288
- className?: string;
4289
- }
4290
- declare function DayChips({ disabled, showPresets, className, }: DayChipsProps): react_jsx_runtime.JSX.Element;
4291
-
4292
- interface MonthDayGridProps {
4293
- disabled?: boolean;
4294
- showPresets?: boolean;
4295
- className?: string;
4296
- }
4297
- declare function MonthDayGrid({ disabled, showPresets, className, }: MonthDayGridProps): react_jsx_runtime.JSX.Element;
4298
-
4299
- interface CustomInputProps {
4300
- disabled?: boolean;
4301
- className?: string;
4302
- }
4303
- declare function CustomInput({ disabled, className }: CustomInputProps): react_jsx_runtime.JSX.Element;
4304
-
4305
- interface SchedulePreviewProps {
4306
- /** Show raw cron expression (default: true) */
4307
- showCronExpression?: boolean;
4308
- /** Enable copy to clipboard */
4309
- allowCopy?: boolean;
4310
- /** Show initial value when changed (default: true) */
4311
- showInitialValue?: boolean;
4312
- /** Additional CSS classes */
4313
- className?: string;
4314
- }
4315
- declare function SchedulePreview({ showCronExpression, allowCopy, showInitialValue, className, }: SchedulePreviewProps): react_jsx_runtime.JSX.Element;
4316
-
4317
- /**
4318
- * CronScheduler with Suspense wrapper
4319
- */
4320
- declare function CronScheduler(props: CronSchedulerProps): react_jsx_runtime.JSX.Element;
4321
-
4322
- interface EditorFile {
4323
- /** Unique file path */
4324
- path: string;
4325
- /** File content */
4326
- content: string;
4327
- /** Detected or specified language */
4328
- language: string;
4329
- /** Whether file has unsaved changes */
4330
- isDirty: boolean;
4331
- /** Monaco model reference */
4332
- model?: monaco.editor.ITextModel;
4333
- }
4334
- interface EditorOptions {
4335
- /** Editor theme: 'vs' | 'vs-dark' | 'hc-black' | custom */
4336
- theme?: string;
4337
- /** Font size in pixels */
4338
- fontSize?: number;
4339
- /** Font family */
4340
- fontFamily?: string;
4341
- /** Tab size */
4342
- tabSize?: number;
4343
- /** Insert spaces instead of tabs */
4344
- insertSpaces?: boolean;
4345
- /** Word wrap mode */
4346
- wordWrap?: 'off' | 'on' | 'wordWrapColumn' | 'bounded';
4347
- /** Show minimap */
4348
- minimap?: boolean;
4349
- /** Show line numbers */
4350
- lineNumbers?: 'on' | 'off' | 'relative' | 'interval';
4351
- /** Read-only mode */
4352
- readOnly?: boolean;
4353
- }
4354
- interface EditorProps {
4355
- /** File content */
4356
- value?: string;
4357
- /** Programming language for syntax highlighting */
4358
- language?: string;
4359
- /** Called when content changes */
4360
- onChange?: (value: string) => void;
4361
- /** Called when editor is mounted */
4362
- onMount?: (editor: monaco.editor.IStandaloneCodeEditor) => void;
4363
- /** Editor options */
4364
- options?: EditorOptions;
4365
- /** CSS class name */
4366
- className?: string;
4367
- /** Height — fixed px, CSS string, or '100%' (default: '100%'). Ignored when autoHeight=true */
4368
- height?: string | number;
4369
- /** Width (default: '100%') */
4370
- width?: string | number;
4371
- /** Auto-resize height to fit content. Editor grows/shrinks with content lines */
4372
- autoHeight?: boolean;
4373
- /** Min height in px when autoHeight is enabled (default: 100) */
4374
- minHeight?: number;
4375
- /** Max height in px when autoHeight is enabled (default: 600) */
4376
- maxHeight?: number;
4377
- }
4378
- interface DiffEditorProps {
4379
- /** Original content (left side) */
4380
- original: string;
4381
- /** Modified content (right side) */
4382
- modified: string;
4383
- /** Programming language */
4384
- language?: string;
4385
- /** Editor options */
4386
- options?: EditorOptions;
4387
- /** CSS class name */
4388
- className?: string;
4389
- /** Height (default: '100%') */
4390
- height?: string | number;
4391
- }
4392
- interface EditorContextValue {
4393
- /** Currently open files */
4394
- openFiles: EditorFile[];
4395
- /** Currently active file */
4396
- activeFile: EditorFile | null;
4397
- /** Monaco instance (null during SSR) */
4398
- monaco: typeof monaco | null;
4399
- /** Editor instance */
4400
- editor: monaco.editor.IStandaloneCodeEditor | null;
4401
- /** Whether editor is ready */
4402
- isReady: boolean;
4403
- openFile: (path: string, content: string, language?: string) => void;
4404
- closeFile: (path: string) => void;
4405
- setActiveFile: (path: string) => void;
4406
- updateContent: (path: string, content: string) => void;
4407
- saveFile: (path: string) => Promise<void>;
4408
- isDirty: (path: string) => boolean;
4409
- getContent: (path: string) => string | null;
4410
- getFile: (path: string) => EditorFile | null;
4411
- }
4412
- interface UseEditorReturn {
4413
- /** Editor instance */
4414
- editor: monaco.editor.IStandaloneCodeEditor | null;
4415
- /** Whether editor is mounted and ready */
4416
- isReady: boolean;
4417
- /** Set editor reference */
4418
- setEditor: (editor: monaco.editor.IStandaloneCodeEditor | null) => void;
4419
- }
4420
- interface UseMonacoReturn {
4421
- /** Monaco namespace */
4422
- monaco: typeof monaco | null;
4423
- /** Whether Monaco is loaded */
4424
- isLoading: boolean;
4425
- /** Loading error if any */
4426
- error: Error | null;
4427
- }
4428
-
4429
- interface EditorRef {
4430
- /** Get editor instance */
4431
- getEditor: () => monaco.editor.IStandaloneCodeEditor | null;
4432
- /** Get current value */
4433
- getValue: () => string;
4434
- /** Set value */
4435
- setValue: (value: string) => void;
4436
- /** Focus editor */
4437
- focus: () => void;
4438
- }
4439
- /**
4440
- * Monaco Editor Component
4441
- *
4442
- * A React wrapper around Monaco Editor with full TypeScript support.
4443
- *
4444
- * @example
4445
- * ```tsx
4446
- * <Editor
4447
- * value={code}
4448
- * language="typescript"
4449
- * onChange={(value) => setCode(value)}
4450
- * options={{ fontSize: 14, minimap: false }}
4451
- * />
4452
- * ```
4453
- */
4454
- declare const Editor: react.ForwardRefExoticComponent<EditorProps & react.RefAttributes<EditorRef>>;
4455
-
4456
- /**
4457
- * Monaco Diff Editor Component
4458
- *
4459
- * Side-by-side or inline diff view for comparing two versions of content.
4460
- *
4461
- * @example
4462
- * ```tsx
4463
- * <DiffEditor
4464
- * original={originalCode}
4465
- * modified={modifiedCode}
4466
- * language="typescript"
4467
- * />
4468
- * ```
4469
- */
4470
- declare function DiffEditor({ original, modified, language, options, className, height, }: DiffEditorProps): react_jsx_runtime.JSX.Element;
4471
-
4472
- /**
4473
- * Hook to access editor context
4474
- * Must be used within EditorProvider
4475
- */
4476
- declare function useEditorContext(): EditorContextValue;
4477
- interface EditorProviderProps {
4478
- children: React.ReactNode;
4479
- /** Callback when file save is requested */
4480
- onSave?: (path: string, content: string) => Promise<void>;
4481
- }
4482
- /**
4483
- * Editor Context Provider
4484
- *
4485
- * Manages multiple open files, active file state, and editor instance.
4486
- *
4487
- * @example
4488
- * ```tsx
4489
- * <EditorProvider onSave={handleSave}>
4490
- * <EditorTabs />
4491
- * <Editor />
4492
- * </EditorProvider>
4493
- * ```
4494
- */
4495
- declare function EditorProvider({ children, onSave }: EditorProviderProps): react_jsx_runtime.JSX.Element;
4496
-
4497
- /**
4498
- * Hook to load and access Monaco Editor instance
4499
- *
4500
- * Handles:
4501
- * - Dynamic import of Monaco (client-side only)
4502
- * - Web worker configuration
4503
- * - Loading state management
4504
- *
4505
- * @example
4506
- * ```tsx
4507
- * const { monaco, isLoading, error } = useMonaco();
4508
- *
4509
- * if (isLoading) return <Spinner />;
4510
- * if (error) return <Error message={error.message} />;
4511
- *
4512
- * // Use monaco API
4513
- * monaco.editor.create(...)
4514
- * ```
4515
- */
4516
- declare function useMonaco(): UseMonacoReturn;
4517
-
4518
- /**
4519
- * Hook to manage editor instance reference
4520
- *
4521
- * @example
4522
- * ```tsx
4523
- * const { editor, isReady, setEditor } = useEditor();
4524
- *
4525
- * // Pass setEditor to Editor component's onMount
4526
- * <Editor onMount={setEditor} />
4527
- *
4528
- * // Use editor when ready
4529
- * if (isReady) {
4530
- * editor.getModel()?.getValue();
4531
- * }
4532
- * ```
4533
- */
4534
- declare function useEditor(): UseEditorReturn;
4535
-
4536
- /**
4537
- * Hook to detect language from filename
4538
- *
4539
- * @param filename - File name or path
4540
- * @returns Monaco language ID
4541
- *
4542
- * @example
4543
- * ```tsx
4544
- * const language = useLanguage('app.tsx');
4545
- * // Returns: 'typescript'
4546
- *
4547
- * const language2 = useLanguage('/path/to/Dockerfile');
4548
- * // Returns: 'dockerfile'
4549
- * ```
4550
- */
4551
- declare function useLanguage(filename: string | undefined): string;
4552
-
4553
- /** Item that can be mentioned via @ trigger */
4554
- interface MentionItem {
4555
- id: string;
4556
- label: string;
4557
- description?: string;
4558
- thumbnail?: string;
4559
- }
4560
- /**
4561
- * Attributes available when rendering a mention to markdown.
4562
- *
4563
- * Same shape Tiptap stores on the `mention` node — `id` is the stable
4564
- * identifier the suggestion popover injected, `label` is the human text
4565
- * shown to the user. Either field may be empty if the upstream config
4566
- * never populated it; renderers should fall back accordingly.
4567
- */
4568
- interface MentionAttrs {
4569
- id: string;
4570
- label: string;
4571
- }
4572
- /**
4573
- * Function that converts a mention node into its markdown serialization.
4574
- *
4575
- * The returned string is what `@tiptap/markdown` writes into the markdown
4576
- * output of `MarkdownEditor.getMarkdown()`.
4577
- */
4578
- type MentionMarkdownRenderer = (attrs: MentionAttrs) => string;
4579
- /** Mention configuration */
4580
- interface MentionConfig {
4581
- /** Trigger character (default: '@') */
4582
- trigger?: string;
4583
- /** Available items */
4584
- items: MentionItem[];
4585
- /** Max dropdown items (default: 5) */
4586
- maxItems?: number;
4587
- /**
4588
- * Custom serializer for mentions when `MarkdownEditor.getMarkdown()` runs.
4589
- *
4590
- * Defaults to `mentionPresets.plainAt` which yields `@<label>` (or `@<id>`
4591
- * when `label` is missing). Use one of `mentionPresets`, or supply your
4592
- * own function for full control over how mentions appear in the output
4593
- * markdown string.
4594
- *
4595
- * Note: this only affects the *markdown* output. `editor.getText()` and
4596
- * the rendered DOM still go through `renderText` (`@<label>` by default).
4597
- */
4598
- renderMarkdown?: MentionMarkdownRenderer;
4599
- }
4600
-
4601
- interface MarkdownEditorProps {
4602
- value: string;
4603
- onChange: (value: string) => void;
4604
- placeholder?: string;
4605
- minHeight?: number;
4606
- className?: string;
4607
- disabled?: boolean;
4608
- showToolbar?: boolean;
4609
- /**
4610
- * `@`-mention autocomplete config.
4611
- *
4612
- * IMPORTANT: Tiptap's `useEditor` initialises the editor exactly once.
4613
- * The `Mention` extension is only registered when `mentions` is truthy
4614
- * on the FIRST render — handing in a real config later (e.g. after an
4615
- * async items fetch) silently does nothing, and typing `@` will not
4616
- * open the popover.
4617
- *
4618
- * If you want mentions even with async-loaded items, pass
4619
- * `{ items: [] }` from the very first render and update the array
4620
- * when data arrives. Either keep the `MentionConfig` object identity
4621
- * stable across renders and mutate `items` in place (the suggestion
4622
- * plugin captures the config by closure and reads `items` on each
4623
- * query), or accept that swapping the whole object reference is a
4624
- * no-op for the live editor.
4625
- */
4626
- mentions?: MentionConfig;
4627
- /** Called when mentioned IDs change */
4628
- onMentionIdsChange?: (ids: string[]) => void;
4629
- /**
4630
- * Called when the user presses Enter (without Shift, no IME
4631
- * composition, no mention popover open). When set, Enter submits
4632
- * and Shift+Enter inserts a newline — ChatGPT / Telegram chat
4633
- * behaviour. When omitted, Enter behaves as Tiptap default
4634
- * (HardBreak).
4635
- *
4636
- * Implementation lives in `submitOnEnter.ts` — it's a Tiptap
4637
- * keymap extension, NOT a React wrapper handler. Wrapper-level
4638
- * onKeyDown fires AFTER ProseMirror's keymap commits HardBreak in
4639
- * the same tick; routing through the extension lets us intercept
4640
- * before HardBreak runs.
4641
- *
4642
- * Return value (optional): truthy / undefined = consume the key
4643
- * (default). Return `false` from onSubmit to let Tiptap fall
4644
- * through to HardBreak — useful for guards like "don't submit an
4645
- * empty draft".
4646
- */
4647
- onSubmit?: () => boolean | void;
4648
- }
4649
- /**
4650
- * Imperative handle exposed via `ref`. Matches `ComposerHandle` from
4651
- * `@djangocfg/ui-tools/chat` so consumers can forward it straight into
4652
- * `useRegisterComposer({ focus, moveCursorToEnd })` — that's what makes
4653
- * voice dictation (`VoiceComposerSlot`) push live text into a TipTap
4654
- * composer.
4655
- */
4656
- interface MarkdownEditorHandle {
4657
- /** Move keyboard focus into the editor. */
4658
- focus: () => void;
4659
- /** Place the caret at the end of the document (and focus). */
4660
- moveCursorToEnd: () => void;
4661
- /** Escape hatch — the underlying TipTap `Editor` instance. */
4662
- getEditor: () => Editor$1 | null;
4663
- }
4664
- declare const MarkdownEditor: react.ForwardRefExoticComponent<MarkdownEditorProps & react.RefAttributes<MarkdownEditorHandle>>;
4665
-
4666
- /**
4667
- * Built-in serializers for the `MentionConfig.renderMarkdown` callback.
4668
- *
4669
- * Pick one based on what consumes the markdown:
4670
- *
4671
- * - LLM / chat composer → `plainAt` (the default)
4672
- * - Plain text export → `plainLabel`
4673
- * - Web app with deep-link → `markdownLink(baseUrl)`
4674
- * - Notion / Linear-style → `customUri(scheme, kind)`
4675
- * - Slack-style id refs → `slackStyle`
4676
- * - HTML-allowing renderer → `htmlSpan(className?)`
4677
- *
4678
- * Or pass a custom function — the type is just `(attrs) => string`.
4679
- */
4680
- declare const mentionPresets: {
4681
- /** "@Label" — default, ideal for chat where LLMs read the text. */
4682
- plainAt: MentionMarkdownRenderer;
4683
- /** "Label" — bare label, no @ prefix. */
4684
- plainLabel: MentionMarkdownRenderer;
4685
- /** "[@Label](baseUrl/id)" — clickable markdown link. */
4686
- markdownLink: (baseUrl: string) => MentionMarkdownRenderer;
4687
- /** "@[Label](scheme://kind/id)" — Notion / Linear-style custom URI. */
4688
- customUri: (scheme: string, kind: string) => MentionMarkdownRenderer;
4689
- /** "<@id>" — Slack-style id-only reference (label dropped — receivers resolve it). */
4690
- slackStyle: MentionMarkdownRenderer;
4691
- /** Inline HTML span — for products that consume markdown with raw HTML allowed. */
4692
- htmlSpan: (className?: string) => MentionMarkdownRenderer;
4693
- };
4694
-
4695
- interface BlobUrlEntry {
4696
- url: string;
4697
- refCount: number;
4698
- createdAt: number;
4699
- }
4700
- interface ImageDimensions {
4701
- width: number;
4702
- height: number;
4703
- }
4704
- interface VideoMetadata {
4705
- duration: number;
4706
- width: number;
4707
- height: number;
4708
- codec?: string;
4709
- }
4710
- interface EffectConfig {
4711
- opacity: number;
4712
- scale: number;
4713
- blur: string;
4714
- }
4715
- /** Video player settings (persisted) */
4716
- interface VideoPlayerSettings {
4717
- volume: number;
4718
- isLooping: boolean;
4719
- }
4720
- interface MediaCacheState {
4721
- blobUrls: Map<string, BlobUrlEntry>;
4722
- imageDimensions: Map<string, ImageDimensions>;
4723
- audioPlaybackPositions: Map<string, number>;
4724
- audioEffectConfigs: Map<string, EffectConfig>;
4725
- videoStreamUrls: Map<string, {
4726
- url: string;
4727
- timestamp: number;
4728
- }>;
4729
- videoPosterUrls: Map<string, string>;
4730
- videoPlaybackPositions: Map<string, number>;
4731
- videoMetadata: Map<string, VideoMetadata>;
4732
- videoPlayerSettings: VideoPlayerSettings;
4733
- }
4734
- interface MediaCacheActions {
4735
- getOrCreateBlobUrl: (key: string, content: ArrayBuffer, mimeType: string) => string;
4736
- releaseBlobUrl: (key: string) => void;
4737
- hasBlobUrl: (key: string) => boolean;
4738
- cacheDimensions: (src: string, dims: ImageDimensions) => void;
4739
- getDimensions: (src: string) => ImageDimensions | null;
4740
- saveAudioPosition: (uri: string, time: number) => void;
4741
- getAudioPosition: (uri: string) => number | null;
4742
- getEffectConfig: (key: string) => EffectConfig | null;
4743
- cacheEffectConfig: (key: string, config: EffectConfig) => void;
4744
- getOrCreateStreamUrl: (sessionId: string, path: string, generator: (sessionId: string, path: string) => string) => string;
4745
- getPosterUrl: (title: string) => string | null;
4746
- cachePosterUrl: (title: string, url: string) => void;
4747
- saveVideoPosition: (key: string, time: number) => void;
4748
- getVideoPosition: (key: string) => number | null;
4749
- cacheVideoMetadata: (url: string, meta: VideoMetadata) => void;
4750
- getVideoMetadata: (url: string) => VideoMetadata | null;
4751
- invalidateSession: (sessionId: string) => void;
4752
- getVideoPlayerSettings: () => VideoPlayerSettings;
4753
- saveVideoPlayerSettings: (settings: Partial<VideoPlayerSettings>) => void;
4754
- clearCache: () => void;
4755
- getCacheStats: () => {
4756
- blobUrls: number;
4757
- dimensions: number;
4758
- audioPositions: number;
4759
- videoPositions: number;
4760
- };
4761
- }
4762
- type MediaCacheStore = MediaCacheState & MediaCacheActions;
4763
- declare const useMediaCacheStore: zustand.UseBoundStore<Omit<Omit<zustand.StoreApi<MediaCacheStore>, "setState" | "devtools"> & {
4764
- setState(partial: MediaCacheStore | Partial<MediaCacheStore> | ((state: MediaCacheStore) => MediaCacheStore | Partial<MediaCacheStore>), replace?: false, action?: string | {
4765
- [x: string]: unknown;
4766
- [x: number]: unknown;
4767
- [x: symbol]: unknown;
4768
- type: string;
4769
- }): void;
4770
- setState(state: MediaCacheStore | ((state: MediaCacheStore) => MediaCacheStore), replace: true, action?: string | {
4771
- [x: string]: unknown;
4772
- [x: number]: unknown;
4773
- [x: symbol]: unknown;
4774
- type: string;
4775
- }): void;
4776
- devtools: {
4777
- cleanup: () => void;
4778
- };
4779
- }, "setState" | "persist"> & {
4780
- setState(partial: MediaCacheStore | Partial<MediaCacheStore> | ((state: MediaCacheStore) => MediaCacheStore | Partial<MediaCacheStore>), replace?: false, action?: string | {
4781
- [x: string]: unknown;
4782
- [x: number]: unknown;
4783
- [x: symbol]: unknown;
4784
- type: string;
4785
- }): unknown;
4786
- setState(state: MediaCacheStore | ((state: MediaCacheStore) => MediaCacheStore), replace: true, action?: string | {
4787
- [x: string]: unknown;
4788
- [x: number]: unknown;
4789
- [x: symbol]: unknown;
4790
- type: string;
4791
- }): unknown;
4792
- persist: {
4793
- setOptions: (options: Partial<zustand_middleware.PersistOptions<MediaCacheStore, {
4794
- audioPlaybackPositions: [string, number][];
4795
- videoPlaybackPositions: [string, number][];
4796
- videoPosterUrls: [string, string][];
4797
- videoPlayerSettings: VideoPlayerSettings;
4798
- }, unknown>>) => void;
4799
- clearStorage: () => void;
4800
- rehydrate: () => Promise<void> | void;
4801
- hasHydrated: () => boolean;
4802
- onHydrate: (fn: (state: MediaCacheStore) => void) => () => void;
4803
- onFinishHydration: (fn: (state: MediaCacheStore) => void) => () => void;
4804
- getOptions: () => Partial<zustand_middleware.PersistOptions<MediaCacheStore, {
4805
- audioPlaybackPositions: [string, number][];
4806
- videoPlaybackPositions: [string, number][];
4807
- videoPosterUrls: [string, string][];
4808
- videoPlayerSettings: VideoPlayerSettings;
4809
- }, unknown>>;
4810
- };
4811
- }>;
4812
- /**
4813
- * Hook for image-related cache operations
4814
- * Uses useShallow to prevent infinite re-renders
4815
- */
4816
- declare const useImageCache: () => {
4817
- getOrCreateBlobUrl: (key: string, content: ArrayBuffer, mimeType: string) => string;
4818
- releaseBlobUrl: (key: string) => void;
4819
- hasBlobUrl: (key: string) => boolean;
4820
- cacheDimensions: (src: string, dims: ImageDimensions) => void;
4821
- getDimensions: (src: string) => ImageDimensions | null;
4822
- };
4823
- /**
4824
- * Hook for audio-related cache operations
4825
- * Uses useShallow to prevent infinite re-renders
4826
- */
4827
- declare const useAudioCache: () => {
4828
- getOrCreateBlobUrl: (key: string, content: ArrayBuffer, mimeType: string) => string;
4829
- releaseBlobUrl: (key: string) => void;
4830
- hasBlobUrl: (key: string) => boolean;
4831
- saveAudioPosition: (uri: string, time: number) => void;
4832
- getAudioPosition: (uri: string) => number | null;
4833
- getEffectConfig: (key: string) => EffectConfig | null;
4834
- cacheEffectConfig: (key: string, config: EffectConfig) => void;
4835
- };
4836
- /**
4837
- * Hook for video-related cache operations
4838
- * Uses useShallow to prevent infinite re-renders
4839
- */
4840
- declare const useVideoCache: () => {
4841
- getOrCreateBlobUrl: (key: string, content: ArrayBuffer, mimeType: string) => string;
4842
- releaseBlobUrl: (key: string) => void;
4843
- hasBlobUrl: (key: string) => boolean;
4844
- getOrCreateStreamUrl: (sessionId: string, path: string, generator: (sessionId: string, path: string) => string) => string;
4845
- getPosterUrl: (title: string) => string | null;
4846
- cachePosterUrl: (title: string, url: string) => void;
4847
- saveVideoPosition: (key: string, time: number) => void;
4848
- getVideoPosition: (key: string) => number | null;
4849
- cacheVideoMetadata: (url: string, meta: VideoMetadata) => void;
4850
- getVideoMetadata: (url: string) => VideoMetadata | null;
4851
- invalidateSession: (sessionId: string) => void;
4852
- getVideoPlayerSettings: () => VideoPlayerSettings;
4853
- saveVideoPlayerSettings: (settings: Partial<VideoPlayerSettings>) => void;
4854
- };
4855
- /**
4856
- * Hook for video player settings only
4857
- * Returns current settings and save function
4858
- */
4859
- declare const useVideoPlayerSettings: () => {
4860
- settings: VideoPlayerSettings;
4861
- saveSettings: (settings: Partial<VideoPlayerSettings>) => void;
4862
- };
4863
- /**
4864
- * Hook for blob URL cleanup on unmount
4865
- */
4866
- declare function useBlobUrlCleanup(key: string | null): void;
4867
- /**
4868
- * Generate a cache key from ArrayBuffer content
4869
- * Uses first and last 1KB + length for fast hashing
4870
- */
4871
- declare function generateContentKey(content: ArrayBuffer): string;
4872
-
4873
- interface UseCollapsibleContentOptions {
4874
- /**
4875
- * Maximum character length before collapsing
4876
- * If both maxLength and maxLines are set, the stricter limit applies
4877
- */
4878
- maxLength?: number;
4879
- /**
4880
- * Maximum number of lines before collapsing
4881
- * If both maxLength and maxLines are set, the stricter limit applies
4882
- */
4883
- maxLines?: number;
4884
- /**
4885
- * Start in expanded state (default: false - starts collapsed)
4886
- */
4887
- defaultExpanded?: boolean;
4888
- }
4889
- interface UseCollapsibleContentResult {
4890
- /** Whether content is currently collapsed */
4891
- isCollapsed: boolean;
4892
- /** Toggle between collapsed/expanded state */
4893
- toggleCollapsed: () => void;
4894
- /** Set collapsed state directly */
4895
- setCollapsed: (collapsed: boolean) => void;
4896
- /** Content to display (truncated if collapsed, full if expanded) */
4897
- displayContent: string;
4898
- /** Whether the content exceeds limits and should be collapsible */
4899
- shouldCollapse: boolean;
4900
- /** Original content length */
4901
- originalLength: number;
4902
- /** Original line count */
4903
- originalLineCount: number;
4904
- }
4905
- /**
4906
- * Hook for managing collapsible content with "Read more..." functionality
4907
- *
4908
- * @example
4909
- * ```tsx
4910
- * const { isCollapsed, toggleCollapsed, displayContent, shouldCollapse } = useCollapsibleContent(
4911
- * longText,
4912
- * { maxLength: 300, maxLines: 5 }
4913
- * );
4914
- *
4915
- * return (
4916
- * <div>
4917
- * <Markdown content={displayContent} />
4918
- * {shouldCollapse && (
4919
- * <button onClick={toggleCollapsed}>
4920
- * {isCollapsed ? 'Read more...' : 'Show less'}
4921
- * </button>
4922
- * )}
4923
- * </div>
4924
- * );
4925
- * ```
4926
- */
4927
- declare function useCollapsibleContent(content: string, options?: UseCollapsibleContentOptions): UseCollapsibleContentResult;
4928
-
4929
- export { ANCHOR, ActionRow, 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, ChatHeaderLanguageButton, type ChatHeaderLanguageButtonProps, 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, ChatMessageRow, 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, MarkdownMessage as MarkdownMessageDefault, 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 UseChatUnreadOptions, type UseChatUnreadReturn, 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, useChatUnread, useCollapsibleContent, useCronCustom, useCronMonthDays, useCronPreview, useCronScheduler, useCronSchedulerContext, useCronTime, useCronType, useCronWeekDays, useEditor, useEditorContext, useFocusOnEmptyClick, useImageCache, useLanguage, useLottie, useMediaCacheStore, useMonaco, useRegisterComposer, useVideoCache, useVideoPlayerContext, useVideoPlayerSettings, useVisitorFingerprint, validateRequiredFields, validateSchema };