@pickleball/expo-sdk 0.1.1 → 0.2.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 (74) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +69 -0
  3. package/dist/advanced-BXDrDl1h.d.ts +316 -0
  4. package/dist/advanced-BdAa2Erv.d.cts +316 -0
  5. package/dist/advanced.cjs +35 -0
  6. package/dist/advanced.d.cts +3 -0
  7. package/dist/advanced.d.ts +3 -0
  8. package/dist/advanced.js +35 -0
  9. package/dist/chunk-2JHULJZ7.js +265 -0
  10. package/dist/chunk-6JOMESNT.js +9 -0
  11. package/dist/chunk-7OX2DSKI.cjs +33 -0
  12. package/dist/chunk-DHDX3ZOO.js +800 -0
  13. package/dist/chunk-FODE2W2H.js +1953 -0
  14. package/dist/chunk-KFQGP6VL.js +33 -0
  15. package/dist/chunk-LCWGNGEN.cjs +265 -0
  16. package/dist/chunk-TBPR2QND.cjs +1953 -0
  17. package/dist/chunk-TRLASNPQ.cjs +9 -0
  18. package/dist/chunk-YGSQ25UA.cjs +800 -0
  19. package/dist/device-agent/index.cjs +498 -0
  20. package/dist/device-agent/index.d.cts +157 -0
  21. package/dist/device-agent/index.d.ts +157 -0
  22. package/dist/device-agent/index.js +498 -0
  23. package/dist/engine-CCSSqPbZ.d.cts +516 -0
  24. package/dist/engine-CCSSqPbZ.d.ts +516 -0
  25. package/dist/index.cjs +339 -5569
  26. package/dist/index.d.cts +22 -1406
  27. package/dist/index.d.ts +22 -1406
  28. package/dist/index.js +269 -5401
  29. package/dist/match/index.cjs +2456 -0
  30. package/dist/match/index.d.cts +253 -0
  31. package/dist/match/index.d.ts +253 -0
  32. package/dist/match/index.js +2456 -0
  33. package/dist/match/remote/index.cjs +21 -0
  34. package/dist/match/remote/index.d.cts +67 -0
  35. package/dist/match/remote/index.d.ts +67 -0
  36. package/dist/match/remote/index.js +21 -0
  37. package/dist/match/voice/index.cjs +23 -0
  38. package/dist/match/voice/index.d.cts +114 -0
  39. package/dist/match/voice/index.d.ts +114 -0
  40. package/dist/match/voice/index.js +23 -0
  41. package/dist/plugin.cjs +53 -70
  42. package/dist/plugin.d.cts +13 -0
  43. package/dist/plugin.d.ts +13 -0
  44. package/dist/plugin.js +20 -15
  45. package/dist/types-CrmcX408.d.cts +176 -0
  46. package/dist/types-CrmcX408.d.ts +176 -0
  47. package/dist/types-DiKWjwvN.d.cts +96 -0
  48. package/dist/types-DiKWjwvN.d.ts +96 -0
  49. package/dist/version.cjs +4 -32
  50. package/dist/version.js +2 -1
  51. package/package.json +68 -4
  52. package/src/advanced.ts +47 -0
  53. package/src/device-agent/agent.ts +443 -0
  54. package/src/device-agent/component.tsx +49 -0
  55. package/src/device-agent/convex-control-channel.ts +82 -0
  56. package/src/device-agent/http-transport.ts +143 -0
  57. package/src/device-agent/index.ts +4 -0
  58. package/src/engine.ts +21 -5
  59. package/src/errors.ts +16 -0
  60. package/src/http-session-provider.ts +19 -13
  61. package/src/index.ts +38 -14
  62. package/src/livekit-room-adapter.ts +39 -2
  63. package/src/livestream-screen.tsx +26 -4
  64. package/src/match/index.ts +29 -0
  65. package/src/match/provider.tsx +4 -2
  66. package/src/match/remote/hid-gesture.ts +10 -2
  67. package/src/match/remote/types.ts +6 -4
  68. package/src/match/voice/scheduler.ts +6 -1
  69. package/src/match/voice/service.ts +16 -4
  70. package/src/native-runtime.ts +54 -4
  71. package/src/plugin.ts +35 -14
  72. package/src/provider.tsx +35 -4
  73. package/src/rtmp-room-adapter.ts +196 -0
  74. package/dist/chunk-VHLUJQG5.js +0 -17
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @pickleball/expo-sdk
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes (BREAKING — modular subpath split)
6
+
7
+ - Root entry (`@pickleball/expo-sdk`) is now the lean livestream core only:
8
+ `PickleballLiveProvider`, `useLivestream`, `LivestreamScreen`,
9
+ `createHttpSessionProvider`, `createDefaultStorage`, contracts, errors, version.
10
+ - Feature clusters moved to subpaths (Metro does not tree-shake — import only
11
+ what the app uses): `@pickleball/expo-sdk/match`, `/match/voice`,
12
+ `/match/remote`, `/device-agent`, `/advanced` (engine internals, DI, mocks).
13
+ - `PickleballLiveProvider` no longer accepts the `deviceAgent` prop. Mount
14
+ `<PickleballDeviceAgent/>` (from `/device-agent`) inside the provider instead —
15
+ this keeps `convex` out of the bundle for apps that never use remote control.
16
+ - Config plugin: new `modules: { remote?: boolean; voice?: boolean }` props.
17
+ `modules.remote: false` drops the Bluetooth permissions/purpose string and the
18
+ MainActivity HID patch. To strip the native modules from the binary entirely,
19
+ exclude `@pickleball/voice-native` / `@pickleball/remote-native` via
20
+ `expo.autolinking.exclude` (see README).
21
+ - Removed unused `expo-speech` dependency.
22
+
23
+ Migration 0.1 → 0.2: imports of match/voice/remote/device-agent/engine symbols
24
+ move from the root barrel to the matching subpath; `deviceAgent` prop becomes
25
+ `<PickleballDeviceAgent/>`.
26
+
3
27
  ## 0.1.1
