tempest-react-sdk 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/README.md +72 -68
  2. package/dist/audio/audio-output.cjs +2 -0
  3. package/dist/audio/audio-output.cjs.map +1 -0
  4. package/dist/audio/audio-output.js +17 -0
  5. package/dist/audio/audio-output.js.map +1 -0
  6. package/dist/audio/audio-player.cjs +1 -1
  7. package/dist/audio/audio-player.cjs.map +1 -1
  8. package/dist/audio/audio-player.js +21 -20
  9. package/dist/audio/audio-player.js.map +1 -1
  10. package/dist/audio/audio-recorder.cjs +2 -0
  11. package/dist/audio/audio-recorder.cjs.map +1 -0
  12. package/dist/audio/audio-recorder.js +30 -0
  13. package/dist/audio/audio-recorder.js.map +1 -0
  14. package/dist/audio/duration.cjs +2 -0
  15. package/dist/audio/duration.cjs.map +1 -0
  16. package/dist/audio/duration.js +10 -0
  17. package/dist/audio/duration.js.map +1 -0
  18. package/dist/audio/level-meter.cjs +2 -0
  19. package/dist/audio/level-meter.cjs.map +1 -0
  20. package/dist/audio/level-meter.js +34 -0
  21. package/dist/audio/level-meter.js.map +1 -0
  22. package/dist/audio/media-access.cjs +2 -0
  23. package/dist/audio/media-access.cjs.map +1 -0
  24. package/dist/audio/media-access.js +51 -0
  25. package/dist/audio/media-access.js.map +1 -0
  26. package/dist/audio/use-audio-recorder.cjs +2 -0
  27. package/dist/audio/use-audio-recorder.cjs.map +1 -0
  28. package/dist/audio/use-audio-recorder.js +94 -0
  29. package/dist/audio/use-audio-recorder.js.map +1 -0
  30. package/dist/audio/use-audio.cjs.map +1 -1
  31. package/dist/audio/use-audio.js.map +1 -1
  32. package/dist/audio/use-microphone.cjs +2 -0
  33. package/dist/audio/use-microphone.cjs.map +1 -0
  34. package/dist/audio/use-microphone.js +54 -0
  35. package/dist/audio/use-microphone.js.map +1 -0
  36. package/dist/audio/wav.cjs +2 -0
  37. package/dist/audio/wav.cjs.map +1 -0
  38. package/dist/audio/wav.js +49 -0
  39. package/dist/audio/wav.js.map +1 -0
  40. package/dist/auth/passkey.cjs +2 -0
  41. package/dist/auth/passkey.cjs.map +1 -0
  42. package/dist/auth/passkey.js +171 -0
  43. package/dist/auth/passkey.js.map +1 -0
  44. package/dist/auth/use-passkey.cjs +2 -0
  45. package/dist/auth/use-passkey.cjs.map +1 -0
  46. package/dist/auth/use-passkey.js +120 -0
  47. package/dist/auth/use-passkey.js.map +1 -0
  48. package/dist/br/PixQRCode.cjs +2 -0
  49. package/dist/br/PixQRCode.cjs.map +1 -0
  50. package/dist/br/PixQRCode.js +70 -0
  51. package/dist/br/PixQRCode.js.map +1 -0
  52. package/dist/br/PixQRCode.module.cjs +2 -0
  53. package/dist/br/PixQRCode.module.cjs.map +1 -0
  54. package/dist/br/PixQRCode.module.js +15 -0
  55. package/dist/br/PixQRCode.module.js.map +1 -0
  56. package/dist/br/boleto.cjs +2 -0
  57. package/dist/br/boleto.cjs.map +1 -0
  58. package/dist/br/boleto.js +225 -0
  59. package/dist/br/boleto.js.map +1 -0
  60. package/dist/br/holidays.cjs +2 -0
  61. package/dist/br/holidays.cjs.map +1 -0
  62. package/dist/br/holidays.js +148 -0
  63. package/dist/br/holidays.js.map +1 -0
  64. package/dist/br/nfe.cjs +2 -0
  65. package/dist/br/nfe.cjs.map +1 -0
  66. package/dist/br/nfe.js +104 -0
  67. package/dist/br/nfe.js.map +1 -0
  68. package/dist/br/pix.cjs +2 -0
  69. package/dist/br/pix.cjs.map +1 -0
  70. package/dist/br/pix.js +148 -0
  71. package/dist/br/pix.js.map +1 -0
  72. package/dist/br.cjs +1 -1
  73. package/dist/br.cjs.map +1 -1
  74. package/dist/br.d.ts +878 -0
  75. package/dist/br.js +7 -2
  76. package/dist/br.js.map +1 -1
  77. package/dist/capture/barcode.cjs +2 -0
  78. package/dist/capture/barcode.cjs.map +1 -0
  79. package/dist/capture/barcode.js +59 -0
  80. package/dist/capture/barcode.js.map +1 -0
  81. package/dist/capture/media-recorder.cjs +2 -0
  82. package/dist/capture/media-recorder.cjs.map +1 -0
  83. package/dist/capture/media-recorder.js +64 -0
  84. package/dist/capture/media-recorder.js.map +1 -0
  85. package/dist/capture/use-barcode-scanner.cjs +2 -0
  86. package/dist/capture/use-barcode-scanner.cjs.map +1 -0
  87. package/dist/capture/use-barcode-scanner.js +86 -0
  88. package/dist/capture/use-barcode-scanner.js.map +1 -0
  89. package/dist/capture/use-screen-capture.cjs +2 -0
  90. package/dist/capture/use-screen-capture.cjs.map +1 -0
  91. package/dist/capture/use-screen-capture.js +79 -0
  92. package/dist/capture/use-screen-capture.js.map +1 -0
  93. package/dist/capture/use-speech-recognition.cjs +2 -0
  94. package/dist/capture/use-speech-recognition.cjs.map +1 -0
  95. package/dist/capture/use-speech-recognition.js +118 -0
  96. package/dist/capture/use-speech-recognition.js.map +1 -0
  97. package/dist/capture/use-torch.cjs +2 -0
  98. package/dist/capture/use-torch.cjs.map +1 -0
  99. package/dist/capture/use-torch.js +33 -0
  100. package/dist/capture/use-torch.js.map +1 -0
  101. package/dist/capture/use-video-recorder.cjs +2 -0
  102. package/dist/capture/use-video-recorder.cjs.map +1 -0
  103. package/dist/capture/use-video-recorder.js +90 -0
  104. package/dist/capture/use-video-recorder.js.map +1 -0
  105. package/dist/capture/video-recorder.cjs +2 -0
  106. package/dist/capture/video-recorder.cjs.map +1 -0
  107. package/dist/capture/video-recorder.js +31 -0
  108. package/dist/capture/video-recorder.js.map +1 -0
  109. package/dist/components/AIChat/AIChat.cjs +1 -1
  110. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  111. package/dist/components/AIChat/AIChat.js +93 -97
  112. package/dist/components/AIChat/AIChat.js.map +1 -1
  113. package/dist/components/AIChat/AIChatComposer.cjs +1 -1
  114. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  115. package/dist/components/AIChat/AIChatComposer.js +2 -1
  116. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  117. package/dist/components/AIChat/AIChatTurn.cjs +2 -2
  118. package/dist/components/AIChat/AIChatTurn.js +6 -6
  119. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  120. package/dist/components/Alert/Alert.module.cjs.map +1 -1
  121. package/dist/components/Alert/Alert.module.js.map +1 -1
  122. package/dist/components/AudioPlayer/AudioPlayer.cjs +2 -0
  123. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -0
  124. package/dist/components/AudioPlayer/AudioPlayer.js +123 -0
  125. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -0
  126. package/dist/components/AudioPlayer/AudioPlayer.module.cjs +2 -0
  127. package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -0
  128. package/dist/components/AudioPlayer/AudioPlayer.module.js +12 -0
  129. package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -0
  130. package/dist/components/AudioRecorder/AudioRecorder.cjs +2 -0
  131. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -0
  132. package/dist/components/AudioRecorder/AudioRecorder.js +179 -0
  133. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -0
  134. package/dist/components/AudioRecorder/AudioRecorder.module.cjs +2 -0
  135. package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -0
  136. package/dist/components/AudioRecorder/AudioRecorder.module.js +19 -0
  137. package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -0
  138. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  139. package/dist/components/Badge/Badge.module.js.map +1 -1
  140. package/dist/components/BarcodeScanner/BarcodeScanner.cjs +2 -0
  141. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -0
  142. package/dist/components/BarcodeScanner/BarcodeScanner.js +123 -0
  143. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -0
  144. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs +2 -0
  145. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -0
  146. package/dist/components/BarcodeScanner/BarcodeScanner.module.js +22 -0
  147. package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -0
  148. package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
  149. package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
  150. package/dist/components/Button/Button.module.cjs.map +1 -1
  151. package/dist/components/Button/Button.module.js.map +1 -1
  152. package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
  153. package/dist/components/Combobox/Combobox.module.js.map +1 -1
  154. package/dist/components/DataTable/DataTable.cjs +1 -1
  155. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  156. package/dist/components/DataTable/DataTable.js +203 -66
  157. package/dist/components/DataTable/DataTable.js.map +1 -1
  158. package/dist/components/DataTable/DataTable.module.cjs +1 -1
  159. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  160. package/dist/components/DataTable/DataTable.module.js +9 -3
  161. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  162. package/dist/components/DataTable/EditableCell.cjs +2 -0
  163. package/dist/components/DataTable/EditableCell.cjs.map +1 -0
  164. package/dist/components/DataTable/EditableCell.js +77 -0
  165. package/dist/components/DataTable/EditableCell.js.map +1 -0
  166. package/dist/components/DataTable/edit-labels.cjs +2 -0
  167. package/dist/components/DataTable/edit-labels.cjs.map +1 -0
  168. package/dist/components/DataTable/edit-labels.js +11 -0
  169. package/dist/components/DataTable/edit-labels.js.map +1 -0
  170. package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
  171. package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
  172. package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
  173. package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
  174. package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
  175. package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
  176. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs +1 -1
  177. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
  178. package/dist/components/SyncStatusBadge/SyncStatusBadge.js +33 -32
  179. package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
  180. package/dist/components/Toast/ToastProvider.cjs +1 -1
  181. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  182. package/dist/components/Toast/ToastProvider.js +1 -2
  183. package/dist/components/Toast/ToastProvider.js.map +1 -1
  184. package/dist/hooks/use-announce.cjs +2 -0
  185. package/dist/hooks/use-announce.cjs.map +1 -0
  186. package/dist/hooks/use-announce.js +50 -0
  187. package/dist/hooks/use-announce.js.map +1 -0
  188. package/dist/hooks/use-media-devices.cjs +2 -0
  189. package/dist/hooks/use-media-devices.cjs.map +1 -0
  190. package/dist/hooks/use-media-devices.js +46 -0
  191. package/dist/hooks/use-media-devices.js.map +1 -0
  192. package/dist/hooks/use-media-permission.cjs +2 -0
  193. package/dist/hooks/use-media-permission.cjs.map +1 -0
  194. package/dist/hooks/use-media-permission.js +33 -0
  195. package/dist/hooks/use-media-permission.js.map +1 -0
  196. package/dist/http/resumable-upload.cjs +2 -0
  197. package/dist/http/resumable-upload.cjs.map +1 -0
  198. package/dist/http/resumable-upload.js +249 -0
  199. package/dist/http/resumable-upload.js.map +1 -0
  200. package/dist/perf/cache-size.cjs +2 -0
  201. package/dist/perf/cache-size.cjs.map +1 -0
  202. package/dist/perf/cache-size.js +16 -0
  203. package/dist/perf/cache-size.js.map +1 -0
  204. package/dist/perf/device.cjs +2 -0
  205. package/dist/perf/device.cjs.map +1 -0
  206. package/dist/perf/device.js +22 -0
  207. package/dist/perf/device.js.map +1 -0
  208. package/dist/perf/format.cjs +2 -0
  209. package/dist/perf/format.cjs.map +1 -0
  210. package/dist/perf/format.js +8 -0
  211. package/dist/perf/format.js.map +1 -0
  212. package/dist/perf/profiler.cjs +2 -0
  213. package/dist/perf/profiler.cjs.map +1 -0
  214. package/dist/perf/profiler.js +46 -0
  215. package/dist/perf/profiler.js.map +1 -0
  216. package/dist/styles.css +1 -1
  217. package/dist/tempest-react-sdk.cjs +1 -1
  218. package/dist/tempest-react-sdk.d.ts +2705 -38
  219. package/dist/tempest-react-sdk.js +268 -240
  220. package/dist/vision/core/timing.cjs +2 -0
  221. package/dist/vision/core/timing.cjs.map +1 -0
  222. package/dist/vision/core/timing.js +24 -0
  223. package/dist/vision/core/timing.js.map +1 -0
  224. package/dist/vision/index.cjs +1 -1
  225. package/dist/vision/index.cjs.map +1 -1
  226. package/dist/vision/index.js +16 -15
  227. package/dist/vision/index.js.map +1 -1
  228. package/dist/vision/postprocess/detection.cjs +1 -1
  229. package/dist/vision/postprocess/detection.cjs.map +1 -1
  230. package/dist/vision/postprocess/detection.js +2 -2
  231. package/dist/vision/postprocess/detection.js.map +1 -1
  232. package/dist/vision/postprocess/segmentation.cjs +1 -1
  233. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  234. package/dist/vision/postprocess/segmentation.js +1 -1
  235. package/dist/vision/postprocess/segmentation.js.map +1 -1
  236. package/dist/vision/results.cjs +1 -1
  237. package/dist/vision/results.cjs.map +1 -1
  238. package/dist/vision/results.js +18 -13
  239. package/dist/vision/results.js.map +1 -1
  240. package/dist/vision/tasks/classifier.cjs +1 -1
  241. package/dist/vision/tasks/classifier.cjs.map +1 -1
  242. package/dist/vision/tasks/classifier.js +46 -39
  243. package/dist/vision/tasks/classifier.js.map +1 -1
  244. package/dist/vision/tasks/detector.cjs +1 -1
  245. package/dist/vision/tasks/detector.cjs.map +1 -1
  246. package/dist/vision/tasks/detector.js +40 -33
  247. package/dist/vision/tasks/detector.js.map +1 -1
  248. package/dist/vision/tasks/segmenter.cjs +1 -1
  249. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  250. package/dist/vision/tasks/segmenter.js +35 -28
  251. package/dist/vision/tasks/segmenter.js.map +1 -1
  252. package/dist/vision/use-camera-stream.cjs +1 -1
  253. package/dist/vision/use-camera-stream.cjs.map +1 -1
  254. package/dist/vision/use-camera-stream.js +40 -57
  255. package/dist/vision/use-camera-stream.js.map +1 -1
  256. package/dist/vision.cjs +1 -1
  257. package/dist/vision.d.ts +93 -13
  258. package/dist/vision.js +21 -20
  259. package/package.json +1 -1
@@ -56,6 +56,7 @@ import { ReactEventHandler } from 'react';
56
56
  import { ReactNode } from 'react';
57
57
  import { ReactPortal } from 'react';
58
58
  import { redirect } from 'react-router';
59
+ import { Ref } from 'react';
59
60
  import { RefAttributes } from 'react';
60
61
  import { RefObject } from 'react';
61
62
  import { Route } from 'react-router';
