@poolse/react-native 2.12.1 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,51 +1,9 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { CallParticipant, Conversation, Uuid, Message, AttachmentUploadInput, Membership, Attachment, WebRtcAdapter, VoiceStatus, LiveKitModule, CallMedia } from '@poolse/sdk';
3
1
  import * as react from 'react';
4
- import { ReactNode, ReactElement } from 'react';
2
+ import { ReactNode, ReactElement, ComponentType } from 'react';
3
+ import { Conversation, Uuid, Message, AttachmentUploadInput, Membership, Attachment, WebRtcAdapter, VoiceStatus, LiveKitModule, CallParticipant, CallMedia } from '@poolse/sdk';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { UseCalls } from '@poolse/react';
6
-
7
- /**
8
- * The slice of `@livekit/react-native` this needs.
9
- *
10
- * Passed in by the app rather than imported, for the same reason
11
- * `react-native-webrtc` is: tsup rewrites `require()` into
12
- * `__require()`, which Metro cannot follow, so anything this package
13
- * imports for itself never reaches a React Native bundle.
14
- *
15
- * import * as livekitRN from '@livekit/react-native';
16
- */
17
- interface LiveKitReactNativeModule {
18
- /**
19
- * The module's `VideoTrack` component.
20
- *
21
- * Typed as `unknown` on purpose. Its real props are far more specific
22
- * than what this renders with, and React component props are
23
- * contravariant — declaring the narrow shape here means the real
24
- * component is not assignable to it and no app can pass the module in.
25
- * It is narrowed to {@link CheckedVideoTrack} at the point of use.
26
- */
27
- VideoTrack: unknown;
28
- }
29
- interface CallVideoGridProps {
30
- participants: CallParticipant[];
31
- /** `@livekit/react-native`, imported by your app. */
32
- livekitReactNative?: LiveKitReactNativeModule | null | undefined;
33
- /** Resolves a user id to a display label. */
34
- labelFor?: ((userId: string) => string) | undefined;
35
- }
36
- /**
37
- * The video half of a call: one tile per participant.
38
- *
39
- * Someone with their camera off still gets a tile, showing their name
40
- * and whether they're muted. Dropping them would make a five-person
41
- * call with four cameras off look like a one-person call, and hide the
42
- * fact that they are there and can hear you.
43
- *
44
- * Tiles are laid out in a simple grid that stays square-ish as the call
45
- * grows. There is no active-speaker promotion yet — with the small
46
- * calls an SFU mesh replacement is sized for, everyone fits on screen.
47
- */
48
- declare function CallVideoGrid({ participants, livekitReactNative, labelFor }: CallVideoGridProps): react_jsx_runtime.JSX.Element | null;
6
+ import { ViewStyle } from 'react-native';
49
7
 