4
28
 
5
29
  ### Patch Changes
package/README.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  Foreground livestreaming for Expo iOS and Android, with a headless state-machine API and a ready-made recording screen. Every successful session uses server-side recording.
4
4
 
5
+ ## Modules (v0.2 — subpath split)
6
+
7
+ The root entry is the lean livestream core. Every other feature lives on its own
8
+ subpath — **Metro does not tree-shake, so only import the subpaths your app
9
+ actually uses**:
10
+
11
+ | Import | Contents | Extra runtime deps |
12
+ |---|---|---|
13
+ | `@pickleball/expo-sdk` | `PickleballLiveProvider`, `useLivestream`, `LivestreamScreen`, `createHttpSessionProvider`, `createDefaultStorage`, contracts, errors | LiveKit (core) |
14
+ | `@pickleball/expo-sdk/match` | Match scoreboard: `PickleballMatchProvider`, `usePickleballMatch`, scoring engine, SQLite persistence | `expo-sqlite` |
15
+ | `@pickleball/expo-sdk/match/voice` | Offline score announcer (VI/EN) + TTS | `@pickleball/voice-native`, `expo-audio` |
16
+ | `@pickleball/expo-sdk/match/remote` | BLE/HID court remote input | `@pickleball/remote-native`, Bluetooth permissions |
17
+ | `@pickleball/expo-sdk/device-agent` | Device registry + dashboard remote control (`PickleballDeviceAgent`) | `convex` (bundled only via this subpath) |
18
+ | `@pickleball/expo-sdk/advanced` | `LivestreamEngine`, DI interfaces (`RoomAdapter`, `TelemetrySink`…), default runtime factories, `LiveKitRoomAdapter` — for mocks/tests/custom wiring | — |
19
+
20
+ Migration from 0.1: symbols that used to come from the root barrel now import
21
+ from the matching subpath above; the provider's `deviceAgent` prop was replaced
22
+ by mounting `<PickleballDeviceAgent/>` (from `/device-agent`) inside the
23
+ provider.
24
+
5
25
  ## Native requirements
6
26
 
