@thestatic-tv/dcl-sdk 2.2.10 → 2.3.0-dev.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/README.md CHANGED
@@ -14,10 +14,12 @@ This SDK allows DCL scene builders to:
14
14
 
15
15
  ## Pricing
16
16
 
17
- | Mode | Price | Features |
17
+ | Tier | Price | Features |
18
18
  |------|-------|----------|
19
- | **Lite** | $5/mo | Session/visitor tracking only |
20
- | **Full** | $10/mo | Guide UI, Chat UI, Heartbeat, Sessions, Interactions |
19
+ | **Lite** | $5/mo | Session/visitor tracking, Guide button, Chat button |
20
+ | **Full** | $10/mo | Lite + Guide UI, Chat UI, Heartbeat, Interactions |
21
+ | **Pro** | $15/mo | Full + Admin Panel (Video tab, Mod tab) |
22
+ | **Custom** | $20/mo | Pro + Custom scene tabs for scene-specific controls |
21
23
 
22
24
  > **All keys use `dcls_` prefix** - the server determines your subscription level.
23
25
  >
@@ -37,16 +39,16 @@ If you need to rotate your API key (e.g., if compromised), you can do so from th
37
39
 
38
40
  ## Example Scene
39
41
 
40
- Clone our starter scene to get started quickly:
42
+ Clone our example scene to get started quickly:
41
43
 
42
44
  ```bash
43
- git clone https://github.com/thestatic-tv/thestatic-dcl-starter.git
44
- cd thestatic-dcl-starter
45
+ git clone https://github.com/thestatic-tv/thestatic-dcl-example.git
46
+ cd thestatic-dcl-example
45
47
  npm install
46
48
  npm start
47
49
  ```
48
50
 