@@ -187,7 +188,7 @@ export declare interface AccordionProps {
187
188
  * suggestions={["Resuma o último relatório", "Quais pedidos atrasaram?"]}
188
189
  * />
189
190
  */
190
- export declare function AIChat({ messages, onSend, onStop, onRegenerate, onEditSubmit, onFeedback, onRetry, pending, suggestions, renderAvatar, renderContent, votes, header, emptyState, showSystem, defaultReasoningOpen, showLineNumbers, locale, placeholder, composerActions, composerFooter, composerDisabled, maxRows, onSendError, className, ...rest }: AIChatProps): JSX.Element;
191
+ export declare function AIChat({ messages, onSend, onStop, onRegenerate, onEditSubmit, onFeedback, onRetry, pending, suggestions, renderAvatar, renderContent, votes, header, emptyState, showSystem, defaultReasoningOpen, showLineNumbers, locale, placeholder, composerActions, composerRef, composerFooter, composerDisabled, maxRows, onSendError, className, ...rest }: AIChatProps): JSX.Element;
191
192
 
192
193
  /** A file carried by a turn — an upload on the way in, a document on the way out. */
193
194
  export declare interface AIChatAttachment {
@@ -224,14 +225,23 @@ export declare interface AIChatAttachment {
224
225
  */
225
226
  export declare const AIChatComposer: ForwardRefExoticComponent<AIChatComposerProps & RefAttributes<AIChatComposerHandle>>;
226
227
 
227
- /** Imperative handle, so a thread can focus or refill the field. */
228
+ /** Imperative handle, so a thread can focus, read or refill the field. */
228
229
  export declare interface AIChatComposerHandle {
229
230
  focus: () => void;
230
231
  /** Replace the draft — used to put a prompt back in the field. */
231
232
  setValue: (text: string) => void;
233
+ /**
234
+ * The current draft.
235
+ *
236
+ * The counterpart `setValue` needs to be usable for anything **additive**. The
237
+ * field is uncontrolled, so without this the only way to append to a draft — a
238
+ * dictated phrase, a picked slash-command, a pasted citation — is to shadow the
239
+ * whole value in app state through `onChange` and hope the two never drift.
240
+ */
241
+ getValue: () => string;
232
242
  }
233
243
 
234
- export declare interface AIChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_5> {
244
+ export declare interface AIChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_8> {
235
245
  /** Called with the trimmed prompt. The field clears only when this does not throw. */
236
246
  onSend: (text: string) => void | Promise<void>;
237
247
  /**
@@ -302,7 +312,7 @@ export declare interface AIChatMessage {
302
312
  data?: Record<string, unknown>;
303
313
  }
304
314
 
305
- export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
315
+ export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
306
316
  /** The transcript, **oldest first**. Never reordered by the component. */
307
317
  messages: readonly AIChatMessage[];
308
318
  /** Renders the composer when given. Receives the trimmed prompt. */
@@ -349,6 +359,16 @@ export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>
349
359
  placeholder?: string;
350
360
  /** Extra controls inside the composer, before the send button. */
351
361
  composerActions?: ReactNode;
362
+ /**
363
+ * Reach the composer imperatively — `focus()`, `getValue()`, `setValue()`.
364
+ *
365
+ * What makes dictation (or a slash-command menu, or "edit and resend") possible
366
+ * without this component knowing anything about them: pair it with
367
+ * `composerActions` and the button you put in the composer can write into the
368
+ * field. Speech recognition is **not** wired in here on purpose — it would make
369
+ * every consumer of `AIChat` pay for an API that streams audio to a third party.
370
+ */
371
+ composerRef?: Ref<AIChatComposerHandle>;
352
372
  /** Under the composer field — token count, model name, a disclaimer. */
353
373
  composerFooter?: ReactNode;
354
374
  /** Disable the composer — no credits, conversation archived, offline. */
@@ -483,6 +503,41 @@ export declare interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>,
483
503
 
484
504
  export declare type AlertVariant = "neutral" | "info" | "success" | "warning" | "danger";
485
505
 
506
+ /** Every symbology in the spec, used to validate what a detector reports back. */
507
+ export declare const ALL_BARCODE_FORMATS: readonly BarcodeFormat[];
508
+
509
+ /**
510
+ * Announce a message to screen readers, from anywhere — a hook, an event handler,
511
+ * a plain function outside React.
512
+ *
513
+ * ## Why the same string announces twice
514
+ *
515
+ * Screen readers announce a live region when its **content changes**. Writing the
516
+ * same text again is not a change, so "Item removido" twice in a row is read once —
517
+ * the classic reason these announcers are quietly broken. Instead of mutating text,
518
+ * every call replaces the region's child with a **new element**. The DOM mutation is
519
+ * real even when the string is identical, so the second announcement happens, and
520
+ * the reader hears the exact message with no padding characters bolted on.
521
+ *
522
+ * @param message - Text to read out. Empty strings are ignored.
523
+ * @param politeness - `"polite"` (default) or `"assertive"`.
524
+ *
525
+ * @example
526
+ * announce(`${count} pedidos encontrados`);
527
+ * announce("Falha ao salvar", "assertive");
528
+ */
529
+ export declare function announce(message: string, politeness?: AnnouncePoliteness): void;
530
+
531
+ /**
532
+ * How urgently a screen reader should interrupt.
533
+ *
534
+ * `"polite"` waits for a pause in what is being read. `"assertive"` cuts in
535
+ * immediately, which is right for an error the user must act on and wrong for
536
+ * everything else — an assertive announcement can truncate the sentence the user
537
+ * was in the middle of.
538
+ */
539
+ export declare type AnnouncePoliteness = "polite" | "assertive";
540
+
486
541
  declare type AnyEventTarget = EventTarget | {
487
542
  current: EventTarget | null;
488
543
  } | null | undefined;
@@ -823,7 +878,50 @@ export declare function assertNever(value: never, message?: string): never;
823
878
 
824
879
  export declare type AsyncStatus = "idle" | "pending" | "success" | "error";
825
880
 
826
- export declare interface AudioPlayer {
881
+ /**
882
+ * Container/codec candidates, best first.
883
+ *
884
+ * No browser supports all of these, and none supports MP3 or WAV from
885
+ * `MediaRecorder` — see the note on {@link pickAudioMimeType}. Opus in WebM is the
886
+ * first choice because it is the smallest at speech bitrates and is what Chromium
887
+ * and Firefox produce natively; `audio/mp4` is here for Safari, which produces AAC
888
+ * and nothing else.
889
+ *
890
+ * Ported from the intersection of what `MediaRecorder.isTypeSupported` accepts in
891
+ * Chrome 120+, Firefox 115+ and Safari 17. Re-check against
892
+ * <https://developer.mozilla.org/docs/Web/API/MediaRecorder/isTypeSupported> before
893
+ * adding to the list.
894
+ */
895
+ export declare const AUDIO_MIME_CANDIDATES: readonly string[];
896
+
897
+ /**
898
+ * Playback transport for one clip: play/pause, a seek bar, elapsed and total time.
899
+ *
900
+ * Built around a real `<audio>` element rather than the SDK's `createAudioPlayer`,
901
+ * which is a fire-and-forget handle for notification chimes and has no transport to
902
+ * expose. Accepts a `Blob` directly, because the thing an app most often plays is the
903
+ * recording it just made.
904
+ *
905
+ * The seek bar is a bare `<input type="range">` rather than the SDK's `Slider`: that
906
+ * component is a form field, with a label row and a value badge, and a transport wants
907
+ * neither. The native input keeps the keyboard and screen-reader behaviour that
908
+ * matters here for free.
909
+ *
910
+ * @example
911
+ * const rec = useAudioRecorder(mic.stream);
912
+ * {rec.recording && (
913
+ * <AudioPlayer src={rec.recording.blob} durationMs={rec.recording.durationMs} />
914
+ * )}
915
+ */
916
+ export declare function AudioPlayer({ src, durationMs, sinkId, autoPlay, loop, locale, actions, onEnded, onError, disabled, className, ...rest }: AudioPlayerProps): JSX.Element;
917
+
918
+ /**
919
+ * Imperative handle over one "current" clip.
920
+ *
921
+ * Named `*Handle` like the SDK's other imperative handles (`ChatComposerHandle`,
922
+ * `SignaturePadHandle`) — it is a control surface, not the `<AudioPlayer>` component.
923
+ */
924
+ export declare interface AudioPlayerHandle {
827
925
  /** Play `src`. Returns the underlying element, or `null` when the browser blocked autoplay. */
828
926
  play: (src: string, options?: PlayAudioOptions) => Promise<HTMLAudioElement | null>;
829
927
  /** Stop the currently-playing clip and rewind it. */
@@ -832,6 +930,157 @@ export declare interface AudioPlayer {
832
930
  current: () => HTMLAudioElement | null;
833
931
  }
834
932
 
933
+ export declare interface AudioPlayerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
934
+ /**
935
+ * What to play — a URL, or a `Blob`/`File` straight from a recorder.
936
+ *
937
+ * A `Blob` is wrapped in an object URL that is revoked when it changes or the
938
+ * component unmounts, so a page that records twenty notes does not leak twenty
939
+ * URLs for the lifetime of the tab.
940
+ */
941
+ src: string | Blob | null;
942
+ /**
943
+ * Known length in milliseconds.
944
+ *
945
+ * Pass it whenever you have it — a recording from `useAudioRecorder` always does.
946
+ * See the note on the seek bar for why the element's own `duration` is not
947
+ * trustworthy for a fresh recording.
948
+ */
949
+ durationMs?: number;
950
+ /** Output device, from `useMediaDevices().audioOutputs`. Chromium only. */
951
+ sinkId?: string;
952
+ /** Start playing as soon as `src` is ready. Default `false`. */
953
+ autoPlay?: boolean;
954
+ /** Loop. Default `false`. */
955
+ loop?: boolean;
956
+ /** Locale for the labels. Default `"pt-BR"`. */
957
+ locale?: "pt-BR" | "en";
958
+ /** Rendered to the right of the times — a download button, a delete button. */
959
+ actions?: React.ReactNode;
960
+ /** Fired when playback reaches the end. */
961
+ onEnded?: () => void;
962
+ /** Fired when the element reports a decode/network error. */
963
+ onError?: (error: unknown) => void;
964
+ /** No `src` yet, or playback not allowed. */
965
+ disabled?: boolean;
966
+ }
967
+
968
+ /**
969
+ * Record a voice note: one button to start, a live level meter, a clock, and a
970
+ * playback review before the audio leaves the component.
971
+ *
972
+ * The permission flow is the part worth reading. The microphone is **not** opened on
973
+ * mount — the prompt fires on the first press of Record, because a prompt the user did
974
+ * not provoke is the most reliable way to earn a permanent block, after which
975
+ * `getUserMedia` rejects without ever asking again. When the permission is already
976
+ * `"denied"`, the component says so and how to fix it instead of offering a button
977
+ * that cannot work.
978
+ *
979
+ * The level meter is not decoration either: a muted OS input or a headset with its mic
980
+ * arm folded up produces a perfectly successful recording of silence, and without a
981
+ * visible level the user only finds out after they finish talking.
982
+ *
983
+ * @example
984
+ * <AudioRecorder
985
+ * maxDurationMs={120_000}
986
+ * format="wav"
987
+ * wavOptions={{ mono: true, sampleRate: 16000 }}
988
+ * onRecorded={({ blob }) => upload(blob)}
989
+ * />
990
+ */
991
+ export declare function AudioRecorder({ onRecorded, maxDurationMs, deviceId, format, wavOptions, audioBitsPerSecond, review, locale, footer, onError, disabled, className, ...rest }: AudioRecorderProps): JSX.Element;
992
+
993
+ /** Imperative recorder. */
994
+ export declare interface AudioRecorderHandle {
995
+ /** Begin recording. No-op when already recording or paused. */
996
+ start: () => void;
997
+ /** Pause. The clock stops; `durationMs` freezes. */
998
+ pause: () => void;
999
+ /** Resume after `pause()`. */
1000
+ resume: () => void;
1001
+ /** Stop and resolve with the assembled recording. */
1002
+ stop: () => Promise<AudioRecording>;
1003
+ /** Stop and throw the audio away. */
1004
+ cancel: () => void;
1005
+ status: () => AudioRecorderStatus;
1006
+ /** Recorded length so far, excluding paused time. */
1007
+ durationMs: () => number;
1008
+ /** The negotiated container. */
1009
+ mimeType: string;
1010
+ }
1011
+
1012
+ /** Options for {@link createAudioRecorder}. */
1013
+ export declare interface AudioRecorderOptions {
1014
+ /**
1015
+ * Force a container. Throws when the browser cannot produce it.
1016
+ *
1017
+ * Leave it out. The default negotiates from {@link AUDIO_MIME_CANDIDATES}, which
1018
+ * is the only way one call site works on both Chromium and Safari.
1019
+ */
1020
+ mimeType?: string;
1021
+ /** Target bitrate. 32000–64000 is plenty for speech in Opus. */
1022
+ audioBitsPerSecond?: number;
1023
+ /**
1024
+ * Emit a chunk every N ms through `onChunk`, for streaming upload.
1025
+ *
1026
+ * Without it the whole recording is buffered in memory until `stop()` — fine for
1027
+ * a voice note, not fine for an hour-long meeting.
1028
+ */
1029
+ timesliceMs?: number;
1030
+ /** Receives each chunk when `timesliceMs` is set. Chunks are **not** independently playable. */
1031
+ onChunk?: (chunk: Blob) => void;
1032
+ /** Recorder-level failure (device unplugged mid-recording, encoder error). */
1033
+ onError?: (error: unknown) => void;
1034
+ }
1035
+
1036
+ export declare interface AudioRecorderProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_5> {
1037
+ /**
1038
+ * Called once a recording is finished and (when asked) converted.
1039
+ *
1040
+ * Fires on stop and on hitting `maxDurationMs`, never on cancel.
1041
+ */
1042
+ onRecorded?: (recording: AudioRecording) => void;
1043
+ /** Stop automatically after this long. Strongly recommended on anything public. */
1044
+ maxDurationMs?: number;
1045
+ /** Specific microphone, from `useMediaDevices().audioInputs`. */
1046
+ deviceId?: string;
1047
+ /**
1048
+ * Output container.
1049
+ *
1050
+ * `"native"` (default) keeps what the browser produced — Opus on Chromium and
1051
+ * Firefox, AAC on Safari — which is the smallest and needs no work. `"wav"`
1052
+ * converts on stop, for a backend that only accepts WAV; see `wavOptions`, and
1053
+ * expect roughly ten times the bytes.
1054
+ */
1055
+ format?: "native" | "wav";
1056
+ /** Passed to `blobToWav` when `format="wav"`. `{ mono: true, sampleRate: 16000 }` suits speech. */
1057
+ wavOptions?: WavOptions;
1058
+ /** Target bitrate. 32000–64000 is plenty for speech in Opus. */
1059
+ audioBitsPerSecond?: number;
1060
+ /** Offer playback of the recording before handing it over. Default `true`. */
1061
+ review?: boolean;
1062
+ /** Locale for the labels. Default `"pt-BR"`. */
1063
+ locale?: "pt-BR" | "en";
1064
+ /** Rendered under the controls — a hint, a character count, a legal notice. */
1065
+ footer?: ReactNode;
1066
+ /** Recorder-level failure, or a failed WAV conversion. */
1067
+ onError?: (error: unknown) => void;
1068
+ disabled?: boolean;
1069
+ }
1070
+
1071
+ /** Lifecycle of a recording. Shared with the video recorder — the states are the same. */
1072
+ export declare type AudioRecorderStatus = MediaRecorderStatus;
1073
+
1074
+ /** A finished recording. */
1075
+ export declare interface AudioRecording {
1076
+ /** The audio. Wrap with `useObjectUrl` to play it, or POST it as-is. */
1077
+ blob: Blob;
1078
+ /** What the browser actually produced — not necessarily what you asked for. */
1079
+ mimeType: string;
1080
+ /** Recorded length, excluding time spent paused. */
1081
+ durationMs: number;
1082
+ }
1083
+
835
1084
  /**
836
1085
  * Router-agnostic auth gate. The caller decides what to render in either
837
1086
  * branch — typically `<Outlet />` for protected layouts and `<Navigate />` for
@@ -996,6 +1245,129 @@ export declare interface BannerProps extends Omit<HTMLAttributes<HTMLDivElement>
996
1245
 
997
1246
  export declare type BannerVariant = "info" | "success" | "warning" | "danger";
998
1247
 
1248
+ /**
1249
+ * The slice of `BarcodeDetector` this SDK uses.
1250
+ *
1251
+ * Exported so a consumer can **inject a polyfill** where the native API is missing —
1252
+ * see {@link isBarcodeDetectionSupported} for why that matters — and so tests can hand
1253
+ * in a decoder without a camera. Anything with a `detect()` that resolves to objects
1254
+ * carrying a `rawValue` will do.
1255
+ */
1256
+ export declare interface BarcodeDetectorLike {
1257
+ /**
1258
+ * Decode every symbol visible in the source.
1259
+ *
1260
+ * @param source - A `<video>`, a `<canvas>`, an `ImageBitmap`, a `Blob`…
1261
+ * @returns Every symbol found, or an empty array — finding nothing is not an error.
1262
+ */
1263
+ detect: (source: ImageBitmapSource) => Promise<readonly DetectedBarcodeLike[]>;
1264
+ }
1265
+
1266
+ /**
1267
+ * Symbologies the `BarcodeDetector` API names.
1268
+ *
1269
+ * Three of them carry the weight in Brazil: `ean_13` is the retail barcode on every
1270
+ * packaged product, `qr_code` is what a Pix "copia e cola" payload travels in, and
1271
+ * `code_128` is the label on a shipment. The rest are here because the spec has them
1272
+ * and asking for one costs nothing.
1273
+ */
1274
+ export declare type BarcodeFormat = "aztec" | "codabar" | "code_128" | "code_39" | "code_93" | "data_matrix" | "ean_13" | "ean_8" | "itf" | "pdf417" | "qr_code" | "upc_a" | "upc_e" | "unknown";
1275
+
1276
+ /** A corner of a detected symbol, in the source's pixel coordinates. */
1277
+ export declare interface BarcodePoint {
1278
+ x: number;
1279
+ y: number;
1280
+ }
1281
+
1282
+ /**
1283
+ * Point the camera at a barcode and get its value.
1284
+ *
1285
+ * The counterpart to {@link QRCode}, which only encodes. Under it are
1286
+ * `useBarcodeScanner` (the detect loop and repeat suppression), `useCameraStream` (the
1287
+ * stream and its classified errors) and `useTorch`.
1288
+ *
1289
+ * **Mounting this opens the camera**, so mount it when the user asks to scan rather
1290
+ * than on a page that happens to contain a scanner: a permission prompt nobody
1291
+ * provoked is the surest way to earn a permanent block, and after that `getUserMedia`
1292
+ * rejects without ever prompting again. The usual shape is a button that reveals it.
1293
+ *
1294
+ * The `unsupported` slot is not a nicety. `BarcodeDetector` is Chromium-only — absent
1295
+ * on Firefox, on every browser on iOS, and on Chromium for Windows and Linux — so on a
1296
+ * large share of real devices the fallback *is* the feature. Give it a text field, or
1297
+ * inject a polyfill through `detector`.
1298
+ *
1299
+ * The preview itself is `aria-hidden`: a live camera frame has nothing to announce and
1300
+ * no audio to caption, so what a screen reader gets is the `role="status"` line, which
1301
+ * says whether scanning is running and reads out each accepted code.
1302
+ *
1303
+ * @example
1304
+ * <BarcodeScanner
1305
+ * formats={["ean_13"]}
1306
+ * onScan={({ rawValue }) => addToCart(rawValue)}
1307
+ * footer={<small>Aponte para o código de barras da embalagem.</small>}
1308
+ * unsupported={<ManualCodeInput onSubmit={addToCart} />}
1309
+ * />
1310
+ */
1311
+ export declare function BarcodeScanner({ onScan, formats, paused, detector, intervalMs, repeatDelayMs, torch, aspectRatio, locale, footer, unsupported, onError, className, ...rest }: BarcodeScannerProps): JSX.Element;
1312
+
1313
+ export declare interface BarcodeScannerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
1314
+ /** Called for every accepted read — repeats of the same value are suppressed. */
1315
+ onScan: (result: BarcodeScanResult) => void;
1316
+ /** Symbologies to look for. Defaults to QR + EAN-13 + Code 128. */
1317
+ formats?: readonly BarcodeFormat[];
1318
+ /** Stop looking without releasing the camera — set it while a confirmation is open. */
1319
+ paused?: boolean;
1320
+ /** A decoder to use instead of the native one, for Safari and Firefox. */
1321
+ detector?: BarcodeDetectorLike;
1322
+ /** How often a frame is examined, in ms. Default 200. */
1323
+ intervalMs?: number;
1324
+ /** Ignore the same value again for this long, in ms. Default 2500. */
1325
+ repeatDelayMs?: number;
1326
+ /** Offer the torch toggle when the camera has a lamp. Default `true`. */
1327
+ torch?: boolean;
1328
+ /** Viewport aspect ratio, `width / height`. Default `4 / 3`. */
1329
+ aspectRatio?: number;
1330
+ /** Locale for the labels. Default `"pt-BR"`. */
1331
+ locale?: "pt-BR" | "en";
1332
+ /** Under the viewport — an instruction, the code just read, a manual-entry link. */
1333
+ footer?: ReactNode;
1334
+ /**
1335
+ * Rendered instead of the camera when there is no decoder.
1336
+ *
1337
+ * Worth filling in: on iOS and Firefox this is the **only** thing the user sees, so
1338
+ * the fallback is usually a plain text field for typing the code.
1339
+ */
1340
+ unsupported?: ReactNode;
1341
+ /** A frame the engine refused to decode. Routine and usually transient. */
1342
+ onError?: (error: unknown) => void;
1343
+ }
1344
+
1345
+ /** One decoded symbol, normalised. */
1346
+ export declare interface BarcodeScanResult {
1347
+ /** The decoded payload — a GTIN, a URL, a Pix BR Code. */
1348
+ rawValue: string;
1349
+ /** Which symbology it was read as. `"unknown"` when the engine does not say. */
1350
+ format: BarcodeFormat;
1351
+ /** Box in source pixels, or `null` when the engine reports none. */
1352
+ boundingBox: DOMRectReadOnly | null;
1353
+ /** Corners in source pixels, clockwise from top-left. Empty when unreported. */
1354
+ cornerPoints: readonly BarcodePoint[];
1355
+ }
1356
+
1357
+ /**
1358
+ * Decode a base64url string into bytes.
1359
+ *
1360
+ * WebAuthn transports every binary field as base64url (`-`/`_`, no padding)
1361
+ * because that is what survives JSON, while the DOM API insists on
1362
+ * `ArrayBuffer`. Getting this pair wrong — usually by feeding plain base64 to
1363
+ * `atob` and losing the last byte — is the classic broken-WebAuthn bug, which is
1364
+ * why the SDK owns it instead of leaving it to each app.
1365
+ *
1366
+ * @param value - Base64url text, with or without `=` padding.
1367
+ * @returns The decoded bytes.
1368
+ */
1369
+ export declare function base64UrlToBytes(value: string): Uint8Array;
1370
+
999
1371
  /**
1000
1372
  * Initial bearing (forward azimuth) from `origin` to `destination`, in degrees
1001
1373
  * clockwise from true north, normalized to `[0, 360)`. Useful for orienting a
@@ -1025,6 +1397,30 @@ export declare interface BeforeInstallPromptEvent extends Event {
1025
1397
  prompt: () => Promise<void>;
1026
1398
  }
1027
1399
 
1400
+ /**
1401
+ * Convert a recording to 16-bit WAV, with no dependency.
1402
+ *
1403
+ * `MediaRecorder` cannot produce WAV — it emits Opus on Chromium and Firefox and AAC
1404
+ * on Safari — so a backend that insists on WAV has to be served either by a
1405
+ * server-side transcode or by this. It decodes through `AudioContext.decodeAudioData`,
1406
+ * which is the browser's own decoder for whatever container the recorder chose, then
1407
+ * re-encodes the PCM.
1408
+ *
1409
+ * !!! The cost is real: WAV is uncompressed, so the same voice note that is 40 KB in
1410
+ * Opus is roughly 500 KB here at 48 kHz stereo. `{ mono: true, sampleRate: 16000 }`
1411
+ * takes that to about 80 KB and is what a speech-to-text endpoint wants anyway.
1412
+ *
1413
+ * Resampling uses `OfflineAudioContext`, i.e. the browser's own resampler, rather
1414
+ * than a hand-rolled one — this is exactly the "we want the underlying call, not a
1415
+ * wrapper" case.
1416
+ *
1417
+ * @param blob - A recording from {@link createAudioRecorder}, or any decodable audio.
1418
+ * @param options - See {@link WavOptions}.
1419
+ * @returns A `Blob` of type `audio/wav`.
1420
+ * @throws When the environment has no Web Audio, or the blob cannot be decoded.
1421
+ */
1422
+ export declare function blobToWav(blob: Blob, options?: WavOptions): Promise<Blob>;
1423
+
1028
1424
  /**
1029
1425
  * Fixed-bottom mobile tab bar. 3–5 items recommended. Pair with
1030
1426
  * `<Show below="md">` to render only on mobile.
@@ -1207,6 +1603,14 @@ export declare type ButtonSize = "xs" | "sm" | "md" | "lg" | "xl";
1207
1603
 
1208
1604
  export declare type ButtonVariant = "primary" | "secondary" | "danger" | "success" | "ghost" | "soft" | "outline" | "link";
1209
1605
 
1606
+ /**
1607
+ * Encode bytes as an unpadded base64url string.
1608
+ *
1609
+ * @param value - Bytes to encode, as a view or a raw buffer.
1610
+ * @returns Base64url text, safe to put in JSON and in a URL.
1611
+ */
1612
+ export declare function bytesToBase64Url(value: ArrayBuffer | Uint8Array): string;
1613
+
1210
1614
  /** Recommended `gcTime` presets (milliseconds). */
1211
1615
  export declare const CACHE_TIME: {
1212
1616
  readonly SHORT: number;
@@ -1214,6 +1618,30 @@ export declare const CACHE_TIME: {
1214
1618
  readonly LONG: number;
1215
1619
  };
1216
1620
 
1621
+ /**
1622
+ * How large the assets a page precached actually are.
1623
+ *
1624
+ * Reads the `Content-Length` of a stored response instead of its body:
1625
+ * materializing a cached ONNX model or WASM binary to learn its length would
1626
+ * pull tens of megabytes into memory on every measurement.
1627
+ */
1628
+ /**
1629
+ * Byte size of a response sitting in a Cache Storage bucket.
1630
+ *
1631
+ * @param cacheName The cache bucket to look in.
1632
+ * @param url The request URL the response was stored under.
1633
+ * @returns The size in bytes, or `null` when Cache Storage is unavailable,
1634
+ * the entry is absent, or the stored response carries no usable
1635
+ * `Content-Length` (a chunked transfer, typically).
1636
+ *
1637
+ * @example
1638
+ * ```typescript
1639
+ * const bytes = await cachedResponseBytes("app-models", "/models/detect.onnx");
1640
+ * console.log(bytes === null ? "—" : formatBytes(bytes)); // "12.0 MB"
1641
+ * ```
1642
+ */
1643
+ export declare function cachedResponseBytes(cacheName: string, url: string): Promise<number | null>;
1644
+
1217
1645
  /** A cache-name matcher: a prefix string, a `RegExp`, or a predicate. */
1218
1646
  export declare type CacheFilter = string | RegExp | ((name: string) => boolean);
1219
1647
 
@@ -1276,6 +1704,18 @@ export declare interface CalendarProps extends Omit<HTMLAttributes<HTMLDivElemen
1276
1704
  */
1277
1705
  export declare function camelCase(value: string): string;
1278
1706
 
1707
+ /** A classified camera error with a human-readable, English message. */
1708
+ declare interface CameraStreamError {
1709
+ kind: CameraStreamErrorKind;
1710
+ message: string;
1711
+ }
1712
+
1713
+ /** Classified reason a camera stream could not be acquired. */
1714
+ declare type CameraStreamErrorKind = "unsupported" | "permission-denied" | "no-camera" | "in-use" | "insecure" | "unknown";
1715
+
1716
+ /** Lifecycle status of the camera stream. */
1717
+ declare type CameraStreamStatus = "idle" | "loading" | "ready" | "error";
1718
+
1279
1719
  /**
1280
1720
  * Conditionally render based on an access check. Renders `children` when the
1281
1721
  * action is allowed, otherwise `fallback` (or nothing). While an async check is
@@ -1663,8 +2103,52 @@ export declare function clamp(value: number, min: number, max: number): number;
1663
2103
  /** Clamp a latitude into the valid `[-90, 90]` range. */
1664
2104
  export declare function clampLatitude(latitude: number): number;
1665
2105
 
2106
+ /**
2107
+ * Map an unknown `getUserMedia` failure into a {@link MediaAccessError}.
2108
+ *
2109
+ * The order matters. A missing `navigator.mediaDevices` is almost never "this
2110
+ * browser cannot do audio" — it is a page served over plain HTTP, where the whole
2111
+ * API is simply absent. Reporting `unsupported` there sends the developer looking
2112
+ * for a polyfill for a problem an `https://` URL fixes, so the secure-context check
2113
+ * runs first and wins.
2114
+ *
2115
+ * The `DOMException.name` values are then collapsed into kinds an app can actually
2116
+ * branch on, because the raw names do not group the way a UI needs them:
2117
+ * `NotFoundError` and `OverconstrainedError` both mean "you will not get a device
2118
+ * with these constraints", and `NotReadableError` and `AbortError` both mean "the
2119
+ * hardware is busy" — most often another tab of the same app.
2120
+ *
2121
+ * @param err - Whatever `getUserMedia` (or a device query) rejected with.
2122
+ * @param device - Which device was being opened, for the message.
2123
+ * @returns A stable kind plus a message safe to show a user.
2124
+ */
2125
+ export declare function classifyMediaError(err: unknown, device?: MediaDeviceKindLabel): MediaAccessError;
2126
+
2127
+ /**
2128
+ * Map a thrown WebAuthn failure onto a {@link PasskeyError}.
2129
+ *
2130
+ * The secure-context check runs first for the same reason it does in the media
2131
+ * classifier: over plain HTTP the whole API is absent or refuses, and reporting
2132
+ * "not supported" sends a developer hunting for a polyfill for something an
2133
+ * `https://` URL fixes.
2134
+ *
2135
+ * @param error - Whatever `navigator.credentials` rejected with.
2136
+ * @param ceremony - Which ceremony was running, for the message.
2137
+ * @returns The classified error, ready to throw or to show.
2138
+ */
2139
+ export declare function classifyPasskeyError(error: unknown, ceremony: PasskeyCeremony): PasskeyError;
2140
+
1666
2141
  declare type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[];
1667
2142
 
2143
+ /**
2144
+ * Remove the shared regions and cancel pending cleanups.
2145
+ *
2146
+ * For test teardown and for a micro-frontend being unmounted from a page it does
2147
+ * not own. Regular apps never need it — two empty hidden `div`s cost nothing, and
2148
+ * tearing them down while another component still announces would lose messages.
2149
+ */
2150
+ export declare function clearAnnouncer(): void;
2151
+
1668
2152
  /**
1669
2153
  * Delete Cache Storage buckets whose name passes `filter` (all of them when no
1670
2154
  * filter is given).
@@ -2070,7 +2554,29 @@ export declare function createApiClient(config: ApiClientConfig): ApiClient;
2070
2554
  * Multiple players coexist independently; use this when several layers of UI
2071
2555
  * need their own playback state.
2072
2556
  */
2073
- export declare function createAudioPlayer(): AudioPlayer;
2557
+ export declare function createAudioPlayer(): AudioPlayerHandle;
2558
+
2559
+ /**
2560
+ * Wrap a `MediaStream` in a recorder with a real state machine and an honest clock.
2561
+ *
2562
+ * The engine is shared with the video recorder (`createMediaRecorder`), because the
2563
+ * subtle parts are not audio-specific: `MediaRecorder` reports **no duration** (WebM
2564
+ * it writes carries none in its header, which is why `<audio>` shows `Infinity` for a
2565
+ * fresh recording) so the clock is kept by hand and subtracts paused time; and
2566
+ * `stop()` returns *before* the last `dataavailable` event, so the blob can only be
2567
+ * assembled in `onstop`. What stays here is the part that genuinely differs — the
2568
+ * container list.
2569
+ *
2570
+ * The stream is **not** owned here: `stop()` leaves the microphone open so a retake
2571
+ * does not need a second permission round-trip. Release it with the owning
2572
+ * `useMicrophone().stop()`.
2573
+ *
2574
+ * @param stream - A live audio stream, usually from {@link useMicrophone}.
2575
+ * @param options - See {@link AudioRecorderOptions}.
2576
+ * @returns The imperative recorder.
2577
+ * @throws When `MediaRecorder` is unavailable, or an explicit `mimeType` is unsupported.
2578
+ */
2579
+ export declare function createAudioRecorder(stream: MediaStream, options?: AudioRecorderOptions): AudioRecorderHandle;
2074
2580
 
2075
2581
  /**
2076
2582
  * Build a typed Zustand auth store with `persist` middleware. Each app passes
@@ -2105,6 +2611,14 @@ export declare interface CreateAuthStoreOptions<TUser> {
2105
2611
  initialToken?: string | null;
2106
2612
  }
2107
2613
 
2614
+ /**
2615
+ * Build a native detector for the given formats.
2616
+ *
2617
+ * @param formats - Symbologies to look for. Must be ones the engine supports.
2618
+ * @returns The detector, or `null` when the API is missing or refused the formats.
2619
+ */
2620
+ export declare function createBarcodeDetector(formats?: readonly BarcodeFormat[]): BarcodeDetectorLike | null;
2621
+
2108
2622
  /**
2109
2623
  * Build a ten-step tint scale from a single color.
2110
2624
  *
@@ -2237,6 +2751,46 @@ export declare interface CreateI18nOptions {
2237
2751
  messages: Catalog;
2238
2752
  }
2239
2753
 
2754
+ /**
2755
+ * Timing and cost accounting for a pipeline that runs on the user's device.
2756
+ */
2757
+ /**
2758
+ * Create a profiler for one run of a pipeline.
2759
+ *
2760
+ * Wrap each step in {@link InferenceProfiler.stage}, fold in durations you
2761
+ * already have (an SDK `speed` breakdown, say) with
2762
+ * {@link InferenceProfiler.mark}, then call `report()` once the run finishes.
2763
+ *
2764
+ * Stages are timed independently rather than as a tiling of the run, so
2765
+ * concurrent work is charged its real wall-clock span to each stage and the
2766
+ * timings can sum to more than `totalMs`. Surface that to users when you
2767
+ * render the breakdown — a bar chart implying a partition of the total would
2768
+ * be wrong for a pipeline that overlaps stages.
2769
+ *
2770
+ * @returns A profiler bound to the moment it was created.
2771
+ *
2772
+ * @example
2773
+ * ```typescript
2774
+ * import { createInferenceProfiler } from "tempest-react-sdk";
2775
+ * import { Detector } from "tempest-react-sdk/vision";
2776
+ *
2777
+ * const profiler = createInferenceProfiler();
2778
+ * const detector = await profiler.stage("load-model", () =>
2779
+ * Detector.create("/models/detect.onnx"),
2780
+ * );
2781
+ * const results = await profiler.stage("detect", () => detector.predict(blob));
2782
+ * profiler.mark("forward-pass", results[0].speed.inference);
2783
+ *
2784
+ * const report = await profiler.report({
2785
+ * models: [
2786
+ * { name: "detector", cacheName: "app-models", url: "/models/detect.onnx" },
2787
+ * ],
2788
+ * });
2789
+ * console.log(report.timings, report.totalMs, report.device, report.models);
2790
+ * ```
2791
+ */
2792
+ export declare function createInferenceProfiler(): InferenceProfiler;
2793
+
2240
2794
  /**
2241
2795
  * Trivial in-memory adapter. Suitable for tests, local development, or as a
2242
2796
  * fallback wrapping the real provider while it loads.
@@ -2272,6 +2826,48 @@ export declare interface CreateLaunchDarklyFeatureFlagsAdapterOptions {
2272
2826
  client: LDClientLike;
2273
2827
  }
2274
2828
 
2829
+ /**
2830
+ * Sample the loudness of a live stream, 0–1.
2831
+ *
2832
+ * This exists because a recorder with no visible level is indistinguishable from a
2833
+ * broken one. A muted OS input, a headset whose mic arm is switched off, the wrong
2834
+ * device selected — all three produce a perfectly successful recording of silence,
2835
+ * and the user only finds out after they finish talking.
2836
+ *
2837
+ * The value is RMS, not peak: peak reacts to a single sample and flickers, RMS tracks
2838
+ * perceived loudness. It is deliberately **not** React state — updating state per
2839
+ * frame would re-render the tree 60 times a second. Poll `level()` from a
2840
+ * `requestAnimationFrame` loop and write to the DOM, or read it inside an existing
2841
+ * animation.
2842
+ *
2843
+ * The `AudioContext` is created here and closed by `stop()`. Browsers cap the number
2844
+ * of live contexts (Chrome allows around six), so a meter left running on unmount
2845
+ * eventually breaks every later one on the page.
2846
+ *
2847
+ * @param stream - A live audio stream.
2848
+ * @param options - See {@link LevelMeterOptions}.
2849
+ * @returns A `level()` reader and a `stop()`.
2850
+ *
2851
+ * @example
2852
+ * const meter = createLevelMeter(stream);
2853
+ * const tick = () => { bar.style.transform = `scaleX(${meter.level()})`; raf = requestAnimationFrame(tick); };
2854
+ */
2855
+ export declare function createLevelMeter(stream: MediaStream, { fftSize, decay }?: LevelMeterOptions): LevelMeter;
2856
+
2857
+ /**
2858
+ * `localStorage`-backed resume storage — the default.
2859
+ *
2860
+ * `localStorage` and not IndexedDB on purpose. The record is four fields and a
2861
+ * URL; the requirement is only that it survives a reload, and pulling Dexie in for
2862
+ * that would put an IndexedDB dependency in the bundle of every app that uploads a
2863
+ * file. Apps that already have `createOfflineStore` open can pass their own
2864
+ * {@link ResumableUploadStorage} instead.
2865
+ *
2866
+ * @param prefix - Key prefix. Default `"tempest-upload:"`.
2867
+ * @returns A storage that no-ops when `localStorage` is unavailable.
2868
+ */
2869
+ export declare function createLocalUploadStorage(prefix?: string): ResumableUploadStorage;
2870
+
2275
2871
  /**
2276
2872
  * Create a structured leveled logger. Plug arbitrary sinks (Sentry, Datadog,
2277
2873
  * remote ingestion) by implementing the `LoggerSink` interface.
@@ -2287,6 +2883,34 @@ export declare interface CreateLoggerOptions {
2287
2883
  namespace?: string;
2288
2884
  }
2289
2885
 
2886
+ /**
2887
+ * Wrap a `MediaStream` in a recorder with a real state machine and an honest clock.
2888
+ *
2889
+ * This is the engine behind both `createAudioRecorder` and `createVideoRecorder`; the
2890
+ * only thing it does not decide is which containers to try, because that is the one
2891
+ * part that genuinely differs between the two.
2892
+ *
2893
+ * Two things `MediaRecorder` does not give you:
2894
+ *
2895
+ * - **A duration.** It reports none, and the `Blob` has no reliable one either —
2896
+ * WebM written by `MediaRecorder` carries no duration in its header, which is why
2897
+ * `<audio>`/`<video>` shows `Infinity` for a fresh recording. So the clock is kept
2898
+ * here, and it subtracts paused time: a recorder that counts wall-clock through a
2899
+ * pause reports a 30-second note as two minutes.
2900
+ * - **A promise from `stop()`.** The last chunk arrives *after* `stop()` returns, in
2901
+ * a `dataavailable` event that fires before `onstop`. Assembling the blob in
2902
+ * `onstop` is the only point where every chunk is in hand.
2903
+ *
2904
+ * The stream is **not** owned here: `stop()` leaves the device open so a retake does
2905
+ * not need a second permission round-trip. Release it with the owning hook's `stop()`.
2906
+ *
2907
+ * @param stream - A live stream, from `getUserMedia` or `getDisplayMedia`.
2908
+ * @param options - See {@link MediaRecordingOptions}.
2909
+ * @returns The imperative recorder.
2910
+ * @throws When `MediaRecorder` is unavailable, or an explicit `mimeType` is unsupported.
2911
+ */
2912
+ export declare function createMediaRecorder(stream: MediaStream, options: MediaRecordingOptions): MediaRecorderHandle;
2913
+
2290
2914
  /**
2291
2915
  * Build a typed IndexedDB-backed store using Dexie. Optionally scope every
2292
2916
  * operation by an `ownerField` (useful for multi-user SSE history, drafts,
@@ -2378,6 +3002,55 @@ export declare function createOSRMBackend(options: OSRMBackendOptions): RoutingB
2378
3002
  */
2379
3003
  export declare function createPartialResponse(request: Request, response: Response): Promise<Response>;
2380
3004
 
3005
+ /**
3006
+ * Build a WebAuthn client: the base64url ↔ `ArrayBuffer` plumbing, the two
3007
+ * ceremonies, and one classified error type.
3008
+ *
3009
+ * ## What your backend must do
3010
+ *
3011
+ * This is the **client half only**, and a WebAuthn client that documents only its
3012
+ * own half is unusable. Four routes are yours to implement:
3013
+ *
3014
+ * 1. `POST /webauthn/register/begin` → a {@link PasskeyCreationOptionsJSON}. Mint a
3015
+ * random `challenge` (≥16 bytes), store it against the session, and list the
3016
+ * user's existing credentials in `excludeCredentials`.
3017
+ * 2. `POST /webauthn/register/finish` ← a {@link PasskeyRegistrationJSON}. Verify
3018
+ * the challenge, `origin` and `type` inside `clientDataJSON`, parse the
3019
+ * attestation object, then store the credential id, public key and signature
3020
+ * counter.
3021
+ * 3. `POST /webauthn/signin/begin` → a {@link PasskeyRequestOptionsJSON}. New
3022
+ * challenge. Omit `allowCredentials` for a usernameless or autofill flow.
3023
+ * 4. `POST /webauthn/signin/finish` ← a {@link PasskeyAuthenticationJSON}. Look the
3024
+ * credential up by `id`, verify the signature over
3025
+ * `authenticatorData || sha256(clientDataJSON)`, and reject a signature counter
3026
+ * that did not grow (a clone). Only then issue your session token.
3027
+ *
3028
+ * @param options - Defaults applied when the server options omit them.
3029
+ * @returns A client usable from anywhere — React, a plain form, a worker.
3030
+ *
3031
+ * @example
3032
+ * const passkeys = createPasskeyClient({ rpId: "acme.com" });
3033
+ *
3034
+ * const options = await api.post("/webauthn/register/begin");
3035
+ * const credential = await passkeys.register(options);
3036
+ * await api.post("/webauthn/register/finish", { body: credential });
3037
+ */
3038
+ export declare function createPasskeyClient(options?: CreatePasskeyClientOptions): PasskeyClient;
3039
+
3040
+ /** Options for {@link createPasskeyClient}. */
3041
+ export declare interface CreatePasskeyClientOptions {
3042
+ /**
3043
+ * Default relying-party id, applied when the server options omit one. Must be
3044
+ * the page's domain or a registrable parent of it (`app.acme.com` may use
3045
+ * `acme.com`, never the other way round).
3046
+ */
3047
+ rpId?: string;
3048
+ /** Default ceremony timeout in ms. Default `60_000`. */
3049
+ timeoutMs?: number;
3050
+ /** `navigator.credentials` replacement, for tests. */
3051
+ credentials?: CredentialsContainerLike;
3052
+ }
3053
+
2381
3054
  /**
2382
3055
  * Record a live GPS trajectory from `navigator.geolocation.watchPosition`.
2383
3056
  * Framework-free — the {@link usePositionTracker} hook wraps this for React.
@@ -2488,6 +3161,61 @@ export declare function createQueryKeys<TKey extends string, TEntries extends Re
2488
3161
  */
2489
3162
  export declare function createRefreshQueue(refresh: () => Promise<void>): () => Promise<void>;
2490
3163
 
3164
+ /**
3165
+ * Chunked, resumable upload speaking the **tus 1.0.0** protocol (core plus the
3166
+ * *creation* and *termination* extensions).
3167
+ *
3168
+ * ## Why tus and not a bespoke scheme
3169
+ *
3170
+ * A resumable client whose wire format is undocumented cannot be integrated, and
3171
+ * inventing one means the backend is ours forever. tus is a published spec with
3172
+ * off-the-shelf servers (`tusd`, `tuspy`, `tus-node-server`), so a caller can point
3173
+ * this at something they did not write.
3174
+ *
3175
+ * ## What the backend must implement
3176
+ *
3177
+ * Every request carries `Tus-Resumable: 1.0.0`.
3178
+ *
3179
+ * | Step | Request | Expected response |
3180
+ * | --- | --- | --- |
3181
+ * | Create | `POST {endpoint}` + `Upload-Length`, `Upload-Metadata`, `Idempotency-Key` | `201` + `Location` (the upload URL, absolute or endpoint-relative) |
3182
+ * | Probe | `HEAD {uploadUrl}` | `200`/`204` + `Upload-Offset` |
3183
+ * | Write | `PATCH {uploadUrl}` + `Upload-Offset`, `Content-Type: application/offset+octet-stream`, chunk body | `204` + the new `Upload-Offset`; `409` when the offset does not match |
3184
+ * | Discard | `DELETE {uploadUrl}` | `204` |
3185
+ *
3186
+ * ## The failure that actually happens
3187
+ *
3188
+ * A chunk that the server stored but whose response never arrived. The client
3189
+ * cannot tell that from a chunk that was lost, and re-sending it blindly would
3190
+ * duplicate bytes. Two things prevent that:
3191
+ *
3192
+ * - **Writes are addressed, not appended.** Every `PATCH` states the offset it
3193
+ * writes at, so a retry after a lost response is asked to write bytes the server
3194
+ * already has and answers `409`. On any retry the client re-reads the truth with
3195
+ * `HEAD` first and continues from there.
3196
+ * - **Creation carries an `Idempotency-Key`** (from `generateIdempotencyKey`),
3197
+ * persisted before the first attempt and reused on retry. tus has no idempotent
3198
+ * creation of its own, so without this a lost `201` leaves an orphan upload on
3199
+ * the server. A backend that honours the header returns the same `Location`; one
3200
+ * that ignores it still works, it just keeps the orphan.
3201
+ *
3202
+ * @param options - Endpoint, file, and the knobs above.
3203
+ * @returns A handle with `start`/`pause`/`resume`/`abort` and live `state`/`offset`.
3204
+ *
3205
+ * @example
3206
+ * const upload = createResumableUpload({
3207
+ * endpoint: "/api/uploads",
3208
+ * file: recording,
3209
+ * metadata: { filename: "nota.webm", ticket: ticketId },
3210
+ * getToken: () => auth.getToken(),
3211
+ * onProgress: ({ fraction }) => setPercent(Math.round(fraction * 100)),
3212
+ * });
3213
+ *
3214
+ * const done = await upload.start();
3215
+ * if (done) await api.post("/api/tickets/1/audio", { body: { url: done.url } });
3216
+ */
3217
+ export declare function createResumableUpload(options: ResumableUploadOptions): ResumableUpload;
3218
+
2491
3219
  /**
2492
3220
  * Build a simple RBAC {@link AccessControl} from a static permission set.
2493
3221
  *
@@ -2735,6 +3463,30 @@ export declare interface CreateThemeOptions {
2735
3463
  darkSelector?: string;
2736
3464
  }
2737
3465
 
3466
+ /**
3467
+ * Record a video stream — a camera, a screen share, or a `canvas.captureStream()`.
3468
+ *
3469
+ * The state machine, the clock that subtracts paused time and the `stop()` that
3470
+ * resolves in `onstop` with every chunk in hand are shared with the audio recorder
3471
+ * (see `createMediaRecorder`); what this adds is the container list and
3472
+ * `videoBitsPerSecond`.
3473
+ *
3474
+ * The stream is **not** owned here. For a screen share in particular, stopping the
3475
+ * recorder must not stop the sharing: a support flow usually records, stops, lets the
3476
+ * user look at the result and then records again.
3477
+ *
3478
+ * @param stream - A live stream carrying at least one video track.
3479
+ * @param options - See {@link VideoRecorderOptions}.
3480
+ * @returns The imperative recorder.
3481
+ * @throws When `MediaRecorder` is unavailable, or an explicit `mimeType` is unsupported.
3482
+ *
3483
+ * @example
3484
+ * const recorder = createVideoRecorder(stream, { videoBitsPerSecond: 2_500_000 });
3485
+ * recorder.start();
3486
+ * const { blob, durationMs } = await recorder.stop();
3487
+ */
3488
+ export declare function createVideoRecorder(stream: MediaStream, options?: VideoRecorderOptions): VideoRecorderHandle;
3489
+
2738
3490
  /**
2739
3491
  * Open a WebSocket with automatic exponential-backoff reconnect, optional
2740
3492
  * heartbeat pings, and typed JSON parsing.
@@ -2796,6 +3548,28 @@ export declare interface CreateWebSocketOptions<T> {
2796
3548
  onStatusChange?: (status: WebSocketStatus) => void;
2797
3549
  }
2798
3550
 
3551
+ /**
3552
+ * Minimal subset of `navigator.credentials` the passkey client touches.
3553
+ *
3554
+ * Declared here — the `<X>Like` pattern the SDK's adapters use — for two reasons:
3555
+ * jsdom has no `navigator.credentials` at all, so tests must inject a double; and
3556
+ * `mediation: "conditional"` is newer than some TypeScript DOM libs, which would
3557
+ * otherwise reject the call that makes autofill work.
3558
+ */
3559
+ export declare interface CredentialsContainerLike {
3560
+ /** Runs the registration ceremony. */
3561
+ create(options: {
3562
+ publicKey: PublicKeyCredentialCreationOptions;
3563
+ signal?: AbortSignal;
3564
+ }): Promise<Credential | null>;
3565
+ /** Runs the authentication ceremony. */
3566
+ get(options: {
3567
+ publicKey: PublicKeyCredentialRequestOptions;
3568
+ signal?: AbortSignal;
3569
+ mediation?: string;
3570
+ }): Promise<Credential | null>;
3571
+ }
3572
+
2799
3573
  /** Cursor-paginated response envelope (`CursorPaginationSchema[T]`). */
2800
3574
  export declare interface CursorPage<T> {
2801
3575
  /** The rows for this batch. */
@@ -2927,25 +3701,53 @@ export declare interface DataProviderOptions {
2927
3701
 
2928
3702
  /**
2929
3703
  * Stateful, headless data table built on top of {@link Table}. Adds
2930
- * client-side searching, click-to-sort columns, and pagination while
2931
- * delegating all table markup to the underlying Table component.
3704
+ * client-side searching, click-to-sort columns, pagination and opt-in inline
3705
+ * editing while delegating all table markup to the underlying Table component.
2932
3706
  *
2933
3707
  * - Clicking a sortable header cycles asc → desc → unsorted.
2934
3708
  * - Search matches a case-insensitive substring across `searchKeys`
2935
3709
  * (or every string/number column when not provided).
2936
3710
  * - Pagination is hidden when the result fits on a single page.
3711
+ * - A column with `editable` renders a button that opens an inline editor;
3712
+ * `Enter` commits, `Escape` discards, `Tab` walks to the next editable cell.
3713
+ *
3714
+ * Editing is strictly opt-in: with no `editable` column (or no `onCellChange`) the
3715
+ * rendered markup is byte-for-byte what it was before the feature existed, which
3716
+ * matters because the component is published.
3717
+ *
3718
+ * ## Optimistic, with a visible rollback
2937
3719
  *
2938
- * The header memo depends on `columns` and `sort` only: `toggleSort` is
2939
- * recreated each render but always closes over the same setter, so including it
2940
- * would rebuild every header on every render without changing behaviour. That
2941
- * is why `exhaustive-deps` is silenced on that dependency array.
3720
+ * An accepted edit is shown immediately and `onCellChange` runs in the background.
3721
+ * If it rejects, the cell returns to the old value **and** shows the reason as a
3722
+ * `role="alert"` tied to the cell. A silent revert is worse than no optimistic
3723
+ * update at all: the user watched their edit appear and has no reason to doubt it.
3724
+ *
3725
+ * The header memo depends on `columns`, `sort` and the editing state only:
3726
+ * `toggleSort` and the commit callbacks are recreated each render but always close
3727
+ * over the same setters, so including them would rebuild every header on every
3728
+ * render without changing behaviour. That is why `exhaustive-deps` is silenced on
3729
+ * that dependency array.
2942
3730
  */
2943
- export declare function DataTable<T>({ data, columns, pageSize, searchable, searchKeys, initialSort, rowKey, emptyMessage, className, ...rest }: DataTableProps<T>): JSX.Element;
3731
+ export declare function DataTable<T>({ data, columns, pageSize, searchable, searchKeys, initialSort, rowKey, emptyMessage, onCellChange, editLabels, className, ...rest }: DataTableProps<T>): JSX.Element;
3732
+
3733
+ /** One accepted cell edit, handed to `onCellChange`. */
3734
+ export declare interface DataTableCellChange<T> {
3735
+ /** The row as it was before the edit. */
3736
+ row: T;
3737
+ /** Which column changed. */
3738
+ key: keyof T;
3739
+ /** The parsed new value. */
3740
+ value: unknown;
3741
+ /** The value that was displayed before the edit. */
3742
+ previous: unknown;
3743
+ /** Index of the row in the full `data` array. */
3744
+ rowIndex: number;
3745
+ }
2944
3746
 
2945
3747
  /**
2946
3748
  * Column definition for {@link DataTable}. Extends the headless {@link Table}
2947
- * column shape with a typed `key`, opt-in sorting, and the visual options that
2948
- * are forwarded to the underlying Table cell.
3749
+ * column shape with a typed `key`, opt-in sorting, opt-in inline editing, and the
3750
+ * visual options that are forwarded to the underlying Table cell.
2949
3751
  */
2950
3752
  export declare interface DataTableColumn<T> {
2951
3753
  /** Property of the row this column reads from. Doubles as the cell key. */
@@ -2962,8 +3764,49 @@ export declare interface DataTableColumn<T> {
2962
3764
  priority?: TablePriority;
2963
3765
  /** Fixed column width forwarded to the Table cell. */
2964
3766
  width?: string | number;
3767
+ /**
3768
+ * Let cells in this column be edited in place. Requires `onCellChange` on the
3769
+ * table; without it the column stays read-only.
3770
+ */
3771
+ editable?: boolean;
3772
+ /** Editor input type. Default `"text"`. */
3773
+ editorType?: DataTableEditorType;
3774
+ /** Text the editor opens with. Defaults to `String(value ?? "")`. */
3775
+ formatEdit?: (row: T) => string;
3776
+ /**
3777
+ * Turn the typed string into the stored value. Defaults to the trimmed string,
3778
+ * or `Number(raw)` when `editorType` is `"number"`.
3779
+ */
3780
+ parse?: (raw: string, row: T) => unknown;
3781
+ /** Return a message to reject the edit, or `null` to accept it. */
3782
+ validate?: (value: unknown, row: T) => string | null;
3783
+ }
3784
+
3785
+ /** Copy for the inline-editing affordances. Every entry has a PT-BR default. */
3786
+ export declare interface DataTableEditLabels {
3787
+ /**
3788
+ * Visually hidden prefix that turns a cell's own content into the button's name.
3789
+ *
3790
+ * A prefix and not a whole label: the accessible name has to *contain* the visible
3791
+ * text (WCAG 2.5.3, Label in Name), and a label built from the raw value would say
3792
+ * "850000" over a cell that reads `R$ 8.500,00` — which breaks voice control and
3793
+ * makes the screen reader disagree with the screen.
3794
+ *
3795
+ * A single space is appended when it is rendered, so the name reads
3796
+ * `"Editar Salário: R$ 8.500,00"`. Do not add one yourself.
3797
+ */
3798
+ editCell: (column: string) => string;
3799
+ /** Accessible name of the editor input. */
3800
+ editor: (column: string, rowNumber: number) => string;
3801
+ /** Announced (politely) once a cell saved. */
3802
+ saved: (column: string) => string;
3803
+ /** Shown in the cell when the save was rejected and no reason was thrown. */
3804
+ saveFailed: (column: string) => string;
2965
3805
  }
2966
3806
 
3807
+ /** Input types an editable column can use. */
3808
+ export declare type DataTableEditorType = "text" | "number" | "date" | "email" | "tel" | "url";
3809
+
2967
3810
  export declare interface DataTableProps<T> extends HTMLAttributes<HTMLDivElement> {
2968
3811
  /** Full, unfiltered dataset. Sorting/filtering/pagination happen client-side. */
2969
3812
  data: T[];
@@ -2984,6 +3827,14 @@ export declare interface DataTableProps<T> extends HTMLAttributes<HTMLDivElement
2984
3827
  rowKey?: (row: T, index: number) => string | number;
2985
3828
  /** Content shown when no rows match. */
2986
3829
  emptyMessage?: ReactNode;
3830
+ /**
3831
+ * Persist an accepted cell edit. Return a promise: while it is pending the cell
3832
+ * already shows the new value, and a rejection rolls that back and surfaces the
3833
+ * error in the cell. Without this prop no column is editable.
3834
+ */
3835
+ onCellChange?: (change: DataTableCellChange<T>) => void | Promise<void>;
3836
+ /** Override the PT-BR copy of the editing affordances. */
3837
+ editLabels?: Partial<DataTableEditLabels>;
2987
3838
  }
2988
3839
 
2989
3840
  export declare interface DataTableSort<T> {
@@ -3118,12 +3969,24 @@ export declare function decodeJWT(token: string): DecodedJWT;
3118
3969
  */
3119
3970
  export declare function deepMerge<T>(target: T, source: Partial<T>): T;
3120
3971
 
3972
+ /**
3973
+ * What a scanner looks for when you do not say.
3974
+ *
3975
+ * Deliberately three formats, not all fourteen. Every extra symbology is more work
3976
+ * per frame, and on a mid-range phone the difference between three and fourteen is the
3977
+ * difference between a scanner that locks on instantly and one that feels broken.
3978
+ */
3979
+ export declare const DEFAULT_BARCODE_FORMATS: readonly BarcodeFormat[];
3980
+
3121
3981
  /**
3122
3982
  * Default average car speed in km/h used to derive duration from distance.
3123
3983
  * Mirrors `DEFAULT_CAR_SPEED_KMH` from `tempest-fastapi-sdk`.
3124
3984
  */
3125
3985
  export declare const DEFAULT_CAR_SPEED_KMH = 50;
3126
3986
 
3987
+ /** Default chunk size: 5 MiB, the size most tus servers are tuned for. */
3988
+ export declare const DEFAULT_CHUNK_SIZE: number;
3989
+
3127
3990
  /**
3128
3991
  * Multiplier applied to the great-circle distance to approximate real road
3129
3992
  * distance. Mirrors `DEFAULT_CIRCUITY_FACTOR` from `tempest-fastapi-sdk`.
@@ -3137,6 +4000,21 @@ export declare const DEFAULT_CIRCUITY_FACTOR = 1.3;
3137
4000
  */
3138
4001
  export declare const DEFAULT_MODE_DURATION_FACTORS: Record<TravelMode, number>;
3139
4002
 
4003
+ /**
4004
+ * COSE algorithms offered when the server sends no `pubKeyCredParams`, in
4005
+ * preference order.
4006
+ *
4007
+ * `-8` is Ed25519, which modern authenticators prefer and which produces the
4008
+ * smallest signatures. `-7` is ES256, the one algorithm every WebAuthn
4009
+ * authenticator supports. `-257` is RS256, needed for TPM-backed Windows Hello.
4010
+ * Offering all three is what avoids a `NotSupportedError` on some device you do
4011
+ * not own; a server that cannot verify one of them should send its own list.
4012
+ */
4013
+ export declare const DEFAULT_PUB_KEY_CRED_PARAMS: {
4014
+ type: "public-key";
4015
+ alg: number;
4016
+ }[];
4017
+
3140
4018
  /**
3141
4019
  * Identity helper that types a declarative route tree. Use it so editors give
3142
4020
  * autocomplete and type-checking on every node; the array is returned as-is.
@@ -3182,12 +4060,53 @@ export declare interface DescriptionListProps extends HTMLAttributes<HTMLDListEl
3182
4060
  items: DescriptionListItem[];
3183
4061
  }
3184
4062
 
4063
+ /**
4064
+ * The shape a detector resolves with, before normalisation.
4065
+ *
4066
+ * Every field is optional because a polyfill is allowed to report the value and no
4067
+ * geometry at all, and the native engines differ on `cornerPoints`.
4068
+ */
4069
+ export declare interface DetectedBarcodeLike {
4070
+ rawValue?: string;
4071
+ format?: string;
4072
+ boundingBox?: DOMRectReadOnly;
4073
+ cornerPoints?: readonly BarcodePoint[];
4074
+ }
4075
+
4076
+ /**
4077
+ * Shapes describing what an on-device inference run cost.
4078
+ *
4079
+ * The browser exposes no energy counter and no FLOP counter, so "cost" here
4080
+ * is assembled from what a page can actually observe: how long each stage
4081
+ * took, how much parallelism and memory the device reports, and how large the
4082
+ * cached model weights are. Anything the platform does not expose stays
4083
+ * `null` — a UI can then render "—" instead of a fabricated number.
4084
+ */
4085
+ /**
4086
+ * Device capabilities as reported by the browser.
4087
+ *
4088
+ * Every field is best-effort. `deviceMemoryGb` and `jsHeapUsedMb` come from
4089
+ * Chromium-only APIs (`navigator.deviceMemory`, `performance.memory`) and are
4090
+ * `null` everywhere else, including Firefox and Safari.
4091
+ */
4092
+ export declare interface DeviceProfile {
4093
+ /** Logical cores available to workers, or `null` when unreported. */
4094
+ hardwareConcurrency: number | null;
4095
+ /** Approximate device RAM in GiB (coarse, Chromium-only), or `null`. */
4096
+ deviceMemoryGb: number | null;
4097
+ /** Used JS heap in MiB (Chromium-only), or `null`. */
4098
+ jsHeapUsedMb: number | null;
4099
+ }
4100
+
3185
4101
  export declare interface DisclosureHandlers {
3186
4102
  open: () => void;
3187
4103
  close: () => void;
3188
4104
  toggle: () => void;
3189
4105
  }
3190
4106
 
4107
+ /** Which surface to put first in the picker. */
4108
+ export declare type DisplaySurfaceHint = "monitor" | "window" | "browser";
4109
+
3191
4110
  /** How many steps the diverging token scale has, midpoint included. */
3192
4111
  export declare const DIVERGING_STEP_COUNT = 9;
3193
4112
 
@@ -3404,6 +4323,23 @@ export declare interface EmptyStateProps {
3404
4323
  */
3405
4324
  export declare function encodeQR(text: string, options?: QREncodeOptions): QRMatrix;
3406
4325
 
4326
+ /**
4327
+ * Wrap PCM in a 16-bit RIFF/WAVE container.
4328
+ *
4329
+ * The header is the 44-byte canonical form: `RIFF` size, `WAVE`, a 16-byte `fmt `
4330
+ * chunk declaring format 1 (uncompressed PCM), then `data`. Samples are interleaved
4331
+ * and clamped before scaling, because a value even slightly past ±1 wraps around when
4332
+ * truncated to 16 bits and turns a loud passage into a burst of noise.
4333
+ *
4334
+ * Implemented here rather than pulled from a package: it is a fixed header and a
4335
+ * scaling loop, roughly forty lines, and a dependency for it would put its own
4336
+ * version bounds on every consumer of this SDK to save writing them.
4337
+ *
4338
+ * @param audio - Channels and sample rate.
4339
+ * @returns A `Blob` of type `audio/wav`.
4340
+ */
4341
+ export declare function encodeWav({ channels, sampleRate }: PcmAudio): Blob;
4342
+
3407
4343
  /**
3408
4344
  * Class-based React error boundary with a render-prop or static fallback.
3409
4345
  * Auto-resets when any value in `resetKeys` changes.
@@ -3643,7 +4579,7 @@ export declare interface Filter {
3643
4579
  */
3644
4580
  export declare function FilterBar({ fields, value, onChange, locale, actions, className, ...rest }: FilterBarProps): JSX.Element;
3645
4581
 
3646
- export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_9> {
4582
+ export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_12> {
3647
4583
  /** Fields the user may filter by. */
3648
4584
  fields: readonly FilterField[];
3649
4585
  /** Applied filters. Controlled. */
@@ -3901,6 +4837,31 @@ export declare function formatDate(value: string | Date): string;
3901
4837
  */
3902
4838
  export declare function formatDateTime(value: string | Date): string;
3903
4839
 
4840
+ /**
4841
+ * Rendering helpers for the numbers a profiler produces.
4842
+ */
4843
+ /**
4844
+ * Format a millisecond duration for display.
4845
+ *
4846
+ * Sub-second values keep millisecond resolution — the interesting range for a
4847
+ * single forward pass — and anything longer switches to seconds so a cold
4848
+ * start that pays a model download does not read as a five-digit number.
4849
+ * Durations under `1 ms` render as `"<1 ms"` rather than `"0 ms"`, which
4850
+ * would read as "not measured".
4851
+ *
4852
+ * @param value Duration in milliseconds.
4853
+ * @returns The formatted string, or `"—"` for a non-finite or negative input.
4854
+ *
4855
+ * @example
4856
+ * ```typescript
4857
+ * formatDurationMs(0.04); // "<1 ms"
4858
+ * formatDurationMs(142.6); // "143 ms"
4859
+ * formatDurationMs(4321); // "4.32 s"
4860
+ * formatDurationMs(NaN); // "—"
4861
+ * ```
4862
+ */
4863
+ export declare function formatDurationMs(value: number): string;
4864
+
3904
4865
  /**
3905
4866
  * Format a fraction (0-1) as a percentage with one decimal.
3906
4867
  *
@@ -4110,6 +5071,18 @@ export declare interface GetListParams {
4110
5071
  filters?: DataFilters;
4111
5072
  }
4112
5073
 
5074
+ /**
5075
+ * Which symbologies this engine will actually decode.
5076
+ *
5077
+ * Worth asking rather than assuming: the format list belongs to the platform decoder,
5078
+ * not to the browser, so two Chromium builds on two operating systems answer
5079
+ * differently — and asking for a format the engine does not have makes the constructor
5080
+ * throw `NotSupportedError`, which reads like a bug in your code.
5081
+ *
5082
+ * @returns The supported formats, or an empty array when there is no detector.
5083
+ */
5084
+ export declare function getSupportedBarcodeFormats(): Promise<readonly BarcodeFormat[]>;
5085
+
4113
5086
  /**
4114
5087
  * Look up a preset by name.
4115
5088
  *
@@ -4467,15 +5440,79 @@ export declare interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivEl
4467
5440
  ref?: React.Ref<ImageCropperHandle>;
4468
5441
  }
4469
5442
 
4470
- export declare interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> {
4471
- /** Primary image source URL. */
4472
- src: string;
4473
- /** Fallback source swapped in once if the primary `src` fails to load. */
4474
- fallback?: string;
4475
- /** Alternative text describing the image (required for accessibility). */
4476
- alt: string;
4477
- /** When true (default) uses native lazy loading; otherwise loads eagerly. */
4478
- lazy?: boolean;
5443
+ export declare interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> {
5444
+ /** Primary image source URL. */
5445
+ src: string;
5446
+ /** Fallback source swapped in once if the primary `src` fails to load. */
5447
+ fallback?: string;
5448
+ /** Alternative text describing the image (required for accessibility). */
5449
+ alt: string;
5450
+ /** When true (default) uses native lazy loading; otherwise loads eagerly. */
5451
+ lazy?: boolean;
5452
+ }
5453
+
5454
+ /**
5455
+ * Records how long each stage of a pipeline took.
5456
+ *
5457
+ * Stages are measured **independently**, not as a tiling of the whole run:
5458
+ * two stages started concurrently are each charged their full wall-clock
5459
+ * span, so the sum can exceed {@link InferenceReport.totalMs}. That is the
5460
+ * honest reading for a pipeline that decodes an image while the model
5461
+ * sessions are still loading.
5462
+ */
5463
+ export declare interface InferenceProfiler {
5464
+ /**
5465
+ * Run an async stage and record its duration.
5466
+ *
5467
+ * @param name Stage label used as the key in the report.
5468
+ * @param run The work to time.
5469
+ * @returns Whatever `run` resolved to.
5470
+ */
5471
+ stage<T>(name: string, run: () => Promise<T>): Promise<T>;
5472
+ /**
5473
+ * Run a synchronous stage and record its duration.
5474
+ *
5475
+ * @param name Stage label used as the key in the report.
5476
+ * @param run The work to time.
5477
+ * @returns Whatever `run` returned.
5478
+ */
5479
+ stageSync<T>(name: string, run: () => T): T;
5480
+ /**
5481
+ * Record a duration measured elsewhere — a `speed` breakdown returned by
5482
+ * `tempest-react-sdk/vision`, for instance.
5483
+ *
5484
+ * Repeated names accumulate, so folding two passes of the same kind into
5485
+ * one row is a matter of calling `mark` twice.
5486
+ *
5487
+ * @param name Stage label used as the key in the report.
5488
+ * @param durationMs How long it took, in milliseconds.
5489
+ */
5490
+ mark(name: string, durationMs: number): void;
5491
+ /**
5492
+ * Assemble the report for everything recorded so far.
5493
+ *
5494
+ * @param options Which models to size up in Cache Storage.
5495
+ * @returns The finished report.
5496
+ */
5497
+ report(options?: InferenceReportOptions): Promise<InferenceReport>;
5498
+ }
5499
+
5500
+ /** What one profiled run cost. */
5501
+ export declare interface InferenceReport {
5502
+ /** Duration in milliseconds per stage name, in the order first recorded. */
5503
+ timings: Readonly<Record<string, number>>;
5504
+ /** Milliseconds from profiler creation to the `report()` call. */
5505
+ totalMs: number;
5506
+ device: DeviceProfile;
5507
+ models: readonly ProfiledModelSize[];
5508
+ /** Epoch millis at which the report was assembled. */
5509
+ measuredAt: number;
5510
+ }
5511
+
5512
+ /** Options for {@link InferenceProfiler.report}. */
5513
+ export declare interface InferenceReportOptions {
5514
+ /** Models to measure in Cache Storage. Omit to report none. */
5515
+ models?: readonly ProfiledModel[];
4479
5516
  }
4480
5517
 
4481
5518
  export declare interface InMemoryFlagsOptions {
@@ -4741,6 +5778,46 @@ export declare function isAndroidWithoutPromptApi(): boolean;
4741
5778
  */
4742
5779
  export declare function isApiError(error: unknown): error is ApiError;
4743
5780
 
5781
+ /**
5782
+ * Whether this browser can route audio to a chosen output device.
5783
+ *
5784
+ * Chromium-only at the time of writing: Firefox has `setSinkId` behind a preference
5785
+ * that is off by default, and Safari does not implement it at all. Check this before
5786
+ * rendering an output picker, or the control is a lie on two of three engines.
5787
+ */
5788
+ export declare function isAudioOutputSelectionSupported(): boolean;
5789
+
5790
+ /** Whether `MediaRecorder` exists and can produce at least one audio container. */
5791
+ export declare function isAudioRecordingSupported(): boolean;
5792
+
5793
+ /**
5794
+ * Whether this browser can decode barcodes on its own.
5795
+ *
5796
+ * **Expect `false` on a lot of real devices, and design for it.** `BarcodeDetector` is
5797
+ * a Chromium-only API backed by a platform decoder, so it is there on Android and
5798
+ * ChromeOS, usually there on macOS, and **absent** on Chromium for Windows and Linux,
5799
+ * in Firefox, and in every browser on iOS (all of which are WebKit underneath,
5800
+ * including Chrome for iOS).
5801
+ *
5802
+ * This SDK ships **no** decoder of its own and no bundled fallback: a QR reader is
5803
+ * Reed–Solomon error correction plus perspective correction plus a finder-pattern
5804
+ * search, and the honest options are a WASM build every consumer of this SDK would pay
5805
+ * for, or nothing. So the escape hatch is injection instead — pass any
5806
+ * {@link BarcodeDetectorLike} (the `barcode-detector` polyfill, your own `zxing-wasm`
5807
+ * wrapper) as `detector` to `useBarcodeScanner`, and the SDK drives it exactly like
5808
+ * the native one.
5809
+ *
5810
+ * @returns `true` when `new BarcodeDetector()` will work.
5811
+ */
5812
+ export declare function isBarcodeDetectionSupported(): boolean;
5813
+
5814
+ /**
5815
+ * Whether autofill-driven passkeys (`mediation: "conditional"`) are available.
5816
+ *
5817
+ * @returns `false` when the API is missing or throws.
5818
+ */
5819
+ export declare function isConditionalMediationAvailable(): Promise<boolean>;
5820
+
4744
5821
  /**
4745
5822
  * Type guard for {@link Coordinate}: an object with finite, in-range
4746
5823
  * `latitude` and `longitude`.
@@ -4805,6 +5882,14 @@ export declare function isIOS(): boolean;
4805
5882
  */
4806
5883
  export declare function isJWTExpired(token: string, leewaySeconds?: number): boolean;
4807
5884
 
5885
+ /**
5886
+ * Whether `getUserMedia` is reachable at all.
5887
+ *
5888
+ * Separate from the classifier because a page often wants to hide a "record" button
5889
+ * entirely rather than render it and fail on click.
5890
+ */
5891
+ export declare function isMediaCaptureSupported(): boolean;
5892
+
4808
5893
  /**
4809
5894
  * Type guard asserting a value is a number, excluding `NaN`.
4810
5895
  *
@@ -4823,6 +5908,15 @@ export declare function isNumber(value: unknown): value is number;
4823
5908
  */
4824
5909
  export declare function isOffsetPage<T = unknown>(value: unknown): value is OffsetPage<T>;
4825
5910
 
5911
+ /**
5912
+ * Whether this browser exposes WebAuthn at all.
5913
+ *
5914
+ * Note that "supported" is not "usable": WebAuthn also requires a secure context,
5915
+ * and a device may have no authenticator. Use
5916
+ * {@link isPlatformAuthenticatorAvailable} before offering a passkey button.
5917
+ */
5918
+ export declare function isPasskeySupported(): boolean;
5919
+
4826
5920
  /**
4827
5921
  * Type guard asserting a value is a plain object literal.
4828
5922
  *
@@ -4837,15 +5931,36 @@ export declare function isOffsetPage<T = unknown>(value: unknown): value is Offs
4837
5931
  */
4838
5932
  export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
4839
5933
 
5934
+ /**
5935
+ * Whether the device has a **built-in** authenticator — Face ID, Touch ID,
5936
+ * Windows Hello, an Android screen lock.
5937
+ *
5938
+ * This is the check that decides whether "Entrar com passkey" may be shown at
5939
+ * all. `isPasskeySupported()` is true on a desktop with no biometrics and no
5940
+ * security key, and offering a passkey there sends the user into a sheet that can
5941
+ * only be cancelled. A `false` here does not forbid passkeys — a phone can still
5942
+ * be used over hybrid/QR — it means the flow needs a second step, so present it
5943
+ * as "usar meu celular", not as one tap.
5944
+ *
5945
+ * @returns `false` when the API is missing, so a caller never has to null-check.
5946
+ */
5947
+ export declare function isPlatformAuthenticatorAvailable(): Promise<boolean>;
5948
+
4840
5949
  /**
4841
5950
  * Convenience check for environments where the Push API is unavailable
4842
5951
  * (Safari iOS without PWA install, older browsers, SSR, etc.).
4843
5952
  */
4844
5953
  export declare function isPushSupported(): boolean;
4845
5954
 
5955
+ /** Whether `getDisplayMedia` is reachable at all. */
5956
+ export declare function isScreenCaptureSupported(): boolean;
5957
+
4846
5958
  /** True when the Web Share API is available in this environment. */
4847
5959
  export declare function isShareSupported(): boolean;
4848
5960
 
5961
+ /** Whether this browser exposes the Web Speech recognition API at all. */
5962
+ export declare function isSpeechRecognitionSupported(): boolean;
5963
+
4849
5964
  /**
4850
5965
  * Reports whether the app is running as an installed PWA (Android Chrome, iOS,
4851
5966
  * or desktop). Use it to suppress install CTAs once the user is already in the
@@ -4870,6 +5985,9 @@ export declare function isValidLatitude(value: number): boolean;
4870
5985
  /** True when `value` is a finite longitude in `[-180, 180]`. */
4871
5986
  export declare function isValidLongitude(value: number): boolean;
4872
5987
 
5988
+ /** Whether `MediaRecorder` exists and can produce at least one video container. */
5989
+ export declare function isVideoRecordingSupported(): boolean;
5990
+
4873
5991
  /**
4874
5992
  * Kanban board: columns of cards, reorderable within a column and movable across
4875
5993
  * columns, by pointer **or** keyboard.
@@ -5104,6 +6222,31 @@ export declare interface LDClientLike {
5104
6222
  off?: (event: string, handler: () => void) => void;
5105
6223
  }
5106
6224
 
6225
+ /** A running level meter. */
6226
+ export declare interface LevelMeter {
6227
+ /** Latest level, 0–1. Read it on your own frame loop. */
6228
+ level: () => number;
6229
+ /** Stop sampling and release the Web Audio graph. */
6230
+ stop: () => void;
6231
+ }
6232
+
6233
+ /** Options for {@link createLevelMeter}. */
6234
+ export declare interface LevelMeterOptions {
6235
+ /**
6236
+ * FFT window. 1024 is a good default: ~21 ms at 48 kHz, long enough to be stable
6237
+ * and short enough to react to a syllable.
6238
+ */
6239
+ fftSize?: number;
6240
+ /**
6241
+ * Extra smoothing on the way down, 0–1. Default `0.7`.
6242
+ *
6243
+ * A raw RMS reading is jittery enough to make a meter look broken. Attack is left
6244
+ * instant — a meter that lags the voice going *up* reads as "not recording" —
6245
+ * while the decay is eased, which is how every hardware meter behaves.
6246
+ */
6247
+ decay?: number;
6248
+ }
6249
+
5107
6250
  /**
5108
6251
  * Full-screen image viewer with keyboard navigation.
5109
6252
  *
@@ -5363,7 +6506,7 @@ export declare type MarkdownInline = {
5363
6506
  type: "break";
5364
6507
  };
5365
6508
 
5366
- export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_8> {
6509
+ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_11> {
5367
6510
  /** The Markdown source. */
5368
6511
  source: string;
5369
6512
  /**
@@ -5401,7 +6544,7 @@ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElemen
5401
6544
  */
5402
6545
  export declare function Masonry<T>({ items, children, itemKey, columns, gap, className, style, ...rest }: MasonryProps<T>): JSX.Element;
5403
6546
 
5404
- export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
6547
+ export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_10> {
5405
6548
  /** What to lay out. */
5406
6549
  items: readonly T[];
5407
6550
  /** Render one card. */
@@ -5430,6 +6573,115 @@ export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElem
5430
6573
  */
5431
6574
  export declare function matrixToPath(matrix: QRMatrix, margin?: number): string;
5432
6575
 
6576
+ /** A classified capture error with a human-readable, English message. */
6577
+ export declare interface MediaAccessError {
6578
+ kind: MediaAccessErrorKind;
6579
+ message: string;
6580
+ }
6581
+
6582
+ /** Classified reason a capture device could not be acquired. */
6583
+ export declare type MediaAccessErrorKind = "unsupported" | "insecure" | "permission-denied" | "not-found" | "in-use" | "unknown";
6584
+
6585
+ /**
6586
+ * What a media error is about.
6587
+ *
6588
+ * `"screen"` is not a device in the `getUserMedia` sense — it is what
6589
+ * `getDisplayMedia` captures — but it fails through the same `DOMException` names, so
6590
+ * it is classified by the same function rather than by a second copy of the table.
6591
+ */
6592
+ export declare type MediaDeviceKindLabel = "microphone" | "camera" | "screen";
6593
+
6594
+ /** One device the browser is willing to tell us about. */
6595
+ export declare interface MediaDeviceOption {
6596
+ deviceId: string;
6597
+ /**
6598
+ * Human label, or `""` until permission has been granted.
6599
+ *
6600
+ * See {@link UseMediaDevicesResult.labelsAvailable} — an empty label is not a
6601
+ * bug, it is the browser refusing to fingerprint the machine.
6602
+ */
6603
+ label: string;
6604
+ kind: MediaDeviceKind;
6605
+ groupId: string;
6606
+ }
6607
+
6608
+ /** Which capture permission to observe. */
6609
+ export declare type MediaPermissionName = "microphone" | "camera";
6610
+
6611
+ /**
6612
+ * Permission state, including the two cases the browser prompt cannot tell you
6613
+ * apart on its own.
6614
+ *
6615
+ * - `"unknown"` — the Permissions API is unavailable (Safari does not report
6616
+ * `microphone`), so the only way to learn the answer is to ask for the device.
6617
+ * - `"prompt"` — never asked. Asking now shows the browser prompt.
6618
+ * - `"granted"` / `"denied"` — settled. `"denied"` is **sticky**: calling
6619
+ * `getUserMedia` again does not re-prompt, it rejects immediately.
6620
+ */
6621
+ export declare type MediaPermissionState = "unknown" | "prompt" | "granted" | "denied";
6622
+
6623
+ /** Imperative recorder over one `MediaStream`. */
6624
+ export declare interface MediaRecorderHandle {
6625
+ /** Begin recording. No-op when already recording or paused. */
6626
+ start: () => void;
6627
+ /** Pause. The clock stops; `durationMs` freezes. */
6628
+ pause: () => void;
6629
+ /** Resume after `pause()`. */
6630
+ resume: () => void;
6631
+ /** Stop and resolve with the assembled recording. */
6632
+ stop: () => Promise<MediaRecording>;
6633
+ /** Stop and throw the bytes away. */
6634
+ cancel: () => void;
6635
+ status: () => MediaRecorderStatus;
6636
+ /** Recorded length so far, excluding paused time. */
6637
+ durationMs: () => number;
6638
+ /** The negotiated container. */
6639
+ mimeType: string;
6640
+ }
6641
+
6642
+ /** Lifecycle of a recording. */
6643
+ export declare type MediaRecorderStatus = "idle" | "recording" | "paused" | "stopped";
6644
+
6645
+ /** A finished recording, whatever it was made of. */
6646
+ export declare interface MediaRecording {
6647
+ /** The bytes. Wrap with `useObjectUrl` to play it, or POST it as-is. */
6648
+ blob: Blob;
6649
+ /** What the browser actually produced — not necessarily what you asked for. */
6650
+ mimeType: string;
6651
+ /** Recorded length, excluding time spent paused. */
6652
+ durationMs: number;
6653
+ }
6654
+
6655
+ /** What a track carries — used only to word the errors this engine throws. */
6656
+ export declare type MediaRecordingKind = "audio" | "video";
6657
+
6658
+ /** Options for {@link createMediaRecorder}. */
6659
+ export declare interface MediaRecordingOptions {
6660
+ /**
6661
+ * Container candidates, best first. Required: this engine has no opinion about
6662
+ * codecs — the audio and video wrappers own that list.
6663
+ */
6664
+ candidates: readonly string[];
6665
+ /** Wording for the thrown messages ("cannot record any supported *video* container"). */
6666
+ kind: MediaRecordingKind;
6667
+ /** Force a container, bypassing the negotiation. Throws when unsupported. */
6668
+ mimeType?: string;
6669
+ /** Target audio bitrate. */
6670
+ audioBitsPerSecond?: number;
6671
+ /** Target video bitrate. Ignored by the browser on an audio-only stream. */
6672
+ videoBitsPerSecond?: number;
6673
+ /**
6674
+ * Emit a chunk every N ms through `onChunk`, for streaming upload.
6675
+ *
6676
+ * Without it the whole recording is buffered in memory until `stop()`.
6677
+ */
6678
+ timesliceMs?: number;
6679
+ /** Receives each chunk when `timesliceMs` is set. Chunks are **not** independently playable. */
6680
+ onChunk?: (chunk: Blob) => void;
6681
+ /** Recorder-level failure (device unplugged mid-recording, encoder error). */
6682
+ onError?: (error: unknown) => void;
6683
+ }
6684
+
5433
6685
  /**
5434
6686
  * Memoize only the most recent call of `fn`, keyed by shallow-equal arguments.
5435
6687
  *
@@ -5513,6 +6765,23 @@ export declare interface MercatorPoint {
5513
6765
 
5514
6766
  export declare type Messages = Record<string, string>;
5515
6767
 
6768
+ /** Lifecycle of a microphone stream. */
6769
+ export declare type MicrophoneStatus = "idle" | "requesting" | "ready" | "error";
6770
+
6771
+ /**
6772
+ * The error for "the API is not here at all", which is a different question from
6773
+ * "the API rejected".
6774
+ *
6775
+ * `classifyMediaError` takes a thrown value; a missing `navigator.mediaDevices` never
6776
+ * threw one, and handing it `null` would come back `unknown` — the least actionable
6777
+ * kind there is. The two real causes are an insecure page (the fix is a URL) and an
6778
+ * engine that genuinely cannot capture (the fix is another browser), and telling them
6779
+ * apart is the whole point.
6780
+ *
6781
+ * @param device - Which device was being opened, for the message.
6782
+ */
6783
+ export declare function missingCaptureApiError(device?: MediaDeviceKindLabel): MediaAccessError;
6784
+
5516
6785
  /**
5517
6786
  * Portal-rendered modal dialog with backdrop, Esc handler, and slots for
5518
6787
  * header/body/footer. Locks body scroll while open.
@@ -5782,6 +7051,19 @@ export declare interface NavigationRailProps extends Omit<HTMLAttributes<HTMLEle
5782
7051
 
5783
7052
  export { NavLink }
5784
7053
 
7054
+ /**
7055
+ * Turn one raw detection into a {@link BarcodeScanResult}.
7056
+ *
7057
+ * An unrecognised `format` string becomes `"unknown"` rather than being passed through
7058
+ * as a lie about the union, and missing geometry becomes `null`/`[]` rather than
7059
+ * `undefined`, so a consumer never has to branch on three kinds of absence.
7060
+ *
7061
+ * @param raw - What the detector resolved with.
7062
+ * @param known - The formats considered valid. Defaults to the whole spec list.
7063
+ * @returns The normalised result.
7064
+ */
7065
+ export declare function normalizeBarcode(raw: DetectedBarcodeLike, known?: readonly BarcodeFormat[]): BarcodeScanResult;
7066
+
5785
7067
  /**
5786
7068
  * Normalize a longitude into the `[-180, 180]` range, wrapping values that
5787
7069
  * cross the antimeridian (e.g. `190` → `-170`).
@@ -6353,6 +7635,15 @@ export { Outlet }
6353
7635
  */
6354
7636
  declare type OverriddenDomProps = "children" | "title" | "onSelect";
6355
7637
 
7638
+ /** DOM attributes this component redefines. */
7639
+ declare type OverriddenDomProps_10 = "children";
7640
+
7641
+ /** DOM attributes this component redefines. */
7642
+ declare type OverriddenDomProps_11 = "children";
7643
+
7644
+ /** DOM attributes this component redefines. */
7645
+ declare type OverriddenDomProps_12 = "children" | "onChange";
7646
+
6356
7647
  /** DOM attributes this component redefines. */
6357
7648
  declare type OverriddenDomProps_2 = "children" | "onSubmit";
6358
7649
 
@@ -6360,22 +7651,22 @@ declare type OverriddenDomProps_2 = "children" | "onSubmit";
6360
7651
  declare type OverriddenDomProps_3 = "onSubmit" | "value" | "defaultValue" | "rows";
6361
7652
 
6362
7653
  /** DOM attributes this component redefines. */
6363
- declare type OverriddenDomProps_4 = "children" | "onSubmit";
6364
-
6365
- /** DOM attributes the composer redefines. */
6366
- declare type OverriddenDomProps_5 = "onSubmit" | "value" | "defaultValue" | "rows";
7654
+ declare type OverriddenDomProps_4 = "children";
6367
7655
 
6368
7656
  /** DOM attributes this component redefines. */
6369
- declare type OverriddenDomProps_6 = "children" | "onChange" | "defaultValue";
7657
+ declare type OverriddenDomProps_5 = "children" | "onError";
6370
7658
 
6371
7659
  /** DOM attributes this component redefines. */
6372
- declare type OverriddenDomProps_7 = "children";
7660
+ declare type OverriddenDomProps_6 = "children" | "onError";
6373
7661
 
6374
7662
  /** DOM attributes this component redefines. */
6375
- declare type OverriddenDomProps_8 = "children";
7663
+ declare type OverriddenDomProps_7 = "children" | "onSubmit";
7664
+
7665
+ /** DOM attributes the composer redefines. */
7666
+ declare type OverriddenDomProps_8 = "onSubmit" | "value" | "defaultValue" | "rows";
6376
7667
 
6377
7668
  /** DOM attributes this component redefines. */
6378
- declare type OverriddenDomProps_9 = "children" | "onChange";
7669
+ declare type OverriddenDomProps_9 = "children" | "onChange" | "defaultValue";
6379
7670
 
6380
7671
  /**
6381
7672
  * Page wrapper with header + (optional) toolbar + content + footer. Pairs
@@ -6451,6 +7742,221 @@ export declare function parseMarkdown(source: string): MarkdownBlock[];
6451
7742
  */
6452
7743
  export declare function parseResponse<TSchema extends z.ZodTypeAny>(schema: TSchema, raw: unknown, context: string): z.infer<TSchema>;
6453
7744
 
7745
+ /** Per-call knobs for {@link PasskeyClient.authenticate}. */
7746
+ export declare interface PasskeyAuthenticateInit extends PasskeyRegisterInit {
7747
+ /**
7748
+ * `"conditional"` is the autofill flow: no modal, the browser offers passkeys
7749
+ * inside a field marked `autocomplete="webauthn"`. Requires a `signal`, and
7750
+ * only one conditional request may be live per page.
7751
+ */
7752
+ mediation?: PasskeyMediation;
7753
+ }
7754
+
7755
+ /** What the client sends to the backend to finish authentication. */
7756
+ export declare interface PasskeyAuthenticationJSON {
7757
+ /** Base64url credential id — the server looks up the stored public key by it. */
7758
+ id: string;
7759
+ /** Same bytes as `id`. */
7760
+ rawId: string;
7761
+ type: "public-key";
7762
+ /** `"platform"` or `"cross-platform"`. */
7763
+ authenticatorAttachment: string | null;
7764
+ response: {
7765
+ /** Base64url client data. */
7766
+ clientDataJSON: string;
7767
+ /** Base64url authenticator data, carrying the signature counter. */
7768
+ authenticatorData: string;
7769
+ /** Base64url signature over `authenticatorData || sha256(clientDataJSON)`. */
7770
+ signature: string;
7771
+ /** Base64url user handle — present on discoverable credentials, else null. */
7772
+ userHandle: string | null;
7773
+ };
7774
+ /** Extension outputs. */
7775
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
7776
+ }
7777
+
7778
+ /** Capability probes shared by both passkey hooks. */
7779
+ export declare interface PasskeyCapabilities {
7780
+ /** WebAuthn exists in this browser. Known synchronously. */
7781
+ supported: boolean;
7782
+ /**
7783
+ * This device has a built-in authenticator. `null` until the async probe
7784
+ * settles — render nothing passkey-related while it is `null`.
7785
+ */
7786
+ platformAvailable: boolean | null;
7787
+ /** Autofill-driven sign-in is available. `null` until the probe settles. */
7788
+ conditionalAvailable: boolean | null;
7789
+ }
7790
+
7791
+ /** Which ceremony was running, so the message can name it. */
7792
+ export declare type PasskeyCeremony = "register" | "authenticate";
7793
+
7794
+ /** Framework-free WebAuthn client. Build one with {@link createPasskeyClient}. */
7795
+ export declare interface PasskeyClient {
7796
+ /** Run the registration ceremony and return the JSON your backend verifies. */
7797
+ register(options: PasskeyCreationOptionsJSON, init?: PasskeyRegisterInit): Promise<PasskeyRegistrationJSON>;
7798
+ /** Run the authentication ceremony and return the JSON your backend verifies. */
7799
+ authenticate(options: PasskeyRequestOptionsJSON, init?: PasskeyAuthenticateInit): Promise<PasskeyAuthenticationJSON>;
7800
+ /**
7801
+ * Whether this client can run a ceremony at all — the WebAuthn API exists, or a
7802
+ * `credentials` container was injected.
7803
+ */
7804
+ isSupported(): boolean;
7805
+ /** Whether this device has a built-in authenticator (Face ID, Hello, …). */
7806
+ isPlatformAuthenticatorAvailable(): Promise<boolean>;
7807
+ /** Whether autofill-driven (`"conditional"`) requests are available. */
7808
+ isConditionalMediationAvailable(): Promise<boolean>;
7809
+ }
7810
+
7811
+ /**
7812
+ * Server-issued registration options, in the base64url JSON shape every WebAuthn
7813
+ * backend speaks (`PublicKeyCredentialCreationOptionsJSON` in the spec).
7814
+ *
7815
+ * `challenge`, `user.id` and every `excludeCredentials[].id` are **base64url**
7816
+ * strings here and `ArrayBuffer`s in the DOM API. Converting them is the plumbing
7817
+ * this client owns.
7818
+ */
7819
+ export declare interface PasskeyCreationOptionsJSON {
7820
+ /** Base64url server challenge. Single-use; the server must remember it. */
7821
+ challenge: string;
7822
+ /** Relying party. `id` defaults to the client's `rpId`, then to the origin. */
7823
+ rp: {
7824
+ name: string;
7825
+ id?: string;
7826
+ };
7827
+ /** The account. `id` is base64url of an opaque, stable user handle. */
7828
+ user: {
7829
+ id: string;
7830
+ name: string;
7831
+ displayName: string;
7832
+ };
7833
+ /** Allowed COSE algorithms. Defaults to {@link DEFAULT_PUB_KEY_CRED_PARAMS}. */
7834
+ pubKeyCredParams?: {
7835
+ type: "public-key";
7836
+ alg: number;
7837
+ }[];
7838
+ /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */
7839
+ timeout?: number;
7840
+ /** Credentials this user already has, so the authenticator refuses a duplicate. */
7841
+ excludeCredentials?: {
7842
+ id: string;
7843
+ type: "public-key";
7844
+ transports?: string[];
7845
+ }[];
7846
+ /** Resident-key / user-verification / attachment requirements. */
7847
+ authenticatorSelection?: AuthenticatorSelectionCriteria;
7848
+ /** Attestation conveyance. Leave unset (`"none"`) unless you verify it. */
7849
+ attestation?: AttestationConveyancePreference;
7850
+ /** Client extension inputs (`credProps`, `largeBlob`, …). */
7851
+ extensions?: AuthenticationExtensionsClientInputs;
7852
+ }
7853
+
7854
+ /**
7855
+ * A passkey failure carrying a stable {@link PasskeyErrorKind} plus an English
7856
+ * message safe to show a user.
7857
+ *
7858
+ * A class rather than the plain `{ kind, message }` object the media classifier
7859
+ * returns, because these surface by rejecting a promise: an `Error` subclass keeps
7860
+ * stack traces, `instanceof` checks and logging intact, and `kind` is what code
7861
+ * branches on.
7862
+ */
7863
+ export declare class PasskeyError extends Error {
7864
+ /** Stable, branchable classification. */
7865
+ readonly kind: PasskeyErrorKind;
7866
+ /**
7867
+ * Build a classified passkey error.
7868
+ *
7869
+ * @param kind - The classification a UI branches on.
7870
+ * @param message - English, user-safe explanation.
7871
+ * @param cause - The original thrown value, when there was one.
7872
+ */
7873
+ constructor(kind: PasskeyErrorKind, message: string, cause?: unknown);
7874
+ }
7875
+
7876
+ /**
7877
+ * Classified reason a passkey ceremony did not produce a credential.
7878
+ *
7879
+ * The kinds group the raw `DOMException.name` values the way a UI has to branch
7880
+ * on them, which is *not* how the spec groups them:
7881
+ *
7882
+ * - `"cancelled"` covers `NotAllowedError`, which the browser raises both when
7883
+ * the user dismissed the sheet and when the ceremony timed out. They are
7884
+ * indistinguishable **by design** — telling a site "the user has no credential
7885
+ * for you" would leak account existence — so a UI must treat them as one thing.
7886
+ * - `"already-registered"` (`InvalidStateError`) is not really a failure: this
7887
+ * device already holds a credential for this user. The correct reaction is
7888
+ * "you are already set up on this device", never a red error.
7889
+ * - `"rp-mismatch"` (`SecurityError`) is the single most common integration bug:
7890
+ * `rp.id` must equal the page's domain or a registrable parent of it.
7891
+ */
7892
+ export declare type PasskeyErrorKind = "unsupported" | "insecure" | "cancelled" | "already-registered" | "not-supported" | "rp-mismatch" | "invalid-options" | "aborted" | "unknown";
7893
+
7894
+ /** How the browser should surface the authentication ceremony. */
7895
+ export declare type PasskeyMediation = "optional" | "conditional" | "required" | "silent";
7896
+
7897
+ /** Per-call knobs for {@link PasskeyClient.register}. */
7898
+ export declare interface PasskeyRegisterInit {
7899
+ /** Cancel the ceremony (closes the browser sheet). */
7900
+ signal?: AbortSignal;
7901
+ }
7902
+
7903
+ /** What the client sends to the backend to finish registration. */
7904
+ export declare interface PasskeyRegistrationJSON {
7905
+ /** Base64url credential id. */
7906
+ id: string;
7907
+ /** Same bytes as `id`; both are sent because servers differ on which they read. */
7908
+ rawId: string;
7909
+ type: "public-key";
7910
+ /** `"platform"` (this device) or `"cross-platform"` (a phone or key). */
7911
+ authenticatorAttachment: string | null;
7912
+ response: {
7913
+ /** Base64url client data — the server re-checks challenge, origin and type. */
7914
+ clientDataJSON: string;
7915
+ /** Base64url attestation object, holding the new public key. */
7916
+ attestationObject: string;
7917
+ /** Transports the authenticator advertises, when the browser exposes them. */
7918
+ transports?: string[];
7919
+ /** COSE algorithm of the new key, when the browser exposes it. */
7920
+ publicKeyAlgorithm?: number;
7921
+ /** Base64url SPKI public key, when the browser exposes it. */
7922
+ publicKey?: string;
7923
+ /** Base64url authenticator data, when the browser exposes it. */
7924
+ authenticatorData?: string;
7925
+ };
7926
+ /** Extension outputs — `credProps.rk` tells you whether it is discoverable. */
7927
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
7928
+ }
7929
+
7930
+ /** Server-issued authentication options, base64url JSON. */
7931
+ export declare interface PasskeyRequestOptionsJSON {
7932
+ /** Base64url server challenge. */
7933
+ challenge: string;
7934
+ /** Relying party id. Defaults to the client's `rpId`, then to the origin. */
7935
+ rpId?: string;
7936
+ /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */
7937
+ timeout?: number;
7938
+ /** Restrict to these credentials. **Omit it** for usernameless / autofill flows. */
7939
+ allowCredentials?: {
7940
+ id: string;
7941
+ type: "public-key";
7942
+ transports?: string[];
7943
+ }[];
7944
+ /** Whether the authenticator must verify the user (biometric / PIN). */
7945
+ userVerification?: UserVerificationRequirement;
7946
+ /** Client extension inputs. */
7947
+ extensions?: AuthenticationExtensionsClientInputs;
7948
+ }
7949
+
7950
+ /**
7951
+ * Where a passkey ceremony is.
7952
+ *
7953
+ * `"prompting"` and `"verifying"` are split because they need different copy:
7954
+ * while prompting, the browser sheet is up and the user must touch a sensor;
7955
+ * while verifying, your backend is checking the signature and the user should
7956
+ * just wait.
7957
+ */
7958
+ export declare type PasskeyStatus = "idle" | "prompting" | "verifying" | "success" | "error";
7959
+
6454
7960
  /**
6455
7961
  * Password field with toggle-visibility button and optional strength meter.
6456
7962
  *
@@ -6494,6 +8000,13 @@ export { Path }
6494
8000
  */
6495
8001
  export declare function pathLengthKm(points: readonly Coordinate[]): number;
6496
8002
 
8003
+ /** Raw PCM ready to be wrapped in a RIFF container. */
8004
+ export declare interface PcmAudio {
8005
+ /** One `Float32Array` per channel, samples in −1…1. */
8006
+ channels: readonly Float32Array[];
8007
+ sampleRate: number;
8008
+ }
8009
+
6497
8010
  /**
6498
8011
  * Extract a permission list from a JWT.
6499
8012
  *
@@ -6550,6 +8063,38 @@ export declare const PhoneInput: ForwardRefExoticComponent<Omit<InputProps, "val
6550
8063
  */
6551
8064
  export declare function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
6552
8065
 
8066
+ /**
8067
+ * First container in `preferred` the browser can actually produce, or `null`.
8068
+ *
8069
+ * **There is no MP3 or WAV here, and that is not an omission.** `MediaRecorder`
8070
+ * emits Opus (in WebM or Ogg) on Chromium and Firefox and AAC (in MP4) on Safari —
8071
+ * no engine implements an MP3 or WAV encoder for it. If a backend needs WAV,
8072
+ * {@link blobToWav} converts one client-side with no dependency; if it needs MP3,
8073
+ * transcode on the server. Shipping an MP3 encoder would mean a WASM build of the
8074
+ * order of 150 KB in every consumer's bundle to serve one format, which is the
8075
+ * trade this SDK does not make.
8076
+ *
8077
+ * @param preferred - Candidates, best first. Defaults to {@link AUDIO_MIME_CANDIDATES}.
8078
+ * @returns A supported MIME type, or `null` when none is.
8079
+ */
8080
+ export declare function pickAudioMimeType(preferred?: readonly string[]): string | null;
8081
+
8082
+ /**
8083
+ * First container in `preferred` the browser can actually produce, or `null`.
8084
+ *
8085
+ * @param preferred - Candidates, best first.
8086
+ * @returns A supported MIME type, or `null` when none is.
8087
+ */
8088
+ export declare function pickRecordingMimeType(preferred: readonly string[]): string | null;
8089
+
8090
+ /**
8091
+ * First video container in `preferred` the browser can actually produce, or `null`.
8092
+ *
8093
+ * @param preferred - Candidates, best first. Defaults to {@link VIDEO_MIME_CANDIDATES}.
8094
+ * @returns A supported MIME type, or `null` when none is.
8095
+ */
8096
+ export declare function pickVideoMimeType(preferred?: readonly string[]): string | null;
8097
+
6553
8098
  /**
6554
8099
  * One-time-password style input — N independent cells, paste support, auto-
6555
8100
  * advance on input, backspace flows back, arrow keys navigate.
@@ -6617,7 +8162,7 @@ export declare interface PlacedEvent {
6617
8162
  }
6618
8163
 
6619
8164
  /**
6620
- * Convenience wrapper around a shared {@link AudioPlayer}. Use this for
8165
+ * Convenience wrapper around a shared {@link AudioPlayerHandle}. Use this for
6621
8166
  * one-off notification sounds. For more complex flows (e.g. several
6622
8167
  * simultaneous channels), build a dedicated player with {@link createAudioPlayer}.
6623
8168
  */
@@ -6632,6 +8177,14 @@ export declare interface PlayAudioOptions {
6632
8177
  autoplay?: boolean;
6633
8178
  /** Stop the previous clip managed by this player. Default: false. */
6634
8179
  stopPrevious?: boolean;
8180
+ /**
8181
+ * Output device to play on, from `useMediaDevices().audioOutputs`.
8182
+ *
8183
+ * Ignored where the browser has no output routing (everything but Chromium) —
8184
+ * the clip still plays, on the system default. Useful for a chime that must land
8185
+ * on a headset while the call audio stays on the speakers.
8186
+ */
8187
+ sinkId?: string;
6635
8188
  /** Fired when playback ends naturally. */
6636
8189
  onEnded?: () => void;
6637
8190
  /** Fired on playback error. */
@@ -6733,6 +8286,23 @@ export declare interface PostHogLike {
6733
8286
  reset?: () => void;
6734
8287
  }
6735
8288
 
8289
+ /** A model whose cached size should appear in the report. */
8290
+ export declare interface ProfiledModel {
8291
+ /** Label for the report row, e.g. `"detector"`. */
8292
+ name: string;
8293
+ /** Cache Storage bucket holding the response, e.g. `"app-models"`. */
8294
+ cacheName: string;
8295
+ /** Request URL the model was cached under. */
8296
+ url: string;
8297
+ }
8298
+
8299
+ /** A model's size as found in the cache. */
8300
+ export declare interface ProfiledModelSize {
8301
+ name: string;
8302
+ /** Size in bytes, or `null` when uncached or the size is unreported. */
8303
+ bytes: number | null;
8304
+ }
8305
+
6736
8306
  /**
6737
8307
  * Linear progress bar with determinate / indeterminate modes.
6738
8308
  *
@@ -7050,6 +8620,22 @@ export declare interface RatingStarsProps {
7050
8620
  */
7051
8621
  export declare function readableForeground(background: string, light?: string, dark?: string): string;
7052
8622
 
8623
+ /**
8624
+ * Sample the device capabilities the browser reports.
8625
+ *
8626
+ * Safe to call during SSR: without a `navigator` every field is `null`.
8627
+ *
8628
+ * @returns The profile, with `null` for anything this platform withholds.
8629
+ *
8630
+ * @example
8631
+ * ```typescript
8632
+ * const device = readDeviceProfile();
8633
+ * console.log(device.hardwareConcurrency); // 8
8634
+ * console.log(device.deviceMemoryGb); // 8 on Chromium, null on Safari
8635
+ * ```
8636
+ */
8637
+ export declare function readDeviceProfile(): DeviceProfile;
8638
+
7053
8639
  /**
7054
8640
  * Read a token's computed value from an element (default: `<html>`).
7055
8641
  *
@@ -7320,6 +8906,131 @@ export declare type ResponsiveValue<T> = T | {
7320
8906
  desktop?: T;
7321
8907
  };
7322
8908
 
8909
+ /** A resumable upload in progress. Build one with {@link createResumableUpload}. */
8910
+ export declare interface ResumableUpload {
8911
+ /**
8912
+ * Create (or re-attach to) the upload and push chunks until it is complete.
8913
+ *
8914
+ * Resolves `null` when the run stopped because of `pause()` or `abort()` —
8915
+ * neither is a failure. Rejects with a `TempestApiError` when the server
8916
+ * refused and the retries ran out.
8917
+ */
8918
+ start(): Promise<ResumableUploadResult | null>;
8919
+ /** Stop after the in-flight chunk is dropped, keeping the resume point. */
8920
+ pause(): void;
8921
+ /** Continue from the server's offset. Same resolution contract as `start`. */
8922
+ resume(): Promise<ResumableUploadResult | null>;
8923
+ /**
8924
+ * Stop for good.
8925
+ *
8926
+ * @param options - `discard: true` also sends `DELETE` (tus termination) and
8927
+ * forgets the persisted record, so the next `start()` uploads from zero.
8928
+ */
8929
+ abort(options?: {
8930
+ discard?: boolean;
8931
+ }): Promise<void>;
8932
+ /** Current state. */
8933
+ readonly state: ResumableUploadState;
8934
+ /** Bytes the server has confirmed. */
8935
+ readonly offset: number;
8936
+ /** The upload URL, once creation succeeded. */
8937
+ readonly url: string | null;
8938
+ /** The resume key in use. */
8939
+ readonly key: string;
8940
+ }
8941
+
8942
+ /** Options for {@link createResumableUpload}. */
8943
+ export declare interface ResumableUploadOptions {
8944
+ /** tus creation endpoint, e.g. `"/api/uploads"`. */
8945
+ endpoint: string;
8946
+ /** The bytes to upload. A `File` also supplies the default resume key. */
8947
+ file: Blob | File;
8948
+ /** Bytes per `PATCH`. Default {@link DEFAULT_CHUNK_SIZE}. */
8949
+ chunkSize?: number;
8950
+ /** Sent as `Upload-Metadata` (base64-encoded values), e.g. `{ filename }`. */
8951
+ metadata?: Record<string, string>;
8952
+ /** Extra headers on every request. */
8953
+ headers?: Record<string, string>;
8954
+ /** Returns the current bearer token, read before each request. */
8955
+ getToken?: () => string | null | undefined;
8956
+ /** Send cookies. Default `false`. */
8957
+ withCredentials?: boolean;
8958
+ /**
8959
+ * Resume key. Defaults to a fingerprint of endpoint + file name/size/mtime, so
8960
+ * picking the same file after a reload resumes instead of restarting.
8961
+ */
8962
+ key?: string;
8963
+ /**
8964
+ * Where to persist resume state. Defaults to `localStorage`. Pass `null` to
8965
+ * disable persistence — resume then only survives a network blip, not a reload.
8966
+ */
8967
+ storage?: ResumableUploadStorage | null;
8968
+ /** Backoff for a failed chunk. Forwarded to `retry`. Default 5 attempts. */
8969
+ retry?: RetryOptions;
8970
+ /** Called on every upload-progress tick and after every confirmed chunk. */
8971
+ onProgress?: (progress: ResumableUploadProgress) => void;
8972
+ /** Called whenever {@link ResumableUpload.state} changes. */
8973
+ onStateChange?: (state: ResumableUploadState) => void;
8974
+ }
8975
+
8976
+ /** Byte-level progress for a resumable upload. */
8977
+ export declare interface ResumableUploadProgress {
8978
+ /** Bytes the server holds, including anything a resume skipped. */
8979
+ loaded: number;
8980
+ /** Total size of the file. */
8981
+ total: number;
8982
+ /** `loaded / total`, between 0 and 1. */
8983
+ fraction: number;
8984
+ /** Bytes already on the server when this run started. `0` on a fresh upload. */
8985
+ resumedFrom: number;
8986
+ }
8987
+
8988
+ /** What has to survive a page reload for a resume to be possible. */
8989
+ export declare interface ResumableUploadRecord {
8990
+ /** Upload URL the creation POST returned, absolute. */
8991
+ url: string;
8992
+ /** Last offset the server confirmed. */
8993
+ offset: number;
8994
+ /** File size, so a different file under the same key is not resumed into. */
8995
+ size: number;
8996
+ /** Idempotency key of the creation request, reused if creation is retried. */
8997
+ idempotencyKey: string;
8998
+ /** Epoch ms of the last write, so an app can sweep stale records. */
8999
+ updatedAt: number;
9000
+ }
9001
+
9002
+ /** What a finished upload resolves with. */
9003
+ export declare interface ResumableUploadResult {
9004
+ /** The tus upload URL — hand this to your API to link the stored file. */
9005
+ url: string;
9006
+ /** Total bytes uploaded. */
9007
+ size: number;
9008
+ }
9009
+
9010
+ /**
9011
+ * Where a resumable upload is.
9012
+ *
9013
+ * `"paused"` and `"aborted"` are both "not running", but only `"paused"` keeps the
9014
+ * persisted offset — `abort({ discard: true })` throws it away.
9015
+ */
9016
+ export declare type ResumableUploadState = "idle" | "creating" | "uploading" | "paused" | "done" | "error" | "aborted";
9017
+
9018
+ /**
9019
+ * Persistence for resume state. Sync or async — both are awaited.
9020
+ *
9021
+ * Implement it over anything: the default is `localStorage`, and
9022
+ * `createOfflineStore` from `@/offline` slots in when you already have a Dexie
9023
+ * database open.
9024
+ */
9025
+ export declare interface ResumableUploadStorage {
9026
+ /** Read the record for `key`, or `null`. */
9027
+ get(key: string): Promise<ResumableUploadRecord | null> | ResumableUploadRecord | null;
9028
+ /** Write the record for `key`. */
9029
+ set(key: string, record: ResumableUploadRecord): Promise<void> | void;
9030
+ /** Forget the record for `key`. */
9031
+ delete(key: string): Promise<void> | void;
9032
+ }
9033
+
7323
9034
  /**
7324
9035
  * Run `factory()` with exponential backoff. Each attempt awaits an
7325
9036
  * increasing delay capped at `maxDelay`. Throws the last error if every
@@ -7594,6 +9305,9 @@ export declare interface SchedulerProps extends Omit<HTMLAttributes<HTMLDivEleme
7594
9305
  now?: Date;
7595
9306
  }
7596
9307
 
9308
+ /** Lifecycle of a screen share. */
9309
+ export declare type ScreenCaptureStatus = "idle" | "requesting" | "sharing" | "error";
9310
+
7597
9311
  /**
7598
9312
  * A styled scroll container that overflows on the chosen axis and renders a
7599
9313
  * thin custom scrollbar (WebKit) while staying fully functional in browsers
@@ -7765,6 +9479,29 @@ export declare interface SequentialScaleOptions {
7765
9479
  ordinal?: boolean;
7766
9480
  }
7767
9481
 
9482
+ /**
9483
+ * Send an element's audio to a specific output device.
9484
+ *
9485
+ * The `sinkId` comes from `useMediaDevices().audioOutputs` — and, like every device
9486
+ * label, that list is anonymous until a capture permission has been granted, so an
9487
+ * output picker realistically only works after the microphone has been allowed once.
9488
+ *
9489
+ * Returns `false` instead of throwing when the browser has no `setSinkId`, because
9490
+ * "this engine cannot route audio" is the common case and not an error the caller can
9491
+ * act on: the sound still plays, on the system default device. A rejected
9492
+ * `setSinkId` — a device that was unplugged between enumeration and playback is the
9493
+ * usual cause — also resolves `false`, and playback continues on the default.
9494
+ *
9495
+ * @param element - The `<audio>` or `<video>` element to route.
9496
+ * @param sinkId - Device id, or `""` for the system default.
9497
+ * @returns `true` when the route was applied.
9498
+ *
9499
+ * @example
9500
+ * const ok = await setAudioOutput(audioRef.current, selectedSpeakerId);
9501
+ * if (!ok) toast("Este navegador não permite escolher a saída de som.");
9502
+ */
9503
+ export declare function setAudioOutput(element: HTMLMediaElement | null, sinkId: string): Promise<boolean>;
9504
+
7768
9505
  /**
7769
9506
  * Wrap the Web Share API with a uniform result object. Falls through to
7770
9507
  * `unsupported: true` when the browser lacks `navigator.share`, leaving the
@@ -8124,6 +9861,69 @@ export declare interface SparklineProps extends Omit<HTMLAttributes<HTMLSpanElem
8124
9861
 
8125
9862
  export declare type SparklineVariant = "line" | "area" | "bar";
8126
9863
 
9864
+ /** One reading of what was heard. */
9865
+ export declare interface SpeechAlternativeLike {
9866
+ transcript: string;
9867
+ confidence?: number;
9868
+ }
9869
+
9870
+ /** A classified speech error with a human-readable, English message. */
9871
+ export declare interface SpeechError {
9872
+ kind: SpeechErrorKind;
9873
+ message: string;
9874
+ }
9875
+
9876
+ /** Classified reason recognition stopped or never started. */
9877
+ export declare type SpeechErrorKind = "unsupported" | "not-allowed" | "no-speech" | "audio-capture" | "network" | "aborted" | "language-not-supported" | "unknown";
9878
+
9879
+ /** The `error` event, reduced to what this hook reads. */
9880
+ export declare interface SpeechRecognitionErrorEventLike {
9881
+ error: string;
9882
+ message?: string;
9883
+ }
9884
+
9885
+ /** The `result` event, reduced to what this hook reads. */
9886
+ export declare interface SpeechRecognitionEventLike {
9887
+ /** Index of the first result that changed — everything before it is settled. */
9888
+ resultIndex: number;
9889
+ results: SpeechResultListLike;
9890
+ }
9891
+
9892
+ /**
9893
+ * The slice of the Web Speech `SpeechRecognition` object this SDK uses.
9894
+ *
9895
+ * Declared here rather than imported: TypeScript's DOM lib ships the *event* types but
9896
+ * not the constructor, because the API is still prefixed in Chromium and absent in
9897
+ * Firefox. Exported so a test — or a consumer wrapping a different engine — can hand in
9898
+ * something else.
9899
+ */
9900
+ export declare interface SpeechRecognitionLike {
9901
+ lang: string;
9902
+ continuous: boolean;
9903
+ interimResults: boolean;
9904
+ maxAlternatives: number;
9905
+ start: () => void;
9906
+ stop: () => void;
9907
+ abort: () => void;
9908
+ onresult: ((event: SpeechRecognitionEventLike) => void) | null;
9909
+ onerror: ((event: SpeechRecognitionErrorEventLike) => void) | null;
9910
+ onend: (() => void) | null;
9911
+ onstart: (() => void) | null;
9912
+ }
9913
+
9914
+ /** One recognised phrase, settled (`isFinal`) or still being revised. */
9915
+ export declare interface SpeechResultLike {
9916
+ isFinal: boolean;
9917
+ length: number;
9918
+ [index: number]: SpeechAlternativeLike | undefined;
9919
+ }
9920
+
9921
+ /** The growing list of phrases in a session. */
9922
+ export declare interface SpeechResultListLike {
9923
+ length: number;
9924
+ [index: number]: SpeechResultLike | undefined;
9925
+ }
9926
+
8127
9927
  /**
8128
9928
  * Loading spinner with preset sizes (xs..xl). Provide `label` for screen
8129
9929
  * readers, `caption` for a visible message, and `overlay` to center it inside a
@@ -9235,7 +11035,7 @@ export declare interface TransferItem {
9235
11035
  data?: Record<string, unknown>;
9236
11036
  }
9237
11037
 
9238
- export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
11038
+ export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_9> {
9239
11039
  /** The whole catalogue. Both panes are derived from it. */
9240
11040
  items: readonly TransferItem[];
9241
11041
  /** Ids on the target side. Controlled. */
@@ -9393,6 +11193,9 @@ export declare interface TruncateTextProps extends HTMLAttributes<HTMLDivElement
9393
11193
  */
9394
11194
  export declare function turnTime(timestamp: number, locale?: "pt-BR" | "en"): string;
9395
11195
 
11196
+ /** The tus protocol version this client speaks. */
11197
+ export declare const TUS_VERSION = "1.0.0";
11198
+
9396
11199
  /** Sentence for the typing indicator, or `null` when nobody is typing. */
9397
11200
  export declare function typingLabel(names: readonly string[], locale?: "pt-BR" | "en"): string | null;
9398
11201
 
@@ -9470,6 +11273,20 @@ export declare interface UpdateVariables {
9470
11273
  data: unknown;
9471
11274
  }
9472
11275
 
11276
+ /**
11277
+ * A stable-enough identity for a file, used as the default resume key.
11278
+ *
11279
+ * Name + size + last-modified is what the tus reference clients fingerprint on:
11280
+ * it is cheap (hashing the bytes of a 400 MB recording is not) and it changes
11281
+ * whenever the file does, which is the property that matters — resuming into the
11282
+ * wrong file would corrupt it silently.
11283
+ *
11284
+ * @param endpoint - Creation endpoint, so the same file to two servers is two uploads.
11285
+ * @param file - The blob or file being uploaded.
11286
+ * @returns A key safe to use in `localStorage`.
11287
+ */
11288
+ export declare function uploadFingerprint(endpoint: string, file: Blob | File): string;
11289
+
9473
11290
  export declare interface UploadProgressEvent {
9474
11291
  /** Bytes already uploaded. */
9475
11292
  loaded: number;
@@ -9561,6 +11378,38 @@ export declare function urlBase64ToUint8Array(base64String: string): Uint8Array<
9561
11378
  */
9562
11379
  export declare function useAccessControl(): AccessControl | null;
9563
11380
 
11381
+ /**
11382
+ * Announce transient messages to screen readers through one shared live region
11383
+ * pair.
11384
+ *
11385
+ * Reach for this when something happened that a sighted user can see and a screen
11386
+ * reader user cannot: a filter narrowed a list, a row saved, a copy succeeded, an
11387
+ * upload failed. It is **not** for content that is already on screen inside a
11388
+ * region with a role — a status pill, a toast that renders as `role="status"`,
11389
+ * a form error tied to its input — announcing those again reads them twice.
11390
+ *
11391
+ * !!! warning "Never wrap streaming text in a live region"
11392
+ * A live region over text that grows token by token makes the reader start the
11393
+ * whole answer again on every token. Announce the **edges** instead — "gerando
11394
+ * resposta" and "resposta concluída" — and leave the transcript in a plain
11395
+ * `role="log"` the user reads at their own pace. `AIChat` does exactly that.
11396
+ *
11397
+ * Mounting the hook creates the regions even before the first message. That is not
11398
+ * tidiness: a live region inserted into the DOM in the same frame as its first
11399
+ * content routinely loses that announcement, because the assistive technology has
11400
+ * to have registered the region before it can notice a change inside it.
11401
+ *
11402
+ * @returns A stable `announce(message, politeness?)` function.
11403
+ *
11404
+ * @example
11405
+ * const announce = useAnnounce();
11406
+ *
11407
+ * function onFilter(rows: Row[]) {
11408
+ * announce(`${rows.length} resultados`);
11409
+ * }
11410
+ */
11411
+ export declare function useAnnounce(): (message: string, politeness?: AnnouncePoliteness) => void;
11412
+
9564
11413
  /**
9565
11414
  * Run an async function and track its `idle/pending/success/error` state.
9566
11415
  *
@@ -9596,11 +11445,73 @@ export declare interface UseAsyncResult<T> {
9596
11445
  * fine and the value is non-null from the first render.
9597
11446
  *
9598
11447
  * Hook-managed audio player. Each component instance gets its own
9599
- * {@link AudioPlayer}, so unmounting cleanly stops playback. Useful for
11448
+ * {@link AudioPlayerHandle}, so unmounting cleanly stops playback. Useful for
9600
11449
  * notification chimes, UI feedback sounds, and per-component soundtracks.
9601
11450
  */
9602
11451
  export declare function useAudio(): UseAudioResult;
9603
11452
 
11453
+ /**
11454
+ * Record the given stream, with a clock, a level meter and a state machine.
11455
+ *
11456
+ * Pass the stream from {@link useMicrophone}; the hook stays `ready: false` until
11457
+ * there is one, so a page can render the whole recorder UI before permission is
11458
+ * granted and simply have it disabled.
11459
+ *
11460
+ * The clock and the level are published on an interval (`tickMs`, default 100 ms)
11461
+ * rather than per animation frame. A hook that set state 60 times a second would
11462
+ * re-render everything the recorder is inside; 10 Hz is smooth enough for a timer and
11463
+ * a meter, and the underlying `createLevelMeter` is still available for anyone who
11464
+ * wants a frame-accurate bar written straight to the DOM.
11465
+ *
11466
+ * @param stream - The stream to record, or `null` while permission is pending.
11467
+ * @param options - See {@link UseAudioRecorderOptions}.
11468
+ *
11469
+ * @example
11470
+ * const mic = useMicrophone();
11471
+ * const rec = useAudioRecorder(mic.stream, { maxDurationMs: 120_000 });
11472
+ * <button disabled={!rec.ready} onClick={rec.start}>Gravar</button>
11473
+ */
11474
+ export declare function useAudioRecorder(stream: MediaStream | null, options?: UseAudioRecorderOptions): UseAudioRecorderResult;
11475
+
11476
+ /** Options for {@link useAudioRecorder}. */
11477
+ export declare interface UseAudioRecorderOptions extends AudioRecorderOptions {
11478
+ /**
11479
+ * Stop automatically after this many milliseconds.
11480
+ *
11481
+ * Worth setting on anything user-facing: a recording left running by accident is
11482
+ * a memory buffer that grows until the tab dies.
11483
+ */
11484
+ maxDurationMs?: number;
11485
+ /** Called once the recording is assembled, whether by `stop()` or `maxDurationMs`. */
11486
+ onRecorded?: (recording: AudioRecording) => void;
11487
+ /** How often the clock and the level are published, in ms. Default 100. */
11488
+ tickMs?: number;
11489
+ /** Skip the level meter — it costs an `AudioContext`. Default `false`. */
11490
+ disableLevelMeter?: boolean;
11491
+ }
11492
+
11493
+ /** Value returned by {@link useAudioRecorder}. */
11494
+ export declare interface UseAudioRecorderResult {
11495
+ status: AudioRecorderStatus;
11496
+ /** Recorded length so far, excluding paused time. */
11497
+ durationMs: number;
11498
+ /** Loudness 0–1, or `0` when the meter is off or nothing is recording. */
11499
+ level: number;
11500
+ /** The finished recording, or `null` before the first `stop()`. */
11501
+ recording: AudioRecording | null;
11502
+ /** Recorder-level error (encoder failure, device pulled mid-recording). */
11503
+ error: unknown;
11504
+ /** `false` when there is no stream yet, or the browser cannot record. */
11505
+ ready: boolean;
11506
+ start: () => void;
11507
+ pause: () => void;
11508
+ resume: () => void;
11509
+ /** Stop and resolve with the recording. Also published on `recording`. */
11510
+ stop: () => Promise<AudioRecording | null>;
11511
+ /** Stop and throw the audio away. */
11512
+ cancel: () => void;
11513
+ }
11514
+
9604
11515
  export declare interface UseAudioResult {
9605
11516
  /** Play `src` on the hook's private player. */
9606
11517
  play: (src: string, options?: PlayAudioOptions) => Promise<void>;
@@ -9613,6 +11524,105 @@ export declare interface UseAudioResult {
9613
11524
  unlocked: boolean;
9614
11525
  }
9615
11526
 
11527
+ /**
11528
+ * Read barcodes and QR codes from the camera.
11529
+ *
11530
+ * The camera and its classified errors come from `useCameraStream`, so this hook is
11531
+ * only the decoding half: it drives a `BarcodeDetector` over the preview on an
11532
+ * interval, suppresses the same value repeating, and exposes the torch.
11533
+ *
11534
+ * **Mounting this opens the camera.** It inherits that from `useCameraStream`, which
11535
+ * acquires on mount — so mount it *after* the user asks to scan (a button that reveals
11536
+ * the scanner), never on a page that merely contains one. A permission prompt nobody
11537
+ * provoked is the most reliable way to earn a permanent block, after which
11538
+ * `getUserMedia` rejects without ever prompting again.
11539
+ *
11540
+ * `supported` deserves a branch in the UI, not an assertion: `BarcodeDetector` is
11541
+ * Chromium-only and missing on Windows/Linux desktop, Firefox and everything on iOS.
11542
+ * Inject a `detector` to cover those, or tell the user to type the code.
11543
+ *
11544
+ * @param options - See {@link UseBarcodeScannerOptions}.
11545
+ * @returns The camera plumbing plus the scan state.
11546
+ *
11547
+ * @example
11548
+ * const scanner = useBarcodeScanner({
11549
+ * formats: ["ean_13"],
11550
+ * onScan: ({ rawValue }) => addToCart(rawValue),
11551
+ * });
11552
+ * return <video ref={scanner.videoRef} muted playsInline />;
11553
+ */
11554
+ export declare function useBarcodeScanner(options?: UseBarcodeScannerOptions): UseBarcodeScannerResult;
11555
+
11556
+ /** Options for {@link useBarcodeScanner}. */
11557
+ export declare interface UseBarcodeScannerOptions {
11558
+ /** Symbologies to look for. Defaults to {@link DEFAULT_BARCODE_FORMATS}. */
11559
+ formats?: readonly BarcodeFormat[];
11560
+ /** Called for every accepted read — that is, after repeat suppression. */
11561
+ onScan?: (result: BarcodeScanResult) => void;
11562
+ /**
11563
+ * How often a frame is examined, in ms. Default 200.
11564
+ *
11565
+ * Not `requestAnimationFrame`: decoding is 10–40 ms of main-thread work on a
11566
+ * phone, so running it per frame competes with the preview it is reading from and
11567
+ * makes the video stutter. Five looks per second is faster than a human can aim.
11568
+ */
11569
+ intervalMs?: number;
11570
+ /**
11571
+ * Ignore the **same** value again for this long, in ms. Default 2500.
11572
+ *
11573
+ * A symbol stays in frame for as long as the user holds the camera there, so a
11574
+ * scanner without this fires the same code five times a second — which, wired to
11575
+ * "add item to cart", is a bug the user pays for. A *different* value is never
11576
+ * suppressed.
11577
+ */
11578
+ repeatDelayMs?: number;
11579
+ /** Stop looking without releasing the camera — a confirmation sheet is open. */
11580
+ paused?: boolean;
11581
+ /**
11582
+ * A decoder to use instead of the native one.
11583
+ *
11584
+ * The way to support Safari and Firefox: hand in a polyfill and everything else
11585
+ * here works unchanged. See {@link isBarcodeDetectionSupported} for why the SDK
11586
+ * does not bundle one.
11587
+ */
11588
+ detector?: BarcodeDetectorLike;
11589
+ /** Camera constraints, forwarded to `useCameraStream`. Defaults to the rear camera. */
11590
+ constraints?: MediaStreamConstraints;
11591
+ /**
11592
+ * A frame the engine refused to decode.
11593
+ *
11594
+ * Not "nothing found" — that resolves to an empty list and is the normal case.
11595
+ * This is the engine itself failing, which the loop survives because it is
11596
+ * usually transient (a frame arriving between two resolutions).
11597
+ */
11598
+ onError?: (error: unknown) => void;
11599
+ }
11600
+
11601
+ /** Value returned by {@link useBarcodeScanner}. */
11602
+ export declare interface UseBarcodeScannerResult {
11603
+ /** Attach to a `<video ref={…} muted playsInline />`. */
11604
+ videoRef: RefObject<HTMLVideoElement | null>;
11605
+ /** Camera lifecycle. `"ready"` means the preview is running. */
11606
+ status: CameraStreamStatus;
11607
+ /** Classified camera error, or `null`. */
11608
+ error: CameraStreamError | null;
11609
+ /** `false` when there is no decoder — no native API and none injected. */
11610
+ supported: boolean;
11611
+ /**
11612
+ * Formats actually in use: the requested ones intersected with what the engine
11613
+ * reports. Empty while the probe is in flight, or when nothing matched.
11614
+ */
11615
+ formats: readonly BarcodeFormat[];
11616
+ /** Whether the detect loop is running right now. */
11617
+ scanning: boolean;
11618
+ /** The most recent accepted read, or `null`. */
11619
+ result: BarcodeScanResult | null;
11620
+ /** The LED torch of this camera, when it has one. */
11621
+ torch: UseTorchResult;
11622
+ /** Re-open the camera after an error (the user changed the permission). */
11623
+ retry: () => void;
11624
+ }
11625
+
9616
11626
  /**
9617
11627
  * React hook for the PWA install prompt. Captures the `beforeinstallprompt`
9618
11628
  * event so you can defer the install UI to a moment that fits your UX.
@@ -10236,6 +12246,93 @@ export declare interface UseMapResult<K, V> {
10236
12246
 
10237
12247
  export { useMatch }
10238
12248
 
12249
+ /**
12250
+ * List capture and playback devices, and keep the list fresh.
12251
+ *
12252
+ * Two things about `enumerateDevices` that decide how a picker must be built:
12253
+ *
12254
+ * 1. **Labels are gated behind permission.** Before the user grants a capture
12255
+ * permission, every `label` is `""` — the list length and ids are real, the names
12256
+ * are not. A device picker rendered at that point is a column of blanks, so
12257
+ * `labelsAvailable` is exposed to gate it. Ask for the microphone first, then
12258
+ * show the picker.
12259
+ * 2. **The list changes while the page is open.** Plugging in a headset mid-recording
12260
+ * is the normal case, not an edge case, so the hook subscribes to `devicechange`
12261
+ * instead of enumerating once on mount.
12262
+ *
12263
+ * `audioOutputs` is empty on browsers with no output routing at all (Safari and
12264
+ * Firefox do not implement `setSinkId`); an empty array there means "you cannot
12265
+ * offer this choice", not "no speakers".
12266
+ *
12267
+ * @returns The device lists, whether labels are filled in, and a `refresh()`.
12268
+ *
12269
+ * @example
12270
+ * const { audioInputs, labelsAvailable } = useMediaDevices();
12271
+ * // ...after the mic permission is granted:
12272
+ * {labelsAvailable && <Select options={audioInputs.map((d) => ({ value: d.deviceId, label: d.label }))} />}
12273
+ */
12274
+ export declare function useMediaDevices(): UseMediaDevicesResult;
12275
+
12276
+ /** Value returned by {@link useMediaDevices}. */
12277
+ export declare interface UseMediaDevicesResult {
12278
+ /** Every device, in the order the browser listed them. */
12279
+ devices: MediaDeviceOption[];
12280
+ /** Microphones and other audio sources. */
12281
+ audioInputs: MediaDeviceOption[];
12282
+ /** Speakers and headsets. Empty on browsers with no output routing (Safari, Firefox). */
12283
+ audioOutputs: MediaDeviceOption[];
12284
+ /** Cameras. */
12285
+ videoInputs: MediaDeviceOption[];
12286
+ /**
12287
+ * Whether labels are filled in.
12288
+ *
12289
+ * `false` means the list is real but anonymous — render a picker only after a
12290
+ * capture permission has been granted, or the user sees "" repeated N times.
12291
+ */
12292
+ labelsAvailable: boolean;
12293
+ /** `enumerateDevices` is unavailable in this browser. */
12294
+ supported: boolean;
12295
+ /** Re-enumerate. The hook already does this on `devicechange`. */
12296
+ refresh: () => void;
12297
+ }
12298
+
12299
+ /**
12300
+ * Read a capture permission **without triggering the prompt**.
12301
+ *
12302
+ * This is the piece that makes a good permission flow possible. `getUserMedia` is
12303
+ * the only way to *get* a device, but calling it is also the only way to *ask*, and
12304
+ * a prompt fired on page load — before the user has pressed anything — is the
12305
+ * single most reliable way to earn a permanent "Block". Reading the state first
12306
+ * lets a page explain why it needs the microphone, and only then ask.
12307
+ *
12308
+ * It also separates "never asked" from "denied", which matters because they need
12309
+ * opposite UI: `"prompt"` gets a button, `"denied"` gets instructions for the
12310
+ * browser's site settings, since no amount of clicking will re-prompt.
12311
+ *
12312
+ * Safari does not expose `microphone` to the Permissions API and throws on the
12313
+ * query, which surfaces as `state: "unknown"` and `supported: false` — treat that
12314
+ * as "you will have to ask to find out", not as an error.
12315
+ *
12316
+ * @param name - Which permission to observe.
12317
+ * @returns The live state, whether it could be read, and a manual `refresh()`.
12318
+ *
12319
+ * @example
12320
+ * const { state } = useMediaPermission("microphone");
12321
+ * if (state === "denied") return <p>Libere o microfone nas configurações do site.</p>;
12322
+ * return <button onClick={start}>Gravar</button>;
12323
+ */
12324
+ export declare function useMediaPermission(name: MediaPermissionName): UseMediaPermissionResult;
12325
+
12326
+ /** Value returned by {@link useMediaPermission}. */
12327
+ export declare interface UseMediaPermissionResult {
12328
+ /** Current state. Updates live when the user changes it in browser settings. */
12329
+ state: MediaPermissionState;
12330
+ /** Whether the Permissions API could answer at all. */
12331
+ supported: boolean;
12332
+ /** Re-read the permission. Rarely needed — the hook subscribes to changes. */
12333
+ refresh: () => void;
12334
+ }
12335
+
10239
12336
  /**
10240
12337
  * Subscribe to a CSS media query and re-render on match changes.
10241
12338
  *
@@ -10244,6 +12341,65 @@ export { useMatch }
10244
12341
  */
10245
12342
  export declare function useMediaQuery(query: string): boolean;
10246
12343
 
12344
+ /**
12345
+ * Acquire a microphone `MediaStream`, classified errors included, and release it
12346
+ * properly.
12347
+ *
12348
+ * Releasing matters more than it looks. Every track has to be stopped by hand:
12349
+ * dropping the last reference to a `MediaStream` does **not** turn off the
12350
+ * microphone, so the browser keeps showing its recording indicator and the OS keeps
12351
+ * the device busy — which then makes the *next* `getUserMedia` fail with
12352
+ * `NotReadableError` in another tab. The hook stops tracks on `stop()`, on unmount,
12353
+ * and before re-opening.
12354
+ *
12355
+ * @param options - See {@link UseMicrophoneOptions}.
12356
+ * @returns The stream, its status, a classified error, and `start`/`stop`.
12357
+ *
12358
+ * @example
12359
+ * const mic = useMicrophone();
12360
+ * const recorder = useAudioRecorder(mic.stream);
12361
+ * <button onClick={mic.start}>Liberar microfone</button>
12362
+ */
12363
+ export declare function useMicrophone(options?: UseMicrophoneOptions): UseMicrophoneResult;
12364
+
12365
+ /** Options for {@link useMicrophone}. */
12366
+ export declare interface UseMicrophoneOptions {
12367
+ /**
12368
+ * Open the stream on mount instead of waiting for `start()`. Default `false`.
12369
+ *
12370
+ * Left off on purpose. Opening on mount means prompting on mount, and a
12371
+ * permission prompt the user did not provoke is the most reliable way to earn a
12372
+ * permanent "Block" — after which `getUserMedia` rejects without ever prompting
12373
+ * again. Wire `start()` to the button that needs the microphone.
12374
+ */
12375
+ autoStart?: boolean;
12376
+ /** Specific microphone, from `useMediaDevices().audioInputs`. */
12377
+ deviceId?: string;
12378
+ /**
12379
+ * Browser voice processing. All three default to `true`, which is what speech
12380
+ * wants; turn them off for music, where a gate chewing on a decaying note is
12381
+ * worse than the room noise it removes.
12382
+ */
12383
+ echoCancellation?: boolean;
12384
+ noiseSuppression?: boolean;
12385
+ autoGainControl?: boolean;
12386
+ /** Escape hatch: full constraints, replacing everything above. */
12387
+ constraints?: MediaStreamConstraints;
12388
+ }
12389
+
12390
+ /** Value returned by {@link useMicrophone}. */
12391
+ export declare interface UseMicrophoneResult {
12392
+ status: MicrophoneStatus;
12393
+ /** The live stream, or `null`. Feed it to {@link useAudioRecorder} or an analyser. */
12394
+ stream: MediaStream | null;
12395
+ /** Classified error, or `null` outside the `error` status. */
12396
+ error: MediaAccessError | null;
12397
+ /** Open the stream. Safe to call when already open — it is a no-op. */
12398
+ start: () => void;
12399
+ /** Release the microphone. The browser's recording indicator only clears here. */
12400
+ stop: () => void;
12401
+ }
12402
+
10247
12403
  /**
10248
12404
  * Access the imperative modals API. Must be used within a {@link ModalsProvider}.
10249
12405
  *
@@ -10643,6 +12799,142 @@ export declare interface UsePaginationResult {
10643
12799
 
10644
12800
  export { useParams }
10645
12801
 
12802
+ /**
12803
+ * Probe what this device can do, once per mount.
12804
+ *
12805
+ * @param client - Client whose probes to call.
12806
+ * @returns The three capability answers, two of them async.
12807
+ */
12808
+ export declare function usePasskeyCapabilities(client?: PasskeyClient): PasskeyCapabilities;
12809
+
12810
+ /**
12811
+ * Register a passkey: fetch options, run `navigator.credentials.create`, hand the
12812
+ * credential to your backend.
12813
+ *
12814
+ * `register()` **resolves** rather than rejects on failure, because every failure
12815
+ * here is already state the UI has to render (`error.kind`, `status`). Forcing a
12816
+ * `try/catch` around a button handler that also has to set state would only
12817
+ * duplicate what the hook holds.
12818
+ *
12819
+ * @param options - Transport callbacks plus optional client and listeners.
12820
+ * @returns Ceremony state, the `register` action, and the capability probes.
12821
+ *
12822
+ * @example
12823
+ * const passkey = usePasskeyRegistration({
12824
+ * getOptions: () => api.post("/webauthn/register/begin"),
12825
+ * verify: (credential) => api.post("/webauthn/register/finish", { body: credential }),
12826
+ * });
12827
+ *
12828
+ * if (passkey.platformAvailable === false) return null;
12829
+ * return (
12830
+ * <button onClick={() => void passkey.register()} disabled={passkey.status === "prompting"}>
12831
+ * Criar passkey
12832
+ * </button>
12833
+ * );
12834
+ */
12835
+ export declare function usePasskeyRegistration<TResult = unknown>(options: UsePasskeyRegistrationOptions<TResult>): UsePasskeyRegistrationResult<TResult>;
12836
+
12837
+ /** Options for {@link usePasskeyRegistration}. */
12838
+ export declare interface UsePasskeyRegistrationOptions<TResult> {
12839
+ /** Fetch server options — your `POST /webauthn/register/begin`. */
12840
+ getOptions: () => Promise<PasskeyCreationOptionsJSON>;
12841
+ /** Send the credential to be verified — your `POST /webauthn/register/finish`. */
12842
+ verify: (credential: PasskeyRegistrationJSON) => Promise<TResult>;
12843
+ /** Client to use. Defaults to a shared `createPasskeyClient()`. */
12844
+ client?: PasskeyClient;
12845
+ /** Called with whatever `verify` resolved to. */
12846
+ onSuccess?: (result: TResult) => void;
12847
+ /** Called with the classified failure. */
12848
+ onError?: (error: PasskeyError) => void;
12849
+ }
12850
+
12851
+ /** Value returned by {@link usePasskeyRegistration}. */
12852
+ export declare interface UsePasskeyRegistrationResult<TResult> extends PasskeyCapabilities {
12853
+ /** Run the ceremony. Resolves `null` on failure — read `error` for the reason. */
12854
+ register: () => Promise<TResult | null>;
12855
+ /** Current phase. */
12856
+ status: PasskeyStatus;
12857
+ /** Last failure, cleared when a new attempt starts. */
12858
+ error: PasskeyError | null;
12859
+ /** Whatever `verify` resolved to, on success. */
12860
+ data: TResult | null;
12861
+ /** Close the browser sheet from your own UI. */
12862
+ cancel: () => void;
12863
+ /** Back to `"idle"`, clearing `error` and `data`. */
12864
+ reset: () => void;
12865
+ }
12866
+
12867
+ /**
12868
+ * Sign in with a passkey, with or without the autofill flow.
12869
+ *
12870
+ * Two ways in, and a good login page wires both. `signIn()` is the explicit
12871
+ * button. `conditional: true` arms the pleasant one: the browser lists the user's
12872
+ * passkeys inside the username field itself, so signing in is one tap and no
12873
+ * password was ever typed. The field must carry
12874
+ * `autocomplete="username webauthn"` or the list never appears — the hook cannot
12875
+ * do that part for you.
12876
+ *
12877
+ * A conditional request that is aborted (unmount, or the user typing a password
12878
+ * instead) is **not** surfaced as an error: nothing failed, the user chose
12879
+ * another door.
12880
+ *
12881
+ * @param options - Transport callbacks, `conditional`, optional client and listeners.
12882
+ * @returns Ceremony state, the `signIn` action, and the capability probes.
12883
+ *
12884
+ * @example
12885
+ * const passkey = usePasskeySignIn({
12886
+ * conditional: true,
12887
+ * getOptions: () => api.post("/webauthn/signin/begin"),
12888
+ * verify: (assertion) => api.post("/webauthn/signin/finish", { body: assertion }),
12889
+ * onSuccess: (session) => auth.setToken(session.access_token),
12890
+ * });
12891
+ *
12892
+ * <input name="email" autoComplete="username webauthn" />
12893
+ * <button onClick={() => void passkey.signIn()}>Entrar com passkey</button>
12894
+ */
12895
+ export declare function usePasskeySignIn<TResult = unknown>(options: UsePasskeySignInOptions<TResult>): UsePasskeySignInResult<TResult>;
12896
+
12897
+ /** Options for {@link usePasskeySignIn}. */
12898
+ export declare interface UsePasskeySignInOptions<TResult> {
12899
+ /** Fetch server options — your `POST /webauthn/signin/begin`. */
12900
+ getOptions: () => Promise<PasskeyRequestOptionsJSON>;
12901
+ /** Send the assertion to be verified — your `POST /webauthn/signin/finish`. */
12902
+ verify: (assertion: PasskeyAuthenticationJSON) => Promise<TResult>;
12903
+ /** Client to use. Defaults to a shared `createPasskeyClient()`. */
12904
+ client?: PasskeyClient;
12905
+ /**
12906
+ * Arm the autofill flow on mount (`mediation: "conditional"`).
12907
+ *
12908
+ * The request stays pending, invisibly, until the user picks a passkey from
12909
+ * the browser's autofill list — so the field it should appear on needs
12910
+ * `autocomplete="username webauthn"`. Only one conditional request may be live
12911
+ * per page, and it is aborted on unmount.
12912
+ */
12913
+ conditional?: boolean;
12914
+ /** Called with whatever `verify` resolved to. */
12915
+ onSuccess?: (result: TResult) => void;
12916
+ /** Called with the classified failure. */
12917
+ onError?: (error: PasskeyError) => void;
12918
+ }
12919
+
12920
+ /** Value returned by {@link usePasskeySignIn}. */
12921
+ export declare interface UsePasskeySignInResult<TResult> extends PasskeyCapabilities {
12922
+ /** Run the modal ceremony. Resolves `null` on failure. */
12923
+ signIn: () => Promise<TResult | null>;
12924
+ /** Current phase. */
12925
+ status: PasskeyStatus;
12926
+ /** Last failure, cleared when a new attempt starts. */
12927
+ error: PasskeyError | null;
12928
+ /** Whatever `verify` resolved to, on success. */
12929
+ data: TResult | null;
12930
+ /** True while an armed conditional (autofill) request is waiting. */
12931
+ conditionalPending: boolean;
12932
+ /** Close the browser sheet from your own UI. */
12933
+ cancel: () => void;
12934
+ /** Back to `"idle"`, clearing `error` and `data`. */
12935
+ reset: () => void;
12936
+ }
12937
+
10646
12938
  /**
10647
12939
  * Poll an async factory on a fixed interval. Skips overlapping requests if a
10648
12940
  * prior call has not finished. Pause via `disabled` or `stopWhen`.
@@ -10795,6 +13087,102 @@ export declare function useResizeObserver(ref: RefObject<Element | null>): Eleme
10795
13087
 
10796
13088
  export { useRouteError }
10797
13089
 
13090
+ /**
13091
+ * Capture a screen, a window or a tab with `getDisplayMedia`.
13092
+ *
13093
+ * Three states decide whether this feels right, and two of them are easy to miss:
13094
+ *
13095
+ * - **The user dismissed the picker.** A rejection, but not a failure. It leaves
13096
+ * `error` at `null` and the status back at `"idle"`, and calls `onCancelled`.
13097
+ * - **The user stopped the share from the browser's own bar.** Nothing in your UI was
13098
+ * clicked and no promise rejects — the *only* signal is the video track's `ended`
13099
+ * event, so the hook listens for it and clears the stream. Without that listener, an
13100
+ * app shows "gravando" over a stream that is already dead.
13101
+ * - **The share is live.** `surface` says what was picked and `hasAudio` says whether
13102
+ * audio actually came along, which is not what you asked for but what you got.
13103
+ *
13104
+ * The stream is owned here: `stop()` and unmount both release every track. A recorder
13105
+ * built on it (`useVideoRecorder`) deliberately does not, so stopping a recording
13106
+ * leaves the share running for the next take.
13107
+ *
13108
+ * @param options - See {@link UseScreenCaptureOptions}.
13109
+ * @returns The stream, its status, a classified error and `start`/`stop`.
13110
+ *
13111
+ * @example
13112
+ * const screen = useScreenCapture({ preferCurrentTab: true, onEnded: () => save() });
13113
+ * const rec = useVideoRecorder(screen.stream);
13114
+ * <button onClick={screen.start}>Compartilhar tela</button>
13115
+ */
13116
+ export declare function useScreenCapture(options?: UseScreenCaptureOptions): UseScreenCaptureResult;
13117
+
13118
+ /** Options for {@link useScreenCapture}. */
13119
+ export declare interface UseScreenCaptureOptions {
13120
+ /**
13121
+ * Capture the tab's audio too. Default `false`.
13122
+ *
13123
+ * Chromium only offers this for a **tab** — sharing a window or a whole screen
13124
+ * yields no audio track no matter what you ask for, and Safari has no display
13125
+ * audio at all. Ask for it and check what you got.
13126
+ */
13127
+ audio?: boolean;
13128
+ /**
13129
+ * Which surface the picker should offer first — `"browser"` is a tab.
13130
+ *
13131
+ * A hint, never a guarantee: the user can always pick something else, and Firefox
13132
+ * ignores it. Read `surface` afterwards to learn what actually happened.
13133
+ */
13134
+ displaySurface?: DisplaySurfaceHint;
13135
+ /**
13136
+ * Put *this* tab at the top of the picker. Default `false`.
13137
+ *
13138
+ * The right setting for "record what you are seeing right now" in a support flow.
13139
+ * Chromium only.
13140
+ */
13141
+ preferCurrentTab?: boolean;
13142
+ /** Offer this tab in the list at all. `"exclude"` prevents the hall-of-mirrors capture. */
13143
+ selfBrowserSurface?: "include" | "exclude";
13144
+ /** Let the user switch to a different surface mid-share, without a new prompt. */
13145
+ surfaceSwitching?: "include" | "exclude";
13146
+ /** Include the system audio when a whole screen is shared. Chromium, Windows only. */
13147
+ systemAudio?: "include" | "exclude";
13148
+ /** Escape hatch: full options, replacing everything above. */
13149
+ options?: DisplayMediaStreamOptions;
13150
+ /**
13151
+ * The user stopped the share from the browser's own bar.
13152
+ *
13153
+ * The single most important callback here — see the note on
13154
+ * {@link useScreenCapture}.
13155
+ */
13156
+ onEnded?: () => void;
13157
+ /**
13158
+ * The user dismissed the picker. **Not an error.**
13159
+ *
13160
+ * Receives the rejection so an app that needs to tell a dismissal from an OS-level
13161
+ * block (macOS screen-recording permission) can look at the message. Most should
13162
+ * simply return the UI to its previous state.
13163
+ */
13164
+ onCancelled?: (reason: unknown) => void;
13165
+ }
13166
+
13167
+ /** Value returned by {@link useScreenCapture}. */
13168
+ export declare interface UseScreenCaptureResult {
13169
+ status: ScreenCaptureStatus;
13170
+ /** The live stream, or `null`. Feed it to {@link useVideoRecorder} or a `<video>`. */
13171
+ stream: MediaStream | null;
13172
+ /** Classified error, or `null`. A cancelled picker leaves this `null`. */
13173
+ error: MediaAccessError | null;
13174
+ /** What the user actually picked, when the browser reports it. */
13175
+ surface: string | null;
13176
+ /** Whether the stream carries an audio track — ask, do not assume. */
13177
+ hasAudio: boolean;
13178
+ /** `false` when `getDisplayMedia` is missing (every browser on iOS, insecure pages). */
13179
+ supported: boolean;
13180
+ /** Open the picker. Must be called from a user gesture. */
13181
+ start: () => void;
13182
+ /** Stop sharing from the app side. Fires nothing — you asked for it. */
13183
+ stop: () => void;
13184
+ }
13185
+
10798
13186
  /**
10799
13187
  * Lock `<body>` scroll while `active` is true. Restores the previous overflow
10800
13188
  * value on unmount. Safe to nest: stacks the restoration via a counter.
@@ -11013,6 +13401,96 @@ export declare interface UseSortableResult {
11013
13401
  setContainer: (node: HTMLElement | null) => void;
11014
13402
  }
11015
13403
 
13404
+ /**
13405
+ * Dictate into your app with the Web Speech API — no dependency, no API key.
13406
+ *
13407
+ * ## Recognition is not local
13408
+ *
13409
+ * **Chromium streams the captured audio to a Google server to transcribe it.** Nothing
13410
+ * about the API says so, there is no setting that changes it, and it happens on every
13411
+ * `start()`. Anything the user says while a session is open leaves the device. Do not
13412
+ * put this on a field that takes clinical notes, credentials, or a client's financial
13413
+ * detail without telling them first — and if the data cannot leave your infrastructure,
13414
+ * this API is the wrong tool and a self-hosted model is the right one.
13415
+ *
13416
+ * ## What the states mean
13417
+ *
13418
+ * `transcript` accumulates the phrases the engine has **settled** on; `interim` is the
13419
+ * guess it is still revising and is replaced wholesale on every event, so rendering
13420
+ * `transcript + interim` gives the live caption effect and rendering `transcript` alone
13421
+ * gives the committed text. `no-speech` and `aborted` come through `onError` but are
13422
+ * routine — a user who pressed the button and said nothing is not a failure to report.
13423
+ *
13424
+ * There is deliberately **no auto-restart** when the engine ends a session on silence.
13425
+ * A restart loop is how an app ends up holding the microphone indefinitely — and, in
13426
+ * Chromium, streaming audio to a third party indefinitely. Show that listening stopped
13427
+ * and let the user press again.
13428
+ *
13429
+ * @param options - See {@link UseSpeechRecognitionOptions}.
13430
+ * @returns Session state, the transcript and the controls.
13431
+ *
13432
+ * @example
13433
+ * const speech = useSpeechRecognition({ onFinal: (text) => setPrompt(text) });
13434
+ * <button onClick={speech.listening ? speech.stop : speech.start}>
13435
+ * {speech.listening ? "Parar" : "Ditar"}
13436
+ * </button>
13437
+ * <p>{speech.transcript}{speech.interim}</p>
13438
+ */
13439
+ export declare function useSpeechRecognition(options?: UseSpeechRecognitionOptions): UseSpeechRecognitionResult;
13440
+
13441
+ /** Options for {@link useSpeechRecognition}. */
13442
+ export declare interface UseSpeechRecognitionOptions {
13443
+ /** BCP-47 tag. Default `"pt-BR"`. */
13444
+ lang?: string;
13445
+ /**
13446
+ * Keep listening after the first phrase settles. Default `false`.
13447
+ *
13448
+ * Even with this on, the engine ends the session by itself after a stretch of
13449
+ * silence — that is a server-side timeout, not a bug — so watch `listening` rather
13450
+ * than assuming the microphone stays open.
13451
+ */
13452
+ continuous?: boolean;
13453
+ /** Publish the running guess as it changes. Default `true`. */
13454
+ interimResults?: boolean;
13455
+ /** How many readings per phrase to ask for. Default 1. */
13456
+ maxAlternatives?: number;
13457
+ /** Every update, settled or not. */
13458
+ onResult?: (result: {
13459
+ transcript: string;
13460
+ isFinal: boolean;
13461
+ }) => void;
13462
+ /** Only the settled text of a phrase. The one to wire dictation to. */
13463
+ onFinal?: (transcript: string) => void;
13464
+ /** Classified failure. `no-speech` and `aborted` arrive here too — they are routine. */
13465
+ onError?: (error: SpeechError) => void;
13466
+ /** The session ended, for any reason. */
13467
+ onEnd?: () => void;
13468
+ /** Build the recogniser yourself — another engine, or a stub in a test. */
13469
+ factory?: () => SpeechRecognitionLike;
13470
+ }
13471
+
13472
+ /** Value returned by {@link useSpeechRecognition}. */
13473
+ export declare interface UseSpeechRecognitionResult {
13474
+ /** `false` in Firefox and in every browser that is not Chromium-based. */
13475
+ supported: boolean;
13476
+ /** Whether a session is open right now. */
13477
+ listening: boolean;
13478
+ /** Everything settled so far in this session. Cleared by `reset()`. */
13479
+ transcript: string;
13480
+ /** The running guess. Replaced on every event, empty once the phrase settles. */
13481
+ interim: string;
13482
+ /** Classified error, or `null`. */
13483
+ error: SpeechError | null;
13484
+ /** Open a session. No-op while already listening. */
13485
+ start: () => void;
13486
+ /** Close the session, keeping what was recognised. */
13487
+ stop: () => void;
13488
+ /** Close the session and throw the pending phrase away. */
13489
+ abort: () => void;
13490
+ /** Clear `transcript`, `interim` and `error`. Does not stop a session. */
13491
+ reset: () => void;
13492
+ }
13493
+
11016
13494
  /**
11017
13495
  * Returns a stable function reference that always invokes the latest
11018
13496
  * `callback` argument. Use to break dependency cycles in effects without
@@ -11116,6 +13594,49 @@ export declare function useToast(): ToastApi;
11116
13594
  */
11117
13595
  export declare function useToggle(initial?: boolean): [boolean, ToggleHelpers];
11118
13596
 
13597
+ /**
13598
+ * Drive the camera's LED torch on the video track of a stream.
13599
+ *
13600
+ * The lamp is not a device you can open — it is a **constraint on a live video
13601
+ * track**, so there is nothing to control until a camera stream exists, and it
13602
+ * disappears when that stream is released. That is also why `supported` can only be
13603
+ * answered after the track is live: the same code is `true` on an Android rear camera
13604
+ * and `false` on the front one of the same phone.
13605
+ *
13606
+ * Capability detection prefers `getCapabilities()` and falls back to
13607
+ * `getSettings()`, because Firefox implements neither the torch nor
13608
+ * `getCapabilities()` and Safari reports the setting without the capability. When
13609
+ * neither mentions `torch`, the hook reports `supported: false` instead of offering a
13610
+ * button that silently does nothing.
13611
+ *
13612
+ * @param stream - A live camera stream, or `null` before permission lands.
13613
+ * @returns Whether a lamp exists, its state, and setters.
13614
+ *
13615
+ * @example
13616
+ * const camera = useBarcodeScanner();
13617
+ * {camera.torch.supported && (
13618
+ * <button onClick={() => void camera.torch.toggle()}>Lanterna</button>
13619
+ * )}
13620
+ */
13621
+ export declare function useTorch(stream: MediaStream | null): UseTorchResult;
13622
+
13623
+ /** Value returned by {@link useTorch}. */
13624
+ export declare interface UseTorchResult {
13625
+ /** Whether this track has a controllable lamp. `false` on every desktop webcam. */
13626
+ supported: boolean;
13627
+ /** Whether the lamp is on, as far as this hook knows. */
13628
+ on: boolean;
13629
+ /**
13630
+ * Turn the lamp on or off.
13631
+ *
13632
+ * @param next - `true` to light it up.
13633
+ * @returns `false` when the track refused — treat that as "no torch".
13634
+ */
13635
+ set: (next: boolean) => Promise<boolean>;
13636
+ /** Flip it. Same return contract as {@link UseTorchResult.set}. */
13637
+ toggle: () => Promise<boolean>;
13638
+ }
13639
+
11119
13640
  /**
11120
13641
  * Shortcut for components that only need the `t` function — avoids destructuring.
11121
13642
  */
@@ -11149,6 +13670,70 @@ export declare interface UseViaCEPResult {
11149
13670
  reset: () => void;
11150
13671
  }
11151
13672
 
13673
+ /**
13674
+ * Record a video stream — from {@link useScreenCapture}, from a camera, or from a
13675
+ * canvas.
13676
+ *
13677
+ * Pass the stream in; the hook stays `ready: false` until there is one, so a page can
13678
+ * render the whole recorder UI before the user has picked a screen and simply have it
13679
+ * disabled.
13680
+ *
13681
+ * There is no level meter here, which is the one real difference from
13682
+ * `useAudioRecorder`: metering a screen share means opening an `AudioContext` on a
13683
+ * stream that usually has no audio track at all, and browsers cap the number of live
13684
+ * contexts. If you are recording a camera **and** want a level, run
13685
+ * `createLevelMeter` on the same stream yourself.
13686
+ *
13687
+ * The clock is published every `tickMs` (default 250 ms) rather than per frame: a
13688
+ * video recording UI shows `0:07`, and a hook that re-rendered its parent 60 times a
13689
+ * second to move a one-second counter would be the most expensive thing on the page.
13690
+ *
13691
+ * @param stream - The stream to record, or `null` while the picker is open.
13692
+ * @param options - See {@link UseVideoRecorderOptions}.
13693
+ *
13694
+ * @example
13695
+ * const screen = useScreenCapture();
13696
+ * const rec = useVideoRecorder(screen.stream, { maxDurationMs: 120_000 });
13697
+ * <button disabled={!rec.ready} onClick={rec.start}>Gravar tela</button>
13698
+ */
13699
+ export declare function useVideoRecorder(stream: MediaStream | null, options?: UseVideoRecorderOptions): UseVideoRecorderResult;
13700
+
13701
+ /** Options for {@link useVideoRecorder}. */
13702
+ export declare interface UseVideoRecorderOptions extends VideoRecorderOptions {
13703
+ /**
13704
+ * Stop automatically after this many milliseconds.
13705
+ *
13706
+ * Worth setting on anything user-facing, and more so than for audio: a minute of
13707
+ * 1080p at 2.5 Mbps is roughly 19 MB, so a recording left running by accident
13708
+ * fills memory an order of magnitude faster than a voice note does.
13709
+ */
13710
+ maxDurationMs?: number;
13711
+ /** Called once the recording is assembled, whether by `stop()` or `maxDurationMs`. */
13712
+ onRecorded?: (recording: VideoRecording) => void;
13713
+ /** How often the clock is published, in ms. Default 250. */
13714
+ tickMs?: number;
13715
+ }
13716
+
13717
+ /** Value returned by {@link useVideoRecorder}. */
13718
+ export declare interface UseVideoRecorderResult {
13719
+ status: MediaRecorderStatus;
13720
+ /** Recorded length so far, excluding paused time. */
13721
+ durationMs: number;
13722
+ /** The finished recording, or `null` before the first `stop()`. */
13723
+ recording: VideoRecording | null;
13724
+ /** Recorder-level error (encoder failure, share revoked mid-recording). */
13725
+ error: unknown;
13726
+ /** `false` when there is no stream yet, or the browser cannot record video. */
13727
+ ready: boolean;
13728
+ start: () => void;
13729
+ pause: () => void;
13730
+ resume: () => void;
13731
+ /** Stop and resolve with the recording. Also published on `recording`. */
13732
+ stop: () => Promise<VideoRecording | null>;
13733
+ /** Stop and throw the video away. */
13734
+ cancel: () => void;
13735
+ }
13736
+
11152
13737
  export { useWatch }
11153
13738
 
11154
13739
  /**
@@ -11266,6 +13851,70 @@ export declare interface ViaCEPResult {
11266
13851
  siafi?: string;
11267
13852
  }
11268
13853
 
13854
+ /**
13855
+ * Container/codec candidates for video, best first.
13856
+ *
13857
+ * VP9 in WebM leads because it is the best quality per byte that Chromium and Firefox
13858
+ * both encode natively; VP8 is the fallback for older Chromium and for hardware that
13859
+ * refuses VP9. `video/mp4` is last and exists for Safari, which produces H.264 in MP4
13860
+ * and nothing else — and only since Safari 14.1.
13861
+ *
13862
+ * Every candidate carries **Opus or AAC audio in the same container**, because a
13863
+ * screen recording with the tab's audio dropped is a support ticket, not a
13864
+ * simplification. On a stream with no audio track the browser simply omits it.
13865
+ *
13866
+ * Ported from the intersection of what `MediaRecorder.isTypeSupported` accepts in
13867
+ * Chrome 120+, Firefox 115+ and Safari 17. Re-check against
13868
+ * <https://developer.mozilla.org/docs/Web/API/MediaRecorder/isTypeSupported> before
13869
+ * adding to the list.
13870
+ */
13871
+ export declare const VIDEO_MIME_CANDIDATES: readonly string[];
13872
+
13873
+ /** Imperative video recorder. Same shape as the audio one. */
13874
+ export declare type VideoRecorderHandle = MediaRecorderHandle;
13875
+
13876
+ /** Options for {@link createVideoRecorder}. */
13877
+ export declare interface VideoRecorderOptions {
13878
+ /**
13879
+ * Force a container. Throws when the browser cannot produce it.
13880
+ *
13881
+ * Leave it out. The default negotiates from {@link VIDEO_MIME_CANDIDATES}, which
13882
+ * is the only way one call site works on both Chromium and Safari.
13883
+ */
13884
+ mimeType?: string;
13885
+ /**
13886
+ * Target video bitrate.
13887
+ *
13888
+ * The browser's default is conservative and a screen recording of text at
13889
+ * 1080p looks smeared under it. 2_500_000 is a good floor for a UI capture,
13890
+ * 8_000_000 for full-motion camera video.
13891
+ */
13892
+ videoBitsPerSecond?: number;
13893
+ /** Target audio bitrate, when the stream carries audio. 64000–128000 is plenty. */
13894
+ audioBitsPerSecond?: number;
13895
+ /**
13896
+ * Emit a chunk every N ms through `onChunk`, for streaming upload.
13897
+ *
13898
+ * Worth setting for video far sooner than for audio: a minute of 1080p at
13899
+ * 2.5 Mbps is roughly 19 MB sitting in memory.
13900
+ */
13901
+ timesliceMs?: number;
13902
+ /** Receives each chunk when `timesliceMs` is set. Chunks are **not** independently playable. */
13903
+ onChunk?: (chunk: Blob) => void;
13904
+ /** Recorder-level failure (screen share revoked mid-recording, encoder error). */
13905
+ onError?: (error: unknown) => void;
13906
+ }
13907
+
13908
+ /**
13909
+ * A finished video recording.
13910
+ *
13911
+ * Structurally the same three fields as an audio one — there is nothing
13912
+ * video-specific to add, and inventing a `width`/`height` here would be a lie: the
13913
+ * browser negotiates the frame size with the device and can change it mid-recording.
13914
+ * Read it from the track's `getSettings()` if you need it.
13915
+ */
13916
+ export declare type VideoRecording = MediaRecording;
13917
+
11269
13918
  /**
11270
13919
  * Fixed-height virtual list. Renders only the visible window plus a small
11271
13920
  * overscan buffer. Suitable for lists of thousands of identical rows.
@@ -11709,6 +14358,24 @@ export declare interface WatermarkStore {
11709
14358
  clear: () => void;
11710
14359
  }
11711
14360
 
14361
+ /** Options for {@link blobToWav}. */
14362
+ export declare interface WavOptions {
14363
+ /**
14364
+ * Mix down to one channel. Default `false`.
14365
+ *
14366
+ * Worth turning on for speech headed to a server: a microphone recorded in stereo
14367
+ * carries two nearly identical channels and doubles the upload for nothing.
14368
+ */
14369
+ mono?: boolean;
14370
+ /**
14371
+ * Resample to this rate. Default: keep the source rate.
14372
+ *
14373
+ * 16000 is the rate most speech-to-text APIs want, and dropping 48 kHz to 16 kHz
14374
+ * removes two thirds of the bytes with no audible loss on voice.
14375
+ */
14376
+ sampleRate?: number;
14377
+ }
14378
+
11712
14379
  /**
11713
14380
  * Browser-side Web Push helper. Wraps `Notification.requestPermission`,
11714
14381
  * `pushManager.subscribe`, and the corresponding teardown. Transport is up to