7
27
  This package requires an Expo Development Build. Expo Go and web are intentionally unsupported because LiveKit needs native WebRTC modules. Supported Expo SDK range: `>=56 <58`.
@@ -30,6 +50,33 @@ manually. The permission set follows the native requirements documented by the
30
50
  MIT-licensed LiveKit React Native/WebRTC projects; this package does not bundle
31
51
  the community `@config-plugins/react-native-webrtc` plugin.
32
52
 
53
+ ### Slimming the native footprint
54
+
55
+ If the app never uses the BLE/HID court remote, disable its native config so
56
+ the build drops the Bluetooth permissions, the iOS Bluetooth purpose string,
57
+ and the MainActivity key-event patch:
58
+
59
+ ```json
60
+ ["@pickleball/expo-sdk", { "modules": { "remote": false } }]
61
+ ```
62
+
63
+ `modules.voice` is accepted for forward compatibility (microphone/audio
64
+ permissions belong to livestreaming, so it currently gates nothing).
65
+
66
+ To strip the unused native modules from the binary entirely, exclude them from
67
+ autolinking in the **app's** `package.json` — safe only if the app never
68
+ activates voice playback or remote scanning at runtime:
69
+
70
+ ```json
71
+ {
72
+ "expo": {
73
+ "autolinking": {
74
+ "exclude": ["@pickleball/voice-native", "@pickleball/remote-native"]
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
33
80
  ## Usage
34
81
 
35
82
  ```tsx
@@ -73,3 +120,25 @@ Production proxy URLs must use HTTPS; plain HTTP is accepted only for loopback d
73
120
  Tokens stay in memory. The only persisted value is a bounded `{sessionId, pendingEnd}` record used to finish a session after connectivity returns. Remote policy can change data and flags, but native changes require a semver release and a rebuilt app.
74
121
 
75
122
  For custom UI, use `useLivestream()` and its `prepare`, `start`, `stop`, `retry`, `switchCamera`, and `setMicrophoneEnabled` actions. `LivestreamScreen` supports Vietnamese/English copy, theme tokens, and preview/header/controls/error render overrides.