50
8
  interface InboxUser {
51
9
  /** The user's external_id (the same id you mint JWTs with). */
@@ -685,10 +643,18 @@ declare const ICONS: {
685
643
  readonly vb: "0 0 24 24";
686
644
  readonly d: "<path d=\"M6 9.2a6 6 0 0 1 12 0c0 4.8 1.4 6.3 1.9 6.8H4.1C4.6 15.5 6 14 6 9.2Z\"/><path d=\"M9.6 19.8a2.5 2.5 0 0 0 4.8 0\"/>";
687
645
  };
646
+ readonly bluetooth: {
647
+ readonly vb: "0 0 24 24";
648
+ readonly d: "<path d=\"M7.5 7.5 16.5 16.5 12 21V3l4.5 4.5L7.5 16.5\"/>";
649
+ };
688
650
  readonly camera: {
689
651
  readonly vb: "0 0 24 24";
690
652
  readonly d: "<path d=\"M3 8.5a2 2 0 0 1 2-2h2.4l1.4-2h6.4l1.4 2H19a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9Z\"/><circle cx=\"12\" cy=\"13\" r=\"3.5\"/>";
691
653
  };
654
+ readonly 'camera-flip': {
655
+ readonly vb: "0 0 24 24";
656
+ readonly d: "<path d=\"M3 8.5a2 2 0 0 1 2-2h2.4l1.4-2h6.4l1.4 2H19a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9Z\"/><path d=\"M14.6 13a2.6 2.6 0 0 1-4.5 1.8\"/><path d=\"M9.4 13a2.6 2.6 0 0 1 4.5-1.8\"/><path d=\"M13.9 9.6v1.7h-1.7\"/><path d=\"M10.1 16.4v-1.7h1.7\"/>";
657
+ };
692
658
  readonly 'check-double': {
693
659
  readonly vb: "0 0 24 24";
694
660
  readonly d: "<path d=\"M2.5 12.8 6.9 17 15.4 7.6\"/><path d=\"M11.4 16.4 12.3 17.2 21 7.6\"/>";
@@ -705,6 +671,10 @@ declare const ICONS: {
705
671
  readonly vb: "0 0 24 24";
706
672
  readonly d: "<path d=\"M9 5 16 12 9 19\"/>";
707
673
  };
674
+ readonly 'chevron-up': {
675
+ readonly vb: "0 0 24 24";
676
+ readonly d: "<path d=\"M6 14.5 12 8.5 18 14.5\"/>";
677
+ };
708
678
  readonly close: {
709
679
  readonly vb: "0 0 24 24";
710
680
  readonly d: "<path d=\"M6 6 18 18M18 6 6 18\"/>";
@@ -733,6 +703,10 @@ declare const ICONS: {
733
703
  readonly vb: "0 0 24 24";
734
704
  readonly d: "<circle cx=\"12\" cy=\"12\" r=\"8.6\"/><circle cx=\"9\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M8.4 14.2a4.6 4.6 0 0 0 7.2 0\"/>";
735
705
  };
706
+ readonly headphones: {
707
+ readonly vb: "0 0 24 24";
708
+ readonly d: "<path d=\"M4 14v-2a8 8 0 0 1 16 0v2\"/><path d=\"M4 14h2.6a1.4 1.4 0 0 1 1.4 1.4v3.2A1.4 1.4 0 0 1 6.6 20H5.4A1.4 1.4 0 0 1 4 18.6Z\"/><path d=\"M20 14h-2.6a1.4 1.4 0 0 0-1.4 1.4v3.2A1.4 1.4 0 0 0 17.4 20h1.2A1.4 1.4 0 0 0 20 18.6Z\"/>";
709
+ };
736
710
  readonly heart: {
737
711
  readonly vb: "0 0 24 24";
738
712
  readonly d: "<path d=\"M12 20.3 4.4 12.9a4.6 4.6 0 1 1 6.5-6.5l1.1 1.1 1.1-1.1a4.6 4.6 0 1 1 6.5 6.5L12 20.3Z\"/>";
@@ -769,6 +743,10 @@ declare const ICONS: {
769
743
  readonly vb: "0 0 24 24";
770
744
  readonly d: "<rect x=\"9\" y=\"2.6\" width=\"6\" height=\"11.2\" rx=\"3\"/><path d=\"M5.6 11.2a6.4 6.4 0 0 0 12.8 0\"/><path d=\"M12 17.6v3.4\"/><path d=\"M8.6 21h6.8\"/>";
771
745
  };
746
+ readonly 'mic-off': {
747
+ readonly vb: "0 0 24 24";
748
+ readonly d: "<rect x=\"9\" y=\"2.6\" width=\"6\" height=\"11.2\" rx=\"3\"/><path d=\"M5.6 11.2a6.4 6.4 0 0 0 12.8 0\"/><path d=\"M12 17.6v3.4\"/><path d=\"M8.6 21h6.8\"/><path d=\"M3.6 3.2 20.4 20.8\"/>";
749
+ };
772
750
  readonly 'more-h': {
773
751
  readonly vb: "0 0 24 24";
774
752
  readonly d: "<circle cx=\"5.4\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"18.6\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/>";
@@ -777,6 +755,14 @@ declare const ICONS: {
777
755
  readonly vb: "0 0 24 24";
778
756
  readonly d: "<circle cx=\"12\" cy=\"5.4\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"18.6\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\"/>";
779
757
  };
758
+ readonly phone: {
759
+ readonly vb: "0 0 24 24";
760
+ readonly d: "<path d=\"M6.6 3.5h3l1.5 3.7-1.9 1.4a12.5 12.5 0 0 0 6.2 6.2l1.4-1.9 3.7 1.5v3a2 2 0 0 1-2.2 2A16.8 16.8 0 0 1 4.6 5.7a2 2 0 0 1 2-2.2Z\"/>";
761
+ };
762
+ readonly 'phone-off': {
763
+ readonly vb: "0 0 24 24";
764
+ readonly d: "<g transform=\"rotate(135 12 12)\"><path d=\"M6.6 3.5h3l1.5 3.7-1.9 1.4a12.5 12.5 0 0 0 6.2 6.2l1.4-1.9 3.7 1.5v3a2 2 0 0 1-2.2 2A16.8 16.8 0 0 1 4.6 5.7a2 2 0 0 1 2-2.2Z\"/></g>";
765
+ };
780
766
  readonly pin: {
781
767
  readonly vb: "0 0 24 24";
782
768
  readonly d: "<path d=\"M9 3.4h6v1.8l-1 5.6 3 3.2H7l3-3.2-1-5.6V3.4Z\"/><path d=\"M12 17v3.6\"/>";
@@ -817,6 +803,14 @@ declare const ICONS: {
817
803
  readonly vb: "0 0 24 24";
818
804
  readonly d: "<path d=\"M4 7h9M17 7h3\"/><circle cx=\"15\" cy=\"7\" r=\"2.1\"/><path d=\"M4 17h3M11 17h9\"/><circle cx=\"9\" cy=\"17\" r=\"2.1\"/>";
819
805
  };
806
+ readonly speaker: {
807
+ readonly vb: "0 0 24 24";
808
+ readonly d: "<path d=\"M4 9.5h3.2L12 5.4v13.2L7.2 14.5H4a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1Z\"/><path d=\"M15.6 9.2a4 4 0 0 1 0 5.6\"/><path d=\"M18.2 6.6a7.7 7.7 0 0 1 0 10.8\"/>";
809
+ };
810
+ readonly 'speaker-off': {
811
+ readonly vb: "0 0 24 24";
812
+ readonly d: "<path d=\"M4 9.5h3.2L12 5.4v13.2L7.2 14.5H4a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1Z\"/><path d=\"M16.4 9.6 21.4 14.4\"/><path d=\"M21.4 9.6 16.4 14.4\"/>";
813
+ };
820
814
  readonly 'thumbs-up': {
821
815
  readonly vb: "0 0 24 24";
822
816
  readonly d: "<path d=\"M7 10.4V20H4.2V10.4Z\"/><path d=\"M7 10.4 11 3.2a2 2 0 0 1 1.9 2.2L12.4 9H18a2 2 0 0 1 2 2.4l-1.1 6A2 2 0 0 1 16.9 20H7\"/>";
@@ -841,6 +835,14 @@ declare const ICONS: {
841
835
  readonly vb: "0 0 24 24";
842
836
  readonly d: "<circle cx=\"9\" cy=\"8\" r=\"3.6\"/><path d=\"M2.6 20a6.4 6.4 0 0 1 12.8 0\"/><path d=\"M15.8 4.7a3.6 3.6 0 0 1 0 6.6\"/><path d=\"M17.6 20a6.4 6.4 0 0 0-3.1-5.5\"/>";
843
837
  };
838
+ readonly video: {
839
+ readonly vb: "0 0 24 24";
840
+ readonly d: "<rect x=\"2.6\" y=\"6\" width=\"13\" height=\"12\" rx=\"2.4\"/><path d=\"M15.6 11.2 21.4 8v8l-5.8-3.2Z\"/>";
841
+ };
842
+ readonly 'video-off': {
843
+ readonly vb: "0 0 24 24";
844
+ readonly d: "<rect x=\"2.6\" y=\"6\" width=\"13\" height=\"12\" rx=\"2.4\"/><path d=\"M15.6 11.2 21.4 8v8l-5.8-3.2Z\"/><path d=\"M3.6 3.2 20.4 20.8\"/>";
845
+ };
844
846
  readonly webhook: {
845
847
  readonly vb: "0 0 24 24";
846
848
  readonly d: "<circle cx=\"6\" cy=\"6\" r=\"2.6\"/><circle cx=\"18\" cy=\"9\" r=\"2.6\"/><circle cx=\"9.5\" cy=\"18\" r=\"2.6\"/><path d=\"M7.9 7.9 12 12l3.7-1.5\"/><path d=\"M11.6 12.7 9.8 16\"/>";
@@ -1115,6 +1117,107 @@ interface VoiceRoomBarProps {
1115
1117
  */
1116
1118
  declare function VoiceRoomBar({ conversationId, labelFor, unavailableSlot, webrtc, onStatusChange, }: VoiceRoomBarProps): react_jsx_runtime.JSX.Element;
1117
1119
 
1120
+ /**
1121
+ * The slice of `@livekit/react-native` this package uses.
1122
+ *
1123
+ * Passed in by the app rather than imported, for the same reason
1124
+ * `react-native-webrtc` is: tsup rewrites `require()` into
1125
+ * `__require()`, which Metro cannot follow, so anything this package
1126
+ * imports for itself never reaches a React Native bundle.
1127
+ *
1128
+ * import * as livekitRN from '@livekit/react-native';
1129
+ * <CallScreen livekitReactNative={livekitRN} … />
1130
+ *
1131
+ * Everything past `VideoTrack` is optional so an older version of the
1132
+ * module still type-checks — the features degrade rather than failing
1133
+ * to compile.
1134
+ */
1135
+
1136
+ /**
1137
+ * The slice of `VideoTrack` actually rendered.
1138
+ *
1139
+ * `LiveKitReactNativeModule.VideoTrack` is `unknown` because React props
1140
+ * are contravariant — declaring the narrow shape there means the real
1141
+ * component is not assignable to it and no app can pass the module in.
1142
+ * Narrowing happens at the point of use, through this.
1143
+ */
1144
+ type CheckedVideoTrack = ComponentType<{
1145
+ trackRef: unknown;
1146
+ style?: ViewStyle;
1147
+ objectFit?: 'cover' | 'contain';
1148
+ mirror?: boolean;
1149
+ zOrder?: number;
1150
+ }>;
1151
+ /** What an audio route is, once its platform id has been read. */
1152
+ type AudioRouteKind = 'speaker' | 'earpiece' | 'headset' | 'bluetooth' | 'auto';
1153
+ interface AudioRoute {
1154
+ /** Platform id, passed back to `selectAudioOutput`. */
1155
+ id: string;
1156
+ kind: AudioRouteKind;
1157
+ /** Human label for a picker row. */
1158
+ label: string;
1159
+ }
1160
+ /**
1161
+ * LiveKit's audio session.
1162
+ *
1163
+ * The two platforms expose genuinely different things and the shape
1164
+ * reflects that rather than papering over it:
1165
+ *
1166
+ * * **Android** enumerates real devices — `speaker`, `earpiece`,
1167
+ * `headset`, `bluetooth` — and `selectAudioOutput` picks one.
1168
+ * * **iOS** offers only `default` and `force_speaker`, because AVAudio
1169
+ * does not let an app pick a route directly. Anything else (AirPods,
1170
+ * a wired headset, AirPlay) goes through the system's own picker,
1171
+ * which is what `showAudioRoutePicker` opens.
1172
+ */
1173
+ interface LiveKitAudioSession {
1174
+ configureAudio(config: {
1175
+ android?: {
1176
+ preferredOutputList?: ('speaker' | 'earpiece' | 'headset' | 'bluetooth')[];
1177
+ audioTypeOptions?: unknown;
1178
+ };
1179
+ ios?: {
1180
+ defaultOutput?: 'speaker' | 'earpiece';
1181
+ };
1182
+ }): Promise<void>;
1183
+ startAudioSession(): Promise<void>;
1184
+ stopAudioSession(): Promise<void>;
1185
+ getAudioOutputs(): Promise<string[]>;
1186
+ selectAudioOutput(deviceId: string): Promise<void>;
1187
+ /** iOS 11+. Opens the system route picker (AirPods, AirPlay, …). */
1188
+ showAudioRoutePicker?(): Promise<void>;
1189
+ }
1190
+ /** Fires when a headset or Bluetooth device appears or disappears. */
1191
+ interface AudioDeviceModuleEvents {
1192
+ addDevicesUpdatedListener(listener: () => void): void;
1193
+ removeDevicesUpdatedListener(listener: () => void): void;
1194
+ }
1195
+ interface LiveKitReactNativeModule {
1196
+ /**
1197
+ * The module's `VideoTrack` component.
1198
+ *
1199
+ * Typed as `unknown` on purpose. Its real props are far more specific
1200
+ * than what this renders with, and React component props are
1201
+ * contravariant — declaring the narrow shape here means the real
1202
+ * component is not assignable to it and no app can pass the module in.
1203
+ * It is narrowed at the point of use.
1204
+ */
1205
+ VideoTrack: unknown;
1206
+ AudioSession?: LiveKitAudioSession | undefined;
1207
+ /**
1208
+ * Installs LiveKit's iOS audio policy and returns a disposer.
1209
+ *
1210
+ * Must not be re-run mid-call: it abandons the session activation the
1211
+ * previous handlers were holding, which kills audio outright. The
1212
+ * speaker preference is therefore captured once, when the call
1213
+ * starts, and later changes go through `selectAudioOutput` instead.
1214
+ */
1215
+ setupIOSAudioManagement?: ((preferSpeakerOutput?: boolean) => () => void) | undefined;
1216
+ audioDeviceModuleEvents?: AudioDeviceModuleEvents | undefined;
1217
+ }
1218
+ /** Turn a platform output id into something renderable. */
1219
+ declare function describeRoute(id: string): AudioRoute;
1220
+
1118
1221
  interface CallScreenProps {
1119
1222
  /** The signed-in user's id — the topic calls are delivered on. */
1120
1223
  userId: string;
@@ -1142,15 +1245,16 @@ interface CallScreenProps {
1142
1245
  */
1143
1246
  livekit?: LiveKitModule | null;
1144
1247
  /**
1145
- * `@livekit/react-native`, imported by your app. Required to *render*
1146
- * video; without it a video call still connects and carries audio, and
1147
- * every tile shows a placeholder.
1248
+ * `@livekit/react-native`, imported by your app.
1249
+ *
1250
+ * Required to *render* video, and also carries `AudioSession`, which
1251
+ * is what routes a call to the speaker, the earpiece or a headset.
1252
+ * Without it a call still connects and carries audio, every tile
1253
+ * shows an avatar, and routing falls to whatever the OS picks.
1148
1254
  */
1149
1255
  livekitReactNative?: LiveKitReactNativeModule | null;
1150
1256
  /**
1151
- * Called whenever the call's media connection state changes. Drive
1152
- * speakerphone and the proximity sensor from here — see
1153
- * {@link VoiceRoomBarProps.onStatusChange}.
1257
+ * Called whenever the call's media connection state changes.
1154
1258
  */
1155
1259
  onStatusChange?: (status: VoiceStatus) => void;
1156
1260
  /**
@@ -1165,17 +1269,11 @@ interface CallScreenProps {
1165
1269
  * only starts working after some unrelated engine change (turning the
1166
1270
  * camera on) makes LiveKit reapply its configuration.
1167
1271
  *
1168
- * So drive InCallManager from this, and only for `'mesh'`. The mesh
1169
- * has no session management of its own and still needs it.
1272
+ * So drive InCallManager from this, and only for `'mesh'`. On the SFU
1273
+ * path this component already owns the session, through LiveKit.
1170
1274
  */
1171
1275
  onTransportChange?: (transport: 'sfu' | 'mesh' | null) => void;
1172
- /**
1173
- * Called when the call's video state changes.
1174
- *
1175
- * A video call belongs on the speaker with the proximity sensor OFF —
1176
- * otherwise the screen blanks the moment the phone comes near your
1177
- * face, which is exactly when you are looking at it.
1178
- */
1276
+ /** Called when the call's video state changes. */
1179
1277
  onVideoChange?: (video: boolean) => void;
1180
1278
  /**
1181
1279
  * Hide this screen while a call is merely ringing in.
@@ -1195,7 +1293,11 @@ interface CallScreenProps {
1195
1293
  * Mount it once, high in the tree, so a call can arrive on any screen:
1196
1294
  *
1197
1295
  * <PoolseProvider config={config}>
1198
- * <CallScreen userId={me.id} livekit={livekit} livekitReactNative={livekitRN} />
1296
+ * <CallScreen
1297
+ * userId={me.id}
1298
+ * livekit={livekit}
1299
+ * livekitReactNative={livekitRN}
1300
+ * />
1199
1301
  * <YourApp />
1200
1302
  * </PoolseProvider>
1201
1303
  *
@@ -1212,6 +1314,310 @@ interface CallScreenProps {
1212
1314
  */
1213
1315
  declare function CallScreen({ userId, labelFor, calls: callsProp, webrtc, livekit, livekitReactNative, onStatusChange, onTransportChange, onVideoChange, nativeIncomingUi, }: CallScreenProps): react_jsx_runtime.JSX.Element;
1214
1316
 
1317
+ interface CallVideoGridProps {
1318
+ participants: CallParticipant[];
1319
+ /** `@livekit/react-native`, imported by your app. */
1320
+ livekitReactNative?: LiveKitReactNativeModule | null | undefined;
1321
+ /** Resolves a user id to a display label. */
1322
+ labelFor?: ((userId: string) => string) | undefined;
1323
+ /**
1324
+ * Tapping the local preview. Wired to the camera flip by
1325
+ * `CallScreen`, which is where every other call app puts it.
1326
+ */
1327
+ onLocalPress?: (() => void) | undefined;
1328
+ /**
1329
+ * How much chrome sits over the top and bottom of the stage, so the
1330
+ * floating preview does not park itself under the control bar.
1331
+ */
1332
+ chromeInsets?: {
1333
+ top: number;
1334
+ bottom: number;
1335
+ } | undefined;
1336
+ }
1337
+ /**
1338
+ * The stage: everyone on the call, laid out for how many there are.
1339
+ *
1340
+ * Three layouts, because one grid cannot serve all of them:
1341
+ *
1342
+ * * **Alone** — you, filling the screen, while the far side connects.
1343
+ * * **One other person** — them full-bleed, you in a draggable
1344
+ * corner tile. A 1:1 call split into two half-height boxes wastes
1345
+ * most of the screen on letterboxing, which is why no calling app
1346
+ * does it.
1347
+ * * **Three or more** — a real grid, two columns up to six people and
1348
+ * three beyond that, scrolling once the tiles would be too small to
1349
+ * make out a face.
1350
+ *
1351
+ * Audio calls land here too. Everyone simply has their camera off, so
1352
+ * every tile draws an avatar, and the layout logic does not need to
1353
+ * know whether video was ever on the table.
1354
+ */
1355
+ declare function CallVideoGrid({ participants, livekitReactNative, labelFor, onLocalPress, chromeInsets, }: CallVideoGridProps): react_jsx_runtime.JSX.Element;
1356
+
1357
+ interface CallControlButtonProps {
1358
+ icon: IconName;
1359
+ /** Shown under the button. Omit for the hang-up / answer buttons. */
1360
+ label?: string | undefined;
1361
+ /**
1362
+ * The control is doing something — muted, speaker forced on, camera
1363
+ * off. Inverts the button so engaged controls are readable at a
1364
+ * glance.
1365
+ */
1366
+ active?: boolean;
1367
+ /** Paints the button a solid colour: the hang-up and answer actions. */
1368
+ tone?: 'neutral' | 'danger' | 'accept';
1369
+ large?: boolean;
1370
+ disabled?: boolean;
1371
+ onPress: () => void;
1372
+ /**
1373
+ * Spoken description. Defaults to `label`, but a toggle needs to say
1374
+ * what pressing it will DO, which is rarely what the label says —
1375
+ * "Mute" under a button that unmutes is exactly backwards for anyone
1376
+ * using a screen reader.
1377
+ */
1378
+ accessibilityLabel?: string | undefined;
1379
+ }
1380
+ /**
1381
+ * One round call control.
1382
+ *
1383
+ * Fixed diameter and a caption underneath, so a row of them lines up on
1384
+ * a grid regardless of label length — the thing that makes a control
1385
+ * bar look built rather than assembled.
1386
+ */
1387
+ declare function CallControlButton({ icon, label, active, tone, large, disabled, onPress, accessibilityLabel, }: CallControlButtonProps): react_jsx_runtime.JSX.Element;
1388
+
1389
+ interface CallParticipantTileProps {
1390
+ participant: CallParticipant;
1391
+ /** Narrowed `@livekit/react-native` VideoTrack, when the app supplied it. */
1392
+ VideoTrack?: CheckedVideoTrack | undefined;
1393
+ label: (userId: string) => string;
1394
+ style?: ViewStyle | ViewStyle[];
1395
+ /** Avatar diameter when the camera is off. */
1396
+ avatarSize?: number;
1397
+ /** Full-bleed tiles drop their rounding and their name chip shrinks. */
1398
+ bleed?: boolean;
1399
+ /** Hide the name chip — the spotlight draws identity in the header. */
1400
+ hideName?: boolean;
1401
+ }
1402
+ /**
1403
+ * One person on the call: their video, or their avatar when the camera
1404
+ * is off.
1405
+ *
1406
+ * A camera-off participant still gets a tile. Dropping them would make
1407
+ * a five-person call with four cameras off look like a one-person call,
1408
+ * and hide the fact that they are there and can hear you.
1409
+ */
1410
+ declare function CallParticipantTile({ participant, VideoTrack, label, style, avatarSize, bleed, hideName, }: CallParticipantTileProps): react_jsx_runtime.JSX.Element;
1411
+
1412
+ interface CallAvatarProps {
1413
+ /** Display name; the first letters become the initials. */
1414
+ name: string;
1415
+ /** Stable colour seed — the poolse user id. */
1416
+ seed: string;
1417
+ size: number;
1418
+ /** Draw the active-speaker ring. */
1419
+ speaking?: boolean;
1420
+ }
1421
+ /**
1422
+ * The stand-in for a face when a camera is off.
1423
+ *
1424
+ * Separate from `<Avatar>` rather than a size variant of it: this one
1425
+ * scales to a third of the screen, carries the speaking ring, and lives
1426
+ * on a dark surface, none of which the list avatar wants.
1427
+ *
1428
+ * The ring sits OUTSIDE the circle, drawn as a border on a larger box.
1429
+ * Growing the avatar itself to show speaking would make everything jump
1430
+ * every time somebody starts talking.
1431
+ */
1432
+ declare function CallAvatar({ name, seed, size, speaking }: CallAvatarProps): react_jsx_runtime.JSX.Element;
1433
+
1434
+ interface LocalVideoPipProps {
1435
+ participant: CallParticipant;
1436
+ VideoTrack?: CheckedVideoTrack | undefined;
1437
+ label: (userId: string) => string;
1438
+ /** Area the tile may be dragged within, in pixels. */
1439
+ bounds: {
1440
+ width: number;
1441
+ height: number;
1442
+ };
1443
+ /** Inset from the edges — keeps the tile clear of the call chrome. */
1444
+ insets?: {
1445
+ top: number;
1446
+ bottom: number;
1447
+ };
1448
+ /** Tap handler. Wired to the camera flip, matching every other call app. */
1449
+ onPress?: (() => void) | undefined;
1450
+ }
1451
+ /**
1452
+ * The local camera preview, floating over the remote video.
1453
+ *
1454
+ * Draggable, and it snaps to the nearest corner on release rather than
1455
+ * staying wherever the finger stopped. Free positioning sounds more
1456
+ * flexible but reads as broken: a tile left at a slight angle to the
1457
+ * edge looks dropped rather than placed, and it is the corners people
1458
+ * actually want — they move it to uncover a face.
1459
+ *
1460
+ * Built on `Animated` + `PanResponder` from React Native itself. A
1461
+ * gesture library would be smoother, but it would be a new native
1462
+ * dependency for every app that installs this SDK, and a call preview
1463
+ * is not worth that.
1464
+ */
1465
+ declare function LocalVideoPip({ participant, VideoTrack, label, bounds, insets, onPress, }: LocalVideoPipProps): react_jsx_runtime.JSX.Element;
1466
+
1467
+ interface AudioRouteSheetProps {
1468
+ visible: boolean;
1469
+ routes: AudioRoute[];
1470
+ /** Platform id of the chosen route, or null while routing is automatic. */
1471
+ selectedRouteId: string | null;
1472
+ onSelect: (id: string) => void;
1473
+ onClose: () => void;
1474
+ }
1475
+ /**
1476
+ * Pick where call audio comes out.
1477
+ *
1478
+ * Only worth showing when there is a real choice — on iOS there are
1479
+ * exactly two entries and the system's own picker covers everything
1480
+ * else, so `CallScreen` opens that instead. This is the Android
1481
+ * surface, where LiveKit enumerates the actual devices.
1482
+ */
1483
+ declare function AudioRouteSheet({ visible, routes, selectedRouteId, onSelect, onClose, }: AudioRouteSheetProps): react_jsx_runtime.JSX.Element;
1484
+
1485
+ /**
1486
+ * The call surface's own palette.
1487
+ *
1488
+ * Deliberately NOT the app theme. Every serious calling app — phone,
1489
+ * FaceTime, WhatsApp, Meet — renders calls dark regardless of the rest
1490
+ * of the UI, for three reasons that all apply here:
1491
+ *
1492
+ * * video is the content, and a light chrome around it washes the
1493
+ * picture out,
1494
+ * * a call screen is the one surface that routinely opens at 3am,
1495
+ * * it takes over the whole screen, so it reads as a mode change
1496
+ * rather than as a screen that has lost the app's styling.
1497
+ *
1498
+ * The brand still shows up — in the accept button and the speaking
1499
+ * ring — it just doesn't set the background.
1500
+ */
1501
+ declare const callColors: {
1502
+ /** Behind everything. Near-black, warmed very slightly to match the brand. */
1503
+ readonly bg: "#101012";
1504
+ /** Behind a participant tile with no video. */
1505
+ readonly tile: "#1c1c20";
1506
+ /** Scrim under the top/bottom chrome so text stays legible over video. */
1507
+ readonly scrim: "rgba(0,0,0,0.45)";
1508
+ readonly text: "#ffffff";
1509
+ readonly textDim: "rgba(255,255,255,0.72)";
1510
+ readonly textFaint: "rgba(255,255,255,0.5)";
1511
+ /** A control that is off / inactive — translucent over whatever is behind. */
1512
+ readonly control: "rgba(255,255,255,0.16)";
1513
+ /**
1514
+ * A control that is ENGAGED (muted, speaker on, camera off).
1515
+ *
1516
+ * Inverted rather than tinted: at a glance the user needs to see
1517
+ * *which* controls are doing something, and a solid white circle is
1518
+ * unmistakable against five translucent ones in a dim room.
1519
+ */
1520
+ readonly controlActive: "#ffffff";
1521
+ readonly controlActiveIcon: "#101012";
1522
+ readonly danger: "#ef4444";
1523
+ readonly accept: "#22c55e";
1524
+ readonly onAction: "#ffffff";
1525
+ };
1526
+
1527
+ /**
1528
+ * How long the call has been connected, as `m:ss` (or `h:mm:ss`).
1529
+ *
1530
+ * Anchored to a timestamp rather than counting ticks: a phone that
1531
+ * sleeps or throttles timers would otherwise drift, and a call timer
1532
+ * that reads 4:12 after eleven minutes is worse than none. Returns null
1533
+ * until the call is actually up, so a ringing call shows its status
1534
+ * line instead of `0:00`.
1535
+ */
1536
+ declare function useCallDuration(connected: boolean): string | null;
1537
+
1538
+ interface UseCallAudioOptions {
1539
+ /**
1540
+ * True as soon as a call exists — ringing counts.
1541
+ *
1542
+ * Deliberately not "connected": the audio session has to be running
1543
+ * before LiveKit's audio engine starts, not after. Start it late and
1544
+ * the call connects, the roster is right, video flows, and no audio
1545
+ * is published in either direction.
1546
+ */
1547
+ active: boolean;
1548
+ /**
1549
+ * Whether the call is carrying video.
1550
+ *
1551
+ * Decides where audio goes by default — nobody holds a phone to their
1552
+ * ear while looking at the screen — and nothing else. Read once, when
1553
+ * the call starts; see {@link LiveKitReactNativeModule.setupIOSAudioManagement}
1554
+ * for why it cannot be re-applied mid-call.
1555
+ */
1556
+ video: boolean;
1557
+ /** `@livekit/react-native`, imported by your app. */
1558
+ livekitReactNative?: LiveKitReactNativeModule | null | undefined;
1559
+ }
1560
+ interface CallAudio {
1561
+ /** Audio is coming out of the loudspeaker. */
1562
+ speakerOn: boolean;
1563
+ toggleSpeaker: () => void;
1564
+ setSpeaker: (on: boolean) => void;
1565
+ /** Every route that can be picked right now. */
1566
+ routes: AudioRoute[];
1567
+ /**
1568
+ * The selected route's platform id, or `null` while routing is
1569
+ * automatic — which is the normal state until the user picks
1570
+ * something. Automatic means the OS follows the preference order the
1571
+ * call was configured with, so plugging in a headset just works.
1572
+ */
1573
+ selectedRouteId: string | null;
1574
+ selectRoute: (id: string) => void;
1575
+ /**
1576
+ * A headset, AirPods or car kit is connected.
1577
+ *
1578
+ * Worth surfacing because it changes what the speaker button means:
1579
+ * with a headset attached, "off" routes to the headset rather than to
1580
+ * the earpiece.
1581
+ *
1582
+ * Android only, and honestly so — iOS reports just `default` and
1583
+ * `force_speaker` from `getAudioOutputs`, with no way to ask what
1584
+ * `default` currently resolves to. On iOS this stays `false` and the
1585
+ * system route picker is the way to see and change the real device.
1586
+ */
1587
+ externalDevice: boolean;
1588
+ /**
1589
+ * The system route picker can be opened. iOS only — Android
1590
+ * enumerates its devices in {@link routes} instead.
1591
+ */
1592
+ canPickSystemRoute: boolean;
1593
+ openSystemRoutePicker: () => void;
1594
+ }
1595
+ /**
1596
+ * Owns the audio session for an SFU-backed call, and the routing on top
1597
+ * of it.
1598
+ *
1599
+ * ## Why this is not `react-native-incall-manager`
1600
+ *
1601
+ * `registerGlobals()` from `@livekit/react-native` drives AVAudioSession
1602
+ * natively off its own audio engine's state. Anything else driving the
1603
+ * session at the same time fights it, and the symptom is brutal: the
1604
+ * microphone captures nothing, and audio only starts working after some
1605
+ * unrelated engine change — turning the camera on, say — makes LiveKit
1606
+ * reapply its configuration. So InCallManager is reserved for the
1607
+ * peer-to-peer mesh, which has no session management of its own.
1608
+ *
1609
+ * ## What "default" means on each platform
1610
+ *
1611
+ * Android is handed a `preferredOutputList` and picks the best
1612
+ * available device itself, so a connected headset wins without the app
1613
+ * detecting anything. iOS is given `defaultOutput`, which LiveKit
1614
+ * documents as the output to use *when a wired headset or Bluetooth
1615
+ * output is unavailable* — same effect, same reason: an app that forced
1616
+ * the speaker on a video call would yank audio out of the user's
1617
+ * AirPods every time.
1618
+ */
1619
+ declare function useCallAudio({ active, video, livekitReactNative, }: UseCallAudioOptions): CallAudio;
1620
+
1215
1621
  /**
1216
1622
  * Bridges iOS PushKit + CallKit to poolse calls, and owns the incoming
1217
1623
  * call UI end to end.
@@ -1350,4 +1756,4 @@ declare function isStalePush(sentAt: number | undefined, now: number, staleAfter
1350
1756
  */
1351
1757
  declare function useVoipCalls({ voipPush, callKeep, calls, onAnswer, onDecline, appName, apnsEnvironment, staleAfterMs, }: UseVoipCallsOptions): void;
1352
1758
 
1353
- export { AttachmentPicker, type AttachmentPickerProps, AttachmentPreview, type AttachmentPreviewProps, Avatar, type AvatarProps, type CallKeepModule, CallScreen, type CallScreenProps, CallVideoGrid, type CallVideoGridProps, ChatHeader, type ChatHeaderProps, ConversationList, type ConversationListProps, ConversationView, type ConversationViewProps, DaySeparator, type DaySeparatorProps, GroupDetailsSheet, type GroupDetailsSheetProps, type IconName, ImageMosaic, type ImageMosaicProps, type InboxUser, type LiveKitReactNativeModule, MemberList, type MemberListProps, MentionInput, type MentionInputProps, MessageActions, type MessageActionsProps, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerProps, MessageList, type MessageListItem, type MessageListProps, MessageRow, type MessageRowProps, type NativeWebRtcModule, PoolseIcon, type PoolseIconProps, PoolseInbox, type PoolseInboxHandle, type PoolseInboxProps, PoolseLogo, type PoolseLogoProps, type PoolseLogoVariant, type PoolseRNTheme, type PoolseRNThemeOverrides, PoolseTheme, type PoolseThemeProps, primitives as Primitives, ReactionPicker, type ReactionPickerProps, ReactionStrip, type ReactionStripProps, type ThemeColors, type ThemeRadii, type ThemeShadows, type ThemeSpacing, type ThemeType, ThreadView, type ThreadViewProps, TypingIndicator, type TypingIndicatorProps, UploadQueueStrip, type UseVoipCallsOptions, UserName, type UserNameProps, VoiceRoomBar, type VoiceRoomBarProps, type VoipIncomingCall, type VoipPushModule, createNativeWebRtcAdapter, defaultDarkTheme, defaultLightTheme, isNativeWebRtcAvailable, isStalePush, useAppStateLifecycle, useDisplayName, usePoolseTheme, useVoipCalls };
1759
+ export { AttachmentPicker, type AttachmentPickerProps, AttachmentPreview, type AttachmentPreviewProps, type AudioRoute, type AudioRouteKind, AudioRouteSheet, type AudioRouteSheetProps, Avatar, type AvatarProps, type CallAudio, CallAvatar, type CallAvatarProps, CallControlButton, type CallControlButtonProps, type CallKeepModule, CallParticipantTile, type CallParticipantTileProps, CallScreen, type CallScreenProps, CallVideoGrid, type CallVideoGridProps, ChatHeader, type ChatHeaderProps, ConversationList, type ConversationListProps, ConversationView, type ConversationViewProps, DaySeparator, type DaySeparatorProps, GroupDetailsSheet, type GroupDetailsSheetProps, type IconName, ImageMosaic, type ImageMosaicProps, type InboxUser, type LiveKitAudioSession, type LiveKitReactNativeModule, LocalVideoPip, type LocalVideoPipProps, MemberList, type MemberListProps, MentionInput, type MentionInputProps, MessageActions, type MessageActionsProps, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerProps, MessageList, type MessageListItem, type MessageListProps, MessageRow, type MessageRowProps, type NativeWebRtcModule, PoolseIcon, type PoolseIconProps, PoolseInbox, type PoolseInboxHandle, type PoolseInboxProps, PoolseLogo, type PoolseLogoProps, type PoolseLogoVariant, type PoolseRNTheme, type PoolseRNThemeOverrides, PoolseTheme, type PoolseThemeProps, primitives as Primitives, ReactionPicker, type ReactionPickerProps, ReactionStrip, type ReactionStripProps, type ThemeColors, type ThemeRadii, type ThemeShadows, type ThemeSpacing, type ThemeType, ThreadView, type ThreadViewProps, TypingIndicator, type TypingIndicatorProps, UploadQueueStrip, type UseCallAudioOptions, type UseVoipCallsOptions, UserName, type UserNameProps, VoiceRoomBar, type VoiceRoomBarProps, type VoipIncomingCall, type VoipPushModule, callColors, createNativeWebRtcAdapter, defaultDarkTheme, defaultLightTheme, describeRoute, isNativeWebRtcAvailable, isStalePush, useAppStateLifecycle, useCallAudio, useCallDuration, useDisplayName, usePoolseTheme, useVoipCalls };