tempest-react-sdk 0.55.0 → 0.57.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 (58) hide show
  1. package/README.md +74 -73
  2. package/dist/components/AppBar/AppBar.module.cjs.map +1 -1
  3. package/dist/components/AppBar/AppBar.module.js.map +1 -1
  4. package/dist/components/AudioPlayer/AudioPlayer.cjs +1 -1
  5. package/dist/components/AudioPlayer/AudioPlayer.js +6 -6
  6. package/dist/components/Scheduler/Scheduler.module.cjs.map +1 -1
  7. package/dist/components/Scheduler/Scheduler.module.js.map +1 -1
  8. package/dist/components/VideoPlayer/VideoPlayer.cjs +2 -0
  9. package/dist/components/VideoPlayer/VideoPlayer.cjs.map +1 -0
  10. package/dist/components/VideoPlayer/VideoPlayer.js +229 -0
  11. package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -0
  12. package/dist/components/VideoPlayer/VideoPlayer.module.cjs +2 -0
  13. package/dist/components/VideoPlayer/VideoPlayer.module.cjs.map +1 -0
  14. package/dist/components/VideoPlayer/VideoPlayer.module.js +19 -0
  15. package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -0
  16. package/dist/components/VideoPlayer/playback-rates.cjs +2 -0
  17. package/dist/components/VideoPlayer/playback-rates.cjs.map +1 -0
  18. package/dist/components/VideoPlayer/playback-rates.js +11 -0
  19. package/dist/components/VideoPlayer/playback-rates.js.map +1 -0
  20. package/dist/hooks/use-push-to-talk.cjs +1 -1
  21. package/dist/hooks/use-push-to-talk.cjs.map +1 -1
  22. package/dist/hooks/use-push-to-talk.js +2 -2
  23. package/dist/hooks/use-push-to-talk.js.map +1 -1
  24. package/dist/imaging/exceptions.cjs +1 -1
  25. package/dist/imaging/exceptions.cjs.map +1 -1
  26. package/dist/imaging/exceptions.js +5 -1
  27. package/dist/imaging/exceptions.js.map +1 -1
  28. package/dist/imaging/frame.cjs +2 -0
  29. package/dist/imaging/frame.cjs.map +1 -0
  30. package/dist/imaging/frame.js +82 -0
  31. package/dist/imaging/frame.js.map +1 -0
  32. package/dist/imaging.cjs +1 -1
  33. package/dist/imaging.d.ts +611 -494
  34. package/dist/imaging.js +10 -9
  35. package/dist/styles/AppBar.css +1 -1
  36. package/dist/styles/Scheduler.css +2 -2
  37. package/dist/styles/VideoPlayer.css +23 -0
  38. package/dist/styles/core.css +1 -1
  39. package/dist/styles/layout.css +2 -2
  40. package/dist/styles/media.css +22 -0
  41. package/dist/styles/navigation.css +1 -1
  42. package/dist/styles.css +1 -1
  43. package/dist/tempest-react-sdk.cjs +1 -1
  44. package/dist/tempest-react-sdk.d.ts +317 -35
  45. package/dist/tempest-react-sdk.js +213 -211
  46. package/dist/webrtc/link-stats.cjs +1 -1
  47. package/dist/webrtc/link-stats.cjs.map +1 -1
  48. package/dist/webrtc/link-stats.js +134 -44
  49. package/dist/webrtc/link-stats.js.map +1 -1
  50. package/dist/webrtc/mesh-quality.cjs +1 -1
  51. package/dist/webrtc/mesh-quality.cjs.map +1 -1
  52. package/dist/webrtc/mesh-quality.js +8 -2
  53. package/dist/webrtc/mesh-quality.js.map +1 -1
  54. package/dist/webrtc/peer-mesh.cjs +1 -1
  55. package/dist/webrtc/peer-mesh.cjs.map +1 -1
  56. package/dist/webrtc/peer-mesh.js +85 -63
  57. package/dist/webrtc/peer-mesh.js.map +1 -1
  58. package/package.json +1 -1
@@ -242,7 +242,7 @@ export declare interface AIChatComposerHandle {
242
242
  getValue: () => string;
243
243
  }
244
244
 