123
+
124
+ ## Optional: dashboard remote control
125
+
126
+ Opt in to device registry + remote start/stop from the operator dashboard by
127
+ mounting `PickleballDeviceAgent` inside the provider (this is the only place
128
+ that pulls the `convex` client into the bundle):
129
+
130
+ ```tsx
131
+ import {
132
+ PickleballDeviceAgent,
133
+ createHttpDeviceAgentTransport,
134
+ } from "@pickleball/expo-sdk/device-agent";
135
+
136
+ <PickleballLiveProvider sessionProvider={sessionProvider} bootstrapInput={identity}>
137
+ <PickleballDeviceAgent
138
+ transport={createHttpDeviceAgentTransport({ baseUrl: proxyUrl, headers })}
139
+ remoteStart={{ consentVersion: "2026-01", defaultTitle: "Court 1" }}
140
+ onRemoteSessionStarted={(sessionId) => router.push("/livestream")}
141
+ />
142
+ {children}
143
+ </PickleballLiveProvider>
144
+ ```
@@ -0,0 +1,316 @@
1
+ import { j as RoomAdapter, C as CameraDeviceInfo, V as RoomConnection, W as RoomEvent, a as CaptureOrientation, X as EngineDependencies, p as SdkNetwork, r as SdkRuntime, u as SdkStorage, T as TelemetrySink, Q as LivestreamEngine, B as BootstrapInput, g as LivestreamSnapshot, S as StartLivestreamInput, c as EndReason, L as LivestreamSessionProvider, i as PickleballExpoError } from './engine-CCSSqPbZ.js';
2
+ import React, { ReactNode } from 'react';
3
+
4
+ interface LocalTrackLike {
5
+ kind: string;
6
+ stop(): void;
7
+ mute?(): Promise<unknown>;
8
+ unmute?(): Promise<unknown>;
9
+ /** livekit-client LocalVideoTrack restart; deterministic facing switch. */
10
+ restartTrack?(options: {
11
+ facingMode?: "user" | "environment";
12
+ deviceId?: string;
13
+ resolution?: {
14
+ width: number;
15
+ height: number;
16
+ frameRate: number;
17
+ };
18
+ }): Promise<unknown>;
19
+ mediaStreamTrack?: {
20
+ readyState?: string;
21
+ /**
22
+ * react-native-webrtc: đổi thiết bị/facing TẠI CHỖ trên cùng track native
23
+ * (mediaStreamTrackApplyConstraints) — preview và sender giữ nguyên.
24
+ */
25
+ applyConstraints?(constraints: {
26
+ facingMode?: "user" | "environment";
27
+ deviceId?: string;
28
+ width?: number;
29
+ height?: number;
30
+ frameRate?: number;
31
+ }): Promise<void>;
32
+ /** react-native-webrtc native camera flip; blind front/back toggle. */
33
+ _switchCamera?(): void;
34
+ };
35
+ }
36
+ interface RoomLike {
37
+ state: string;
38
+ localParticipant: {
39
+ publishTrack(track: LocalTrackLike, options?: unknown): Promise<unknown>;
40
+ unpublishTrack?(track: LocalTrackLike, stopOnUnpublish?: boolean): Promise<unknown> | unknown;
41
+ };
42
+ connect(serverUrl: string, token: string, options?: unknown): Promise<void>;
43
+ disconnect(stopTracks?: boolean): Promise<void>;
44
+ on(event: string, listener: (...args: unknown[]) => void): unknown;
45
+ off(event: string, listener: (...args: unknown[]) => void): unknown;
46
+ }
47
+ interface NativeLiveKitBindings {
48
+ registerGlobals(): void;
49
+ createRoom(): RoomLike;
50
+ createLocalTracks(options: {
51
+ audio: true;
52
+ video: {
53
+ facingMode?: "user" | "environment";
54
+ deviceId?: string;
55
+ resolution: {
56
+ width: number;
57
+ height: number;
58
+ frameRate: number;
59
+ };
60
+ };
61
+ }): Promise<LocalTrackLike[]>;
62
+ startAudioSession(): Promise<void> | void;
63
+ stopAudioSession(): Promise<void> | void;
64
+ /** Current window orientation; capture dimensions follow it. */
65
+ isLandscape?(): boolean;
66
+ /** Physical/virtual cameras reported by the platform. */
67
+ listCameras?(): Promise<CameraDeviceInfo[]>;
68
+ cameraSource?: unknown;
69
+ events: {
70
+ reconnecting: string;
71
+ reconnected: string;
72
+ disconnected: string;
73
+ mediaDevicesError: string;
74
+ /** LiveKit RoomEvent.DataReceived — nhận lệnh điều khiển từ dashboard. */
75
+ dataReceived?: string;
76
+ };
77
+ }
78
+ interface LocalPreviewReference {
79
+ videoTrack: unknown;
80
+ trackRef?: {
81
+ participant: RoomLike["localParticipant"];
82
+ publication: unknown;
83
+ source?: unknown;
84
+ };
85
+ }
86
+ declare class LiveKitRoomAdapter implements RoomAdapter {
87
+ private readonly bindings;
88
+ private readonly room;
89
+ private readonly listeners;
90
+ private tracks;
91
+ private videoTrack?;
92
+ private audioTrack?;
93
+ private preview?;
94
+ private isFront;
95
+ private orientationOverride;
96
+ private deviceOverride;
97
+ private published;
98
+ private disposed;
99
+ private quality;
100
+ private readonly nativeListeners;
101
+ constructor(bindings: NativeLiveKitBindings);
102
+ preparePreview(quality: 720 | 1080): Promise<LocalPreviewReference | undefined>;
103
+ connect(input: RoomConnection): Promise<void>;
104
+ /** Bật/tắt publish track khi đã trong phòng — standby ↔ live. */
105
+ setPublishing(enabled: boolean): Promise<void>;
106
+ disconnect(stopTracks?: boolean): Promise<void>;
107
+ private captureResolution;
108
+ /**
109
+ * Tùy chọn publish video. Mặc định của livekit-client (VP8, không encoding,
110
+ * không degradation preference) khiến uplink yếu bóp bitrate xuống ~600kbps
111
+ * mà VẪN giữ 1080 @ ~10fps → khối bể nát, tệ hơn 720p sạch.
112
+ *
113
+ * - videoCodec H.264: HW-encode trên Android, hiệu quả hơn VP8 ở bitrate thấp,
114
+ * trùng preset egress (H264_*) nên bỏ được 1 lần transcode phía egress.
115
+ * - simulcast tắt: viewer chỉ xem HLS do egress xuất; egress subscribe đúng
116
+ * 1 lớp đã publish, nên simulcast chỉ thêm tải/bất ổn encoder (H.264 simulcast
117
+ * kém tin cậy trên Android) mà không lợi gì cho người xem ở kiến trúc này.
118
+ * - maintain-framerate: pickleball chuyển động nhanh; khi uplink không gánh nổi
119
+ * mức đích thì HẠ ĐỘ PHÂN GIẢI (giữ nét-trên-điểm-ảnh) thay vì đóng băng fps.
120
+ * - maxBitrate: trần theo mức chất lượng; BWE vẫn tự hạ dưới trần khi mạng yếu.
121
+ */
122
+ private videoPublishOptions;
123
+ setCaptureOrientation(orientation: "portrait" | "landscape"): Promise<void>;
124
+ /**
125
+ * livekit-client restart() chỉ giữ deviceId/facingMode khi gọi getUserMedia
126
+ * (vứt width/height/frameRate) nên track mới rơi về format mặc định
127
+ * 640x480. Native applyConstraints thì ngược lại: chỉ xử lý
128
+ * width/height/frameRate. Sau mỗi restartTrack phải nắn lại format trên
129
+ * track mới bằng applyConstraints.
130
+ */
131
+ private reapplyCaptureFormat;
132
+ switchCamera(): Promise<void>;
133
+ listCameras(): Promise<CameraDeviceInfo[]>;
134
+ selectCamera(deviceId: string, facing: CameraDeviceInfo["facing"]): Promise<void>;
135
+ setMicrophoneEnabled(enabled: boolean): Promise<void>;
136
+ subscribe(listener: (event: RoomEvent) => void): () => boolean;
137
+ dispose(): Promise<void>;
138
+ private releaseTracks;
139
+ private ensurePreparedTracks;
140
+ private emit;
141
+ private ensureNotDisposed;
142
+ }
143
+
144
+ /**
145
+ * Trạng thái từ tầng RTMP native (trùng NativeRtmpStatus của @pickleball/rtmp-native).
146
+ */
147
+ type RtmpStatus = {
148
+ readonly status: "idle" | "connecting" | "connected" | "publishing";
149
+ } | {
150
+ readonly status: "disconnected";
151
+ readonly reason?: string;
152
+ } | {
153
+ readonly status: "error";
154
+ readonly code: string;
155
+ readonly message: string;
156
+ };
157
+ /**
158
+ * Dấu hiệu để UI biết render nguồn nào. LiveKit trả về một track object; RTMP
159
+ * không có "track" ở JS (khung hình đi thẳng trong native), nên trả marker này
160
+ * — nếu trả undefined thì UI tưởng chưa có preview và vẽ màn TỐI ĐEN.
161
+ */
162
+ interface RtmpPreviewMarker {
163
+ readonly kind: "rtmp";
164
+ }
165
+ /** Bề mặt native mà adapter cần — tiêm vào để test được không cần thiết bị thật. */
166
+ interface NativeRtmpBindings {
167
+ prepare(options: {
168
+ quality: 720 | 1080;
169
+ landscape: boolean;
170
+ }): Promise<void>;
171
+ /** Hướng cầm máy hiện tại — cùng nguồn mà LiveKitRoomAdapter dùng. */
172
+ isLandscape?(): boolean;
173
+ connect(options: {
174
+ url: string;
175
+ videoBitrate: number;
176
+ publish: boolean;
177
+ }): Promise<void>;
178
+ setPublishing(enabled: boolean): Promise<void>;
179
+ disconnect(): Promise<void>;
180
+ switchCamera(): Promise<void>;
181
+ listCameras(): Array<{
182
+ deviceId: string;
183
+ label: string;
184
+ facing: string;
185
+ }>;
186
+ selectCamera(deviceId: string, facing: string): Promise<void>;
187
+ setMicrophoneEnabled(enabled: boolean): Promise<void>;
188
+ setVideoBitrate(bitsPerSecond: number): Promise<void>;
189
+ dispose(): Promise<void>;
190
+ addStatusListener(listener: (event: RtmpStatus) => void): {
191
+ remove(): void;
192
+ };
193
+ }
194
+ /**
195
+ * Adapter cho mode deliveryMode="device-rtmp".
196
+ *
197
+ * Thiết bị mã hoá H.264 bằng phần cứng MỘT lần rồi đẩy thẳng RTMP; server chỉ
198
+ * remux sang HLS. Không có phòng LiveKit, không egress → $0 transcode.
199
+ *
200
+ * Khác LiveKitRoomAdapter ở một điểm quan trọng: RTMP **không có kênh dữ liệu**,
201
+ * nên adapter này không bao giờ phát RoomEvent "command". Lệnh điều khiển từ
202
+ * dashboard đi đường khác (deviceControl trên Convex) — xem device-agent.
203
+ */
204
+ declare class RtmpRoomAdapter implements RoomAdapter {
205
+ private readonly bindings;
206
+ private readonly listeners;
207
+ private nativeSubscription?;
208
+ private quality;
209
+ private connected;
210
+ constructor(bindings: NativeRtmpBindings);
211
+ preparePreview(quality: 720 | 1080): Promise<RtmpPreviewMarker>;
212
+ connect(input: RoomConnection): Promise<void>;
213
+ setPublishing(enabled: boolean): Promise<void>;
214
+ disconnect(_stopTracks?: boolean): Promise<void>;
215
+ switchCamera(): Promise<void>;
216
+ /** Ống kính vật lý (0.5x siêu rộng · 1x · tele) — không có thì UI kẹt ở mặc định. */
217
+ listCameras(): Promise<CameraDeviceInfo[]>;
218
+ selectCamera(deviceId: string, facing: CameraDeviceInfo["facing"]): Promise<void>;
219
+ setMicrophoneEnabled(enabled: boolean): Promise<void>;
220
+ /** Hạ chất lượng khi mạng yếu — thay cho BWE mà WebRTC cho sẵn. */
221
+ setVideoBitrate(bitsPerSecond: number): Promise<void>;
222
+ setCaptureOrientation(_orientation: CaptureOrientation): Promise<void>;
223
+ subscribe(listener: (event: RoomEvent) => void): () => void;
224
+ dispose(): Promise<void>;
225
+ private emit;
226
+ }
227
+
228
+ declare function createNativeLiveKitBindings(): NativeLiveKitBindings;
229
+ declare function createDefaultRuntime(): SdkRuntime;
230
+ declare function createDefaultStorage(): SdkStorage;
231
+ declare function createDefaultNetwork(): SdkNetwork;
232
+ declare function createDefaultTelemetry(fetchImplementation?: typeof fetch, timeoutMs?: number): TelemetrySink;
233
+ declare function createDefaultRoomFactory(): EngineDependencies["roomFactory"];
234
+ /**
235
+ * Bindings cho mode device-rtmp. `require` động giống LiveKit ở trên: app nào
236
+ * không cài @pickleball/rtmp-native thì chỉ lỗi khi thật sự chọn mode này,
237
+ * không gãy lúc import SDK.
238
+ */
239
+ declare function createNativeRtmpBindings(): NativeRtmpBindings;
240
+ /** roomFactory cho mode device-rtmp (thiết bị đẩy RTMP, không dùng LiveKit). */
241
+ declare function createRtmpRoomFactory(): EngineDependencies["roomFactory"];
242
+ /**
243
+ * Thu chỉ số thiết bị cho heartbeat. Mỗi nguồn là optional — thiếu package
244
+ * (expo-battery/expo-device/expo-file-system) thì bỏ qua trường đó thay vì lỗi.
245
+ */
246
+ declare function createDefaultDeviceMetrics(): NonNullable<EngineDependencies["deviceMetrics"]>;
247
+
248
+ interface LivestreamTheme {
249
+ background: string;
250
+ foreground: string;
251
+ accent: string;
252
+ danger: string;
253
+ /** Chữ phụ mờ nhất (labels, chú thích). */
254
+ muted: string;
255
+ overlay: string;
256
+ radius: number;
257
+ /** Token FintechX — đồng bộ với dashboard web. */
258
+ surface: string;
259
+ elevated: string;
260
+ hairline: string;
261
+ /** Màu chữ đặt trên nền accent. */
262
+ ink: string;
263
+ textSecondary: string;
264
+ radiusSm: number;
265
+ fontFamily?: string;
266
+ fontFamilyBold?: string;
267
+ displayFontFamily?: string;
268
+ }
269
+ /** FintechX design tokens — trùng bộ token trong apps/web/globals.css. */
270
+ declare const defaultLivestreamTheme: LivestreamTheme;
271
+ interface PickleballLiveProviderProps {
272
+ children?: ReactNode;
273
+ sessionProvider: LivestreamSessionProvider;
274
+ bootstrapInput: BootstrapInput;
275
+ runtime?: SdkRuntime;
276
+ storage?: SdkStorage;
277
+ network?: SdkNetwork;
278
+ telemetry?: TelemetrySink;
279
+ roomFactory?: () => RoomAdapter;
280
+ deviceMetrics?: EngineDependencies["deviceMetrics"];
281
+ theme?: Partial<LivestreamTheme>;
282
+ locale?: "vi" | "en";
283
+ onError?: (error: PickleballExpoError) => void;
284
+ }
285
+ /**
286
+ * Context nội bộ cho các module opt-in (VD PickleballDeviceAgent) cần truy cập
287
+ * engine trực tiếp — export qua "./advanced", không thuộc API tích hợp cơ bản.
288
+ */
289
+ interface LivestreamHostContextValue {
290
+ engine: LivestreamEngine;
291
+ bootstrapInput: BootstrapInput;
292
+ deviceMetrics: NonNullable<EngineDependencies["deviceMetrics"]>;
293
+ }
294
+ declare function useLivestreamHost(): LivestreamHostContextValue;
295
+ interface LivestreamContextValue extends LivestreamSnapshot {
296
+ locale: "vi" | "en";
297
+ theme: LivestreamTheme;
298
+ prepare(): Promise<void>;
299
+ start(input: StartLivestreamInput, options?: {
300
+ autoPublish?: boolean;
301
+ }): Promise<void>;
302
+ /** Bắt đầu phát khi đang standby. */
303
+ startPublishing(): Promise<void>;
304
+ /** Tạm dừng phát về standby (không kết thúc phiên). */
305
+ stopPublishing(): Promise<void>;
306
+ stop(reason?: EndReason): Promise<void>;
307
+ retry(): Promise<void>;
308
+ switchCamera(): Promise<void>;
309
+ setMicrophoneEnabled(enabled: boolean): Promise<void>;
310
+ setCaptureOrientation(orientation: "portrait" | "landscape"): Promise<void>;
311
+ selectCamera(deviceId: string): Promise<void>;
312
+ }
313
+ declare function PickleballLiveProvider(props: PickleballLiveProviderProps): React.JSX.Element;
314
+ declare function useLivestream(): LivestreamContextValue;
315
+
316
+ export { type LivestreamContextValue as L, type NativeLiveKitBindings as N, PickleballLiveProvider as P, RtmpRoomAdapter as R, type LivestreamTheme as a, type PickleballLiveProviderProps as b, createDefaultStorage as c, defaultLivestreamTheme as d, LiveKitRoomAdapter as e, type LivestreamHostContextValue as f, type LocalPreviewReference as g, type NativeRtmpBindings as h, type RtmpStatus as i, createDefaultDeviceMetrics as j, createDefaultNetwork as k, createDefaultRoomFactory as l, createDefaultRuntime as m, createDefaultTelemetry as n, createNativeLiveKitBindings as o, createNativeRtmpBindings as p, createRtmpRoomFactory as q, useLivestreamHost as r, useLivestream as u };