49
- See the [starter repo](https://github.com/thestatic-tv/thestatic-dcl-starter) for a complete working scene.
51
+ See the [example repo](https://github.com/thestatic-tv/thestatic-dcl-example) for a complete working scene with video player integration.
50
52
 
51
53
  ## Installation
52
54
 
@@ -58,18 +60,24 @@ npm install @thestatic-tv/dcl-sdk
58
60
 
59
61
  1. Get your API key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
60
62
 
61
- 2. Initialize the client in your scene:
63
+ 2. Initialize the client in your scene's `main()` function:
62
64
 
63
65
  ```typescript
66
+ import {} from '@dcl/sdk/math'
67
+ import { engine } from '@dcl/sdk/ecs'
64
68
  import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
65
69
 
66
- const staticTV = new StaticTVClient({
67
- apiKey: 'dcls_your_api_key_here',
68
- debug: true // Enable for development
69
- })
70
+ let staticTV: StaticTVClient
71
+
72
+ export function main() {
73
+ staticTV = new StaticTVClient({
74
+ apiKey: 'dcls_your_api_key_here'
75
+ })
76
+ // Session tracking starts automatically!
77
+ }
70
78
  ```
71
79
 
72
- 3. Fetch channels and display them:
80
+ 3. Fetch channels and display them (Full mode only):
73
81
 
74
82
  ```typescript
75
83
  // Get all channels
@@ -114,17 +122,21 @@ If you don't have a channel but want to track visitors to your scene:
114
122
 
115
123
  1. Get a scene key from [thestatic.tv/dashboard](https://thestatic.tv/dashboard) (DCL Scenes tab)
116
124
 
117
- 2. Initialize with your scene key:
125
+ 2. Initialize with your scene key in `main()`:
118
126
 
119
127
  ```typescript
128
+ import {} from '@dcl/sdk/math'
129
+ import { engine } from '@dcl/sdk/ecs'
120
130
  import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
121
131
 
122
- const staticTV = new StaticTVClient({
123
- apiKey: 'dcls_your_scene_key_here'
124
- })
132
+ let staticTV: StaticTVClient
125
133
 
126
- // Session tracking starts automatically
127
- // Visitors are tracked when they enter your scene
134
+ export function main() {
135
+ staticTV = new StaticTVClient({
136
+ apiKey: 'dcls_your_scene_key_here'
137
+ })
138
+ // Session tracking starts automatically!
139
+ }
128
140
  ```
129
141
 
130
142
  3. Check if running in lite mode:
@@ -162,12 +174,22 @@ Main client class for interacting with thestatic.tv.
162
174
  |----------|------|-------------|
163
175
  | `keyType` | `'channel' \| 'scene'` | The detected key type |
164
176
  | `isLite` | `boolean` | `true` if using a scene key (lite mode) |
177
+ | `hasProFeatures` | `boolean` | `true` if pro features are enabled |
165
178
  | `guide` | `GuideModule \| null` | Guide module (null in lite mode) |
166
179
  | `session` | `SessionModule` | Session module (always available) |
167
180
  | `heartbeat` | `HeartbeatModule \| null` | Heartbeat module (null in lite mode) |
168
181
  | `interactions` | `InteractionsModule \| null` | Interactions module (null in lite mode) |
169
182
  | `guideUI` | `GuideUIModule \| null` | Guide UI module (null in lite mode) |
170
183
  | `chatUI` | `ChatUIModule \| null` | Chat UI module (null in lite mode) |
184
+ | `adminPanel` | `AdminPanelUIModule \| null` | Admin panel (null until enableProFeatures() called) |
185
+
186
+ #### Methods
187
+
188
+ | Method | Description |
189
+ |--------|-------------|
190
+ | `enableProFeatures(config)` | Enable Pro tier admin panel |
191
+ | `registerSceneTab(tab)` | Add custom scene tab (Custom tier) |
192
+ | `destroy()` | Cleanup before scene unload |
171
193
 
172
194
  ### Guide Module (Full Mode Only)
173
195
 
@@ -215,19 +237,22 @@ staticTV.interactions.follow(channelSlug) // Follow a channel
215
237
  Built-in channel browser UI. You provide a callback to handle video selection.
216
238
 
217
239
  ```typescript
218
- // Configure in constructor
219
- const staticTV = new StaticTVClient({
220
- apiKey: 'dcls_your_api_key',
221
- guideUI: {
222
- onVideoSelect: (video) => {
223
- // Handle video playback in your scene
224
- console.log('Playing:', video.name, video.src)
240
+ let staticTV: StaticTVClient
241
+
242
+ export function main() {
243
+ staticTV = new StaticTVClient({
244
+ apiKey: 'dcls_your_api_key',
245
+ guideUI: {
246
+ onVideoSelect: (video) => {
247
+ // Handle video playback in your scene
248
+ console.log('Playing:', video.name, video.src)
249
+ }
225
250
  }
226
- }
227
- })
251
+ })
228
252
 
229
- // Initialize the UI (call once after client is created)
230
- await staticTV.guideUI.init()
253
+ // Initialize the UI (call once after client is created)
254
+ staticTV.guideUI.init()
255
+ }
231
256
 
232
257
  // Show/hide the guide
233
258
  staticTV.guideUI.show()
@@ -249,17 +274,20 @@ await staticTV.guideUI.refresh()
249
274
  Real-time chat with Firebase authentication.
250
275
 
251
276
  ```typescript
252
- // Configure in constructor
253
- const staticTV = new StaticTVClient({
254
- apiKey: 'dcls_your_api_key',
255
- chatUI: {
256
- position: 'right', // 'left', 'center', or 'right'
257
- fontScale: 1.0
258
- }
259
- })
277
+ let staticTV: StaticTVClient
278
+
279
+ export function main() {
280
+ staticTV = new StaticTVClient({
281
+ apiKey: 'dcls_your_api_key',
282
+ chatUI: {
283
+ position: 'right', // 'left', 'center', or 'right'
284
+ fontScale: 1.0
285
+ }
286
+ })
260
287
 
261
- // Initialize the chat (call once after client is created)
262
- await staticTV.chatUI.init()
288
+ // Initialize the chat (call once after client is created)
289
+ staticTV.chatUI.init()
290
+ }
263
291
 
264
292
  // Show/hide the chat
265
293
  staticTV.chatUI.show()
@@ -276,23 +304,131 @@ const unread = staticTV.chatUI.unreadCount
276
304
  staticTV.chatUI.setChannel('channel-slug')
277
305
  ```
278
306
 
279
- ### Rendering UI Components
307
+ ### Admin Panel Module (Pro Tier)
280
308
 
281
- The UI modules provide `getComponent()` methods that return React-ECS elements. Call these in your UI renderer:
309
+ In-scene admin panel with Video and Mod tabs. Allows scene owners/admins to:
310
+ - Control live streaming (start/stop, rotate keys)
311
+ - Play videos from URL or predefined slots
312
+ - Manage scene admins and banned wallets
313
+ - Send broadcast messages to all players
282
314
 
283
315
  ```typescript
284
- import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
316
+ import { StaticTVClient } from '@thestatic-tv/dcl-sdk'
317
+ import ReactEcs, { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
285
318
 
286
- // In your scene setup
319
+ let staticTV: StaticTVClient
320
+
321
+ export function main() {
322
+ staticTV = new StaticTVClient({
323
+ apiKey: 'dcls_your_api_key'
324
+ })
325
+
326
+ // Enable admin panel (Pro tier)
327
+ staticTV.enableProFeatures({
328
+ sceneId: 'my-scene', // Your scene ID from thestatic.tv
329
+ title: 'MY SCENE ADMIN', // Panel header title
330
+ onVideoPlay: (url) => {
331
+ // Handle video playback in your scene
332
+ videoPlayer.play(url)
333
+ },
334
+ onVideoStop: () => {
335
+ videoPlayer.stop()
336
+ },
337
+ onVideoSlotPlay: (slot) => {
338
+ // Play a predefined video slot (slot1-slot5)
339
+ fetchAndPlaySlot(slot)
340
+ },
341
+ onBroadcast: (text) => {
342
+ // Show notification to all players
343
+ showNotification(text)
344
+ },
345
+ onCommand: (type, payload) => {
346
+ // Handle custom commands (kickAll, kickBanned, etc.)
347
+ handleCommand(type, payload)
348
+ }
349
+ })
350
+ }
351
+
352
+ // Render the admin panel
287
353
  ReactEcsRenderer.setUiRenderer(() => {
288
- return (
289
- <>
290
- {/* Your other UI elements */}
291
- {staticTV.guideUI?.getComponent()}
292
- {staticTV.chatUI?.getComponent()}
293
- </>
354
+ return staticTV.adminPanel?.getComponent()
355
+ })
356
+
357
+ // Toggle panel visibility
358
+ staticTV.adminPanel.toggle()
359
+
360
+ // Check if user has admin access
361
+ if (staticTV.adminPanel.hasAccess) { ... }
362
+ ```
363
+
364
+ #### Admin Panel Configuration Options
365
+
366
+ | Option | Type | Default | Description |
367
+ |--------|------|---------|-------------|
368
+ | `sceneId` | `string` | required | Scene ID for API calls |
369
+ | `title` | `string` | `'ADMIN PANEL'` | Header title |
370
+ | `headerColor` | `{r,g,b,a}` | red | Header background color |
371
+ | `showVideoTab` | `boolean` | `true` | Show Video tab |
372
+ | `showModTab` | `boolean` | `true` | Show Mod tab (owners only) |
373
+ | `onVideoPlay` | `(url) => void` | - | Called when video should play |
374
+ | `onVideoStop` | `() => void` | - | Called when video should stop |
375
+ | `onVideoSlotPlay` | `(slot) => void` | - | Called when slot is selected |
376
+ | `onBroadcast` | `(text) => void` | - | Called for broadcast messages |
377
+ | `onCommand` | `(type, payload) => void` | - | Called for custom commands |
378
+ | `footerLink` | `string` | scene page | Link shown in footer |
379
+ | `debug` | `boolean` | `false` | Enable debug logging |
380
+
381
+ ### Custom Scene Tabs (Custom Tier)
382
+
383
+ Add your own scene-specific control tabs to the admin panel:
384
+
385
+ ```typescript
386
+ import ReactEcs, { UiEntity, Button, Label } from '@dcl/sdk/react-ecs'
387
+
388
+ // Enable pro features first
389
+ staticTV.enableProFeatures({ sceneId: 'my-scene', ... })
390
+
391
+ // Register custom tabs
392
+ staticTV.registerSceneTab({
393
+ label: 'LIGHTS',
394
+ id: 'lights',
395
+ render: () => (
396
+ <UiEntity uiTransform={{ flexDirection: 'column', padding: 8 }}>
397
+ <Label value="Light Controls" fontSize={14} />
398
+ <Button value="Disco Mode" onMouseDown={() => setDiscoLights()} />
399
+ <Button value="Ambient" onMouseDown={() => setAmbientLights()} />
400
+ <Button value="Off" onMouseDown={() => turnOffLights()} />
401
+ </UiEntity>
294
402
  )
295
403
  })
404
+
405
+ staticTV.registerSceneTab({
406
+ label: 'DOORS',
407
+ id: 'doors',
408
+ render: () => <MyDoorsControls />
409
+ })
410
+ ```
411
+
412
+ Custom tabs appear before the Video and Mod tabs in the tab bar.
413
+
414
+ ### Rendering UI Components
415
+
416
+ The UI modules provide `getComponent()` methods that return React-ECS elements. Add the renderer **outside** your `main()` function:
417
+
418
+ ```typescript
419
+ import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
420
+
421
+ // Outside main() - required by DCL
422
+ ReactEcsRenderer.setUiRenderer(() => {
423
+ if (!staticTV) return null
424
+ return ReactEcs.createElement(UiEntity, {
425
+ uiTransform: { width: '100%', height: '100%', positionType: 'absolute' },
426
+ children: [
427
+ staticTV.guideUI?.getComponent(),
428
+ staticTV.chatUI?.getComponent()
429
+ ].filter(Boolean)
430
+ })
431
+ })
296
432
  ```
297
433
 
298
434
  ## Metrics Attribution
package/dist/index.d.mts CHANGED
@@ -1,3 +1,5 @@
1
+ import ReactEcs from '@dcl/sdk/react-ecs';
2
+
1
3
  /**
2
4
  * Player identity data from DCL
3
5
  */
@@ -203,6 +205,111 @@ interface ChatUIConfig {
203
205
  */
204
206
  fontScale?: number;
205
207
  }
208
+ /**
209
+ * Stream channel data from the API
210
+ */
211
+ interface StreamData {
212
+ hasChannel: boolean;
213
+ channelId: string | null;
214
+ channelName?: string;
215
+ isLive: boolean;
216
+ hlsUrl: string | null;
217
+ rtmpUrl?: string | null;
218
+ streamKey?: string | null;
219
+ currentViewers: number;
220
+ sparksBalance: number;
221
+ tier?: string;
222
+ /** True if user can claim the one-time streaming trial */
223
+ trialAvailable?: boolean;
224
+ /** Number of Sparks included in trial (240 = 4 hours) */
225
+ trialSparks?: number;
226
+ }
227
+ /**
228
+ * Video slot configuration
229
+ */
230
+ interface VideoSlot {
231
+ id: string;
232
+ name: string;
233
+ url: string;
234
+ }
235
+ /**
236
+ * Command handler for scene-specific commands
237
+ */
238
+ type CommandHandler = (type: string, payload?: Record<string, unknown>) => void;
239
+ /**
240
+ * Custom scene tab definition for Full/Custom tier
241
+ */
242
+ interface SceneTabDefinition {
243
+ /** Tab label shown in the tab bar */
244
+ label: string;
245
+ /** Unique tab ID */
246
+ id: string;
247
+ /** React-ECS component that renders the tab content */
248
+ render: () => any;
249
+ }
250
+ /**
251
+ * Configuration options for AdminPanelModule
252
+ */
253
+ interface AdminPanelConfig {
254
+ /**
255
+ * Scene ID for API calls
256
+ */
257
+ sceneId: string;
258
+ /**
259
+ * Panel title (shown in header)
260
+ */
261
+ title?: string;
262
+ /**
263
+ * Header background color (default: red)
264
+ */
265
+ headerColor?: {
266
+ r: number;
267
+ g: number;
268
+ b: number;
269
+ a: number;
270
+ };
271
+ /**
272
+ * Show Video tab (default: true for Pro tier)
273
+ */
274
+ showVideoTab?: boolean;
275
+ /**
276
+ * Show Mod tab (default: true for owners)
277
+ */
278
+ showModTab?: boolean;
279
+ /**
280
+ * Custom scene tabs (Full/Custom tier only)
281
+ */
282
+ sceneTabs?: SceneTabDefinition[];
283
+ /**
284
+ * Command handler for scene-specific commands (e.g., elevator, lights)
285
+ * Called when admin triggers a command from the panel
286
+ */
287
+ onCommand?: CommandHandler;
288
+ /**
289
+ * Callback when video URL should be played
290
+ */
291
+ onVideoPlay?: (url: string) => void;
292
+ /**
293
+ * Callback when video playback should stop
294
+ */
295
+ onVideoStop?: () => void;
296
+ /**
297
+ * Callback when video slot is selected
298
+ */
299
+ onVideoSlotPlay?: (slot: string) => void;
300
+ /**
301
+ * Callback for broadcast messages
302
+ */
303
+ onBroadcast?: (text: string) => void;
304
+ /**
305
+ * Link shown in footer (default: scene page on thestatic.tv)
306
+ */
307
+ footerLink?: string;
308
+ /**
309
+ * Enable debug logging
310
+ */
311
+ debug?: boolean;
312
+ }
206
313
 
207
314
  /**
208
315
  * Guide module - fetch channel lineup from thestatic.tv
@@ -534,12 +641,106 @@ declare class ChatUIModule {
534
641
  private renderToggleButton;
535
642
  }
536
643
 
644
+ /**
645
+ * Admin Panel UI Module for The Static TV SDK (Pro Tier)
646
+ *
647
+ * Provides in-scene admin controls:
648
+ * - Video Tab: Stream control, video playback, slots
649
+ * - Mod Tab: Scene admins, banned wallets, broadcast
650
+ * - Custom Scene Tabs: Full/Custom tier
651
+ */
652
+
653
+ declare class AdminPanelUIModule {
654
+ private client;
655
+ private config;
656
+ private baseUrl;
657
+ private isAdmin;
658
+ private isOwner;
659
+ private panelOpen;
660
+ private activeTab;
661
+ private playerWallet;
662
+ private customVideoUrl;
663
+ private streamData;
664
+ private streamFetched;
665
+ private channelCreating;
666
+ private channelCreateError;
667
+ private channelDeleting;
668
+ private channelDeleteError;
669
+ private keyRotating;
670
+ private keyRotateStatus;
671
+ private streamControlling;
672
+ private streamControlStatus;
673
+ private pollIntervalId;
674
+ private trialClaiming;
675
+ private trialClaimError;
676
+ private sceneAdmins;
677
+ private bannedWallets;
678
+ private newAdminWallet;
679
+ private newBanWallet;
680
+ private broadcastText;
681
+ private modStatus;
682
+ private modsFetched;
683
+ constructor(client: StaticTVClient, config: AdminPanelConfig);
684
+ private log;
685
+ /**
686
+ * Initialize the admin panel - checks admin status
687
+ */
688
+ init(): Promise<void>;
689
+ /**
690
+ * Check if current player is an admin for this scene
691
+ */
692
+ checkAdminStatus(): Promise<void>;
693
+ /**
694
+ * Toggle the admin panel open/closed
695
+ */
696
+ toggle(): void;
697
+ /**
698
+ * Check if the panel is currently open
699
+ */
700
+ get isOpen(): boolean;
701
+ /**
702
+ * Check if current user has admin access
703
+ */
704
+ get hasAccess(): boolean;
705
+ /**
706
+ * Register a custom scene tab (Full/Custom tier)
707
+ */
708
+ registerSceneTab(tab: SceneTabDefinition): void;
709
+ private startStreamPolling;
710
+ private stopStreamPolling;
711
+ private fetchStreamData;
712
+ private refreshStreamStatus;
713
+ private createChannel;
714
+ private claimTrial;
715
+ private deleteChannel;
716
+ private startStream;
717
+ private stopStream;
718
+ private rotateStreamKey;
719
+ private fetchModData;
720
+ private addSceneAdmin;
721
+ private removeSceneAdmin;
722
+ private banWallet;
723
+ private unbanWallet;
724
+ private banKickPlayer;
725
+ private sendBroadcast;
726
+ private setActiveTab;
727
+ private SectionHead;
728
+ private TabBtn;
729
+ private VideoTab;
730
+ private ModTab;
731
+ /**
732
+ * Get the React-ECS component for the admin panel
733
+ */
734
+ getComponent: () => ReactEcs.JSX.Element | null;
735
+ }
736
+
537
737
  /**
538
738
  * StaticTVClient - Main client for connecting DCL scenes to thestatic.tv
539
739
  *
540
740
  * All keys use dcls_ prefix. Features enabled based on sdkType from server:
541
741
  * - lite: Session tracking only
542
742
  * - full: Guide, Chat, Heartbeat, Interactions + session tracking
743
+ * - pro: Full + Admin Panel (Video + Mod tabs)
543
744
  */
544
745
 
545
746
  /** Key type constants (legacy - kept for compatibility) */
@@ -551,6 +752,7 @@ declare class StaticTVClient {
551
752
  private _keyType;
552
753
  private _disabled;
553
754
  private _fullFeaturesEnabled;
755
+ private _proFeaturesEnabled;
554
756
  /** Guide module - fetch channel lineup (full SDK only) */
555
757
  guide: GuideModule | null;
556
758
  /** Session module - track visitor sessions (all keys, null when disabled) */
@@ -563,6 +765,8 @@ declare class StaticTVClient {
563
765
  guideUI: GuideUIModule | null;
564
766
  /** Chat UI module - real-time chat UI (full SDK only) */
565
767
  chatUI: ChatUIModule | null;
768
+ /** Admin Panel module - Video/Mod tabs (pro SDK only) */
769
+ adminPanel: AdminPanelUIModule | null;
566
770
  /**
567
771
  * Create a new StaticTVClient
568
772
  *
@@ -570,16 +774,15 @@ declare class StaticTVClient {
570
774
  *
571
775
  * @example
572
776
  * ```typescript
573
- * // Full access with channel key
574
- * const staticTV = new StaticTVClient({
575
- * apiKey: 'dclk_your_channel_key_here',
576
- * debug: true
577
- * });
777
+ * let staticTV: StaticTVClient
578
778
  *
579
- * // Lite mode with scene key (visitors only)
580
- * const staticTV = new StaticTVClient({
581
- * apiKey: 'dcls_your_scene_key_here'
582
- * });
779
+ * export function main() {
780
+ * // All keys use dcls_ prefix - features determined by subscription
781
+ * staticTV = new StaticTVClient({
782
+ * apiKey: 'dcls_your_key_here'
783
+ * })
784
+ * // Session tracking starts automatically!
785
+ * }
583
786
  * ```
584
787
  */
585
788
  constructor(config: StaticTVConfig);
@@ -626,10 +829,51 @@ declare class StaticTVClient {
626
829
  * Check if full features are enabled (server confirmed sdkType: 'full')
627
830
  */
628
831
  get hasFullFeatures(): boolean;
832
+ /**
833
+ * Check if pro features are enabled (admin panel)
834
+ */
835
+ get hasProFeatures(): boolean;
629
836
  /**
630
837
  * Get the SDK type (lite or full) - only available after session starts
631
838
  */
632
839
  get sdkType(): 'lite' | 'full';
840
+ /**
841
+ * Enable Pro features (Admin Panel with Video + Mod tabs)
842
+ * Call this after creating the client to add admin panel functionality.
843
+ *
844
+ * @param config Admin panel configuration
845
+ *
846
+ * @example
847
+ * ```typescript
848
+ * const staticTV = new StaticTVClient({ apiKey: 'dcls_...' })
849
+ *
850
+ * // Enable admin panel
851
+ * staticTV.enableProFeatures({
852
+ * sceneId: 'my-scene',
853
+ * title: 'MY SCENE ADMIN',
854
+ * onVideoPlay: (url) => videoPlayer.play(url),
855
+ * onVideoStop: () => videoPlayer.stop(),
856
+ * onBroadcast: (text) => showNotification(text)
857
+ * })
858
+ * ```
859
+ */
860
+ enableProFeatures(config: AdminPanelConfig): void;
861
+ /**
862
+ * Register a custom scene tab for the admin panel (Full/Custom tier)
863
+ * Must call enableProFeatures() first.
864
+ *
865
+ * @param tab The tab definition with label, id, and render function
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * staticTV.registerSceneTab({
870
+ * label: 'LIGHTS',
871
+ * id: 'lights',
872
+ * render: () => <MyLightsControls />
873
+ * })
874
+ * ```
875
+ */
876
+ registerSceneTab(tab: SceneTabDefinition): void;
633
877
  /**
634
878
  * Cleanup when done (call before scene unload)
635
879
  */
@@ -660,4 +904,4 @@ declare function getPlayerWallet(): string | null;
660
904
  */
661
905
  declare function getPlayerDisplayName(): string | null;
662
906
 
663
- export { type Channel, type ChatChannel, type ChatMessage, type ChatUIConfig, ChatUIModule, type GuideFeaturedPlaylist, GuideModule, type GuideResponse, type GuideUIConfig, GuideUIModule, type GuideVideo, HeartbeatModule, type HeartbeatResponse, type InteractionResponse, InteractionsModule, KEY_TYPE_CHANNEL, KEY_TYPE_SCENE, type PlayerData, type SceneStats, type SceneStatsResponse, SessionModule, type SessionResponse, StaticTVClient, type StaticTVConfig, type Vod, fetchUserData, getPlayerDisplayName, getPlayerWallet };
907
+ export { type AdminPanelConfig, AdminPanelUIModule, type Channel, type ChatChannel, type ChatMessage, type ChatUIConfig, ChatUIModule, type CommandHandler, type GuideFeaturedPlaylist, GuideModule, type GuideResponse, type GuideUIConfig, GuideUIModule, type GuideVideo, HeartbeatModule, type HeartbeatResponse, type InteractionResponse, InteractionsModule, KEY_TYPE_CHANNEL, KEY_TYPE_SCENE, type PlayerData, type SceneStats, type SceneStatsResponse, type SceneTabDefinition, SessionModule, type SessionResponse, StaticTVClient, type StaticTVConfig, type StreamData, type VideoSlot, type Vod, fetchUserData, getPlayerDisplayName, getPlayerWallet };