245
- export declare interface AIChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_8> {
245
+ export declare interface AIChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_9> {
246
246
  /** Called with the trimmed prompt. The field clears only when this does not throw. */
247
247
  onSend: (text: string) => void | Promise<void>;
248
248
  /**
@@ -313,7 +313,7 @@ export declare interface AIChatMessage {
313
313
  data?: Record<string, unknown>;
314
314
  }
315
315
 
316
- export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
316
+ export declare interface AIChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_8> {
317
317
  /** The transcript, **oldest first**. Never reordered by the component. */
318
318
  messages: readonly AIChatMessage[];
319
319
  /** Renders the composer when given. Receives the trimmed prompt. */
@@ -1221,7 +1221,7 @@ export declare interface AudioPlayerHandle {
1221
1221
  current: () => HTMLAudioElement | null;
1222
1222
  }
1223
1223
 
1224
- export declare interface AudioPlayerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_4> {
1224
+ export declare interface AudioPlayerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_5> {
1225
1225
  /**
1226
1226
  * What to play — a URL, or a `Blob`/`File` straight from a recorder.
1227
1227
  *
@@ -1324,7 +1324,7 @@ export declare interface AudioRecorderOptions {
1324
1324
  onError?: (error: unknown) => void;
1325
1325
  }
1326
1326
 
1327
- export declare interface AudioRecorderProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_5> {
1327
+ export declare interface AudioRecorderProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
1328
1328
  /**
1329
1329
  * Called once a recording is finished and (when asked) converted.
1330
1330
  *
@@ -1601,7 +1601,7 @@ export declare interface BarcodePoint {
1601
1601
  */
1602
1602
  export declare function BarcodeScanner({ onScan, formats, paused, detector, intervalMs, repeatDelayMs, torch, aspectRatio, locale, footer, unsupported, onError, className, ...rest }: BarcodeScannerProps): JSX.Element;
1603
1603
 
1604
- export declare interface BarcodeScannerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_6> {
1604
+ export declare interface BarcodeScannerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_7> {
1605
1605
  /** Called for every accepted read — repeats of the same value are suppressed. */
1606
1606
  onScan: (result: BarcodeScanResult) => void;
1607
1607
  /** Symbologies to look for. Defaults to QR + EAN-13 + Code 128. */
@@ -2381,7 +2381,7 @@ export declare interface ChatComposerHandle {
2381
2381
  setValue: (text: string) => void;
2382
2382
  }
2383
2383
 
2384
- export declare interface ChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_3> {
2384
+ export declare interface ChatComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, OverriddenDomProps_4> {
2385
2385
  /** Called with the trimmed text. The field clears only when this does not throw. */
2386
2386
  onSend: (text: string) => void | Promise<void>;
2387
2387
  /** Locale for the placeholder and the send label. Default `"pt-BR"`. */
@@ -2437,7 +2437,7 @@ export declare interface ChatMessage {
2437
2437
  data?: Record<string, unknown>;
2438
2438
  }
2439
2439
 
2440
- export declare interface ChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_2> {
2440
+ export declare interface ChatProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_3> {
2441
2441
  /** The thread, **oldest first**. Never reordered by the component. */
2442
2442
  messages: readonly ChatMessage[];
2443
2443
  /** Author id treated as "own" — decides side, colour and status ticks. */
@@ -5085,6 +5085,17 @@ export declare const DEFAULT_MAX_GAIN = 3;
5085
5085
  */
5086
5086
  export declare const DEFAULT_MODE_DURATION_FACTORS: Record<TravelMode, number>;
5087
5087
 
5088
+ /**
5089
+ * The speed presets the player offers, and why they stop at 2×.
5090
+ *
5091
+ * The spec lets a browser drop the audio once `playbackRate` leaves a range it
5092
+ * considers useful, and that limit varies by engine. These four sit inside every
5093
+ * range measured, so the default control never silences a clip by accident. A
5094
+ * caller who wants 4× can pass it — and should test it with sound on the
5095
+ * browsers they support before promising it.
5096
+ */
5097
+ export declare const DEFAULT_PLAYBACK_RATES: readonly number[];
5098
+
5088
5099
  /**
5089
5100
  * COSE algorithms offered when the server sends no `pubKeyCredParams`, in
5090
5101
  * preference order.
@@ -5810,7 +5821,7 @@ export declare interface Filter {
5810
5821
  */
5811
5822
  export declare function FilterBar({ fields, value, onChange, locale, actions, className, ...rest }: FilterBarProps): JSX.Element;
5812
5823
 
5813
- export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_12> {
5824
+ export declare interface FilterBarProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_13> {
5814
5825
  /** Fields the user may filter by. */
5815
5826
  fields: readonly FilterField[];
5816
5827
  /** Applied filters. Controlled. */
@@ -7854,6 +7865,43 @@ export declare interface LinkStats {
7854
7865
  fps: number;
7855
7866
  /** Round trip to the peer in milliseconds, or `null` before the first reading. */
7856
7867
  rttMs: number | null;
7868
+ /**
7869
+ * Uplink the transport estimates for this path, in kbps, or `null`.
7870
+ *
7871
+ * `null` and not `0`, because the two mean opposite things: no estimate yet
7872
+ * is the normal state for the first seconds of every call and the permanent
7873
+ * state on an engine that publishes none, while `0` is indistinguishable
7874
+ * from a path that died. A consumer that reads absence as zero drops the
7875
+ * quality at the start of every call.
7876
+ *
7877
+ * This is the field that separates "healthy at 2.5 Mbps" from "capped at
7878
+ * 2.5 Mbps and drowning" — `kbps` reports the cap being honoured either
7879
+ * way, while the queue behind it grows.
7880
+ */
7881
+ availableKbps: number | null;
7882
+ /**
7883
+ * What the encoder says is holding the picture back, or `null` for nothing.
7884
+ *
7885
+ * `"bandwidth"` wins over the other values when senders disagree, because
7886
+ * it is the only one a lower cap answers. Reacting to bandwidth on a
7887
+ * machine that is actually CPU-bound buys a worse picture and no relief.
7888
+ *
7889
+ * The spec's `"none"` is reported as `null`: a consumer should not have to
7890
+ * know that one of the truthy strings means "nothing".
7891
+ */
7892
+ limitedBy: RTCQualityLimitationReason | null;
7893
+ /**
7894
+ * Whether the link is travelling through a TURN relay.
7895
+ *
7896
+ * On a self-hosted mesh this is the hosting bill: a relayed stream goes up
7897
+ * and down through the machine somebody is paying for, and the person who
7898
+ * picked 4K is not that somebody.
7899
+ *
7900
+ * Resolved only from the pair the transport **names**, never from a merely
7901
+ * `succeeded` one — guessing the route from a pair that carries nothing
7902
+ * would report a cost nobody is paying.
7903
+ */
7904
+ relayed: boolean;
7857
7905
  }
7858
7906
 
7859
7907
  /** Which media a sampler counts. */
@@ -8110,7 +8158,7 @@ export declare type MarkdownInline = {
8110
8158
  type: "break";
8111
8159
  };
8112
8160
 
8113
- export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_11> {
8161
+ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_12> {
8114
8162
  /** The Markdown source. */
8115
8163
  source: string;
8116
8164
  /**
@@ -8148,7 +8196,7 @@ export declare interface MarkdownProps extends Omit<HTMLAttributes<HTMLDivElemen
8148
8196
  */
8149
8197
  export declare function Masonry<T>({ items, children, itemKey, columns, gap, className, style, ...rest }: MasonryProps<T>): JSX.Element;
8150
8198
 
8151
- export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_10> {
8199
+ export declare interface MasonryProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_11> {
8152
8200
  /** What to lay out. */
8153
8201
  items: readonly T[];
8154
8202
  /** Render one card. */
@@ -8418,6 +8466,14 @@ export declare interface MeshPeer {
8418
8466
  connection: RTCPeerConnectionState;
8419
8467
  /** Inbound stream per slot name, `null` for a slot the peer is not sending. */
8420
8468
  streams: Record<string, MediaStream | null>;
8469
+ /**
8470
+ * The last sample for this link, when the mesh was asked to measure.
8471
+ *
8472
+ * Absent unless {@link PeerMeshOptions.stats} was given: measuring costs a
8473
+ * `getStats()` per link per tick, and a mesh that shows no badge should not
8474
+ * pay it.
8475
+ */
8476
+ stats?: LinkStats;
8421
8477
  }
8422
8478
 
8423
8479
  /** Encoder limits, before the room divides them. */
@@ -8440,6 +8496,21 @@ export declare interface MeshQuality {
8440
8496
  maxFramerate?: number;
8441
8497
  /** What a video encoder gives up first. */
8442
8498
  degradationPreference?: RTCDegradationPreference;
8499
+ /**
8500
+ * Which video slot decides whether `maintain-framerate` still holds.
8501
+ *
8502
+ * Without it the decision reads the **largest** cap across every video
8503
+ * slot, which is right for a mesh whose slots are interchangeable and wrong
8504
+ * for one where they are not. Somebody who picked fluidity was thinking
8505
+ * about the screen — code, a spreadsheet, a video at 60 fps — and with only
8506
+ * a camera on, that choice ends up being decided by a stream it was never
8507
+ * about.
8508
+ *
8509
+ * Name the slot the choice was about and it decides alone. A slot the caps
8510
+ * do not mention keeps the preference: nothing has been said about the
8511
+ * thing being asked about, and a modest camera beside it is not an answer.
8512
+ */
8513
+ degradationAnchor?: string;
8443
8514
  /**
8444
8515
  * Total uplink to divide among the peers, in kbps.
8445
8516
  *
@@ -8493,6 +8564,37 @@ export declare type MeshSlotKind = "audio" | "video";
8493
8564
  */
8494
8565
  export declare type MeshState = "connecting" | "connected" | "reconnecting" | "failed" | "closed";
8495
8566
 
8567
+ /** Options for `createPeerMesh`. */
8568
+ /**
8569
+ * Ask the mesh to measure its own links.
8570
+ *
8571
+ * The rule this exists to keep is the one a hand-rolled loop gets wrong: **one
8572
+ * sampler per connection**. The rate is a delta, so a sampler shared across
8573
+ * peers subtracts one connection's counter from another's and reports nonsense
8574
+ * — and the mesh is the only place that knows how many links there are and when
8575
+ * one goes away. It also owns a single timer instead of one per peer.
8576
+ *
8577
+ * Sampling only runs for a link whose connection is `connected`. A link still
8578
+ * gathering candidates has no traffic to measure, and asking anyway spends a
8579
+ * `getStats()` to learn that.
8580
+ */
8581
+ export declare interface MeshStatsOptions {
8582
+ /** How often to sample each connected link, in milliseconds. Default `2000`. */
8583
+ intervalMs?: number;
8584
+ /** Which media the throughput counts. Passed straight to the sampler. */
8585
+ kind?: LinkStatsKind;
8586
+ /**
8587
+ * Called with each link's sample, as it is taken.
8588
+ *
8589
+ * The same value lands on {@link MeshPeer.stats}, so a consumer that reads
8590
+ * the peer list needs no callback at all. Note that measuring therefore
8591
+ * makes {@link PeerMeshOptions.onPeers} fire on the interval — which is the
8592
+ * point for a badge, and worth knowing for anything that does real work in
8593
+ * that handler.
8594
+ */
8595
+ onStats?: (peerId: string, stats: LinkStats) => void;
8596
+ }
8597
+
8496
8598
  export declare type Messages = Record<string, string>;
8497
8599
 
8498
8600
  /** Lifecycle of a microphone stream. */
@@ -9532,37 +9634,49 @@ export { Outlet }
9532
9634
  declare type OverriddenDomProps = "children" | "title" | "onSelect";
9533
9635
 
9534
9636
  /** DOM attributes this component redefines. */
9535
- declare type OverriddenDomProps_10 = "children";
9637
+ declare type OverriddenDomProps_10 = "children" | "onChange" | "defaultValue";
9536
9638
 
9537
9639
  /** DOM attributes this component redefines. */
9538
9640
  declare type OverriddenDomProps_11 = "children";
9539
9641
 
9540
9642
  /** DOM attributes this component redefines. */
9541
- declare type OverriddenDomProps_12 = "children" | "onChange";
9643
+ declare type OverriddenDomProps_12 = "children";
9542
9644
 
9543
9645
  /** DOM attributes this component redefines. */
9544
- declare type OverriddenDomProps_2 = "children" | "onSubmit";
9646
+ declare type OverriddenDomProps_13 = "children" | "onChange";
9545
9647
 
9546
- /** DOM attributes the composer redefines. */
9547
- declare type OverriddenDomProps_3 = "onSubmit" | "value" | "defaultValue" | "rows";
9648
+ /**
9649
+ * DOM attributes this component redefines.
9650
+ *
9651
+ * `onRateChange` is a real collision, not tidiness: React types it on every
9652
+ * element as the media `ratechange` handler, `ReactEventHandler`. Ours carries
9653
+ * the rate the viewer picked, and a `(rate: number) => void` is not assignable
9654
+ * to a handler that receives an event — same shape of clash as `Input`'s `size`
9655
+ * against `HTMLInputElement.size`. The DOM one is useless on a `<div>` anyway:
9656
+ * the event fires on the media element inside, which this component owns.
9657
+ */
9658
+ declare type OverriddenDomProps_2 = "children" | "onRateChange";
9548
9659
 
9549
9660
  /** DOM attributes this component redefines. */
9550
- declare type OverriddenDomProps_4 = "children";
9661
+ declare type OverriddenDomProps_3 = "children" | "onSubmit";
9662
+
9663
+ /** DOM attributes the composer redefines. */
9664
+ declare type OverriddenDomProps_4 = "onSubmit" | "value" | "defaultValue" | "rows";
9551
9665
 
9552
9666
  /** DOM attributes this component redefines. */
9553
- declare type OverriddenDomProps_5 = "children" | "onError";
9667
+ declare type OverriddenDomProps_5 = "children";
9554
9668
 
9555
9669
  /** DOM attributes this component redefines. */
9556
9670
  declare type OverriddenDomProps_6 = "children" | "onError";
9557
9671
 
9558
9672
  /** DOM attributes this component redefines. */
9559
- declare type OverriddenDomProps_7 = "children" | "onSubmit";
9560
-
9561
- /** DOM attributes the composer redefines. */
9562
- declare type OverriddenDomProps_8 = "onSubmit" | "value" | "defaultValue" | "rows";
9673
+ declare type OverriddenDomProps_7 = "children" | "onError";
9563
9674
 
9564
9675
  /** DOM attributes this component redefines. */
9565
- declare type OverriddenDomProps_9 = "children" | "onChange" | "defaultValue";
9676
+ declare type OverriddenDomProps_8 = "children" | "onSubmit";
9677
+
9678
+ /** DOM attributes the composer redefines. */
9679
+ declare type OverriddenDomProps_9 = "onSubmit" | "value" | "defaultValue" | "rows";
9566
9680
 
9567
9681
  /**
9568
9682
  * Page wrapper with header + (optional) toolbar + content + footer. Pairs
@@ -9981,9 +10095,26 @@ export declare interface PeerMesh {
9981
10095
  stop: () => void;
9982
10096
  /** The peers as the mesh currently sees them. */
9983
10097
  readonly peers: MeshPeer[];
10098
+ /**
10099
+ * The connection carrying one peer's link, or `null`.
10100
+ *
10101
+ * The escape hatch for everything this mesh does not model. `getStats()`,
10102
+ * `getSenders()`, an `RTCDataChannel`, an encoding tweak the `quality`
10103
+ * shape has no field for — all of it lives on the connection, and a mesh
10104
+ * that keeps it private turns adopting the mesh into losing a feature.
10105
+ *
10106
+ * {@link MeshPeer.connection} is the *state*, which is what a view needs;
10107
+ * this is the object, which is what a measurement needs. For the common
10108
+ * case of measuring, {@link PeerMeshOptions.stats} spares you the loop —
10109
+ * including the one-sampler-per-connection rule that a hand-rolled version
10110
+ * gets wrong.
10111
+ *
10112
+ * @param peerId - The id the peer was added under.
10113
+ * @returns The connection, or `null` when there is no link for that id.
10114
+ */
10115
+ getConnection: (peerId: string) => RTCPeerConnection | null;
9984
10116
  }
9985
10117
 
9986
- /** Options for `createPeerMesh`. */
9987
10118
  export declare interface PeerMeshOptions {
9988
10119
  /** The lanes every link negotiates, in the order they are allocated. */
9989
10120
  slots: readonly MeshSlot[];
@@ -9999,6 +10130,8 @@ export declare interface PeerMeshOptions {
9999
10130
  onNotice?: (reason: string) => void;
10000
10131
  /** Initial encoder limits. */
10001
10132
  quality?: MeshQuality;
10133
+ /** Measure every link, on one timer the mesh owns. See {@link MeshStatsOptions}. */
10134
+ stats?: MeshStatsOptions;
10002
10135
  /**
10003
10136
  * Applies a local description, so the SDP can be rewritten on the way out.
10004
10137
  *
@@ -10737,6 +10870,26 @@ export declare interface RatingStarsProps {
10737
10870
  */
10738
10871
  export declare function readableForeground(background: string, light?: string, dark?: string): string;
10739
10872
 
10873
+ /**
10874
+ * Read the uplink the transport estimates for this path, in kbps.
10875
+ *
10876
+ * This is the field that tells a cap being honoured apart from a cap that is
10877
+ * drowning: `bytesSent` reports the same 2500 kbps whether the path has room
10878
+ * for it or the queue behind it is growing. No fixed budget can stand in for it
10879
+ * — a domestic uplink of 1 Mbps and a fibre link differ by an order of
10880
+ * magnitude, and in Brazil the upload routinely is a tenth of the download
10881
+ * beside it.
10882
+ *
10883
+ * @param report - A report from `RTCPeerConnection.getStats()`.
10884
+ * @returns The estimate in kbps, or `null` while there is none. Every reader
10885
+ * needs a fallback for that, not a default of zero.
10886
+ *
10887
+ * @example
10888
+ * const headroom = readAvailableOutgoingKbps(await pc.getStats());
10889
+ * if (headroom !== null && headroom < asked) lowerTheCap(headroom);
10890
+ */
10891
+ export declare function readAvailableOutgoingKbps(report: RTCStatsReport): number | null;
10892
+
10740
10893
  /**
10741
10894
  * Sample the device capabilities the browser reports.
10742
10895
  *
@@ -10754,18 +10907,41 @@ export declare function readableForeground(background: string, light?: string, d
10754
10907
  export declare function readDeviceProfile(): DeviceProfile;
10755
10908
 
10756
10909
  /**
10757
- * Read the round trip of the candidate pair actually carrying the link.
10910
+ * Read what the encoder says is holding the picture back.
10758
10911
  *
10759
- * A connection routinely keeps several viable pairs alive at once host,
10760
- * server-reflexive, relayed and only one of them carries traffic. Reading the
10761
- * first `succeeded` pair makes the number jump between paths that are not being
10762
- * travelled: 8 ms on an idle host pair alternating with 180 ms on the TURN pair
10763
- * doing the work. The pair the transport names in `selectedCandidatePairId` is
10764
- * the one being used.
10912
+ * `"bandwidth"` wins when senders disagree, because it is the only reason a
10913
+ * lower cap answers. The spec's `"none"` comes back as `null`.
10765
10914
  *
10766
- * A succeeded pair is kept as a fallback because not every browser fills that
10767
- * field in losing the reading entirely is worse than an occasionally
10768
- * optimistic one.
10915
+ * @param report - A report from `RTCPeerConnection.getStats()`.
10916
+ * @returns The reason, or `null` when nothing is limiting the picture.
10917
+ *
10918
+ * @example
10919
+ * if (readQualityLimitation(await pc.getStats()) === "cpu") stopBlurringTheBackground();
10920
+ */
10921
+ export declare function readQualityLimitation(report: RTCStatsReport): RTCQualityLimitationReason | null;
10922
+
10923
+ /**
10924
+ * Read whether the link is travelling through a TURN relay.
10925
+ *
10926
+ * Resolved only from the pair the browser names, never from a merely
10927
+ * `succeeded` one: a relayed route is somebody's hosting bill, and reporting
10928
+ * one from a pair that carries nothing bills a cost nobody is paying.
10929
+ *
10930
+ * @param report - A report from `RTCPeerConnection.getStats()`.
10931
+ * @returns `true` when the carrying pair's local candidate is a relay.
10932
+ *
10933
+ * @example
10934
+ * if (readRelayed(await pc.getStats())) capTheStreamThatCostsMoney();
10935
+ */
10936
+ export declare function readRelayed(report: RTCStatsReport): boolean;
10937
+
10938
+ /**
10939
+ * Read the round trip of the candidate pair actually carrying the link.
10940
+ *
10941
+ * A `succeeded` pair is kept as a last resort because not every browser names
10942
+ * the selected one — losing the reading entirely is worse than an occasionally
10943
+ * optimistic one. See {@link carryingPair} for the chain and why the middle
10944
+ * step exists.
10769
10945
  *
10770
10946
  * @param report - A report from `RTCPeerConnection.getStats()`.
10771
10947
  * @returns Round trip in milliseconds, rounded, or `null` when nothing reported
@@ -11054,7 +11230,17 @@ export declare interface ResizableProps extends Omit<HTMLAttributes<HTMLDivEleme
11054
11230
  * is worse than the lower rate it replaced — so below that line the preference
11055
11231
  * is overridden rather than obeyed.
11056
11232
  *
11057
- * @param quality - What was asked for.
11233
+ * Two things decide *which* budget answers that question:
11234
+ *
11235
+ * - **`null` is the most generous case, not the absent one.** A slot with no cap
11236
+ * is unbounded, which is exactly where fluidity should hold. Reading it as
11237
+ * missing — and then deciding from a modest camera beside it — is the answer
11238
+ * backwards.
11239
+ * - **{@link MeshQuality.degradationAnchor} names the slot the choice was
11240
+ * about.** Without it the largest cap across the video slots answers, which
11241
+ * is right when the slots are interchangeable and wrong when they are not.
11242
+ *
11243
+ * @param quality - What was asked for, including the anchor and the floor.
11058
11244
  * @param effective - What the room's share actually allows.
11059
11245
  * @returns The degradation preference to write onto the senders, or `undefined`
11060
11246
  * when the caller expressed no preference.
@@ -13422,7 +13608,7 @@ export declare interface TransferItem {
13422
13608
  data?: Record<string, unknown>;
13423
13609
  }
13424
13610
 
13425
- export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_9> {
13611
+ export declare interface TransferProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_10> {
13426
13612
  /** The whole catalogue. Both panes are derived from it. */
13427
13613
  items: readonly TransferItem[];
13428
13614
  /** Ids on the target side. Controlled. */
@@ -16654,6 +16840,88 @@ export declare interface ViaCEPResult {
16654
16840
  siafi?: string;
16655
16841
  }
16656
16842
 
16843
+ /**
16844
+ * Playback transport for one video: play/pause, seek, volume, speed, fullscreen.
16845
+ *
16846
+ * Built on a real `<video>` element, and deliberately **not** an overlay: the
16847
+ * controls sit in a bar under the frame rather than on top of it. Controls drawn
16848
+ * over video have to earn their contrast against arbitrary pixels, which no
16849
+ * `--tempest-*` token can promise — every text token in this SDK is resolved
16850
+ * against a known surface, and the two contrast defects this repo shipped were
16851
+ * both a text token used over a surface it was never checked against. A bar with
16852
+ * its own surface inherits the theme and is legible by construction.
16853
+ *
16854
+ * The seek bar, the volume slider and the speed picker are bare `<input>` and
16855
+ * `<select>` elements rather than the SDK's `Slider` and `Select`: those are form
16856
+ * fields, with a label row and a value badge, and a transport wants neither. The
16857
+ * native elements keep the keyboard and screen-reader behaviour that matters here
16858
+ * for free.
16859
+ *
16860
+ * @example
16861
+ * const rec = useVideoRecorder(screen.stream);
16862
+ * {rec.recording && (
16863
+ * <VideoPlayer src={rec.recording.blob} durationMs={rec.recording.durationMs} />
16864
+ * )}
16865
+ */
16866
+ export declare function VideoPlayer({ src, durationMs, poster, tracks, aspectRatio, rate, rates, onRateChange, shiftPitch, fullscreen, autoPlay, loop, muted, locale, actions, onEnded, onError, disabled, className, ...rest }: VideoPlayerProps): JSX.Element;
16867
+
16868
+ export declare interface VideoPlayerProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps_2> {
16869
+ /**
16870
+ * What to play — a URL, or a `Blob`/`File` straight from a recorder.
16871
+ *
16872
+ * A `Blob` is wrapped in an object URL that is revoked when it changes or the
16873
+ * component unmounts, so a session that records twenty clips does not leak
16874
+ * twenty URLs for the lifetime of the tab.
16875
+ */
16876
+ src: string | Blob | null;
16877
+ /**
16878
+ * Known length in milliseconds.
16879
+ *
16880
+ * Pass it whenever you have it — a recording from `useVideoRecorder` always
16881
+ * does. Without it the element's own `duration` is used, and a fresh
16882
+ * `MediaRecorder` blob may report `Infinity` until it is probed for one.
16883
+ */
16884
+ durationMs?: number;
16885
+ /** Still shown before playback. Pair it with `captureFrame` from `/imaging`. */
16886
+ poster?: string;
16887
+ /** Caption and subtitle files. */
16888
+ tracks?: readonly VideoTextTrack[];
16889
+ /** Frame shape while the video has no intrinsic size yet. Default `16 / 9`. */
16890
+ aspectRatio?: number;
16891
+ /**
16892
+ * Playback rate. Controlled when passed with `onRateChange`.
16893
+ *
16894
+ * Written to both `playbackRate` and `defaultPlaybackRate`, because the
16895
+ * element resets the first to the second when a source loads — a player that
16896
+ * only writes `playbackRate` silently drops back to 1× on every clip change.
16897
+ */
16898
+ rate?: number;
16899
+ /** Presets the control offers. `[]` hides it. Default {@link DEFAULT_PLAYBACK_RATES}. */
16900
+ rates?: readonly number[];
16901
+ /** Called with the rate the viewer picked. */
16902
+ onRateChange?: (rate: number) => void;
16903
+ /** Let the pitch rise with the rate (`preservesPitch = false`). Default `false`. */
16904
+ shiftPitch?: boolean;
16905
+ /** Offer a fullscreen button where the browser supports it. Default `true`. */
16906
+ fullscreen?: boolean;
16907
+ /** Start playing as soon as `src` is ready. Default `false`. */
16908
+ autoPlay?: boolean;
16909
+ /** Loop. Default `false`. */
16910
+ loop?: boolean;
16911
+ /** Start muted. Autoplay without a gesture needs this. Default `false`. */
16912
+ muted?: boolean;
16913
+ /** Locale for the labels. Default `"pt-BR"`. */
16914
+ locale?: "pt-BR" | "en";
16915
+ /** Rendered at the end of the control row — a download button, a delete button. */
16916
+ actions?: ReactNode;
16917
+ /** Fired when playback reaches the end. */
16918
+ onEnded?: () => void;
16919
+ /** Fired when the element reports a decode/network error. */
16920
+ onError?: (error: unknown) => void;
16921
+ /** No `src` yet, or playback not allowed. */
16922
+ disabled?: boolean;
16923
+ }
16924
+
16657
16925
  /** Imperative video recorder. Same shape as the audio one. */
16658
16926
  export declare type VideoRecorderHandle = MediaRecorderHandle;
16659
16927
 
@@ -16699,6 +16967,20 @@ export declare interface VideoRecorderOptions {
16699
16967
  */
16700
16968
  export declare type VideoRecording = MediaRecording;
16701
16969
 
16970
+ /** One caption or subtitle file, rendered as a `<track>`. */
16971
+ export declare interface VideoTextTrack {
16972
+ /** URL of the WebVTT file. */
16973
+ src: string;
16974
+ /** BCP 47 language tag, e.g. `"pt-BR"`. */
16975
+ srcLang: string;
16976
+ /** Name shown in the browser's own track menu. */
16977
+ label: string;
16978
+ /** Track kind. Default `"captions"`. */
16979
+ kind?: "subtitles" | "captions" | "descriptions" | "chapters" | "metadata";
16980
+ /** Whether this track is on unless the viewer picks another. */
16981
+ default?: boolean;
16982
+ }
16983
+
16702
16984
  /**
16703
16985
  * Fixed-height virtual list. Renders only the visible window plus a small
16704
16986
  * overscan buffer. Suitable for lists of thousands of identical rows.